1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (C) 2018 Linaro Limited
7 #include <sandboxtee.h>
9 #include <tee/optee_ta_avb.h>
12 * The sandbox tee driver tries to emulate a generic Trusted Exectution
13 * Environment (TEE) with the Trusted Application (TA) OPTEE_TA_AVB
17 static const u32 pstorage_max = 16;
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
24 * This struct is used to register TAs in this sandbox emulation of a TEE.
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);
35 #ifdef CONFIG_OPTEE_TA_AVB
36 static u32 get_attr(uint n, uint num_params, struct tee_param *params)
39 return TEE_PARAM_ATTR_TYPE_NONE;
41 return params[n].attr;
44 static u32 check_params(u8 p0, u8 p1, u8 p2, u8 p3, uint num_params,
45 struct tee_param *params)
47 u8 p[] = { p0, p1, p2, p3};
50 for (n = 0; n < ARRAY_SIZE(p); n++)
51 if (p[n] != get_attr(n, num_params, params))
54 for (; n < num_params; n++)
55 if (get_attr(n, num_params, params))
61 printf("Bad param attrs\n");
63 return TEE_ERROR_BAD_PARAMETERS;
66 static u32 ta_avb_open_session(struct udevice *dev, uint num_params,
67 struct tee_param *params)
70 * We don't expect additional parameters when opening a session to
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,
78 static u32 ta_avb_invoke_func(struct udevice *dev, u32 func, uint num_params,
79 struct tee_param *params)
81 struct sandbox_tee_state *state = dev_get_priv(dev);
82 struct env_entry e, *ep;
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,
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;
106 val = state->ta_avb_rollback_indexes[slot];
107 params[1].u.value.a = val >> 32;
108 params[1].u.value.b = val;
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,
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;
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;
130 state->ta_avb_rollback_indexes[slot] = val;
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,
142 params[0].u.value.a = state->ta_avb_lock_state;
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,
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));
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,
170 name = params[0].u.memref.shm->addr;
172 value = params[1].u.memref.shm->addr;
173 value_sz = params[1].u.memref.size;
177 hsearch_r(e, ENV_FIND, &ep, &state->pstorage_htab, 0);
179 return TEE_ERROR_ITEM_NOT_FOUND;
181 value_sz = strlen(ep->data) + 1;
182 memcpy(value, ep->data, value_sz);
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,
194 name = params[0].u.memref.shm->addr;
196 value = params[1].u.memref.shm->addr;
197 value_sz = params[1].u.memref.size;
201 hsearch_r(e, ENV_FIND, &ep, &state->pstorage_htab, 0);
203 hdelete_r(e.key, &state->pstorage_htab, 0);
207 hsearch_r(e, ENV_ENTER, &ep, &state->pstorage_htab, 0);
209 return TEE_ERROR_OUT_OF_MEMORY;
214 return TEE_ERROR_NOT_SUPPORTED;
217 #endif /*OPTEE_TA_AVB*/
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,
228 static void sandbox_tee_get_version(struct udevice *dev,
229 struct tee_version_data *vers)
231 struct tee_version_data v = {
232 .gen_caps = TEE_GEN_CAP_GP | TEE_GEN_CAP_REG_MEM,
238 static int sandbox_tee_close_session(struct udevice *dev, u32 session)
240 struct sandbox_tee_state *state = dev_get_priv(dev);
242 if (!state->ta || state->session != session)
251 static const struct ta_entry *find_ta_entry(u8 uuid[TEE_UUID_LEN])
253 struct tee_optee_ta_uuid u;
256 tee_optee_ta_uuid_from_octets(&u, uuid);
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;
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)
269 struct sandbox_tee_state *state = dev_get_priv(dev);
270 const struct ta_entry *ta;
273 printf("A session is already open\n");
277 ta = find_ta_entry(arg->uuid);
279 printf("Cannot find TA\n");
280 arg->ret = TEE_ERROR_ITEM_NOT_FOUND;
281 arg->ret_origin = TEE_ORIGIN_TEE;
286 arg->ret = ta->open_session(dev, num_params, params);
287 arg->ret_origin = TEE_ORIGIN_TRUSTED_APP;
290 state->ta = (void *)ta;
292 arg->session = state->session;
294 printf("Cannot open session, TA returns error\n");
300 static int sandbox_tee_invoke_func(struct udevice *dev,
301 struct tee_invoke_arg *arg,
302 uint num_params, struct tee_param *params)
304 struct sandbox_tee_state *state = dev_get_priv(dev);
305 struct ta_entry *ta = state->ta;
308 printf("Missing session\n");
313 printf("TA session not available\n");
317 if (arg->session != state->session) {
318 printf("Session mismatch\n");
322 arg->ret = ta->invoke_func(dev, arg->func, num_params, params);
323 arg->ret_origin = TEE_ORIGIN_TRUSTED_APP;
328 static int sandbox_tee_shm_register(struct udevice *dev, struct tee_shm *shm)
330 struct sandbox_tee_state *state = dev_get_priv(dev);
337 static int sandbox_tee_shm_unregister(struct udevice *dev, struct tee_shm *shm)
339 struct sandbox_tee_state *state = dev_get_priv(dev);
346 static int sandbox_tee_remove(struct udevice *dev)
348 struct sandbox_tee_state *state = dev_get_priv(dev);
350 hdestroy_r(&state->pstorage_htab);
355 static int sandbox_tee_probe(struct udevice *dev)
357 struct sandbox_tee_state *state = dev_get_priv(dev);
359 * With this hastable we emulate persistent storage,
360 * which should contain persistent values
361 * between different sessions/command invocations.
363 if (!hcreate_r(pstorage_max, &state->pstorage_htab))
364 return TEE_ERROR_OUT_OF_MEMORY;
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,
378 static const struct udevice_id sandbox_tee_match[] = {
379 { .compatible = "sandbox,tee" },
383 U_BOOT_DRIVER(sandbox_tee) = {
384 .name = "sandbox_tee",
386 .of_match = sandbox_tee_match,
387 .ops = &sandbox_tee_ops,
388 .priv_auto = sizeof(struct sandbox_tee_state),
389 .probe = sandbox_tee_probe,
390 .remove = sandbox_tee_remove,