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