1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2017, Linaro Limited 4 */ 5 6 #include <assert.h> 7 #include <bitstring.h> 8 #include <crypto/crypto.h> 9 #include <kernel/mutex.h> 10 #include <kernel/refcount.h> 11 #include <kernel/thread.h> 12 #include <mm/mobj.h> 13 #include <optee_msg_supplicant.h> 14 #include <stdio.h> 15 #include <string.h> 16 #include <tee_api_defines_extensions.h> 17 #include <tee/tadb.h> 18 #include <tee/tee_fs.h> 19 #include <tee/tee_fs_rpc.h> 20 #include <tee/tee_pobj.h> 21 #include <tee/tee_svc_storage.h> 22 #include <utee_defines.h> 23 24 #define TADB_MAX_BUFFER_SIZE (64U * 1024) 25 26 #define TADB_AUTH_ENC_ALG TEE_ALG_AES_GCM 27 #define TADB_IV_SIZE TEE_AES_BLOCK_SIZE 28 #define TADB_TAG_SIZE TEE_AES_BLOCK_SIZE 29 #define TADB_KEY_SIZE TEE_AES_MAX_KEY_SIZE 30 31 struct tee_tadb_dir { 32 const struct tee_file_operations *ops; 33 struct tee_file_handle *fh; 34 int nbits; 35 bitstr_t *files; 36 }; 37 38 struct tadb_entry { 39 struct tee_tadb_property prop; 40 uint32_t file_number; 41 uint8_t iv[TADB_IV_SIZE]; 42 uint8_t tag[TADB_TAG_SIZE]; 43 uint8_t key[TADB_KEY_SIZE]; 44 }; 45 46 struct tadb_header { 47 uint32_t opaque_len; 48 uint8_t opaque[]; 49 }; 50 51 struct tee_tadb_ta_write { 52 struct tee_tadb_dir *db; 53 int fd; 54 struct tadb_entry entry; 55 size_t pos; 56 void *ctx; 57 }; 58 59 struct tee_tadb_ta_read { 60 struct tee_tadb_dir *db; 61 int fd; 62 struct tadb_entry entry; 63 size_t pos; 64 void *ctx; 65 struct mobj *ta_mobj; 66 uint8_t *ta_buf; 67 }; 68 69 static const char tadb_obj_id[] = "ta.db"; 70 static struct tee_tadb_dir *tadb_db; 71 static struct refcount tadb_db_refc; 72 static struct mutex tadb_mutex = MUTEX_INITIALIZER; 73 74 static void file_num_to_str(char *buf, size_t blen, uint32_t file_number) 75 { 76 snprintf(buf, blen, "%" PRIu32 ".ta", file_number); 77 } 78 79 static bool is_null_uuid(const TEE_UUID *uuid) 80 { 81 const TEE_UUID null_uuid = { 0 }; 82 83 return !memcmp(uuid, &null_uuid, sizeof(*uuid)); 84 } 85 86 static void init_memparam(struct thread_param *param, struct mobj *mobj, 87 size_t offs, size_t size, enum thread_param_attr attr) 88 { 89 *param = (struct thread_param){ .attr = attr, .u = { .memref = { 90 .offs = offs, .size = size, .mobj = mobj } } }; 91 } 92 93 static TEE_Result ta_operation_open(unsigned int cmd, uint32_t file_number, 94 int *fd) 95 { 96 struct mobj *mobj; 97 TEE_Result res; 98 void *va; 99 struct thread_param params[] = { 100 [0] = THREAD_PARAM_VALUE(IN, cmd, 0, 0), 101 [2] = THREAD_PARAM_VALUE(OUT, 0, 0, 0), 102 }; 103 104 va = tee_fs_rpc_cache_alloc(TEE_FS_NAME_MAX, &mobj); 105 if (!va) 106 return TEE_ERROR_OUT_OF_MEMORY; 107 108 init_memparam(params + 1, mobj, 0, TEE_FS_NAME_MAX, 109 THREAD_PARAM_ATTR_MEMREF_IN); 110 111 file_num_to_str(va, TEE_FS_NAME_MAX, file_number); 112 113 res = thread_rpc_cmd(OPTEE_MSG_RPC_CMD_FS, ARRAY_SIZE(params), params); 114 if (!res) 115 *fd = params[2].u.value.a; 116 117 return res; 118 } 119 120 static TEE_Result ta_operation_remove(uint32_t file_number) 121 { 122 struct mobj *mobj; 123 void *va; 124 struct thread_param params[2] = { 125 [0] = THREAD_PARAM_VALUE(IN, OPTEE_MRF_REMOVE, 0, 0), 126 }; 127 128 va = tee_fs_rpc_cache_alloc(TEE_FS_NAME_MAX, &mobj); 129 if (!va) 130 return TEE_ERROR_OUT_OF_MEMORY; 131 132 init_memparam(params + 1, mobj, 0, TEE_FS_NAME_MAX, 133 THREAD_PARAM_ATTR_MEMREF_IN); 134 135 file_num_to_str(va, TEE_FS_NAME_MAX, file_number); 136 137 return thread_rpc_cmd(OPTEE_MSG_RPC_CMD_FS, ARRAY_SIZE(params), params); 138 } 139 140 static TEE_Result maybe_grow_files(struct tee_tadb_dir *db, int idx) 141 { 142 void *p; 143 144 if (idx < db->nbits) 145 return TEE_SUCCESS; 146 147 p = realloc(db->files, bitstr_size(idx + 1)); 148 if (!p) 149 return TEE_ERROR_OUT_OF_MEMORY; 150 db->files = p; 151 152 bit_nclear(db->files, db->nbits, idx); 153 db->nbits = idx + 1; 154 155 return TEE_SUCCESS; 156 } 157 158 static TEE_Result set_file(struct tee_tadb_dir *db, int idx) 159 { 160 TEE_Result res = maybe_grow_files(db, idx); 161 162 if (!res) 163 bit_set(db->files, idx); 164 165 return res; 166 } 167 168 static void clear_file(struct tee_tadb_dir *db, int idx) 169 { 170 if (idx < db->nbits) 171 bit_clear(db->files, idx); 172 } 173 174 static bool test_file(struct tee_tadb_dir *db, int idx) 175 { 176 if (idx < db->nbits) 177 return bit_test(db->files, idx); 178 179 return false; 180 } 181 182 static TEE_Result read_ent(struct tee_tadb_dir *db, size_t idx, 183 struct tadb_entry *entry) 184 { 185 size_t l = sizeof(*entry); 186 TEE_Result res = db->ops->read(db->fh, idx * l, entry, &l); 187 188 if (!res && l != sizeof(*entry)) 189 return TEE_ERROR_ITEM_NOT_FOUND; 190 191 return res; 192 } 193 194 static TEE_Result write_ent(struct tee_tadb_dir *db, size_t idx, 195 const struct tadb_entry *entry) 196 { 197 const size_t l = sizeof(*entry); 198 199 return db->ops->write(db->fh, idx * l, entry, l); 200 } 201 202 static TEE_Result tadb_open(struct tee_tadb_dir **db_ret) 203 { 204 TEE_Result res; 205 struct tee_tadb_dir *db = calloc(1, sizeof(*db)); 206 struct tee_pobj po = { 207 .obj_id = (void *)tadb_obj_id, 208 .obj_id_len = sizeof(tadb_obj_id) 209 }; 210 211 if (!db) 212 return TEE_ERROR_OUT_OF_MEMORY; 213 214 db->ops = tee_svc_storage_file_ops(TEE_STORAGE_PRIVATE); 215 216 res = db->ops->open(&po, NULL, &db->fh); 217 if (res == TEE_ERROR_ITEM_NOT_FOUND) 218 res = db->ops->create(&po, false, NULL, 0, NULL, 0, NULL, 0, 219 &db->fh); 220 221 if (res) 222 free(db); 223 else 224 *db_ret = db; 225 226 return res; 227 } 228 229 static TEE_Result tee_tadb_open(struct tee_tadb_dir **db) 230 { 231 if (!refcount_inc(&tadb_db_refc)) { 232 TEE_Result res; 233 234 mutex_lock(&tadb_mutex); 235 if (!tadb_db) { 236 res = tadb_open(&tadb_db); 237 if (!res) 238 refcount_set(&tadb_db_refc, 1); 239 } else { 240 /* 241 * This case is handling the small window where the 242 * reference counter was decreased to 0 but before 243 * the mutex was acquired by tadb_put() this thread 244 * acquired the mutex instead. 245 * 246 * Since tadb_db isn't NULL it's enough to increase 247 * the reference counter. If the value of the 248 * counter is 0 refcount_inc() will fail and we'll 249 * have to set it directly with refcount_set() 250 * instead. 251 */ 252 if (!refcount_inc(&tadb_db_refc)) 253 refcount_set(&tadb_db_refc, 1); 254 res = TEE_SUCCESS; 255 } 256 mutex_unlock(&tadb_mutex); 257 if (res) 258 return res; 259 } 260 261 *db = tadb_db; 262 return TEE_SUCCESS; 263 } 264 265 static void tadb_put(struct tee_tadb_dir *db) 266 { 267 if (refcount_dec(&tadb_db_refc)) { 268 mutex_lock(&tadb_mutex); 269 if (!refcount_val(&tadb_db_refc) && tadb_db) { 270 db->ops->close(&db->fh); 271 free(db->files); 272 free(db); 273 tadb_db = NULL; 274 } 275 mutex_unlock(&tadb_mutex); 276 } 277 } 278 279 static void tee_tadb_close(struct tee_tadb_dir *db) 280 { 281 tadb_put(db); 282 } 283 284 static TEE_Result tadb_authenc_init(TEE_OperationMode mode, 285 const struct tadb_entry *entry, 286 void **ctx_ret) 287 { 288 TEE_Result res; 289 void *ctx; 290 const size_t enc_size = entry->prop.custom_size + entry->prop.bin_size; 291 292 res = crypto_authenc_alloc_ctx(&ctx, TADB_AUTH_ENC_ALG); 293 if (res) 294 return res; 295 296 res = crypto_authenc_init(ctx, TADB_AUTH_ENC_ALG, mode, 297 entry->key, sizeof(entry->key), 298 entry->iv, sizeof(entry->iv), 299 sizeof(entry->tag), 0, enc_size); 300 if (res) 301 crypto_authenc_free_ctx(ctx, TADB_AUTH_ENC_ALG); 302 else 303 *ctx_ret = ctx; 304 305 return res; 306 } 307 308 static TEE_Result tadb_update_payload(void *ctx, TEE_OperationMode mode, 309 const void *src, size_t len, void *dst) 310 { 311 TEE_Result res; 312 size_t sz = len; 313 314 res = crypto_authenc_update_payload(ctx, TADB_AUTH_ENC_ALG, mode, 315 (const uint8_t *)src, len, dst, 316 &sz); 317 assert(res || sz == len); 318 return res; 319 } 320 321 static TEE_Result populate_files(struct tee_tadb_dir *db) 322 { 323 TEE_Result res; 324 size_t idx; 325 326 /* 327 * If db->files isn't NULL the bitfield is already populated and 328 * there's nothing left to do here for now. 329 */ 330 if (db->files) 331 return TEE_SUCCESS; 332 333 /* 334 * Iterate over the TA database and set the bits in the bit field 335 * for used file numbers. Note that set_file() will allocate and 336 * grow the bitfield as needed. 337 * 338 * At the same time clean out duplicate file numbers, the first 339 * entry with the file number has precedence. Duplicate entries is 340 * not supposed to be able to happen, but if it still does better 341 * to clean it out here instead of letting the error spread with 342 * unexpected side effects. 343 */ 344 for (idx = 0;; idx++) { 345 struct tadb_entry entry; 346 347 res = read_ent(db, idx, &entry); 348 if (res) { 349 if (res == TEE_ERROR_ITEM_NOT_FOUND) 350 return TEE_SUCCESS; 351 goto err; 352 } 353 354 if (is_null_uuid(&entry.prop.uuid)) 355 continue; 356 357 if (test_file(db, entry.file_number)) { 358 IMSG("Clearing duplicate file number %" PRIu32, 359 entry.file_number); 360 memset(&entry, 0, sizeof(entry)); 361 res = write_ent(db, idx, &entry); 362 if (res) 363 goto err; 364 continue; 365 } 366 367 res = set_file(db, entry.file_number); 368 if (res) 369 goto err; 370 } 371 372 err: 373 free(db->files); 374 db->files = NULL; 375 db->nbits = 0; 376 377 return res; 378 } 379 380 TEE_Result tee_tadb_ta_create(const struct tee_tadb_property *property, 381 struct tee_tadb_ta_write **ta_ret) 382 { 383 TEE_Result res; 384 struct tee_tadb_ta_write *ta; 385 int i = 0; 386 387 if (is_null_uuid(&property->uuid)) 388 return TEE_ERROR_GENERIC; 389 390 ta = calloc(1, sizeof(*ta)); 391 if (!ta) 392 return TEE_ERROR_OUT_OF_MEMORY; 393 394 res = tee_tadb_open(&ta->db); 395 if (res) 396 goto err_free; 397 398 mutex_lock(&tadb_mutex); 399 400 /* 401 * Since we're going to search for next free file number below we 402 * need to populate the bitfield holding used file numbers. 403 */ 404 res = populate_files(ta->db); 405 if (res) 406 goto err_mutex; 407 408 if (ta->db->files) { 409 bit_ffc(ta->db->files, ta->db->nbits, &i); 410 if (i == -1) 411 i = ta->db->nbits; 412 } 413 414 res = set_file(ta->db, i); 415 if (res) 416 goto err_mutex; 417 418 mutex_unlock(&tadb_mutex); 419 420 ta->entry.file_number = i; 421 ta->entry.prop = *property; 422 423 res = crypto_rng_read(ta->entry.iv, sizeof(ta->entry.iv)); 424 if (res) 425 goto err_put; 426 427 res = crypto_rng_read(ta->entry.key, sizeof(ta->entry.key)); 428 if (res) 429 goto err_put; 430 431 res = ta_operation_open(OPTEE_MRF_CREATE, ta->entry.file_number, 432 &ta->fd); 433 if (res) 434 goto err_put; 435 436 res = tadb_authenc_init(TEE_MODE_ENCRYPT, &ta->entry, &ta->ctx); 437 if (res) 438 goto err_put; 439 440 *ta_ret = ta; 441 442 return TEE_SUCCESS; 443 444 err_mutex: 445 mutex_unlock(&tadb_mutex); 446 err_put: 447 tadb_put(ta->db); 448 err_free: 449 free(ta); 450 451 return res; 452 } 453 454 TEE_Result tee_tadb_ta_write(struct tee_tadb_ta_write *ta, const void *buf, 455 size_t len) 456 { 457 TEE_Result res; 458 const uint8_t *rb = buf; 459 size_t rl = len; 460 struct tee_fs_rpc_operation op; 461 462 while (rl) { 463 size_t wl = MIN(rl, TADB_MAX_BUFFER_SIZE); 464 void *wb; 465 466 res = tee_fs_rpc_write_init(&op, OPTEE_MSG_RPC_CMD_FS, ta->fd, 467 ta->pos, wl, &wb); 468 if (res) 469 return res; 470 471 res = tadb_update_payload(ta->ctx, TEE_MODE_ENCRYPT, 472 rb, wl, wb); 473 if (res) 474 return res; 475 476 res = tee_fs_rpc_write_final(&op); 477 if (res) 478 return res; 479 480 rl -= wl; 481 rb += wl; 482 ta->pos += wl; 483 } 484 485 return TEE_SUCCESS; 486 } 487 488 void tee_tadb_ta_close_and_delete(struct tee_tadb_ta_write *ta) 489 { 490 crypto_authenc_final(ta->ctx, TADB_AUTH_ENC_ALG); 491 crypto_authenc_free_ctx(ta->ctx, TADB_AUTH_ENC_ALG); 492 tee_fs_rpc_close(OPTEE_MSG_RPC_CMD_FS, ta->fd); 493 ta_operation_remove(ta->entry.file_number); 494 495 mutex_lock(&tadb_mutex); 496 clear_file(ta->db, ta->entry.file_number); 497 mutex_unlock(&tadb_mutex); 498 499 tadb_put(ta->db); 500 free(ta); 501 } 502 503 static TEE_Result find_ent(struct tee_tadb_dir *db, const TEE_UUID *uuid, 504 size_t *idx_ret, struct tadb_entry *entry_ret) 505 { 506 TEE_Result res; 507 size_t idx; 508 509 /* 510 * Search for the provided uuid, if it's found return the index it 511 * has together with TEE_SUCCESS. 512 * 513 * If the uuid can't be found return the number indexes together 514 * with TEE_ERROR_ITEM_NOT_FOUND. 515 */ 516 for (idx = 0;; idx++) { 517 struct tadb_entry entry; 518 519 res = read_ent(db, idx, &entry); 520 if (res) { 521 if (res == TEE_ERROR_ITEM_NOT_FOUND) 522 break; 523 return res; 524 } 525 526 if (!memcmp(&entry.prop.uuid, uuid, sizeof(*uuid))) { 527 if (entry_ret) 528 *entry_ret = entry; 529 break; 530 } 531 } 532 533 *idx_ret = idx; 534 return res; 535 } 536 537 static TEE_Result find_free_ent_idx(struct tee_tadb_dir *db, size_t *idx) 538 { 539 const TEE_UUID null_uuid = { 0 }; 540 TEE_Result res = find_ent(db, &null_uuid, idx, NULL); 541 542 /* 543 * Note that *idx is set to the number of entries on 544 * TEE_ERROR_ITEM_NOT_FOUND. 545 */ 546 if (res == TEE_ERROR_ITEM_NOT_FOUND) 547 return TEE_SUCCESS; 548 return res; 549 } 550 551 TEE_Result tee_tadb_ta_close_and_commit(struct tee_tadb_ta_write *ta) 552 { 553 TEE_Result res; 554 size_t dsz = 0; 555 size_t sz = sizeof(ta->entry.tag); 556 size_t idx; 557 struct tadb_entry old_ent; 558 bool have_old_ent = false; 559 560 res = crypto_authenc_enc_final(ta->ctx, TADB_AUTH_ENC_ALG, 561 NULL, 0, NULL, &dsz, 562 ta->entry.tag, &sz); 563 if (res) 564 goto err; 565 566 tee_fs_rpc_close(OPTEE_MSG_RPC_CMD_FS, ta->fd); 567 568 mutex_lock(&tadb_mutex); 569 /* 570 * First try to find an existing TA to replace. If there's one 571 * we'll use the entry, but we should also remove the old encrypted 572 * file. 573 * 574 * If there isn't an existing TA to replace, grab a new entry. 575 */ 576 res = find_ent(ta->db, &ta->entry.prop.uuid, &idx, &old_ent); 577 if (!res) { 578 have_old_ent = true; 579 } else { 580 res = find_free_ent_idx(ta->db, &idx); 581 if (res) 582 goto err_mutex; 583 } 584 res = write_ent(ta->db, idx, &ta->entry); 585 if (res) 586 goto err_mutex; 587 if (have_old_ent) 588 clear_file(ta->db, old_ent.file_number); 589 mutex_unlock(&tadb_mutex); 590 591 crypto_authenc_final(ta->ctx, TADB_AUTH_ENC_ALG); 592 crypto_authenc_free_ctx(ta->ctx, TADB_AUTH_ENC_ALG); 593 tadb_put(ta->db); 594 free(ta); 595 if (have_old_ent) 596 ta_operation_remove(old_ent.file_number); 597 return TEE_SUCCESS; 598 599 err_mutex: 600 mutex_unlock(&tadb_mutex); 601 err: 602 tee_tadb_ta_close_and_delete(ta); 603 return res; 604 } 605 606 TEE_Result tee_tadb_ta_delete(const TEE_UUID *uuid) 607 { 608 const struct tadb_entry null_entry = { { { 0 } } }; 609 struct tee_tadb_dir *db; 610 struct tadb_entry entry; 611 size_t idx; 612 TEE_Result res; 613 614 if (is_null_uuid(uuid)) 615 return TEE_ERROR_GENERIC; 616 617 res = tee_tadb_open(&db); 618 if (res) 619 return res; 620 621 mutex_lock(&tadb_mutex); 622 res = find_ent(db, uuid, &idx, &entry); 623 if (res) { 624 mutex_unlock(&tadb_mutex); 625 tee_tadb_close(db); 626 return res; 627 } 628 629 clear_file(db, entry.file_number); 630 res = write_ent(db, idx, &null_entry); 631 mutex_unlock(&tadb_mutex); 632 633 tee_tadb_close(db); 634 if (res) 635 return res; 636 637 ta_operation_remove(entry.file_number); 638 return TEE_SUCCESS; 639 } 640 641 TEE_Result tee_tadb_ta_open(const TEE_UUID *uuid, 642 struct tee_tadb_ta_read **ta_ret) 643 { 644 TEE_Result res; 645 size_t idx; 646 struct tee_tadb_ta_read *ta; 647 static struct tadb_entry last_entry; 648 649 if (is_null_uuid(uuid)) 650 return TEE_ERROR_GENERIC; 651 652 ta = calloc(1, sizeof(*ta)); 653 if (!ta) 654 return TEE_ERROR_OUT_OF_MEMORY; 655 656 if (!memcmp(uuid, &last_entry.prop.uuid, sizeof(*uuid))) { 657 ta->entry = last_entry; 658 } else { 659 res = tee_tadb_open(&ta->db); 660 if (res) 661 goto err_free; /* Mustn't all tadb_put() */ 662 663 mutex_read_lock(&tadb_mutex); 664 res = find_ent(ta->db, uuid, &idx, &ta->entry); 665 mutex_read_unlock(&tadb_mutex); 666 if (res) 667 goto err; 668 } 669 670 res = ta_operation_open(OPTEE_MRF_OPEN, ta->entry.file_number, &ta->fd); 671 if (res) 672 goto err; 673 674 res = tadb_authenc_init(TEE_MODE_DECRYPT, &ta->entry, &ta->ctx); 675 if (res) 676 goto err; 677 678 *ta_ret = ta; 679 680 return TEE_SUCCESS; 681 err: 682 tadb_put(ta->db); 683 err_free: 684 free(ta); 685 return res; 686 } 687 688 const struct tee_tadb_property * 689 tee_tadb_ta_get_property(struct tee_tadb_ta_read *ta) 690 { 691 return &ta->entry.prop; 692 } 693 694 static TEE_Result ta_load(struct tee_tadb_ta_read *ta) 695 { 696 TEE_Result res; 697 const size_t sz = ta->entry.prop.custom_size + ta->entry.prop.bin_size; 698 struct thread_param params[2] = { 699 [0] = THREAD_PARAM_VALUE(IN, OPTEE_MRF_READ, ta->fd, 0), 700 }; 701 702 if (ta->ta_mobj) 703 return TEE_SUCCESS; 704 705 ta->ta_mobj = thread_rpc_alloc_payload(sz); 706 if (!ta->ta_mobj) 707 return TEE_ERROR_OUT_OF_MEMORY; 708 709 ta->ta_buf = mobj_get_va(ta->ta_mobj, 0); 710 assert(ta->ta_buf); 711 712 init_memparam(params + 1, ta->ta_mobj, 0, sz, 713 THREAD_PARAM_ATTR_MEMREF_OUT); 714 715 res = thread_rpc_cmd(OPTEE_MSG_RPC_CMD_FS, ARRAY_SIZE(params), params); 716 if (res) { 717 thread_rpc_free_payload(ta->ta_mobj); 718 ta->ta_mobj = NULL; 719 } 720 return res; 721 } 722 723 TEE_Result tee_tadb_ta_read(struct tee_tadb_ta_read *ta, void *buf, size_t *len) 724 { 725 TEE_Result res; 726 const size_t sz = ta->entry.prop.custom_size + ta->entry.prop.bin_size; 727 size_t l = MIN(*len, sz - ta->pos); 728 729 res = ta_load(ta); 730 if (res) 731 return res; 732 733 if (buf) { 734 res = tadb_update_payload(ta->ctx, TEE_MODE_DECRYPT, 735 ta->ta_buf + ta->pos, l, buf); 736 if (res) 737 return res; 738 } else { 739 size_t num_bytes = 0; 740 size_t b_size = MIN(256U, l); 741 uint8_t *b = malloc(b_size); 742 743 if (!b) 744 return TEE_ERROR_OUT_OF_MEMORY; 745 746 while (num_bytes < l) { 747 size_t n = MIN(b_size, l - num_bytes); 748 749 res = tadb_update_payload(ta->ctx, TEE_MODE_DECRYPT, 750 ta->ta_buf + ta->pos + 751 num_bytes, n, b); 752 if (res) 753 break; 754 num_bytes += n; 755 } 756 757 free(b); 758 if (res) 759 return res; 760 } 761 762 ta->pos += l; 763 if (ta->pos == sz) { 764 size_t dl = 0; 765 766 res = crypto_authenc_dec_final(ta->ctx, TADB_AUTH_ENC_ALG, 767 NULL, 0, NULL, &dl, 768 ta->entry.tag, TADB_TAG_SIZE); 769 if (res) 770 return res; 771 } 772 *len = l; 773 return TEE_SUCCESS; 774 } 775 776 void tee_tadb_ta_close(struct tee_tadb_ta_read *ta) 777 { 778 crypto_authenc_final(ta->ctx, TADB_AUTH_ENC_ALG); 779 crypto_authenc_free_ctx(ta->ctx, TADB_AUTH_ENC_ALG); 780 if (ta->ta_mobj) 781 thread_rpc_free_payload(ta->ta_mobj); 782 tee_fs_rpc_close(OPTEE_MSG_RPC_CMD_FS, ta->fd); 783 tadb_put(ta->db); 784 free(ta); 785 } 786