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