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