125c76675SMarouene Boubakri // SPDX-License-Identifier: BSD-2-Clause 225c76675SMarouene Boubakri /* 325c76675SMarouene Boubakri * Copyright (c) 2015-2016, Linaro Limited 425c76675SMarouene Boubakri * Copyright (c) 2014, STMicroelectronics International N.V. 525c76675SMarouene Boubakri */ 625c76675SMarouene Boubakri 725c76675SMarouene Boubakri #include <assert.h> 825c76675SMarouene Boubakri #include <bench.h> 925c76675SMarouene Boubakri #include <compiler.h> 1025c76675SMarouene Boubakri #include <initcall.h> 1125c76675SMarouene Boubakri #include <io.h> 1225c76675SMarouene Boubakri #include <kernel/linker.h> 1325c76675SMarouene Boubakri #include <kernel/msg_param.h> 1425c76675SMarouene Boubakri #include <kernel/panic.h> 1525c76675SMarouene Boubakri #include <kernel/tee_misc.h> 1625c76675SMarouene Boubakri #include <mm/core_memprot.h> 1725c76675SMarouene Boubakri #include <mm/core_mmu.h> 1825c76675SMarouene Boubakri #include <mm/mobj.h> 1925c76675SMarouene Boubakri #include <optee_msg.h> 2025c76675SMarouene Boubakri #include <sm/optee_smc.h> 2125c76675SMarouene Boubakri #include <string.h> 2225c76675SMarouene Boubakri #include <tee/entry_std.h> 2325c76675SMarouene Boubakri #include <tee/tee_cryp_utl.h> 2425c76675SMarouene Boubakri #include <tee/uuid.h> 2525c76675SMarouene Boubakri #include <util.h> 2625c76675SMarouene Boubakri 2725c76675SMarouene Boubakri #define SHM_CACHE_ATTRS \ 2825c76675SMarouene Boubakri (uint32_t)(core_mmu_is_shm_cached() ? OPTEE_SMC_SHM_CACHED : 0) 2925c76675SMarouene Boubakri 3025c76675SMarouene Boubakri /* Sessions opened from normal world */ 3125c76675SMarouene Boubakri static struct tee_ta_session_head tee_open_sessions = 3225c76675SMarouene Boubakri TAILQ_HEAD_INITIALIZER(tee_open_sessions); 3325c76675SMarouene Boubakri 3425c76675SMarouene Boubakri #ifdef CFG_CORE_RESERVED_SHM 3525c76675SMarouene Boubakri static struct mobj *shm_mobj; 3625c76675SMarouene Boubakri #endif 3725c76675SMarouene Boubakri #ifdef CFG_SECURE_DATA_PATH 3825c76675SMarouene Boubakri static struct mobj **sdp_mem_mobjs; 3925c76675SMarouene Boubakri #endif 4025c76675SMarouene Boubakri 4125c76675SMarouene Boubakri static unsigned int session_pnum; 4225c76675SMarouene Boubakri 4325c76675SMarouene Boubakri static bool __maybe_unused param_mem_from_mobj(struct param_mem *mem, 4425c76675SMarouene Boubakri struct mobj *mobj, 4525c76675SMarouene Boubakri const paddr_t pa, 4625c76675SMarouene Boubakri const size_t sz) 4725c76675SMarouene Boubakri { 4825c76675SMarouene Boubakri paddr_t b; 4925c76675SMarouene Boubakri 5025c76675SMarouene Boubakri if (mobj_get_pa(mobj, 0, 0, &b) != TEE_SUCCESS) 5125c76675SMarouene Boubakri panic("mobj_get_pa failed"); 5225c76675SMarouene Boubakri 5325c76675SMarouene Boubakri if (!core_is_buffer_inside(pa, MAX(sz, 1UL), b, mobj->size)) 5425c76675SMarouene Boubakri return false; 5525c76675SMarouene Boubakri 5625c76675SMarouene Boubakri mem->mobj = mobj_get(mobj); 5725c76675SMarouene Boubakri mem->offs = pa - b; 5825c76675SMarouene Boubakri mem->size = sz; 5925c76675SMarouene Boubakri return true; 6025c76675SMarouene Boubakri } 6125c76675SMarouene Boubakri 6225c76675SMarouene Boubakri #ifdef CFG_CORE_FFA 6325c76675SMarouene Boubakri static TEE_Result set_fmem_param(const struct optee_msg_param_fmem *fmem, 6425c76675SMarouene Boubakri struct param_mem *mem) 6525c76675SMarouene Boubakri { 6625c76675SMarouene Boubakri size_t req_size = 0; 6725c76675SMarouene Boubakri uint64_t global_id = READ_ONCE(fmem->global_id); 6825c76675SMarouene Boubakri size_t sz = READ_ONCE(fmem->size); 6925c76675SMarouene Boubakri 70*c1bdf4fcSJens Wiklander if (global_id == OPTEE_MSG_FMEM_INVALID_GLOBAL_ID && !sz) { 7125c76675SMarouene Boubakri mem->mobj = NULL; 7225c76675SMarouene Boubakri mem->offs = 0; 7325c76675SMarouene Boubakri mem->size = 0; 7425c76675SMarouene Boubakri return TEE_SUCCESS; 7525c76675SMarouene Boubakri } 7625c76675SMarouene Boubakri mem->mobj = mobj_ffa_get_by_cookie(global_id, 7725c76675SMarouene Boubakri READ_ONCE(fmem->internal_offs)); 7825c76675SMarouene Boubakri if (!mem->mobj) 7925c76675SMarouene Boubakri return TEE_ERROR_BAD_PARAMETERS; 8025c76675SMarouene Boubakri 8125c76675SMarouene Boubakri mem->offs = reg_pair_to_64(READ_ONCE(fmem->offs_high), 8225c76675SMarouene Boubakri READ_ONCE(fmem->offs_low)); 8325c76675SMarouene Boubakri mem->size = sz; 8425c76675SMarouene Boubakri 8525c76675SMarouene Boubakri /* 8625c76675SMarouene Boubakri * Check that the supplied offset and size is covered by the 8725c76675SMarouene Boubakri * previously verified MOBJ. 8825c76675SMarouene Boubakri */ 8925c76675SMarouene Boubakri if (ADD_OVERFLOW(mem->offs, mem->size, &req_size) || 9025c76675SMarouene Boubakri mem->mobj->size < req_size) 9125c76675SMarouene Boubakri return TEE_ERROR_SECURITY; 9225c76675SMarouene Boubakri 9325c76675SMarouene Boubakri return TEE_SUCCESS; 9425c76675SMarouene Boubakri } 9525c76675SMarouene Boubakri #else /*!CFG_CORE_FFA*/ 9625c76675SMarouene Boubakri /* fill 'struct param_mem' structure if buffer matches a valid memory object */ 9725c76675SMarouene Boubakri static TEE_Result set_tmem_param(const struct optee_msg_param_tmem *tmem, 9825c76675SMarouene Boubakri uint32_t attr, struct param_mem *mem) 9925c76675SMarouene Boubakri { 10025c76675SMarouene Boubakri struct mobj __maybe_unused **mobj; 10125c76675SMarouene Boubakri paddr_t pa = READ_ONCE(tmem->buf_ptr); 10225c76675SMarouene Boubakri size_t sz = READ_ONCE(tmem->size); 10325c76675SMarouene Boubakri 10425c76675SMarouene Boubakri /* 10525c76675SMarouene Boubakri * Handle NULL memory reference 10625c76675SMarouene Boubakri */ 10725c76675SMarouene Boubakri if (!pa) { 10825c76675SMarouene Boubakri mem->mobj = NULL; 10925c76675SMarouene Boubakri mem->offs = 0; 11025c76675SMarouene Boubakri mem->size = 0; 11125c76675SMarouene Boubakri return TEE_SUCCESS; 11225c76675SMarouene Boubakri } 11325c76675SMarouene Boubakri 11425c76675SMarouene Boubakri /* Handle non-contiguous reference from a shared memory area */ 11525c76675SMarouene Boubakri if (attr & OPTEE_MSG_ATTR_NONCONTIG) { 11625c76675SMarouene Boubakri uint64_t shm_ref = READ_ONCE(tmem->shm_ref); 11725c76675SMarouene Boubakri 11825c76675SMarouene Boubakri mem->mobj = msg_param_mobj_from_noncontig(pa, sz, shm_ref, 11925c76675SMarouene Boubakri false); 12025c76675SMarouene Boubakri if (!mem->mobj) 12125c76675SMarouene Boubakri return TEE_ERROR_BAD_PARAMETERS; 12225c76675SMarouene Boubakri mem->offs = 0; 12325c76675SMarouene Boubakri mem->size = sz; 12425c76675SMarouene Boubakri return TEE_SUCCESS; 12525c76675SMarouene Boubakri } 12625c76675SMarouene Boubakri 12725c76675SMarouene Boubakri #ifdef CFG_CORE_RESERVED_SHM 12825c76675SMarouene Boubakri /* Handle memory reference in the contiguous shared memory */ 12925c76675SMarouene Boubakri if (param_mem_from_mobj(mem, shm_mobj, pa, sz)) 13025c76675SMarouene Boubakri return TEE_SUCCESS; 13125c76675SMarouene Boubakri #endif 13225c76675SMarouene Boubakri 13325c76675SMarouene Boubakri #ifdef CFG_SECURE_DATA_PATH 13425c76675SMarouene Boubakri /* Handle memory reference to Secure Data Path memory areas */ 13525c76675SMarouene Boubakri for (mobj = sdp_mem_mobjs; *mobj; mobj++) 13625c76675SMarouene Boubakri if (param_mem_from_mobj(mem, *mobj, pa, sz)) 13725c76675SMarouene Boubakri return TEE_SUCCESS; 13825c76675SMarouene Boubakri #endif 13925c76675SMarouene Boubakri 14025c76675SMarouene Boubakri return TEE_ERROR_BAD_PARAMETERS; 14125c76675SMarouene Boubakri } 14225c76675SMarouene Boubakri 14325c76675SMarouene Boubakri #ifdef CFG_CORE_DYN_SHM 14425c76675SMarouene Boubakri static TEE_Result set_rmem_param(const struct optee_msg_param_rmem *rmem, 14525c76675SMarouene Boubakri struct param_mem *mem) 14625c76675SMarouene Boubakri { 14725c76675SMarouene Boubakri size_t req_size = 0; 14825c76675SMarouene Boubakri uint64_t shm_ref = READ_ONCE(rmem->shm_ref); 14925c76675SMarouene Boubakri size_t sz = READ_ONCE(rmem->size); 15025c76675SMarouene Boubakri 15125c76675SMarouene Boubakri mem->mobj = mobj_reg_shm_get_by_cookie(shm_ref); 15225c76675SMarouene Boubakri if (!mem->mobj) 15325c76675SMarouene Boubakri return TEE_ERROR_BAD_PARAMETERS; 15425c76675SMarouene Boubakri 15525c76675SMarouene Boubakri mem->offs = READ_ONCE(rmem->offs); 15625c76675SMarouene Boubakri mem->size = sz; 15725c76675SMarouene Boubakri 15825c76675SMarouene Boubakri /* 15925c76675SMarouene Boubakri * Check that the supplied offset and size is covered by the 16025c76675SMarouene Boubakri * previously verified MOBJ. 16125c76675SMarouene Boubakri */ 16225c76675SMarouene Boubakri if (ADD_OVERFLOW(mem->offs, mem->size, &req_size) || 16325c76675SMarouene Boubakri mem->mobj->size < req_size) 16425c76675SMarouene Boubakri return TEE_ERROR_SECURITY; 16525c76675SMarouene Boubakri 16625c76675SMarouene Boubakri return TEE_SUCCESS; 16725c76675SMarouene Boubakri } 16825c76675SMarouene Boubakri #endif /*CFG_CORE_DYN_SHM*/ 16925c76675SMarouene Boubakri #endif /*!CFG_CORE_FFA*/ 17025c76675SMarouene Boubakri 17125c76675SMarouene Boubakri static TEE_Result copy_in_params(const struct optee_msg_param *params, 17225c76675SMarouene Boubakri uint32_t num_params, 17325c76675SMarouene Boubakri struct tee_ta_param *ta_param, 17425c76675SMarouene Boubakri uint64_t *saved_attr) 17525c76675SMarouene Boubakri { 17625c76675SMarouene Boubakri TEE_Result res; 17725c76675SMarouene Boubakri size_t n; 17825c76675SMarouene Boubakri uint8_t pt[TEE_NUM_PARAMS] = { 0 }; 17925c76675SMarouene Boubakri 18025c76675SMarouene Boubakri if (num_params > TEE_NUM_PARAMS) 18125c76675SMarouene Boubakri return TEE_ERROR_BAD_PARAMETERS; 18225c76675SMarouene Boubakri 18325c76675SMarouene Boubakri memset(ta_param, 0, sizeof(*ta_param)); 18425c76675SMarouene Boubakri 18525c76675SMarouene Boubakri for (n = 0; n < num_params; n++) { 18625c76675SMarouene Boubakri uint32_t attr; 18725c76675SMarouene Boubakri 18825c76675SMarouene Boubakri saved_attr[n] = READ_ONCE(params[n].attr); 18925c76675SMarouene Boubakri 19025c76675SMarouene Boubakri if (saved_attr[n] & OPTEE_MSG_ATTR_META) 19125c76675SMarouene Boubakri return TEE_ERROR_BAD_PARAMETERS; 19225c76675SMarouene Boubakri 19325c76675SMarouene Boubakri attr = saved_attr[n] & OPTEE_MSG_ATTR_TYPE_MASK; 19425c76675SMarouene Boubakri switch (attr) { 19525c76675SMarouene Boubakri case OPTEE_MSG_ATTR_TYPE_NONE: 19625c76675SMarouene Boubakri pt[n] = TEE_PARAM_TYPE_NONE; 19725c76675SMarouene Boubakri break; 19825c76675SMarouene Boubakri case OPTEE_MSG_ATTR_TYPE_VALUE_INPUT: 19925c76675SMarouene Boubakri case OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT: 20025c76675SMarouene Boubakri case OPTEE_MSG_ATTR_TYPE_VALUE_INOUT: 20125c76675SMarouene Boubakri pt[n] = TEE_PARAM_TYPE_VALUE_INPUT + attr - 20225c76675SMarouene Boubakri OPTEE_MSG_ATTR_TYPE_VALUE_INPUT; 20325c76675SMarouene Boubakri ta_param->u[n].val.a = READ_ONCE(params[n].u.value.a); 20425c76675SMarouene Boubakri ta_param->u[n].val.b = READ_ONCE(params[n].u.value.b); 20525c76675SMarouene Boubakri break; 20625c76675SMarouene Boubakri #ifdef CFG_CORE_FFA 20725c76675SMarouene Boubakri case OPTEE_MSG_ATTR_TYPE_FMEM_INPUT: 20825c76675SMarouene Boubakri case OPTEE_MSG_ATTR_TYPE_FMEM_OUTPUT: 20925c76675SMarouene Boubakri case OPTEE_MSG_ATTR_TYPE_FMEM_INOUT: 21025c76675SMarouene Boubakri res = set_fmem_param(¶ms[n].u.fmem, 21125c76675SMarouene Boubakri &ta_param->u[n].mem); 21225c76675SMarouene Boubakri if (res) 21325c76675SMarouene Boubakri return res; 21425c76675SMarouene Boubakri pt[n] = TEE_PARAM_TYPE_MEMREF_INPUT + attr - 21525c76675SMarouene Boubakri OPTEE_MSG_ATTR_TYPE_FMEM_INPUT; 21625c76675SMarouene Boubakri break; 21725c76675SMarouene Boubakri #else /*!CFG_CORE_FFA*/ 21825c76675SMarouene Boubakri case OPTEE_MSG_ATTR_TYPE_TMEM_INPUT: 21925c76675SMarouene Boubakri case OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT: 22025c76675SMarouene Boubakri case OPTEE_MSG_ATTR_TYPE_TMEM_INOUT: 22125c76675SMarouene Boubakri res = set_tmem_param(¶ms[n].u.tmem, saved_attr[n], 22225c76675SMarouene Boubakri &ta_param->u[n].mem); 22325c76675SMarouene Boubakri if (res) 22425c76675SMarouene Boubakri return res; 22525c76675SMarouene Boubakri pt[n] = TEE_PARAM_TYPE_MEMREF_INPUT + attr - 22625c76675SMarouene Boubakri OPTEE_MSG_ATTR_TYPE_TMEM_INPUT; 22725c76675SMarouene Boubakri break; 22825c76675SMarouene Boubakri #ifdef CFG_CORE_DYN_SHM 22925c76675SMarouene Boubakri case OPTEE_MSG_ATTR_TYPE_RMEM_INPUT: 23025c76675SMarouene Boubakri case OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT: 23125c76675SMarouene Boubakri case OPTEE_MSG_ATTR_TYPE_RMEM_INOUT: 23225c76675SMarouene Boubakri res = set_rmem_param(¶ms[n].u.rmem, 23325c76675SMarouene Boubakri &ta_param->u[n].mem); 23425c76675SMarouene Boubakri if (res) 23525c76675SMarouene Boubakri return res; 23625c76675SMarouene Boubakri pt[n] = TEE_PARAM_TYPE_MEMREF_INPUT + attr - 23725c76675SMarouene Boubakri OPTEE_MSG_ATTR_TYPE_RMEM_INPUT; 23825c76675SMarouene Boubakri break; 23925c76675SMarouene Boubakri #endif /*CFG_CORE_DYN_SHM*/ 24025c76675SMarouene Boubakri #endif /*!CFG_CORE_FFA*/ 24125c76675SMarouene Boubakri default: 24225c76675SMarouene Boubakri return TEE_ERROR_BAD_PARAMETERS; 24325c76675SMarouene Boubakri } 24425c76675SMarouene Boubakri } 24525c76675SMarouene Boubakri 24625c76675SMarouene Boubakri ta_param->types = TEE_PARAM_TYPES(pt[0], pt[1], pt[2], pt[3]); 24725c76675SMarouene Boubakri 24825c76675SMarouene Boubakri return TEE_SUCCESS; 24925c76675SMarouene Boubakri } 25025c76675SMarouene Boubakri 25125c76675SMarouene Boubakri static void cleanup_shm_refs(const uint64_t *saved_attr, 25225c76675SMarouene Boubakri struct tee_ta_param *param, uint32_t num_params) 25325c76675SMarouene Boubakri { 25425c76675SMarouene Boubakri size_t n; 25525c76675SMarouene Boubakri 25625c76675SMarouene Boubakri for (n = 0; n < num_params; n++) { 25725c76675SMarouene Boubakri switch (saved_attr[n]) { 25825c76675SMarouene Boubakri case OPTEE_MSG_ATTR_TYPE_TMEM_INPUT: 25925c76675SMarouene Boubakri case OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT: 26025c76675SMarouene Boubakri case OPTEE_MSG_ATTR_TYPE_TMEM_INOUT: 26125c76675SMarouene Boubakri #ifdef CFG_CORE_DYN_SHM 26225c76675SMarouene Boubakri case OPTEE_MSG_ATTR_TYPE_RMEM_INPUT: 26325c76675SMarouene Boubakri case OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT: 26425c76675SMarouene Boubakri case OPTEE_MSG_ATTR_TYPE_RMEM_INOUT: 26525c76675SMarouene Boubakri #endif 26625c76675SMarouene Boubakri mobj_put(param->u[n].mem.mobj); 26725c76675SMarouene Boubakri break; 26825c76675SMarouene Boubakri default: 26925c76675SMarouene Boubakri break; 27025c76675SMarouene Boubakri } 27125c76675SMarouene Boubakri } 27225c76675SMarouene Boubakri } 27325c76675SMarouene Boubakri 27425c76675SMarouene Boubakri static void copy_out_param(struct tee_ta_param *ta_param, uint32_t num_params, 27525c76675SMarouene Boubakri struct optee_msg_param *params, uint64_t *saved_attr) 27625c76675SMarouene Boubakri { 27725c76675SMarouene Boubakri size_t n; 27825c76675SMarouene Boubakri 27925c76675SMarouene Boubakri for (n = 0; n < num_params; n++) { 28025c76675SMarouene Boubakri switch (TEE_PARAM_TYPE_GET(ta_param->types, n)) { 28125c76675SMarouene Boubakri case TEE_PARAM_TYPE_MEMREF_OUTPUT: 28225c76675SMarouene Boubakri case TEE_PARAM_TYPE_MEMREF_INOUT: 28325c76675SMarouene Boubakri switch (saved_attr[n] & OPTEE_MSG_ATTR_TYPE_MASK) { 28425c76675SMarouene Boubakri case OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT: 28525c76675SMarouene Boubakri case OPTEE_MSG_ATTR_TYPE_TMEM_INOUT: 28625c76675SMarouene Boubakri params[n].u.tmem.size = ta_param->u[n].mem.size; 28725c76675SMarouene Boubakri break; 28825c76675SMarouene Boubakri case OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT: 28925c76675SMarouene Boubakri case OPTEE_MSG_ATTR_TYPE_RMEM_INOUT: 29025c76675SMarouene Boubakri params[n].u.rmem.size = ta_param->u[n].mem.size; 29125c76675SMarouene Boubakri break; 29225c76675SMarouene Boubakri default: 29325c76675SMarouene Boubakri break; 29425c76675SMarouene Boubakri } 29525c76675SMarouene Boubakri break; 29625c76675SMarouene Boubakri case TEE_PARAM_TYPE_VALUE_OUTPUT: 29725c76675SMarouene Boubakri case TEE_PARAM_TYPE_VALUE_INOUT: 29825c76675SMarouene Boubakri params[n].u.value.a = ta_param->u[n].val.a; 29925c76675SMarouene Boubakri params[n].u.value.b = ta_param->u[n].val.b; 30025c76675SMarouene Boubakri break; 30125c76675SMarouene Boubakri default: 30225c76675SMarouene Boubakri break; 30325c76675SMarouene Boubakri } 30425c76675SMarouene Boubakri } 30525c76675SMarouene Boubakri } 30625c76675SMarouene Boubakri 30725c76675SMarouene Boubakri /* 30825c76675SMarouene Boubakri * Extracts mandatory parameter for open session. 30925c76675SMarouene Boubakri * 31025c76675SMarouene Boubakri * Returns 31125c76675SMarouene Boubakri * false : mandatory parameter wasn't found or malformatted 31225c76675SMarouene Boubakri * true : paramater found and OK 31325c76675SMarouene Boubakri */ 31425c76675SMarouene Boubakri static TEE_Result get_open_session_meta(size_t num_params, 31525c76675SMarouene Boubakri struct optee_msg_param *params, 31625c76675SMarouene Boubakri size_t *num_meta, TEE_UUID *uuid, 31725c76675SMarouene Boubakri TEE_Identity *clnt_id) 31825c76675SMarouene Boubakri { 31925c76675SMarouene Boubakri const uint32_t req_attr = OPTEE_MSG_ATTR_META | 32025c76675SMarouene Boubakri OPTEE_MSG_ATTR_TYPE_VALUE_INPUT; 32125c76675SMarouene Boubakri 32225c76675SMarouene Boubakri if (num_params < 2) 32325c76675SMarouene Boubakri return TEE_ERROR_BAD_PARAMETERS; 32425c76675SMarouene Boubakri 32525c76675SMarouene Boubakri if (params[0].attr != req_attr || params[1].attr != req_attr) 32625c76675SMarouene Boubakri return TEE_ERROR_BAD_PARAMETERS; 32725c76675SMarouene Boubakri 32825c76675SMarouene Boubakri tee_uuid_from_octets(uuid, (void *)¶ms[0].u.value); 32925c76675SMarouene Boubakri clnt_id->login = params[1].u.value.c; 33025c76675SMarouene Boubakri switch (clnt_id->login) { 33125c76675SMarouene Boubakri case TEE_LOGIN_PUBLIC: 33225c76675SMarouene Boubakri case TEE_LOGIN_REE_KERNEL: 33325c76675SMarouene Boubakri memset(&clnt_id->uuid, 0, sizeof(clnt_id->uuid)); 33425c76675SMarouene Boubakri break; 33525c76675SMarouene Boubakri case TEE_LOGIN_USER: 33625c76675SMarouene Boubakri case TEE_LOGIN_GROUP: 33725c76675SMarouene Boubakri case TEE_LOGIN_APPLICATION: 33825c76675SMarouene Boubakri case TEE_LOGIN_APPLICATION_USER: 33925c76675SMarouene Boubakri case TEE_LOGIN_APPLICATION_GROUP: 34025c76675SMarouene Boubakri tee_uuid_from_octets(&clnt_id->uuid, 34125c76675SMarouene Boubakri (void *)¶ms[1].u.value); 34225c76675SMarouene Boubakri break; 34325c76675SMarouene Boubakri default: 34425c76675SMarouene Boubakri return TEE_ERROR_BAD_PARAMETERS; 34525c76675SMarouene Boubakri } 34625c76675SMarouene Boubakri 34725c76675SMarouene Boubakri *num_meta = 2; 34825c76675SMarouene Boubakri return TEE_SUCCESS; 34925c76675SMarouene Boubakri } 35025c76675SMarouene Boubakri 35125c76675SMarouene Boubakri static void entry_open_session(struct optee_msg_arg *arg, uint32_t num_params) 35225c76675SMarouene Boubakri { 35325c76675SMarouene Boubakri TEE_Result res; 35425c76675SMarouene Boubakri TEE_ErrorOrigin err_orig = TEE_ORIGIN_TEE; 35525c76675SMarouene Boubakri struct tee_ta_session *s = NULL; 35625c76675SMarouene Boubakri TEE_Identity clnt_id; 35725c76675SMarouene Boubakri TEE_UUID uuid; 35825c76675SMarouene Boubakri struct tee_ta_param param; 35925c76675SMarouene Boubakri size_t num_meta; 36025c76675SMarouene Boubakri uint64_t saved_attr[TEE_NUM_PARAMS] = { 0 }; 36125c76675SMarouene Boubakri 36225c76675SMarouene Boubakri res = get_open_session_meta(num_params, arg->params, &num_meta, &uuid, 36325c76675SMarouene Boubakri &clnt_id); 36425c76675SMarouene Boubakri if (res != TEE_SUCCESS) 36525c76675SMarouene Boubakri goto out; 36625c76675SMarouene Boubakri 36725c76675SMarouene Boubakri res = copy_in_params(arg->params + num_meta, num_params - num_meta, 36825c76675SMarouene Boubakri ¶m, saved_attr); 36925c76675SMarouene Boubakri if (res != TEE_SUCCESS) 37025c76675SMarouene Boubakri goto cleanup_shm_refs; 37125c76675SMarouene Boubakri 37225c76675SMarouene Boubakri res = tee_ta_open_session(&err_orig, &s, &tee_open_sessions, &uuid, 37325c76675SMarouene Boubakri &clnt_id, TEE_TIMEOUT_INFINITE, ¶m); 37425c76675SMarouene Boubakri if (res != TEE_SUCCESS) 37525c76675SMarouene Boubakri s = NULL; 37625c76675SMarouene Boubakri copy_out_param(¶m, num_params - num_meta, arg->params + num_meta, 37725c76675SMarouene Boubakri saved_attr); 37825c76675SMarouene Boubakri 37925c76675SMarouene Boubakri /* 38025c76675SMarouene Boubakri * The occurrence of open/close session command is usually 38125c76675SMarouene Boubakri * un-predictable, using this property to increase randomness 38225c76675SMarouene Boubakri * of prng 38325c76675SMarouene Boubakri */ 38425c76675SMarouene Boubakri plat_prng_add_jitter_entropy(CRYPTO_RNG_SRC_JITTER_SESSION, 38525c76675SMarouene Boubakri &session_pnum); 38625c76675SMarouene Boubakri 38725c76675SMarouene Boubakri cleanup_shm_refs: 38825c76675SMarouene Boubakri cleanup_shm_refs(saved_attr, ¶m, num_params - num_meta); 38925c76675SMarouene Boubakri 39025c76675SMarouene Boubakri out: 39125c76675SMarouene Boubakri if (s) 39225c76675SMarouene Boubakri arg->session = s->id; 39325c76675SMarouene Boubakri else 39425c76675SMarouene Boubakri arg->session = 0; 39525c76675SMarouene Boubakri arg->ret = res; 39625c76675SMarouene Boubakri arg->ret_origin = err_orig; 39725c76675SMarouene Boubakri } 39825c76675SMarouene Boubakri 39925c76675SMarouene Boubakri static void entry_close_session(struct optee_msg_arg *arg, uint32_t num_params) 40025c76675SMarouene Boubakri { 40125c76675SMarouene Boubakri TEE_Result res; 40225c76675SMarouene Boubakri struct tee_ta_session *s; 40325c76675SMarouene Boubakri 40425c76675SMarouene Boubakri if (num_params) { 40525c76675SMarouene Boubakri res = TEE_ERROR_BAD_PARAMETERS; 40625c76675SMarouene Boubakri goto out; 40725c76675SMarouene Boubakri } 40825c76675SMarouene Boubakri 40925c76675SMarouene Boubakri plat_prng_add_jitter_entropy(CRYPTO_RNG_SRC_JITTER_SESSION, 41025c76675SMarouene Boubakri &session_pnum); 41125c76675SMarouene Boubakri 41225c76675SMarouene Boubakri s = tee_ta_find_session(arg->session, &tee_open_sessions); 41325c76675SMarouene Boubakri res = tee_ta_close_session(s, &tee_open_sessions, NSAPP_IDENTITY); 41425c76675SMarouene Boubakri out: 41525c76675SMarouene Boubakri arg->ret = res; 41625c76675SMarouene Boubakri arg->ret_origin = TEE_ORIGIN_TEE; 41725c76675SMarouene Boubakri } 41825c76675SMarouene Boubakri 41925c76675SMarouene Boubakri static void entry_invoke_command(struct optee_msg_arg *arg, uint32_t num_params) 42025c76675SMarouene Boubakri { 42125c76675SMarouene Boubakri TEE_Result res; 42225c76675SMarouene Boubakri TEE_ErrorOrigin err_orig = TEE_ORIGIN_TEE; 42325c76675SMarouene Boubakri struct tee_ta_session *s; 42425c76675SMarouene Boubakri struct tee_ta_param param = { 0 }; 42525c76675SMarouene Boubakri uint64_t saved_attr[TEE_NUM_PARAMS] = { 0 }; 42625c76675SMarouene Boubakri 42725c76675SMarouene Boubakri bm_timestamp(); 42825c76675SMarouene Boubakri 42925c76675SMarouene Boubakri res = copy_in_params(arg->params, num_params, ¶m, saved_attr); 43025c76675SMarouene Boubakri if (res != TEE_SUCCESS) 43125c76675SMarouene Boubakri goto out; 43225c76675SMarouene Boubakri 43325c76675SMarouene Boubakri s = tee_ta_get_session(arg->session, true, &tee_open_sessions); 43425c76675SMarouene Boubakri if (!s) { 43525c76675SMarouene Boubakri res = TEE_ERROR_BAD_PARAMETERS; 43625c76675SMarouene Boubakri goto out; 43725c76675SMarouene Boubakri } 43825c76675SMarouene Boubakri 43925c76675SMarouene Boubakri res = tee_ta_invoke_command(&err_orig, s, NSAPP_IDENTITY, 44025c76675SMarouene Boubakri TEE_TIMEOUT_INFINITE, arg->func, ¶m); 44125c76675SMarouene Boubakri 44225c76675SMarouene Boubakri bm_timestamp(); 44325c76675SMarouene Boubakri 44425c76675SMarouene Boubakri tee_ta_put_session(s); 44525c76675SMarouene Boubakri 44625c76675SMarouene Boubakri copy_out_param(¶m, num_params, arg->params, saved_attr); 44725c76675SMarouene Boubakri 44825c76675SMarouene Boubakri out: 44925c76675SMarouene Boubakri cleanup_shm_refs(saved_attr, ¶m, num_params); 45025c76675SMarouene Boubakri 45125c76675SMarouene Boubakri arg->ret = res; 45225c76675SMarouene Boubakri arg->ret_origin = err_orig; 45325c76675SMarouene Boubakri } 45425c76675SMarouene Boubakri 45525c76675SMarouene Boubakri static void entry_cancel(struct optee_msg_arg *arg, uint32_t num_params) 45625c76675SMarouene Boubakri { 45725c76675SMarouene Boubakri TEE_Result res; 45825c76675SMarouene Boubakri TEE_ErrorOrigin err_orig = TEE_ORIGIN_TEE; 45925c76675SMarouene Boubakri struct tee_ta_session *s; 46025c76675SMarouene Boubakri 46125c76675SMarouene Boubakri if (num_params) { 46225c76675SMarouene Boubakri res = TEE_ERROR_BAD_PARAMETERS; 46325c76675SMarouene Boubakri goto out; 46425c76675SMarouene Boubakri } 46525c76675SMarouene Boubakri 46625c76675SMarouene Boubakri s = tee_ta_get_session(arg->session, false, &tee_open_sessions); 46725c76675SMarouene Boubakri if (!s) { 46825c76675SMarouene Boubakri res = TEE_ERROR_BAD_PARAMETERS; 46925c76675SMarouene Boubakri goto out; 47025c76675SMarouene Boubakri } 47125c76675SMarouene Boubakri 47225c76675SMarouene Boubakri res = tee_ta_cancel_command(&err_orig, s, NSAPP_IDENTITY); 47325c76675SMarouene Boubakri tee_ta_put_session(s); 47425c76675SMarouene Boubakri 47525c76675SMarouene Boubakri out: 47625c76675SMarouene Boubakri arg->ret = res; 47725c76675SMarouene Boubakri arg->ret_origin = err_orig; 47825c76675SMarouene Boubakri } 47925c76675SMarouene Boubakri 48025c76675SMarouene Boubakri #ifndef CFG_CORE_FFA 48125c76675SMarouene Boubakri #ifdef CFG_CORE_DYN_SHM 48225c76675SMarouene Boubakri static void register_shm(struct optee_msg_arg *arg, uint32_t num_params) 48325c76675SMarouene Boubakri { 48425c76675SMarouene Boubakri arg->ret = TEE_ERROR_BAD_PARAMETERS; 48525c76675SMarouene Boubakri 48625c76675SMarouene Boubakri if (num_params != 1 || 48725c76675SMarouene Boubakri (arg->params[0].attr != 48825c76675SMarouene Boubakri (OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT | OPTEE_MSG_ATTR_NONCONTIG))) 48925c76675SMarouene Boubakri return; 49025c76675SMarouene Boubakri 49125c76675SMarouene Boubakri struct optee_msg_param_tmem *tmem = &arg->params[0].u.tmem; 49225c76675SMarouene Boubakri struct mobj *mobj = msg_param_mobj_from_noncontig(tmem->buf_ptr, 49325c76675SMarouene Boubakri tmem->size, 49425c76675SMarouene Boubakri tmem->shm_ref, false); 49525c76675SMarouene Boubakri 49625c76675SMarouene Boubakri if (!mobj) 49725c76675SMarouene Boubakri return; 49825c76675SMarouene Boubakri 49925c76675SMarouene Boubakri mobj_reg_shm_unguard(mobj); 50025c76675SMarouene Boubakri arg->ret = TEE_SUCCESS; 50125c76675SMarouene Boubakri } 50225c76675SMarouene Boubakri 50325c76675SMarouene Boubakri static void unregister_shm(struct optee_msg_arg *arg, uint32_t num_params) 50425c76675SMarouene Boubakri { 50525c76675SMarouene Boubakri if (num_params == 1) { 50625c76675SMarouene Boubakri uint64_t cookie = arg->params[0].u.rmem.shm_ref; 50725c76675SMarouene Boubakri TEE_Result res = mobj_reg_shm_release_by_cookie(cookie); 50825c76675SMarouene Boubakri 50925c76675SMarouene Boubakri if (res) 51025c76675SMarouene Boubakri EMSG("Can't find mapping with given cookie"); 51125c76675SMarouene Boubakri arg->ret = res; 51225c76675SMarouene Boubakri } else { 51325c76675SMarouene Boubakri arg->ret = TEE_ERROR_BAD_PARAMETERS; 51425c76675SMarouene Boubakri arg->ret_origin = TEE_ORIGIN_TEE; 51525c76675SMarouene Boubakri } 51625c76675SMarouene Boubakri } 51725c76675SMarouene Boubakri #endif /*CFG_CORE_DYN_SHM*/ 51825c76675SMarouene Boubakri #endif 51925c76675SMarouene Boubakri 52025c76675SMarouene Boubakri void nsec_sessions_list_head(struct tee_ta_session_head **open_sessions) 52125c76675SMarouene Boubakri { 52225c76675SMarouene Boubakri *open_sessions = &tee_open_sessions; 52325c76675SMarouene Boubakri } 52425c76675SMarouene Boubakri 52525c76675SMarouene Boubakri /* Note: this function is weak to let platforms add special handling */ 52625c76675SMarouene Boubakri uint32_t __weak tee_entry_std(struct optee_msg_arg *arg, uint32_t num_params) 52725c76675SMarouene Boubakri { 52825c76675SMarouene Boubakri return __tee_entry_std(arg, num_params); 52925c76675SMarouene Boubakri } 53025c76675SMarouene Boubakri 53125c76675SMarouene Boubakri /* 53225c76675SMarouene Boubakri * If tee_entry_std() is overridden, it's still supposed to call this 53325c76675SMarouene Boubakri * function. 53425c76675SMarouene Boubakri */ 53525c76675SMarouene Boubakri uint32_t __tee_entry_std(struct optee_msg_arg *arg, uint32_t num_params) 53625c76675SMarouene Boubakri { 53725c76675SMarouene Boubakri uint32_t rv = OPTEE_SMC_RETURN_OK; 53825c76675SMarouene Boubakri 53925c76675SMarouene Boubakri /* Enable foreign interrupts for STD calls */ 54025c76675SMarouene Boubakri thread_set_foreign_intr(true); 54125c76675SMarouene Boubakri switch (arg->cmd) { 54225c76675SMarouene Boubakri case OPTEE_MSG_CMD_OPEN_SESSION: 54325c76675SMarouene Boubakri entry_open_session(arg, num_params); 54425c76675SMarouene Boubakri break; 54525c76675SMarouene Boubakri case OPTEE_MSG_CMD_CLOSE_SESSION: 54625c76675SMarouene Boubakri entry_close_session(arg, num_params); 54725c76675SMarouene Boubakri break; 54825c76675SMarouene Boubakri case OPTEE_MSG_CMD_INVOKE_COMMAND: 54925c76675SMarouene Boubakri entry_invoke_command(arg, num_params); 55025c76675SMarouene Boubakri break; 55125c76675SMarouene Boubakri case OPTEE_MSG_CMD_CANCEL: 55225c76675SMarouene Boubakri entry_cancel(arg, num_params); 55325c76675SMarouene Boubakri break; 55425c76675SMarouene Boubakri #ifndef CFG_CORE_FFA 55525c76675SMarouene Boubakri #ifdef CFG_CORE_DYN_SHM 55625c76675SMarouene Boubakri case OPTEE_MSG_CMD_REGISTER_SHM: 55725c76675SMarouene Boubakri register_shm(arg, num_params); 55825c76675SMarouene Boubakri break; 55925c76675SMarouene Boubakri case OPTEE_MSG_CMD_UNREGISTER_SHM: 56025c76675SMarouene Boubakri unregister_shm(arg, num_params); 56125c76675SMarouene Boubakri break; 56225c76675SMarouene Boubakri #endif 56325c76675SMarouene Boubakri #endif 56425c76675SMarouene Boubakri default: 56525c76675SMarouene Boubakri EMSG("Unknown cmd 0x%x", arg->cmd); 56625c76675SMarouene Boubakri rv = OPTEE_SMC_RETURN_EBADCMD; 56725c76675SMarouene Boubakri } 56825c76675SMarouene Boubakri 56925c76675SMarouene Boubakri return rv; 57025c76675SMarouene Boubakri } 57125c76675SMarouene Boubakri 57225c76675SMarouene Boubakri static TEE_Result default_mobj_init(void) 57325c76675SMarouene Boubakri { 57425c76675SMarouene Boubakri #ifdef CFG_CORE_RESERVED_SHM 57525c76675SMarouene Boubakri shm_mobj = mobj_phys_alloc(default_nsec_shm_paddr, 57625c76675SMarouene Boubakri default_nsec_shm_size, SHM_CACHE_ATTRS, 57725c76675SMarouene Boubakri CORE_MEM_NSEC_SHM); 57825c76675SMarouene Boubakri if (!shm_mobj) 57925c76675SMarouene Boubakri panic("Failed to register shared memory"); 58025c76675SMarouene Boubakri #endif 58125c76675SMarouene Boubakri 58225c76675SMarouene Boubakri #ifdef CFG_SECURE_DATA_PATH 58325c76675SMarouene Boubakri sdp_mem_mobjs = core_sdp_mem_create_mobjs(); 58425c76675SMarouene Boubakri if (!sdp_mem_mobjs) 58525c76675SMarouene Boubakri panic("Failed to register SDP memory"); 58625c76675SMarouene Boubakri #endif 58725c76675SMarouene Boubakri 58825c76675SMarouene Boubakri return TEE_SUCCESS; 58925c76675SMarouene Boubakri } 59025c76675SMarouene Boubakri 59125c76675SMarouene Boubakri driver_init_late(default_mobj_init); 592