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