xref: /optee_os/core/kernel/ree_fs_ta.c (revision c82196572938147434632e7d187f31de186bfa20)
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 *)&params[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 *)&params[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 
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 	res = shdr_verify_signature(shdr);
269 	if (res != TEE_SUCCESS)
270 		goto error_free_payload;
271 
272 	shdr_sz = SHDR_GET_SIZE(shdr);
273 	if (!shdr_sz) {
274 		res = TEE_ERROR_SECURITY;
275 		goto error_free_payload;
276 	}
277 	offs = shdr_sz;
278 
279 	while (shdr->img_type == SHDR_SUBKEY) {
280 		struct shdr_pub_key pub_key = { };
281 
282 		if (offs > ta_size) {
283 			res = TEE_ERROR_SECURITY;
284 			goto error_free_payload;
285 		}
286 
287 		res = shdr_load_pub_key(shdr, offs, (const void *)ta,
288 					ta_size, next_uuid_ptr, max_depth,
289 					&pub_key);
290 		if (res)
291 			goto error_free_payload;
292 
293 		if (ADD_OVERFLOW(offs, shdr->img_size, &offs) ||
294 		    ADD_OVERFLOW(offs, pub_key.name_size, &offs) ||
295 		    offs > ta_size) {
296 			res = TEE_ERROR_SECURITY;
297 			goto error_free_payload;
298 		}
299 		max_depth = pub_key.max_depth;
300 		memcpy(next_uuid, pub_key.next_uuid, sizeof(TEE_UUID));
301 		next_uuid_ptr = next_uuid;
302 
303 		res = check_update_version(subkey_ver_db, pub_key.uuid,
304 					   pub_key.version);
305 		if (res) {
306 			res = TEE_ERROR_SECURITY;
307 			shdr_free_pub_key(&pub_key);
308 			goto error_free_payload;
309 		}
310 
311 		shdr_free(shdr);
312 		shdr = shdr_alloc_and_copy(offs, ta, ta_size);
313 		res = TEE_ERROR_SECURITY;
314 		if (shdr)
315 			res = shdr_verify_signature2(&pub_key, shdr);
316 		shdr_free_pub_key(&pub_key);
317 		if (res)
318 			goto error_free_payload;
319 
320 		shdr_sz = SHDR_GET_SIZE(shdr);
321 		if (!shdr_sz) {
322 			res = TEE_ERROR_SECURITY;
323 			goto error_free_payload;
324 		}
325 		offs += shdr_sz;
326 		if (offs > ta_size) {
327 			res = TEE_ERROR_SECURITY;
328 			goto error_free_payload;
329 		}
330 	}
331 
332 	if (shdr->img_type != SHDR_TA && shdr->img_type != SHDR_BOOTSTRAP_TA &&
333 	    shdr->img_type != SHDR_ENCRYPTED_TA) {
334 		res = TEE_ERROR_SECURITY;
335 		goto error_free_payload;
336 	}
337 
338 	/*
339 	 * If we're verifying this TA using a subkey, make sure that
340 	 * the UUID of the TA belongs to the namespace defined by the subkey.
341 	 * The namespace is defined as in RFC4122, that is, valid UUID
342 	 * is calculated as a V5 UUID SHA-512(subkey UUID, "name string").
343 	 */
344 	if (next_uuid_ptr) {
345 		TEE_UUID check_uuid = { };
346 
347 		tee_uuid_from_octets(&check_uuid, next_uuid_ptr);
348 		if (memcmp(&check_uuid, uuid, sizeof(*uuid))) {
349 			res = TEE_ERROR_SECURITY;
350 			goto error_free_payload;
351 		}
352 	}
353 
354 	/*
355 	 * Initialize a hash context and run the algorithm over the signed
356 	 * header (less the final file hash and its signature of course)
357 	 */
358 	res = crypto_hash_alloc_ctx(&hash_ctx,
359 				    TEE_DIGEST_HASH_TO_ALGO(shdr->algo));
360 	if (res != TEE_SUCCESS)
361 		goto error_free_payload;
362 	res = crypto_hash_init(hash_ctx);
363 	if (res != TEE_SUCCESS)
364 		goto error_free_hash;
365 	res = crypto_hash_update(hash_ctx, (uint8_t *)shdr, sizeof(*shdr));
366 	if (res != TEE_SUCCESS)
367 		goto error_free_hash;
368 
369 	if (shdr->img_type == SHDR_BOOTSTRAP_TA ||
370 	    shdr->img_type == SHDR_ENCRYPTED_TA) {
371 		TEE_UUID bs_uuid = { };
372 		size_t sz = shdr_sz;
373 
374 		if (ADD_OVERFLOW(sz, sizeof(*bs_hdr), &sz) || ta_size < sz) {
375 			res = TEE_ERROR_SECURITY;
376 			goto error_free_hash;
377 		}
378 
379 		bs_hdr = malloc(sizeof(*bs_hdr));
380 		if (!bs_hdr) {
381 			res = TEE_ERROR_OUT_OF_MEMORY;
382 			goto error_free_hash;
383 		}
384 
385 		memcpy(bs_hdr, (uint8_t *)ta + offs, sizeof(*bs_hdr));
386 
387 		/*
388 		 * There's a check later that the UUID embedded inside the
389 		 * ELF is matching, but since we now have easy access to
390 		 * the expected uuid of the TA we check it a bit earlier
391 		 * here.
392 		 */
393 		tee_uuid_from_octets(&bs_uuid, bs_hdr->uuid);
394 		if (memcmp(&bs_uuid, uuid, sizeof(TEE_UUID))) {
395 			res = TEE_ERROR_SECURITY;
396 			goto error_free_hash;
397 		}
398 
399 		res = crypto_hash_update(hash_ctx, (uint8_t *)bs_hdr,
400 					 sizeof(*bs_hdr));
401 		if (res != TEE_SUCCESS)
402 			goto error_free_hash;
403 		offs += sizeof(*bs_hdr);
404 		handle->bs_hdr = bs_hdr;
405 	}
406 
407 	if (shdr->img_type == SHDR_ENCRYPTED_TA) {
408 		struct shdr_encrypted_ta img_ehdr = { };
409 		size_t sz = shdr_sz;
410 		size_t ehdr_sz = 0;
411 
412 		if (ADD_OVERFLOW(sz, sizeof(struct shdr_bootstrap_ta), &sz) ||
413 		    ADD_OVERFLOW(sz, sizeof(img_ehdr), &sz) ||
414 		    ta_size < sz) {
415 			res = TEE_ERROR_SECURITY;
416 			goto error_free_hash;
417 		}
418 
419 		memcpy(&img_ehdr, ((uint8_t *)ta + offs), sizeof(img_ehdr));
420 		ehdr_sz = SHDR_ENC_GET_SIZE(&img_ehdr);
421 		sz -= sizeof(img_ehdr);
422 		if (!ehdr_sz || ADD_OVERFLOW(sz, ehdr_sz, &sz) ||
423 		    ta_size < sz) {
424 			res = TEE_ERROR_SECURITY;
425 			goto error_free_hash;
426 		}
427 
428 		/*
429 		 * This is checked further down too, but we must sanity
430 		 * check shdr->img_size before it's used below.
431 		 */
432 		if (ta_size != sz + shdr->img_size) {
433 			res = TEE_ERROR_SECURITY;
434 			goto error_free_hash;
435 		}
436 
437 		ehdr = malloc(ehdr_sz);
438 		if (!ehdr) {
439 			res = TEE_ERROR_OUT_OF_MEMORY;
440 			goto error_free_hash;
441 		}
442 
443 		*ehdr = img_ehdr;
444 		memcpy((uint8_t *)ehdr + sizeof(img_ehdr),
445 		       (uint8_t *)ta + offs + sizeof(img_ehdr),
446 		       ehdr_sz - sizeof(img_ehdr));
447 
448 		res = crypto_hash_update(hash_ctx, (uint8_t *)ehdr, ehdr_sz);
449 		if (res != TEE_SUCCESS)
450 			goto error_free_hash;
451 
452 		res = tee_ta_decrypt_init(&handle->enc_ctx, ehdr,
453 					  shdr->img_size);
454 		if (res != TEE_SUCCESS)
455 			goto error_free_hash;
456 
457 		offs += ehdr_sz;
458 		handle->ehdr = ehdr;
459 	}
460 
461 	if (ta_size != offs + shdr->img_size) {
462 		res = TEE_ERROR_SECURITY;
463 		goto error_free_hash;
464 	}
465 
466 	handle->nw_ta = ta;
467 	handle->nw_ta_size = ta_size;
468 	handle->offs = offs;
469 	handle->hash_ctx = hash_ctx;
470 	handle->shdr = shdr;
471 	handle->mobj = mobj;
472 	*h = (struct ts_store_handle *)handle;
473 	return TEE_SUCCESS;
474 
475 error_free_hash:
476 	crypto_hash_free_ctx(hash_ctx);
477 error_free_payload:
478 	thread_rpc_free_payload(mobj);
479 error:
480 	free(ehdr);
481 	free(bs_hdr);
482 	shdr_free(shdr);
483 	free(handle);
484 	return res;
485 }
486 
487 static TEE_Result ree_fs_ta_get_size(const struct ts_store_handle *h,
488 				     size_t *size)
489 {
490 	struct ree_fs_ta_handle *handle = (struct ree_fs_ta_handle *)h;
491 
492 	*size = handle->shdr->img_size;
493 	return TEE_SUCCESS;
494 }
495 
496 static TEE_Result ree_fs_ta_get_tag(const struct ts_store_handle *h,
497 				    uint8_t *tag, unsigned int *tag_len)
498 {
499 	struct ree_fs_ta_handle *handle = (struct ree_fs_ta_handle *)h;
500 
501 	if (!tag || *tag_len < handle->shdr->hash_size) {
502 		*tag_len = handle->shdr->hash_size;
503 		return TEE_ERROR_SHORT_BUFFER;
504 	}
505 	*tag_len = handle->shdr->hash_size;
506 
507 	memcpy(tag, SHDR_GET_HASH(handle->shdr), handle->shdr->hash_size);
508 
509 	return TEE_SUCCESS;
510 }
511 
512 static TEE_Result check_digest(struct ree_fs_ta_handle *h)
513 {
514 	void *digest = NULL;
515 	TEE_Result res;
516 
517 	digest = malloc(h->shdr->hash_size);
518 	if (!digest)
519 		return TEE_ERROR_OUT_OF_MEMORY;
520 	res = crypto_hash_final(h->hash_ctx, digest, h->shdr->hash_size);
521 	if (res != TEE_SUCCESS) {
522 		res = TEE_ERROR_SECURITY;
523 		goto out;
524 	}
525 	if (FTMN_CALLEE_DONE_MEMCMP(memcmp, digest, SHDR_GET_HASH(h->shdr),
526 				    h->shdr->hash_size))
527 		res = TEE_ERROR_SECURITY;
528 out:
529 	free(digest);
530 	return res;
531 }
532 
533 static TEE_Result ree_fs_ta_read(struct ts_store_handle *h, void *data,
534 				 size_t len)
535 {
536 	struct ree_fs_ta_handle *handle = (struct ree_fs_ta_handle *)h;
537 
538 	uint8_t *src = (uint8_t *)handle->nw_ta + handle->offs;
539 	size_t next_offs = 0;
540 	uint8_t *dst = src;
541 	TEE_Result res = TEE_SUCCESS;
542 
543 	if (ADD_OVERFLOW(handle->offs, len, &next_offs) ||
544 	    next_offs > handle->nw_ta_size)
545 		return TEE_ERROR_BAD_PARAMETERS;
546 
547 	if (handle->shdr->img_type == SHDR_ENCRYPTED_TA) {
548 		if (data) {
549 			dst = data; /* Hash secure buffer */
550 			res = tee_ta_decrypt_update(handle->enc_ctx, dst, src,
551 						    len);
552 			if (res != TEE_SUCCESS)
553 				return TEE_ERROR_SECURITY;
554 		} else {
555 			size_t num_bytes = 0;
556 			size_t b_size = MIN(1024U, len);
557 			uint8_t *b = malloc(b_size);
558 
559 			if (!b)
560 				return TEE_ERROR_OUT_OF_MEMORY;
561 
562 			dst = NULL;
563 			while (num_bytes < len) {
564 				size_t n = MIN(b_size, len - num_bytes);
565 
566 				res = tee_ta_decrypt_update(handle->enc_ctx, b,
567 							    src + num_bytes, n);
568 				if (res)
569 					break;
570 				num_bytes += n;
571 
572 				res = crypto_hash_update(handle->hash_ctx, b,
573 							 n);
574 				if (res)
575 					break;
576 			}
577 
578 			free(b);
579 			if (res != TEE_SUCCESS)
580 				return TEE_ERROR_SECURITY;
581 		}
582 	} else if (data) {
583 		dst = data; /* Hash secure buffer (shm might be modified) */
584 		memcpy(dst, src, len);
585 	}
586 
587 	if (dst) {
588 		res = crypto_hash_update(handle->hash_ctx, dst, len);
589 		if (res != TEE_SUCCESS)
590 			return TEE_ERROR_SECURITY;
591 	}
592 
593 	handle->offs = next_offs;
594 	if (handle->offs == handle->nw_ta_size) {
595 		if (handle->shdr->img_type == SHDR_ENCRYPTED_TA) {
596 			/*
597 			 * Last read: time to finalize authenticated
598 			 * decryption.
599 			 */
600 			res = tee_ta_decrypt_final(handle->enc_ctx,
601 						   handle->ehdr, NULL, NULL, 0);
602 			if (res != TEE_SUCCESS)
603 				return TEE_ERROR_SECURITY;
604 		}
605 		/*
606 		 * Last read: time to check if our digest matches the expected
607 		 * one (from the signed header)
608 		 */
609 		res = check_digest(handle);
610 		if (res != TEE_SUCCESS)
611 			return res;
612 
613 		if (handle->bs_hdr)
614 			res = check_update_version(ta_ver_db,
615 						   handle->bs_hdr->uuid,
616 						   handle->bs_hdr->ta_version);
617 	}
618 	return res;
619 }
620 
621 static void ree_fs_ta_close(struct ts_store_handle *h)
622 {
623 	struct ree_fs_ta_handle *handle = (struct ree_fs_ta_handle *)h;
624 
625 	if (!handle)
626 		return;
627 	thread_rpc_free_payload(handle->mobj);
628 	crypto_hash_free_ctx(handle->hash_ctx);
629 	free(handle->shdr);
630 	free(handle->ehdr);
631 	free(handle->bs_hdr);
632 	free(handle);
633 }
634 
635 #ifndef CFG_REE_FS_TA_BUFFERED
636 REGISTER_TA_STORE(9) = {
637 	.description = "REE",
638 	.open = ree_fs_ta_open,
639 	.get_size = ree_fs_ta_get_size,
640 	.get_tag = ree_fs_ta_get_tag,
641 	.read = ree_fs_ta_read,
642 	.close = ree_fs_ta_close,
643 };
644 #endif
645 
646 #ifdef CFG_REE_FS_TA_BUFFERED
647 
648 /*
649  * This is a wrapper around the "REE FS" TA store.
650  * The whole TA/library is read into a temporary buffer during .open(). This
651  * allows the binary to be authenticated before any data is read and processed
652  * by the upper layer (ELF loader).
653  */
654 
655 struct buf_ree_fs_ta_handle {
656 	struct ts_store_handle *h; /* Note: a REE FS TA store handle */
657 	size_t ta_size;
658 	tee_mm_entry_t *mm;
659 	uint8_t *buf;
660 	size_t offs;
661 	uint8_t *tag;
662 	unsigned int tag_len;
663 };
664 
665 static TEE_Result buf_ta_open(const TEE_UUID *uuid,
666 			      struct ts_store_handle **h)
667 {
668 	struct buf_ree_fs_ta_handle *handle = NULL;
669 	struct ftmn ftmn = { };
670 	TEE_Result res = TEE_SUCCESS;
671 
672 	handle = calloc(1, sizeof(*handle));
673 	if (!handle)
674 		return TEE_ERROR_OUT_OF_MEMORY;
675 	FTMN_PUSH_LINKED_CALL(&ftmn, FTMN_FUNC_HASH("shdr_verify_signature"));
676 	res = ree_fs_ta_open(uuid, &handle->h);
677 	if (!res)
678 		FTMN_SET_CHECK_RES_FROM_CALL(&ftmn, FTMN_INCR0, res);
679 	FTMN_POP_LINKED_CALL(&ftmn);
680 	if (res)
681 		goto err_free_handle;
682 	ftmn_checkpoint(&ftmn, FTMN_INCR1);
683 
684 	res = ree_fs_ta_get_size(handle->h, &handle->ta_size);
685 	if (res)
686 		goto err;
687 
688 	res = ree_fs_ta_get_tag(handle->h, NULL, &handle->tag_len);
689 	if (res != TEE_ERROR_SHORT_BUFFER) {
690 		res = TEE_ERROR_GENERIC;
691 		goto err;
692 	}
693 	handle->tag = malloc(handle->tag_len);
694 	if (!handle->tag) {
695 		res = TEE_ERROR_OUT_OF_MEMORY;
696 		goto err;
697 	}
698 	res = ree_fs_ta_get_tag(handle->h, handle->tag, &handle->tag_len);
699 	if (res)
700 		goto err;
701 
702 	handle->mm = tee_mm_alloc(&tee_mm_sec_ddr, handle->ta_size);
703 	if (!handle->mm) {
704 		res = TEE_ERROR_OUT_OF_MEMORY;
705 		goto err;
706 	}
707 	handle->buf = phys_to_virt(tee_mm_get_smem(handle->mm),
708 				   MEM_AREA_TA_RAM, handle->ta_size);
709 	if (!handle->buf) {
710 		res = TEE_ERROR_OUT_OF_MEMORY;
711 		goto err;
712 	}
713 
714 	FTMN_PUSH_LINKED_CALL(&ftmn, FTMN_FUNC_HASH("check_digest"));
715 	res = ree_fs_ta_read(handle->h, handle->buf, handle->ta_size);
716 	if (!res)
717 		FTMN_SET_CHECK_RES_FROM_CALL(&ftmn, FTMN_INCR0, res);
718 	FTMN_POP_LINKED_CALL(&ftmn);
719 	if (res)
720 		goto err;
721 	ftmn_checkpoint(&ftmn, FTMN_INCR1);
722 
723 	*h = (struct ts_store_handle *)handle;
724 	ree_fs_ta_close(handle->h);
725 	return ftmn_return_res(&ftmn, FTMN_STEP_COUNT(2, 2), TEE_SUCCESS);
726 
727 err:
728 	ree_fs_ta_close(handle->h);
729 	tee_mm_free(handle->mm);
730 	free(handle->tag);
731 err_free_handle:
732 	free(handle);
733 	return res;
734 }
735 
736 static TEE_Result buf_ta_get_size(const struct ts_store_handle *h,
737 				  size_t *size)
738 {
739 	struct buf_ree_fs_ta_handle *handle = (struct buf_ree_fs_ta_handle *)h;
740 
741 	*size = handle->ta_size;
742 	return TEE_SUCCESS;
743 }
744 
745 static TEE_Result buf_ta_read(struct ts_store_handle *h, void *data,
746 			      size_t len)
747 {
748 	struct buf_ree_fs_ta_handle *handle = (struct buf_ree_fs_ta_handle *)h;
749 	uint8_t *src = handle->buf + handle->offs;
750 	size_t next_offs = 0;
751 
752 	if (ADD_OVERFLOW(handle->offs, len, &next_offs) ||
753 	    next_offs > handle->ta_size)
754 		return TEE_ERROR_BAD_PARAMETERS;
755 
756 	if (data)
757 		memcpy(data, src, len);
758 	handle->offs = next_offs;
759 	return TEE_SUCCESS;
760 }
761 
762 static TEE_Result buf_ta_get_tag(const struct ts_store_handle *h,
763 				 uint8_t *tag, unsigned int *tag_len)
764 {
765 	struct buf_ree_fs_ta_handle *handle = (struct buf_ree_fs_ta_handle *)h;
766 
767 	*tag_len = handle->tag_len;
768 	if (!tag || *tag_len < handle->tag_len)
769 		return TEE_ERROR_SHORT_BUFFER;
770 
771 	memcpy(tag, handle->tag, handle->tag_len);
772 
773 	return TEE_SUCCESS;
774 }
775 
776 static void buf_ta_close(struct ts_store_handle *h)
777 {
778 	struct buf_ree_fs_ta_handle *handle = (struct buf_ree_fs_ta_handle *)h;
779 
780 	if (!handle)
781 		return;
782 	tee_mm_free(handle->mm);
783 	free(handle->tag);
784 	free(handle);
785 }
786 
787 REGISTER_TA_STORE(9) = {
788 	.description = "REE [buffered]",
789 	.open = buf_ta_open,
790 	.get_size = buf_ta_get_size,
791 	.get_tag = buf_ta_get_tag,
792 	.read = buf_ta_read,
793 	.close = buf_ta_close,
794 };
795 
796 #endif /* CFG_REE_FS_TA_BUFFERED */
797