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*9bee8f2aSJens Wiklander va = thread_rpc_shm_cache_alloc(THREAD_SHM_TYPE_APPLICATION, 37*9bee8f2aSJens Wiklander params[1].memref.size, &mobj); 386e9e277fSJerome Forissier if (!va) 396e9e277fSJerome Forissier return TEE_ERROR_OUT_OF_MEMORY; 406e9e277fSJerome Forissier 416e9e277fSJerome Forissier memcpy(va, params[1].memref.buffer, params[1].memref.size); 426e9e277fSJerome Forissier 436e9e277fSJerome Forissier struct thread_param tpm[4] = { 446e9e277fSJerome Forissier [0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SOCKET_OPEN, 456e9e277fSJerome Forissier instance_id, 0), 466e9e277fSJerome Forissier [1] = THREAD_PARAM_VALUE(IN, 476e9e277fSJerome Forissier params[0].value.b, /* server port number */ 486e9e277fSJerome Forissier params[2].value.a, /* protocol */ 496e9e277fSJerome Forissier params[0].value.a /* ip version */), 506e9e277fSJerome Forissier [2] = THREAD_PARAM_MEMREF(IN, mobj, 0, params[1].memref.size), 516e9e277fSJerome Forissier [3] = THREAD_PARAM_VALUE(OUT, 0, 0, 0), 526e9e277fSJerome Forissier }; 536e9e277fSJerome Forissier 546e9e277fSJerome Forissier res = thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 4, tpm); 556e9e277fSJerome Forissier if (res == TEE_SUCCESS) 566e9e277fSJerome Forissier params[3].value.a = tpm[3].u.value.a; 576e9e277fSJerome Forissier 586e9e277fSJerome Forissier return res; 596e9e277fSJerome Forissier } 606e9e277fSJerome Forissier 616e9e277fSJerome Forissier static TEE_Result socket_close(uint32_t instance_id, uint32_t param_types, 626e9e277fSJerome Forissier TEE_Param params[TEE_NUM_PARAMS]) 636e9e277fSJerome Forissier { 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 756e9e277fSJerome Forissier struct thread_param tpm = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SOCKET_CLOSE, 766e9e277fSJerome Forissier instance_id, 776e9e277fSJerome Forissier params[0].value.a); 786e9e277fSJerome Forissier 796e9e277fSJerome Forissier return thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 1, &tpm); 806e9e277fSJerome Forissier } 816e9e277fSJerome Forissier 826e9e277fSJerome Forissier static TEE_Result socket_send(uint32_t instance_id, uint32_t param_types, 836e9e277fSJerome Forissier TEE_Param params[TEE_NUM_PARAMS]) 846e9e277fSJerome Forissier { 856e9e277fSJerome Forissier struct mobj *mobj; 866e9e277fSJerome Forissier TEE_Result res; 876e9e277fSJerome Forissier void *va; 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 99*9bee8f2aSJens Wiklander va = thread_rpc_shm_cache_alloc(THREAD_SHM_TYPE_APPLICATION, 100*9bee8f2aSJens Wiklander params[1].memref.size, &mobj); 1016e9e277fSJerome Forissier if (!va) 1026e9e277fSJerome Forissier return TEE_ERROR_OUT_OF_MEMORY; 1036e9e277fSJerome Forissier 1046e9e277fSJerome Forissier memcpy(va, params[1].memref.buffer, params[1].memref.size); 1056e9e277fSJerome Forissier 1066e9e277fSJerome Forissier struct thread_param tpm[3] = { 1076e9e277fSJerome Forissier [0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SOCKET_SEND, instance_id, 1086e9e277fSJerome Forissier params[0].value.a /* handle */), 1096e9e277fSJerome Forissier [1] = THREAD_PARAM_MEMREF(IN, mobj, 0, params[1].memref.size), 1106e9e277fSJerome Forissier [2] = THREAD_PARAM_VALUE(INOUT, params[0].value.b, /* timeout */ 1116e9e277fSJerome Forissier 0, 0), 1126e9e277fSJerome Forissier }; 1136e9e277fSJerome Forissier 1146e9e277fSJerome Forissier res = thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 3, tpm); 1156e9e277fSJerome Forissier params[2].value.a = tpm[2].u.value.b; /* transmitted bytes */ 1166e9e277fSJerome Forissier 1176e9e277fSJerome Forissier return res; 1186e9e277fSJerome Forissier } 1196e9e277fSJerome Forissier 1206e9e277fSJerome Forissier static TEE_Result socket_recv(uint32_t instance_id, uint32_t param_types, 1216e9e277fSJerome Forissier TEE_Param params[TEE_NUM_PARAMS]) 1226e9e277fSJerome Forissier { 1236e9e277fSJerome Forissier struct mobj *mobj; 1246e9e277fSJerome Forissier TEE_Result res; 1256e9e277fSJerome Forissier void *va; 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 137*9bee8f2aSJens Wiklander va = thread_rpc_shm_cache_alloc(THREAD_SHM_TYPE_APPLICATION, 138*9bee8f2aSJens Wiklander params[1].memref.size, &mobj); 1396e9e277fSJerome Forissier if (!va) 1406e9e277fSJerome Forissier return TEE_ERROR_OUT_OF_MEMORY; 1416e9e277fSJerome Forissier 1426e9e277fSJerome Forissier struct thread_param tpm[3] = { 1436e9e277fSJerome Forissier [0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SOCKET_RECV, instance_id, 1446e9e277fSJerome Forissier params[0].value.a /* handle */), 1456e9e277fSJerome Forissier [1] = THREAD_PARAM_MEMREF(OUT, mobj, 0, params[1].memref.size), 1466e9e277fSJerome Forissier [2] = THREAD_PARAM_VALUE(IN, params[0].value.b /* timeout */, 1476e9e277fSJerome Forissier 0, 0), 1486e9e277fSJerome Forissier }; 1496e9e277fSJerome Forissier 1506e9e277fSJerome Forissier res = thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 3, tpm); 1516e9e277fSJerome Forissier 1526e9e277fSJerome Forissier if (tpm[1].u.memref.size > params[1].memref.size) 1536e9e277fSJerome Forissier return TEE_ERROR_GENERIC; 1546e9e277fSJerome Forissier params[1].memref.size = tpm[1].u.memref.size; 1556e9e277fSJerome Forissier if (params[1].memref.size) 1566e9e277fSJerome Forissier memcpy(params[1].memref.buffer, va, params[1].memref.size); 1576e9e277fSJerome Forissier 1586e9e277fSJerome Forissier return res; 1596e9e277fSJerome Forissier } 1606e9e277fSJerome Forissier 1616e9e277fSJerome Forissier static TEE_Result socket_ioctl(uint32_t instance_id, uint32_t param_types, 1626e9e277fSJerome Forissier TEE_Param params[TEE_NUM_PARAMS]) 1636e9e277fSJerome Forissier { 1646e9e277fSJerome Forissier struct mobj *mobj; 1656e9e277fSJerome Forissier TEE_Result res; 1666e9e277fSJerome Forissier void *va; 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 178*9bee8f2aSJens Wiklander va = thread_rpc_shm_cache_alloc(THREAD_SHM_TYPE_APPLICATION, 179*9bee8f2aSJens Wiklander params[1].memref.size, &mobj); 1806e9e277fSJerome Forissier if (!va) 1816e9e277fSJerome Forissier return TEE_ERROR_OUT_OF_MEMORY; 1826e9e277fSJerome Forissier 1836e9e277fSJerome Forissier memcpy(va, params[1].memref.buffer, params[1].memref.size); 1846e9e277fSJerome Forissier 1856e9e277fSJerome Forissier struct thread_param tpm[3] = { 1866e9e277fSJerome Forissier [0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SOCKET_IOCTL, 1876e9e277fSJerome Forissier instance_id, 1886e9e277fSJerome Forissier params[0].value.a /* handle */), 1896e9e277fSJerome Forissier [1] = THREAD_PARAM_MEMREF(INOUT, mobj, 0, 1906e9e277fSJerome Forissier params[1].memref.size), 1916e9e277fSJerome Forissier [2] = THREAD_PARAM_VALUE(IN, 1926e9e277fSJerome Forissier params[0].value.b /* ioctl command */, 1936e9e277fSJerome Forissier 0, 0), 1946e9e277fSJerome Forissier }; 1956e9e277fSJerome Forissier 1966e9e277fSJerome Forissier res = thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 3, tpm); 1976e9e277fSJerome Forissier if (tpm[1].u.memref.size <= params[1].memref.size) 1986e9e277fSJerome Forissier memcpy(params[1].memref.buffer, va, tpm[1].u.memref.size); 1996e9e277fSJerome Forissier 2006e9e277fSJerome Forissier params[1].memref.size = tpm[1].u.memref.size; 2016e9e277fSJerome Forissier 2026e9e277fSJerome Forissier return res; 2036e9e277fSJerome Forissier } 2046e9e277fSJerome Forissier 2056e9e277fSJerome Forissier typedef TEE_Result (*ta_func)(uint32_t instance_id, uint32_t param_types, 2066e9e277fSJerome Forissier TEE_Param params[TEE_NUM_PARAMS]); 2076e9e277fSJerome Forissier 2086e9e277fSJerome Forissier static const ta_func ta_funcs[] = { 2096e9e277fSJerome Forissier [PTA_SOCKET_OPEN] = socket_open, 2106e9e277fSJerome Forissier [PTA_SOCKET_CLOSE] = socket_close, 2116e9e277fSJerome Forissier [PTA_SOCKET_SEND] = socket_send, 2126e9e277fSJerome Forissier [PTA_SOCKET_RECV] = socket_recv, 2136e9e277fSJerome Forissier [PTA_SOCKET_IOCTL] = socket_ioctl, 2146e9e277fSJerome Forissier }; 2156e9e277fSJerome Forissier 2166e9e277fSJerome Forissier /* 2176e9e277fSJerome Forissier * Trusted Application Entry Points 2186e9e277fSJerome Forissier */ 2196e9e277fSJerome Forissier 2206e9e277fSJerome Forissier static TEE_Result pta_socket_open_session(uint32_t param_types __unused, 2216e9e277fSJerome Forissier TEE_Param pParams[TEE_NUM_PARAMS] __unused, 2226e9e277fSJerome Forissier void **sess_ctx) 2236e9e277fSJerome Forissier { 2246e9e277fSJerome Forissier struct tee_ta_session *s; 2256e9e277fSJerome Forissier 2266e9e277fSJerome Forissier /* Check that we're called from a TA */ 2276e9e277fSJerome Forissier s = tee_ta_get_calling_session(); 2286e9e277fSJerome Forissier if (!s) 2296e9e277fSJerome Forissier return TEE_ERROR_ACCESS_DENIED; 2306e9e277fSJerome Forissier 2316e9e277fSJerome Forissier *sess_ctx = (void *)(vaddr_t)get_instance_id(s); 2326e9e277fSJerome Forissier 2336e9e277fSJerome Forissier return TEE_SUCCESS; 2346e9e277fSJerome Forissier } 2356e9e277fSJerome Forissier 2366e9e277fSJerome Forissier static void pta_socket_close_session(void *sess_ctx) 2376e9e277fSJerome Forissier { 2386e9e277fSJerome Forissier TEE_Result res; 2396e9e277fSJerome Forissier struct thread_param tpm = { 2406e9e277fSJerome Forissier .attr = THREAD_PARAM_ATTR_VALUE_IN, .u.value = { 2416e9e277fSJerome Forissier .a = OPTEE_RPC_SOCKET_CLOSE_ALL, .b = (vaddr_t)sess_ctx, 2426e9e277fSJerome Forissier }, 2436e9e277fSJerome Forissier }; 2446e9e277fSJerome Forissier 2456e9e277fSJerome Forissier res = thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 1, &tpm); 2466e9e277fSJerome Forissier if (res != TEE_SUCCESS) 2476e9e277fSJerome Forissier DMSG("OPTEE_RPC_SOCKET_CLOSE_ALL failed: %#" PRIx32, res); 2486e9e277fSJerome Forissier } 2496e9e277fSJerome Forissier 2506e9e277fSJerome Forissier static TEE_Result pta_socket_invoke_command(void *sess_ctx, uint32_t cmd_id, 2516e9e277fSJerome Forissier uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) 2526e9e277fSJerome Forissier { 2536e9e277fSJerome Forissier if (cmd_id < ARRAY_SIZE(ta_funcs) && ta_funcs[cmd_id]) 2546e9e277fSJerome Forissier return ta_funcs[cmd_id]((vaddr_t)sess_ctx, param_types, params); 2556e9e277fSJerome Forissier 2566e9e277fSJerome Forissier return TEE_ERROR_NOT_IMPLEMENTED; 2576e9e277fSJerome Forissier } 2586e9e277fSJerome Forissier 2596e9e277fSJerome Forissier pseudo_ta_register(.uuid = PTA_SOCKET_UUID, .name = "socket", 2606e9e277fSJerome Forissier .flags = PTA_DEFAULT_FLAGS | TA_FLAG_CONCURRENT, 2616e9e277fSJerome Forissier .open_session_entry_point = pta_socket_open_session, 2626e9e277fSJerome Forissier .close_session_entry_point = pta_socket_close_session, 2636e9e277fSJerome Forissier .invoke_command_entry_point = pta_socket_invoke_command); 264