1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2014, STMicroelectronics International N.V. 4 * Copyright (c) 2015, Linaro Limited 5 * Copyright (c) 2020, Arm Limited 6 */ 7 #include <initcall.h> 8 #include <kernel/linker.h> 9 #include <kernel/panic.h> 10 #include <kernel/pseudo_ta.h> 11 #include <kernel/tee_ta_manager.h> 12 #include <kernel/user_access.h> 13 #include <mm/core_memprot.h> 14 #include <mm/mobj.h> 15 #include <stdlib.h> 16 #include <string.h> 17 #include <trace.h> 18 #include <types_ext.h> 19 20 #ifdef CFG_SECURE_DATA_PATH 21 static bool client_is_secure(struct ts_session *s) 22 { 23 /* rely on core entry to have constrained client IDs */ 24 if (to_ta_session(s)->clnt_id.login == TEE_LOGIN_TRUSTED_APP) 25 return true; 26 27 return false; 28 } 29 30 static bool validate_in_param(struct ts_session *s, struct mobj *mobj) 31 { 32 /* Supplying NULL to query buffer size is OK */ 33 if (!mobj) 34 return true; 35 36 /* for secure clients, core entry always holds valid memref objects */ 37 if (client_is_secure(s)) 38 return true; 39 40 /* all non-secure memory references are handled by PTAs */ 41 if (mobj_is_nonsec(mobj)) 42 return true; 43 44 return false; 45 } 46 #else 47 static bool validate_in_param(struct ts_session *s __unused, 48 struct mobj *mobj __unused) 49 { 50 /* At this point, core has filled only valid accessible memref mobj */ 51 return true; 52 } 53 #endif 54 55 /* Maps pseudo TA params */ 56 static TEE_Result copy_in_param(struct ts_session *s __maybe_unused, 57 struct tee_ta_param *param, 58 TEE_Param tee_param[TEE_NUM_PARAMS], 59 bool did_map[TEE_NUM_PARAMS]) 60 { 61 size_t n; 62 void *va; 63 struct param_mem *mem; 64 65 for (n = 0; n < TEE_NUM_PARAMS; n++) { 66 switch (TEE_PARAM_TYPE_GET(param->types, n)) { 67 case TEE_PARAM_TYPE_VALUE_INPUT: 68 case TEE_PARAM_TYPE_VALUE_OUTPUT: 69 case TEE_PARAM_TYPE_VALUE_INOUT: 70 tee_param[n].value.a = param->u[n].val.a; 71 tee_param[n].value.b = param->u[n].val.b; 72 break; 73 case TEE_PARAM_TYPE_MEMREF_INPUT: 74 case TEE_PARAM_TYPE_MEMREF_OUTPUT: 75 case TEE_PARAM_TYPE_MEMREF_INOUT: 76 mem = ¶m->u[n].mem; 77 if (!validate_in_param(s, mem->mobj)) 78 return TEE_ERROR_BAD_PARAMETERS; 79 if (mem->size) { 80 TEE_Result res = mobj_inc_map(mem->mobj); 81 82 if (res) 83 return res; 84 did_map[n] = true; 85 va = mobj_get_va(mem->mobj, mem->offs, 86 mem->size); 87 if (!va) 88 return TEE_ERROR_BAD_PARAMETERS; 89 } else { 90 va = NULL; 91 } 92 93 tee_param[n].memref.buffer = va; 94 tee_param[n].memref.size = mem->size; 95 break; 96 default: 97 memset(tee_param + n, 0, sizeof(TEE_Param)); 98 break; 99 } 100 } 101 102 return TEE_SUCCESS; 103 } 104 105 static void update_out_param(TEE_Param tee_param[TEE_NUM_PARAMS], 106 struct tee_ta_param *param) 107 { 108 size_t n; 109 110 for (n = 0; n < TEE_NUM_PARAMS; n++) { 111 switch (TEE_PARAM_TYPE_GET(param->types, n)) { 112 case TEE_PARAM_TYPE_VALUE_OUTPUT: 113 case TEE_PARAM_TYPE_VALUE_INOUT: 114 param->u[n].val.a = tee_param[n].value.a; 115 param->u[n].val.b = tee_param[n].value.b; 116 break; 117 case TEE_PARAM_TYPE_MEMREF_OUTPUT: 118 case TEE_PARAM_TYPE_MEMREF_INOUT: 119 param->u[n].mem.size = tee_param[n].memref.size; 120 break; 121 default: 122 break; 123 } 124 } 125 } 126 127 static void unmap_mapped_param(struct tee_ta_param *param, 128 bool did_map[TEE_NUM_PARAMS]) 129 { 130 size_t n; 131 132 for (n = 0; n < TEE_NUM_PARAMS; n++) { 133 if (did_map[n]) { 134 TEE_Result res __maybe_unused; 135 136 res = mobj_dec_map(param->u[n].mem.mobj); 137 assert(!res); 138 } 139 } 140 } 141 142 static TEE_Result pseudo_ta_enter_open_session(struct ts_session *s) 143 { 144 TEE_Result res = TEE_SUCCESS; 145 struct pseudo_ta_ctx *stc = to_pseudo_ta_ctx(s->ctx); 146 struct tee_ta_session *ta_sess = to_ta_session(s); 147 TEE_Param tee_param[TEE_NUM_PARAMS] = { }; 148 bool did_map[TEE_NUM_PARAMS] = { false }; 149 150 ts_push_current_session(s); 151 ta_sess->err_origin = TEE_ORIGIN_TRUSTED_APP; 152 153 if (stc->ctx.ref_count == 1 && stc->pseudo_ta->create_entry_point) { 154 res = stc->pseudo_ta->create_entry_point(); 155 if (res != TEE_SUCCESS) 156 goto out; 157 } 158 159 if (stc->pseudo_ta->open_session_entry_point) { 160 void **user_ctx = &s->user_ctx; 161 uint32_t param_types = 0; 162 163 if (ta_sess->param) { 164 res = copy_in_param(s, ta_sess->param, tee_param, 165 did_map); 166 if (res != TEE_SUCCESS) { 167 unmap_mapped_param(ta_sess->param, did_map); 168 ta_sess->err_origin = TEE_ORIGIN_TEE; 169 goto out; 170 } 171 param_types = ta_sess->param->types; 172 } 173 174 res = stc->pseudo_ta->open_session_entry_point(param_types, 175 tee_param, 176 user_ctx); 177 if (ta_sess->param) { 178 update_out_param(tee_param, ta_sess->param); 179 unmap_mapped_param(ta_sess->param, did_map); 180 } 181 } 182 183 out: 184 ts_pop_current_session(); 185 return res; 186 } 187 188 static TEE_Result pseudo_ta_enter_invoke_cmd(struct ts_session *s, uint32_t cmd) 189 { 190 TEE_Result res = TEE_SUCCESS; 191 struct pseudo_ta_ctx *stc = to_pseudo_ta_ctx(s->ctx); 192 struct tee_ta_session *ta_sess = to_ta_session(s); 193 uint32_t param_types = 0; 194 TEE_Param tee_param[TEE_NUM_PARAMS] = { }; 195 bool did_map[TEE_NUM_PARAMS] = { false }; 196 197 ts_push_current_session(s); 198 if (ta_sess->param) { 199 res = copy_in_param(s, ta_sess->param, tee_param, did_map); 200 if (res != TEE_SUCCESS) { 201 unmap_mapped_param(ta_sess->param, did_map); 202 ta_sess->err_origin = TEE_ORIGIN_TEE; 203 goto out; 204 } 205 param_types = ta_sess->param->types; 206 } 207 208 ta_sess->err_origin = TEE_ORIGIN_TRUSTED_APP; 209 res = stc->pseudo_ta->invoke_command_entry_point(s->user_ctx, cmd, 210 param_types, 211 tee_param); 212 if (ta_sess->param) { 213 update_out_param(tee_param, ta_sess->param); 214 unmap_mapped_param(ta_sess->param, did_map); 215 } 216 out: 217 ts_pop_current_session(); 218 return res; 219 } 220 221 static void pseudo_ta_enter_close_session(struct ts_session *s) 222 { 223 struct pseudo_ta_ctx *stc = to_pseudo_ta_ctx(s->ctx); 224 void *user_ctx = s->user_ctx; 225 226 ts_push_current_session(s); 227 228 if (stc->pseudo_ta->close_session_entry_point) 229 stc->pseudo_ta->close_session_entry_point(user_ctx); 230 231 if (stc->ctx.ref_count == 1 && stc->pseudo_ta->destroy_entry_point) 232 stc->pseudo_ta->destroy_entry_point(); 233 234 ts_pop_current_session(); 235 } 236 237 static void pseudo_ta_destroy(struct ts_ctx *ctx) 238 { 239 free(to_pseudo_ta_ctx(ctx)); 240 } 241 242 static const struct ts_ops pseudo_ta_ops = { 243 .enter_open_session = pseudo_ta_enter_open_session, 244 .enter_invoke_cmd = pseudo_ta_enter_invoke_cmd, 245 .enter_close_session = pseudo_ta_enter_close_session, 246 .destroy = pseudo_ta_destroy, 247 }; 248 249 bool is_pseudo_ta_ctx(struct ts_ctx *ctx) 250 { 251 return ctx->ops == &pseudo_ta_ops; 252 } 253 254 /* Insures declared pseudo TAs conforms with core expectations */ 255 static TEE_Result verify_pseudo_tas_conformance(void) 256 { 257 const struct pseudo_ta_head *start = 258 SCATTERED_ARRAY_BEGIN(pseudo_tas, struct pseudo_ta_head); 259 const struct pseudo_ta_head *end = 260 SCATTERED_ARRAY_END(pseudo_tas, struct pseudo_ta_head); 261 const struct pseudo_ta_head *pta; 262 263 for (pta = start; pta < end; pta++) { 264 const struct pseudo_ta_head *pta2; 265 266 /* PTAs must all have a specific UUID */ 267 for (pta2 = pta + 1; pta2 < end; pta2++) { 268 if (!memcmp(&pta->uuid, &pta2->uuid, sizeof(TEE_UUID))) 269 goto err; 270 } 271 272 if (!pta->name || 273 (pta->flags & PTA_MANDATORY_FLAGS) != PTA_MANDATORY_FLAGS || 274 pta->flags & ~PTA_ALLOWED_FLAGS || 275 !pta->invoke_command_entry_point) 276 goto err; 277 } 278 return TEE_SUCCESS; 279 err: 280 DMSG("pseudo TA error at %p", (void *)pta); 281 panic("PTA"); 282 } 283 284 service_init(verify_pseudo_tas_conformance); 285 286 /*----------------------------------------------------------------------------- 287 * Initialises a session based on the UUID or ptr to the ta 288 * Returns ptr to the session (ta_session) and a TEE_Result 289 *---------------------------------------------------------------------------*/ 290 TEE_Result tee_ta_init_pseudo_ta_session(const TEE_UUID *uuid, 291 struct tee_ta_session *s) 292 { 293 struct pseudo_ta_ctx *stc = NULL; 294 struct tee_ta_ctx *ctx; 295 const struct pseudo_ta_head *ta; 296 297 DMSG("Lookup pseudo TA %pUl", (void *)uuid); 298 299 ta = SCATTERED_ARRAY_BEGIN(pseudo_tas, struct pseudo_ta_head); 300 while (true) { 301 if (ta >= SCATTERED_ARRAY_END(pseudo_tas, 302 struct pseudo_ta_head)) 303 return TEE_ERROR_ITEM_NOT_FOUND; 304 if (memcmp(&ta->uuid, uuid, sizeof(TEE_UUID)) == 0) 305 break; 306 ta++; 307 } 308 309 /* Load a new TA and create a session */ 310 DMSG("Open %s", ta->name); 311 stc = calloc(1, sizeof(struct pseudo_ta_ctx)); 312 if (!stc) 313 return TEE_ERROR_OUT_OF_MEMORY; 314 ctx = &stc->ctx; 315 316 ctx->ref_count = 1; 317 ctx->flags = ta->flags; 318 stc->pseudo_ta = ta; 319 ctx->ts_ctx.uuid = ta->uuid; 320 ctx->ts_ctx.ops = &pseudo_ta_ops; 321 322 mutex_lock(&tee_ta_mutex); 323 s->ts_sess.ctx = &ctx->ts_ctx; 324 TAILQ_INSERT_TAIL(&tee_ctxes, ctx, link); 325 mutex_unlock(&tee_ta_mutex); 326 327 DMSG("%s : %pUl", stc->pseudo_ta->name, (void *)&ctx->ts_ctx.uuid); 328 329 return TEE_SUCCESS; 330 } 331 332 TEE_Result to_bounce_params(uint32_t param_types, 333 TEE_Param params[TEE_NUM_PARAMS], 334 TEE_Param bparams[TEE_NUM_PARAMS], 335 TEE_Param **oparams) 336 { 337 TEE_Result res = TEE_ERROR_GENERIC; 338 void *kptr = NULL; 339 void *uptr = NULL; 340 size_t size = 0; 341 int i = 0; 342 343 if (!is_caller_ta_with_pan()) { 344 *oparams = params; 345 return TEE_SUCCESS; 346 } 347 348 for (i = 0; i < TEE_NUM_PARAMS; i++) { 349 switch (TEE_PARAM_TYPE_GET(param_types, i)) { 350 case TEE_PARAM_TYPE_MEMREF_INPUT: 351 case TEE_PARAM_TYPE_MEMREF_OUTPUT: 352 case TEE_PARAM_TYPE_MEMREF_INOUT: 353 size = params[i].memref.size; 354 uptr = params[i].memref.buffer; 355 kptr = bb_alloc(size); 356 if (!kptr) 357 return TEE_ERROR_OUT_OF_MEMORY; 358 bparams[i].memref.buffer = kptr; 359 bparams[i].memref.size = size; 360 break; 361 default: 362 break; 363 } 364 switch (TEE_PARAM_TYPE_GET(param_types, i)) { 365 case TEE_PARAM_TYPE_MEMREF_INPUT: 366 case TEE_PARAM_TYPE_MEMREF_INOUT: 367 res = copy_from_user(kptr, uptr, size); 368 if (res) 369 return res; 370 break; 371 case TEE_PARAM_TYPE_VALUE_INPUT: 372 case TEE_PARAM_TYPE_VALUE_INOUT: 373 bparams[i].value.a = params[i].value.a; 374 bparams[i].value.b = params[i].value.b; 375 break; 376 default: 377 break; 378 } 379 } 380 *oparams = bparams; 381 382 return TEE_SUCCESS; 383 } 384 385 TEE_Result from_bounce_params(uint32_t param_types, 386 TEE_Param params[TEE_NUM_PARAMS], 387 TEE_Param bparams[TEE_NUM_PARAMS], 388 TEE_Param *eparams) 389 { 390 TEE_Result res = TEE_ERROR_GENERIC; 391 void *kptr = NULL; 392 void *uptr = NULL; 393 size_t size = 0; 394 int i = 0; 395 396 if (eparams == params) 397 return TEE_SUCCESS; 398 399 for (i = 0; i < TEE_NUM_PARAMS; i++) { 400 switch (TEE_PARAM_TYPE_GET(param_types, i)) { 401 case TEE_PARAM_TYPE_MEMREF_OUTPUT: 402 case TEE_PARAM_TYPE_MEMREF_INOUT: 403 uptr = params[i].memref.buffer; 404 kptr = bparams[i].memref.buffer; 405 size = bparams[i].memref.size; 406 res = copy_to_user(uptr, kptr, size); 407 if (res) 408 return res; 409 params[i].memref.size = size; 410 break; 411 case TEE_PARAM_TYPE_VALUE_OUTPUT: 412 case TEE_PARAM_TYPE_VALUE_INOUT: 413 params[i].value.a = bparams[i].value.a; 414 params[i].value.b = bparams[i].value.b; 415 break; 416 default: 417 break; 418 } 419 } 420 421 return res; 422 } 423