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