xref: /optee_os/core/tee/socket.c (revision 9bee8f2a5af7ad5219a65d6f12ff25771f3325c0)
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*9bee8f2aSJens Wiklander 	va = thread_rpc_shm_cache_alloc(THREAD_SHM_TYPE_APPLICATION,
37*9bee8f2aSJens Wiklander 					params[1].memref.size, &mobj);
386e9e277fSJerome Forissier 	if (!va)
396e9e277fSJerome Forissier 		return TEE_ERROR_OUT_OF_MEMORY;
406e9e277fSJerome Forissier 
416e9e277fSJerome Forissier 	memcpy(va, params[1].memref.buffer, params[1].memref.size);
426e9e277fSJerome Forissier 
436e9e277fSJerome Forissier 	struct thread_param tpm[4] = {
446e9e277fSJerome Forissier 		[0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SOCKET_OPEN,
456e9e277fSJerome Forissier 					 instance_id, 0),
466e9e277fSJerome Forissier 		[1] = THREAD_PARAM_VALUE(IN,
476e9e277fSJerome Forissier 				params[0].value.b, /* server port number */
486e9e277fSJerome Forissier 				params[2].value.a, /* protocol */
496e9e277fSJerome Forissier 				params[0].value.a  /* ip version */),
506e9e277fSJerome Forissier 		[2] = THREAD_PARAM_MEMREF(IN, mobj, 0, params[1].memref.size),
516e9e277fSJerome Forissier 		[3] = THREAD_PARAM_VALUE(OUT, 0, 0, 0),
526e9e277fSJerome Forissier 	};
536e9e277fSJerome Forissier 
546e9e277fSJerome Forissier 	res = thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 4, tpm);
556e9e277fSJerome Forissier 	if (res == TEE_SUCCESS)
566e9e277fSJerome Forissier 		params[3].value.a = tpm[3].u.value.a;
576e9e277fSJerome Forissier 
586e9e277fSJerome Forissier 	return res;
596e9e277fSJerome Forissier }
606e9e277fSJerome Forissier 
616e9e277fSJerome Forissier static TEE_Result socket_close(uint32_t instance_id, uint32_t param_types,
626e9e277fSJerome Forissier 			       TEE_Param params[TEE_NUM_PARAMS])
636e9e277fSJerome Forissier {
646e9e277fSJerome Forissier 	uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
656e9e277fSJerome Forissier 					  TEE_PARAM_TYPE_NONE,
666e9e277fSJerome Forissier 					  TEE_PARAM_TYPE_NONE,
676e9e277fSJerome Forissier 					  TEE_PARAM_TYPE_NONE);
686e9e277fSJerome Forissier 
696e9e277fSJerome Forissier 	if (exp_pt != param_types) {
706e9e277fSJerome Forissier 		DMSG("got param_types 0x%x, expected 0x%x",
716e9e277fSJerome Forissier 		     param_types, exp_pt);
726e9e277fSJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
736e9e277fSJerome Forissier 	}
746e9e277fSJerome Forissier 
756e9e277fSJerome Forissier 	struct thread_param tpm = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SOCKET_CLOSE,
766e9e277fSJerome Forissier 						     instance_id,
776e9e277fSJerome Forissier 						     params[0].value.a);
786e9e277fSJerome Forissier 
796e9e277fSJerome Forissier 	return thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 1, &tpm);
806e9e277fSJerome Forissier }
816e9e277fSJerome Forissier 
826e9e277fSJerome Forissier static TEE_Result socket_send(uint32_t instance_id, uint32_t param_types,
836e9e277fSJerome Forissier 			      TEE_Param params[TEE_NUM_PARAMS])
846e9e277fSJerome Forissier {
856e9e277fSJerome Forissier 	struct mobj *mobj;
866e9e277fSJerome Forissier 	TEE_Result res;
876e9e277fSJerome Forissier 	void *va;
886e9e277fSJerome Forissier 	uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
896e9e277fSJerome Forissier 					  TEE_PARAM_TYPE_MEMREF_INPUT,
906e9e277fSJerome Forissier 					  TEE_PARAM_TYPE_VALUE_OUTPUT,
916e9e277fSJerome Forissier 					  TEE_PARAM_TYPE_NONE);
926e9e277fSJerome Forissier 
936e9e277fSJerome Forissier 	if (exp_pt != param_types) {
946e9e277fSJerome Forissier 		DMSG("got param_types 0x%x, expected 0x%x",
956e9e277fSJerome Forissier 		     param_types, exp_pt);
966e9e277fSJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
976e9e277fSJerome Forissier 	}
986e9e277fSJerome Forissier 
99*9bee8f2aSJens Wiklander 	va = thread_rpc_shm_cache_alloc(THREAD_SHM_TYPE_APPLICATION,
100*9bee8f2aSJens Wiklander 					params[1].memref.size, &mobj);
1016e9e277fSJerome Forissier 	if (!va)
1026e9e277fSJerome Forissier 		return TEE_ERROR_OUT_OF_MEMORY;
1036e9e277fSJerome Forissier 
1046e9e277fSJerome Forissier 	memcpy(va, params[1].memref.buffer, params[1].memref.size);
1056e9e277fSJerome Forissier 
1066e9e277fSJerome Forissier 	struct thread_param tpm[3] = {
1076e9e277fSJerome Forissier 		[0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SOCKET_SEND, instance_id,
1086e9e277fSJerome Forissier 					 params[0].value.a /* handle */),
1096e9e277fSJerome Forissier 		[1] = THREAD_PARAM_MEMREF(IN, mobj, 0, params[1].memref.size),
1106e9e277fSJerome Forissier 		[2] = THREAD_PARAM_VALUE(INOUT, params[0].value.b, /* timeout */
1116e9e277fSJerome Forissier 					 0, 0),
1126e9e277fSJerome Forissier 	};
1136e9e277fSJerome Forissier 
1146e9e277fSJerome Forissier 	res = thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 3, tpm);
1156e9e277fSJerome Forissier 	params[2].value.a = tpm[2].u.value.b; /* transmitted bytes */
1166e9e277fSJerome Forissier 
1176e9e277fSJerome Forissier 	return res;
1186e9e277fSJerome Forissier }
1196e9e277fSJerome Forissier 
1206e9e277fSJerome Forissier static TEE_Result socket_recv(uint32_t instance_id, uint32_t param_types,
1216e9e277fSJerome Forissier 			      TEE_Param params[TEE_NUM_PARAMS])
1226e9e277fSJerome Forissier {
1236e9e277fSJerome Forissier 	struct mobj *mobj;
1246e9e277fSJerome Forissier 	TEE_Result res;
1256e9e277fSJerome Forissier 	void *va;
1266e9e277fSJerome Forissier 	uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
1276e9e277fSJerome Forissier 					  TEE_PARAM_TYPE_MEMREF_OUTPUT,
1286e9e277fSJerome Forissier 					  TEE_PARAM_TYPE_NONE,
1296e9e277fSJerome Forissier 					  TEE_PARAM_TYPE_NONE);
1306e9e277fSJerome Forissier 
1316e9e277fSJerome Forissier 	if (exp_pt != param_types) {
1326e9e277fSJerome Forissier 		DMSG("got param_types 0x%x, expected 0x%x",
1336e9e277fSJerome Forissier 		     param_types, exp_pt);
1346e9e277fSJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
1356e9e277fSJerome Forissier 	}
1366e9e277fSJerome Forissier 
137*9bee8f2aSJens Wiklander 	va = thread_rpc_shm_cache_alloc(THREAD_SHM_TYPE_APPLICATION,
138*9bee8f2aSJens Wiklander 					params[1].memref.size, &mobj);
1396e9e277fSJerome Forissier 	if (!va)
1406e9e277fSJerome Forissier 		return TEE_ERROR_OUT_OF_MEMORY;
1416e9e277fSJerome Forissier 
1426e9e277fSJerome Forissier 	struct thread_param tpm[3] = {
1436e9e277fSJerome Forissier 		[0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SOCKET_RECV, instance_id,
1446e9e277fSJerome Forissier 					 params[0].value.a /* handle */),
1456e9e277fSJerome Forissier 		[1] = THREAD_PARAM_MEMREF(OUT, mobj, 0, params[1].memref.size),
1466e9e277fSJerome Forissier 		[2] = THREAD_PARAM_VALUE(IN, params[0].value.b /* timeout */,
1476e9e277fSJerome Forissier 					 0, 0),
1486e9e277fSJerome Forissier 	};
1496e9e277fSJerome Forissier 
1506e9e277fSJerome Forissier 	res = thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 3, tpm);
1516e9e277fSJerome Forissier 
1526e9e277fSJerome Forissier 	if (tpm[1].u.memref.size > params[1].memref.size)
1536e9e277fSJerome Forissier 		return TEE_ERROR_GENERIC;
1546e9e277fSJerome Forissier 	params[1].memref.size = tpm[1].u.memref.size;
1556e9e277fSJerome Forissier 	if (params[1].memref.size)
1566e9e277fSJerome Forissier 		memcpy(params[1].memref.buffer, va, params[1].memref.size);
1576e9e277fSJerome Forissier 
1586e9e277fSJerome Forissier 	return res;
1596e9e277fSJerome Forissier }
1606e9e277fSJerome Forissier 
1616e9e277fSJerome Forissier static TEE_Result socket_ioctl(uint32_t instance_id, uint32_t param_types,
1626e9e277fSJerome Forissier 			       TEE_Param params[TEE_NUM_PARAMS])
1636e9e277fSJerome Forissier {
1646e9e277fSJerome Forissier 	struct mobj *mobj;
1656e9e277fSJerome Forissier 	TEE_Result res;
1666e9e277fSJerome Forissier 	void *va;
1676e9e277fSJerome Forissier 	uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
1686e9e277fSJerome Forissier 					  TEE_PARAM_TYPE_MEMREF_INOUT,
1696e9e277fSJerome Forissier 					  TEE_PARAM_TYPE_NONE,
1706e9e277fSJerome Forissier 					  TEE_PARAM_TYPE_NONE);
1716e9e277fSJerome Forissier 
1726e9e277fSJerome Forissier 	if (exp_pt != param_types) {
1736e9e277fSJerome Forissier 		DMSG("got param_types 0x%x, expected 0x%x",
1746e9e277fSJerome Forissier 		     param_types, exp_pt);
1756e9e277fSJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
1766e9e277fSJerome Forissier 	}
1776e9e277fSJerome Forissier 
178*9bee8f2aSJens Wiklander 	va = thread_rpc_shm_cache_alloc(THREAD_SHM_TYPE_APPLICATION,
179*9bee8f2aSJens Wiklander 					params[1].memref.size, &mobj);
1806e9e277fSJerome Forissier 	if (!va)
1816e9e277fSJerome Forissier 		return TEE_ERROR_OUT_OF_MEMORY;
1826e9e277fSJerome Forissier 
1836e9e277fSJerome Forissier 	memcpy(va, params[1].memref.buffer, params[1].memref.size);
1846e9e277fSJerome Forissier 
1856e9e277fSJerome Forissier 	struct thread_param tpm[3] = {
1866e9e277fSJerome Forissier 		[0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SOCKET_IOCTL,
1876e9e277fSJerome Forissier 					 instance_id,
1886e9e277fSJerome Forissier 					 params[0].value.a /* handle */),
1896e9e277fSJerome Forissier 		[1] = THREAD_PARAM_MEMREF(INOUT, mobj, 0,
1906e9e277fSJerome Forissier 					  params[1].memref.size),
1916e9e277fSJerome Forissier 		[2] = THREAD_PARAM_VALUE(IN,
1926e9e277fSJerome Forissier 					 params[0].value.b /* ioctl command */,
1936e9e277fSJerome Forissier 					 0, 0),
1946e9e277fSJerome Forissier 	};
1956e9e277fSJerome Forissier 
1966e9e277fSJerome Forissier 	res = thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 3, tpm);
1976e9e277fSJerome Forissier 	if (tpm[1].u.memref.size <= params[1].memref.size)
1986e9e277fSJerome Forissier 		memcpy(params[1].memref.buffer, va, tpm[1].u.memref.size);
1996e9e277fSJerome Forissier 
2006e9e277fSJerome Forissier 	params[1].memref.size = tpm[1].u.memref.size;
2016e9e277fSJerome Forissier 
2026e9e277fSJerome Forissier 	return res;
2036e9e277fSJerome Forissier }
2046e9e277fSJerome Forissier 
2056e9e277fSJerome Forissier typedef TEE_Result (*ta_func)(uint32_t instance_id, uint32_t param_types,
2066e9e277fSJerome Forissier 			      TEE_Param params[TEE_NUM_PARAMS]);
2076e9e277fSJerome Forissier 
2086e9e277fSJerome Forissier static const ta_func ta_funcs[] = {
2096e9e277fSJerome Forissier 	[PTA_SOCKET_OPEN] = socket_open,
2106e9e277fSJerome Forissier 	[PTA_SOCKET_CLOSE] = socket_close,
2116e9e277fSJerome Forissier 	[PTA_SOCKET_SEND] = socket_send,
2126e9e277fSJerome Forissier 	[PTA_SOCKET_RECV] = socket_recv,
2136e9e277fSJerome Forissier 	[PTA_SOCKET_IOCTL] = socket_ioctl,
2146e9e277fSJerome Forissier };
2156e9e277fSJerome Forissier 
2166e9e277fSJerome Forissier /*
2176e9e277fSJerome Forissier  * Trusted Application Entry Points
2186e9e277fSJerome Forissier  */
2196e9e277fSJerome Forissier 
2206e9e277fSJerome Forissier static TEE_Result pta_socket_open_session(uint32_t param_types __unused,
2216e9e277fSJerome Forissier 			TEE_Param pParams[TEE_NUM_PARAMS] __unused,
2226e9e277fSJerome Forissier 			void **sess_ctx)
2236e9e277fSJerome Forissier {
2246e9e277fSJerome Forissier 	struct tee_ta_session *s;
2256e9e277fSJerome Forissier 
2266e9e277fSJerome Forissier 	/* Check that we're called from a TA */
2276e9e277fSJerome Forissier 	s = tee_ta_get_calling_session();
2286e9e277fSJerome Forissier 	if (!s)
2296e9e277fSJerome Forissier 		return TEE_ERROR_ACCESS_DENIED;
2306e9e277fSJerome Forissier 
2316e9e277fSJerome Forissier 	*sess_ctx = (void *)(vaddr_t)get_instance_id(s);
2326e9e277fSJerome Forissier 
2336e9e277fSJerome Forissier 	return TEE_SUCCESS;
2346e9e277fSJerome Forissier }
2356e9e277fSJerome Forissier 
2366e9e277fSJerome Forissier static void pta_socket_close_session(void *sess_ctx)
2376e9e277fSJerome Forissier {
2386e9e277fSJerome Forissier 	TEE_Result res;
2396e9e277fSJerome Forissier 	struct thread_param tpm = {
2406e9e277fSJerome Forissier 		.attr = THREAD_PARAM_ATTR_VALUE_IN, .u.value = {
2416e9e277fSJerome Forissier 			.a = OPTEE_RPC_SOCKET_CLOSE_ALL, .b = (vaddr_t)sess_ctx,
2426e9e277fSJerome Forissier 		},
2436e9e277fSJerome Forissier 	};
2446e9e277fSJerome Forissier 
2456e9e277fSJerome Forissier 	res = thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 1, &tpm);
2466e9e277fSJerome Forissier 	if (res != TEE_SUCCESS)
2476e9e277fSJerome Forissier 		DMSG("OPTEE_RPC_SOCKET_CLOSE_ALL failed: %#" PRIx32, res);
2486e9e277fSJerome Forissier }
2496e9e277fSJerome Forissier 
2506e9e277fSJerome Forissier static TEE_Result pta_socket_invoke_command(void *sess_ctx, uint32_t cmd_id,
2516e9e277fSJerome Forissier 			uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS])
2526e9e277fSJerome Forissier {
2536e9e277fSJerome Forissier 	if (cmd_id < ARRAY_SIZE(ta_funcs) && ta_funcs[cmd_id])
2546e9e277fSJerome Forissier 		return ta_funcs[cmd_id]((vaddr_t)sess_ctx, param_types, params);
2556e9e277fSJerome Forissier 
2566e9e277fSJerome Forissier 	return TEE_ERROR_NOT_IMPLEMENTED;
2576e9e277fSJerome Forissier }
2586e9e277fSJerome Forissier 
2596e9e277fSJerome Forissier pseudo_ta_register(.uuid = PTA_SOCKET_UUID, .name = "socket",
2606e9e277fSJerome Forissier 		   .flags = PTA_DEFAULT_FLAGS | TA_FLAG_CONCURRENT,
2616e9e277fSJerome Forissier 		   .open_session_entry_point = pta_socket_open_session,
2626e9e277fSJerome Forissier 		   .close_session_entry_point = pta_socket_close_session,
2636e9e277fSJerome Forissier 		   .invoke_command_entry_point = pta_socket_invoke_command);
264