summaryrefslogtreecommitdiff
path: root/core/tee/socket.c
diff options
context:
space:
mode:
authorJerome Forissier <jerome@forissier.org>2019-09-13 14:59:59 +0200
committerJérôme Forissier <jerome@forissier.org>2019-09-13 18:20:52 +0200
commit6e9e277f455a70e5b7f59cd7df5da419bc0697f8 (patch)
tree8ac92a26a07254e51ee83222042e7d1f9c00585e /core/tee/socket.c
parent5843bb755f152c7961130e90bba969b8a1ce8f64 (diff)
core: move sockets PTA to core/tee
The sockets pseudo-TA is architecture-independent. Move it to core/tee and drop the pta_ prefix which is not really useful. Signed-off-by: Jerome Forissier <jerome@forissier.org> Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org>
Diffstat (limited to 'core/tee/socket.c')
-rw-r--r--core/tee/socket.c259
1 files changed, 259 insertions, 0 deletions
diff --git a/core/tee/socket.c b/core/tee/socket.c
new file mode 100644
index 00000000..5ced5802
--- /dev/null
+++ b/core/tee/socket.c
@@ -0,0 +1,259 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2016-2017, Linaro Limited
+ */
+
+#include <assert.h>
+#include <mm/mobj.h>
+#include <kernel/pseudo_ta.h>
+#include <optee_rpc_cmd.h>
+#include <pta_socket.h>
+#include <string.h>
+#include <tee/tee_fs_rpc.h>
+
+static uint32_t get_instance_id(struct tee_ta_session *sess)
+{
+ return sess->ctx->ops->get_instance_id(sess->ctx);
+}
+
+static TEE_Result socket_open(uint32_t instance_id, uint32_t param_types,
+ TEE_Param params[TEE_NUM_PARAMS])
+{
+ struct mobj *mobj;
+ TEE_Result res;
+ void *va;
+ uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
+ TEE_PARAM_TYPE_MEMREF_INPUT,
+ TEE_PARAM_TYPE_VALUE_INPUT,
+ TEE_PARAM_TYPE_VALUE_OUTPUT);
+
+ if (exp_pt != param_types) {
+ DMSG("got param_types 0x%x, expected 0x%x",
+ param_types, exp_pt);
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ va = tee_fs_rpc_cache_alloc(params[1].memref.size, &mobj);
+ if (!va)
+ return TEE_ERROR_OUT_OF_MEMORY;
+
+ memcpy(va, params[1].memref.buffer, params[1].memref.size);
+
+ struct thread_param tpm[4] = {
+ [0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SOCKET_OPEN,
+ instance_id, 0),
+ [1] = THREAD_PARAM_VALUE(IN,
+ params[0].value.b, /* server port number */
+ params[2].value.a, /* protocol */
+ params[0].value.a /* ip version */),
+ [2] = THREAD_PARAM_MEMREF(IN, mobj, 0, params[1].memref.size),
+ [3] = THREAD_PARAM_VALUE(OUT, 0, 0, 0),
+ };
+
+ res = thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 4, tpm);
+ if (res == TEE_SUCCESS)
+ params[3].value.a = tpm[3].u.value.a;
+
+ return res;
+}
+
+static TEE_Result socket_close(uint32_t instance_id, uint32_t param_types,
+ TEE_Param params[TEE_NUM_PARAMS])
+{
+ uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
+ TEE_PARAM_TYPE_NONE,
+ TEE_PARAM_TYPE_NONE,
+ TEE_PARAM_TYPE_NONE);
+
+ if (exp_pt != param_types) {
+ DMSG("got param_types 0x%x, expected 0x%x",
+ param_types, exp_pt);
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ struct thread_param tpm = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SOCKET_CLOSE,
+ instance_id,
+ params[0].value.a);
+
+ return thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 1, &tpm);
+}
+
+static TEE_Result socket_send(uint32_t instance_id, uint32_t param_types,
+ TEE_Param params[TEE_NUM_PARAMS])
+{
+ struct mobj *mobj;
+ TEE_Result res;
+ void *va;
+ uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
+ TEE_PARAM_TYPE_MEMREF_INPUT,
+ TEE_PARAM_TYPE_VALUE_OUTPUT,
+ TEE_PARAM_TYPE_NONE);
+
+ if (exp_pt != param_types) {
+ DMSG("got param_types 0x%x, expected 0x%x",
+ param_types, exp_pt);
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ va = tee_fs_rpc_cache_alloc(params[1].memref.size, &mobj);
+ if (!va)
+ return TEE_ERROR_OUT_OF_MEMORY;
+
+ memcpy(va, params[1].memref.buffer, params[1].memref.size);
+
+ struct thread_param tpm[3] = {
+ [0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SOCKET_SEND, instance_id,
+ params[0].value.a /* handle */),
+ [1] = THREAD_PARAM_MEMREF(IN, mobj, 0, params[1].memref.size),
+ [2] = THREAD_PARAM_VALUE(INOUT, params[0].value.b, /* timeout */
+ 0, 0),
+ };
+
+ res = thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 3, tpm);
+ params[2].value.a = tpm[2].u.value.b; /* transmitted bytes */
+
+ return res;
+}
+
+static TEE_Result socket_recv(uint32_t instance_id, uint32_t param_types,
+ TEE_Param params[TEE_NUM_PARAMS])
+{
+ struct mobj *mobj;
+ TEE_Result res;
+ void *va;
+ uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
+ TEE_PARAM_TYPE_MEMREF_OUTPUT,
+ TEE_PARAM_TYPE_NONE,
+ TEE_PARAM_TYPE_NONE);
+
+ if (exp_pt != param_types) {
+ DMSG("got param_types 0x%x, expected 0x%x",
+ param_types, exp_pt);
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ va = tee_fs_rpc_cache_alloc(params[1].memref.size, &mobj);
+ if (!va)
+ return TEE_ERROR_OUT_OF_MEMORY;
+
+ struct thread_param tpm[3] = {
+ [0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SOCKET_RECV, instance_id,
+ params[0].value.a /* handle */),
+ [1] = THREAD_PARAM_MEMREF(OUT, mobj, 0, params[1].memref.size),
+ [2] = THREAD_PARAM_VALUE(IN, params[0].value.b /* timeout */,
+ 0, 0),
+ };
+
+ res = thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 3, tpm);
+
+ if (tpm[1].u.memref.size > params[1].memref.size)
+ return TEE_ERROR_GENERIC;
+ params[1].memref.size = tpm[1].u.memref.size;
+ if (params[1].memref.size)
+ memcpy(params[1].memref.buffer, va, params[1].memref.size);
+
+ return res;
+}
+
+static TEE_Result socket_ioctl(uint32_t instance_id, uint32_t param_types,
+ TEE_Param params[TEE_NUM_PARAMS])
+{
+ struct mobj *mobj;
+ TEE_Result res;
+ void *va;
+ uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
+ TEE_PARAM_TYPE_MEMREF_INOUT,
+ TEE_PARAM_TYPE_NONE,
+ TEE_PARAM_TYPE_NONE);
+
+ if (exp_pt != param_types) {
+ DMSG("got param_types 0x%x, expected 0x%x",
+ param_types, exp_pt);
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ va = tee_fs_rpc_cache_alloc(params[1].memref.size, &mobj);
+ if (!va)
+ return TEE_ERROR_OUT_OF_MEMORY;
+
+ memcpy(va, params[1].memref.buffer, params[1].memref.size);
+
+ struct thread_param tpm[3] = {
+ [0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SOCKET_IOCTL,
+ instance_id,
+ params[0].value.a /* handle */),
+ [1] = THREAD_PARAM_MEMREF(INOUT, mobj, 0,
+ params[1].memref.size),
+ [2] = THREAD_PARAM_VALUE(IN,
+ params[0].value.b /* ioctl command */,
+ 0, 0),
+ };
+
+ res = thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 3, tpm);
+ if (tpm[1].u.memref.size <= params[1].memref.size)
+ memcpy(params[1].memref.buffer, va, tpm[1].u.memref.size);
+
+ params[1].memref.size = tpm[1].u.memref.size;
+
+ return res;
+}
+
+typedef TEE_Result (*ta_func)(uint32_t instance_id, uint32_t param_types,
+ TEE_Param params[TEE_NUM_PARAMS]);
+
+static const ta_func ta_funcs[] = {
+ [PTA_SOCKET_OPEN] = socket_open,
+ [PTA_SOCKET_CLOSE] = socket_close,
+ [PTA_SOCKET_SEND] = socket_send,
+ [PTA_SOCKET_RECV] = socket_recv,
+ [PTA_SOCKET_IOCTL] = socket_ioctl,
+};
+
+/*
+ * Trusted Application Entry Points
+ */
+
+static TEE_Result pta_socket_open_session(uint32_t param_types __unused,
+ TEE_Param pParams[TEE_NUM_PARAMS] __unused,
+ void **sess_ctx)
+{
+ struct tee_ta_session *s;
+
+ /* Check that we're called from a TA */
+ s = tee_ta_get_calling_session();
+ if (!s)
+ return TEE_ERROR_ACCESS_DENIED;
+
+ *sess_ctx = (void *)(vaddr_t)get_instance_id(s);
+
+ return TEE_SUCCESS;
+}
+
+static void pta_socket_close_session(void *sess_ctx)
+{
+ TEE_Result res;
+ struct thread_param tpm = {
+ .attr = THREAD_PARAM_ATTR_VALUE_IN, .u.value = {
+ .a = OPTEE_RPC_SOCKET_CLOSE_ALL, .b = (vaddr_t)sess_ctx,
+ },
+ };
+
+ res = thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 1, &tpm);
+ if (res != TEE_SUCCESS)
+ DMSG("OPTEE_RPC_SOCKET_CLOSE_ALL failed: %#" PRIx32, res);
+}
+
+static TEE_Result pta_socket_invoke_command(void *sess_ctx, uint32_t cmd_id,
+ uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS])
+{
+ if (cmd_id < ARRAY_SIZE(ta_funcs) && ta_funcs[cmd_id])
+ return ta_funcs[cmd_id]((vaddr_t)sess_ctx, param_types, params);
+
+ return TEE_ERROR_NOT_IMPLEMENTED;
+}
+
+pseudo_ta_register(.uuid = PTA_SOCKET_UUID, .name = "socket",
+ .flags = PTA_DEFAULT_FLAGS | TA_FLAG_CONCURRENT,
+ .open_session_entry_point = pta_socket_open_session,
+ .close_session_entry_point = pta_socket_close_session,
+ .invoke_command_entry_point = pta_socket_invoke_command);