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 if (!num_bytes)
164 return TEE_ERROR_BAD_PARAMETERS;
165
166 va = reg_pair_to_64(params[1].value.a, params[1].value.b);
167 pad_begin = params[2].value.a;
168 pad_end = params[2].value.b;
169
170 f = fobj_ta_mem_alloc(ROUNDUP_DIV(num_bytes, SMALL_PAGE_SIZE));
171 if (!f)
172 return TEE_ERROR_OUT_OF_MEMORY;
173 mobj = mobj_with_fobj_alloc(f, NULL, TEE_MATTR_MEM_TYPE_TAGGED);
174 fobj_put(f);
175 if (!mobj)
176 return TEE_ERROR_OUT_OF_MEMORY;
177 res = vm_map_pad(uctx, &va, num_bytes, prot, vm_flags,
178 mobj, 0, pad_begin, pad_end, 0);
179 mobj_put(mobj);
180 if (!res)
181 reg_pair_from_64(va, ¶ms[1].value.a, ¶ms[1].value.b);
182
183 return res;
184 }
185
system_unmap(struct user_mode_ctx * uctx,uint32_t param_types,TEE_Param params[TEE_NUM_PARAMS])186 static TEE_Result system_unmap(struct user_mode_ctx *uctx, uint32_t param_types,
187 TEE_Param params[TEE_NUM_PARAMS])
188 {
189 uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
190 TEE_PARAM_TYPE_VALUE_INPUT,
191 TEE_PARAM_TYPE_NONE,
192 TEE_PARAM_TYPE_NONE);
193 TEE_Result res = TEE_SUCCESS;
194 uint32_t vm_flags = 0;
195 vaddr_t end_va = 0;
196 vaddr_t va = 0;
197 size_t sz = 0;
198
199 if (exp_pt != param_types)
200 return TEE_ERROR_BAD_PARAMETERS;
201
202 if (params[0].value.b)
203 return TEE_ERROR_BAD_PARAMETERS;
204
205 va = reg_pair_to_64(params[1].value.a, params[1].value.b);
206 sz = ROUNDUP(params[0].value.a, SMALL_PAGE_SIZE);
207
208 /*
209 * The vm_get_flags() and vm_unmap() are supposed to detect or
210 * handle overflow directly or indirectly. However, this function
211 * an API function so an extra guard here is in order. If nothing
212 * else to make it easier to review the code.
213 */
214 if (ADD_OVERFLOW(va, sz, &end_va))
215 return TEE_ERROR_BAD_PARAMETERS;
216
217 res = vm_get_flags(uctx, va, sz, &vm_flags);
218 if (res)
219 return res;
220 if (vm_flags & VM_FLAG_PERMANENT)
221 return TEE_ERROR_ACCESS_DENIED;
222
223 return vm_unmap(uctx, va, sz);
224 }
225
system_dlopen(struct user_mode_ctx * uctx,uint32_t param_types,TEE_Param params[TEE_NUM_PARAMS])226 static TEE_Result system_dlopen(struct user_mode_ctx *uctx,
227 uint32_t param_types,
228 TEE_Param params[TEE_NUM_PARAMS])
229 {
230 uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
231 TEE_PARAM_TYPE_VALUE_INPUT,
232 TEE_PARAM_TYPE_NONE,
233 TEE_PARAM_TYPE_NONE);
234 TEE_Result res = TEE_ERROR_GENERIC;
235 struct ts_session *s = NULL;
236 TEE_UUID uuid = { };
237 uint32_t flags = 0;
238
239 if (exp_pt != param_types)
240 return TEE_ERROR_BAD_PARAMETERS;
241
242 if (!params[0].memref.buffer || params[0].memref.size != sizeof(uuid))
243 return TEE_ERROR_BAD_PARAMETERS;
244
245 res = copy_from_user(&uuid, params[0].memref.buffer, sizeof(uuid));
246 if (res)
247 return res;
248
249 flags = params[1].value.a;
250
251 s = ts_pop_current_session();
252 res = ldelf_dlopen(uctx, &uuid, flags);
253 ts_push_current_session(s);
254
255 return res;
256 }
257
system_dlsym(struct user_mode_ctx * uctx,uint32_t param_types,TEE_Param params[TEE_NUM_PARAMS])258 static TEE_Result system_dlsym(struct user_mode_ctx *uctx, uint32_t param_types,
259 TEE_Param params[TEE_NUM_PARAMS])
260 {
261 uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
262 TEE_PARAM_TYPE_MEMREF_INPUT,
263 TEE_PARAM_TYPE_VALUE_OUTPUT,
264 TEE_PARAM_TYPE_NONE);
265 TEE_Result res = TEE_ERROR_GENERIC;
266 struct ts_session *s = NULL;
267 char *sym = NULL;
268 TEE_UUID uuid = { };
269 size_t symlen = 0;
270 vaddr_t va = 0;
271
272 if (exp_pt != param_types)
273 return TEE_ERROR_BAD_PARAMETERS;
274
275 if (!params[0].memref.buffer || params[0].memref.size != sizeof(uuid))
276 return TEE_ERROR_BAD_PARAMETERS;
277
278 res = copy_from_user(&uuid, params[0].memref.buffer, sizeof(uuid));
279 if (res)
280 return res;
281
282 if (!params[1].memref.buffer)
283 return TEE_ERROR_BAD_PARAMETERS;
284 res = bb_strndup_user(params[1].memref.buffer, params[1].memref.size,
285 &sym, &symlen);
286 if (res)
287 return res;
288
289 s = ts_pop_current_session();
290 res = ldelf_dlsym(uctx, &uuid, sym, symlen, &va);
291 ts_push_current_session(s);
292
293 if (!res)
294 reg_pair_from_64(va, ¶ms[2].value.a, ¶ms[2].value.b);
295
296 return res;
297 }
298
system_get_tpm_event_log(uint32_t param_types,TEE_Param params[TEE_NUM_PARAMS])299 static TEE_Result system_get_tpm_event_log(uint32_t param_types,
300 TEE_Param params[TEE_NUM_PARAMS])
301 {
302 uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT,
303 TEE_PARAM_TYPE_NONE,
304 TEE_PARAM_TYPE_NONE,
305 TEE_PARAM_TYPE_NONE);
306 size_t size = 0;
307 TEE_Result res = TEE_SUCCESS;
308
309 if (exp_pt != param_types)
310 return TEE_ERROR_BAD_PARAMETERS;
311
312 size = params[0].memref.size;
313 res = tpm_get_event_log(params[0].memref.buffer, &size);
314 params[0].memref.size = size;
315
316 return res;
317 }
318
system_supp_plugin_invoke(uint32_t param_types,TEE_Param params[TEE_NUM_PARAMS])319 static TEE_Result system_supp_plugin_invoke(uint32_t param_types,
320 TEE_Param params[TEE_NUM_PARAMS])
321 {
322 uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
323 TEE_PARAM_TYPE_VALUE_INPUT,
324 TEE_PARAM_TYPE_MEMREF_INOUT,
325 TEE_PARAM_TYPE_VALUE_OUTPUT);
326 TEE_Result res = TEE_ERROR_GENERIC;
327 size_t outlen = 0;
328 TEE_UUID uuid = { };
329
330 if (exp_pt != param_types)
331 return TEE_ERROR_BAD_PARAMETERS;
332
333 if (!params[0].memref.buffer || params[0].memref.size != sizeof(uuid))
334 return TEE_ERROR_BAD_PARAMETERS;
335
336 res = copy_from_user(&uuid, params[0].memref.buffer, sizeof(uuid));
337 if (res)
338 return res;
339
340 res = tee_invoke_supp_plugin_rpc(&uuid,
341 params[1].value.a, /* cmd */
342 params[1].value.b, /* sub_cmd */
343 NULL,
344 params[2].memref.buffer, /* data */
345 params[2].memref.size, /* in len */
346 &outlen);
347 params[3].value.a = (uint32_t)outlen;
348
349 return res;
350 }
351
open_session(uint32_t param_types __unused,TEE_Param params[TEE_NUM_PARAMS]__unused,void ** sess_ctx __unused)352 static TEE_Result open_session(uint32_t param_types __unused,
353 TEE_Param params[TEE_NUM_PARAMS] __unused,
354 void **sess_ctx __unused)
355 {
356 struct ts_session *s = NULL;
357
358 /* Check that we're called from a user TA */
359 s = ts_get_calling_session();
360 if (!s)
361 return TEE_ERROR_ACCESS_DENIED;
362 if (!is_user_ta_ctx(s->ctx))
363 return TEE_ERROR_ACCESS_DENIED;
364
365 return TEE_SUCCESS;
366 }
367
invoke_command(void * sess_ctx __unused,uint32_t cmd_id,uint32_t param_types,TEE_Param params[TEE_NUM_PARAMS])368 static TEE_Result invoke_command(void *sess_ctx __unused, uint32_t cmd_id,
369 uint32_t param_types,
370 TEE_Param params[TEE_NUM_PARAMS])
371 {
372 struct ts_session *s = ts_get_calling_session();
373 struct user_mode_ctx *uctx = to_user_mode_ctx(s->ctx);
374
375 switch (cmd_id) {
376 case PTA_SYSTEM_ADD_RNG_ENTROPY:
377 return system_rng_reseed(param_types, params);
378 case PTA_SYSTEM_DERIVE_TA_UNIQUE_KEY:
379 return system_derive_ta_unique_key(uctx, param_types, params);
380 case PTA_SYSTEM_MAP_ZI:
381 return system_map_zi(uctx, param_types, params);
382 case PTA_SYSTEM_UNMAP:
383 return system_unmap(uctx, param_types, params);
384 case PTA_SYSTEM_DLOPEN:
385 return system_dlopen(uctx, param_types, params);
386 case PTA_SYSTEM_DLSYM:
387 return system_dlsym(uctx, param_types, params);
388 case PTA_SYSTEM_GET_TPM_EVENT_LOG:
389 return system_get_tpm_event_log(param_types, params);
390 case PTA_SYSTEM_SUPP_PLUGIN_INVOKE:
391 return system_supp_plugin_invoke(param_types, params);
392 default:
393 break;
394 }
395
396 return TEE_ERROR_NOT_IMPLEMENTED;
397 }
398
399 pseudo_ta_register(.uuid = PTA_SYSTEM_UUID, .name = "system.pta",
400 .flags = PTA_DEFAULT_FLAGS | TA_FLAG_CONCURRENT,
401 .open_session_entry_point = open_session,
402 .invoke_command_entry_point = invoke_command);
403