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