xref: /openbmc/u-boot/drivers/tee/sandbox.c (revision eadf26f1834666e6ad3ab8f17556d5939c88549e)
1*eadf26f1SJens Wiklander // SPDX-License-Identifier: GPL-2.0+
2*eadf26f1SJens Wiklander /*
3*eadf26f1SJens Wiklander  * Copyright (C) 2018 Linaro Limited
4*eadf26f1SJens Wiklander  */
5*eadf26f1SJens Wiklander #include <common.h>
6*eadf26f1SJens Wiklander #include <dm.h>
7*eadf26f1SJens Wiklander #include <sandboxtee.h>
8*eadf26f1SJens Wiklander #include <tee.h>
9*eadf26f1SJens Wiklander #include <tee/optee_ta_avb.h>
10*eadf26f1SJens Wiklander 
11*eadf26f1SJens Wiklander /*
12*eadf26f1SJens Wiklander  * The sandbox tee driver tries to emulate a generic Trusted Exectution
13*eadf26f1SJens Wiklander  * Environment (TEE) with the Trusted Application (TA) OPTEE_TA_AVB
14*eadf26f1SJens Wiklander  * available.
15*eadf26f1SJens Wiklander  */
16*eadf26f1SJens Wiklander 
17*eadf26f1SJens Wiklander /**
18*eadf26f1SJens Wiklander  * struct ta_entry - TA entries
19*eadf26f1SJens Wiklander  * @uuid:		UUID of an emulated TA
20*eadf26f1SJens Wiklander  * @open_session	Called when a session is openened to the TA
21*eadf26f1SJens Wiklander  * @invoke_func		Called when a function in the TA is to be invoked
22*eadf26f1SJens Wiklander  *
23*eadf26f1SJens Wiklander  * This struct is used to register TAs in this sandbox emulation of a TEE.
24*eadf26f1SJens Wiklander  */
25*eadf26f1SJens Wiklander struct ta_entry {
26*eadf26f1SJens Wiklander 	struct tee_optee_ta_uuid uuid;
27*eadf26f1SJens Wiklander 	u32 (*open_session)(uint num_params, struct tee_param *params);
28*eadf26f1SJens Wiklander 	u32 (*invoke_func)(u32 func, uint num_params, struct tee_param *params);
29*eadf26f1SJens Wiklander };
30*eadf26f1SJens Wiklander 
31*eadf26f1SJens Wiklander #ifdef CONFIG_OPTEE_TA_AVB
get_attr(uint n,uint num_params,struct tee_param * params)32*eadf26f1SJens Wiklander static u32 get_attr(uint n, uint num_params, struct tee_param *params)
33*eadf26f1SJens Wiklander {
34*eadf26f1SJens Wiklander 	if (n >= num_params)
35*eadf26f1SJens Wiklander 		return TEE_PARAM_ATTR_TYPE_NONE;
36*eadf26f1SJens Wiklander 
37*eadf26f1SJens Wiklander 	return params[n].attr;
38*eadf26f1SJens Wiklander }
39*eadf26f1SJens Wiklander 
check_params(u8 p0,u8 p1,u8 p2,u8 p3,uint num_params,struct tee_param * params)40*eadf26f1SJens Wiklander static u32 check_params(u8 p0, u8 p1, u8 p2, u8 p3, uint num_params,
41*eadf26f1SJens Wiklander 			struct tee_param *params)
42*eadf26f1SJens Wiklander {
43*eadf26f1SJens Wiklander 	u8 p[] = { p0, p1, p2, p3};
44*eadf26f1SJens Wiklander 	uint n;
45*eadf26f1SJens Wiklander 
46*eadf26f1SJens Wiklander 	for (n = 0; n < ARRAY_SIZE(p); n++)
47*eadf26f1SJens Wiklander 		if (p[n] != get_attr(n, num_params, params))
48*eadf26f1SJens Wiklander 			goto bad_params;
49*eadf26f1SJens Wiklander 
50*eadf26f1SJens Wiklander 	for (; n < num_params; n++)
51*eadf26f1SJens Wiklander 		if (get_attr(n, num_params, params))
52*eadf26f1SJens Wiklander 			goto bad_params;
53*eadf26f1SJens Wiklander 
54*eadf26f1SJens Wiklander 	return TEE_SUCCESS;
55*eadf26f1SJens Wiklander 
56*eadf26f1SJens Wiklander bad_params:
57*eadf26f1SJens Wiklander 	printf("Bad param attrs\n");
58*eadf26f1SJens Wiklander 
59*eadf26f1SJens Wiklander 	return TEE_ERROR_BAD_PARAMETERS;
60*eadf26f1SJens Wiklander }
61*eadf26f1SJens Wiklander 
62*eadf26f1SJens Wiklander static u64 ta_avb_rollback_indexes[TA_AVB_MAX_ROLLBACK_LOCATIONS];
63*eadf26f1SJens Wiklander static u32 ta_avb_lock_state;
64*eadf26f1SJens Wiklander 
ta_avb_open_session(uint num_params,struct tee_param * params)65*eadf26f1SJens Wiklander static u32 ta_avb_open_session(uint num_params, struct tee_param *params)
66*eadf26f1SJens Wiklander {
67*eadf26f1SJens Wiklander 	/*
68*eadf26f1SJens Wiklander 	 * We don't expect additional parameters when opening a session to
69*eadf26f1SJens Wiklander 	 * this TA.
70*eadf26f1SJens Wiklander 	 */
71*eadf26f1SJens Wiklander 	return check_params(TEE_PARAM_ATTR_TYPE_NONE, TEE_PARAM_ATTR_TYPE_NONE,
72*eadf26f1SJens Wiklander 			    TEE_PARAM_ATTR_TYPE_NONE, TEE_PARAM_ATTR_TYPE_NONE,
73*eadf26f1SJens Wiklander 			    num_params, params);
74*eadf26f1SJens Wiklander }
75*eadf26f1SJens Wiklander 
ta_avb_invoke_func(u32 func,uint num_params,struct tee_param * params)76*eadf26f1SJens Wiklander static u32 ta_avb_invoke_func(u32 func, uint num_params,
77*eadf26f1SJens Wiklander 			      struct tee_param *params)
78*eadf26f1SJens Wiklander {
79*eadf26f1SJens Wiklander 	u32 res;
80*eadf26f1SJens Wiklander 	uint slot;
81*eadf26f1SJens Wiklander 	u64 val;
82*eadf26f1SJens Wiklander 
83*eadf26f1SJens Wiklander 	switch (func) {
84*eadf26f1SJens Wiklander 	case TA_AVB_CMD_READ_ROLLBACK_INDEX:
85*eadf26f1SJens Wiklander 		res = check_params(TEE_PARAM_ATTR_TYPE_VALUE_INPUT,
86*eadf26f1SJens Wiklander 				   TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT,
87*eadf26f1SJens Wiklander 				   TEE_PARAM_ATTR_TYPE_NONE,
88*eadf26f1SJens Wiklander 				   TEE_PARAM_ATTR_TYPE_NONE,
89*eadf26f1SJens Wiklander 				   num_params, params);
90*eadf26f1SJens Wiklander 		if (res)
91*eadf26f1SJens Wiklander 			return res;
92*eadf26f1SJens Wiklander 
93*eadf26f1SJens Wiklander 		slot = params[0].u.value.a;
94*eadf26f1SJens Wiklander 		if (slot >= ARRAY_SIZE(ta_avb_rollback_indexes)) {
95*eadf26f1SJens Wiklander 			printf("Rollback index slot out of bounds %u\n", slot);
96*eadf26f1SJens Wiklander 			return TEE_ERROR_BAD_PARAMETERS;
97*eadf26f1SJens Wiklander 		}
98*eadf26f1SJens Wiklander 
99*eadf26f1SJens Wiklander 		val = ta_avb_rollback_indexes[slot];
100*eadf26f1SJens Wiklander 		params[1].u.value.a = val >> 32;
101*eadf26f1SJens Wiklander 		params[1].u.value.b = val;
102*eadf26f1SJens Wiklander 		return TEE_SUCCESS;
103*eadf26f1SJens Wiklander 
104*eadf26f1SJens Wiklander 	case TA_AVB_CMD_WRITE_ROLLBACK_INDEX:
105*eadf26f1SJens Wiklander 		res = check_params(TEE_PARAM_ATTR_TYPE_VALUE_INPUT,
106*eadf26f1SJens Wiklander 				   TEE_PARAM_ATTR_TYPE_VALUE_INPUT,
107*eadf26f1SJens Wiklander 				   TEE_PARAM_ATTR_TYPE_NONE,
108*eadf26f1SJens Wiklander 				   TEE_PARAM_ATTR_TYPE_NONE,
109*eadf26f1SJens Wiklander 				   num_params, params);
110*eadf26f1SJens Wiklander 		if (res)
111*eadf26f1SJens Wiklander 			return res;
112*eadf26f1SJens Wiklander 
113*eadf26f1SJens Wiklander 		slot = params[0].u.value.a;
114*eadf26f1SJens Wiklander 		if (slot >= ARRAY_SIZE(ta_avb_rollback_indexes)) {
115*eadf26f1SJens Wiklander 			printf("Rollback index slot out of bounds %u\n", slot);
116*eadf26f1SJens Wiklander 			return TEE_ERROR_BAD_PARAMETERS;
117*eadf26f1SJens Wiklander 		}
118*eadf26f1SJens Wiklander 
119*eadf26f1SJens Wiklander 		val = (u64)params[1].u.value.a << 32 | params[1].u.value.b;
120*eadf26f1SJens Wiklander 		if (val < ta_avb_rollback_indexes[slot])
121*eadf26f1SJens Wiklander 			return TEE_ERROR_SECURITY;
122*eadf26f1SJens Wiklander 
123*eadf26f1SJens Wiklander 		ta_avb_rollback_indexes[slot] = val;
124*eadf26f1SJens Wiklander 		return TEE_SUCCESS;
125*eadf26f1SJens Wiklander 
126*eadf26f1SJens Wiklander 	case TA_AVB_CMD_READ_LOCK_STATE:
127*eadf26f1SJens Wiklander 		res = check_params(TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT,
128*eadf26f1SJens Wiklander 				   TEE_PARAM_ATTR_TYPE_NONE,
129*eadf26f1SJens Wiklander 				   TEE_PARAM_ATTR_TYPE_NONE,
130*eadf26f1SJens Wiklander 				   TEE_PARAM_ATTR_TYPE_NONE,
131*eadf26f1SJens Wiklander 				   num_params, params);
132*eadf26f1SJens Wiklander 		if (res)
133*eadf26f1SJens Wiklander 			return res;
134*eadf26f1SJens Wiklander 
135*eadf26f1SJens Wiklander 		params[0].u.value.a = ta_avb_lock_state;
136*eadf26f1SJens Wiklander 		return TEE_SUCCESS;
137*eadf26f1SJens Wiklander 
138*eadf26f1SJens Wiklander 	case TA_AVB_CMD_WRITE_LOCK_STATE:
139*eadf26f1SJens Wiklander 		res = check_params(TEE_PARAM_ATTR_TYPE_VALUE_INPUT,
140*eadf26f1SJens Wiklander 				   TEE_PARAM_ATTR_TYPE_NONE,
141*eadf26f1SJens Wiklander 				   TEE_PARAM_ATTR_TYPE_NONE,
142*eadf26f1SJens Wiklander 				   TEE_PARAM_ATTR_TYPE_NONE,
143*eadf26f1SJens Wiklander 				   num_params, params);
144*eadf26f1SJens Wiklander 		if (res)
145*eadf26f1SJens Wiklander 			return res;
146*eadf26f1SJens Wiklander 
147*eadf26f1SJens Wiklander 		if (ta_avb_lock_state != params[0].u.value.a) {
148*eadf26f1SJens Wiklander 			ta_avb_lock_state = params[0].u.value.a;
149*eadf26f1SJens Wiklander 			memset(ta_avb_rollback_indexes, 0,
150*eadf26f1SJens Wiklander 			       sizeof(ta_avb_rollback_indexes));
151*eadf26f1SJens Wiklander 		}
152*eadf26f1SJens Wiklander 
153*eadf26f1SJens Wiklander 		return TEE_SUCCESS;
154*eadf26f1SJens Wiklander 
155*eadf26f1SJens Wiklander 	default:
156*eadf26f1SJens Wiklander 		return TEE_ERROR_NOT_SUPPORTED;
157*eadf26f1SJens Wiklander 	}
158*eadf26f1SJens Wiklander }
159*eadf26f1SJens Wiklander #endif /*OPTEE_TA_AVB*/
160*eadf26f1SJens Wiklander 
161*eadf26f1SJens Wiklander static const struct ta_entry ta_entries[] = {
162*eadf26f1SJens Wiklander #ifdef CONFIG_OPTEE_TA_AVB
163*eadf26f1SJens Wiklander 	{ .uuid = TA_AVB_UUID,
164*eadf26f1SJens Wiklander 	  .open_session = ta_avb_open_session,
165*eadf26f1SJens Wiklander 	  .invoke_func = ta_avb_invoke_func,
166*eadf26f1SJens Wiklander 	},
167*eadf26f1SJens Wiklander #endif
168*eadf26f1SJens Wiklander };
169*eadf26f1SJens Wiklander 
sandbox_tee_get_version(struct udevice * dev,struct tee_version_data * vers)170*eadf26f1SJens Wiklander static void sandbox_tee_get_version(struct udevice *dev,
171*eadf26f1SJens Wiklander 				    struct tee_version_data *vers)
172*eadf26f1SJens Wiklander {
173*eadf26f1SJens Wiklander 	struct tee_version_data v = {
174*eadf26f1SJens Wiklander 		.gen_caps = TEE_GEN_CAP_GP | TEE_GEN_CAP_REG_MEM,
175*eadf26f1SJens Wiklander 	};
176*eadf26f1SJens Wiklander 
177*eadf26f1SJens Wiklander 	*vers = v;
178*eadf26f1SJens Wiklander }
179*eadf26f1SJens Wiklander 
sandbox_tee_close_session(struct udevice * dev,u32 session)180*eadf26f1SJens Wiklander static int sandbox_tee_close_session(struct udevice *dev, u32 session)
181*eadf26f1SJens Wiklander {
182*eadf26f1SJens Wiklander 	struct sandbox_tee_state *state = dev_get_priv(dev);
183*eadf26f1SJens Wiklander 
184*eadf26f1SJens Wiklander 	if (!state->ta || state->session != session)
185*eadf26f1SJens Wiklander 		return -EINVAL;
186*eadf26f1SJens Wiklander 
187*eadf26f1SJens Wiklander 	state->session = 0;
188*eadf26f1SJens Wiklander 	state->ta = NULL;
189*eadf26f1SJens Wiklander 
190*eadf26f1SJens Wiklander 	return 0;
191*eadf26f1SJens Wiklander }
192*eadf26f1SJens Wiklander 
find_ta_entry(u8 uuid[TEE_UUID_LEN])193*eadf26f1SJens Wiklander static const struct ta_entry *find_ta_entry(u8 uuid[TEE_UUID_LEN])
194*eadf26f1SJens Wiklander {
195*eadf26f1SJens Wiklander 	struct tee_optee_ta_uuid u;
196*eadf26f1SJens Wiklander 	uint n;
197*eadf26f1SJens Wiklander 
198*eadf26f1SJens Wiklander 	tee_optee_ta_uuid_from_octets(&u, uuid);
199*eadf26f1SJens Wiklander 
200*eadf26f1SJens Wiklander 	for (n = 0; n < ARRAY_SIZE(ta_entries); n++)
201*eadf26f1SJens Wiklander 		if (!memcmp(&u, &ta_entries[n].uuid, sizeof(u)))
202*eadf26f1SJens Wiklander 			return ta_entries + n;
203*eadf26f1SJens Wiklander 
204*eadf26f1SJens Wiklander 	return NULL;
205*eadf26f1SJens Wiklander }
206*eadf26f1SJens Wiklander 
sandbox_tee_open_session(struct udevice * dev,struct tee_open_session_arg * arg,uint num_params,struct tee_param * params)207*eadf26f1SJens Wiklander static int sandbox_tee_open_session(struct udevice *dev,
208*eadf26f1SJens Wiklander 				    struct tee_open_session_arg *arg,
209*eadf26f1SJens Wiklander 				    uint num_params, struct tee_param *params)
210*eadf26f1SJens Wiklander {
211*eadf26f1SJens Wiklander 	struct sandbox_tee_state *state = dev_get_priv(dev);
212*eadf26f1SJens Wiklander 	const struct ta_entry *ta;
213*eadf26f1SJens Wiklander 
214*eadf26f1SJens Wiklander 	if (state->ta) {
215*eadf26f1SJens Wiklander 		printf("A session is already open\n");
216*eadf26f1SJens Wiklander 		return -EBUSY;
217*eadf26f1SJens Wiklander 	}
218*eadf26f1SJens Wiklander 
219*eadf26f1SJens Wiklander 	ta = find_ta_entry(arg->uuid);
220*eadf26f1SJens Wiklander 	if (!ta) {
221*eadf26f1SJens Wiklander 		printf("Cannot find TA\n");
222*eadf26f1SJens Wiklander 		arg->ret = TEE_ERROR_ITEM_NOT_FOUND;
223*eadf26f1SJens Wiklander 		arg->ret_origin = TEE_ORIGIN_TEE;
224*eadf26f1SJens Wiklander 
225*eadf26f1SJens Wiklander 		return 0;
226*eadf26f1SJens Wiklander 	}
227*eadf26f1SJens Wiklander 
228*eadf26f1SJens Wiklander 	arg->ret = ta->open_session(num_params, params);
229*eadf26f1SJens Wiklander 	arg->ret_origin = TEE_ORIGIN_TRUSTED_APP;
230*eadf26f1SJens Wiklander 
231*eadf26f1SJens Wiklander 	if (!arg->ret) {
232*eadf26f1SJens Wiklander 		state->ta = (void *)ta;
233*eadf26f1SJens Wiklander 		state->session = 1;
234*eadf26f1SJens Wiklander 		arg->session = state->session;
235*eadf26f1SJens Wiklander 	} else {
236*eadf26f1SJens Wiklander 		printf("Cannot open session, TA returns error\n");
237*eadf26f1SJens Wiklander 	}
238*eadf26f1SJens Wiklander 
239*eadf26f1SJens Wiklander 	return 0;
240*eadf26f1SJens Wiklander }
241*eadf26f1SJens Wiklander 
sandbox_tee_invoke_func(struct udevice * dev,struct tee_invoke_arg * arg,uint num_params,struct tee_param * params)242*eadf26f1SJens Wiklander static int sandbox_tee_invoke_func(struct udevice *dev,
243*eadf26f1SJens Wiklander 				   struct tee_invoke_arg *arg,
244*eadf26f1SJens Wiklander 				   uint num_params, struct tee_param *params)
245*eadf26f1SJens Wiklander {
246*eadf26f1SJens Wiklander 	struct sandbox_tee_state *state = dev_get_priv(dev);
247*eadf26f1SJens Wiklander 	struct ta_entry *ta = state->ta;
248*eadf26f1SJens Wiklander 
249*eadf26f1SJens Wiklander 	if (!arg->session) {
250*eadf26f1SJens Wiklander 		printf("Missing session\n");
251*eadf26f1SJens Wiklander 		return -EINVAL;
252*eadf26f1SJens Wiklander 	}
253*eadf26f1SJens Wiklander 
254*eadf26f1SJens Wiklander 	if (!ta) {
255*eadf26f1SJens Wiklander 		printf("TA session not available\n");
256*eadf26f1SJens Wiklander 		return -EINVAL;
257*eadf26f1SJens Wiklander 	}
258*eadf26f1SJens Wiklander 
259*eadf26f1SJens Wiklander 	if (arg->session != state->session) {
260*eadf26f1SJens Wiklander 		printf("Session mismatch\n");
261*eadf26f1SJens Wiklander 		return -EINVAL;
262*eadf26f1SJens Wiklander 	}
263*eadf26f1SJens Wiklander 
264*eadf26f1SJens Wiklander 	arg->ret = ta->invoke_func(arg->func, num_params, params);
265*eadf26f1SJens Wiklander 	arg->ret_origin = TEE_ORIGIN_TRUSTED_APP;
266*eadf26f1SJens Wiklander 
267*eadf26f1SJens Wiklander 	return 0;
268*eadf26f1SJens Wiklander }
269*eadf26f1SJens Wiklander 
sandbox_tee_shm_register(struct udevice * dev,struct tee_shm * shm)270*eadf26f1SJens Wiklander static int sandbox_tee_shm_register(struct udevice *dev, struct tee_shm *shm)
271*eadf26f1SJens Wiklander {
272*eadf26f1SJens Wiklander 	struct sandbox_tee_state *state = dev_get_priv(dev);
273*eadf26f1SJens Wiklander 
274*eadf26f1SJens Wiklander 	state->num_shms++;
275*eadf26f1SJens Wiklander 
276*eadf26f1SJens Wiklander 	return 0;
277*eadf26f1SJens Wiklander }
278*eadf26f1SJens Wiklander 
sandbox_tee_shm_unregister(struct udevice * dev,struct tee_shm * shm)279*eadf26f1SJens Wiklander static int sandbox_tee_shm_unregister(struct udevice *dev, struct tee_shm *shm)
280*eadf26f1SJens Wiklander {
281*eadf26f1SJens Wiklander 	struct sandbox_tee_state *state = dev_get_priv(dev);
282*eadf26f1SJens Wiklander 
283*eadf26f1SJens Wiklander 	state->num_shms--;
284*eadf26f1SJens Wiklander 
285*eadf26f1SJens Wiklander 	return 0;
286*eadf26f1SJens Wiklander }
287*eadf26f1SJens Wiklander 
288*eadf26f1SJens Wiklander static const struct tee_driver_ops sandbox_tee_ops = {
289*eadf26f1SJens Wiklander 	.get_version = sandbox_tee_get_version,
290*eadf26f1SJens Wiklander 	.open_session = sandbox_tee_open_session,
291*eadf26f1SJens Wiklander 	.close_session = sandbox_tee_close_session,
292*eadf26f1SJens Wiklander 	.invoke_func = sandbox_tee_invoke_func,
293*eadf26f1SJens Wiklander 	.shm_register = sandbox_tee_shm_register,
294*eadf26f1SJens Wiklander 	.shm_unregister = sandbox_tee_shm_unregister,
295*eadf26f1SJens Wiklander };
296*eadf26f1SJens Wiklander 
297*eadf26f1SJens Wiklander static const struct udevice_id sandbox_tee_match[] = {
298*eadf26f1SJens Wiklander 	{ .compatible = "sandbox,tee" },
299*eadf26f1SJens Wiklander 	{},
300*eadf26f1SJens Wiklander };
301*eadf26f1SJens Wiklander 
302*eadf26f1SJens Wiklander U_BOOT_DRIVER(sandbox_tee) = {
303*eadf26f1SJens Wiklander 	.name = "sandbox_tee",
304*eadf26f1SJens Wiklander 	.id = UCLASS_TEE,
305*eadf26f1SJens Wiklander 	.of_match = sandbox_tee_match,
306*eadf26f1SJens Wiklander 	.ops = &sandbox_tee_ops,
307*eadf26f1SJens Wiklander 	.priv_auto_alloc_size = sizeof(struct sandbox_tee_state),
308*eadf26f1SJens Wiklander };
309