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 146e9e277fSJerome Forissier static uint32_t get_instance_id(struct tee_ta_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 { 226e9e277fSJerome Forissier struct mobj *mobj; 236e9e277fSJerome Forissier TEE_Result res; 246e9e277fSJerome Forissier void *va; 256e9e277fSJerome Forissier uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 266e9e277fSJerome Forissier TEE_PARAM_TYPE_MEMREF_INPUT, 276e9e277fSJerome Forissier TEE_PARAM_TYPE_VALUE_INPUT, 286e9e277fSJerome Forissier TEE_PARAM_TYPE_VALUE_OUTPUT); 296e9e277fSJerome Forissier 306e9e277fSJerome Forissier if (exp_pt != param_types) { 316e9e277fSJerome Forissier DMSG("got param_types 0x%x, expected 0x%x", 326e9e277fSJerome Forissier param_types, exp_pt); 336e9e277fSJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 346e9e277fSJerome Forissier } 356e9e277fSJerome Forissier 36*1a7d8eaeSJens Wiklander va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_SOCKET, 37*1a7d8eaeSJens Wiklander THREAD_SHM_TYPE_APPLICATION, 389bee8f2aSJens Wiklander params[1].memref.size, &mobj); 396e9e277fSJerome Forissier if (!va) 406e9e277fSJerome Forissier return TEE_ERROR_OUT_OF_MEMORY; 416e9e277fSJerome Forissier 426e9e277fSJerome Forissier memcpy(va, params[1].memref.buffer, params[1].memref.size); 436e9e277fSJerome Forissier 446e9e277fSJerome Forissier struct thread_param tpm[4] = { 456e9e277fSJerome Forissier [0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SOCKET_OPEN, 466e9e277fSJerome Forissier instance_id, 0), 476e9e277fSJerome Forissier [1] = THREAD_PARAM_VALUE(IN, 486e9e277fSJerome Forissier params[0].value.b, /* server port number */ 496e9e277fSJerome Forissier params[2].value.a, /* protocol */ 506e9e277fSJerome Forissier params[0].value.a /* ip version */), 516e9e277fSJerome Forissier [2] = THREAD_PARAM_MEMREF(IN, mobj, 0, params[1].memref.size), 526e9e277fSJerome Forissier [3] = THREAD_PARAM_VALUE(OUT, 0, 0, 0), 536e9e277fSJerome Forissier }; 546e9e277fSJerome Forissier 556e9e277fSJerome Forissier res = thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 4, tpm); 566e9e277fSJerome Forissier if (res == TEE_SUCCESS) 576e9e277fSJerome Forissier params[3].value.a = tpm[3].u.value.a; 586e9e277fSJerome Forissier 596e9e277fSJerome Forissier return res; 606e9e277fSJerome Forissier } 616e9e277fSJerome Forissier 626e9e277fSJerome Forissier static TEE_Result socket_close(uint32_t instance_id, uint32_t param_types, 636e9e277fSJerome Forissier TEE_Param params[TEE_NUM_PARAMS]) 646e9e277fSJerome Forissier { 656e9e277fSJerome Forissier uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 666e9e277fSJerome Forissier TEE_PARAM_TYPE_NONE, 676e9e277fSJerome Forissier TEE_PARAM_TYPE_NONE, 686e9e277fSJerome Forissier TEE_PARAM_TYPE_NONE); 696e9e277fSJerome Forissier 706e9e277fSJerome Forissier if (exp_pt != param_types) { 716e9e277fSJerome Forissier DMSG("got param_types 0x%x, expected 0x%x", 726e9e277fSJerome Forissier param_types, exp_pt); 736e9e277fSJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 746e9e277fSJerome Forissier } 756e9e277fSJerome Forissier 766e9e277fSJerome Forissier struct thread_param tpm = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SOCKET_CLOSE, 776e9e277fSJerome Forissier instance_id, 786e9e277fSJerome Forissier params[0].value.a); 796e9e277fSJerome Forissier 806e9e277fSJerome Forissier return thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 1, &tpm); 816e9e277fSJerome Forissier } 826e9e277fSJerome Forissier 836e9e277fSJerome Forissier static TEE_Result socket_send(uint32_t instance_id, uint32_t param_types, 846e9e277fSJerome Forissier TEE_Param params[TEE_NUM_PARAMS]) 856e9e277fSJerome Forissier { 866e9e277fSJerome Forissier struct mobj *mobj; 876e9e277fSJerome Forissier TEE_Result res; 886e9e277fSJerome Forissier void *va; 896e9e277fSJerome Forissier uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 906e9e277fSJerome Forissier TEE_PARAM_TYPE_MEMREF_INPUT, 916e9e277fSJerome Forissier TEE_PARAM_TYPE_VALUE_OUTPUT, 926e9e277fSJerome Forissier TEE_PARAM_TYPE_NONE); 936e9e277fSJerome Forissier 946e9e277fSJerome Forissier if (exp_pt != param_types) { 956e9e277fSJerome Forissier DMSG("got param_types 0x%x, expected 0x%x", 966e9e277fSJerome Forissier param_types, exp_pt); 976e9e277fSJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 986e9e277fSJerome Forissier } 996e9e277fSJerome Forissier 100*1a7d8eaeSJens Wiklander va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_SOCKET, 101*1a7d8eaeSJens Wiklander THREAD_SHM_TYPE_APPLICATION, 1029bee8f2aSJens Wiklander params[1].memref.size, &mobj); 1036e9e277fSJerome Forissier if (!va) 1046e9e277fSJerome Forissier return TEE_ERROR_OUT_OF_MEMORY; 1056e9e277fSJerome Forissier 1066e9e277fSJerome Forissier memcpy(va, params[1].memref.buffer, params[1].memref.size); 1076e9e277fSJerome Forissier 1086e9e277fSJerome Forissier struct thread_param tpm[3] = { 1096e9e277fSJerome Forissier [0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SOCKET_SEND, instance_id, 1106e9e277fSJerome Forissier params[0].value.a /* handle */), 1116e9e277fSJerome Forissier [1] = THREAD_PARAM_MEMREF(IN, mobj, 0, params[1].memref.size), 1126e9e277fSJerome Forissier [2] = THREAD_PARAM_VALUE(INOUT, params[0].value.b, /* timeout */ 1136e9e277fSJerome Forissier 0, 0), 1146e9e277fSJerome Forissier }; 1156e9e277fSJerome Forissier 1166e9e277fSJerome Forissier res = thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 3, tpm); 1176e9e277fSJerome Forissier params[2].value.a = tpm[2].u.value.b; /* transmitted bytes */ 1186e9e277fSJerome Forissier 1196e9e277fSJerome Forissier return res; 1206e9e277fSJerome Forissier } 1216e9e277fSJerome Forissier 1226e9e277fSJerome Forissier static TEE_Result socket_recv(uint32_t instance_id, uint32_t param_types, 1236e9e277fSJerome Forissier TEE_Param params[TEE_NUM_PARAMS]) 1246e9e277fSJerome Forissier { 1256e9e277fSJerome Forissier struct mobj *mobj; 1266e9e277fSJerome Forissier TEE_Result res; 1276e9e277fSJerome Forissier void *va; 1286e9e277fSJerome Forissier uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 1296e9e277fSJerome Forissier TEE_PARAM_TYPE_MEMREF_OUTPUT, 1306e9e277fSJerome Forissier TEE_PARAM_TYPE_NONE, 1316e9e277fSJerome Forissier TEE_PARAM_TYPE_NONE); 1326e9e277fSJerome Forissier 1336e9e277fSJerome Forissier if (exp_pt != param_types) { 1346e9e277fSJerome Forissier DMSG("got param_types 0x%x, expected 0x%x", 1356e9e277fSJerome Forissier param_types, exp_pt); 1366e9e277fSJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 1376e9e277fSJerome Forissier } 1386e9e277fSJerome Forissier 139*1a7d8eaeSJens Wiklander va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_SOCKET, 140*1a7d8eaeSJens Wiklander THREAD_SHM_TYPE_APPLICATION, 1419bee8f2aSJens Wiklander params[1].memref.size, &mobj); 1426e9e277fSJerome Forissier if (!va) 1436e9e277fSJerome Forissier return TEE_ERROR_OUT_OF_MEMORY; 1446e9e277fSJerome Forissier 1456e9e277fSJerome Forissier struct thread_param tpm[3] = { 1466e9e277fSJerome Forissier [0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SOCKET_RECV, instance_id, 1476e9e277fSJerome Forissier params[0].value.a /* handle */), 1486e9e277fSJerome Forissier [1] = THREAD_PARAM_MEMREF(OUT, mobj, 0, params[1].memref.size), 1496e9e277fSJerome Forissier [2] = THREAD_PARAM_VALUE(IN, params[0].value.b /* timeout */, 1506e9e277fSJerome Forissier 0, 0), 1516e9e277fSJerome Forissier }; 1526e9e277fSJerome Forissier 1536e9e277fSJerome Forissier res = thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 3, tpm); 1546e9e277fSJerome Forissier 1556e9e277fSJerome Forissier if (tpm[1].u.memref.size > params[1].memref.size) 1566e9e277fSJerome Forissier return TEE_ERROR_GENERIC; 1576e9e277fSJerome Forissier params[1].memref.size = tpm[1].u.memref.size; 1586e9e277fSJerome Forissier if (params[1].memref.size) 1596e9e277fSJerome Forissier memcpy(params[1].memref.buffer, va, params[1].memref.size); 1606e9e277fSJerome Forissier 1616e9e277fSJerome Forissier return res; 1626e9e277fSJerome Forissier } 1636e9e277fSJerome Forissier 1646e9e277fSJerome Forissier static TEE_Result socket_ioctl(uint32_t instance_id, uint32_t param_types, 1656e9e277fSJerome Forissier TEE_Param params[TEE_NUM_PARAMS]) 1666e9e277fSJerome Forissier { 1676e9e277fSJerome Forissier struct mobj *mobj; 1686e9e277fSJerome Forissier TEE_Result res; 1696e9e277fSJerome Forissier void *va; 1706e9e277fSJerome Forissier uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 1716e9e277fSJerome Forissier TEE_PARAM_TYPE_MEMREF_INOUT, 1726e9e277fSJerome Forissier TEE_PARAM_TYPE_NONE, 1736e9e277fSJerome Forissier TEE_PARAM_TYPE_NONE); 1746e9e277fSJerome Forissier 1756e9e277fSJerome Forissier if (exp_pt != param_types) { 1766e9e277fSJerome Forissier DMSG("got param_types 0x%x, expected 0x%x", 1776e9e277fSJerome Forissier param_types, exp_pt); 1786e9e277fSJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 1796e9e277fSJerome Forissier } 1806e9e277fSJerome Forissier 181*1a7d8eaeSJens Wiklander va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_SOCKET, 182*1a7d8eaeSJens Wiklander THREAD_SHM_TYPE_APPLICATION, 1839bee8f2aSJens Wiklander params[1].memref.size, &mobj); 1846e9e277fSJerome Forissier if (!va) 1856e9e277fSJerome Forissier return TEE_ERROR_OUT_OF_MEMORY; 1866e9e277fSJerome Forissier 1876e9e277fSJerome Forissier memcpy(va, params[1].memref.buffer, params[1].memref.size); 1886e9e277fSJerome Forissier 1896e9e277fSJerome Forissier struct thread_param tpm[3] = { 1906e9e277fSJerome Forissier [0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SOCKET_IOCTL, 1916e9e277fSJerome Forissier instance_id, 1926e9e277fSJerome Forissier params[0].value.a /* handle */), 1936e9e277fSJerome Forissier [1] = THREAD_PARAM_MEMREF(INOUT, mobj, 0, 1946e9e277fSJerome Forissier params[1].memref.size), 1956e9e277fSJerome Forissier [2] = THREAD_PARAM_VALUE(IN, 1966e9e277fSJerome Forissier params[0].value.b /* ioctl command */, 1976e9e277fSJerome Forissier 0, 0), 1986e9e277fSJerome Forissier }; 1996e9e277fSJerome Forissier 2006e9e277fSJerome Forissier res = thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 3, tpm); 2016e9e277fSJerome Forissier if (tpm[1].u.memref.size <= params[1].memref.size) 2026e9e277fSJerome Forissier memcpy(params[1].memref.buffer, va, tpm[1].u.memref.size); 2036e9e277fSJerome Forissier 2046e9e277fSJerome Forissier params[1].memref.size = tpm[1].u.memref.size; 2056e9e277fSJerome Forissier 2066e9e277fSJerome Forissier return res; 2076e9e277fSJerome Forissier } 2086e9e277fSJerome Forissier 2096e9e277fSJerome Forissier typedef TEE_Result (*ta_func)(uint32_t instance_id, uint32_t param_types, 2106e9e277fSJerome Forissier TEE_Param params[TEE_NUM_PARAMS]); 2116e9e277fSJerome Forissier 2126e9e277fSJerome Forissier static const ta_func ta_funcs[] = { 2136e9e277fSJerome Forissier [PTA_SOCKET_OPEN] = socket_open, 2146e9e277fSJerome Forissier [PTA_SOCKET_CLOSE] = socket_close, 2156e9e277fSJerome Forissier [PTA_SOCKET_SEND] = socket_send, 2166e9e277fSJerome Forissier [PTA_SOCKET_RECV] = socket_recv, 2176e9e277fSJerome Forissier [PTA_SOCKET_IOCTL] = socket_ioctl, 2186e9e277fSJerome Forissier }; 2196e9e277fSJerome Forissier 2206e9e277fSJerome Forissier /* 2216e9e277fSJerome Forissier * Trusted Application Entry Points 2226e9e277fSJerome Forissier */ 2236e9e277fSJerome Forissier 2246e9e277fSJerome Forissier static TEE_Result pta_socket_open_session(uint32_t param_types __unused, 2256e9e277fSJerome Forissier TEE_Param pParams[TEE_NUM_PARAMS] __unused, 2266e9e277fSJerome Forissier void **sess_ctx) 2276e9e277fSJerome Forissier { 2286e9e277fSJerome Forissier struct tee_ta_session *s; 2296e9e277fSJerome Forissier 2306e9e277fSJerome Forissier /* Check that we're called from a TA */ 2316e9e277fSJerome Forissier s = tee_ta_get_calling_session(); 2326e9e277fSJerome Forissier if (!s) 2336e9e277fSJerome Forissier return TEE_ERROR_ACCESS_DENIED; 2346e9e277fSJerome Forissier 2356e9e277fSJerome Forissier *sess_ctx = (void *)(vaddr_t)get_instance_id(s); 2366e9e277fSJerome Forissier 2376e9e277fSJerome Forissier return TEE_SUCCESS; 2386e9e277fSJerome Forissier } 2396e9e277fSJerome Forissier 2406e9e277fSJerome Forissier static void pta_socket_close_session(void *sess_ctx) 2416e9e277fSJerome Forissier { 2426e9e277fSJerome Forissier TEE_Result res; 2436e9e277fSJerome Forissier struct thread_param tpm = { 2446e9e277fSJerome Forissier .attr = THREAD_PARAM_ATTR_VALUE_IN, .u.value = { 2456e9e277fSJerome Forissier .a = OPTEE_RPC_SOCKET_CLOSE_ALL, .b = (vaddr_t)sess_ctx, 2466e9e277fSJerome Forissier }, 2476e9e277fSJerome Forissier }; 2486e9e277fSJerome Forissier 2496e9e277fSJerome Forissier res = thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 1, &tpm); 2506e9e277fSJerome Forissier if (res != TEE_SUCCESS) 2516e9e277fSJerome Forissier DMSG("OPTEE_RPC_SOCKET_CLOSE_ALL failed: %#" PRIx32, res); 2526e9e277fSJerome Forissier } 2536e9e277fSJerome Forissier 2546e9e277fSJerome Forissier static TEE_Result pta_socket_invoke_command(void *sess_ctx, uint32_t cmd_id, 2556e9e277fSJerome Forissier uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) 2566e9e277fSJerome Forissier { 2576e9e277fSJerome Forissier if (cmd_id < ARRAY_SIZE(ta_funcs) && ta_funcs[cmd_id]) 2586e9e277fSJerome Forissier return ta_funcs[cmd_id]((vaddr_t)sess_ctx, param_types, params); 2596e9e277fSJerome Forissier 2606e9e277fSJerome Forissier return TEE_ERROR_NOT_IMPLEMENTED; 2616e9e277fSJerome Forissier } 2626e9e277fSJerome Forissier 2636e9e277fSJerome Forissier pseudo_ta_register(.uuid = PTA_SOCKET_UUID, .name = "socket", 2646e9e277fSJerome Forissier .flags = PTA_DEFAULT_FLAGS | TA_FLAG_CONCURRENT, 2656e9e277fSJerome Forissier .open_session_entry_point = pta_socket_open_session, 2666e9e277fSJerome Forissier .close_session_entry_point = pta_socket_close_session, 2676e9e277fSJerome Forissier .invoke_command_entry_point = pta_socket_invoke_command); 268