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