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 { 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 361a7d8eaeSJens Wiklander va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_SOCKET, 371a7d8eaeSJens 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 1001a7d8eaeSJens Wiklander va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_SOCKET, 1011a7d8eaeSJens 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 { 125*e9907fd7SJens Wiklander struct mobj *mobj = NULL; 126*e9907fd7SJens Wiklander TEE_Result res = TEE_SUCCESS; 127*e9907fd7SJens Wiklander void *va = NULL; 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*e9907fd7SJens Wiklander if (params[1].memref.size) { 1401a7d8eaeSJens Wiklander va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_SOCKET, 1411a7d8eaeSJens Wiklander THREAD_SHM_TYPE_APPLICATION, 1429bee8f2aSJens Wiklander params[1].memref.size, &mobj); 1436e9e277fSJerome Forissier if (!va) 1446e9e277fSJerome Forissier return TEE_ERROR_OUT_OF_MEMORY; 145*e9907fd7SJens Wiklander } 1466e9e277fSJerome Forissier 1476e9e277fSJerome Forissier struct thread_param tpm[3] = { 1486e9e277fSJerome Forissier [0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SOCKET_RECV, instance_id, 1496e9e277fSJerome Forissier params[0].value.a /* handle */), 1506e9e277fSJerome Forissier [1] = THREAD_PARAM_MEMREF(OUT, mobj, 0, params[1].memref.size), 1516e9e277fSJerome Forissier [2] = THREAD_PARAM_VALUE(IN, params[0].value.b /* timeout */, 1526e9e277fSJerome Forissier 0, 0), 1536e9e277fSJerome Forissier }; 1546e9e277fSJerome Forissier 1556e9e277fSJerome Forissier res = thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 3, tpm); 1566e9e277fSJerome Forissier 1576e9e277fSJerome Forissier if (params[1].memref.size) 158*e9907fd7SJens Wiklander memcpy(params[1].memref.buffer, va, 159*e9907fd7SJens Wiklander MIN(params[1].memref.size, tpm[1].u.memref.size)); 160*e9907fd7SJens Wiklander params[1].memref.size = tpm[1].u.memref.size; 1616e9e277fSJerome Forissier 1626e9e277fSJerome Forissier return res; 1636e9e277fSJerome Forissier } 1646e9e277fSJerome Forissier 1656e9e277fSJerome Forissier static TEE_Result socket_ioctl(uint32_t instance_id, uint32_t param_types, 1666e9e277fSJerome Forissier TEE_Param params[TEE_NUM_PARAMS]) 1676e9e277fSJerome Forissier { 1686e9e277fSJerome Forissier struct mobj *mobj; 1696e9e277fSJerome Forissier TEE_Result res; 1706e9e277fSJerome Forissier void *va; 1716e9e277fSJerome Forissier uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 1726e9e277fSJerome Forissier TEE_PARAM_TYPE_MEMREF_INOUT, 1736e9e277fSJerome Forissier TEE_PARAM_TYPE_NONE, 1746e9e277fSJerome Forissier TEE_PARAM_TYPE_NONE); 1756e9e277fSJerome Forissier 1766e9e277fSJerome Forissier if (exp_pt != param_types) { 1776e9e277fSJerome Forissier DMSG("got param_types 0x%x, expected 0x%x", 1786e9e277fSJerome Forissier param_types, exp_pt); 1796e9e277fSJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 1806e9e277fSJerome Forissier } 1816e9e277fSJerome Forissier 1821a7d8eaeSJens Wiklander va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_SOCKET, 1831a7d8eaeSJens Wiklander THREAD_SHM_TYPE_APPLICATION, 1849bee8f2aSJens Wiklander params[1].memref.size, &mobj); 1856e9e277fSJerome Forissier if (!va) 1866e9e277fSJerome Forissier return TEE_ERROR_OUT_OF_MEMORY; 1876e9e277fSJerome Forissier 1886e9e277fSJerome Forissier memcpy(va, params[1].memref.buffer, params[1].memref.size); 1896e9e277fSJerome Forissier 1906e9e277fSJerome Forissier struct thread_param tpm[3] = { 1916e9e277fSJerome Forissier [0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SOCKET_IOCTL, 1926e9e277fSJerome Forissier instance_id, 1936e9e277fSJerome Forissier params[0].value.a /* handle */), 1946e9e277fSJerome Forissier [1] = THREAD_PARAM_MEMREF(INOUT, mobj, 0, 1956e9e277fSJerome Forissier params[1].memref.size), 1966e9e277fSJerome Forissier [2] = THREAD_PARAM_VALUE(IN, 1976e9e277fSJerome Forissier params[0].value.b /* ioctl command */, 1986e9e277fSJerome Forissier 0, 0), 1996e9e277fSJerome Forissier }; 2006e9e277fSJerome Forissier 2016e9e277fSJerome Forissier res = thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 3, tpm); 2026e9e277fSJerome Forissier if (tpm[1].u.memref.size <= params[1].memref.size) 2036e9e277fSJerome Forissier memcpy(params[1].memref.buffer, va, tpm[1].u.memref.size); 2046e9e277fSJerome Forissier 2056e9e277fSJerome Forissier params[1].memref.size = tpm[1].u.memref.size; 2066e9e277fSJerome Forissier 2076e9e277fSJerome Forissier return res; 2086e9e277fSJerome Forissier } 2096e9e277fSJerome Forissier 2106e9e277fSJerome Forissier typedef TEE_Result (*ta_func)(uint32_t instance_id, uint32_t param_types, 2116e9e277fSJerome Forissier TEE_Param params[TEE_NUM_PARAMS]); 2126e9e277fSJerome Forissier 2136e9e277fSJerome Forissier static const ta_func ta_funcs[] = { 2146e9e277fSJerome Forissier [PTA_SOCKET_OPEN] = socket_open, 2156e9e277fSJerome Forissier [PTA_SOCKET_CLOSE] = socket_close, 2166e9e277fSJerome Forissier [PTA_SOCKET_SEND] = socket_send, 2176e9e277fSJerome Forissier [PTA_SOCKET_RECV] = socket_recv, 2186e9e277fSJerome Forissier [PTA_SOCKET_IOCTL] = socket_ioctl, 2196e9e277fSJerome Forissier }; 2206e9e277fSJerome Forissier 2216e9e277fSJerome Forissier /* 2226e9e277fSJerome Forissier * Trusted Application Entry Points 2236e9e277fSJerome Forissier */ 2246e9e277fSJerome Forissier 2256e9e277fSJerome Forissier static TEE_Result pta_socket_open_session(uint32_t param_types __unused, 2266e9e277fSJerome Forissier TEE_Param pParams[TEE_NUM_PARAMS] __unused, 2276e9e277fSJerome Forissier void **sess_ctx) 2286e9e277fSJerome Forissier { 22900b3b9a2SJens Wiklander struct ts_session *s = ts_get_calling_session(); 2306e9e277fSJerome Forissier 2316e9e277fSJerome Forissier /* Check that we're called from a TA */ 23200b3b9a2SJens Wiklander if (!s || !is_user_ta_ctx(s->ctx)) 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