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