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