16e9e277fSJerome Forissier // SPDX-License-Identifier: BSD-2-Clause 26e9e277fSJerome Forissier /* 36e9e277fSJerome Forissier * Copyright (c) 2016-2017, Linaro Limited 46e9e277fSJerome Forissier */ 56e9e277fSJerome Forissier 66e9e277fSJerome Forissier #include <assert.h> 76e9e277fSJerome Forissier #include <mm/mobj.h> 86e9e277fSJerome Forissier #include <kernel/pseudo_ta.h> 96e9e277fSJerome Forissier #include <optee_rpc_cmd.h> 106e9e277fSJerome Forissier #include <pta_socket.h> 116e9e277fSJerome Forissier #include <string.h> 126e9e277fSJerome Forissier #include <tee/tee_fs_rpc.h> 136e9e277fSJerome Forissier 1400b3b9a2SJens Wiklander static uint32_t get_instance_id(struct ts_session *sess) 156e9e277fSJerome Forissier { 166e9e277fSJerome Forissier return sess->ctx->ops->get_instance_id(sess->ctx); 176e9e277fSJerome Forissier } 186e9e277fSJerome Forissier 196e9e277fSJerome Forissier static TEE_Result socket_open(uint32_t instance_id, uint32_t param_types, 206e9e277fSJerome Forissier TEE_Param params[TEE_NUM_PARAMS]) 216e9e277fSJerome Forissier { 22*7c94d5d6SJens Wiklander struct thread_param tpm[4] = { }; 23*7c94d5d6SJens Wiklander struct mobj *mobj = NULL; 24*7c94d5d6SJens Wiklander TEE_Result res = TEE_SUCCESS; 25*7c94d5d6SJens Wiklander void *va = NULL; 266e9e277fSJerome Forissier uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 276e9e277fSJerome Forissier TEE_PARAM_TYPE_MEMREF_INPUT, 286e9e277fSJerome Forissier TEE_PARAM_TYPE_VALUE_INPUT, 296e9e277fSJerome Forissier TEE_PARAM_TYPE_VALUE_OUTPUT); 306e9e277fSJerome Forissier 316e9e277fSJerome Forissier if (exp_pt != param_types) { 326e9e277fSJerome Forissier DMSG("got param_types 0x%x, expected 0x%x", 336e9e277fSJerome Forissier param_types, exp_pt); 346e9e277fSJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 356e9e277fSJerome Forissier } 366e9e277fSJerome Forissier 371a7d8eaeSJens Wiklander va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_SOCKET, 381a7d8eaeSJens Wiklander THREAD_SHM_TYPE_APPLICATION, 399bee8f2aSJens Wiklander params[1].memref.size, &mobj); 406e9e277fSJerome Forissier if (!va) 416e9e277fSJerome Forissier return TEE_ERROR_OUT_OF_MEMORY; 426e9e277fSJerome Forissier 436e9e277fSJerome Forissier memcpy(va, params[1].memref.buffer, params[1].memref.size); 446e9e277fSJerome Forissier 45*7c94d5d6SJens Wiklander tpm[0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SOCKET_OPEN, instance_id, 0); 46*7c94d5d6SJens Wiklander tpm[1] = THREAD_PARAM_VALUE(IN, 476e9e277fSJerome Forissier params[0].value.b, /* server port number */ 486e9e277fSJerome Forissier params[2].value.a, /* protocol */ 49*7c94d5d6SJens Wiklander params[0].value.a /* ip version */); 50*7c94d5d6SJens Wiklander tpm[2] = THREAD_PARAM_MEMREF(IN, mobj, 0, params[1].memref.size); 51*7c94d5d6SJens Wiklander tpm[3] = THREAD_PARAM_VALUE(OUT, 0, 0, 0); 526e9e277fSJerome Forissier 536e9e277fSJerome Forissier res = thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 4, tpm); 546e9e277fSJerome Forissier if (res == TEE_SUCCESS) 556e9e277fSJerome Forissier params[3].value.a = tpm[3].u.value.a; 566e9e277fSJerome Forissier 576e9e277fSJerome Forissier return res; 586e9e277fSJerome Forissier } 596e9e277fSJerome Forissier 606e9e277fSJerome Forissier static TEE_Result socket_close(uint32_t instance_id, uint32_t param_types, 616e9e277fSJerome Forissier TEE_Param params[TEE_NUM_PARAMS]) 626e9e277fSJerome Forissier { 63*7c94d5d6SJens Wiklander struct thread_param tpm = { }; 646e9e277fSJerome Forissier uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 656e9e277fSJerome Forissier TEE_PARAM_TYPE_NONE, 666e9e277fSJerome Forissier TEE_PARAM_TYPE_NONE, 676e9e277fSJerome Forissier TEE_PARAM_TYPE_NONE); 686e9e277fSJerome Forissier 696e9e277fSJerome Forissier if (exp_pt != param_types) { 706e9e277fSJerome Forissier DMSG("got param_types 0x%x, expected 0x%x", 716e9e277fSJerome Forissier param_types, exp_pt); 726e9e277fSJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 736e9e277fSJerome Forissier } 746e9e277fSJerome Forissier 75*7c94d5d6SJens Wiklander tpm = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SOCKET_CLOSE, instance_id, 766e9e277fSJerome Forissier params[0].value.a); 776e9e277fSJerome Forissier 786e9e277fSJerome Forissier return thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 1, &tpm); 796e9e277fSJerome Forissier } 806e9e277fSJerome Forissier 816e9e277fSJerome Forissier static TEE_Result socket_send(uint32_t instance_id, uint32_t param_types, 826e9e277fSJerome Forissier TEE_Param params[TEE_NUM_PARAMS]) 836e9e277fSJerome Forissier { 84*7c94d5d6SJens Wiklander struct thread_param tpm[3] = { }; 85*7c94d5d6SJens Wiklander struct mobj *mobj = NULL; 86*7c94d5d6SJens Wiklander TEE_Result res = TEE_SUCCESS; 87*7c94d5d6SJens Wiklander void *va = NULL; 886e9e277fSJerome Forissier uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 896e9e277fSJerome Forissier TEE_PARAM_TYPE_MEMREF_INPUT, 906e9e277fSJerome Forissier TEE_PARAM_TYPE_VALUE_OUTPUT, 916e9e277fSJerome Forissier TEE_PARAM_TYPE_NONE); 926e9e277fSJerome Forissier 936e9e277fSJerome Forissier if (exp_pt != param_types) { 946e9e277fSJerome Forissier DMSG("got param_types 0x%x, expected 0x%x", 956e9e277fSJerome Forissier param_types, exp_pt); 966e9e277fSJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 976e9e277fSJerome Forissier } 986e9e277fSJerome Forissier 991a7d8eaeSJens Wiklander va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_SOCKET, 1001a7d8eaeSJens Wiklander THREAD_SHM_TYPE_APPLICATION, 1019bee8f2aSJens Wiklander params[1].memref.size, &mobj); 1026e9e277fSJerome Forissier if (!va) 1036e9e277fSJerome Forissier return TEE_ERROR_OUT_OF_MEMORY; 1046e9e277fSJerome Forissier 1056e9e277fSJerome Forissier memcpy(va, params[1].memref.buffer, params[1].memref.size); 1066e9e277fSJerome Forissier 107*7c94d5d6SJens Wiklander tpm[0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SOCKET_SEND, instance_id, 108*7c94d5d6SJens Wiklander params[0].value.a /* handle */); 109*7c94d5d6SJens Wiklander tpm[1] = THREAD_PARAM_MEMREF(IN, mobj, 0, params[1].memref.size); 110*7c94d5d6SJens Wiklander tpm[2] = THREAD_PARAM_VALUE(INOUT, params[0].value.b, /* timeout */ 111*7c94d5d6SJens Wiklander 0, 0); 1126e9e277fSJerome Forissier 1136e9e277fSJerome Forissier res = thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 3, tpm); 1146e9e277fSJerome Forissier params[2].value.a = tpm[2].u.value.b; /* transmitted bytes */ 1156e9e277fSJerome Forissier 1166e9e277fSJerome Forissier return res; 1176e9e277fSJerome Forissier } 1186e9e277fSJerome Forissier 1196e9e277fSJerome Forissier static TEE_Result socket_recv(uint32_t instance_id, uint32_t param_types, 1206e9e277fSJerome Forissier TEE_Param params[TEE_NUM_PARAMS]) 1216e9e277fSJerome Forissier { 122*7c94d5d6SJens Wiklander struct thread_param tpm[3] = { }; 123e9907fd7SJens Wiklander struct mobj *mobj = NULL; 124e9907fd7SJens Wiklander TEE_Result res = TEE_SUCCESS; 125e9907fd7SJens Wiklander void *va = NULL; 1266e9e277fSJerome Forissier uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 1276e9e277fSJerome Forissier TEE_PARAM_TYPE_MEMREF_OUTPUT, 1286e9e277fSJerome Forissier TEE_PARAM_TYPE_NONE, 1296e9e277fSJerome Forissier TEE_PARAM_TYPE_NONE); 1306e9e277fSJerome Forissier 1316e9e277fSJerome Forissier if (exp_pt != param_types) { 1326e9e277fSJerome Forissier DMSG("got param_types 0x%x, expected 0x%x", 1336e9e277fSJerome Forissier param_types, exp_pt); 1346e9e277fSJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 1356e9e277fSJerome Forissier } 1366e9e277fSJerome Forissier 137e9907fd7SJens Wiklander if (params[1].memref.size) { 1381a7d8eaeSJens Wiklander va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_SOCKET, 1391a7d8eaeSJens Wiklander THREAD_SHM_TYPE_APPLICATION, 1409bee8f2aSJens Wiklander params[1].memref.size, &mobj); 1416e9e277fSJerome Forissier if (!va) 1426e9e277fSJerome Forissier return TEE_ERROR_OUT_OF_MEMORY; 143e9907fd7SJens Wiklander } 1446e9e277fSJerome Forissier 145*7c94d5d6SJens Wiklander tpm[0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SOCKET_RECV, instance_id, 146*7c94d5d6SJens Wiklander params[0].value.a /* handle */); 147*7c94d5d6SJens Wiklander tpm[1] = THREAD_PARAM_MEMREF(OUT, mobj, 0, params[1].memref.size); 148*7c94d5d6SJens Wiklander tpm[2] = THREAD_PARAM_VALUE(IN, params[0].value.b /* timeout */, 0, 0); 1496e9e277fSJerome Forissier 1506e9e277fSJerome Forissier res = thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 3, tpm); 1516e9e277fSJerome Forissier 1526e9e277fSJerome Forissier if (params[1].memref.size) 153e9907fd7SJens Wiklander memcpy(params[1].memref.buffer, va, 154e9907fd7SJens Wiklander MIN(params[1].memref.size, tpm[1].u.memref.size)); 155e9907fd7SJens Wiklander params[1].memref.size = tpm[1].u.memref.size; 1566e9e277fSJerome Forissier 1576e9e277fSJerome Forissier return res; 1586e9e277fSJerome Forissier } 1596e9e277fSJerome Forissier 1606e9e277fSJerome Forissier static TEE_Result socket_ioctl(uint32_t instance_id, uint32_t param_types, 1616e9e277fSJerome Forissier TEE_Param params[TEE_NUM_PARAMS]) 1626e9e277fSJerome Forissier { 163*7c94d5d6SJens Wiklander struct thread_param tpm[3] = { }; 164*7c94d5d6SJens Wiklander struct mobj *mobj = NULL; 165*7c94d5d6SJens Wiklander TEE_Result res = TEE_SUCCESS; 166*7c94d5d6SJens Wiklander void *va = NULL; 1676e9e277fSJerome Forissier uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 1686e9e277fSJerome Forissier TEE_PARAM_TYPE_MEMREF_INOUT, 1696e9e277fSJerome Forissier TEE_PARAM_TYPE_NONE, 1706e9e277fSJerome Forissier TEE_PARAM_TYPE_NONE); 1716e9e277fSJerome Forissier 1726e9e277fSJerome Forissier if (exp_pt != param_types) { 1736e9e277fSJerome Forissier DMSG("got param_types 0x%x, expected 0x%x", 1746e9e277fSJerome Forissier param_types, exp_pt); 1756e9e277fSJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 1766e9e277fSJerome Forissier } 1776e9e277fSJerome Forissier 1781a7d8eaeSJens Wiklander va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_SOCKET, 1791a7d8eaeSJens Wiklander THREAD_SHM_TYPE_APPLICATION, 1809bee8f2aSJens Wiklander params[1].memref.size, &mobj); 1816e9e277fSJerome Forissier if (!va) 1826e9e277fSJerome Forissier return TEE_ERROR_OUT_OF_MEMORY; 1836e9e277fSJerome Forissier 1846e9e277fSJerome Forissier memcpy(va, params[1].memref.buffer, params[1].memref.size); 1856e9e277fSJerome Forissier 186*7c94d5d6SJens Wiklander tpm[0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SOCKET_IOCTL, instance_id, 187*7c94d5d6SJens Wiklander params[0].value.a /* handle */); 188*7c94d5d6SJens Wiklander tpm[1] = THREAD_PARAM_MEMREF(INOUT, mobj, 0, params[1].memref.size); 189*7c94d5d6SJens Wiklander tpm[2] = THREAD_PARAM_VALUE(IN, params[0].value.b /* ioctl command */, 190*7c94d5d6SJens Wiklander 0, 0); 1916e9e277fSJerome Forissier 1926e9e277fSJerome Forissier res = thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 3, tpm); 1936e9e277fSJerome Forissier if (tpm[1].u.memref.size <= params[1].memref.size) 1946e9e277fSJerome Forissier memcpy(params[1].memref.buffer, va, tpm[1].u.memref.size); 1956e9e277fSJerome Forissier 1966e9e277fSJerome Forissier params[1].memref.size = tpm[1].u.memref.size; 1976e9e277fSJerome Forissier 1986e9e277fSJerome Forissier return res; 1996e9e277fSJerome Forissier } 2006e9e277fSJerome Forissier 2016e9e277fSJerome Forissier typedef TEE_Result (*ta_func)(uint32_t instance_id, uint32_t param_types, 2026e9e277fSJerome Forissier TEE_Param params[TEE_NUM_PARAMS]); 2036e9e277fSJerome Forissier 2046e9e277fSJerome Forissier static const ta_func ta_funcs[] = { 2056e9e277fSJerome Forissier [PTA_SOCKET_OPEN] = socket_open, 2066e9e277fSJerome Forissier [PTA_SOCKET_CLOSE] = socket_close, 2076e9e277fSJerome Forissier [PTA_SOCKET_SEND] = socket_send, 2086e9e277fSJerome Forissier [PTA_SOCKET_RECV] = socket_recv, 2096e9e277fSJerome Forissier [PTA_SOCKET_IOCTL] = socket_ioctl, 2106e9e277fSJerome Forissier }; 2116e9e277fSJerome Forissier 2126e9e277fSJerome Forissier /* 2136e9e277fSJerome Forissier * Trusted Application Entry Points 2146e9e277fSJerome Forissier */ 2156e9e277fSJerome Forissier 2166e9e277fSJerome Forissier static TEE_Result pta_socket_open_session(uint32_t param_types __unused, 2176e9e277fSJerome Forissier TEE_Param pParams[TEE_NUM_PARAMS] __unused, 2186e9e277fSJerome Forissier void **sess_ctx) 2196e9e277fSJerome Forissier { 22000b3b9a2SJens Wiklander struct ts_session *s = ts_get_calling_session(); 2216e9e277fSJerome Forissier 2226e9e277fSJerome Forissier /* Check that we're called from a TA */ 22300b3b9a2SJens Wiklander if (!s || !is_user_ta_ctx(s->ctx)) 2246e9e277fSJerome Forissier return TEE_ERROR_ACCESS_DENIED; 2256e9e277fSJerome Forissier 2266e9e277fSJerome Forissier *sess_ctx = (void *)(vaddr_t)get_instance_id(s); 2276e9e277fSJerome Forissier 2286e9e277fSJerome Forissier return TEE_SUCCESS; 2296e9e277fSJerome Forissier } 2306e9e277fSJerome Forissier 2316e9e277fSJerome Forissier static void pta_socket_close_session(void *sess_ctx) 2326e9e277fSJerome Forissier { 2336e9e277fSJerome Forissier TEE_Result res; 2346e9e277fSJerome Forissier struct thread_param tpm = { 2356e9e277fSJerome Forissier .attr = THREAD_PARAM_ATTR_VALUE_IN, .u.value = { 2366e9e277fSJerome Forissier .a = OPTEE_RPC_SOCKET_CLOSE_ALL, .b = (vaddr_t)sess_ctx, 2376e9e277fSJerome Forissier }, 2386e9e277fSJerome Forissier }; 2396e9e277fSJerome Forissier 2406e9e277fSJerome Forissier res = thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 1, &tpm); 2416e9e277fSJerome Forissier if (res != TEE_SUCCESS) 2426e9e277fSJerome Forissier DMSG("OPTEE_RPC_SOCKET_CLOSE_ALL failed: %#" PRIx32, res); 2436e9e277fSJerome Forissier } 2446e9e277fSJerome Forissier 2456e9e277fSJerome Forissier static TEE_Result pta_socket_invoke_command(void *sess_ctx, uint32_t cmd_id, 2466e9e277fSJerome Forissier uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) 2476e9e277fSJerome Forissier { 2486e9e277fSJerome Forissier if (cmd_id < ARRAY_SIZE(ta_funcs) && ta_funcs[cmd_id]) 2496e9e277fSJerome Forissier return ta_funcs[cmd_id]((vaddr_t)sess_ctx, param_types, params); 2506e9e277fSJerome Forissier 2516e9e277fSJerome Forissier return TEE_ERROR_NOT_IMPLEMENTED; 2526e9e277fSJerome Forissier } 2536e9e277fSJerome Forissier 2546e9e277fSJerome Forissier pseudo_ta_register(.uuid = PTA_SOCKET_UUID, .name = "socket", 2556e9e277fSJerome Forissier .flags = PTA_DEFAULT_FLAGS | TA_FLAG_CONCURRENT, 2566e9e277fSJerome Forissier .open_session_entry_point = pta_socket_open_session, 2576e9e277fSJerome Forissier .close_session_entry_point = pta_socket_close_session, 2586e9e277fSJerome Forissier .invoke_command_entry_point = pta_socket_invoke_command); 259