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