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