1 /* 2 * Copyright (c) 2016-2017, Linaro Limited 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include <pta_socket.h> 29 #include <tee_internal_api.h> 30 #include <tee_isocket.h> 31 #include <tee_tcpsocket.h> 32 #include <__tee_tcpsocket_defines_extensions.h> 33 #include <tee_udpsocket.h> 34 35 #include "tee_socket_private.h" 36 37 struct socket_ctx { 38 uint32_t handle; 39 uint32_t proto_error; 40 }; 41 42 static TEE_Result tcp_open(TEE_iSocketHandle *ctx, void *setup, 43 uint32_t *proto_error) 44 { 45 TEE_Result res; 46 struct socket_ctx *sock_ctx; 47 TEE_tcpSocket_Setup *tcp_setup = setup; 48 49 if (!ctx || !setup || !proto_error) 50 TEE_Panic(0); 51 52 *proto_error = TEE_SUCCESS; 53 54 sock_ctx = TEE_Malloc(sizeof(*sock_ctx), TEE_MALLOC_FILL_ZERO); 55 if (!sock_ctx) 56 return TEE_ERROR_OUT_OF_MEMORY; 57 58 res = __tee_socket_pta_open(tcp_setup->ipVersion, 59 tcp_setup->server_addr, 60 tcp_setup->server_port, 61 TEE_ISOCKET_PROTOCOLID_TCP, 62 &sock_ctx->handle); 63 if (res != TEE_SUCCESS) { 64 TEE_Free(sock_ctx); 65 sock_ctx = NULL; 66 } 67 *ctx = (TEE_iSocketHandle)sock_ctx; 68 69 switch (res) { 70 case TEE_ISOCKET_ERROR_HOSTNAME: 71 *proto_error = res; 72 return TEE_ISOCKET_ERROR_PROTOCOL; 73 case TEE_ISOCKET_TCP_WARNING_UNKNOWN_OUT_OF_BAND: 74 *proto_error = res; 75 return TEE_ISOCKET_WARNING_PROTOCOL; 76 default: 77 return res; 78 } 79 } 80 81 static TEE_Result udp_open(TEE_iSocketHandle *ctx, void *setup, 82 uint32_t *proto_error) 83 { 84 TEE_Result res; 85 struct socket_ctx *sock_ctx; 86 TEE_udpSocket_Setup *udp_setup = setup; 87 88 if (!ctx || !setup || !proto_error) 89 TEE_Panic(0); 90 91 *proto_error = TEE_SUCCESS; 92 93 sock_ctx = TEE_Malloc(sizeof(*sock_ctx), TEE_MALLOC_FILL_ZERO); 94 if (!sock_ctx) 95 return TEE_ERROR_OUT_OF_MEMORY; 96 97 res = __tee_socket_pta_open(udp_setup->ipVersion, 98 udp_setup->server_addr, 99 udp_setup->server_port, 100 TEE_ISOCKET_PROTOCOLID_UDP, 101 &sock_ctx->handle); 102 if (res != TEE_SUCCESS) { 103 TEE_Free(sock_ctx); 104 sock_ctx = NULL; 105 } 106 *ctx = (TEE_iSocketHandle)sock_ctx; 107 108 switch (res) { 109 case TEE_ISOCKET_ERROR_HOSTNAME: 110 *proto_error = res; 111 return TEE_ISOCKET_ERROR_PROTOCOL; 112 case TEE_ISOCKET_UDP_WARNING_UNKNOWN_OUT_OF_BAND: 113 *proto_error = res; 114 return TEE_ISOCKET_WARNING_PROTOCOL; 115 default: 116 return res; 117 } 118 } 119 120 static TEE_Result sock_close(TEE_iSocketHandle ctx) 121 { 122 TEE_Result res; 123 struct socket_ctx *sock_ctx = (struct socket_ctx *)ctx; 124 125 if (ctx == TEE_HANDLE_NULL) 126 return TEE_SUCCESS; 127 128 res = __tee_socket_pta_close(sock_ctx->handle); 129 TEE_Free(sock_ctx); 130 131 return res; 132 } 133 134 static TEE_Result sock_send(TEE_iSocketHandle ctx, const void *buf, 135 uint32_t *length, uint32_t timeout) 136 { 137 TEE_Result res; 138 struct socket_ctx *sock_ctx = (struct socket_ctx *)ctx; 139 140 if (ctx == TEE_HANDLE_NULL || !buf || !length) 141 TEE_Panic(0); 142 143 res = __tee_socket_pta_send(sock_ctx->handle, buf, length, timeout); 144 sock_ctx->proto_error = res; 145 146 return res; 147 } 148 149 static TEE_Result sock_recv(TEE_iSocketHandle ctx, void *buf, uint32_t *length, 150 uint32_t timeout) 151 { 152 TEE_Result res; 153 struct socket_ctx *sock_ctx = (struct socket_ctx *)ctx; 154 155 if (ctx == TEE_HANDLE_NULL || !length || (!buf && *length)) 156 TEE_Panic(0); 157 158 res = __tee_socket_pta_recv(sock_ctx->handle, buf, length, timeout); 159 sock_ctx->proto_error = res; 160 161 return res; 162 } 163 164 static uint32_t sock_error(TEE_iSocketHandle ctx) 165 { 166 struct socket_ctx *sock_ctx = (struct socket_ctx *)ctx; 167 168 if (ctx == TEE_HANDLE_NULL) 169 TEE_Panic(0); 170 171 return sock_ctx->proto_error; 172 } 173 174 static TEE_Result tcp_ioctl(TEE_iSocketHandle ctx, uint32_t commandCode, 175 void *buf, uint32_t *length) 176 { 177 TEE_Result res = TEE_ERROR_GENERIC; 178 struct socket_ctx *sock_ctx = (struct socket_ctx *)ctx; 179 180 if (ctx == TEE_HANDLE_NULL || !length || (!buf && *length)) 181 TEE_Panic(0); 182 183 if (__tee_socket_ioctl_cmd_to_proto(commandCode) == 0) 184 return TEE_SUCCESS; 185 186 switch (commandCode) { 187 case TEE_TCP_SET_RECVBUF: 188 case TEE_TCP_SET_SENDBUF: 189 res = __tee_socket_pta_ioctl(sock_ctx->handle, commandCode, 190 buf, length); 191 break; 192 default: 193 TEE_Panic(0); 194 } 195 196 sock_ctx->proto_error = res; 197 198 return res; 199 } 200 201 static TEE_Result udp_ioctl(TEE_iSocketHandle ctx, uint32_t commandCode, 202 void *buf, uint32_t *length) 203 { 204 TEE_Result res = TEE_ERROR_GENERIC; 205 struct socket_ctx *sock_ctx = (struct socket_ctx *)ctx; 206 207 if (ctx == TEE_HANDLE_NULL || !length || (!buf && *length)) 208 TEE_Panic(0); 209 210 if (__tee_socket_ioctl_cmd_to_proto(commandCode) == 0) 211 return TEE_SUCCESS; 212 213 switch (commandCode) { 214 case TEE_UDP_CHANGEADDR: 215 case TEE_UDP_CHANGEPORT: 216 res = __tee_socket_pta_ioctl(sock_ctx->handle, commandCode, 217 buf, length); 218 break; 219 default: 220 TEE_Panic(0); 221 } 222 223 sock_ctx->proto_error = res; 224 225 return res; 226 } 227 228 229 230 static TEE_iSocket tcp_socket_instance = { 231 .TEE_iSocketVersion = TEE_ISOCKET_VERSION, 232 .protocolID = TEE_ISOCKET_PROTOCOLID_TCP, 233 .open = &tcp_open, 234 .close = &sock_close, 235 .send = &sock_send, 236 .recv = &sock_recv, 237 .error = &sock_error, 238 .ioctl = &tcp_ioctl, 239 }; 240 241 static TEE_iSocket udp_socket_instance = { 242 .TEE_iSocketVersion = TEE_ISOCKET_VERSION, 243 .protocolID = TEE_ISOCKET_PROTOCOLID_UDP, 244 .open = &udp_open, 245 .close = &sock_close, 246 .send = &sock_send, 247 .recv = &sock_recv, 248 .error = &sock_error, 249 .ioctl = &udp_ioctl, 250 }; 251 252 TEE_iSocket *const TEE_tcpSocket = &tcp_socket_instance; 253 TEE_iSocket *const TEE_udpSocket = &udp_socket_instance; 254