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 45struct 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 53static 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 78static 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 103const 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 114static 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 145struct get_code_info { 146 unsigned long code_start; 147 unsigned long code_end; 148 unsigned long code_size; 149}; 150static 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 */ 207static 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 259static 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 301int 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 362static 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; 379error: 380 return -EFAULT; 381} 382 383static 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 396static 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 413static 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 441int 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 495error: 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 508static 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" */ 523static 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} 541static 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*/ 571int 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