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