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