1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2017, 2019, Linaro Limited 4 * Copyright (c) 2020, Arm Limited. 5 */ 6 7 /* 8 * Security properties of REE-FS TAs 9 * ================================= 10 * 11 * Authentication only 12 * ------------------- 13 * 14 * Required security properties: 15 * 1. Authentication and non-repudiation of a TA to Service Provider (SP). 16 * 2. Integrity of a TA. 17 * 18 * To satisfy (1) and (2), SP needs to sign TA and OP-TEE core needs to verify 19 * the signature using SP public key with computed hash of the TA. 20 * 21 * Authentication along with Confidentiality 22 * ----------------------------------------- 23 * 24 * Required security properties: 25 * 1. Authentication and non-repudiation of a TA to Service Provider (SP). 26 * 2. Confidentiality of a TA. 27 * 3. Integrity of an encrypted TA blob. 28 * 29 * To satisfy (1), SP needs to sign plain TA and OP-TEE core needs to verify the 30 * signature using SP public key with computed hash of the TA. 31 * 32 * To satisfy (2) and (3), SP needs to do authenticated encryption of TA and 33 * OP-TEE core needs to do authenticated decryption of TA to retrieve its 34 * contents. Here encryption provides the confidentiality of TA and MAC tag 35 * provides the integrity of encrypted TA blob. 36 */ 37 38 #include <assert.h> 39 #include <crypto/crypto.h> 40 #include <initcall.h> 41 #include <kernel/thread.h> 42 #include <kernel/ts_store.h> 43 #include <mm/core_memprot.h> 44 #include <mm/tee_mm.h> 45 #include <mm/mobj.h> 46 #include <optee_rpc_cmd.h> 47 #include <signed_hdr.h> 48 #include <stdlib.h> 49 #include <string.h> 50 #include <tee_api_defines_extensions.h> 51 #include <tee_api_types.h> 52 #include <tee/tee_pobj.h> 53 #include <tee/tee_svc_storage.h> 54 #include <tee/tee_ta_enc_manager.h> 55 #include <tee/uuid.h> 56 #include <utee_defines.h> 57 58 struct ree_fs_ta_handle { 59 struct shdr *nw_ta; /* Non-secure (shared memory) */ 60 size_t nw_ta_size; 61 struct mobj *mobj; 62 size_t offs; 63 struct shdr *shdr; /* Verified secure copy of @nw_ta's signed header */ 64 void *hash_ctx; 65 void *enc_ctx; 66 struct shdr_bootstrap_ta *bs_hdr; 67 struct shdr_encrypted_ta *ehdr; 68 }; 69 70 struct ver_db_entry { 71 uint8_t uuid[sizeof(TEE_UUID)]; 72 uint32_t version; 73 }; 74 75 struct ver_db_hdr { 76 uint32_t db_version; 77 uint32_t nb_entries; 78 }; 79 80 static const char ta_ver_db[] = "ta_ver.db"; 81 static const char subkey_ver_db[] = "subkey_ver.db"; 82 static struct mutex ver_db_mutex = MUTEX_INITIALIZER; 83 84 static TEE_Result check_update_version(const char *db_name, 85 const uint8_t uuid[sizeof(TEE_UUID)], 86 uint32_t version) 87 { 88 struct ver_db_entry db_entry = { }; 89 const struct tee_file_operations *ops = NULL; 90 struct tee_file_handle *fh = NULL; 91 TEE_Result res = TEE_SUCCESS; 92 bool entry_found = false; 93 size_t len = 0; 94 unsigned int i = 0; 95 struct ver_db_hdr db_hdr = { }; 96 struct tee_pobj pobj = { 97 .obj_id = (void *)db_name, 98 .obj_id_len = strlen(db_name) + 1, 99 }; 100 101 ops = tee_svc_storage_file_ops(TEE_STORAGE_PRIVATE); 102 if (!ops) 103 return TEE_SUCCESS; /* Compiled with no secure storage */ 104 105 mutex_lock(&ver_db_mutex); 106 107 res = ops->open(&pobj, NULL, &fh); 108 if (res != TEE_SUCCESS && res != TEE_ERROR_ITEM_NOT_FOUND) 109 goto out; 110 111 if (res == TEE_ERROR_ITEM_NOT_FOUND) { 112 res = ops->create(&pobj, false, NULL, 0, NULL, 0, NULL, 0, &fh); 113 if (res != TEE_SUCCESS) 114 goto out; 115 116 res = ops->write(fh, 0, &db_hdr, sizeof(db_hdr)); 117 if (res != TEE_SUCCESS) 118 goto out; 119 } else { 120 len = sizeof(db_hdr); 121 122 res = ops->read(fh, 0, &db_hdr, &len); 123 if (res != TEE_SUCCESS) { 124 goto out; 125 } else if (len != sizeof(db_hdr)) { 126 res = TEE_ERROR_BAD_STATE; 127 goto out; 128 } 129 } 130 131 for (i = 0; i < db_hdr.nb_entries; i++) { 132 len = sizeof(db_entry); 133 134 res = ops->read(fh, sizeof(db_hdr) + (i * len), &db_entry, 135 &len); 136 if (res != TEE_SUCCESS) { 137 goto out; 138 } else if (len != sizeof(db_entry)) { 139 res = TEE_ERROR_BAD_STATE; 140 goto out; 141 } 142 143 if (!memcmp(uuid, db_entry.uuid, sizeof(TEE_UUID))) { 144 entry_found = true; 145 break; 146 } 147 } 148 149 if (entry_found) { 150 if (db_entry.version > version) { 151 res = TEE_ERROR_ACCESS_CONFLICT; 152 goto out; 153 } else if (db_entry.version < version) { 154 memcpy(db_entry.uuid, uuid, sizeof(TEE_UUID)); 155 db_entry.version = version; 156 len = sizeof(db_entry); 157 res = ops->write(fh, sizeof(db_hdr) + (i * len), 158 &db_entry, len); 159 if (res != TEE_SUCCESS) 160 goto out; 161 } 162 } else { 163 memcpy(db_entry.uuid, uuid, sizeof(TEE_UUID)); 164 db_entry.version = version; 165 len = sizeof(db_entry); 166 res = ops->write(fh, sizeof(db_hdr) + (db_hdr.nb_entries * len), 167 &db_entry, len); 168 if (res != TEE_SUCCESS) 169 goto out; 170 171 db_hdr.nb_entries++; 172 res = ops->write(fh, 0, &db_hdr, sizeof(db_hdr)); 173 if (res != TEE_SUCCESS) 174 goto out; 175 } 176 177 out: 178 ops->close(&fh); 179 mutex_unlock(&ver_db_mutex); 180 return res; 181 } 182 183 /* 184 * Load a TA via RPC with UUID defined by input param @uuid. The virtual 185 * address of the raw TA binary is received in out parameter @ta. 186 */ 187 static TEE_Result rpc_load(const TEE_UUID *uuid, struct shdr **ta, 188 size_t *ta_size, struct mobj **mobj) 189 { 190 TEE_Result res; 191 struct thread_param params[2]; 192 193 if (!uuid || !ta || !mobj || !ta_size) 194 return TEE_ERROR_BAD_PARAMETERS; 195 196 memset(params, 0, sizeof(params)); 197 params[0].attr = THREAD_PARAM_ATTR_VALUE_IN; 198 tee_uuid_to_octets((void *)¶ms[0].u.value, uuid); 199 params[1].attr = THREAD_PARAM_ATTR_MEMREF_OUT; 200 201 res = thread_rpc_cmd(OPTEE_RPC_CMD_LOAD_TA, 2, params); 202 if (res != TEE_SUCCESS) 203 return res; 204 205 *mobj = thread_rpc_alloc_payload(params[1].u.memref.size); 206 if (!*mobj) 207 return TEE_ERROR_OUT_OF_MEMORY; 208 209 *ta = mobj_get_va(*mobj, 0, params[1].u.memref.size); 210 if (!*ta) { 211 res = TEE_ERROR_SHORT_BUFFER; 212 goto exit; 213 } 214 /* We don't expect NULL as thread_rpc_alloc_payload() was successful */ 215 assert(*ta); 216 *ta_size = params[1].u.memref.size; 217 218 params[0].attr = THREAD_PARAM_ATTR_VALUE_IN; 219 tee_uuid_to_octets((void *)¶ms[0].u.value, uuid); 220 params[1].attr = THREAD_PARAM_ATTR_MEMREF_OUT; 221 params[1].u.memref.offs = 0; 222 params[1].u.memref.mobj = *mobj; 223 224 res = thread_rpc_cmd(OPTEE_RPC_CMD_LOAD_TA, 2, params); 225 exit: 226 if (res != TEE_SUCCESS) 227 thread_rpc_free_payload(*mobj); 228 229 return res; 230 } 231 232 static TEE_Result ree_fs_ta_open(const TEE_UUID *uuid, 233 struct ts_store_handle **h) 234 { 235 uint8_t next_uuid[sizeof(TEE_UUID)] = { }; 236 struct ree_fs_ta_handle *handle; 237 uint8_t *next_uuid_ptr = NULL; 238 struct shdr *shdr = NULL; 239 struct mobj *mobj = NULL; 240 void *hash_ctx = NULL; 241 struct shdr *ta = NULL; 242 size_t ta_size = 0; 243 TEE_Result res = TEE_SUCCESS; 244 size_t offs = 0; 245 struct shdr_bootstrap_ta *bs_hdr = NULL; 246 struct shdr_encrypted_ta *ehdr = NULL; 247 size_t shdr_sz = 0; 248 uint32_t max_depth = UINT32_MAX; 249 250 handle = calloc(1, sizeof(*handle)); 251 if (!handle) 252 return TEE_ERROR_OUT_OF_MEMORY; 253 254 /* Request TA from tee-supplicant */ 255 res = rpc_load(uuid, &ta, &ta_size, &mobj); 256 if (res != TEE_SUCCESS) 257 goto error; 258 259 /* Make secure copy of signed header */ 260 shdr = shdr_alloc_and_copy(0, ta, ta_size); 261 if (!shdr) { 262 res = TEE_ERROR_SECURITY; 263 goto error_free_payload; 264 } 265 266 /* Validate header signature */ 267 res = shdr_verify_signature(shdr); 268 if (res != TEE_SUCCESS) 269 goto error_free_payload; 270 271 shdr_sz = SHDR_GET_SIZE(shdr); 272 if (!shdr_sz) { 273 res = TEE_ERROR_SECURITY; 274 goto error_free_payload; 275 } 276 offs = shdr_sz; 277 278 while (shdr->img_type == SHDR_SUBKEY) { 279 struct shdr_pub_key pub_key = { }; 280 281 if (offs > ta_size) { 282 res = TEE_ERROR_SECURITY; 283 goto error_free_payload; 284 } 285 286 res = shdr_load_pub_key(shdr, offs, (const void *)ta, 287 ta_size, next_uuid_ptr, max_depth, 288 &pub_key); 289 if (res) 290 goto error_free_payload; 291 292 if (ADD_OVERFLOW(offs, shdr->img_size, &offs) || 293 ADD_OVERFLOW(offs, pub_key.name_size, &offs) || 294 offs > ta_size) { 295 res = TEE_ERROR_SECURITY; 296 goto error_free_payload; 297 } 298 max_depth = pub_key.max_depth; 299 memcpy(next_uuid, pub_key.next_uuid, sizeof(TEE_UUID)); 300 next_uuid_ptr = next_uuid; 301 302 res = check_update_version(subkey_ver_db, pub_key.uuid, 303 pub_key.version); 304 if (res) { 305 res = TEE_ERROR_SECURITY; 306 shdr_free_pub_key(&pub_key); 307 goto error_free_payload; 308 } 309 310 shdr_free(shdr); 311 shdr = shdr_alloc_and_copy(offs, ta, ta_size); 312 res = TEE_ERROR_SECURITY; 313 if (shdr) 314 res = shdr_verify_signature2(&pub_key, shdr); 315 shdr_free_pub_key(&pub_key); 316 if (res) 317 goto error_free_payload; 318 319 shdr_sz = SHDR_GET_SIZE(shdr); 320 if (!shdr_sz) { 321 res = TEE_ERROR_SECURITY; 322 goto error_free_payload; 323 } 324 offs += shdr_sz; 325 if (offs > ta_size) { 326 res = TEE_ERROR_SECURITY; 327 goto error_free_payload; 328 } 329 } 330 331 if (shdr->img_type != SHDR_TA && shdr->img_type != SHDR_BOOTSTRAP_TA && 332 shdr->img_type != SHDR_ENCRYPTED_TA) { 333 res = TEE_ERROR_SECURITY; 334 goto error_free_payload; 335 } 336 337 /* 338 * If we're verifying this TA using a subkey, make sure that 339 * the UUID of the TA belongs to the namespace defined by the subkey. 340 * The namespace is defined as in RFC4122, that is, valid UUID 341 * is calculated as a V5 UUID SHA-512(subkey UUID, "name string"). 342 */ 343 if (next_uuid_ptr) { 344 TEE_UUID check_uuid = { }; 345 346 tee_uuid_from_octets(&check_uuid, next_uuid_ptr); 347 if (memcmp(&check_uuid, uuid, sizeof(*uuid))) { 348 res = TEE_ERROR_SECURITY; 349 goto error_free_payload; 350 } 351 } 352 353 /* 354 * Initialize a hash context and run the algorithm over the signed 355 * header (less the final file hash and its signature of course) 356 */ 357 res = crypto_hash_alloc_ctx(&hash_ctx, 358 TEE_DIGEST_HASH_TO_ALGO(shdr->algo)); 359 if (res != TEE_SUCCESS) 360 goto error_free_payload; 361 res = crypto_hash_init(hash_ctx); 362 if (res != TEE_SUCCESS) 363 goto error_free_hash; 364 res = crypto_hash_update(hash_ctx, (uint8_t *)shdr, sizeof(*shdr)); 365 if (res != TEE_SUCCESS) 366 goto error_free_hash; 367 368 if (shdr->img_type == SHDR_BOOTSTRAP_TA || 369 shdr->img_type == SHDR_ENCRYPTED_TA) { 370 TEE_UUID bs_uuid = { }; 371 size_t sz = shdr_sz; 372 373 if (ADD_OVERFLOW(sz, sizeof(*bs_hdr), &sz) || ta_size < sz) { 374 res = TEE_ERROR_SECURITY; 375 goto error_free_hash; 376 } 377 378 bs_hdr = malloc(sizeof(*bs_hdr)); 379 if (!bs_hdr) { 380 res = TEE_ERROR_OUT_OF_MEMORY; 381 goto error_free_hash; 382 } 383 384 memcpy(bs_hdr, (uint8_t *)ta + offs, sizeof(*bs_hdr)); 385 386 /* 387 * There's a check later that the UUID embedded inside the 388 * ELF is matching, but since we now have easy access to 389 * the expected uuid of the TA we check it a bit earlier 390 * here. 391 */ 392 tee_uuid_from_octets(&bs_uuid, bs_hdr->uuid); 393 if (memcmp(&bs_uuid, uuid, sizeof(TEE_UUID))) { 394 res = TEE_ERROR_SECURITY; 395 goto error_free_hash; 396 } 397 398 res = crypto_hash_update(hash_ctx, (uint8_t *)bs_hdr, 399 sizeof(*bs_hdr)); 400 if (res != TEE_SUCCESS) 401 goto error_free_hash; 402 offs += sizeof(*bs_hdr); 403 handle->bs_hdr = bs_hdr; 404 } 405 406 if (shdr->img_type == SHDR_ENCRYPTED_TA) { 407 struct shdr_encrypted_ta img_ehdr = { }; 408 size_t sz = shdr_sz; 409 size_t ehdr_sz = 0; 410 411 if (ADD_OVERFLOW(sz, sizeof(struct shdr_bootstrap_ta), &sz) || 412 ADD_OVERFLOW(sz, sizeof(img_ehdr), &sz) || 413 ta_size < sz) { 414 res = TEE_ERROR_SECURITY; 415 goto error_free_hash; 416 } 417 418 memcpy(&img_ehdr, ((uint8_t *)ta + offs), sizeof(img_ehdr)); 419 ehdr_sz = SHDR_ENC_GET_SIZE(&img_ehdr); 420 sz -= sizeof(img_ehdr); 421 if (!ehdr_sz || ADD_OVERFLOW(sz, ehdr_sz, &sz) || 422 ta_size < sz) { 423 res = TEE_ERROR_SECURITY; 424 goto error_free_hash; 425 } 426 427 /* 428 * This is checked further down too, but we must sanity 429 * check shdr->img_size before it's used below. 430 */ 431 if (ta_size != sz + shdr->img_size) { 432 res = TEE_ERROR_SECURITY; 433 goto error_free_hash; 434 } 435 436 ehdr = malloc(ehdr_sz); 437 if (!ehdr) { 438 res = TEE_ERROR_OUT_OF_MEMORY; 439 goto error_free_hash; 440 } 441 442 *ehdr = img_ehdr; 443 memcpy((uint8_t *)ehdr + sizeof(img_ehdr), 444 (uint8_t *)ta + offs + sizeof(img_ehdr), 445 ehdr_sz - sizeof(img_ehdr)); 446 447 res = crypto_hash_update(hash_ctx, (uint8_t *)ehdr, ehdr_sz); 448 if (res != TEE_SUCCESS) 449 goto error_free_hash; 450 451 res = tee_ta_decrypt_init(&handle->enc_ctx, ehdr, 452 shdr->img_size); 453 if (res != TEE_SUCCESS) 454 goto error_free_hash; 455 456 offs += ehdr_sz; 457 handle->ehdr = ehdr; 458 } 459 460 if (ta_size != offs + shdr->img_size) { 461 res = TEE_ERROR_SECURITY; 462 goto error_free_hash; 463 } 464 465 handle->nw_ta = ta; 466 handle->nw_ta_size = ta_size; 467 handle->offs = offs; 468 handle->hash_ctx = hash_ctx; 469 handle->shdr = shdr; 470 handle->mobj = mobj; 471 *h = (struct ts_store_handle *)handle; 472 return TEE_SUCCESS; 473 474 error_free_hash: 475 crypto_hash_free_ctx(hash_ctx); 476 error_free_payload: 477 thread_rpc_free_payload(mobj); 478 error: 479 free(ehdr); 480 free(bs_hdr); 481 shdr_free(shdr); 482 free(handle); 483 return res; 484 } 485 486 static TEE_Result ree_fs_ta_get_size(const struct ts_store_handle *h, 487 size_t *size) 488 { 489 struct ree_fs_ta_handle *handle = (struct ree_fs_ta_handle *)h; 490 491 *size = handle->shdr->img_size; 492 return TEE_SUCCESS; 493 } 494 495 static TEE_Result ree_fs_ta_get_tag(const struct ts_store_handle *h, 496 uint8_t *tag, unsigned int *tag_len) 497 { 498 struct ree_fs_ta_handle *handle = (struct ree_fs_ta_handle *)h; 499 500 if (!tag || *tag_len < handle->shdr->hash_size) { 501 *tag_len = handle->shdr->hash_size; 502 return TEE_ERROR_SHORT_BUFFER; 503 } 504 *tag_len = handle->shdr->hash_size; 505 506 memcpy(tag, SHDR_GET_HASH(handle->shdr), handle->shdr->hash_size); 507 508 return TEE_SUCCESS; 509 } 510 511 static TEE_Result check_digest(struct ree_fs_ta_handle *h) 512 { 513 void *digest = NULL; 514 TEE_Result res; 515 516 digest = malloc(h->shdr->hash_size); 517 if (!digest) 518 return TEE_ERROR_OUT_OF_MEMORY; 519 res = crypto_hash_final(h->hash_ctx, digest, h->shdr->hash_size); 520 if (res != TEE_SUCCESS) { 521 res = TEE_ERROR_SECURITY; 522 goto out; 523 } 524 if (memcmp(digest, SHDR_GET_HASH(h->shdr), h->shdr->hash_size)) 525 res = TEE_ERROR_SECURITY; 526 out: 527 free(digest); 528 return res; 529 } 530 531 static TEE_Result ree_fs_ta_read(struct ts_store_handle *h, void *data, 532 size_t len) 533 { 534 struct ree_fs_ta_handle *handle = (struct ree_fs_ta_handle *)h; 535 536 uint8_t *src = (uint8_t *)handle->nw_ta + handle->offs; 537 size_t next_offs = 0; 538 uint8_t *dst = src; 539 TEE_Result res = TEE_SUCCESS; 540 541 if (ADD_OVERFLOW(handle->offs, len, &next_offs) || 542 next_offs > handle->nw_ta_size) 543 return TEE_ERROR_BAD_PARAMETERS; 544 545 if (handle->shdr->img_type == SHDR_ENCRYPTED_TA) { 546 if (data) { 547 dst = data; /* Hash secure buffer */ 548 res = tee_ta_decrypt_update(handle->enc_ctx, dst, src, 549 len); 550 if (res != TEE_SUCCESS) 551 return TEE_ERROR_SECURITY; 552 } else { 553 size_t num_bytes = 0; 554 size_t b_size = MIN(1024U, len); 555 uint8_t *b = malloc(b_size); 556 557 if (!b) 558 return TEE_ERROR_OUT_OF_MEMORY; 559 560 dst = NULL; 561 while (num_bytes < len) { 562 size_t n = MIN(b_size, len - num_bytes); 563 564 res = tee_ta_decrypt_update(handle->enc_ctx, b, 565 src + num_bytes, n); 566 if (res) 567 break; 568 num_bytes += n; 569 570 res = crypto_hash_update(handle->hash_ctx, b, 571 n); 572 if (res) 573 break; 574 } 575 576 free(b); 577 if (res != TEE_SUCCESS) 578 return TEE_ERROR_SECURITY; 579 } 580 } else if (data) { 581 dst = data; /* Hash secure buffer (shm might be modified) */ 582 memcpy(dst, src, len); 583 } 584 585 if (dst) { 586 res = crypto_hash_update(handle->hash_ctx, dst, len); 587 if (res != TEE_SUCCESS) 588 return TEE_ERROR_SECURITY; 589 } 590 591 handle->offs = next_offs; 592 if (handle->offs == handle->nw_ta_size) { 593 if (handle->shdr->img_type == SHDR_ENCRYPTED_TA) { 594 /* 595 * Last read: time to finalize authenticated 596 * decryption. 597 */ 598 res = tee_ta_decrypt_final(handle->enc_ctx, 599 handle->ehdr, NULL, NULL, 0); 600 if (res != TEE_SUCCESS) 601 return TEE_ERROR_SECURITY; 602 } 603 /* 604 * Last read: time to check if our digest matches the expected 605 * one (from the signed header) 606 */ 607 res = check_digest(handle); 608 if (res != TEE_SUCCESS) 609 return res; 610 611 if (handle->bs_hdr) 612 res = check_update_version(ta_ver_db, 613 handle->bs_hdr->uuid, 614 handle->bs_hdr->ta_version); 615 } 616 return res; 617 } 618 619 static void ree_fs_ta_close(struct ts_store_handle *h) 620 { 621 struct ree_fs_ta_handle *handle = (struct ree_fs_ta_handle *)h; 622 623 if (!handle) 624 return; 625 thread_rpc_free_payload(handle->mobj); 626 crypto_hash_free_ctx(handle->hash_ctx); 627 free(handle->shdr); 628 free(handle->ehdr); 629 free(handle->bs_hdr); 630 free(handle); 631 } 632 633 #ifndef CFG_REE_FS_TA_BUFFERED 634 REGISTER_TA_STORE(9) = { 635 .description = "REE", 636 .open = ree_fs_ta_open, 637 .get_size = ree_fs_ta_get_size, 638 .get_tag = ree_fs_ta_get_tag, 639 .read = ree_fs_ta_read, 640 .close = ree_fs_ta_close, 641 }; 642 #endif 643 644 #ifdef CFG_REE_FS_TA_BUFFERED 645 646 /* 647 * This is a wrapper around the "REE FS" TA store. 648 * The whole TA/library is read into a temporary buffer during .open(). This 649 * allows the binary to be authenticated before any data is read and processed 650 * by the upper layer (ELF loader). 651 */ 652 653 struct buf_ree_fs_ta_handle { 654 struct ts_store_handle *h; /* Note: a REE FS TA store handle */ 655 size_t ta_size; 656 tee_mm_entry_t *mm; 657 uint8_t *buf; 658 size_t offs; 659 uint8_t *tag; 660 unsigned int tag_len; 661 }; 662 663 static TEE_Result buf_ta_open(const TEE_UUID *uuid, 664 struct ts_store_handle **h) 665 { 666 struct buf_ree_fs_ta_handle *handle = NULL; 667 TEE_Result res = TEE_SUCCESS; 668 669 handle = calloc(1, sizeof(*handle)); 670 if (!handle) 671 return TEE_ERROR_OUT_OF_MEMORY; 672 res = ree_fs_ta_open(uuid, &handle->h); 673 if (res) 674 goto err2; 675 res = ree_fs_ta_get_size(handle->h, &handle->ta_size); 676 if (res) 677 goto err; 678 679 res = ree_fs_ta_get_tag(handle->h, NULL, &handle->tag_len); 680 if (res != TEE_ERROR_SHORT_BUFFER) { 681 res = TEE_ERROR_GENERIC; 682 goto err; 683 } 684 handle->tag = malloc(handle->tag_len); 685 if (!handle->tag) { 686 res = TEE_ERROR_OUT_OF_MEMORY; 687 goto err; 688 } 689 res = ree_fs_ta_get_tag(handle->h, handle->tag, &handle->tag_len); 690 if (res) 691 goto err; 692 693 handle->mm = tee_mm_alloc(&tee_mm_sec_ddr, handle->ta_size); 694 if (!handle->mm) { 695 res = TEE_ERROR_OUT_OF_MEMORY; 696 goto err; 697 } 698 handle->buf = phys_to_virt(tee_mm_get_smem(handle->mm), 699 MEM_AREA_TA_RAM, handle->ta_size); 700 if (!handle->buf) { 701 res = TEE_ERROR_OUT_OF_MEMORY; 702 goto err; 703 } 704 res = ree_fs_ta_read(handle->h, handle->buf, handle->ta_size); 705 if (res) 706 goto err; 707 *h = (struct ts_store_handle *)handle; 708 err: 709 ree_fs_ta_close(handle->h); 710 err2: 711 if (res) { 712 tee_mm_free(handle->mm); 713 free(handle->tag); 714 free(handle); 715 } 716 return res; 717 } 718 719 static TEE_Result buf_ta_get_size(const struct ts_store_handle *h, 720 size_t *size) 721 { 722 struct buf_ree_fs_ta_handle *handle = (struct buf_ree_fs_ta_handle *)h; 723 724 *size = handle->ta_size; 725 return TEE_SUCCESS; 726 } 727 728 static TEE_Result buf_ta_read(struct ts_store_handle *h, void *data, 729 size_t len) 730 { 731 struct buf_ree_fs_ta_handle *handle = (struct buf_ree_fs_ta_handle *)h; 732 uint8_t *src = handle->buf + handle->offs; 733 size_t next_offs = 0; 734 735 if (ADD_OVERFLOW(handle->offs, len, &next_offs) || 736 next_offs > handle->ta_size) 737 return TEE_ERROR_BAD_PARAMETERS; 738 739 if (data) 740 memcpy(data, src, len); 741 handle->offs = next_offs; 742 return TEE_SUCCESS; 743 } 744 745 static TEE_Result buf_ta_get_tag(const struct ts_store_handle *h, 746 uint8_t *tag, unsigned int *tag_len) 747 { 748 struct buf_ree_fs_ta_handle *handle = (struct buf_ree_fs_ta_handle *)h; 749 750 *tag_len = handle->tag_len; 751 if (!tag || *tag_len < handle->tag_len) 752 return TEE_ERROR_SHORT_BUFFER; 753 754 memcpy(tag, handle->tag, handle->tag_len); 755 756 return TEE_SUCCESS; 757 } 758 759 static void buf_ta_close(struct ts_store_handle *h) 760 { 761 struct buf_ree_fs_ta_handle *handle = (struct buf_ree_fs_ta_handle *)h; 762 763 if (!handle) 764 return; 765 tee_mm_free(handle->mm); 766 free(handle->tag); 767 free(handle); 768 } 769 770 REGISTER_TA_STORE(9) = { 771 .description = "REE [buffered]", 772 .open = buf_ta_open, 773 .get_size = buf_ta_get_size, 774 .get_tag = buf_ta_get_tag, 775 .read = buf_ta_read, 776 .close = buf_ta_close, 777 }; 778 779 #endif /* CFG_REE_FS_TA_BUFFERED */ 780