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