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