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