1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Copyright (C) 2018 Linaro Limited
4 */
5 #include <common.h>
6 #include <dm.h>
7 #include <sandboxtee.h>
8 #include <tee.h>
9 #include <tee/optee_ta_avb.h>
10
11 /*
12 * The sandbox tee driver tries to emulate a generic Trusted Exectution
13 * Environment (TEE) with the Trusted Application (TA) OPTEE_TA_AVB
14 * available.
15 */
16
17 static const u32 pstorage_max = 16;
18 /**
19 * struct ta_entry - TA entries
20 * @uuid: UUID of an emulated TA
21 * @open_session Called when a session is openened to the TA
22 * @invoke_func Called when a function in the TA is to be invoked
23 *
24 * This struct is used to register TAs in this sandbox emulation of a TEE.
25 */
26 struct ta_entry {
27 struct tee_optee_ta_uuid uuid;
28 u32 (*open_session)(struct udevice *dev, uint num_params,
29 struct tee_param *params);
30 u32 (*invoke_func)(struct udevice *dev,
31 u32 func, uint num_params,
32 struct tee_param *params);
33 };
34
35 #ifdef CONFIG_OPTEE_TA_AVB
get_attr(uint n,uint num_params,struct tee_param * params)36 static u32 get_attr(uint n, uint num_params, struct tee_param *params)
37 {
38 if (n >= num_params)
39 return TEE_PARAM_ATTR_TYPE_NONE;
40
41 return params[n].attr;
42 }
43
check_params(u8 p0,u8 p1,u8 p2,u8 p3,uint num_params,struct tee_param * params)44 static u32 check_params(u8 p0, u8 p1, u8 p2, u8 p3, uint num_params,
45 struct tee_param *params)
46 {
47 u8 p[] = { p0, p1, p2, p3};
48 uint n;
49
50 for (n = 0; n < ARRAY_SIZE(p); n++)
51 if (p[n] != get_attr(n, num_params, params))
52 goto bad_params;
53
54 for (; n < num_params; n++)
55 if (get_attr(n, num_params, params))
56 goto bad_params;
57
58 return TEE_SUCCESS;
59
60 bad_params:
61 printf("Bad param attrs\n");
62
63 return TEE_ERROR_BAD_PARAMETERS;
64 }
65
ta_avb_open_session(struct udevice * dev,uint num_params,struct tee_param * params)66 static u32 ta_avb_open_session(struct udevice *dev, uint num_params,
67 struct tee_param *params)
68 {
69 /*
70 * We don't expect additional parameters when opening a session to
71 * this TA.
72 */
73 return check_params(TEE_PARAM_ATTR_TYPE_NONE, TEE_PARAM_ATTR_TYPE_NONE,
74 TEE_PARAM_ATTR_TYPE_NONE, TEE_PARAM_ATTR_TYPE_NONE,
75 num_params, params);
76 }
77
ta_avb_invoke_func(struct udevice * dev,u32 func,uint num_params,struct tee_param * params)78 static u32 ta_avb_invoke_func(struct udevice *dev, u32 func, uint num_params,
79 struct tee_param *params)
80 {
81 struct sandbox_tee_state *state = dev_get_priv(dev);
82 struct env_entry e, *ep;
83 char *name;
84 u32 res;
85 uint slot;
86 u64 val;
87 char *value;
88 u32 value_sz;
89
90 switch (func) {
91 case TA_AVB_CMD_READ_ROLLBACK_INDEX:
92 res = check_params(TEE_PARAM_ATTR_TYPE_VALUE_INPUT,
93 TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT,
94 TEE_PARAM_ATTR_TYPE_NONE,
95 TEE_PARAM_ATTR_TYPE_NONE,
96 num_params, params);
97 if (res)
98 return res;
99
100 slot = params[0].u.value.a;
101 if (slot >= ARRAY_SIZE(state->ta_avb_rollback_indexes)) {
102 printf("Rollback index slot out of bounds %u\n", slot);
103 return TEE_ERROR_BAD_PARAMETERS;
104 }
105
106 val = state->ta_avb_rollback_indexes[slot];
107 params[1].u.value.a = val >> 32;
108 params[1].u.value.b = val;
109 return TEE_SUCCESS;
110
111 case TA_AVB_CMD_WRITE_ROLLBACK_INDEX:
112 res = check_params(TEE_PARAM_ATTR_TYPE_VALUE_INPUT,
113 TEE_PARAM_ATTR_TYPE_VALUE_INPUT,
114 TEE_PARAM_ATTR_TYPE_NONE,
115 TEE_PARAM_ATTR_TYPE_NONE,
116 num_params, params);
117 if (res)
118 return res;
119
120 slot = params[0].u.value.a;
121 if (slot >= ARRAY_SIZE(state->ta_avb_rollback_indexes)) {
122 printf("Rollback index slot out of bounds %u\n", slot);
123 return TEE_ERROR_BAD_PARAMETERS;
124 }
125
126 val = (u64)params[1].u.value.a << 32 | params[1].u.value.b;
127 if (val < state->ta_avb_rollback_indexes[slot])
128 return TEE_ERROR_SECURITY;
129
130 state->ta_avb_rollback_indexes[slot] = val;
131 return TEE_SUCCESS;
132
133 case TA_AVB_CMD_READ_LOCK_STATE:
134 res = check_params(TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT,
135 TEE_PARAM_ATTR_TYPE_NONE,
136 TEE_PARAM_ATTR_TYPE_NONE,
137 TEE_PARAM_ATTR_TYPE_NONE,
138 num_params, params);
139 if (res)
140 return res;
141
142 params[0].u.value.a = state->ta_avb_lock_state;
143 return TEE_SUCCESS;
144
145 case TA_AVB_CMD_WRITE_LOCK_STATE:
146 res = check_params(TEE_PARAM_ATTR_TYPE_VALUE_INPUT,
147 TEE_PARAM_ATTR_TYPE_NONE,
148 TEE_PARAM_ATTR_TYPE_NONE,
149 TEE_PARAM_ATTR_TYPE_NONE,
150 num_params, params);
151 if (res)
152 return res;
153
154 if (state->ta_avb_lock_state != params[0].u.value.a) {
155 state->ta_avb_lock_state = params[0].u.value.a;
156 memset(state->ta_avb_rollback_indexes, 0,
157 sizeof(state->ta_avb_rollback_indexes));
158 }
159
160 return TEE_SUCCESS;
161 case TA_AVB_CMD_READ_PERSIST_VALUE:
162 res = check_params(TEE_PARAM_ATTR_TYPE_MEMREF_INPUT,
163 TEE_PARAM_ATTR_TYPE_MEMREF_INOUT,
164 TEE_PARAM_ATTR_TYPE_NONE,
165 TEE_PARAM_ATTR_TYPE_NONE,
166 num_params, params);
167 if (res)
168 return res;
169
170 name = params[0].u.memref.shm->addr;
171
172 value = params[1].u.memref.shm->addr;
173 value_sz = params[1].u.memref.size;
174
175 e.key = name;
176 e.data = NULL;
177 hsearch_r(e, ENV_FIND, &ep, &state->pstorage_htab, 0);
178 if (!ep)
179 return TEE_ERROR_ITEM_NOT_FOUND;
180
181 value_sz = strlen(ep->data) + 1;
182 memcpy(value, ep->data, value_sz);
183
184 return TEE_SUCCESS;
185 case TA_AVB_CMD_WRITE_PERSIST_VALUE:
186 res = check_params(TEE_PARAM_ATTR_TYPE_MEMREF_INPUT,
187 TEE_PARAM_ATTR_TYPE_MEMREF_INPUT,
188 TEE_PARAM_ATTR_TYPE_NONE,
189 TEE_PARAM_ATTR_TYPE_NONE,
190 num_params, params);
191 if (res)
192 return res;
193
194 name = params[0].u.memref.shm->addr;
195
196 value = params[1].u.memref.shm->addr;
197 value_sz = params[1].u.memref.size;
198
199 e.key = name;
200 e.data = NULL;
201 hsearch_r(e, ENV_FIND, &ep, &state->pstorage_htab, 0);
202 if (ep)
203 hdelete_r(e.key, &state->pstorage_htab, 0);
204
205 e.key = name;
206 e.data = value;
207 hsearch_r(e, ENV_ENTER, &ep, &state->pstorage_htab, 0);
208 if (!ep)
209 return TEE_ERROR_OUT_OF_MEMORY;
210
211 return TEE_SUCCESS;
212
213 default:
214 return TEE_ERROR_NOT_SUPPORTED;
215 }
216 }
217 #endif /*OPTEE_TA_AVB*/
218
219 static const struct ta_entry ta_entries[] = {
220 #ifdef CONFIG_OPTEE_TA_AVB
221 { .uuid = TA_AVB_UUID,
222 .open_session = ta_avb_open_session,
223 .invoke_func = ta_avb_invoke_func,
224 },
225 #endif
226 };
227
sandbox_tee_get_version(struct udevice * dev,struct tee_version_data * vers)228 static void sandbox_tee_get_version(struct udevice *dev,
229 struct tee_version_data *vers)
230 {
231 struct tee_version_data v = {
232 .gen_caps = TEE_GEN_CAP_GP | TEE_GEN_CAP_REG_MEM,
233 };
234
235 *vers = v;
236 }
237
sandbox_tee_close_session(struct udevice * dev,u32 session)238 static int sandbox_tee_close_session(struct udevice *dev, u32 session)
239 {
240 struct sandbox_tee_state *state = dev_get_priv(dev);
241
242 if (!state->ta || state->session != session)
243 return -EINVAL;
244
245 state->session = 0;
246 state->ta = NULL;
247
248 return 0;
249 }
250
find_ta_entry(u8 uuid[TEE_UUID_LEN])251 static const struct ta_entry *find_ta_entry(u8 uuid[TEE_UUID_LEN])
252 {
253 struct tee_optee_ta_uuid u;
254 uint n;
255
256 tee_optee_ta_uuid_from_octets(&u, uuid);
257
258 for (n = 0; n < ARRAY_SIZE(ta_entries); n++)
259 if (!memcmp(&u, &ta_entries[n].uuid, sizeof(u)))
260 return ta_entries + n;
261
262 return NULL;
263 }
264
sandbox_tee_open_session(struct udevice * dev,struct tee_open_session_arg * arg,uint num_params,struct tee_param * params)265 static int sandbox_tee_open_session(struct udevice *dev,
266 struct tee_open_session_arg *arg,
267 uint num_params, struct tee_param *params)
268 {
269 struct sandbox_tee_state *state = dev_get_priv(dev);
270 const struct ta_entry *ta;
271
272 if (state->ta) {
273 printf("A session is already open\n");
274 return -EBUSY;
275 }
276
277 ta = find_ta_entry(arg->uuid);
278 if (!ta) {
279 printf("Cannot find TA\n");
280 arg->ret = TEE_ERROR_ITEM_NOT_FOUND;
281 arg->ret_origin = TEE_ORIGIN_TEE;
282
283 return 0;
284 }
285
286 arg->ret = ta->open_session(dev, num_params, params);
287 arg->ret_origin = TEE_ORIGIN_TRUSTED_APP;
288
289 if (!arg->ret) {
290 state->ta = (void *)ta;
291 state->session = 1;
292 arg->session = state->session;
293 } else {
294 printf("Cannot open session, TA returns error\n");
295 }
296
297 return 0;
298 }
299
sandbox_tee_invoke_func(struct udevice * dev,struct tee_invoke_arg * arg,uint num_params,struct tee_param * params)300 static int sandbox_tee_invoke_func(struct udevice *dev,
301 struct tee_invoke_arg *arg,
302 uint num_params, struct tee_param *params)
303 {
304 struct sandbox_tee_state *state = dev_get_priv(dev);
305 struct ta_entry *ta = state->ta;
306
307 if (!arg->session) {
308 printf("Missing session\n");
309 return -EINVAL;
310 }
311
312 if (!ta) {
313 printf("TA session not available\n");
314 return -EINVAL;
315 }
316
317 if (arg->session != state->session) {
318 printf("Session mismatch\n");
319 return -EINVAL;
320 }
321
322 arg->ret = ta->invoke_func(dev, arg->func, num_params, params);
323 arg->ret_origin = TEE_ORIGIN_TRUSTED_APP;
324
325 return 0;
326 }
327
sandbox_tee_shm_register(struct udevice * dev,struct tee_shm * shm)328 static int sandbox_tee_shm_register(struct udevice *dev, struct tee_shm *shm)
329 {
330 struct sandbox_tee_state *state = dev_get_priv(dev);
331
332 state->num_shms++;
333
334 return 0;
335 }
336
sandbox_tee_shm_unregister(struct udevice * dev,struct tee_shm * shm)337 static int sandbox_tee_shm_unregister(struct udevice *dev, struct tee_shm *shm)
338 {
339 struct sandbox_tee_state *state = dev_get_priv(dev);
340
341 state->num_shms--;
342
343 return 0;
344 }
345
sandbox_tee_remove(struct udevice * dev)346 static int sandbox_tee_remove(struct udevice *dev)
347 {
348 struct sandbox_tee_state *state = dev_get_priv(dev);
349
350 hdestroy_r(&state->pstorage_htab);
351
352 return 0;
353 }
354
sandbox_tee_probe(struct udevice * dev)355 static int sandbox_tee_probe(struct udevice *dev)
356 {
357 struct sandbox_tee_state *state = dev_get_priv(dev);
358 /*
359 * With this hastable we emulate persistent storage,
360 * which should contain persistent values
361 * between different sessions/command invocations.
362 */
363 if (!hcreate_r(pstorage_max, &state->pstorage_htab))
364 return TEE_ERROR_OUT_OF_MEMORY;
365
366 return 0;
367 }
368
369 static const struct tee_driver_ops sandbox_tee_ops = {
370 .get_version = sandbox_tee_get_version,
371 .open_session = sandbox_tee_open_session,
372 .close_session = sandbox_tee_close_session,
373 .invoke_func = sandbox_tee_invoke_func,
374 .shm_register = sandbox_tee_shm_register,
375 .shm_unregister = sandbox_tee_shm_unregister,
376 };
377
378 static const struct udevice_id sandbox_tee_match[] = {
379 { .compatible = "sandbox,tee" },
380 {},
381 };
382
383 U_BOOT_DRIVER(sandbox_tee) = {
384 .name = "sandbox_tee",
385 .id = UCLASS_TEE,
386 .of_match = sandbox_tee_match,
387 .ops = &sandbox_tee_ops,
388 .priv_auto_alloc_size = sizeof(struct sandbox_tee_state),
389 .probe = sandbox_tee_probe,
390 .remove = sandbox_tee_remove,
391 };
392