1*6e9e277fSJerome Forissier // SPDX-License-Identifier: BSD-2-Clause 2*6e9e277fSJerome Forissier /* 3*6e9e277fSJerome Forissier * Copyright (c) 2016-2017, Linaro Limited 4*6e9e277fSJerome Forissier */ 5*6e9e277fSJerome Forissier 6*6e9e277fSJerome Forissier #include <assert.h> 7*6e9e277fSJerome Forissier #include <mm/mobj.h> 8*6e9e277fSJerome Forissier #include <kernel/pseudo_ta.h> 9*6e9e277fSJerome Forissier #include <optee_rpc_cmd.h> 10*6e9e277fSJerome Forissier #include <pta_socket.h> 11*6e9e277fSJerome Forissier #include <string.h> 12*6e9e277fSJerome Forissier #include <tee/tee_fs_rpc.h> 13*6e9e277fSJerome Forissier 14*6e9e277fSJerome Forissier static uint32_t get_instance_id(struct tee_ta_session *sess) 15*6e9e277fSJerome Forissier { 16*6e9e277fSJerome Forissier return sess->ctx->ops->get_instance_id(sess->ctx); 17*6e9e277fSJerome Forissier } 18*6e9e277fSJerome Forissier 19*6e9e277fSJerome Forissier static TEE_Result socket_open(uint32_t instance_id, uint32_t param_types, 20*6e9e277fSJerome Forissier TEE_Param params[TEE_NUM_PARAMS]) 21*6e9e277fSJerome Forissier { 22*6e9e277fSJerome Forissier struct mobj *mobj; 23*6e9e277fSJerome Forissier TEE_Result res; 24*6e9e277fSJerome Forissier void *va; 25*6e9e277fSJerome Forissier uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 26*6e9e277fSJerome Forissier TEE_PARAM_TYPE_MEMREF_INPUT, 27*6e9e277fSJerome Forissier TEE_PARAM_TYPE_VALUE_INPUT, 28*6e9e277fSJerome Forissier TEE_PARAM_TYPE_VALUE_OUTPUT); 29*6e9e277fSJerome Forissier 30*6e9e277fSJerome Forissier if (exp_pt != param_types) { 31*6e9e277fSJerome Forissier DMSG("got param_types 0x%x, expected 0x%x", 32*6e9e277fSJerome Forissier param_types, exp_pt); 33*6e9e277fSJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 34*6e9e277fSJerome Forissier } 35*6e9e277fSJerome Forissier 36*6e9e277fSJerome Forissier va = tee_fs_rpc_cache_alloc(params[1].memref.size, &mobj); 37*6e9e277fSJerome Forissier if (!va) 38*6e9e277fSJerome Forissier return TEE_ERROR_OUT_OF_MEMORY; 39*6e9e277fSJerome Forissier 40*6e9e277fSJerome Forissier memcpy(va, params[1].memref.buffer, params[1].memref.size); 41*6e9e277fSJerome Forissier 42*6e9e277fSJerome Forissier struct thread_param tpm[4] = { 43*6e9e277fSJerome Forissier [0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SOCKET_OPEN, 44*6e9e277fSJerome Forissier instance_id, 0), 45*6e9e277fSJerome Forissier [1] = THREAD_PARAM_VALUE(IN, 46*6e9e277fSJerome Forissier params[0].value.b, /* server port number */ 47*6e9e277fSJerome Forissier params[2].value.a, /* protocol */ 48*6e9e277fSJerome Forissier params[0].value.a /* ip version */), 49*6e9e277fSJerome Forissier [2] = THREAD_PARAM_MEMREF(IN, mobj, 0, params[1].memref.size), 50*6e9e277fSJerome Forissier [3] = THREAD_PARAM_VALUE(OUT, 0, 0, 0), 51*6e9e277fSJerome Forissier }; 52*6e9e277fSJerome Forissier 53*6e9e277fSJerome Forissier res = thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 4, tpm); 54*6e9e277fSJerome Forissier if (res == TEE_SUCCESS) 55*6e9e277fSJerome Forissier params[3].value.a = tpm[3].u.value.a; 56*6e9e277fSJerome Forissier 57*6e9e277fSJerome Forissier return res; 58*6e9e277fSJerome Forissier } 59*6e9e277fSJerome Forissier 60*6e9e277fSJerome Forissier static TEE_Result socket_close(uint32_t instance_id, uint32_t param_types, 61*6e9e277fSJerome Forissier TEE_Param params[TEE_NUM_PARAMS]) 62*6e9e277fSJerome Forissier { 63*6e9e277fSJerome Forissier uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 64*6e9e277fSJerome Forissier TEE_PARAM_TYPE_NONE, 65*6e9e277fSJerome Forissier TEE_PARAM_TYPE_NONE, 66*6e9e277fSJerome Forissier TEE_PARAM_TYPE_NONE); 67*6e9e277fSJerome Forissier 68*6e9e277fSJerome Forissier if (exp_pt != param_types) { 69*6e9e277fSJerome Forissier DMSG("got param_types 0x%x, expected 0x%x", 70*6e9e277fSJerome Forissier param_types, exp_pt); 71*6e9e277fSJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 72*6e9e277fSJerome Forissier } 73*6e9e277fSJerome Forissier 74*6e9e277fSJerome Forissier struct thread_param tpm = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SOCKET_CLOSE, 75*6e9e277fSJerome Forissier instance_id, 76*6e9e277fSJerome Forissier params[0].value.a); 77*6e9e277fSJerome Forissier 78*6e9e277fSJerome Forissier return thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 1, &tpm); 79*6e9e277fSJerome Forissier } 80*6e9e277fSJerome Forissier 81*6e9e277fSJerome Forissier static TEE_Result socket_send(uint32_t instance_id, uint32_t param_types, 82*6e9e277fSJerome Forissier TEE_Param params[TEE_NUM_PARAMS]) 83*6e9e277fSJerome Forissier { 84*6e9e277fSJerome Forissier struct mobj *mobj; 85*6e9e277fSJerome Forissier TEE_Result res; 86*6e9e277fSJerome Forissier void *va; 87*6e9e277fSJerome Forissier uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 88*6e9e277fSJerome Forissier TEE_PARAM_TYPE_MEMREF_INPUT, 89*6e9e277fSJerome Forissier TEE_PARAM_TYPE_VALUE_OUTPUT, 90*6e9e277fSJerome Forissier TEE_PARAM_TYPE_NONE); 91*6e9e277fSJerome Forissier 92*6e9e277fSJerome Forissier if (exp_pt != param_types) { 93*6e9e277fSJerome Forissier DMSG("got param_types 0x%x, expected 0x%x", 94*6e9e277fSJerome Forissier param_types, exp_pt); 95*6e9e277fSJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 96*6e9e277fSJerome Forissier } 97*6e9e277fSJerome Forissier 98*6e9e277fSJerome Forissier va = tee_fs_rpc_cache_alloc(params[1].memref.size, &mobj); 99*6e9e277fSJerome Forissier if (!va) 100*6e9e277fSJerome Forissier return TEE_ERROR_OUT_OF_MEMORY; 101*6e9e277fSJerome Forissier 102*6e9e277fSJerome Forissier memcpy(va, params[1].memref.buffer, params[1].memref.size); 103*6e9e277fSJerome Forissier 104*6e9e277fSJerome Forissier struct thread_param tpm[3] = { 105*6e9e277fSJerome Forissier [0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SOCKET_SEND, instance_id, 106*6e9e277fSJerome Forissier params[0].value.a /* handle */), 107*6e9e277fSJerome Forissier [1] = THREAD_PARAM_MEMREF(IN, mobj, 0, params[1].memref.size), 108*6e9e277fSJerome Forissier [2] = THREAD_PARAM_VALUE(INOUT, params[0].value.b, /* timeout */ 109*6e9e277fSJerome Forissier 0, 0), 110*6e9e277fSJerome Forissier }; 111*6e9e277fSJerome Forissier 112*6e9e277fSJerome Forissier res = thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 3, tpm); 113*6e9e277fSJerome Forissier params[2].value.a = tpm[2].u.value.b; /* transmitted bytes */ 114*6e9e277fSJerome Forissier 115*6e9e277fSJerome Forissier return res; 116*6e9e277fSJerome Forissier } 117*6e9e277fSJerome Forissier 118*6e9e277fSJerome Forissier static TEE_Result socket_recv(uint32_t instance_id, uint32_t param_types, 119*6e9e277fSJerome Forissier TEE_Param params[TEE_NUM_PARAMS]) 120*6e9e277fSJerome Forissier { 121*6e9e277fSJerome Forissier struct mobj *mobj; 122*6e9e277fSJerome Forissier TEE_Result res; 123*6e9e277fSJerome Forissier void *va; 124*6e9e277fSJerome Forissier uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 125*6e9e277fSJerome Forissier TEE_PARAM_TYPE_MEMREF_OUTPUT, 126*6e9e277fSJerome Forissier TEE_PARAM_TYPE_NONE, 127*6e9e277fSJerome Forissier TEE_PARAM_TYPE_NONE); 128*6e9e277fSJerome Forissier 129*6e9e277fSJerome Forissier if (exp_pt != param_types) { 130*6e9e277fSJerome Forissier DMSG("got param_types 0x%x, expected 0x%x", 131*6e9e277fSJerome Forissier param_types, exp_pt); 132*6e9e277fSJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 133*6e9e277fSJerome Forissier } 134*6e9e277fSJerome Forissier 135*6e9e277fSJerome Forissier va = tee_fs_rpc_cache_alloc(params[1].memref.size, &mobj); 136*6e9e277fSJerome Forissier if (!va) 137*6e9e277fSJerome Forissier return TEE_ERROR_OUT_OF_MEMORY; 138*6e9e277fSJerome Forissier 139*6e9e277fSJerome Forissier struct thread_param tpm[3] = { 140*6e9e277fSJerome Forissier [0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SOCKET_RECV, instance_id, 141*6e9e277fSJerome Forissier params[0].value.a /* handle */), 142*6e9e277fSJerome Forissier [1] = THREAD_PARAM_MEMREF(OUT, mobj, 0, params[1].memref.size), 143*6e9e277fSJerome Forissier [2] = THREAD_PARAM_VALUE(IN, params[0].value.b /* timeout */, 144*6e9e277fSJerome Forissier 0, 0), 145*6e9e277fSJerome Forissier }; 146*6e9e277fSJerome Forissier 147*6e9e277fSJerome Forissier res = thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 3, tpm); 148*6e9e277fSJerome Forissier 149*6e9e277fSJerome Forissier if (tpm[1].u.memref.size > params[1].memref.size) 150*6e9e277fSJerome Forissier return TEE_ERROR_GENERIC; 151*6e9e277fSJerome Forissier params[1].memref.size = tpm[1].u.memref.size; 152*6e9e277fSJerome Forissier if (params[1].memref.size) 153*6e9e277fSJerome Forissier memcpy(params[1].memref.buffer, va, params[1].memref.size); 154*6e9e277fSJerome Forissier 155*6e9e277fSJerome Forissier return res; 156*6e9e277fSJerome Forissier } 157*6e9e277fSJerome Forissier 158*6e9e277fSJerome Forissier static TEE_Result socket_ioctl(uint32_t instance_id, uint32_t param_types, 159*6e9e277fSJerome Forissier TEE_Param params[TEE_NUM_PARAMS]) 160*6e9e277fSJerome Forissier { 161*6e9e277fSJerome Forissier struct mobj *mobj; 162*6e9e277fSJerome Forissier TEE_Result res; 163*6e9e277fSJerome Forissier void *va; 164*6e9e277fSJerome Forissier uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 165*6e9e277fSJerome Forissier TEE_PARAM_TYPE_MEMREF_INOUT, 166*6e9e277fSJerome Forissier TEE_PARAM_TYPE_NONE, 167*6e9e277fSJerome Forissier TEE_PARAM_TYPE_NONE); 168*6e9e277fSJerome Forissier 169*6e9e277fSJerome Forissier if (exp_pt != param_types) { 170*6e9e277fSJerome Forissier DMSG("got param_types 0x%x, expected 0x%x", 171*6e9e277fSJerome Forissier param_types, exp_pt); 172*6e9e277fSJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 173*6e9e277fSJerome Forissier } 174*6e9e277fSJerome Forissier 175*6e9e277fSJerome Forissier va = tee_fs_rpc_cache_alloc(params[1].memref.size, &mobj); 176*6e9e277fSJerome Forissier if (!va) 177*6e9e277fSJerome Forissier return TEE_ERROR_OUT_OF_MEMORY; 178*6e9e277fSJerome Forissier 179*6e9e277fSJerome Forissier memcpy(va, params[1].memref.buffer, params[1].memref.size); 180*6e9e277fSJerome Forissier 181*6e9e277fSJerome Forissier struct thread_param tpm[3] = { 182*6e9e277fSJerome Forissier [0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SOCKET_IOCTL, 183*6e9e277fSJerome Forissier instance_id, 184*6e9e277fSJerome Forissier params[0].value.a /* handle */), 185*6e9e277fSJerome Forissier [1] = THREAD_PARAM_MEMREF(INOUT, mobj, 0, 186*6e9e277fSJerome Forissier params[1].memref.size), 187*6e9e277fSJerome Forissier [2] = THREAD_PARAM_VALUE(IN, 188*6e9e277fSJerome Forissier params[0].value.b /* ioctl command */, 189*6e9e277fSJerome Forissier 0, 0), 190*6e9e277fSJerome Forissier }; 191*6e9e277fSJerome Forissier 192*6e9e277fSJerome Forissier res = thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 3, tpm); 193*6e9e277fSJerome Forissier if (tpm[1].u.memref.size <= params[1].memref.size) 194*6e9e277fSJerome Forissier memcpy(params[1].memref.buffer, va, tpm[1].u.memref.size); 195*6e9e277fSJerome Forissier 196*6e9e277fSJerome Forissier params[1].memref.size = tpm[1].u.memref.size; 197*6e9e277fSJerome Forissier 198*6e9e277fSJerome Forissier return res; 199*6e9e277fSJerome Forissier } 200*6e9e277fSJerome Forissier 201*6e9e277fSJerome Forissier typedef TEE_Result (*ta_func)(uint32_t instance_id, uint32_t param_types, 202*6e9e277fSJerome Forissier TEE_Param params[TEE_NUM_PARAMS]); 203*6e9e277fSJerome Forissier 204*6e9e277fSJerome Forissier static const ta_func ta_funcs[] = { 205*6e9e277fSJerome Forissier [PTA_SOCKET_OPEN] = socket_open, 206*6e9e277fSJerome Forissier [PTA_SOCKET_CLOSE] = socket_close, 207*6e9e277fSJerome Forissier [PTA_SOCKET_SEND] = socket_send, 208*6e9e277fSJerome Forissier [PTA_SOCKET_RECV] = socket_recv, 209*6e9e277fSJerome Forissier [PTA_SOCKET_IOCTL] = socket_ioctl, 210*6e9e277fSJerome Forissier }; 211*6e9e277fSJerome Forissier 212*6e9e277fSJerome Forissier /* 213*6e9e277fSJerome Forissier * Trusted Application Entry Points 214*6e9e277fSJerome Forissier */ 215*6e9e277fSJerome Forissier 216*6e9e277fSJerome Forissier static TEE_Result pta_socket_open_session(uint32_t param_types __unused, 217*6e9e277fSJerome Forissier TEE_Param pParams[TEE_NUM_PARAMS] __unused, 218*6e9e277fSJerome Forissier void **sess_ctx) 219*6e9e277fSJerome Forissier { 220*6e9e277fSJerome Forissier struct tee_ta_session *s; 221*6e9e277fSJerome Forissier 222*6e9e277fSJerome Forissier /* Check that we're called from a TA */ 223*6e9e277fSJerome Forissier s = tee_ta_get_calling_session(); 224*6e9e277fSJerome Forissier if (!s) 225*6e9e277fSJerome Forissier return TEE_ERROR_ACCESS_DENIED; 226*6e9e277fSJerome Forissier 227*6e9e277fSJerome Forissier *sess_ctx = (void *)(vaddr_t)get_instance_id(s); 228*6e9e277fSJerome Forissier 229*6e9e277fSJerome Forissier return TEE_SUCCESS; 230*6e9e277fSJerome Forissier } 231*6e9e277fSJerome Forissier 232*6e9e277fSJerome Forissier static void pta_socket_close_session(void *sess_ctx) 233*6e9e277fSJerome Forissier { 234*6e9e277fSJerome Forissier TEE_Result res; 235*6e9e277fSJerome Forissier struct thread_param tpm = { 236*6e9e277fSJerome Forissier .attr = THREAD_PARAM_ATTR_VALUE_IN, .u.value = { 237*6e9e277fSJerome Forissier .a = OPTEE_RPC_SOCKET_CLOSE_ALL, .b = (vaddr_t)sess_ctx, 238*6e9e277fSJerome Forissier }, 239*6e9e277fSJerome Forissier }; 240*6e9e277fSJerome Forissier 241*6e9e277fSJerome Forissier res = thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 1, &tpm); 242*6e9e277fSJerome Forissier if (res != TEE_SUCCESS) 243*6e9e277fSJerome Forissier DMSG("OPTEE_RPC_SOCKET_CLOSE_ALL failed: %#" PRIx32, res); 244*6e9e277fSJerome Forissier } 245*6e9e277fSJerome Forissier 246*6e9e277fSJerome Forissier static TEE_Result pta_socket_invoke_command(void *sess_ctx, uint32_t cmd_id, 247*6e9e277fSJerome Forissier uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) 248*6e9e277fSJerome Forissier { 249*6e9e277fSJerome Forissier if (cmd_id < ARRAY_SIZE(ta_funcs) && ta_funcs[cmd_id]) 250*6e9e277fSJerome Forissier return ta_funcs[cmd_id]((vaddr_t)sess_ctx, param_types, params); 251*6e9e277fSJerome Forissier 252*6e9e277fSJerome Forissier return TEE_ERROR_NOT_IMPLEMENTED; 253*6e9e277fSJerome Forissier } 254*6e9e277fSJerome Forissier 255*6e9e277fSJerome Forissier pseudo_ta_register(.uuid = PTA_SOCKET_UUID, .name = "socket", 256*6e9e277fSJerome Forissier .flags = PTA_DEFAULT_FLAGS | TA_FLAG_CONCURRENT, 257*6e9e277fSJerome Forissier .open_session_entry_point = pta_socket_open_session, 258*6e9e277fSJerome Forissier .close_session_entry_point = pta_socket_close_session, 259*6e9e277fSJerome Forissier .invoke_command_entry_point = pta_socket_invoke_command); 260