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