Commit eadf26f1834666e6ad3ab8f17556d5939c88549e
Committed by
Tom Rini
1 parent
fe39e8e0ee
Exists in
smarc_8mq_lf_v2020.04
and in
11 other branches
tee: add sandbox driver
Adds a sandbox tee driver which emulates a generic TEE with the OP-TEE AVB TA. Reviewed-by: Simon Glass <sjg@chromium.org> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org> Reviewed-by: Simon Glass <sjg@chromium.org> [trini: Fix printf warnings in ta_avb_invoke_func, slots is uint] Signed-off-by: Tom Rini <trini@konsulko.com>
Showing 5 changed files with 347 additions and 3 deletions Side-by-side Diff
drivers/tee/Kconfig
1 | 1 | # Generic Trusted Execution Environment Configuration |
2 | 2 | config TEE |
3 | 3 | bool "Trusted Execution Environment support" |
4 | - depends on ARM && (ARM64 || CPU_V7A) | |
5 | - select ARM_SMCCC | |
4 | + depends on (ARM && (ARM64 || CPU_V7A)) || SANDBOX | |
5 | + select ARM_SMCCC if ARM | |
6 | 6 | help |
7 | 7 | This implements a generic interface towards a Trusted Execution |
8 | 8 | Environment (TEE). A TEE is a trusted OS running in some secure |
... | ... | @@ -13,6 +13,20 @@ |
13 | 13 | if TEE |
14 | 14 | |
15 | 15 | menu "TEE drivers" |
16 | + | |
17 | +config SANDBOX_TEE | |
18 | + bool "Sandbox TEE emulator" | |
19 | + depends on SANDBOX | |
20 | + default y | |
21 | + help | |
22 | + This emulates a generic TEE needed for testing including the AVB | |
23 | + TA. The emulation provides all callbacks of a regular TEE and | |
24 | + supports session and shared memory management. The AVB TA is | |
25 | + emulated with rollback indexes and device lock-state, the state | |
26 | + of the TA is only kept in RAM and will be reset on each boot. | |
27 | + The emulation only supports one open session at a time. | |
28 | + Interaction from the U-Boot command line in possible via the | |
29 | + "avb" commands. | |
16 | 30 | |
17 | 31 | source "drivers/tee/optee/Kconfig" |
18 | 32 |
drivers/tee/Makefile
drivers/tee/optee/Kconfig
drivers/tee/sandbox.c
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 | +/** | |
18 | + * struct ta_entry - TA entries | |
19 | + * @uuid: UUID of an emulated TA | |
20 | + * @open_session Called when a session is openened to the TA | |
21 | + * @invoke_func Called when a function in the TA is to be invoked | |
22 | + * | |
23 | + * This struct is used to register TAs in this sandbox emulation of a TEE. | |
24 | + */ | |
25 | +struct ta_entry { | |
26 | + struct tee_optee_ta_uuid uuid; | |
27 | + u32 (*open_session)(uint num_params, struct tee_param *params); | |
28 | + u32 (*invoke_func)(u32 func, uint num_params, struct tee_param *params); | |
29 | +}; | |
30 | + | |
31 | +#ifdef CONFIG_OPTEE_TA_AVB | |
32 | +static u32 get_attr(uint n, uint num_params, struct tee_param *params) | |
33 | +{ | |
34 | + if (n >= num_params) | |
35 | + return TEE_PARAM_ATTR_TYPE_NONE; | |
36 | + | |
37 | + return params[n].attr; | |
38 | +} | |
39 | + | |
40 | +static u32 check_params(u8 p0, u8 p1, u8 p2, u8 p3, uint num_params, | |
41 | + struct tee_param *params) | |
42 | +{ | |
43 | + u8 p[] = { p0, p1, p2, p3}; | |
44 | + uint n; | |
45 | + | |
46 | + for (n = 0; n < ARRAY_SIZE(p); n++) | |
47 | + if (p[n] != get_attr(n, num_params, params)) | |
48 | + goto bad_params; | |
49 | + | |
50 | + for (; n < num_params; n++) | |
51 | + if (get_attr(n, num_params, params)) | |
52 | + goto bad_params; | |
53 | + | |
54 | + return TEE_SUCCESS; | |
55 | + | |
56 | +bad_params: | |
57 | + printf("Bad param attrs\n"); | |
58 | + | |
59 | + return TEE_ERROR_BAD_PARAMETERS; | |
60 | +} | |
61 | + | |
62 | +static u64 ta_avb_rollback_indexes[TA_AVB_MAX_ROLLBACK_LOCATIONS]; | |
63 | +static u32 ta_avb_lock_state; | |
64 | + | |
65 | +static u32 ta_avb_open_session(uint num_params, struct tee_param *params) | |
66 | +{ | |
67 | + /* | |
68 | + * We don't expect additional parameters when opening a session to | |
69 | + * this TA. | |
70 | + */ | |
71 | + return check_params(TEE_PARAM_ATTR_TYPE_NONE, TEE_PARAM_ATTR_TYPE_NONE, | |
72 | + TEE_PARAM_ATTR_TYPE_NONE, TEE_PARAM_ATTR_TYPE_NONE, | |
73 | + num_params, params); | |
74 | +} | |
75 | + | |
76 | +static u32 ta_avb_invoke_func(u32 func, uint num_params, | |
77 | + struct tee_param *params) | |
78 | +{ | |
79 | + u32 res; | |
80 | + uint slot; | |
81 | + u64 val; | |
82 | + | |
83 | + switch (func) { | |
84 | + case TA_AVB_CMD_READ_ROLLBACK_INDEX: | |
85 | + res = check_params(TEE_PARAM_ATTR_TYPE_VALUE_INPUT, | |
86 | + TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT, | |
87 | + TEE_PARAM_ATTR_TYPE_NONE, | |
88 | + TEE_PARAM_ATTR_TYPE_NONE, | |
89 | + num_params, params); | |
90 | + if (res) | |
91 | + return res; | |
92 | + | |
93 | + slot = params[0].u.value.a; | |
94 | + if (slot >= ARRAY_SIZE(ta_avb_rollback_indexes)) { | |
95 | + printf("Rollback index slot out of bounds %u\n", slot); | |
96 | + return TEE_ERROR_BAD_PARAMETERS; | |
97 | + } | |
98 | + | |
99 | + val = ta_avb_rollback_indexes[slot]; | |
100 | + params[1].u.value.a = val >> 32; | |
101 | + params[1].u.value.b = val; | |
102 | + return TEE_SUCCESS; | |
103 | + | |
104 | + case TA_AVB_CMD_WRITE_ROLLBACK_INDEX: | |
105 | + res = check_params(TEE_PARAM_ATTR_TYPE_VALUE_INPUT, | |
106 | + TEE_PARAM_ATTR_TYPE_VALUE_INPUT, | |
107 | + TEE_PARAM_ATTR_TYPE_NONE, | |
108 | + TEE_PARAM_ATTR_TYPE_NONE, | |
109 | + num_params, params); | |
110 | + if (res) | |
111 | + return res; | |
112 | + | |
113 | + slot = params[0].u.value.a; | |
114 | + if (slot >= ARRAY_SIZE(ta_avb_rollback_indexes)) { | |
115 | + printf("Rollback index slot out of bounds %u\n", slot); | |
116 | + return TEE_ERROR_BAD_PARAMETERS; | |
117 | + } | |
118 | + | |
119 | + val = (u64)params[1].u.value.a << 32 | params[1].u.value.b; | |
120 | + if (val < ta_avb_rollback_indexes[slot]) | |
121 | + return TEE_ERROR_SECURITY; | |
122 | + | |
123 | + ta_avb_rollback_indexes[slot] = val; | |
124 | + return TEE_SUCCESS; | |
125 | + | |
126 | + case TA_AVB_CMD_READ_LOCK_STATE: | |
127 | + res = check_params(TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT, | |
128 | + TEE_PARAM_ATTR_TYPE_NONE, | |
129 | + TEE_PARAM_ATTR_TYPE_NONE, | |
130 | + TEE_PARAM_ATTR_TYPE_NONE, | |
131 | + num_params, params); | |
132 | + if (res) | |
133 | + return res; | |
134 | + | |
135 | + params[0].u.value.a = ta_avb_lock_state; | |
136 | + return TEE_SUCCESS; | |
137 | + | |
138 | + case TA_AVB_CMD_WRITE_LOCK_STATE: | |
139 | + res = check_params(TEE_PARAM_ATTR_TYPE_VALUE_INPUT, | |
140 | + TEE_PARAM_ATTR_TYPE_NONE, | |
141 | + TEE_PARAM_ATTR_TYPE_NONE, | |
142 | + TEE_PARAM_ATTR_TYPE_NONE, | |
143 | + num_params, params); | |
144 | + if (res) | |
145 | + return res; | |
146 | + | |
147 | + if (ta_avb_lock_state != params[0].u.value.a) { | |
148 | + ta_avb_lock_state = params[0].u.value.a; | |
149 | + memset(ta_avb_rollback_indexes, 0, | |
150 | + sizeof(ta_avb_rollback_indexes)); | |
151 | + } | |
152 | + | |
153 | + return TEE_SUCCESS; | |
154 | + | |
155 | + default: | |
156 | + return TEE_ERROR_NOT_SUPPORTED; | |
157 | + } | |
158 | +} | |
159 | +#endif /*OPTEE_TA_AVB*/ | |
160 | + | |
161 | +static const struct ta_entry ta_entries[] = { | |
162 | +#ifdef CONFIG_OPTEE_TA_AVB | |
163 | + { .uuid = TA_AVB_UUID, | |
164 | + .open_session = ta_avb_open_session, | |
165 | + .invoke_func = ta_avb_invoke_func, | |
166 | + }, | |
167 | +#endif | |
168 | +}; | |
169 | + | |
170 | +static void sandbox_tee_get_version(struct udevice *dev, | |
171 | + struct tee_version_data *vers) | |
172 | +{ | |
173 | + struct tee_version_data v = { | |
174 | + .gen_caps = TEE_GEN_CAP_GP | TEE_GEN_CAP_REG_MEM, | |
175 | + }; | |
176 | + | |
177 | + *vers = v; | |
178 | +} | |
179 | + | |
180 | +static int sandbox_tee_close_session(struct udevice *dev, u32 session) | |
181 | +{ | |
182 | + struct sandbox_tee_state *state = dev_get_priv(dev); | |
183 | + | |
184 | + if (!state->ta || state->session != session) | |
185 | + return -EINVAL; | |
186 | + | |
187 | + state->session = 0; | |
188 | + state->ta = NULL; | |
189 | + | |
190 | + return 0; | |
191 | +} | |
192 | + | |
193 | +static const struct ta_entry *find_ta_entry(u8 uuid[TEE_UUID_LEN]) | |
194 | +{ | |
195 | + struct tee_optee_ta_uuid u; | |
196 | + uint n; | |
197 | + | |
198 | + tee_optee_ta_uuid_from_octets(&u, uuid); | |
199 | + | |
200 | + for (n = 0; n < ARRAY_SIZE(ta_entries); n++) | |
201 | + if (!memcmp(&u, &ta_entries[n].uuid, sizeof(u))) | |
202 | + return ta_entries + n; | |
203 | + | |
204 | + return NULL; | |
205 | +} | |
206 | + | |
207 | +static int sandbox_tee_open_session(struct udevice *dev, | |
208 | + struct tee_open_session_arg *arg, | |
209 | + uint num_params, struct tee_param *params) | |
210 | +{ | |
211 | + struct sandbox_tee_state *state = dev_get_priv(dev); | |
212 | + const struct ta_entry *ta; | |
213 | + | |
214 | + if (state->ta) { | |
215 | + printf("A session is already open\n"); | |
216 | + return -EBUSY; | |
217 | + } | |
218 | + | |
219 | + ta = find_ta_entry(arg->uuid); | |
220 | + if (!ta) { | |
221 | + printf("Cannot find TA\n"); | |
222 | + arg->ret = TEE_ERROR_ITEM_NOT_FOUND; | |
223 | + arg->ret_origin = TEE_ORIGIN_TEE; | |
224 | + | |
225 | + return 0; | |
226 | + } | |
227 | + | |
228 | + arg->ret = ta->open_session(num_params, params); | |
229 | + arg->ret_origin = TEE_ORIGIN_TRUSTED_APP; | |
230 | + | |
231 | + if (!arg->ret) { | |
232 | + state->ta = (void *)ta; | |
233 | + state->session = 1; | |
234 | + arg->session = state->session; | |
235 | + } else { | |
236 | + printf("Cannot open session, TA returns error\n"); | |
237 | + } | |
238 | + | |
239 | + return 0; | |
240 | +} | |
241 | + | |
242 | +static int sandbox_tee_invoke_func(struct udevice *dev, | |
243 | + struct tee_invoke_arg *arg, | |
244 | + uint num_params, struct tee_param *params) | |
245 | +{ | |
246 | + struct sandbox_tee_state *state = dev_get_priv(dev); | |
247 | + struct ta_entry *ta = state->ta; | |
248 | + | |
249 | + if (!arg->session) { | |
250 | + printf("Missing session\n"); | |
251 | + return -EINVAL; | |
252 | + } | |
253 | + | |
254 | + if (!ta) { | |
255 | + printf("TA session not available\n"); | |
256 | + return -EINVAL; | |
257 | + } | |
258 | + | |
259 | + if (arg->session != state->session) { | |
260 | + printf("Session mismatch\n"); | |
261 | + return -EINVAL; | |
262 | + } | |
263 | + | |
264 | + arg->ret = ta->invoke_func(arg->func, num_params, params); | |
265 | + arg->ret_origin = TEE_ORIGIN_TRUSTED_APP; | |
266 | + | |
267 | + return 0; | |
268 | +} | |
269 | + | |
270 | +static int sandbox_tee_shm_register(struct udevice *dev, struct tee_shm *shm) | |
271 | +{ | |
272 | + struct sandbox_tee_state *state = dev_get_priv(dev); | |
273 | + | |
274 | + state->num_shms++; | |
275 | + | |
276 | + return 0; | |
277 | +} | |
278 | + | |
279 | +static int sandbox_tee_shm_unregister(struct udevice *dev, struct tee_shm *shm) | |
280 | +{ | |
281 | + struct sandbox_tee_state *state = dev_get_priv(dev); | |
282 | + | |
283 | + state->num_shms--; | |
284 | + | |
285 | + return 0; | |
286 | +} | |
287 | + | |
288 | +static const struct tee_driver_ops sandbox_tee_ops = { | |
289 | + .get_version = sandbox_tee_get_version, | |
290 | + .open_session = sandbox_tee_open_session, | |
291 | + .close_session = sandbox_tee_close_session, | |
292 | + .invoke_func = sandbox_tee_invoke_func, | |
293 | + .shm_register = sandbox_tee_shm_register, | |
294 | + .shm_unregister = sandbox_tee_shm_unregister, | |
295 | +}; | |
296 | + | |
297 | +static const struct udevice_id sandbox_tee_match[] = { | |
298 | + { .compatible = "sandbox,tee" }, | |
299 | + {}, | |
300 | +}; | |
301 | + | |
302 | +U_BOOT_DRIVER(sandbox_tee) = { | |
303 | + .name = "sandbox_tee", | |
304 | + .id = UCLASS_TEE, | |
305 | + .of_match = sandbox_tee_match, | |
306 | + .ops = &sandbox_tee_ops, | |
307 | + .priv_auto_alloc_size = sizeof(struct sandbox_tee_state), | |
308 | +}; |
include/sandboxtee.h
1 | +/* SPDX-License-Identifier: GPL-2.0+ */ | |
2 | +/* | |
3 | + * Copyright (C) 2018 Linaro Limited | |
4 | + */ | |
5 | + | |
6 | +#ifndef __SANDBOXTEE_H | |
7 | +#define __SANDBOXTEE_H | |
8 | + | |
9 | +/** | |
10 | + * struct sandbox_tee_state - internal state of the sandbox TEE | |
11 | + * @session: current open session | |
12 | + * @num_shms: number of registered shared memory objects | |
13 | + * @ta: Trusted Application of current session | |
14 | + */ | |
15 | +struct sandbox_tee_state { | |
16 | + u32 session; | |
17 | + int num_shms; | |
18 | + void *ta; | |
19 | +}; | |
20 | + | |
21 | +#endif /*__SANDBOXTEE_H*/ |