blob: ccddb03e730ca651edd41e15ecd98f1e33f2bb47 [file] [log] [blame]
Jens Wiklanderc7b443a2018-09-25 16:40:18 +02001// 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 */
25struct 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
32static 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
40static 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
56bad_params:
57 printf("Bad param attrs\n");
58
59 return TEE_ERROR_BAD_PARAMETERS;
60}
61
62static u64 ta_avb_rollback_indexes[TA_AVB_MAX_ROLLBACK_LOCATIONS];
63static u32 ta_avb_lock_state;
64
65static 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
76static 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
161static 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
170static 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
180static 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
193static 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
207static 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
242static 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
270static 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
279static 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
288static 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
297static const struct udevice_id sandbox_tee_match[] = {
298 { .compatible = "sandbox,tee" },
299 {},
300};
301
302U_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};