env: net: U_BOOT_ENV_CALLBACKs should not depend on CMD_NET
[oweals/u-boot.git] / 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 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
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
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
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
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
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
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
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
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
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
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
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
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
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 };