1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2016-2017, Linaro Limited
4  */
5 
6 #include <pta_socket.h>
7 #include <tee_internal_api.h>
8 #include <tee_isocket.h>
9 #include <tee_tcpsocket.h>
10 #include <__tee_tcpsocket_defines_extensions.h>
11 #include <tee_udpsocket.h>
12 
13 #include "tee_socket_private.h"
14 
15 struct socket_ctx {
16 	uint32_t handle;
17 	uint32_t proto_error;
18 };
19 
tcp_open(TEE_iSocketHandle * ctx,void * setup,uint32_t * proto_error)20 static TEE_Result tcp_open(TEE_iSocketHandle *ctx, void *setup,
21 			   uint32_t *proto_error)
22 {
23 	TEE_Result res;
24 	struct socket_ctx *sock_ctx;
25 	TEE_tcpSocket_Setup *tcp_setup = setup;
26 
27 	if (!ctx || !setup || !proto_error)
28 		TEE_Panic(0);
29 
30 	*proto_error = TEE_SUCCESS;
31 
32 	sock_ctx = TEE_Malloc(sizeof(*sock_ctx), TEE_MALLOC_FILL_ZERO);
33 	if (!sock_ctx)
34 		return TEE_ERROR_OUT_OF_MEMORY;
35 
36 	res = __tee_socket_pta_open(tcp_setup->ipVersion,
37 				    tcp_setup->server_addr,
38 				    tcp_setup->server_port,
39 				    TEE_ISOCKET_PROTOCOLID_TCP,
40 				    &sock_ctx->handle);
41 	if (res != TEE_SUCCESS) {
42 		TEE_Free(sock_ctx);
43 		sock_ctx = NULL;
44 	}
45 	*ctx = (TEE_iSocketHandle)sock_ctx;
46 
47 	switch (res) {
48 	case TEE_ISOCKET_ERROR_HOSTNAME:
49 		*proto_error = res;
50 		return TEE_ISOCKET_ERROR_PROTOCOL;
51 	case TEE_ISOCKET_TCP_WARNING_UNKNOWN_OUT_OF_BAND:
52 		*proto_error = res;
53 		return TEE_ISOCKET_WARNING_PROTOCOL;
54 	default:
55 		return res;
56 	}
57 }
58 
udp_open(TEE_iSocketHandle * ctx,void * setup,uint32_t * proto_error)59 static TEE_Result udp_open(TEE_iSocketHandle *ctx, void *setup,
60 			   uint32_t *proto_error)
61 {
62 	TEE_Result res;
63 	struct socket_ctx *sock_ctx;
64 	TEE_udpSocket_Setup *udp_setup = setup;
65 
66 	if (!ctx || !setup || !proto_error)
67 		TEE_Panic(0);
68 
69 	*proto_error = TEE_SUCCESS;
70 
71 	sock_ctx = TEE_Malloc(sizeof(*sock_ctx), TEE_MALLOC_FILL_ZERO);
72 	if (!sock_ctx)
73 		return TEE_ERROR_OUT_OF_MEMORY;
74 
75 	res = __tee_socket_pta_open(udp_setup->ipVersion,
76 				    udp_setup->server_addr,
77 				    udp_setup->server_port,
78 				    TEE_ISOCKET_PROTOCOLID_UDP,
79 				    &sock_ctx->handle);
80 	if (res != TEE_SUCCESS) {
81 		TEE_Free(sock_ctx);
82 		sock_ctx = NULL;
83 	}
84 	*ctx = (TEE_iSocketHandle)sock_ctx;
85 
86 	switch (res) {
87 	case TEE_ISOCKET_ERROR_HOSTNAME:
88 		*proto_error = res;
89 		return TEE_ISOCKET_ERROR_PROTOCOL;
90 	case TEE_ISOCKET_UDP_WARNING_UNKNOWN_OUT_OF_BAND:
91 		*proto_error = res;
92 		return TEE_ISOCKET_WARNING_PROTOCOL;
93 	default:
94 		return res;
95 	}
96 }
97 
sock_close(TEE_iSocketHandle ctx)98 static TEE_Result sock_close(TEE_iSocketHandle ctx)
99 {
100 	TEE_Result res;
101 	struct socket_ctx *sock_ctx = (struct socket_ctx *)ctx;
102 
103 	if (ctx == TEE_HANDLE_NULL)
104 		return TEE_SUCCESS;
105 
106 	res = __tee_socket_pta_close(sock_ctx->handle);
107 	TEE_Free(sock_ctx);
108 
109 	return res;
110 }
111 
sock_send(TEE_iSocketHandle ctx,const void * buf,uint32_t * length,uint32_t timeout)112 static TEE_Result sock_send(TEE_iSocketHandle ctx, const void *buf,
113 			   uint32_t *length, uint32_t timeout)
114 {
115 	TEE_Result res;
116 	struct socket_ctx *sock_ctx = (struct socket_ctx *)ctx;
117 
118 	if (ctx == TEE_HANDLE_NULL || !buf || !length)
119 		TEE_Panic(0);
120 
121 	res = __tee_socket_pta_send(sock_ctx->handle, buf, length, timeout);
122 	sock_ctx->proto_error = res;
123 
124 	return res;
125 }
126 
sock_recv(TEE_iSocketHandle ctx,void * buf,uint32_t * length,uint32_t timeout)127 static TEE_Result sock_recv(TEE_iSocketHandle ctx, void *buf, uint32_t *length,
128 			   uint32_t timeout)
129 {
130 	TEE_Result res;
131 	struct socket_ctx *sock_ctx = (struct socket_ctx *)ctx;
132 
133 	if (ctx == TEE_HANDLE_NULL || !length || (!buf && *length))
134 		TEE_Panic(0);
135 
136 	res = __tee_socket_pta_recv(sock_ctx->handle, buf, length, timeout);
137 	sock_ctx->proto_error = res;
138 
139 	return res;
140 }
141 
sock_error(TEE_iSocketHandle ctx)142 static uint32_t sock_error(TEE_iSocketHandle ctx)
143 {
144 	struct socket_ctx *sock_ctx = (struct socket_ctx *)ctx;
145 
146 	if (ctx == TEE_HANDLE_NULL)
147 		TEE_Panic(0);
148 
149 	return sock_ctx->proto_error;
150 }
151 
tcp_ioctl(TEE_iSocketHandle ctx,uint32_t commandCode,void * buf,uint32_t * length)152 static TEE_Result tcp_ioctl(TEE_iSocketHandle ctx, uint32_t commandCode,
153 			    void *buf, uint32_t *length)
154 {
155 	TEE_Result res = TEE_ERROR_GENERIC;
156 	struct socket_ctx *sock_ctx = (struct socket_ctx *)ctx;
157 
158 	if (ctx == TEE_HANDLE_NULL || !length || (!buf && *length))
159 		TEE_Panic(0);
160 
161 	if  (__tee_socket_ioctl_cmd_to_proto(commandCode) == 0)
162 		return TEE_SUCCESS;
163 
164 	switch (commandCode) {
165 	case TEE_TCP_SET_RECVBUF:
166 	case TEE_TCP_SET_SENDBUF:
167 		res = __tee_socket_pta_ioctl(sock_ctx->handle, commandCode,
168 					     buf, length);
169 		break;
170 	default:
171 		TEE_Panic(0);
172 	}
173 
174 	sock_ctx->proto_error = res;
175 
176 	return res;
177 }
178 
udp_ioctl(TEE_iSocketHandle ctx,uint32_t commandCode,void * buf,uint32_t * length)179 static TEE_Result udp_ioctl(TEE_iSocketHandle ctx, uint32_t commandCode,
180 			    void *buf, uint32_t *length)
181 {
182 	TEE_Result res = TEE_ERROR_GENERIC;
183 	struct socket_ctx *sock_ctx = (struct socket_ctx *)ctx;
184 
185 	if (ctx == TEE_HANDLE_NULL || !length || (!buf && *length))
186 		TEE_Panic(0);
187 
188 	if  (__tee_socket_ioctl_cmd_to_proto(commandCode) == 0)
189 		return TEE_SUCCESS;
190 
191 	switch (commandCode) {
192 	case TEE_UDP_CHANGEADDR:
193 	case TEE_UDP_CHANGEPORT:
194 		res = __tee_socket_pta_ioctl(sock_ctx->handle, commandCode,
195 					     buf, length);
196 		break;
197 	default:
198 		TEE_Panic(0);
199 	}
200 
201 	sock_ctx->proto_error = res;
202 
203 	return res;
204 }
205 
206 
207 
208 static TEE_iSocket tcp_socket_instance = {
209 	.TEE_iSocketVersion = TEE_ISOCKET_VERSION,
210 	.protocolID = TEE_ISOCKET_PROTOCOLID_TCP,
211 	.open = tcp_open,
212 	.close = sock_close,
213 	.send = sock_send,
214 	.recv = sock_recv,
215 	.error = sock_error,
216 	.ioctl = tcp_ioctl,
217 };
218 
219 static TEE_iSocket udp_socket_instance = {
220 	.TEE_iSocketVersion = TEE_ISOCKET_VERSION,
221 	.protocolID = TEE_ISOCKET_PROTOCOLID_UDP,
222 	.open = udp_open,
223 	.close = sock_close,
224 	.send = sock_send,
225 	.recv = sock_recv,
226 	.error = sock_error,
227 	.ioctl = udp_ioctl,
228 };
229 
230 TEE_iSocket *const TEE_tcpSocket = &tcp_socket_instance;
231 TEE_iSocket *const TEE_udpSocket = &udp_socket_instance;
232