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