diff options
author | Jerome Forissier <jerome@forissier.org> | 2019-09-13 14:59:59 +0200 |
---|---|---|
committer | Jérôme Forissier <jerome@forissier.org> | 2019-09-13 18:20:52 +0200 |
commit | 6e9e277f455a70e5b7f59cd7df5da419bc0697f8 (patch) | |
tree | 8ac92a26a07254e51ee83222042e7d1f9c00585e /core/tee/socket.c | |
parent | 5843bb755f152c7961130e90bba969b8a1ce8f64 (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.c | 259 |
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); |