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