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