xref: /optee_os/core/pta/system.c (revision 4522f807ca8292e3787cd7fa393f38f827c8914f)
15843bb75SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause
25843bb75SJerome Forissier /*
36105aa86SJens Wiklander  * Copyright (c) 2018-2022 Linaro Limited
46cb02818SJelle Sels  * Copyright (c) 2020, Arm Limited.
5e4ad5ccdSAleksandr Anisimov  * Copyright (c) 2020, Open Mobile Platform LLC
65843bb75SJerome Forissier  */
75843bb75SJerome Forissier 
85843bb75SJerome Forissier #include <assert.h>
95843bb75SJerome Forissier #include <crypto/crypto.h>
105843bb75SJerome Forissier #include <kernel/handle.h>
115843bb75SJerome Forissier #include <kernel/huk_subkey.h>
12cbe7e1b8SBalint Dobszay #include <kernel/ldelf_loader.h>
135843bb75SJerome Forissier #include <kernel/misc.h>
145843bb75SJerome Forissier #include <kernel/msg_param.h>
155843bb75SJerome Forissier #include <kernel/pseudo_ta.h>
16a8e39e9cSJens Wiklander #include <kernel/tpm.h>
176cb02818SJelle Sels #include <kernel/ts_store.h>
1852e7b1a6SJens Wiklander #include <kernel/user_access.h>
199c34c0c7SBalint Dobszay #include <kernel/user_mode_ctx.h>
205843bb75SJerome Forissier #include <ldelf.h>
215843bb75SJerome Forissier #include <mm/file.h>
225843bb75SJerome Forissier #include <mm/fobj.h>
2389c9728dSJens Wiklander #include <mm/vm.h>
245843bb75SJerome Forissier #include <pta_system.h>
25a8e39e9cSJens Wiklander #include <stdlib_ext.h>
26a8e39e9cSJens Wiklander #include <stdlib.h>
275843bb75SJerome Forissier #include <string.h>
285843bb75SJerome Forissier #include <tee_api_defines_extensions.h>
295843bb75SJerome Forissier #include <tee_api_defines.h>
30e4ad5ccdSAleksandr Anisimov #include <tee/tee_supp_plugin_rpc.h>
31e4ad5ccdSAleksandr Anisimov #include <tee/uuid.h>
325843bb75SJerome Forissier #include <util.h>
335843bb75SJerome Forissier 
345843bb75SJerome Forissier static unsigned int system_pnum;
355843bb75SJerome Forissier 
369c34c0c7SBalint Dobszay static TEE_Result system_rng_reseed(uint32_t param_types,
375843bb75SJerome Forissier 				    TEE_Param params[TEE_NUM_PARAMS])
385843bb75SJerome Forissier {
3900b3b9a2SJens Wiklander 	size_t entropy_sz = 0;
4000b3b9a2SJens Wiklander 	uint8_t *entropy_input = NULL;
41953707a4SSeonghyun Park 	void *seed_bbuf = NULL;
42953707a4SSeonghyun Park 	TEE_Result res = TEE_SUCCESS;
435843bb75SJerome Forissier 	uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
445843bb75SJerome Forissier 					  TEE_PARAM_TYPE_NONE,
455843bb75SJerome Forissier 					  TEE_PARAM_TYPE_NONE,
465843bb75SJerome Forissier 					  TEE_PARAM_TYPE_NONE);
475843bb75SJerome Forissier 
485843bb75SJerome Forissier 	if (exp_pt != param_types)
495843bb75SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
505843bb75SJerome Forissier 	entropy_input = params[0].memref.buffer;
515843bb75SJerome Forissier 	entropy_sz = params[0].memref.size;
525843bb75SJerome Forissier 
53c2020b9dSJens Wiklander 	if (!entropy_sz || !entropy_input)
545843bb75SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
555843bb75SJerome Forissier 
56953707a4SSeonghyun Park 	res = bb_memdup_user(entropy_input, entropy_sz, &seed_bbuf);
57953707a4SSeonghyun Park 	if (res)
58953707a4SSeonghyun Park 		return res;
59953707a4SSeonghyun Park 
605843bb75SJerome Forissier 	crypto_rng_add_event(CRYPTO_RNG_SRC_NONSECURE, &system_pnum,
61953707a4SSeonghyun Park 			     seed_bbuf, entropy_sz);
62953707a4SSeonghyun Park 
63953707a4SSeonghyun Park 	bb_free(seed_bbuf, entropy_sz);
64953707a4SSeonghyun Park 
655843bb75SJerome Forissier 	return TEE_SUCCESS;
665843bb75SJerome Forissier }
675843bb75SJerome Forissier 
689c34c0c7SBalint Dobszay static TEE_Result system_derive_ta_unique_key(struct user_mode_ctx *uctx,
695843bb75SJerome Forissier 					      uint32_t param_types,
705843bb75SJerome Forissier 					      TEE_Param params[TEE_NUM_PARAMS])
715843bb75SJerome Forissier {
725843bb75SJerome Forissier 	size_t data_len = sizeof(TEE_UUID);
735843bb75SJerome Forissier 	TEE_Result res = TEE_ERROR_GENERIC;
745843bb75SJerome Forissier 	uint8_t *data = NULL;
755843bb75SJerome Forissier 	uint32_t access_flags = 0;
76953707a4SSeonghyun Park 	void *subkey_bbuf = NULL;
775843bb75SJerome Forissier 	uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
785843bb75SJerome Forissier 					  TEE_PARAM_TYPE_MEMREF_OUTPUT,
795843bb75SJerome Forissier 					  TEE_PARAM_TYPE_NONE,
805843bb75SJerome Forissier 					  TEE_PARAM_TYPE_NONE);
815843bb75SJerome Forissier 
825843bb75SJerome Forissier 	if (exp_pt != param_types)
835843bb75SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
845843bb75SJerome Forissier 
855843bb75SJerome Forissier 	if (params[0].memref.size > TA_DERIVED_EXTRA_DATA_MAX_SIZE ||
865843bb75SJerome Forissier 	    params[1].memref.size < TA_DERIVED_KEY_MIN_SIZE ||
875843bb75SJerome Forissier 	    params[1].memref.size > TA_DERIVED_KEY_MAX_SIZE)
885843bb75SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
895843bb75SJerome Forissier 
905843bb75SJerome Forissier 	/*
915843bb75SJerome Forissier 	 * The derived key shall not end up in non-secure memory by
925843bb75SJerome Forissier 	 * mistake.
935843bb75SJerome Forissier 	 *
945843bb75SJerome Forissier 	 * Note that we're allowing shared memory as long as it's
955843bb75SJerome Forissier 	 * secure. This is needed because a TA always uses shared memory
965843bb75SJerome Forissier 	 * when communicating with another TA.
975843bb75SJerome Forissier 	 */
985843bb75SJerome Forissier 	access_flags = TEE_MEMORY_ACCESS_WRITE | TEE_MEMORY_ACCESS_ANY_OWNER |
995843bb75SJerome Forissier 		       TEE_MEMORY_ACCESS_SECURE;
1009c34c0c7SBalint Dobszay 	res = vm_check_access_rights(uctx, access_flags,
1015843bb75SJerome Forissier 				     (uaddr_t)params[1].memref.buffer,
1025843bb75SJerome Forissier 				     params[1].memref.size);
1035843bb75SJerome Forissier 	if (res != TEE_SUCCESS)
1045843bb75SJerome Forissier 		return TEE_ERROR_SECURITY;
1055843bb75SJerome Forissier 
1065843bb75SJerome Forissier 	/* Take extra data into account. */
1075843bb75SJerome Forissier 	if (ADD_OVERFLOW(data_len, params[0].memref.size, &data_len))
1085843bb75SJerome Forissier 		return TEE_ERROR_SECURITY;
1095843bb75SJerome Forissier 
110*4522f807SJens Wiklander 	data = bb_alloc(data_len);
1115843bb75SJerome Forissier 	if (!data)
1125843bb75SJerome Forissier 		return TEE_ERROR_OUT_OF_MEMORY;
1135843bb75SJerome Forissier 
1149c34c0c7SBalint Dobszay 	memcpy(data, &uctx->ts_ctx->uuid, sizeof(TEE_UUID));
1155843bb75SJerome Forissier 
1165843bb75SJerome Forissier 	/* Append the user provided data */
117953707a4SSeonghyun Park 	res = copy_from_user(data + sizeof(TEE_UUID), params[0].memref.buffer,
1185843bb75SJerome Forissier 			     params[0].memref.size);
119953707a4SSeonghyun Park 	if (res)
120953707a4SSeonghyun Park 		goto out;
121953707a4SSeonghyun Park 
122953707a4SSeonghyun Park 	subkey_bbuf = bb_alloc(params[1].memref.size);
123953707a4SSeonghyun Park 	if (!subkey_bbuf) {
124953707a4SSeonghyun Park 		res = TEE_ERROR_OUT_OF_MEMORY;
125953707a4SSeonghyun Park 		goto out;
126953707a4SSeonghyun Park 	}
1275843bb75SJerome Forissier 
1285843bb75SJerome Forissier 	res = huk_subkey_derive(HUK_SUBKEY_UNIQUE_TA, data, data_len,
129953707a4SSeonghyun Park 				subkey_bbuf, params[1].memref.size);
130953707a4SSeonghyun Park 	if (res)
131953707a4SSeonghyun Park 		goto out;
1325843bb75SJerome Forissier 
133953707a4SSeonghyun Park 	res = copy_to_user(params[1].memref.buffer, subkey_bbuf,
134953707a4SSeonghyun Park 			   params[1].memref.size);
135953707a4SSeonghyun Park 
136953707a4SSeonghyun Park out:
137*4522f807SJens Wiklander 	bb_free_wipe(subkey_bbuf, params[1].memref.size);
138*4522f807SJens Wiklander 	bb_free_wipe(data, data_len);
1395843bb75SJerome Forissier 	return res;
1405843bb75SJerome Forissier }
1415843bb75SJerome Forissier 
1429c34c0c7SBalint Dobszay static TEE_Result system_map_zi(struct user_mode_ctx *uctx,
1439c34c0c7SBalint Dobszay 				uint32_t param_types,
1445843bb75SJerome Forissier 				TEE_Param params[TEE_NUM_PARAMS])
1455843bb75SJerome Forissier {
1465843bb75SJerome Forissier 	uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
1475843bb75SJerome Forissier 					  TEE_PARAM_TYPE_VALUE_INOUT,
1485843bb75SJerome Forissier 					  TEE_PARAM_TYPE_VALUE_INPUT,
1495843bb75SJerome Forissier 					  TEE_PARAM_TYPE_NONE);
1505843bb75SJerome Forissier 	uint32_t prot = TEE_MATTR_URW | TEE_MATTR_PRW;
1515843bb75SJerome Forissier 	TEE_Result res = TEE_ERROR_GENERIC;
1525843bb75SJerome Forissier 	struct mobj *mobj = NULL;
1535843bb75SJerome Forissier 	uint32_t pad_begin = 0;
154b9651492SJens Wiklander 	uint32_t vm_flags = 0;
1555843bb75SJerome Forissier 	struct fobj *f = NULL;
1565843bb75SJerome Forissier 	uint32_t pad_end = 0;
1575843bb75SJerome Forissier 	size_t num_bytes = 0;
1585843bb75SJerome Forissier 	vaddr_t va = 0;
1595843bb75SJerome Forissier 
1605843bb75SJerome Forissier 	if (exp_pt != param_types)
1615843bb75SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
1625843bb75SJerome Forissier 	if (params[0].value.b & ~PTA_SYSTEM_MAP_FLAG_SHAREABLE)
1635843bb75SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
1645843bb75SJerome Forissier 
1655843bb75SJerome Forissier 	if (params[0].value.b & PTA_SYSTEM_MAP_FLAG_SHAREABLE)
1665843bb75SJerome Forissier 		vm_flags |= VM_FLAG_SHAREABLE;
1675843bb75SJerome Forissier 
1685843bb75SJerome Forissier 	num_bytes = params[0].value.a;
1695843bb75SJerome Forissier 	va = reg_pair_to_64(params[1].value.a, params[1].value.b);
1705843bb75SJerome Forissier 	pad_begin = params[2].value.a;
1715843bb75SJerome Forissier 	pad_end = params[2].value.b;
1725843bb75SJerome Forissier 
173787295dfSJens Wiklander 	f = fobj_ta_mem_alloc(ROUNDUP_DIV(num_bytes, SMALL_PAGE_SIZE));
1745843bb75SJerome Forissier 	if (!f)
1755843bb75SJerome Forissier 		return TEE_ERROR_OUT_OF_MEMORY;
1766105aa86SJens Wiklander 	mobj = mobj_with_fobj_alloc(f, NULL, TEE_MATTR_MEM_TYPE_TAGGED);
1775843bb75SJerome Forissier 	fobj_put(f);
1785843bb75SJerome Forissier 	if (!mobj)
1795843bb75SJerome Forissier 		return TEE_ERROR_OUT_OF_MEMORY;
1809c34c0c7SBalint Dobszay 	res = vm_map_pad(uctx, &va, num_bytes, prot, vm_flags,
181918e36c6SSughosh Ganu 			 mobj, 0, pad_begin, pad_end, 0);
182b9651492SJens Wiklander 	mobj_put(mobj);
183b9651492SJens Wiklander 	if (!res)
1845843bb75SJerome Forissier 		reg_pair_from_64(va, &params[1].value.a, &params[1].value.b);
1855843bb75SJerome Forissier 
1865843bb75SJerome Forissier 	return res;
1875843bb75SJerome Forissier }
1885843bb75SJerome Forissier 
1899c34c0c7SBalint Dobszay static TEE_Result system_unmap(struct user_mode_ctx *uctx, uint32_t param_types,
1905843bb75SJerome Forissier 			       TEE_Param params[TEE_NUM_PARAMS])
1915843bb75SJerome Forissier {
1925843bb75SJerome Forissier 	uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
1935843bb75SJerome Forissier 					  TEE_PARAM_TYPE_VALUE_INPUT,
1945843bb75SJerome Forissier 					  TEE_PARAM_TYPE_NONE,
1955843bb75SJerome Forissier 					  TEE_PARAM_TYPE_NONE);
19679f22013SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
19779f22013SJens Wiklander 	uint32_t vm_flags = 0;
198095b07ceSJens Wiklander 	vaddr_t end_va = 0;
19979f22013SJens Wiklander 	vaddr_t va = 0;
20079f22013SJens Wiklander 	size_t sz = 0;
2015843bb75SJerome Forissier 
2025843bb75SJerome Forissier 	if (exp_pt != param_types)
2035843bb75SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
2045843bb75SJerome Forissier 
2055843bb75SJerome Forissier 	if (params[0].value.b)
2065843bb75SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
2075843bb75SJerome Forissier 
20879f22013SJens Wiklander 	va = reg_pair_to_64(params[1].value.a, params[1].value.b);
20979f22013SJens Wiklander 	sz = ROUNDUP(params[0].value.a, SMALL_PAGE_SIZE);
21079f22013SJens Wiklander 
211095b07ceSJens Wiklander 	/*
212095b07ceSJens Wiklander 	 * The vm_get_flags() and vm_unmap() are supposed to detect or
213095b07ceSJens Wiklander 	 * handle overflow directly or indirectly. However, this function
214095b07ceSJens Wiklander 	 * an API function so an extra guard here is in order. If nothing
215095b07ceSJens Wiklander 	 * else to make it easier to review the code.
216095b07ceSJens Wiklander 	 */
217095b07ceSJens Wiklander 	if (ADD_OVERFLOW(va, sz, &end_va))
218095b07ceSJens Wiklander 		return TEE_ERROR_BAD_PARAMETERS;
219095b07ceSJens Wiklander 
2209c34c0c7SBalint Dobszay 	res = vm_get_flags(uctx, va, sz, &vm_flags);
22179f22013SJens Wiklander 	if (res)
22279f22013SJens Wiklander 		return res;
22379f22013SJens Wiklander 	if (vm_flags & VM_FLAG_PERMANENT)
22479f22013SJens Wiklander 		return TEE_ERROR_ACCESS_DENIED;
22579f22013SJens Wiklander 
2269c34c0c7SBalint Dobszay 	return vm_unmap(uctx, va, sz);
2275843bb75SJerome Forissier }
2285843bb75SJerome Forissier 
2299c34c0c7SBalint Dobszay static TEE_Result system_dlopen(struct user_mode_ctx *uctx,
2309c34c0c7SBalint Dobszay 				uint32_t param_types,
2315843bb75SJerome Forissier 				TEE_Param params[TEE_NUM_PARAMS])
2325843bb75SJerome Forissier {
2335843bb75SJerome Forissier 	uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
2345843bb75SJerome Forissier 					  TEE_PARAM_TYPE_VALUE_INPUT,
2355843bb75SJerome Forissier 					  TEE_PARAM_TYPE_NONE,
2365843bb75SJerome Forissier 					  TEE_PARAM_TYPE_NONE);
2375843bb75SJerome Forissier 	TEE_Result res = TEE_ERROR_GENERIC;
23800b3b9a2SJens Wiklander 	struct ts_session *s = NULL;
23952e7b1a6SJens Wiklander 	TEE_UUID uuid = { };
2405843bb75SJerome Forissier 	uint32_t flags = 0;
2415843bb75SJerome Forissier 
2425843bb75SJerome Forissier 	if (exp_pt != param_types)
2435843bb75SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
2445843bb75SJerome Forissier 
24552e7b1a6SJens Wiklander 	if (!params[0].memref.buffer || params[0].memref.size != sizeof(uuid))
2465843bb75SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
2475843bb75SJerome Forissier 
24852e7b1a6SJens Wiklander 	res = copy_from_user(&uuid, params[0].memref.buffer, sizeof(uuid));
24952e7b1a6SJens Wiklander 	if (res)
25052e7b1a6SJens Wiklander 		return res;
25152e7b1a6SJens Wiklander 
2525843bb75SJerome Forissier 	flags = params[1].value.a;
2535843bb75SJerome Forissier 
25400b3b9a2SJens Wiklander 	s = ts_pop_current_session();
25552e7b1a6SJens Wiklander 	res = ldelf_dlopen(uctx, &uuid, flags);
25600b3b9a2SJens Wiklander 	ts_push_current_session(s);
2575843bb75SJerome Forissier 
2585843bb75SJerome Forissier 	return res;
2595843bb75SJerome Forissier }
2605843bb75SJerome Forissier 
2619c34c0c7SBalint Dobszay static TEE_Result system_dlsym(struct user_mode_ctx *uctx, uint32_t param_types,
2625843bb75SJerome Forissier 			       TEE_Param params[TEE_NUM_PARAMS])
2635843bb75SJerome Forissier {
2645843bb75SJerome Forissier 	uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
2655843bb75SJerome Forissier 					  TEE_PARAM_TYPE_MEMREF_INPUT,
2665843bb75SJerome Forissier 					  TEE_PARAM_TYPE_VALUE_OUTPUT,
2675843bb75SJerome Forissier 					  TEE_PARAM_TYPE_NONE);
2685843bb75SJerome Forissier 	TEE_Result res = TEE_ERROR_GENERIC;
26900b3b9a2SJens Wiklander 	struct ts_session *s = NULL;
27052e7b1a6SJens Wiklander 	char *sym = NULL;
27152e7b1a6SJens Wiklander 	TEE_UUID uuid = { };
27252e7b1a6SJens Wiklander 	size_t symlen = 0;
2735843bb75SJerome Forissier 	vaddr_t va = 0;
2745843bb75SJerome Forissier 
2755843bb75SJerome Forissier 	if (exp_pt != param_types)
2765843bb75SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
2775843bb75SJerome Forissier 
27852e7b1a6SJens Wiklander 	if (!params[0].memref.buffer || params[0].memref.size != sizeof(uuid))
2795843bb75SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
2805843bb75SJerome Forissier 
28152e7b1a6SJens Wiklander 	res = copy_from_user(&uuid, params[0].memref.buffer, sizeof(uuid));
28252e7b1a6SJens Wiklander 	if (res)
28352e7b1a6SJens Wiklander 		return res;
28452e7b1a6SJens Wiklander 
28552e7b1a6SJens Wiklander 	if (!params[1].memref.buffer)
2865843bb75SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
28752e7b1a6SJens Wiklander 	res = bb_strndup_user(params[1].memref.buffer, params[1].memref.size,
28852e7b1a6SJens Wiklander 			      &sym, &symlen);
28952e7b1a6SJens Wiklander 	if (res)
29052e7b1a6SJens Wiklander 		return res;
2915843bb75SJerome Forissier 
29200b3b9a2SJens Wiklander 	s = ts_pop_current_session();
29352e7b1a6SJens Wiklander 	res = ldelf_dlsym(uctx, &uuid, sym, symlen, &va);
29400b3b9a2SJens Wiklander 	ts_push_current_session(s);
2955843bb75SJerome Forissier 
2965843bb75SJerome Forissier 	if (!res)
2975843bb75SJerome Forissier 		reg_pair_from_64(va, &params[2].value.a, &params[2].value.b);
2985843bb75SJerome Forissier 
2995843bb75SJerome Forissier 	return res;
3005843bb75SJerome Forissier }
3015843bb75SJerome Forissier 
302dd333f03SJavier Almansa Sobrino static TEE_Result system_get_tpm_event_log(uint32_t param_types,
303dd333f03SJavier Almansa Sobrino 					   TEE_Param params[TEE_NUM_PARAMS])
304dd333f03SJavier Almansa Sobrino {
305dd333f03SJavier Almansa Sobrino 	uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT,
306dd333f03SJavier Almansa Sobrino 					  TEE_PARAM_TYPE_NONE,
307dd333f03SJavier Almansa Sobrino 					  TEE_PARAM_TYPE_NONE,
308dd333f03SJavier Almansa Sobrino 					  TEE_PARAM_TYPE_NONE);
309dd333f03SJavier Almansa Sobrino 	size_t size = 0;
310dd333f03SJavier Almansa Sobrino 	TEE_Result res = TEE_SUCCESS;
311dd333f03SJavier Almansa Sobrino 
312dd333f03SJavier Almansa Sobrino 	if (exp_pt != param_types)
313dd333f03SJavier Almansa Sobrino 		return TEE_ERROR_BAD_PARAMETERS;
314dd333f03SJavier Almansa Sobrino 
315dd333f03SJavier Almansa Sobrino 	size = params[0].memref.size;
316dd333f03SJavier Almansa Sobrino 	res = tpm_get_event_log(params[0].memref.buffer, &size);
317dd333f03SJavier Almansa Sobrino 	params[0].memref.size = size;
318dd333f03SJavier Almansa Sobrino 
319dd333f03SJavier Almansa Sobrino 	return res;
320dd333f03SJavier Almansa Sobrino }
321dd333f03SJavier Almansa Sobrino 
322e4ad5ccdSAleksandr Anisimov static TEE_Result system_supp_plugin_invoke(uint32_t param_types,
323e4ad5ccdSAleksandr Anisimov 					    TEE_Param params[TEE_NUM_PARAMS])
324e4ad5ccdSAleksandr Anisimov {
325e4ad5ccdSAleksandr Anisimov 	uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
326e4ad5ccdSAleksandr Anisimov 					  TEE_PARAM_TYPE_VALUE_INPUT,
327e4ad5ccdSAleksandr Anisimov 					  TEE_PARAM_TYPE_MEMREF_INOUT,
328e4ad5ccdSAleksandr Anisimov 					  TEE_PARAM_TYPE_VALUE_OUTPUT);
329e4ad5ccdSAleksandr Anisimov 	TEE_Result res = TEE_ERROR_GENERIC;
330e4ad5ccdSAleksandr Anisimov 	size_t outlen = 0;
331953707a4SSeonghyun Park 	TEE_UUID uuid = { };
332e4ad5ccdSAleksandr Anisimov 
333e4ad5ccdSAleksandr Anisimov 	if (exp_pt != param_types)
334e4ad5ccdSAleksandr Anisimov 		return TEE_ERROR_BAD_PARAMETERS;
335e4ad5ccdSAleksandr Anisimov 
336953707a4SSeonghyun Park 	if (!params[0].memref.buffer || params[0].memref.size != sizeof(uuid))
337953707a4SSeonghyun Park 		return TEE_ERROR_BAD_PARAMETERS;
338953707a4SSeonghyun Park 
339953707a4SSeonghyun Park 	res = copy_from_user(&uuid, params[0].memref.buffer, sizeof(uuid));
340953707a4SSeonghyun Park 	if (res)
341953707a4SSeonghyun Park 		return res;
342953707a4SSeonghyun Park 
343953707a4SSeonghyun Park 	res = tee_invoke_supp_plugin_rpc(&uuid,
344e4ad5ccdSAleksandr Anisimov 					 params[1].value.a, /* cmd */
345e4ad5ccdSAleksandr Anisimov 					 params[1].value.b, /* sub_cmd */
346eb4a988aSJens Wiklander 					 NULL,
347e4ad5ccdSAleksandr Anisimov 					 params[2].memref.buffer, /* data */
348e4ad5ccdSAleksandr Anisimov 					 params[2].memref.size, /* in len */
349e4ad5ccdSAleksandr Anisimov 					 &outlen);
350e4ad5ccdSAleksandr Anisimov 	params[3].value.a = (uint32_t)outlen;
351e4ad5ccdSAleksandr Anisimov 
352e4ad5ccdSAleksandr Anisimov 	return res;
353e4ad5ccdSAleksandr Anisimov }
354e4ad5ccdSAleksandr Anisimov 
3555843bb75SJerome Forissier static TEE_Result open_session(uint32_t param_types __unused,
3565843bb75SJerome Forissier 			       TEE_Param params[TEE_NUM_PARAMS] __unused,
357baa5161dSBalint Dobszay 			       void **sess_ctx __unused)
3585843bb75SJerome Forissier {
35900b3b9a2SJens Wiklander 	struct ts_session *s = NULL;
3605843bb75SJerome Forissier 
3615843bb75SJerome Forissier 	/* Check that we're called from a user TA */
36200b3b9a2SJens Wiklander 	s = ts_get_calling_session();
3635843bb75SJerome Forissier 	if (!s)
3645843bb75SJerome Forissier 		return TEE_ERROR_ACCESS_DENIED;
3655843bb75SJerome Forissier 	if (!is_user_ta_ctx(s->ctx))
3665843bb75SJerome Forissier 		return TEE_ERROR_ACCESS_DENIED;
3675843bb75SJerome Forissier 
3685843bb75SJerome Forissier 	return TEE_SUCCESS;
3695843bb75SJerome Forissier }
3705843bb75SJerome Forissier 
371baa5161dSBalint Dobszay static TEE_Result invoke_command(void *sess_ctx __unused, uint32_t cmd_id,
3725843bb75SJerome Forissier 				 uint32_t param_types,
3735843bb75SJerome Forissier 				 TEE_Param params[TEE_NUM_PARAMS])
3745843bb75SJerome Forissier {
37500b3b9a2SJens Wiklander 	struct ts_session *s = ts_get_calling_session();
3769c34c0c7SBalint Dobszay 	struct user_mode_ctx *uctx = to_user_mode_ctx(s->ctx);
3775843bb75SJerome Forissier 
3785843bb75SJerome Forissier 	switch (cmd_id) {
3795843bb75SJerome Forissier 	case PTA_SYSTEM_ADD_RNG_ENTROPY:
3809c34c0c7SBalint Dobszay 		return system_rng_reseed(param_types, params);
3815843bb75SJerome Forissier 	case PTA_SYSTEM_DERIVE_TA_UNIQUE_KEY:
3829c34c0c7SBalint Dobszay 		return system_derive_ta_unique_key(uctx, param_types, params);
3835843bb75SJerome Forissier 	case PTA_SYSTEM_MAP_ZI:
3849c34c0c7SBalint Dobszay 		return system_map_zi(uctx, param_types, params);
3855843bb75SJerome Forissier 	case PTA_SYSTEM_UNMAP:
3869c34c0c7SBalint Dobszay 		return system_unmap(uctx, param_types, params);
3875843bb75SJerome Forissier 	case PTA_SYSTEM_DLOPEN:
3889c34c0c7SBalint Dobszay 		return system_dlopen(uctx, param_types, params);
3895843bb75SJerome Forissier 	case PTA_SYSTEM_DLSYM:
3909c34c0c7SBalint Dobszay 		return system_dlsym(uctx, param_types, params);
391dd333f03SJavier Almansa Sobrino 	case PTA_SYSTEM_GET_TPM_EVENT_LOG:
392dd333f03SJavier Almansa Sobrino 		return system_get_tpm_event_log(param_types, params);
393e4ad5ccdSAleksandr Anisimov 	case PTA_SYSTEM_SUPP_PLUGIN_INVOKE:
394e4ad5ccdSAleksandr Anisimov 		return system_supp_plugin_invoke(param_types, params);
3955843bb75SJerome Forissier 	default:
3965843bb75SJerome Forissier 		break;
3975843bb75SJerome Forissier 	}
3985843bb75SJerome Forissier 
3995843bb75SJerome Forissier 	return TEE_ERROR_NOT_IMPLEMENTED;
4005843bb75SJerome Forissier }
4015843bb75SJerome Forissier 
4025843bb75SJerome Forissier pseudo_ta_register(.uuid = PTA_SYSTEM_UUID, .name = "system.pta",
4035843bb75SJerome Forissier 		   .flags = PTA_DEFAULT_FLAGS | TA_FLAG_CONCURRENT,
4045843bb75SJerome Forissier 		   .open_session_entry_point = open_session,
4055843bb75SJerome Forissier 		   .invoke_command_entry_point = invoke_command);
406