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
check_update_version(const char * db_name,const uint8_t uuid[sizeof (TEE_UUID)],uint32_t version)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 */
rpc_load(const TEE_UUID * uuid,struct shdr ** ta,size_t * ta_size,struct mobj ** mobj)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
ree_fs_ta_open(const TEE_UUID * uuid,struct ts_store_handle ** h)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
ree_fs_ta_get_size(const struct ts_store_handle * h,size_t * size)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
ree_fs_ta_get_tag(const struct ts_store_handle * h,uint8_t * tag,unsigned int * tag_len)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
check_digest(struct ree_fs_ta_handle * h)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
ree_fs_ta_read(struct ts_store_handle * h,void * data_core,void * data_user,size_t len)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
ree_fs_ta_close(struct ts_store_handle * h)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
buf_ta_open(const TEE_UUID * uuid,struct ts_store_handle ** h)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
buf_ta_get_size(const struct ts_store_handle * h,size_t * size)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
buf_ta_read(struct ts_store_handle * h,void * data_core,void * data_user,size_t len)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
buf_ta_get_tag(const struct ts_store_handle * h,uint8_t * tag,unsigned int * tag_len)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
buf_ta_close(struct ts_store_handle * h)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