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