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