tee: add sandbox driver
[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 /**
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 };