1 /*
2 * client_hash_auth.c
3 *
4 * function for CA code hash auth
5 *
6 * Copyright (C) 2022 Huawei Technologies Co., Ltd.
7 *
8 * This software is licensed under the terms of the GNU General Public
9 * License version 2, as published by the Free Software Foundation, and
10 * may be copied, distributed, and modified under those terms.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 */
17 #include "client_hash_auth.h"
18 #include <linux/string.h>
19 #include <linux/mutex.h>
20 #include <linux/types.h>
21 #include <linux/rwsem.h>
22 #ifdef CONFIG_AUTH_SUPPORT_UNAME
23 #include <linux/fs.h>
24 #endif
25 #ifdef CONFIG_CLIENT_AUTH
26 #include <linux/mm.h>
27 #include <linux/dcache.h>
28 #include <linux/mm_types.h>
29 #include <linux/highmem.h>
30 #include <linux/cred.h>
31 #include <linux/slab.h>
32 #include <linux/sched/mm.h>
33 #endif
34 #ifdef CONFIG_AUTH_HASH
35 #include <crypto/hash.h>
36 #endif
37 #include <securec.h>
38
39 #include "tc_ns_log.h"
40 #include "auth_base_impl.h"
41
42 #ifdef CONFIG_AUTH_HASH
43 #define SHA256_DIGEST_LENGTH 32
44 #define FIXED_PKG_NAME_LENGTH 256
45 struct sdesc_hash {
46 struct shash_desc shash;
47 char ctx[];
48 };
49 #endif
50
51 #if defined (CONFIG_ANDROID_HIDL) || defined (CONFIG_MDC_HAL_AUTH)
52
check_proc_state(bool is_hidl,struct task_struct ** hidl_struct,const struct tc_ns_client_context * context)53 static int check_proc_state(bool is_hidl, struct task_struct **hidl_struct,
54 const struct tc_ns_client_context *context)
55 {
56 bool check_value = false;
57
58 if (is_hidl) {
59 rcu_read_lock();
60 *hidl_struct = pid_task(find_vpid(context->calling_pid),
61 PIDTYPE_PID);
62 check_value = !*hidl_struct ||
63 (*hidl_struct)->state == TASK_DEAD;
64 if (check_value) {
65 tloge("task is dead\n");
66 rcu_read_unlock();
67 return -EFAULT;
68 }
69
70 get_task_struct(*hidl_struct);
71 rcu_read_unlock();
72 return EOK;
73 }
74
75 return EOK;
76 }
77
get_hidl_client_task(bool is_hidl_task,struct tc_ns_client_context * context,struct task_struct ** cur_struct)78 static int get_hidl_client_task(bool is_hidl_task, struct tc_ns_client_context *context,
79 struct task_struct **cur_struct)
80 {
81 int ret;
82 struct task_struct *hidl_struct = NULL;
83
84 ret = check_proc_state(is_hidl_task, &hidl_struct, context);
85 if (ret)
86 return ret;
87
88 if (hidl_struct)
89 *cur_struct = hidl_struct;
90 else
91 *cur_struct = current;
92
93 return EOK;
94 }
95
96 #endif
97
98 #ifdef CONFIG_CLIENT_AUTH
99 #define LIBTEEC_CODE_PAGE_SIZE 8
100 #define DEFAULT_TEXT_OFF 0
101 #define LIBTEEC_NAME_MAX_LEN 50
102
103 const char g_libso[KIND_OF_SO][LIBTEEC_NAME_MAX_LEN] = {
104 "libteec_vendor.so",
105 #ifndef CONFIG_CMS_CAHASH_AUTH
106 #ifndef CONFIG_CADAEMON_AUTH
107 "libteec.huawei.so",
108 #else
109 "libteec.so",
110 #endif
111 #endif
112 };
113
find_lib_code_area(struct mm_struct * mm,struct vm_area_struct ** lib_code_area,int so_index)114 static int find_lib_code_area(struct mm_struct *mm,
115 struct vm_area_struct **lib_code_area, int so_index)
116 {
117 struct vm_area_struct *vma = NULL;
118 bool is_valid_vma = false;
119 bool is_so_exists = false;
120 bool param_check = (!mm || !mm->mmap ||
121 !lib_code_area || so_index >= KIND_OF_SO);
122
123 if (param_check) {
124 tloge("illegal input params\n");
125 return -EFAULT;
126 }
127 for (vma = mm->mmap; vma; vma = vma->vm_next) {
128 is_valid_vma = (vma->vm_file &&
129 vma->vm_file->f_path.dentry &&
130 vma->vm_file->f_path.dentry->d_name.name);
131 if (is_valid_vma) {
132 is_so_exists = !strcmp(g_libso[so_index],
133 vma->vm_file->f_path.dentry->d_name.name);
134 if (is_so_exists && (vma->vm_flags & VM_EXEC)) {
135 *lib_code_area = vma;
136 tlogd("so name is %s\n",
137 vma->vm_file->f_path.dentry->d_name.name);
138 return EOK;
139 }
140 }
141 }
142 return -EFAULT;
143 }
144
145 struct get_code_info {
146 unsigned long code_start;
147 unsigned long code_end;
148 unsigned long code_size;
149 };
update_so_hash(struct mm_struct * mm,struct task_struct * cur_struct,struct shash_desc * shash,int so_index)150 static int update_so_hash(struct mm_struct *mm,
151 struct task_struct *cur_struct, struct shash_desc *shash, int so_index)
152 {
153 struct vm_area_struct *vma = NULL;
154 int rc = -EFAULT;
155 struct get_code_info code_info;
156 unsigned long in_size;
157 struct page *ptr_page = NULL;
158 void *ptr_base = NULL;
159
160 if (find_lib_code_area(mm, &vma, so_index)) {
161 tlogd("get lib code vma area failed\n");
162 return -EFAULT;
163 }
164
165 code_info.code_start = vma->vm_start;
166 code_info.code_end = vma->vm_end;
167 code_info.code_size = code_info.code_end - code_info.code_start;
168
169 while (code_info.code_start < code_info.code_end) {
170 // Get a handle of the page we want to read
171 #if (KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE)
172 rc = get_user_pages_remote(mm, code_info.code_start,
173 1, FOLL_FORCE, &ptr_page, NULL, NULL);
174 #else
175 rc = get_user_pages_remote(cur_struct, mm, code_info.code_start,
176 1, FOLL_FORCE, &ptr_page, NULL, NULL);
177 #endif
178 if (rc != 1) {
179 tloge("get user pages locked error[0x%x]\n", rc);
180 rc = -EFAULT;
181 break;
182 }
183
184 ptr_base = kmap_atomic(ptr_page);
185 if (!ptr_base) {
186 rc = -EFAULT;
187 put_page(ptr_page);
188 break;
189 }
190 in_size = (code_info.code_size > PAGE_SIZE) ? PAGE_SIZE : code_info.code_size;
191
192 rc = crypto_shash_update(shash, ptr_base, in_size);
193 if (rc) {
194 kunmap_atomic(ptr_base);
195 put_page(ptr_page);
196 break;
197 }
198 kunmap_atomic(ptr_base);
199 put_page(ptr_page);
200 code_info.code_start += in_size;
201 code_info.code_size = code_info.code_end - code_info.code_start;
202 }
203 return rc;
204 }
205
206 /* Calculate the SHA256 library digest */
calc_task_so_hash(unsigned char * digest,uint32_t dig_len,struct task_struct * cur_struct,int so_index)207 static int calc_task_so_hash(unsigned char *digest, uint32_t dig_len,
208 struct task_struct *cur_struct, int so_index)
209 {
210 struct mm_struct *mm = NULL;
211 int rc;
212 size_t size;
213 size_t shash_size;
214 struct sdesc *desc = NULL;
215
216 if (!digest || dig_len != SHA256_DIGEST_LENTH) {
217 tloge("tee hash: digest is NULL\n");
218 return -EFAULT;
219 }
220
221 shash_size = crypto_shash_descsize(get_shash_handle());
222 size = sizeof(desc->shash) + shash_size;
223 if (size < sizeof(desc->shash) || size < shash_size) {
224 tloge("size overflow\n");
225 return -ENOMEM;
226 }
227
228 desc = kzalloc(size, GFP_KERNEL);
229 if (ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)desc)) {
230 tloge("alloc desc failed\n");
231 return -ENOMEM;
232 }
233
234 desc->shash.tfm = get_shash_handle();
235 if (crypto_shash_init(&desc->shash)) {
236 kfree(desc);
237 return -EFAULT;
238 }
239
240 mm = get_task_mm(cur_struct);
241 if (!mm) {
242 tloge("so does not have mm struct\n");
243 if (memset_s(digest, MAX_SHA_256_SZ, 0, dig_len))
244 tloge("memset digest failed\n");
245 kfree(desc);
246 return -EFAULT;
247 }
248
249 down_read(&mm_sem_lock(mm));
250 rc = update_so_hash(mm, cur_struct, &desc->shash, so_index);
251 up_read(&mm_sem_lock(mm));
252 mmput(mm);
253 if (!rc)
254 rc = crypto_shash_final(&desc->shash, digest);
255 kfree(desc);
256 return rc;
257 }
258
proc_calc_hash(uint8_t kernel_api,struct tc_ns_session * session,struct task_struct * cur_struct,uint32_t pub_key_len)259 static int proc_calc_hash(uint8_t kernel_api, struct tc_ns_session *session,
260 struct task_struct *cur_struct, uint32_t pub_key_len)
261 {
262 int rc, i;
263 int so_found = 0;
264
265 mutex_crypto_hash_lock();
266 if (kernel_api == TEE_REQ_FROM_USER_MODE) {
267 for (i = 0; so_found < NUM_OF_SO && i < KIND_OF_SO; i++) {
268 rc = calc_task_so_hash(session->auth_hash_buf + MAX_SHA_256_SZ * so_found,
269 (uint32_t)SHA256_DIGEST_LENTH, cur_struct, i);
270 if (!rc)
271 so_found++;
272 }
273 if (so_found != NUM_OF_SO)
274 tlogd("so library found: %d\n", so_found);
275 } else {
276 tlogd("request from kernel\n");
277 }
278
279 #ifdef CONFIG_ASAN_DEBUG
280 tloge("so auth disabled for ASAN debug\n");
281 uint32_t so_hash_len = MAX_SHA_256_SZ * NUM_OF_SO;
282 errno_t sret = memset_s(session->auth_hash_buf, so_hash_len, 0, so_hash_len);
283 if (sret) {
284 mutex_crypto_hash_unlock();
285 tloge("memset so hash failed\n");
286 return -EFAULT;
287 }
288 #endif
289
290 rc = calc_task_hash(session->auth_hash_buf + MAX_SHA_256_SZ * NUM_OF_SO,
291 (uint32_t)SHA256_DIGEST_LENTH, cur_struct, pub_key_len);
292 if (rc) {
293 mutex_crypto_hash_unlock();
294 tloge("tee calc ca hash failed\n");
295 return -EFAULT;
296 }
297 mutex_crypto_hash_unlock();
298 return EOK;
299 }
300
calc_client_auth_hash(struct tc_ns_dev_file * dev_file,struct tc_ns_client_context * context,struct tc_ns_session * session)301 int calc_client_auth_hash(struct tc_ns_dev_file *dev_file,
302 struct tc_ns_client_context *context, struct tc_ns_session *session)
303 {
304 int ret;
305 struct task_struct *cur_struct = NULL;
306 bool check = false;
307 #if defined(CONFIG_ANDROID_HIDL) || defined(CONFIG_MDC_HAL_AUTH)
308 bool is_hidl_srvc = false;
309 #endif
310 check = (!dev_file || !context || !session);
311 if (check) {
312 tloge("bad params\n");
313 return -EFAULT;
314 }
315
316 if (tee_init_shash_handle("sha256")) {
317 tloge("init code hash error\n");
318 return -EFAULT;
319 }
320
321 #if defined(CONFIG_ANDROID_HIDL) || defined(CONFIG_MDC_HAL_AUTH)
322 if(!current->mm) {
323 tlogd("kernel thread need not check\n");
324 ret = ENTER_BYPASS_CHANNEL;
325 } else {
326 #ifdef CONFIG_CADAEMON_AUTH
327 /* for OH */
328 ret = check_cadaemon_auth();
329 #else
330 /* for HO and MDC/DC */
331 ret = check_hidl_auth();
332 #endif
333 }
334 if (ret != CHECK_ACCESS_SUCC) {
335 if (ret != ENTER_BYPASS_CHANNEL) {
336 tloge("hidl service may be exploited ret 0x%x\n", ret);
337 return -EACCES;
338 }
339 /* native\kernel ca task this branch */
340 } else {
341 /* android hidl\mdc secmgr(libteec\kms) task this branch */
342 is_hidl_srvc = true;
343 }
344 ret = get_hidl_client_task(is_hidl_srvc, context, &cur_struct);
345 if (ret)
346 return -EFAULT;
347 #else
348 cur_struct = current;
349 #endif
350
351 ret = proc_calc_hash(dev_file->kernel_api, session, cur_struct, dev_file->pub_key_len);
352 #if defined(CONFIG_ANDROID_HIDL) || defined(CONFIG_MDC_HAL_AUTH)
353 if (is_hidl_srvc)
354 put_task_struct(cur_struct);
355 #endif
356 return ret;
357 }
358 #endif
359
360 #ifdef CONFIG_AUTH_HASH
361 #define UID_LEN 16
construct_hashdata(struct tc_ns_dev_file * dev_file,uint8_t * buf,uint32_t buf_len)362 static int construct_hashdata(struct tc_ns_dev_file *dev_file,
363 uint8_t *buf, uint32_t buf_len)
364 {
365 int ret;
366 ret = memcpy_s(buf, buf_len, dev_file->pkg_name, dev_file->pkg_name_len);
367 if (ret) {
368 tloge("memcpy_s failed\n");
369 goto error;
370 }
371 buf += dev_file->pkg_name_len;
372 buf_len -= dev_file->pkg_name_len;
373 ret = memcpy_s(buf, buf_len, dev_file->pub_key, dev_file->pub_key_len);
374 if (ret) {
375 tloge("memcpy_s failed\n");
376 goto error;
377 }
378 return 0;
379 error:
380 return -EFAULT;
381 }
382
init_sdesc(struct crypto_shash * alg)383 static struct sdesc_hash *init_sdesc(struct crypto_shash *alg)
384 {
385 struct sdesc_hash *sdesc;
386 size_t size;
387
388 size = sizeof(struct shash_desc) + crypto_shash_descsize(alg);
389 sdesc = kmalloc(size, GFP_KERNEL);
390 if (sdesc == NULL)
391 return ERR_PTR(-ENOMEM);
392 sdesc->shash.tfm = alg;
393 return sdesc;
394 }
395
calc_hash(struct crypto_shash * alg,const unsigned char * data,unsigned int datalen,unsigned char * digest)396 static int calc_hash(struct crypto_shash *alg,
397 const unsigned char *data, unsigned int datalen, unsigned char *digest)
398 {
399 struct sdesc_hash *sdesc;
400 int ret;
401
402 sdesc = init_sdesc(alg);
403 if (IS_ERR(sdesc)) {
404 pr_info("can't alloc sdesc\n");
405 return PTR_ERR(sdesc);
406 }
407
408 ret = crypto_shash_digest(&sdesc->shash, data, datalen, digest);
409 kfree(sdesc);
410 return ret;
411 }
412
do_sha256(const unsigned char * data,uint32_t datalen,unsigned char * out_digest,uint8_t digest_len)413 static int do_sha256(const unsigned char *data, uint32_t datalen,
414 unsigned char *out_digest, uint8_t digest_len)
415 {
416 int ret;
417 struct crypto_shash *alg;
418 const char *hash_alg_name = "sha256";
419 if (digest_len != SHA256_DIGEST_LENGTH) {
420 tloge("error digest_len\n");
421 return -1;
422 }
423
424 alg = crypto_alloc_shash(hash_alg_name, 0, 0);
425 if(IS_ERR_OR_NULL(alg)) {
426 tloge("can't alloc alg %s, PTR_ERR alg is %ld\n", hash_alg_name, PTR_ERR(alg));
427 return PTR_ERR(alg);
428 }
429 ret = calc_hash(alg, data, datalen, out_digest);
430 if (ret != 0) {
431 tloge("calc hash failed\n");
432 crypto_free_shash(alg);
433 alg = NULL;
434 return -1;
435 }
436 crypto_free_shash(alg);
437 alg = NULL;
438 return 0;
439 }
440
set_login_information_hash(struct tc_ns_dev_file * hash_dev_file)441 int set_login_information_hash(struct tc_ns_dev_file *hash_dev_file)
442 {
443 int ret = 0;
444 uint8_t *indata = NULL;
445 if (hash_dev_file == NULL) {
446 tloge("wrong caller info, cal hash stopped\n");
447 return -1;
448 }
449 mutex_lock(&hash_dev_file->cainfo_hash_setup_lock);
450
451 if (!(hash_dev_file->cainfo_hash_setup)) {
452 unsigned char digest[SHA256_DIGEST_LENGTH] = {0};
453 uint8_t digest_len = sizeof(digest);
454
455 uint32_t indata_len;
456 #ifdef CONFIG_AUTH_SUPPORT_UNAME
457 /* username using fixed length to cal hash */
458 if (hash_dev_file->pub_key_len >= FIXED_PKG_NAME_LENGTH) {
459 tloge("username is too loog\n");
460 ret = -1;
461 goto error;
462 }
463 indata_len = hash_dev_file->pkg_name_len + FIXED_PKG_NAME_LENGTH;
464 #else
465 indata_len = hash_dev_file->pkg_name_len + hash_dev_file->pub_key_len;
466 #endif
467 indata = kzalloc(indata_len, GFP_KERNEL);
468 if (ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)indata)) {
469 tloge("indata kmalloc fail\n");
470 ret = -1;
471 goto error;
472 }
473
474 ret = construct_hashdata(hash_dev_file, indata, indata_len);
475 if (ret != 0) {
476 tloge("construct hashdata failed\n");
477 goto error;
478 }
479
480 ret = do_sha256((unsigned char *)indata, indata_len, digest, digest_len);
481 if (ret != 0) {
482 tloge("do sha256 failed\n");
483 goto error;
484 }
485
486 ret = memcpy_s(hash_dev_file->pkg_name, MAX_PACKAGE_NAME_LEN, digest, digest_len);
487 if (ret != 0) {
488 tloge("memcpy_s failed\n");
489 goto error;
490 }
491 hash_dev_file->pkg_name_len = SHA256_DIGEST_LENGTH;
492 hash_dev_file->cainfo_hash_setup = true;
493 }
494
495 error:
496 if (!ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)indata))
497 kfree(indata);
498
499 mutex_unlock(&hash_dev_file->cainfo_hash_setup_lock);
500 return ret;
501 }
502 #endif
503
504 #ifdef CONFIG_AUTH_SUPPORT_UNAME
505 #define PASSWD_FILE "/etc/passwd"
506 #define UID_POS 2U
507 #define DECIMAL 10
uid_compare(uint32_t uid,const char * uid_str,uint32_t uid_len)508 static int uid_compare(uint32_t uid, const char* uid_str, uint32_t uid_len)
509 {
510 uint32_t uid_num = 0;
511 for (uint32_t i = 0; i < uid_len; i++) {
512 bool is_number = uid_str[i] >= '0' && uid_str[i] <= '9';
513 if (!is_number) {
514 tloge("passwd info wrong format: uid missing\n");
515 return -1;
516 }
517 uid_num = DECIMAL * uid_num + (uid_str[i] - '0');
518 }
519 return (uid_num == uid) ? 0 : -1;
520 }
521
522 /* "username:[encrypted password]:uid:gid:[comments]:home directory:login shell" */
parse_uname(uint32_t uid,char * username,int buffer_len)523 static uint32_t parse_uname(uint32_t uid, char *username, int buffer_len)
524 {
525 char *str = username;
526 char *token = strsep(&str, ":");
527 char *temp_name = token; // first tokon is username, need to check uid
528 int index = 0;
529 while(token != NULL && index < UID_POS) {
530 token = strsep(&str, ":");
531 index++;
532 }
533 if (token == NULL)
534 return -1;
535 if (uid_compare(uid, token, strlen(token)) != 0)
536 return -1;
537 if (strcpy_s(username, buffer_len, temp_name) != EOK)
538 return -1;
539 return strlen(temp_name);
540 }
read_line(char * buf,int buf_len,struct file * fp,loff_t * offset)541 static int read_line(char *buf, int buf_len, struct file *fp, loff_t *offset)
542 {
543 if (offset == NULL) {
544 tloge("offset is null while read file\n");
545 return -1;
546 }
547 ssize_t ret = kernel_read(fp, buf, buf_len, offset);
548 if (ret < 0)
549 return -1;
550 ssize_t i = 0;
551 /* read buf_len, need to find first '\n' */
552 while (i < ret) {
553 if (i >= buf_len)
554 break;
555 if (buf[i] == '\n')
556 break;
557 i++;
558 }
559 if (i < ret)
560 *offset -= (loff_t)(ret - i);
561 if (i < buf_len)
562 buf[i] = '\0';
563 return 0;
564 }
565
566 /* get username by uid,
567 * on linux, user info is stored in system file "/etc/passwd",
568 * each line represents a user, fields are separated by ':',
569 * formatted as such: "username:[encrypted password]:uid:gid:[comments]:home directory:login shell"
570 */
tc_ns_get_uname(uint32_t uid,char * username,int buffer_len,uint32_t * out_len)571 int tc_ns_get_uname(uint32_t uid, char *username, int buffer_len, uint32_t *out_len)
572 {
573 if (username == NULL || out_len == NULL || buffer_len != FIXED_PKG_NAME_LENGTH) {
574 tloge("params is null\n");
575 return -1;
576 }
577 struct file *f = NULL;
578 loff_t offset = 0;
579 f = filp_open(PASSWD_FILE, O_RDONLY, 0);
580 if (IS_ERR(f)) {
581 tloge("kernel open passwd file failed\n");
582 return -1;
583 }
584 while (read_line(username, buffer_len, f, &offset) == 0) {
585 uint32_t ret = parse_uname(uid, username, buffer_len);
586 if (ret >= 0) {
587 *out_len = ret;
588 filp_close(f, NULL);
589 return 0;
590 }
591 }
592 filp_close(f, NULL);
593 return -1;
594 }
595 #endif