xref: /optee_os/core/tee/socket.c (revision 1a7d8eae372f72e36f4d08674f09fe72c4f64d6a)
16e9e277fSJerome Forissier // SPDX-License-Identifier: BSD-2-Clause
26e9e277fSJerome Forissier /*
36e9e277fSJerome Forissier  * Copyright (c) 2016-2017, Linaro Limited
46e9e277fSJerome Forissier  */
56e9e277fSJerome Forissier 
66e9e277fSJerome Forissier #include <assert.h>
76e9e277fSJerome Forissier #include <mm/mobj.h>
86e9e277fSJerome Forissier #include <kernel/pseudo_ta.h>
96e9e277fSJerome Forissier #include <optee_rpc_cmd.h>
106e9e277fSJerome Forissier #include <pta_socket.h>
116e9e277fSJerome Forissier #include <string.h>
126e9e277fSJerome Forissier #include <tee/tee_fs_rpc.h>
136e9e277fSJerome Forissier 
146e9e277fSJerome Forissier static uint32_t get_instance_id(struct tee_ta_session *sess)
156e9e277fSJerome Forissier {
166e9e277fSJerome Forissier 	return sess->ctx->ops->get_instance_id(sess->ctx);
176e9e277fSJerome Forissier }
186e9e277fSJerome Forissier 
196e9e277fSJerome Forissier static TEE_Result socket_open(uint32_t instance_id, uint32_t param_types,
206e9e277fSJerome Forissier 			      TEE_Param params[TEE_NUM_PARAMS])
216e9e277fSJerome Forissier {
226e9e277fSJerome Forissier 	struct mobj *mobj;
236e9e277fSJerome Forissier 	TEE_Result res;
246e9e277fSJerome Forissier 	void *va;
256e9e277fSJerome Forissier 	uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
266e9e277fSJerome Forissier 					  TEE_PARAM_TYPE_MEMREF_INPUT,
276e9e277fSJerome Forissier 					  TEE_PARAM_TYPE_VALUE_INPUT,
286e9e277fSJerome Forissier 					  TEE_PARAM_TYPE_VALUE_OUTPUT);
296e9e277fSJerome Forissier 
306e9e277fSJerome Forissier 	if (exp_pt != param_types) {
316e9e277fSJerome Forissier 		DMSG("got param_types 0x%x, expected 0x%x",
326e9e277fSJerome Forissier 		     param_types, exp_pt);
336e9e277fSJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
346e9e277fSJerome Forissier 	}
356e9e277fSJerome Forissier 
36*1a7d8eaeSJens Wiklander 	va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_SOCKET,
37*1a7d8eaeSJens Wiklander 					THREAD_SHM_TYPE_APPLICATION,
389bee8f2aSJens Wiklander 					params[1].memref.size, &mobj);
396e9e277fSJerome Forissier 	if (!va)
406e9e277fSJerome Forissier 		return TEE_ERROR_OUT_OF_MEMORY;
416e9e277fSJerome Forissier 
426e9e277fSJerome Forissier 	memcpy(va, params[1].memref.buffer, params[1].memref.size);
436e9e277fSJerome Forissier 
446e9e277fSJerome Forissier 	struct thread_param tpm[4] = {
456e9e277fSJerome Forissier 		[0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SOCKET_OPEN,
466e9e277fSJerome Forissier 					 instance_id, 0),
476e9e277fSJerome Forissier 		[1] = THREAD_PARAM_VALUE(IN,
486e9e277fSJerome Forissier 				params[0].value.b, /* server port number */
496e9e277fSJerome Forissier 				params[2].value.a, /* protocol */
506e9e277fSJerome Forissier 				params[0].value.a  /* ip version */),
516e9e277fSJerome Forissier 		[2] = THREAD_PARAM_MEMREF(IN, mobj, 0, params[1].memref.size),
526e9e277fSJerome Forissier 		[3] = THREAD_PARAM_VALUE(OUT, 0, 0, 0),
536e9e277fSJerome Forissier 	};
546e9e277fSJerome Forissier 
556e9e277fSJerome Forissier 	res = thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 4, tpm);
566e9e277fSJerome Forissier 	if (res == TEE_SUCCESS)
576e9e277fSJerome Forissier 		params[3].value.a = tpm[3].u.value.a;
586e9e277fSJerome Forissier 
596e9e277fSJerome Forissier 	return res;
606e9e277fSJerome Forissier }
616e9e277fSJerome Forissier 
626e9e277fSJerome Forissier static TEE_Result socket_close(uint32_t instance_id, uint32_t param_types,
636e9e277fSJerome Forissier 			       TEE_Param params[TEE_NUM_PARAMS])
646e9e277fSJerome Forissier {
656e9e277fSJerome Forissier 	uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
666e9e277fSJerome Forissier 					  TEE_PARAM_TYPE_NONE,
676e9e277fSJerome Forissier 					  TEE_PARAM_TYPE_NONE,
686e9e277fSJerome Forissier 					  TEE_PARAM_TYPE_NONE);
696e9e277fSJerome Forissier 
706e9e277fSJerome Forissier 	if (exp_pt != param_types) {
716e9e277fSJerome Forissier 		DMSG("got param_types 0x%x, expected 0x%x",
726e9e277fSJerome Forissier 		     param_types, exp_pt);
736e9e277fSJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
746e9e277fSJerome Forissier 	}
756e9e277fSJerome Forissier 
766e9e277fSJerome Forissier 	struct thread_param tpm = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SOCKET_CLOSE,
776e9e277fSJerome Forissier 						     instance_id,
786e9e277fSJerome Forissier 						     params[0].value.a);
796e9e277fSJerome Forissier 
806e9e277fSJerome Forissier 	return thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 1, &tpm);
816e9e277fSJerome Forissier }
826e9e277fSJerome Forissier 
836e9e277fSJerome Forissier static TEE_Result socket_send(uint32_t instance_id, uint32_t param_types,
846e9e277fSJerome Forissier 			      TEE_Param params[TEE_NUM_PARAMS])
856e9e277fSJerome Forissier {
866e9e277fSJerome Forissier 	struct mobj *mobj;
876e9e277fSJerome Forissier 	TEE_Result res;
886e9e277fSJerome Forissier 	void *va;
896e9e277fSJerome Forissier 	uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
906e9e277fSJerome Forissier 					  TEE_PARAM_TYPE_MEMREF_INPUT,
916e9e277fSJerome Forissier 					  TEE_PARAM_TYPE_VALUE_OUTPUT,
926e9e277fSJerome Forissier 					  TEE_PARAM_TYPE_NONE);
936e9e277fSJerome Forissier 
946e9e277fSJerome Forissier 	if (exp_pt != param_types) {
956e9e277fSJerome Forissier 		DMSG("got param_types 0x%x, expected 0x%x",
966e9e277fSJerome Forissier 		     param_types, exp_pt);
976e9e277fSJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
986e9e277fSJerome Forissier 	}
996e9e277fSJerome Forissier 
100*1a7d8eaeSJens Wiklander 	va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_SOCKET,
101*1a7d8eaeSJens Wiklander 					THREAD_SHM_TYPE_APPLICATION,
1029bee8f2aSJens Wiklander 					params[1].memref.size, &mobj);
1036e9e277fSJerome Forissier 	if (!va)
1046e9e277fSJerome Forissier 		return TEE_ERROR_OUT_OF_MEMORY;
1056e9e277fSJerome Forissier 
1066e9e277fSJerome Forissier 	memcpy(va, params[1].memref.buffer, params[1].memref.size);
1076e9e277fSJerome Forissier 
1086e9e277fSJerome Forissier 	struct thread_param tpm[3] = {
1096e9e277fSJerome Forissier 		[0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SOCKET_SEND, instance_id,
1106e9e277fSJerome Forissier 					 params[0].value.a /* handle */),
1116e9e277fSJerome Forissier 		[1] = THREAD_PARAM_MEMREF(IN, mobj, 0, params[1].memref.size),
1126e9e277fSJerome Forissier 		[2] = THREAD_PARAM_VALUE(INOUT, params[0].value.b, /* timeout */
1136e9e277fSJerome Forissier 					 0, 0),
1146e9e277fSJerome Forissier 	};
1156e9e277fSJerome Forissier 
1166e9e277fSJerome Forissier 	res = thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 3, tpm);
1176e9e277fSJerome Forissier 	params[2].value.a = tpm[2].u.value.b; /* transmitted bytes */
1186e9e277fSJerome Forissier 
1196e9e277fSJerome Forissier 	return res;
1206e9e277fSJerome Forissier }
1216e9e277fSJerome Forissier 
1226e9e277fSJerome Forissier static TEE_Result socket_recv(uint32_t instance_id, uint32_t param_types,
1236e9e277fSJerome Forissier 			      TEE_Param params[TEE_NUM_PARAMS])
1246e9e277fSJerome Forissier {
1256e9e277fSJerome Forissier 	struct mobj *mobj;
1266e9e277fSJerome Forissier 	TEE_Result res;
1276e9e277fSJerome Forissier 	void *va;
1286e9e277fSJerome Forissier 	uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
1296e9e277fSJerome Forissier 					  TEE_PARAM_TYPE_MEMREF_OUTPUT,
1306e9e277fSJerome Forissier 					  TEE_PARAM_TYPE_NONE,
1316e9e277fSJerome Forissier 					  TEE_PARAM_TYPE_NONE);
1326e9e277fSJerome Forissier 
1336e9e277fSJerome Forissier 	if (exp_pt != param_types) {
1346e9e277fSJerome Forissier 		DMSG("got param_types 0x%x, expected 0x%x",
1356e9e277fSJerome Forissier 		     param_types, exp_pt);
1366e9e277fSJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
1376e9e277fSJerome Forissier 	}
1386e9e277fSJerome Forissier 
139*1a7d8eaeSJens Wiklander 	va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_SOCKET,
140*1a7d8eaeSJens Wiklander 					THREAD_SHM_TYPE_APPLICATION,
1419bee8f2aSJens Wiklander 					params[1].memref.size, &mobj);
1426e9e277fSJerome Forissier 	if (!va)
1436e9e277fSJerome Forissier 		return TEE_ERROR_OUT_OF_MEMORY;
1446e9e277fSJerome Forissier 
1456e9e277fSJerome Forissier 	struct thread_param tpm[3] = {
1466e9e277fSJerome Forissier 		[0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SOCKET_RECV, instance_id,
1476e9e277fSJerome Forissier 					 params[0].value.a /* handle */),
1486e9e277fSJerome Forissier 		[1] = THREAD_PARAM_MEMREF(OUT, mobj, 0, params[1].memref.size),
1496e9e277fSJerome Forissier 		[2] = THREAD_PARAM_VALUE(IN, params[0].value.b /* timeout */,
1506e9e277fSJerome Forissier 					 0, 0),
1516e9e277fSJerome Forissier 	};
1526e9e277fSJerome Forissier 
1536e9e277fSJerome Forissier 	res = thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 3, tpm);
1546e9e277fSJerome Forissier 
1556e9e277fSJerome Forissier 	if (tpm[1].u.memref.size > params[1].memref.size)
1566e9e277fSJerome Forissier 		return TEE_ERROR_GENERIC;
1576e9e277fSJerome Forissier 	params[1].memref.size = tpm[1].u.memref.size;
1586e9e277fSJerome Forissier 	if (params[1].memref.size)
1596e9e277fSJerome Forissier 		memcpy(params[1].memref.buffer, va, params[1].memref.size);
1606e9e277fSJerome Forissier 
1616e9e277fSJerome Forissier 	return res;
1626e9e277fSJerome Forissier }
1636e9e277fSJerome Forissier 
1646e9e277fSJerome Forissier static TEE_Result socket_ioctl(uint32_t instance_id, uint32_t param_types,
1656e9e277fSJerome Forissier 			       TEE_Param params[TEE_NUM_PARAMS])
1666e9e277fSJerome Forissier {
1676e9e277fSJerome Forissier 	struct mobj *mobj;
1686e9e277fSJerome Forissier 	TEE_Result res;
1696e9e277fSJerome Forissier 	void *va;
1706e9e277fSJerome Forissier 	uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
1716e9e277fSJerome Forissier 					  TEE_PARAM_TYPE_MEMREF_INOUT,
1726e9e277fSJerome Forissier 					  TEE_PARAM_TYPE_NONE,
1736e9e277fSJerome Forissier 					  TEE_PARAM_TYPE_NONE);
1746e9e277fSJerome Forissier 
1756e9e277fSJerome Forissier 	if (exp_pt != param_types) {
1766e9e277fSJerome Forissier 		DMSG("got param_types 0x%x, expected 0x%x",
1776e9e277fSJerome Forissier 		     param_types, exp_pt);
1786e9e277fSJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
1796e9e277fSJerome Forissier 	}
1806e9e277fSJerome Forissier 
181*1a7d8eaeSJens Wiklander 	va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_SOCKET,
182*1a7d8eaeSJens Wiklander 					THREAD_SHM_TYPE_APPLICATION,
1839bee8f2aSJens Wiklander 					params[1].memref.size, &mobj);
1846e9e277fSJerome Forissier 	if (!va)
1856e9e277fSJerome Forissier 		return TEE_ERROR_OUT_OF_MEMORY;
1866e9e277fSJerome Forissier 
1876e9e277fSJerome Forissier 	memcpy(va, params[1].memref.buffer, params[1].memref.size);
1886e9e277fSJerome Forissier 
1896e9e277fSJerome Forissier 	struct thread_param tpm[3] = {
1906e9e277fSJerome Forissier 		[0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SOCKET_IOCTL,
1916e9e277fSJerome Forissier 					 instance_id,
1926e9e277fSJerome Forissier 					 params[0].value.a /* handle */),
1936e9e277fSJerome Forissier 		[1] = THREAD_PARAM_MEMREF(INOUT, mobj, 0,
1946e9e277fSJerome Forissier 					  params[1].memref.size),
1956e9e277fSJerome Forissier 		[2] = THREAD_PARAM_VALUE(IN,
1966e9e277fSJerome Forissier 					 params[0].value.b /* ioctl command */,
1976e9e277fSJerome Forissier 					 0, 0),
1986e9e277fSJerome Forissier 	};
1996e9e277fSJerome Forissier 
2006e9e277fSJerome Forissier 	res = thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 3, tpm);
2016e9e277fSJerome Forissier 	if (tpm[1].u.memref.size <= params[1].memref.size)
2026e9e277fSJerome Forissier 		memcpy(params[1].memref.buffer, va, tpm[1].u.memref.size);
2036e9e277fSJerome Forissier 
2046e9e277fSJerome Forissier 	params[1].memref.size = tpm[1].u.memref.size;
2056e9e277fSJerome Forissier 
2066e9e277fSJerome Forissier 	return res;
2076e9e277fSJerome Forissier }
2086e9e277fSJerome Forissier 
2096e9e277fSJerome Forissier typedef TEE_Result (*ta_func)(uint32_t instance_id, uint32_t param_types,
2106e9e277fSJerome Forissier 			      TEE_Param params[TEE_NUM_PARAMS]);
2116e9e277fSJerome Forissier 
2126e9e277fSJerome Forissier static const ta_func ta_funcs[] = {
2136e9e277fSJerome Forissier 	[PTA_SOCKET_OPEN] = socket_open,
2146e9e277fSJerome Forissier 	[PTA_SOCKET_CLOSE] = socket_close,
2156e9e277fSJerome Forissier 	[PTA_SOCKET_SEND] = socket_send,
2166e9e277fSJerome Forissier 	[PTA_SOCKET_RECV] = socket_recv,
2176e9e277fSJerome Forissier 	[PTA_SOCKET_IOCTL] = socket_ioctl,
2186e9e277fSJerome Forissier };
2196e9e277fSJerome Forissier 
2206e9e277fSJerome Forissier /*
2216e9e277fSJerome Forissier  * Trusted Application Entry Points
2226e9e277fSJerome Forissier  */
2236e9e277fSJerome Forissier 
2246e9e277fSJerome Forissier static TEE_Result pta_socket_open_session(uint32_t param_types __unused,
2256e9e277fSJerome Forissier 			TEE_Param pParams[TEE_NUM_PARAMS] __unused,
2266e9e277fSJerome Forissier 			void **sess_ctx)
2276e9e277fSJerome Forissier {
2286e9e277fSJerome Forissier 	struct tee_ta_session *s;
2296e9e277fSJerome Forissier 
2306e9e277fSJerome Forissier 	/* Check that we're called from a TA */
2316e9e277fSJerome Forissier 	s = tee_ta_get_calling_session();
2326e9e277fSJerome Forissier 	if (!s)
2336e9e277fSJerome Forissier 		return TEE_ERROR_ACCESS_DENIED;
2346e9e277fSJerome Forissier 
2356e9e277fSJerome Forissier 	*sess_ctx = (void *)(vaddr_t)get_instance_id(s);
2366e9e277fSJerome Forissier 
2376e9e277fSJerome Forissier 	return TEE_SUCCESS;
2386e9e277fSJerome Forissier }
2396e9e277fSJerome Forissier 
2406e9e277fSJerome Forissier static void pta_socket_close_session(void *sess_ctx)
2416e9e277fSJerome Forissier {
2426e9e277fSJerome Forissier 	TEE_Result res;
2436e9e277fSJerome Forissier 	struct thread_param tpm = {
2446e9e277fSJerome Forissier 		.attr = THREAD_PARAM_ATTR_VALUE_IN, .u.value = {
2456e9e277fSJerome Forissier 			.a = OPTEE_RPC_SOCKET_CLOSE_ALL, .b = (vaddr_t)sess_ctx,
2466e9e277fSJerome Forissier 		},
2476e9e277fSJerome Forissier 	};
2486e9e277fSJerome Forissier 
2496e9e277fSJerome Forissier 	res = thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 1, &tpm);
2506e9e277fSJerome Forissier 	if (res != TEE_SUCCESS)
2516e9e277fSJerome Forissier 		DMSG("OPTEE_RPC_SOCKET_CLOSE_ALL failed: %#" PRIx32, res);
2526e9e277fSJerome Forissier }
2536e9e277fSJerome Forissier 
2546e9e277fSJerome Forissier static TEE_Result pta_socket_invoke_command(void *sess_ctx, uint32_t cmd_id,
2556e9e277fSJerome Forissier 			uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS])
2566e9e277fSJerome Forissier {
2576e9e277fSJerome Forissier 	if (cmd_id < ARRAY_SIZE(ta_funcs) && ta_funcs[cmd_id])
2586e9e277fSJerome Forissier 		return ta_funcs[cmd_id]((vaddr_t)sess_ctx, param_types, params);
2596e9e277fSJerome Forissier 
2606e9e277fSJerome Forissier 	return TEE_ERROR_NOT_IMPLEMENTED;
2616e9e277fSJerome Forissier }
2626e9e277fSJerome Forissier 
2636e9e277fSJerome Forissier pseudo_ta_register(.uuid = PTA_SOCKET_UUID, .name = "socket",
2646e9e277fSJerome Forissier 		   .flags = PTA_DEFAULT_FLAGS | TA_FLAG_CONCURRENT,
2656e9e277fSJerome Forissier 		   .open_session_entry_point = pta_socket_open_session,
2666e9e277fSJerome Forissier 		   .close_session_entry_point = pta_socket_close_session,
2676e9e277fSJerome Forissier 		   .invoke_command_entry_point = pta_socket_invoke_command);
268