// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2016-2017, Linaro Limited */ #include #include #include #include #include <__tee_tcpsocket_defines_extensions.h> #include #include "tee_socket_private.h" struct socket_ctx { uint32_t handle; uint32_t proto_error; }; static TEE_Result tcp_open(TEE_iSocketHandle *ctx, void *setup, uint32_t *proto_error) { TEE_Result res; struct socket_ctx *sock_ctx; TEE_tcpSocket_Setup *tcp_setup = setup; if (!ctx || !setup || !proto_error) TEE_Panic(0); *proto_error = TEE_SUCCESS; sock_ctx = TEE_Malloc(sizeof(*sock_ctx), TEE_MALLOC_FILL_ZERO); if (!sock_ctx) return TEE_ERROR_OUT_OF_MEMORY; res = __tee_socket_pta_open(tcp_setup->ipVersion, tcp_setup->server_addr, tcp_setup->server_port, TEE_ISOCKET_PROTOCOLID_TCP, &sock_ctx->handle); if (res != TEE_SUCCESS) { TEE_Free(sock_ctx); sock_ctx = NULL; } *ctx = (TEE_iSocketHandle)sock_ctx; switch (res) { case TEE_ISOCKET_ERROR_HOSTNAME: *proto_error = res; return TEE_ISOCKET_ERROR_PROTOCOL; case TEE_ISOCKET_TCP_WARNING_UNKNOWN_OUT_OF_BAND: *proto_error = res; return TEE_ISOCKET_WARNING_PROTOCOL; default: return res; } } static TEE_Result udp_open(TEE_iSocketHandle *ctx, void *setup, uint32_t *proto_error) { TEE_Result res; struct socket_ctx *sock_ctx; TEE_udpSocket_Setup *udp_setup = setup; if (!ctx || !setup || !proto_error) TEE_Panic(0); *proto_error = TEE_SUCCESS; sock_ctx = TEE_Malloc(sizeof(*sock_ctx), TEE_MALLOC_FILL_ZERO); if (!sock_ctx) return TEE_ERROR_OUT_OF_MEMORY; res = __tee_socket_pta_open(udp_setup->ipVersion, udp_setup->server_addr, udp_setup->server_port, TEE_ISOCKET_PROTOCOLID_UDP, &sock_ctx->handle); if (res != TEE_SUCCESS) { TEE_Free(sock_ctx); sock_ctx = NULL; } *ctx = (TEE_iSocketHandle)sock_ctx; switch (res) { case TEE_ISOCKET_ERROR_HOSTNAME: *proto_error = res; return TEE_ISOCKET_ERROR_PROTOCOL; case TEE_ISOCKET_UDP_WARNING_UNKNOWN_OUT_OF_BAND: *proto_error = res; return TEE_ISOCKET_WARNING_PROTOCOL; default: return res; } } static TEE_Result sock_close(TEE_iSocketHandle ctx) { TEE_Result res; struct socket_ctx *sock_ctx = (struct socket_ctx *)ctx; if (ctx == TEE_HANDLE_NULL) return TEE_SUCCESS; res = __tee_socket_pta_close(sock_ctx->handle); TEE_Free(sock_ctx); return res; } static TEE_Result sock_send(TEE_iSocketHandle ctx, const void *buf, uint32_t *length, uint32_t timeout) { TEE_Result res; struct socket_ctx *sock_ctx = (struct socket_ctx *)ctx; if (ctx == TEE_HANDLE_NULL || !buf || !length) TEE_Panic(0); res = __tee_socket_pta_send(sock_ctx->handle, buf, length, timeout); sock_ctx->proto_error = res; return res; } static TEE_Result sock_recv(TEE_iSocketHandle ctx, void *buf, uint32_t *length, uint32_t timeout) { TEE_Result res; struct socket_ctx *sock_ctx = (struct socket_ctx *)ctx; if (ctx == TEE_HANDLE_NULL || !length || (!buf && *length)) TEE_Panic(0); res = __tee_socket_pta_recv(sock_ctx->handle, buf, length, timeout); sock_ctx->proto_error = res; return res; } static uint32_t sock_error(TEE_iSocketHandle ctx) { struct socket_ctx *sock_ctx = (struct socket_ctx *)ctx; if (ctx == TEE_HANDLE_NULL) TEE_Panic(0); return sock_ctx->proto_error; } static TEE_Result tcp_ioctl(TEE_iSocketHandle ctx, uint32_t commandCode, void *buf, uint32_t *length) { TEE_Result res = TEE_ERROR_GENERIC; struct socket_ctx *sock_ctx = (struct socket_ctx *)ctx; if (ctx == TEE_HANDLE_NULL || !length || (!buf && *length)) TEE_Panic(0); if (__tee_socket_ioctl_cmd_to_proto(commandCode) == 0) return TEE_SUCCESS; switch (commandCode) { case TEE_TCP_SET_RECVBUF: case TEE_TCP_SET_SENDBUF: res = __tee_socket_pta_ioctl(sock_ctx->handle, commandCode, buf, length); break; default: TEE_Panic(0); } sock_ctx->proto_error = res; return res; } static TEE_Result udp_ioctl(TEE_iSocketHandle ctx, uint32_t commandCode, void *buf, uint32_t *length) { TEE_Result res = TEE_ERROR_GENERIC; struct socket_ctx *sock_ctx = (struct socket_ctx *)ctx; if (ctx == TEE_HANDLE_NULL || !length || (!buf && *length)) TEE_Panic(0); if (__tee_socket_ioctl_cmd_to_proto(commandCode) == 0) return TEE_SUCCESS; switch (commandCode) { case TEE_UDP_CHANGEADDR: case TEE_UDP_CHANGEPORT: res = __tee_socket_pta_ioctl(sock_ctx->handle, commandCode, buf, length); break; default: TEE_Panic(0); } sock_ctx->proto_error = res; return res; } static TEE_iSocket tcp_socket_instance = { .TEE_iSocketVersion = TEE_ISOCKET_VERSION, .protocolID = TEE_ISOCKET_PROTOCOLID_TCP, .open = tcp_open, .close = sock_close, .send = sock_send, .recv = sock_recv, .error = sock_error, .ioctl = tcp_ioctl, }; static TEE_iSocket udp_socket_instance = { .TEE_iSocketVersion = TEE_ISOCKET_VERSION, .protocolID = TEE_ISOCKET_PROTOCOLID_UDP, .open = udp_open, .close = sock_close, .send = sock_send, .recv = sock_recv, .error = sock_error, .ioctl = udp_ioctl, }; TEE_iSocket *const TEE_tcpSocket = &tcp_socket_instance; TEE_iSocket *const TEE_udpSocket = &udp_socket_instance;