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 }; 309