xref: /optee_os/core/pta/system.c (revision 6630b8462328a51356c59129ef1489634e0af861)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2018-2019, Linaro Limited
4  * Copyright (c) 2020, Arm Limited.
5  */
6 
7 #include <assert.h>
8 #include <crypto/crypto.h>
9 #include <kernel/handle.h>
10 #include <kernel/huk_subkey.h>
11 #include <kernel/ldelf_loader.h>
12 #include <kernel/misc.h>
13 #include <kernel/msg_param.h>
14 #include <kernel/pseudo_ta.h>
15 #include <kernel/tpm.h>
16 #include <kernel/ts_store.h>
17 #include <kernel/user_mode_ctx.h>
18 #include <ldelf.h>
19 #include <mm/file.h>
20 #include <mm/fobj.h>
21 #include <mm/vm.h>
22 #include <pta_system.h>
23 #include <stdlib_ext.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <tee_api_defines_extensions.h>
27 #include <tee_api_defines.h>
28 #include <util.h>
29 
30 static unsigned int system_pnum;
31 
32 static TEE_Result system_rng_reseed(uint32_t param_types,
33 				    TEE_Param params[TEE_NUM_PARAMS])
34 {
35 	size_t entropy_sz = 0;
36 	uint8_t *entropy_input = NULL;
37 	uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
38 					  TEE_PARAM_TYPE_NONE,
39 					  TEE_PARAM_TYPE_NONE,
40 					  TEE_PARAM_TYPE_NONE);
41 
42 	if (exp_pt != param_types)
43 		return TEE_ERROR_BAD_PARAMETERS;
44 	entropy_input = params[0].memref.buffer;
45 	entropy_sz = params[0].memref.size;
46 
47 	if (!entropy_sz || !entropy_input)
48 		return TEE_ERROR_BAD_PARAMETERS;
49 
50 	crypto_rng_add_event(CRYPTO_RNG_SRC_NONSECURE, &system_pnum,
51 			     entropy_input, entropy_sz);
52 	return TEE_SUCCESS;
53 }
54 
55 static TEE_Result system_derive_ta_unique_key(struct user_mode_ctx *uctx,
56 					      uint32_t param_types,
57 					      TEE_Param params[TEE_NUM_PARAMS])
58 {
59 	size_t data_len = sizeof(TEE_UUID);
60 	TEE_Result res = TEE_ERROR_GENERIC;
61 	uint8_t *data = NULL;
62 	uint32_t access_flags = 0;
63 	uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
64 					  TEE_PARAM_TYPE_MEMREF_OUTPUT,
65 					  TEE_PARAM_TYPE_NONE,
66 					  TEE_PARAM_TYPE_NONE);
67 
68 	if (exp_pt != param_types)
69 		return TEE_ERROR_BAD_PARAMETERS;
70 
71 	if (params[0].memref.size > TA_DERIVED_EXTRA_DATA_MAX_SIZE ||
72 	    params[1].memref.size < TA_DERIVED_KEY_MIN_SIZE ||
73 	    params[1].memref.size > TA_DERIVED_KEY_MAX_SIZE)
74 		return TEE_ERROR_BAD_PARAMETERS;
75 
76 	/*
77 	 * The derived key shall not end up in non-secure memory by
78 	 * mistake.
79 	 *
80 	 * Note that we're allowing shared memory as long as it's
81 	 * secure. This is needed because a TA always uses shared memory
82 	 * when communicating with another TA.
83 	 */
84 	access_flags = TEE_MEMORY_ACCESS_WRITE | TEE_MEMORY_ACCESS_ANY_OWNER |
85 		       TEE_MEMORY_ACCESS_SECURE;
86 	res = vm_check_access_rights(uctx, access_flags,
87 				     (uaddr_t)params[1].memref.buffer,
88 				     params[1].memref.size);
89 	if (res != TEE_SUCCESS)
90 		return TEE_ERROR_SECURITY;
91 
92 	/* Take extra data into account. */
93 	if (ADD_OVERFLOW(data_len, params[0].memref.size, &data_len))
94 		return TEE_ERROR_SECURITY;
95 
96 	data = calloc(data_len, 1);
97 	if (!data)
98 		return TEE_ERROR_OUT_OF_MEMORY;
99 
100 	memcpy(data, &uctx->ts_ctx->uuid, sizeof(TEE_UUID));
101 
102 	/* Append the user provided data */
103 	memcpy(data + sizeof(TEE_UUID), params[0].memref.buffer,
104 	       params[0].memref.size);
105 
106 	res = huk_subkey_derive(HUK_SUBKEY_UNIQUE_TA, data, data_len,
107 				params[1].memref.buffer,
108 				params[1].memref.size);
109 	free_wipe(data);
110 
111 	return res;
112 }
113 
114 static TEE_Result system_map_zi(struct user_mode_ctx *uctx,
115 				uint32_t param_types,
116 				TEE_Param params[TEE_NUM_PARAMS])
117 {
118 	uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
119 					  TEE_PARAM_TYPE_VALUE_INOUT,
120 					  TEE_PARAM_TYPE_VALUE_INPUT,
121 					  TEE_PARAM_TYPE_NONE);
122 	uint32_t prot = TEE_MATTR_URW | TEE_MATTR_PRW;
123 	TEE_Result res = TEE_ERROR_GENERIC;
124 	struct mobj *mobj = NULL;
125 	uint32_t pad_begin = 0;
126 	uint32_t vm_flags = 0;
127 	struct fobj *f = NULL;
128 	uint32_t pad_end = 0;
129 	size_t num_bytes = 0;
130 	vaddr_t va = 0;
131 
132 	if (exp_pt != param_types)
133 		return TEE_ERROR_BAD_PARAMETERS;
134 	if (params[0].value.b & ~PTA_SYSTEM_MAP_FLAG_SHAREABLE)
135 		return TEE_ERROR_BAD_PARAMETERS;
136 
137 	if (params[0].value.b & PTA_SYSTEM_MAP_FLAG_SHAREABLE)
138 		vm_flags |= VM_FLAG_SHAREABLE;
139 
140 	num_bytes = params[0].value.a;
141 	va = reg_pair_to_64(params[1].value.a, params[1].value.b);
142 	pad_begin = params[2].value.a;
143 	pad_end = params[2].value.b;
144 
145 	f = fobj_ta_mem_alloc(ROUNDUP_DIV(num_bytes, SMALL_PAGE_SIZE));
146 	if (!f)
147 		return TEE_ERROR_OUT_OF_MEMORY;
148 	mobj = mobj_with_fobj_alloc(f, NULL);
149 	fobj_put(f);
150 	if (!mobj)
151 		return TEE_ERROR_OUT_OF_MEMORY;
152 	res = vm_map_pad(uctx, &va, num_bytes, prot, vm_flags,
153 			 mobj, 0, pad_begin, pad_end, 0);
154 	mobj_put(mobj);
155 	if (!res)
156 		reg_pair_from_64(va, &params[1].value.a, &params[1].value.b);
157 
158 	return res;
159 }
160 
161 static TEE_Result system_unmap(struct user_mode_ctx *uctx, uint32_t param_types,
162 			       TEE_Param params[TEE_NUM_PARAMS])
163 {
164 	uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
165 					  TEE_PARAM_TYPE_VALUE_INPUT,
166 					  TEE_PARAM_TYPE_NONE,
167 					  TEE_PARAM_TYPE_NONE);
168 	TEE_Result res = TEE_SUCCESS;
169 	uint32_t vm_flags = 0;
170 	vaddr_t end_va = 0;
171 	vaddr_t va = 0;
172 	size_t sz = 0;
173 
174 	if (exp_pt != param_types)
175 		return TEE_ERROR_BAD_PARAMETERS;
176 
177 	if (params[0].value.b)
178 		return TEE_ERROR_BAD_PARAMETERS;
179 
180 	va = reg_pair_to_64(params[1].value.a, params[1].value.b);
181 	sz = ROUNDUP(params[0].value.a, SMALL_PAGE_SIZE);
182 
183 	/*
184 	 * The vm_get_flags() and vm_unmap() are supposed to detect or
185 	 * handle overflow directly or indirectly. However, this function
186 	 * an API function so an extra guard here is in order. If nothing
187 	 * else to make it easier to review the code.
188 	 */
189 	if (ADD_OVERFLOW(va, sz, &end_va))
190 		return TEE_ERROR_BAD_PARAMETERS;
191 
192 	res = vm_get_flags(uctx, va, sz, &vm_flags);
193 	if (res)
194 		return res;
195 	if (vm_flags & VM_FLAG_PERMANENT)
196 		return TEE_ERROR_ACCESS_DENIED;
197 
198 	return vm_unmap(uctx, va, sz);
199 }
200 
201 static TEE_Result system_dlopen(struct user_mode_ctx *uctx,
202 				uint32_t param_types,
203 				TEE_Param params[TEE_NUM_PARAMS])
204 {
205 	uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
206 					  TEE_PARAM_TYPE_VALUE_INPUT,
207 					  TEE_PARAM_TYPE_NONE,
208 					  TEE_PARAM_TYPE_NONE);
209 	TEE_Result res = TEE_ERROR_GENERIC;
210 	struct ts_session *s = NULL;
211 	TEE_UUID *uuid = NULL;
212 	uint32_t flags = 0;
213 
214 	if (exp_pt != param_types)
215 		return TEE_ERROR_BAD_PARAMETERS;
216 
217 	uuid = params[0].memref.buffer;
218 	if (!uuid || params[0].memref.size != sizeof(*uuid))
219 		return TEE_ERROR_BAD_PARAMETERS;
220 
221 	flags = params[1].value.a;
222 
223 	s = ts_pop_current_session();
224 	res = ldelf_dlopen(uctx, uuid, flags);
225 	ts_push_current_session(s);
226 
227 	return res;
228 }
229 
230 static TEE_Result system_dlsym(struct user_mode_ctx *uctx, uint32_t param_types,
231 			       TEE_Param params[TEE_NUM_PARAMS])
232 {
233 	uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
234 					  TEE_PARAM_TYPE_MEMREF_INPUT,
235 					  TEE_PARAM_TYPE_VALUE_OUTPUT,
236 					  TEE_PARAM_TYPE_NONE);
237 	TEE_Result res = TEE_ERROR_GENERIC;
238 	struct ts_session *s = NULL;
239 	const char *sym = NULL;
240 	TEE_UUID *uuid = NULL;
241 	size_t maxlen = 0;
242 	vaddr_t va = 0;
243 
244 	if (exp_pt != param_types)
245 		return TEE_ERROR_BAD_PARAMETERS;
246 
247 	uuid = params[0].memref.buffer;
248 	if (uuid && params[0].memref.size != sizeof(*uuid))
249 		return TEE_ERROR_BAD_PARAMETERS;
250 
251 	sym = params[1].memref.buffer;
252 	if (!sym)
253 		return TEE_ERROR_BAD_PARAMETERS;
254 	maxlen = params[1].memref.size;
255 
256 	s = ts_pop_current_session();
257 	res = ldelf_dlsym(uctx, uuid, sym, maxlen, &va);
258 	ts_push_current_session(s);
259 
260 	if (!res)
261 		reg_pair_from_64(va, &params[2].value.a, &params[2].value.b);
262 
263 	return res;
264 }
265 
266 static TEE_Result system_get_tpm_event_log(uint32_t param_types,
267 					   TEE_Param params[TEE_NUM_PARAMS])
268 {
269 	uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT,
270 					  TEE_PARAM_TYPE_NONE,
271 					  TEE_PARAM_TYPE_NONE,
272 					  TEE_PARAM_TYPE_NONE);
273 	size_t size = 0;
274 	TEE_Result res = TEE_SUCCESS;
275 
276 	if (exp_pt != param_types)
277 		return TEE_ERROR_BAD_PARAMETERS;
278 
279 	size = params[0].memref.size;
280 	res = tpm_get_event_log(params[0].memref.buffer, &size);
281 	params[0].memref.size = size;
282 
283 	return res;
284 }
285 
286 static TEE_Result open_session(uint32_t param_types __unused,
287 			       TEE_Param params[TEE_NUM_PARAMS] __unused,
288 			       void **sess_ctx __unused)
289 {
290 	struct ts_session *s = NULL;
291 
292 	/* Check that we're called from a user TA */
293 	s = ts_get_calling_session();
294 	if (!s)
295 		return TEE_ERROR_ACCESS_DENIED;
296 	if (!is_user_ta_ctx(s->ctx))
297 		return TEE_ERROR_ACCESS_DENIED;
298 
299 	return TEE_SUCCESS;
300 }
301 
302 static TEE_Result invoke_command(void *sess_ctx __unused, uint32_t cmd_id,
303 				 uint32_t param_types,
304 				 TEE_Param params[TEE_NUM_PARAMS])
305 {
306 	struct ts_session *s = ts_get_calling_session();
307 	struct user_mode_ctx *uctx = to_user_mode_ctx(s->ctx);
308 
309 	switch (cmd_id) {
310 	case PTA_SYSTEM_ADD_RNG_ENTROPY:
311 		return system_rng_reseed(param_types, params);
312 	case PTA_SYSTEM_DERIVE_TA_UNIQUE_KEY:
313 		return system_derive_ta_unique_key(uctx, param_types, params);
314 	case PTA_SYSTEM_MAP_ZI:
315 		return system_map_zi(uctx, param_types, params);
316 	case PTA_SYSTEM_UNMAP:
317 		return system_unmap(uctx, param_types, params);
318 	case PTA_SYSTEM_DLOPEN:
319 		return system_dlopen(uctx, param_types, params);
320 	case PTA_SYSTEM_DLSYM:
321 		return system_dlsym(uctx, param_types, params);
322 	case PTA_SYSTEM_GET_TPM_EVENT_LOG:
323 		return system_get_tpm_event_log(param_types, params);
324 	default:
325 		break;
326 	}
327 
328 	return TEE_ERROR_NOT_IMPLEMENTED;
329 }
330 
331 pseudo_ta_register(.uuid = PTA_SYSTEM_UUID, .name = "system.pta",
332 		   .flags = PTA_DEFAULT_FLAGS | TA_FLAG_CONCURRENT,
333 		   .open_session_entry_point = open_session,
334 		   .invoke_command_entry_point = invoke_command);
335