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