• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
get_attr(uint n,uint num_params,struct tee_param * params)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 
check_params(u8 p0,u8 p1,u8 p2,u8 p3,uint num_params,struct tee_param * params)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 
ta_avb_open_session(struct udevice * dev,uint num_params,struct tee_param * params)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 
ta_avb_invoke_func(struct udevice * dev,u32 func,uint num_params,struct tee_param * params)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 
sandbox_tee_get_version(struct udevice * dev,struct tee_version_data * vers)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 
sandbox_tee_close_session(struct udevice * dev,u32 session)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 
find_ta_entry(u8 uuid[TEE_UUID_LEN])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 
sandbox_tee_open_session(struct udevice * dev,struct tee_open_session_arg * arg,uint num_params,struct tee_param * params)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 
sandbox_tee_invoke_func(struct udevice * dev,struct tee_invoke_arg * arg,uint num_params,struct tee_param * params)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 
sandbox_tee_shm_register(struct udevice * dev,struct tee_shm * shm)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 
sandbox_tee_shm_unregister(struct udevice * dev,struct tee_shm * shm)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 
sandbox_tee_remove(struct udevice * dev)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 
sandbox_tee_probe(struct udevice * dev)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 };
392