From de8465cd14de5d1e44a2cced05e200d354e0dc3a Mon Sep 17 00:00:00 2001 From: Patrik Flykt Date: Wed, 18 Apr 2018 11:34:23 +0300 Subject: [PATCH 01/24] net: socket: Define getsockopt() and setsockopt() Define the socket option functions and make them return -EOPNOTSUPP. Signed-off-by: Patrik Flykt --- include/net/socket.h | 39 ++++++++++++++++++++++++++++++++ subsys/net/lib/sockets/sockets.c | 16 +++++++++++++ 2 files changed, 55 insertions(+) diff --git a/include/net/socket.h b/include/net/socket.h index f7890ab1cc0e6..b3b7d9993913a 100644 --- a/include/net/socket.h +++ b/include/net/socket.h @@ -75,6 +75,10 @@ int zsock_inet_pton(sa_family_t family, const char *src, void *dst); int zsock_getaddrinfo(const char *host, const char *service, const struct zsock_addrinfo *hints, struct zsock_addrinfo **res); +int zsock_getsockopt(int sock, int level, int optname, + void *optval, socklen_t *optlen); +int zsock_setsockopt(int sock, int level, int optname, + const void *optval, socklen_t optlen); #if defined(CONFIG_NET_SOCKETS_POSIX_NAMES) static inline int socket(int family, int type, int proto) @@ -175,6 +179,41 @@ static inline void freeaddrinfo(struct zsock_addrinfo *ai) #define EAI_AGAIN DNS_EAI_AGAIN #define EAI_FAIL DNS_EAI_FAIL #define EAI_NODATA DNS_EAI_NODATA + +/** + * @brief Access socket option values + * + * @param sock The socket that the operation refers to + * @param level Protocol level the option applies to + * @param optname Numerical value of the option to access + * @param optval Location, i.e. buffer, where to store the option value + * @param optlen Size of the option value location, i.e. buffer + * + * @return 0 on success, -1 on error with errno set to the error value + */ +static inline int getsockopt(int sock, int level, int optname, + void *optval, socklen_t *optlen) +{ + return zsock_getsockopt(sock, level, optname, optval, optlen); +} + +/** + * @brief Set socket option values + * + * @param sock The socket that the option refers to + * @param level Protocol level the option applies to + * @param optname Numerical value of the option to set + * @param optval Location, i.e. buffer, that contains the option value + * @param optlen Size of the option value location, i.e. buffer + * + * @return 0 on success, -1 on error with errno set to the error value + */ +static inline int setsockopt(int sock, int level, int optname, + const void *optval, socklen_t optlen) +{ + return zsock_setsockopt(sock, level, optname, optval, optlen); +} + #endif /* defined(CONFIG_NET_SOCKETS_POSIX_NAMES) */ #ifdef __cplusplus diff --git a/subsys/net/lib/sockets/sockets.c b/subsys/net/lib/sockets/sockets.c index 5bcd771f5909d..258124421149b 100644 --- a/subsys/net/lib/sockets/sockets.c +++ b/subsys/net/lib/sockets/sockets.c @@ -577,3 +577,19 @@ int zsock_inet_pton(sa_family_t family, const char *src, void *dst) return 0; } } + +int zsock_getsockopt(int sock, int level, int optname, + void *optval, socklen_t *optlen) +{ + SET_ERRNO(-EOPNOTSUPP); + + return 0; +} + +int zsock_setsockopt(int sock, int level, int optname, + const void *optval, socklen_t optlen) +{ + SET_ERRNO(-EOPNOTSUPP); + + return 0; +} From 5303cb5d1b5087c100d50204bd50f898957ffb9f Mon Sep 17 00:00:00 2001 From: Patrik Flykt Date: Wed, 18 Apr 2018 11:34:42 +0300 Subject: [PATCH 02/24] net: socket: Add TLS getsockopt and setsockopt functions Call getsockopt and setsockopt for TLS when the socket level is set to SOL_TCP. Verify the option to be TCP_TLS and that the context type is SOCK_STREAM. Signed-off-by: Patrik Flykt --- include/net/socket.h | 6 +++ subsys/net/lib/sockets/CMakeLists.txt | 2 + subsys/net/lib/sockets/Kconfig | 7 ++++ subsys/net/lib/sockets/sockets.c | 40 +++++++++++++++++- subsys/net/lib/sockets/sockets_tls.c | 60 +++++++++++++++++++++++++++ subsys/net/lib/sockets/sockets_tls.h | 47 +++++++++++++++++++++ 6 files changed, 160 insertions(+), 2 deletions(-) create mode 100644 subsys/net/lib/sockets/sockets_tls.c create mode 100644 subsys/net/lib/sockets/sockets_tls.h diff --git a/include/net/socket.h b/include/net/socket.h index b3b7d9993913a..a810f4e248db5 100644 --- a/include/net/socket.h +++ b/include/net/socket.h @@ -43,6 +43,12 @@ struct zsock_pollfd { #define ZSOCK_MSG_PEEK 0x02 #define ZSOCK_MSG_DONTWAIT 0x40 +/* socket option for TCP */ +#define SOL_TCP 6 + +/* TCP socket options */ +#define TCP_TLS 0xff + struct zsock_addrinfo { struct zsock_addrinfo *ai_next; int ai_flags; diff --git a/subsys/net/lib/sockets/CMakeLists.txt b/subsys/net/lib/sockets/CMakeLists.txt index 94ed549b22131..a2f1b942d9eab 100644 --- a/subsys/net/lib/sockets/CMakeLists.txt +++ b/subsys/net/lib/sockets/CMakeLists.txt @@ -3,3 +3,5 @@ zephyr_sources( getaddrinfo.c sockets.c ) + +zephyr_sources_ifdef(CONFIG_NET_SOCKETS_SOCKOPT_TLS sockets_tls.c) diff --git a/subsys/net/lib/sockets/Kconfig b/subsys/net/lib/sockets/Kconfig index 561af3de53376..6620e8bc9ffec 100644 --- a/subsys/net/lib/sockets/Kconfig +++ b/subsys/net/lib/sockets/Kconfig @@ -32,6 +32,13 @@ config NET_SOCKETS_POLL_MAX help Maximum number of entries supported for poll() call. +config NET_SOCKETS_SOCKOPT_TLS + bool "Enable TCP TLS socket option support" + default n + help + Enable TCP TLS socket option support which automatically establishes + a TLS connection to the remote host. + config NET_DEBUG_SOCKETS bool "Debug BSD Sockets compatible API calls" default n diff --git a/subsys/net/lib/sockets/sockets.c b/subsys/net/lib/sockets/sockets.c index 258124421149b..808149a661150 100644 --- a/subsys/net/lib/sockets/sockets.c +++ b/subsys/net/lib/sockets/sockets.c @@ -18,6 +18,8 @@ #include #include +#include "sockets_tls.h" + #define SOCK_EOF 1 #define SOCK_NONBLOCK 2 @@ -581,7 +583,24 @@ int zsock_inet_pton(sa_family_t family, const char *src, void *dst) int zsock_getsockopt(int sock, int level, int optname, void *optval, socklen_t *optlen) { - SET_ERRNO(-EOPNOTSUPP); + int ret = 0; + + if (!sock) { + SET_ERRNO(-ENOTSOCK); + } + + switch (level) { + case SOL_TCP: + /* TLS is the only one implemented right now */ + ret = tls_getsockopt(sock, level, optname, optval, optlen); + break; + + default: + ret = -EOPNOTSUPP; + break; + } + + SET_ERRNO(ret); return 0; } @@ -589,7 +608,24 @@ int zsock_getsockopt(int sock, int level, int optname, int zsock_setsockopt(int sock, int level, int optname, const void *optval, socklen_t optlen) { - SET_ERRNO(-EOPNOTSUPP); + int ret = 0; + + if (!sock) { + SET_ERRNO(-ENOTSOCK); + } + + switch (level) { + case SOL_TCP: + /* TLS is the only one implemented right now */ + ret = tls_setsockopt(sock, level, optname, optval, optlen); + break; + + default: + ret = -EOPNOTSUPP; + break; + } + + SET_ERRNO(ret); return 0; } diff --git a/subsys/net/lib/sockets/sockets_tls.c b/subsys/net/lib/sockets/sockets_tls.c new file mode 100644 index 0000000000000..27ff0120ec636 --- /dev/null +++ b/subsys/net/lib/sockets/sockets_tls.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include "sockets_tls.h" + +int tls_getsockopt(int sock, int level, int optname, + void *optval, socklen_t *optlen) +{ + struct net_context *ctx = INT_TO_POINTER(sock); + int ret = 0; + + if (net_context_get_type(ctx) != SOCK_STREAM) { + return -EBADF; + } + + if (!optval || !optlen || !*optlen) { + return -EFAULT; + } + + switch (optname) { + case TCP_TLS: + break; + + default: + return -ENOPROTOOPT; + } + + return ret; +} + +int tls_setsockopt(int sock, int level, int optname, + const void *optval, socklen_t optlen) +{ + struct net_context *ctx = INT_TO_POINTER(sock); + int ret = 0; + + if (net_context_get_type(ctx) != SOCK_STREAM) { + return -EBADF; + } + + if (!optval || !optlen) { + return -EFAULT; + } + + switch (optname) { + case TCP_TLS: + break; + + default: + return -ENOPROTOOPT; + } + + return ret; +} diff --git a/subsys/net/lib/sockets/sockets_tls.h b/subsys/net/lib/sockets/sockets_tls.h new file mode 100644 index 0000000000000..c386a1fd6b415 --- /dev/null +++ b/subsys/net/lib/sockets/sockets_tls.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2018 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _SOCKETS_TLS_H_ +#define _SOCKETS_TLS_H_ + +#include + +#ifdef CONFIG_NET_SOCKETS_SOCKOPT_TLS + +int tls_getsockopt(int sock, int level, int optname, + void *optval, socklen_t *optlen); +int tls_setsockopt(int sock, int level, int optname, + const void *optval, socklen_t optlen); + +#else + +static inline int tls_getsockopt(int sock, int level, int optname, + const void *optval, socklen_t *optlen) +{ + ARG_UNUSED(sock); + ARG_UNUSED(level); + ARG_UNUSED(optname); + ARG_UNUSED(optval); + ARG_UNUSED(optlen); + + return -EOPNOTSUPP; +} + +static inline int tls_setsockopt(int sock, int level, int optname, + const void *optval, socklen_t optlen) +{ + ARG_UNUSED(sock); + ARG_UNUSED(level); + ARG_UNUSED(optname); + ARG_UNUSED(optval); + ARG_UNUSED(optlen); + + return -EOPNOTSUPP; +} + +#endif + +#endif From 95207e76ffcfc74dfff2413e8453b99169ce90c1 Mon Sep 17 00:00:00 2001 From: Patrik Flykt Date: Wed, 18 Apr 2018 11:34:45 +0300 Subject: [PATCH 03/24] tests: socket: Create getsockopt() and setsockopt() tests Create tests for getsockopt() and setsockopt(). Notice that the option value and length may be missing or zero, but that the TLS options need both of them. getsockopt() also needs a length passed in. Signed-off-by: Patrik Flykt --- tests/net/socket/sockopt/CMakeLists.txt | 5 + tests/net/socket/sockopt/prj.conf | 35 +++++ tests/net/socket/sockopt/src/main.c | 185 ++++++++++++++++++++++++ tests/net/socket/sockopt/testcase.yaml | 4 + 4 files changed, 229 insertions(+) create mode 100644 tests/net/socket/sockopt/CMakeLists.txt create mode 100644 tests/net/socket/sockopt/prj.conf create mode 100644 tests/net/socket/sockopt/src/main.c create mode 100644 tests/net/socket/sockopt/testcase.yaml diff --git a/tests/net/socket/sockopt/CMakeLists.txt b/tests/net/socket/sockopt/CMakeLists.txt new file mode 100644 index 0000000000000..92a4288bc1d85 --- /dev/null +++ b/tests/net/socket/sockopt/CMakeLists.txt @@ -0,0 +1,5 @@ +include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE) +project(NONE) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/net/socket/sockopt/prj.conf b/tests/net/socket/sockopt/prj.conf new file mode 100644 index 0000000000000..adc72b0fbcfab --- /dev/null +++ b/tests/net/socket/sockopt/prj.conf @@ -0,0 +1,35 @@ +# Setup for self-contained net testing without requiring a SLIP driver +CONFIG_NET_TEST=y + +# General config +CONFIG_NEWLIB_LIBC=y + +# Networking config +CONFIG_NETWORKING=y +CONFIG_NET_IPV4=y +CONFIG_NET_IPV6=y +CONFIG_NET_TCP=y +CONFIG_NET_SOCKETS=y +CONFIG_NET_SOCKETS_POSIX_NAMES=y +CONFIG_NET_SOCKETS_SOCKOPT_TLS=y + +# Network driver config +CONFIG_NET_LOOPBACK=y +CONFIG_TEST_RANDOM_GENERATOR=y + +# Network address config +CONFIG_NET_APP_SETTINGS=y +CONFIG_NET_APP_NEED_IPV4=y +CONFIG_NET_APP_NEED_IPV6=y +CONFIG_NET_APP_MY_IPV4_ADDR="192.0.2.1" +CONFIG_NET_APP_MY_IPV6_ADDR="2001:db8::1" + +CONFIG_MAIN_STACK_SIZE=2048 + +# Required: +# Net pkt will be reused since src and dst address are the same. +# It takes at least 3 tx pkt to establish TCP connection (syn/syn-ack/ack) +CONFIG_NET_PKT_TX_COUNT=6 + +CONFIG_ZTEST=y +CONFIG_ZTEST_STACKSIZE=2048 diff --git a/tests/net/socket/sockopt/src/main.c b/tests/net/socket/sockopt/src/main.c new file mode 100644 index 0000000000000..200ed809ec378 --- /dev/null +++ b/tests/net/socket/sockopt/src/main.c @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2017 Linaro Limited + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#define TEST_STR_SMALL "test" + +#define ANY_PORT 0 +#define SERVER_PORT 4242 + +#define MAX_CONNS 5 + +#define TCP_TEARDOWN_TIMEOUT K_SECONDS(1) + +static void prepare_tcp_sock_v6(const char *addr, u16_t port, int *sock, + struct sockaddr_in6 *sockaddr) +{ + int rv; + + zassert_not_null(addr, "null addr"); + zassert_not_null(sock, "null sock"); + zassert_not_null(sockaddr, "null sockaddr"); + + *sock = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); + zassert_true(*sock >= 0, "socket open failed"); + + sockaddr->sin6_family = AF_INET6; + sockaddr->sin6_port = htons(port); + rv = inet_pton(AF_INET6, addr, &sockaddr->sin6_addr); + zassert_equal(rv, 1, "inet_pton failed"); +} + +static void prepare_udp_sock_v6(const char *addr, u16_t port, int *sock, + struct sockaddr_in6 *sockaddr) +{ + int rv; + + zassert_not_null(addr, "null addr"); + zassert_not_null(sock, "null sock"); + zassert_not_null(sockaddr, "null sockaddr"); + + *sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); + zassert_true(*sock >= 0, "socket open failed"); + + sockaddr->sin6_family = AF_INET6; + sockaddr->sin6_port = htons(port); + rv = inet_pton(AF_INET6, addr, &sockaddr->sin6_addr); + zassert_equal(rv, 1, "inet_pton failed"); +} + +static void test_getsockopt(void) +{ + int enable; + socklen_t size; + int s6_tcp, s6_udp; + struct sockaddr_in6 addr6; + + prepare_tcp_sock_v6(CONFIG_NET_APP_MY_IPV6_ADDR, ANY_PORT, + &s6_tcp, &addr6); + + errno = 0; + zassert_equal(getsockopt(0, 0, 0, NULL, NULL), -1, "getsockopt"); + zassert_equal(errno, ENOTSOCK, "getsockopt errno"); + + errno = 0; + zassert_equal(getsockopt(s6_tcp, 0, 0, NULL, NULL), -1, "getsockopt"); + zassert_equal(errno, EOPNOTSUPP, "getsockopt errno"); + + errno = 0; + zassert_equal(getsockopt(s6_tcp, SOL_TCP, 0, NULL, NULL), -1, + "getsockopt"); + zassert_equal(errno, EFAULT, "getsockopt errno"); + + prepare_udp_sock_v6(CONFIG_NET_APP_MY_IPV6_ADDR, ANY_PORT, + &s6_udp, &addr6); + + errno = 0; + zassert_equal(getsockopt(s6_udp, SOL_TCP, 0, &enable, &size), -1, + "getsockopt"); + zassert_equal(errno, EBADF, "getsockopt errno"); + + errno = 0; + zassert_equal(getsockopt(s6_tcp, SOL_TCP, 0, &enable, NULL), -1, + "getsockopt"); + zassert_equal(errno, EFAULT, "getsockopt errno"); + + errno = 0; + zassert_equal(getsockopt(s6_tcp, SOL_TCP, 0, NULL, &size), -1, + "getsockopt"); + zassert_equal(errno, EFAULT, "getsockopt errno"); + + errno = 0; + zassert_equal(getsockopt(s6_tcp, SOL_TCP, 0, &enable, NULL), -1, + "getsockopt"); + zassert_equal(errno, EFAULT, "getsockopt errno"); + + errno = 0; + size = 0; + zassert_equal(getsockopt(s6_tcp, SOL_TCP, 0, &enable, &size), -1, + "getsockopt"); + zassert_equal(errno, EFAULT, "getsockopt errno"); + + size = 0; + errno = 0; + zassert_equal(getsockopt(s6_tcp, SOL_TCP, 0, &enable, &size), -1, + "getsockopt"); + zassert_equal(errno, EFAULT, "getsockopt errno"); + + size = sizeof(enable); + errno = 0; + zassert_equal(getsockopt(s6_tcp, SOL_TCP, 0, &enable, &size), + -1, "getsockopt"); + zassert_equal(errno, ENOPROTOOPT, "getsockopt errno"); + zassert_equal(size, sizeof(enable), "getsockopt errno"); + + errno = 0; + zassert_equal(getsockopt(s6_tcp, SOL_TCP, TCP_TLS, &enable, &size), + 0, "getsockopt"); + zassert_equal(errno, 0, "getsockopt errno"); + zassert_equal(size, sizeof(enable), "getsockopt errno"); + + zassert_equal(close(s6_tcp), 0, "close failed"); + zassert_equal(close(s6_udp), 0, "close failed"); +} + +static void test_setsockopt(void) +{ + int enable = 1; + int s6_tcp, s6_udp; + struct sockaddr_in6 addr6; + + prepare_tcp_sock_v6(CONFIG_NET_APP_MY_IPV6_ADDR, ANY_PORT, + &s6_tcp, &addr6); + + zassert_equal(setsockopt(0, 0, 0, NULL, 0), -1, "setsockopt"); + zassert_equal(errno, ENOTSOCK, "setsockopt errno"); + + errno = 0; + zassert_equal(setsockopt(s6_tcp, 0, 0, NULL, 0), -1, "setsockopt"); + zassert_equal(errno, EOPNOTSUPP, "setsockopt errno"); + + errno = 0; + zassert_equal(setsockopt(s6_tcp, SOL_TCP, 0, NULL, 0), -1, + "setsockopt"); + zassert_equal(errno, EFAULT, "setsockopt errno"); + + errno = 0; + zassert_equal(setsockopt(s6_tcp, SOL_TCP, 0, &enable, 0), -1, + "setsockopt"); + zassert_equal(errno, EFAULT, "setsockopt errno"); + + errno = 0; + zassert_equal(setsockopt(s6_tcp, SOL_TCP, 0, &enable, sizeof(enable)), + -1, "setsockopt"); + zassert_equal(errno, ENOPROTOOPT, "setsockopt errno"); + + prepare_udp_sock_v6(CONFIG_NET_APP_MY_IPV6_ADDR, ANY_PORT, + &s6_udp, &addr6); + + errno = 0; + zassert_equal(setsockopt(s6_udp, SOL_TCP, 0, &enable, sizeof(enable)), + -1, "setsockopt"); + zassert_equal(errno, EBADF, "setsockopt errno"); + + errno = 0; + zassert_equal(setsockopt(s6_tcp, SOL_TCP, TCP_TLS, + &enable, sizeof(enable)), 0, "setsockopt"); + zassert_equal(errno, 0, "setsockopt errno"); + + zassert_equal(close(s6_tcp), 0, "close failed"); + zassert_equal(close(s6_udp), 0, "close failed"); +} + +void test_main(void) +{ + ztest_test_suite(socket_sockopt, + ztest_unit_test(test_getsockopt), + ztest_unit_test(test_setsockopt)); + + ztest_run_test_suite(socket_sockopt); +} diff --git a/tests/net/socket/sockopt/testcase.yaml b/tests/net/socket/sockopt/testcase.yaml new file mode 100644 index 0000000000000..ccff53bc72ad7 --- /dev/null +++ b/tests/net/socket/sockopt/testcase.yaml @@ -0,0 +1,4 @@ +tests: + test: + min_ram: 32 + tags: net socket From 9e9f8229cfe484500db662abebf1c2c5208263cb Mon Sep 17 00:00:00 2001 From: Patrik Flykt Date: Fri, 20 Apr 2018 13:55:06 +0300 Subject: [PATCH 04/24] net: tls: Add build files and initial header file for TLS Add build files and initial header file containing the required mbedTLS includes. Signed-off-by: Patrik Flykt --- include/net/net_context.h | 15 +++++++++ subsys/net/ip/CMakeLists.txt | 5 ++- subsys/net/ip/Kconfig | 12 +++++++ subsys/net/ip/net_context.c | 1 + subsys/net/ip/net_tls.c | 7 ++++ subsys/net/ip/net_tls.h | 47 +++++++++++++++++++++++++++ subsys/net/lib/sockets/CMakeLists.txt | 2 ++ tests/net/socket/sockopt/prj.conf | 3 ++ 8 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 subsys/net/ip/net_tls.c create mode 100644 subsys/net/ip/net_tls.h diff --git a/include/net/net_context.h b/include/net/net_context.h index 63a622936fa73..ed76867a7d1de 100644 --- a/include/net/net_context.h +++ b/include/net/net_context.h @@ -27,6 +27,12 @@ #include #include +#if defined(CONFIG_NET_TLS) || defined(CONFIG_NET_DTLS) +#if defined(CONFIG_MBEDTLS) +#include +#endif +#endif + #ifdef __cplusplus extern "C" { #endif @@ -218,6 +224,15 @@ struct net_context { #endif } options; +#if defined(CONFIG_NET_TLS) || defined(CONFIG_NET_DTLS) +#if defined(CONFIG_MBEDTLS) + struct { + mbedtls_ssl_context ssl; + mbedtls_ssl_config config; + } mbedtls; +#endif +#endif + /** Connection handle */ struct net_conn_handle *conn_handler; diff --git a/subsys/net/ip/CMakeLists.txt b/subsys/net/ip/CMakeLists.txt index fc4e571a700d5..90f4974a4f9f6 100644 --- a/subsys/net/ip/CMakeLists.txt +++ b/subsys/net/ip/CMakeLists.txt @@ -27,10 +27,13 @@ zephyr_library_sources_ifdef(CONFIG_NET_STATISTICS net_stats.c) zephyr_library_sources_ifdef(CONFIG_NET_TCP connection.c tcp.c) zephyr_library_sources_ifdef(CONFIG_NET_TRICKLE trickle.c) zephyr_library_sources_ifdef(CONFIG_NET_UDP connection.c udp.c) +if(CONFIG_NET_TLS OR CONFIG_NET_DTLS) +zephyr_library_sources(net_tls.c) +endif() add_subdirectory(l2) -if(CONFIG_NET_SHELL) +if(CONFIG_NET_SHELL OR CONFIG_NET_TLS OR CONFIG_NET_DTLS) zephyr_link_interface_ifdef(CONFIG_MBEDTLS mbedTLS) zephyr_library_link_libraries_ifdef(CONFIG_MBEDTLS mbedTLS) endif() diff --git a/subsys/net/ip/Kconfig b/subsys/net/ip/Kconfig index ac92d8585f358..ef78ec916e08a 100644 --- a/subsys/net/ip/Kconfig +++ b/subsys/net/ip/Kconfig @@ -248,6 +248,18 @@ config NET_DEBUG_UDP help Enables UDP handler output debug messages +config NET_TLS + bool "TCP TLS support" + default n + depends on NET_TCP && MBEDTLS + help + Enable TLS support for TCP connections. TLS is implemented by mbedTLS. + +config NET_DTLS + bool "UDP DTLS placeholder" + default n + depends on NET_UDP && MBEDTLS + config NET_MAX_CONN int "How many network connections are supported" depends on NET_UDP || NET_TCP diff --git a/subsys/net/ip/net_context.c b/subsys/net/ip/net_context.c index 032d0f8673846..fae616c970e79 100644 --- a/subsys/net/ip/net_context.c +++ b/subsys/net/ip/net_context.c @@ -28,6 +28,7 @@ #include "connection.h" #include "net_private.h" +#include "net_tls.h" #include "ipv6.h" #include "ipv4.h" diff --git a/subsys/net/ip/net_tls.c b/subsys/net/ip/net_tls.c new file mode 100644 index 0000000000000..e4f3f9f202c8a --- /dev/null +++ b/subsys/net/ip/net_tls.c @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2018 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "net_tls.h" diff --git a/subsys/net/ip/net_tls.h b/subsys/net/ip/net_tls.h new file mode 100644 index 0000000000000..985526c5aa7d2 --- /dev/null +++ b/subsys/net/ip/net_tls.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2018 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __NET_TLS_H +#define __NET_TLS_H + +#include + +#if defined(CONFIG_NET_TLS) || defined(CONFIG_NET_DTLS) + +#if defined(CONFIG_MBEDTLS) + +#if !defined(CONFIG_MBEDTLS_CFG_FILE) +#include "mbedtls/config.h" +#else +#include CONFIG_MBEDTLS_CFG_FILE +#endif /* CONFIG_MBEDTLS_CFG_FILE */ + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_time_t time_t +#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS +#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE +#endif /* MBEDTLS_PLATFORM_C */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif /* CONFIG_MBEDTLS */ + +#else + +#endif /* CONFIG_NET_TLS || CONFIG_NET_DTLS */ + +#endif diff --git a/subsys/net/lib/sockets/CMakeLists.txt b/subsys/net/lib/sockets/CMakeLists.txt index a2f1b942d9eab..1df7be6ca8017 100644 --- a/subsys/net/lib/sockets/CMakeLists.txt +++ b/subsys/net/lib/sockets/CMakeLists.txt @@ -5,3 +5,5 @@ zephyr_sources( ) zephyr_sources_ifdef(CONFIG_NET_SOCKETS_SOCKOPT_TLS sockets_tls.c) +zephyr_link_interface_ifdef(CONFIG_MBEDTLS mbedTLS) +zephyr_link_libraries_ifdef(CONFIG_MBEDTLS mbedTLS) diff --git a/tests/net/socket/sockopt/prj.conf b/tests/net/socket/sockopt/prj.conf index adc72b0fbcfab..cded33cbd588b 100644 --- a/tests/net/socket/sockopt/prj.conf +++ b/tests/net/socket/sockopt/prj.conf @@ -12,6 +12,9 @@ CONFIG_NET_TCP=y CONFIG_NET_SOCKETS=y CONFIG_NET_SOCKETS_POSIX_NAMES=y CONFIG_NET_SOCKETS_SOCKOPT_TLS=y +CONFIG_MBEDTLS=y +CONFIG_NET_TLS=y +CONFIG_NET_DTLS=y # Network driver config CONFIG_NET_LOOPBACK=y From b7dbf475edd8284f54ba4fbf05f04554e9f976cc Mon Sep 17 00:00:00 2001 From: Patrik Flykt Date: Wed, 18 Apr 2018 11:34:47 +0300 Subject: [PATCH 05/24] net: context: Store TLS enabled/disabled value in context Store information about TLS being enabled or disabled in net_context. Get and set the value via TLS socket options. Signed-off-by: Patrik Flykt --- include/net/net_context.h | 5 +++ subsys/net/ip/net_context.c | 49 ++++++++++++++++++++++++++++ subsys/net/lib/sockets/sockets_tls.c | 18 ++++++++++ 3 files changed, 72 insertions(+) diff --git a/include/net/net_context.h b/include/net/net_context.h index ed76867a7d1de..8a9dace35fbac 100644 --- a/include/net/net_context.h +++ b/include/net/net_context.h @@ -221,6 +221,10 @@ struct net_context { #if defined(CONFIG_NET_CONTEXT_PRIORITY) /** Priority of the network data sent via this net_context */ u8_t priority; +#endif +#if defined(CONFIG_NET_TLS) || defined(CONFIG_NET_DTLS) + /** Enable/disable TLS for the context */ + bool tls; #endif } options; @@ -794,6 +798,7 @@ int net_context_update_recv_wnd(struct net_context *context, enum net_context_option { NET_OPT_PRIORITY = 1, + NET_OPT_TLS = 2, }; /** diff --git a/subsys/net/ip/net_context.c b/subsys/net/ip/net_context.c index fae616c970e79..9931c0b371841 100644 --- a/subsys/net/ip/net_context.c +++ b/subsys/net/ip/net_context.c @@ -1293,6 +1293,38 @@ static int get_context_priority(struct net_context *context, #endif } +static int get_context_tls(struct net_context *context, + void *value, size_t *len) +{ +#if defined(CONFIG_NET_TLS) || defined(CONFIG_NET_DTLS) + if (!len || *len != sizeof(int)) { + return -EINVAL; + } + + *((int *)value) = context->options.tls; + + return 0; +#else + return -ENOTSUP; +#endif +} + +static int set_context_tls(struct net_context *context, + const void *value, size_t len) +{ +#if defined(CONFIG_NET_TLS) || defined(CONFIG_NET_DTLS) + if (len != sizeof(int)) { + return -EINVAL; + } + + context->options.tls = !!*(int *)value; + + return 0; +#else + return -ENOTSUP; +#endif +} + int net_context_set_option(struct net_context *context, enum net_context_option option, const void *value, size_t len) @@ -1305,10 +1337,19 @@ int net_context_set_option(struct net_context *context, return -EINVAL; } + if (!value) { + return -EINVAL; + } + switch (option) { case NET_OPT_PRIORITY: ret = set_context_priority(context, value, len); break; + + case NET_OPT_TLS: + ret = set_context_tls(context, value, len); + break; + } return ret; @@ -1326,10 +1367,18 @@ int net_context_get_option(struct net_context *context, return -EINVAL; } + if (!value) { + return -EINVAL; + } + switch (option) { case NET_OPT_PRIORITY: ret = get_context_priority(context, value, len); break; + + case NET_OPT_TLS: + ret = get_context_tls(context, value, len); + break; } return ret; diff --git a/subsys/net/lib/sockets/sockets_tls.c b/subsys/net/lib/sockets/sockets_tls.c index 27ff0120ec636..a28dbae9629f2 100644 --- a/subsys/net/lib/sockets/sockets_tls.c +++ b/subsys/net/lib/sockets/sockets_tls.c @@ -25,6 +25,15 @@ int tls_getsockopt(int sock, int level, int optname, switch (optname) { case TCP_TLS: + if (*optlen != sizeof(int)) { + return -EINVAL; + } + + if (net_context_get_option(ctx, NET_OPT_TLS, optval, + optlen) < 0) { + ret = -EINVAL; + } + break; default: @@ -50,6 +59,15 @@ int tls_setsockopt(int sock, int level, int optname, switch (optname) { case TCP_TLS: + if (optlen != sizeof(int)) { + return -EINVAL; + } + + if (net_context_set_option(ctx, NET_OPT_TLS, optval, + optlen) < 0) { + ret = -EINVAL; + } + break; default: From f0510d3fff05c02cd4d51e461d5ab14cf5b6341c Mon Sep 17 00:00:00 2001 From: Patrik Flykt Date: Fri, 20 Apr 2018 14:04:46 +0300 Subject: [PATCH 06/24] net: tls: Initialize TLS data structures When enabling network context TLS option, initialize mbedTLS data structures and set up the handler functions for TLS TX and RX. Signed-off-by: Patrik Flykt --- include/net/net_context.h | 2 ++ subsys/net/ip/net_context.c | 12 +++++++-- subsys/net/ip/net_tls.c | 53 +++++++++++++++++++++++++++++++++++++ subsys/net/ip/net_tls.h | 9 +++++++ 4 files changed, 74 insertions(+), 2 deletions(-) diff --git a/include/net/net_context.h b/include/net/net_context.h index 8a9dace35fbac..cf2c62c08700b 100644 --- a/include/net/net_context.h +++ b/include/net/net_context.h @@ -233,6 +233,8 @@ struct net_context { struct { mbedtls_ssl_context ssl; mbedtls_ssl_config config; + /** TLS packet fifo */ + struct k_fifo rx_fifo; } mbedtls; #endif #endif diff --git a/subsys/net/ip/net_context.c b/subsys/net/ip/net_context.c index 9931c0b371841..b71b6fc68e0ab 100644 --- a/subsys/net/ip/net_context.c +++ b/subsys/net/ip/net_context.c @@ -342,6 +342,12 @@ int net_context_put(struct net_context *context) return 0; } +#if defined(CONFIG_NET_TLS) || defined(CONFIG_NET_DTLS) + if (context->options.tls) { + net_tls_enable(context, false); + } +#endif /* defined(CONFIG_NET_TLS) || defined(CONFIG_NET_DTLS) */ + net_context_unref(context); return 0; } @@ -1313,13 +1319,15 @@ static int set_context_tls(struct net_context *context, const void *value, size_t len) { #if defined(CONFIG_NET_TLS) || defined(CONFIG_NET_DTLS) + bool enabled; + if (len != sizeof(int)) { return -EINVAL; } - context->options.tls = !!*(int *)value; + enabled = !!*(int *)value; - return 0; + return net_tls_enable(context, enabled); #else return -ENOTSUP; #endif diff --git a/subsys/net/ip/net_tls.c b/subsys/net/ip/net_tls.c index e4f3f9f202c8a..89cd1bfcf546a 100644 --- a/subsys/net/ip/net_tls.c +++ b/subsys/net/ip/net_tls.c @@ -5,3 +5,56 @@ */ #include "net_tls.h" + +static int tls_tx(void *ctx, const unsigned char *buf, size_t len) +{ + struct net_context *context = ctx; + + ARG_UNUSED(context); + + return -EOPNOTSUPP; +} + +static int tls_rx(void *ctx, unsigned char *buf, size_t len) +{ + struct net_context *context = ctx; + + ARG_UNUSED(context); + + return -EOPNOTSUPP; +} + +int net_tls_enable(struct net_context *context, bool enabled) +{ + int state; + + if (!context) { + return -EINVAL; + } + + if (context->options.tls == enabled) { + return 0; + } + + state = net_context_get_state(context); + if (state != NET_CONTEXT_IDLE && state != NET_CONTEXT_UNCONNECTED) { + return -EBUSY; + } + + if (enabled) { + k_fifo_init(&context->mbedtls.rx_fifo); + mbedtls_ssl_init(&context->mbedtls.ssl); + mbedtls_ssl_config_init(&context->mbedtls.config); + mbedtls_ssl_set_bio(&context->mbedtls.ssl, context, + tls_tx, tls_rx, NULL); + } else { + mbedtls_ssl_set_bio(&context->mbedtls.ssl, + NULL, NULL, NULL, NULL); + mbedtls_ssl_config_free(&context->mbedtls.config); + mbedtls_ssl_free(&context->mbedtls.ssl); + } + + context->options.tls = enabled; + + return 0; +} diff --git a/subsys/net/ip/net_tls.h b/subsys/net/ip/net_tls.h index 985526c5aa7d2..262a69c4e7998 100644 --- a/subsys/net/ip/net_tls.h +++ b/subsys/net/ip/net_tls.h @@ -40,7 +40,16 @@ #endif /* CONFIG_MBEDTLS */ +int net_tls_enable(struct net_context *context, bool enabled); + #else +static inline int net_tls_enable(struct net_context *context, bool enabled) +{ + ARG_UNUSED(context); + ARG_UNUSED(enabled); + + return 0; +} #endif /* CONFIG_NET_TLS || CONFIG_NET_DTLS */ From f38bc880680778f408dbc1eb940cf2ad92697b79 Mon Sep 17 00:00:00 2001 From: Patrik Flykt Date: Mon, 14 May 2018 11:33:08 +0300 Subject: [PATCH 07/24] net: pkt: Add flag to net_pkt_clone() Add a flag that indicates which parts of a net_pkt to clone. Valid flags are NET_PKT_CLONE_META that copies only the pkt metadata but no fragments, NET_PKT_CLONE_HDR that copies only headers and NET_PKT_CLONE_USER_DATA that copies net_pkt and all fragments. This last option retains the same behavior as before. Signed-off-by: Patrik Flykt --- drivers/net/loopback.c | 2 +- include/net/net_pkt.h | 13 ++++++++++++- subsys/net/ip/ipv6.c | 2 +- subsys/net/ip/net_pkt.c | 19 ++++++++++++++----- subsys/net/ip/tcp.c | 3 ++- subsys/net/lib/http/http_server.c | 3 ++- 6 files changed, 32 insertions(+), 10 deletions(-) diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index cf45462b961ad..4b88ab8a83346 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -69,7 +69,7 @@ static int loopback_send(struct net_if *iface, struct net_pkt *pkt) * must be dropped. This is very much needed for TCP packets where * the packet is reference counted in various stages of sending. */ - cloned = net_pkt_clone(pkt, K_MSEC(100)); + cloned = net_pkt_clone(pkt, K_MSEC(100), NET_PKT_CLONE_USER_DATA); if (!cloned) { res = -ENOMEM; goto out; diff --git a/include/net/net_pkt.h b/include/net/net_pkt.h index 993d170e06367..3d6a4bcbeed7c 100644 --- a/include/net/net_pkt.h +++ b/include/net/net_pkt.h @@ -1543,15 +1543,26 @@ struct net_buf *net_frag_get_pos(struct net_pkt *pkt, u16_t offset, u16_t *pos); +/** Flags for pkt clone operation + */ +/** Clone pkt metadata only */ +#define NET_PKT_CLONE_META 0x0 +/** Clone pkt headers */ +#define NET_PKT_CLONE_HDR 0x1 +/** Clone headers and application data */ +#define NET_PKT_CLONE_USER_DATA 0x2 + /** * @brief Clone pkt and its fragment chain. * * @param pkt Original pkt to be cloned * @param timeout Timeout to wait for free net_buf + * @param flags Flags to indicate which parts of the pkt to clone * * @return NULL if error, clone fragment chain otherwise. */ -struct net_pkt *net_pkt_clone(struct net_pkt *pkt, s32_t timeout); +struct net_pkt *net_pkt_clone(struct net_pkt *pkt, s32_t timeout, + int flags); /** * @brief Get information about predefined RX, TX and DATA pools. diff --git a/subsys/net/ip/ipv6.c b/subsys/net/ip/ipv6.c index 0995adaefea18..dc73663dd1f6e 100644 --- a/subsys/net/ip/ipv6.c +++ b/subsys/net/ip/ipv6.c @@ -3787,7 +3787,7 @@ int net_ipv6_send_fragmented_pkt(struct net_if *iface, struct net_pkt *pkt, * some other purposes, like TCP resend etc. So we need to copy * the large pkt here and do the fragmenting with the clone. */ - clone = net_pkt_clone(pkt, BUF_ALLOC_TIMEOUT); + clone = net_pkt_clone(pkt, BUF_ALLOC_TIMEOUT, NET_PKT_CLONE_USER_DATA); if (!clone) { NET_DBG("Cannot clone %p", pkt); return -ENOMEM; diff --git a/subsys/net/ip/net_pkt.c b/subsys/net/ip/net_pkt.c index 6464f082a1655..8ff24fd911bbd 100644 --- a/subsys/net/ip/net_pkt.c +++ b/subsys/net/ip/net_pkt.c @@ -1964,7 +1964,7 @@ struct net_tcp_hdr *net_pkt_tcp_data(struct net_pkt *pkt) return (struct net_tcp_hdr *)(frag->data + offset); } -struct net_pkt *net_pkt_clone(struct net_pkt *pkt, s32_t timeout) +struct net_pkt *net_pkt_clone(struct net_pkt *pkt, s32_t timeout, int flags) { struct net_pkt *clone; struct net_buf *frag; @@ -1981,8 +1981,15 @@ struct net_pkt *net_pkt_clone(struct net_pkt *pkt, s32_t timeout) clone->frags = NULL; - if (pkt->frags) { - clone->frags = net_pkt_copy_all(pkt, 0, timeout); + if (flags && pkt->frags) { + if (flags & NET_PKT_CLONE_USER_DATA) { + clone->frags = net_pkt_copy_all(pkt, 0, timeout); + } else if (flags & NET_PKT_CLONE_HDR) { + clone->frags = net_pkt_copy(pkt, + net_pkt_ip_hdr_len(pkt), + 0, timeout); + } + if (!clone->frags) { net_pkt_unref(clone); return NULL; @@ -1996,8 +2003,10 @@ struct net_pkt *net_pkt_clone(struct net_pkt *pkt, s32_t timeout) if (clone->frags) { frag = net_frag_get_pos(clone, net_pkt_ip_hdr_len(pkt), &pos); - net_pkt_set_appdata(clone, frag->data + pos); - net_pkt_set_appdatalen(clone, net_pkt_appdatalen(pkt)); + if (frag) { + net_pkt_set_appdata(clone, frag->data + pos); + net_pkt_set_appdatalen(clone, net_pkt_appdatalen(pkt)); + } /* The link header pointers are only usable if there is * a fragment that we copied because those pointers point diff --git a/subsys/net/ip/tcp.c b/subsys/net/ip/tcp.c index 560c23bd911bc..7044b0e2e18b8 100644 --- a/subsys/net/ip/tcp.c +++ b/subsys/net/ip/tcp.c @@ -908,7 +908,8 @@ int net_tcp_send_pkt(struct net_pkt *pkt) } if (pkt_in_slist) { - new_pkt = net_pkt_clone(pkt, ALLOC_TIMEOUT); + new_pkt = net_pkt_clone(pkt, ALLOC_TIMEOUT, + NET_PKT_CLONE_USER_DATA); if (!new_pkt) { return -ENOMEM; } diff --git a/subsys/net/lib/http/http_server.c b/subsys/net/lib/http/http_server.c index a175d66491b3c..a971339c32e74 100644 --- a/subsys/net/lib/http/http_server.c +++ b/subsys/net/lib/http/http_server.c @@ -796,7 +796,8 @@ static void http_received(struct net_app_ctx *app_ctx, net_pkt_frag_unref(pkt->frags); pkt->frags = NULL; - cloned = net_pkt_clone(pkt, ctx->timeout); + cloned = net_pkt_clone(pkt, ctx->timeout, + NET_PKT_CLONE_USER_DATA); if (!cloned) { net_pkt_unref(pkt); return; From 2ed252240507b7e5d5d339470af00ed7c734ced6 Mon Sep 17 00:00:00 2001 From: Patrik Flykt Date: Fri, 20 Apr 2018 14:06:55 +0300 Subject: [PATCH 08/24] net: tls: Connect TLS on listen() and connect() When listen() or connect() is called on the socket, start TLS. On connect() do a TLS handshake, on listen set up TLS and wait for incoming connections. Add initial function for randomness. Updated with fixes from Robert Lubos. Signed-off-by: Patrik Flykt --- include/net/net_context.h | 4 + subsys/net/ip/net_context.c | 18 +++-- subsys/net/ip/net_tls.c | 157 ++++++++++++++++++++++++++++++++++++ subsys/net/ip/net_tls.h | 9 +++ 4 files changed, 182 insertions(+), 6 deletions(-) diff --git a/include/net/net_context.h b/include/net/net_context.h index cf2c62c08700b..b01b015bb0441 100644 --- a/include/net/net_context.h +++ b/include/net/net_context.h @@ -233,10 +233,14 @@ struct net_context { struct { mbedtls_ssl_context ssl; mbedtls_ssl_config config; + /** intermediated mbedTLS buffer to store decrypted content */ + char rx_ssl_buf[64]; /** TLS packet fifo */ struct k_fifo rx_fifo; } mbedtls; #endif + /** Receive callback for TLS */ + net_context_recv_cb_t tls_cb; #endif /** Connection handle */ diff --git a/subsys/net/ip/net_context.c b/subsys/net/ip/net_context.c index b71b6fc68e0ab..dd9e1f095d3d3 100644 --- a/subsys/net/ip/net_context.c +++ b/subsys/net/ip/net_context.c @@ -624,7 +624,7 @@ int net_context_listen(struct net_context *context, int backlog) #endif /* CONFIG_NET_OFFLOAD */ if (net_tcp_listen(context) >= 0) { - return 0; + return net_tls_connect(context, true); } return -EOPNOTSUPP; @@ -774,19 +774,25 @@ int net_context_connect(struct net_context *context, cb(context, 0, user_data); } - return 0; + ret = 0; + break; #endif /* CONFIG_NET_UDP */ case SOCK_STREAM: - return net_tcp_connect(context, addr, laddr, rport, lport, - timeout, cb, user_data); + ret = net_tcp_connect(context, addr, laddr, rport, lport, + timeout, cb, user_data); + break; default: - return -ENOTSUP; + ret = -ENOTSUP; } - return 0; + if (ret < 0) { + return ret; + } + + return net_tls_connect(context, false); } int net_context_accept(struct net_context *context, diff --git a/subsys/net/ip/net_tls.c b/subsys/net/ip/net_tls.c index 89cd1bfcf546a..52eae8658efc9 100644 --- a/subsys/net/ip/net_tls.c +++ b/subsys/net/ip/net_tls.c @@ -5,6 +5,11 @@ */ #include "net_tls.h" +#include "net_private.h" + +#define TIMEOUT_TLS_RX_MS 100 + +static mbedtls_ctr_drbg_context tls_ctr_drbg; static int tls_tx(void *ctx, const unsigned char *buf, size_t len) { @@ -24,6 +29,95 @@ static int tls_rx(void *ctx, unsigned char *buf, size_t len) return -EOPNOTSUPP; } +static int tls_mbedtls_ctr_drbg_random(void *p_rng, unsigned char *output, + size_t output_len) +{ + static K_MUTEX_DEFINE(mutex); + + ARG_UNUSED(mutex); + + return 0; +} + +static void tls_recv_cb(struct net_context *context, struct net_pkt *pkt, + int status, void *user_data) +{ + struct net_pkt *decrypted_pkt; + int len, ret = 0; + + if (!pkt) { + /* Forward EOF */ + if (context->tls_cb) { + context->tls_cb(context, pkt, status, user_data); + } + return; + } + + k_fifo_put(&context->mbedtls.rx_fifo, pkt); + + /* Process it as application data only after handshake is over, + * otherwise packet will be consumed by handshake. + */ + if (context->mbedtls.ssl.state == MBEDTLS_SSL_HANDSHAKE_OVER) { + len = net_pkt_appdatalen(pkt); + + decrypted_pkt = net_pkt_clone(pkt, 0, NET_PKT_CLONE_HDR); + if (!decrypted_pkt) { + return; + } + + /* Copy IP and transport header */ + u16_t header_len = net_pkt_appdata(pkt) - pkt->frags->data; + + ret = net_frag_linear_copy(decrypted_pkt->frags, pkt->frags, + 0, header_len); + if (ret < 0) { + goto err; + } + + /* Set appdata and appdatalen */ + net_pkt_set_appdata(decrypted_pkt, + decrypted_pkt->frags->data + header_len); + net_pkt_set_appdatalen(decrypted_pkt, 0); + + while (1) { + ret = mbedtls_ssl_read(&context->mbedtls.ssl, + context->mbedtls.rx_ssl_buf, + sizeof(context->mbedtls.rx_ssl_buf)); + if (ret == 0 || ret == MBEDTLS_ERR_SSL_WANT_READ || + ret == MBEDTLS_ERR_SSL_WANT_WRITE) { + ret = 0; + + break; + } + + if (ret > 0) { + ret = net_pkt_append(decrypted_pkt, ret, + context->mbedtls.rx_ssl_buf, + TIMEOUT_TLS_RX_MS); + /* Update appdatalen */ + net_pkt_set_appdatalen(decrypted_pkt, + net_pkt_appdatalen(decrypted_pkt) + ret); + continue; + } + + ret = -EBADF; + break; + } + + if (ret >= 0 && context->tls_cb) { + context->tls_cb(context, decrypted_pkt, status, user_data); + } else { + goto err; + } + } + + return; + +err: + net_pkt_unref(decrypted_pkt); +} + int net_tls_enable(struct net_context *context, bool enabled) { int state; @@ -58,3 +152,66 @@ int net_tls_enable(struct net_context *context, bool enabled) return 0; } + +int net_tls_connect(struct net_context *context, bool listening) +{ + enum net_context_state state; + int err, role, type; + + if (!context) { + return -EINVAL; + } + + if (!context->options.tls) { + return 0; + } + + state = net_context_get_state(context); + if (state != NET_CONTEXT_READY) { + return -EBUSY; + } + + context->recv_cb = tls_recv_cb; + + role = listening ? MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT; + + type = (net_context_get_type(context) == SOCK_STREAM) ? + MBEDTLS_SSL_TRANSPORT_STREAM : + MBEDTLS_SSL_TRANSPORT_DATAGRAM; + + err = mbedtls_ssl_config_defaults(&context->mbedtls.config, role, type, + MBEDTLS_SSL_PRESET_DEFAULT); + if (err) { + err = -ENOMEM; + goto mbed_err_conf; + } + + mbedtls_ctr_drbg_init(&tls_ctr_drbg); + + mbedtls_ssl_conf_rng(&context->mbedtls.config, + tls_mbedtls_ctr_drbg_random, &tls_ctr_drbg); + + err = mbedtls_ssl_setup(&context->mbedtls.ssl, + &context->mbedtls.config); + if (err) { + err = -EINVAL; + goto mbed_err_conf; + } + + while ((err = mbedtls_ssl_handshake(&context->mbedtls.ssl)) != 0) { + if (err != MBEDTLS_ERR_SSL_WANT_READ && + err != MBEDTLS_ERR_SSL_WANT_WRITE) { + err = -ENOPROTOOPT; + goto mbed_err_handshake; + } + } + + return 0; + +mbed_err_handshake: +mbed_err_conf: + mbedtls_ssl_session_reset(&context->mbedtls.ssl); + mbedtls_ssl_config_free(&context->mbedtls.config); + + return err; +} diff --git a/subsys/net/ip/net_tls.h b/subsys/net/ip/net_tls.h index 262a69c4e7998..78d563b7a846f 100644 --- a/subsys/net/ip/net_tls.h +++ b/subsys/net/ip/net_tls.h @@ -41,6 +41,7 @@ #endif /* CONFIG_MBEDTLS */ int net_tls_enable(struct net_context *context, bool enabled); +int net_tls_connect(struct net_context *context, bool listening); #else static inline int net_tls_enable(struct net_context *context, bool enabled) @@ -51,6 +52,14 @@ static inline int net_tls_enable(struct net_context *context, bool enabled) return 0; } +static inline int net_tls_connect(struct net_context *context, bool listening) +{ + ARG_UNUSED(context); + ARG_UNUSED(listening); + + return 0; +} + #endif /* CONFIG_NET_TLS || CONFIG_NET_DTLS */ #endif From 9ea819392c859aa49bfed58e1755769ddf24baa8 Mon Sep 17 00:00:00 2001 From: Patrik Flykt Date: Wed, 25 Apr 2018 14:10:32 +0300 Subject: [PATCH 09/24] net: context: Split packet sending into two functions Split packet sending into two functions with the existing sendto() taking care of user data, callbacks and destination address verification up until offloading and TLS support. The second part, net_context_output(), re-uses send_data() and augments it with the later parts of sendto(). This split is visible only internally to the net stack, as the function definition is made private. Signed-off-by: Patrik Flykt --- subsys/net/ip/net_context.c | 103 +++++++++++++++++++++--------------- subsys/net/ip/net_private.h | 2 + 2 files changed, 61 insertions(+), 44 deletions(-) diff --git a/subsys/net/ip/net_context.c b/subsys/net/ip/net_context.c index dd9e1f095d3d3..2f6ee4a777ea1 100644 --- a/subsys/net/ip/net_context.c +++ b/subsys/net/ip/net_context.c @@ -886,6 +886,64 @@ static int create_udp_packet(struct net_context *context, } #endif /* CONFIG_NET_UDP */ +int net_context_output(struct net_context *context, struct net_pkt *pkt, + const struct sockaddr *dst_addr) +{ + int ret; + + switch (net_context_get_ip_proto(context)) { +#if defined(CONFIG_NET_UDP) + case IPPROTO_UDP: + /* Bind default address and port only if UDP */ + ret = bind_default(context); + if (ret) { + return ret; + } + + ret = create_udp_packet(context, pkt, dst_addr, &pkt); + if (ret < 0) { + goto err; + } + + ret = net_send_data(pkt); + if (ret < 0) { + goto err; + } + break; +#endif /* CONFIG_NET_UDP */ + + case IPPROTO_TCP: + ret = net_tcp_queue_data(context, pkt); + if (ret < 0) { + goto err; + } + + ret = net_tcp_send_data(context, context->send_cb, + net_pkt_token(pkt), context->user_data); + if (ret < 0) { + goto err; + } + + break; + + default: + ret = -EPROTONOSUPPORT; + } + +err: + if (ret < 0) { + if (ret == -EPROTONOSUPPORT) { + NET_DBG("Unknown protocol while sending packet: %d", + net_context_get_ip_proto(context)); + } else { + NET_DBG("Could not create network packet to send (%d)", + ret); + } + } + + return ret; +} + static int sendto(struct net_pkt *pkt, const struct sockaddr *dst_addr, socklen_t addrlen, @@ -895,7 +953,6 @@ static int sendto(struct net_pkt *pkt, void *user_data) { struct net_context *context = net_pkt_context(pkt); - int ret = 0; if (!net_context_is_used(context)) { return -EBADF; @@ -946,53 +1003,11 @@ static int sendto(struct net_pkt *pkt, } #endif /* CONFIG_NET_OFFLOAD */ - switch (net_context_get_ip_proto(context)) { - case IPPROTO_UDP: -#if defined(CONFIG_NET_UDP) - /* Bind default address and port only if UDP */ - ret = bind_default(context); - if (ret) { - return ret; - } - - ret = create_udp_packet(context, pkt, dst_addr, &pkt); -#endif /* CONFIG_NET_UDP */ - break; - - case IPPROTO_TCP: - ret = net_tcp_queue_data(context, pkt); - break; - - default: - ret = -EPROTONOSUPPORT; - } - - if (ret < 0) { - if (ret == -EPROTONOSUPPORT) { - NET_DBG("Unknown protocol while sending packet: %d", - net_context_get_ip_proto(context)); - } else { - NET_DBG("Could not create network packet to send (%d)", - ret); - } - - return ret; - } - context->send_cb = cb; context->user_data = user_data; net_pkt_set_token(pkt, token); - switch (net_context_get_ip_proto(context)) { - case IPPROTO_UDP: - return net_send_data(pkt); - - case IPPROTO_TCP: - return net_tcp_send_data(context, cb, token, user_data); - - default: - return -EPROTONOSUPPORT; - } + return net_context_output(context, pkt, dst_addr); } int net_context_send(struct net_pkt *pkt, diff --git a/subsys/net/ip/net_private.h b/subsys/net/ip/net_private.h index d6d5483dc1740..6c2bac1f9caa7 100644 --- a/subsys/net/ip/net_private.h +++ b/subsys/net/ip/net_private.h @@ -42,6 +42,8 @@ extern void net_pkt_init(void); extern void net_if_init(void); extern void net_if_post_init(void); extern void net_if_carrier_down(struct net_if *iface); +extern int net_context_output(struct net_context *context, struct net_pkt *pkt, + const struct sockaddr *dst_addr); extern void net_context_init(void); enum net_verdict net_ipv4_process_pkt(struct net_pkt *pkt); enum net_verdict net_ipv6_process_pkt(struct net_pkt *pkt); From ef6c11c7dc767004229551305e7b94c2ed979c11 Mon Sep 17 00:00:00 2001 From: Patrik Flykt Date: Wed, 25 Apr 2018 14:17:36 +0300 Subject: [PATCH 10/24] net: tls: Add mbedTLS packet sending On packet send apply TLS using mbedTLS. Go through each fragment and send their data to mbedTLS for encryption. Create a new packet from the output of mbedTLS and send it in the existing network context for UDP or TCP header processing. Signed-off-by: Patrik Flykt --- subsys/net/ip/net_context.c | 10 +++++++ subsys/net/ip/net_tls.c | 54 +++++++++++++++++++++++++++++++++++-- subsys/net/ip/net_tls.h | 7 +++++ 3 files changed, 69 insertions(+), 2 deletions(-) diff --git a/subsys/net/ip/net_context.c b/subsys/net/ip/net_context.c index 2f6ee4a777ea1..c8d1443864814 100644 --- a/subsys/net/ip/net_context.c +++ b/subsys/net/ip/net_context.c @@ -994,6 +994,10 @@ static int sendto(struct net_pkt *pkt, return -EINVAL; } + context->send_cb = cb; + context->user_data = user_data; + net_pkt_set_token(pkt, token); + #if defined(CONFIG_NET_OFFLOAD) if (net_if_is_ip_offloaded(net_pkt_iface(pkt))) { return net_offload_sendto( @@ -1007,6 +1011,12 @@ static int sendto(struct net_pkt *pkt, context->user_data = user_data; net_pkt_set_token(pkt, token); +#if defined(CONFIG_NET_TLS) || defined(CONFIG_NET_DTLS) + if (context->options.tls) { + return net_tls_send(pkt); + } +#endif + return net_context_output(context, pkt, dst_addr); } diff --git a/subsys/net/ip/net_tls.c b/subsys/net/ip/net_tls.c index 52eae8658efc9..cc2d3d658359f 100644 --- a/subsys/net/ip/net_tls.c +++ b/subsys/net/ip/net_tls.c @@ -8,16 +8,31 @@ #include "net_private.h" #define TIMEOUT_TLS_RX_MS 100 +#define TIMEOUT_TLS_TX_MS 100 static mbedtls_ctr_drbg_context tls_ctr_drbg; static int tls_tx(void *ctx, const unsigned char *buf, size_t len) { struct net_context *context = ctx; + struct net_pkt *pkt; + int bytes, ret; - ARG_UNUSED(context); + pkt = net_pkt_get_tx(context, TIMEOUT_TLS_TX_MS); - return -EOPNOTSUPP; + if (!pkt) { + return -EIO; + } + + bytes = net_pkt_append(pkt, len, (u8_t *)buf, TIMEOUT_TLS_TX_MS); + + ret = net_context_output(context, pkt, &context->remote); + if (ret < 0) { + net_pkt_unref(pkt); + return ret; + } + + return bytes; } static int tls_rx(void *ctx, unsigned char *buf, size_t len) @@ -215,3 +230,38 @@ int net_tls_connect(struct net_context *context, bool listening) return err; } + +int net_tls_send(struct net_pkt *pkt) +{ + struct net_context *context = net_pkt_context(pkt); + struct net_buf *frag = pkt->frags; + + while (frag) { + int ret = 0; + u8_t *data = frag->data; + u16_t len = frag->len; + + while (ret < len) { + ret = mbedtls_ssl_write(&context->mbedtls.ssl, + data, len); + if (ret == len) { + break; + } + + if (ret > 0 && ret < len) { + data += ret; + len -= ret; + continue; + } + + if (ret != MBEDTLS_ERR_SSL_WANT_WRITE && + ret != MBEDTLS_ERR_SSL_WANT_READ) { + return -EBADF; + } + } + + frag = frag->frags; + } + + return 0; +} diff --git a/subsys/net/ip/net_tls.h b/subsys/net/ip/net_tls.h index 78d563b7a846f..8494a142eec10 100644 --- a/subsys/net/ip/net_tls.h +++ b/subsys/net/ip/net_tls.h @@ -42,6 +42,7 @@ int net_tls_enable(struct net_context *context, bool enabled); int net_tls_connect(struct net_context *context, bool listening); +int net_tls_send(struct net_pkt *pkt); #else static inline int net_tls_enable(struct net_context *context, bool enabled) @@ -60,6 +61,12 @@ static inline int net_tls_connect(struct net_context *context, bool listening) return 0; } +static inline int net_tls_send(struct net_pkt *pkt) +{ + ARG_UNUSED(pkt); + + return 0; +} #endif /* CONFIG_NET_TLS || CONFIG_NET_DTLS */ #endif From 8a3131add0099052ed7986c7227fdbfe289a4317 Mon Sep 17 00:00:00 2001 From: Patrik Flykt Date: Wed, 16 May 2018 11:18:44 +0300 Subject: [PATCH 11/24] net: context: Add TLS receive functionality Add functionality to receive and decrypt TLS packets. Add TLS bookkeeping information so that the call through mbedTLS remembers the packet and serves an interim buffer to store mbedTLS output. Signed-off-by: Patrik Flykt --- include/net/net_context.h | 4 +++ subsys/net/ip/net_context.c | 6 +++++ subsys/net/ip/net_tls.c | 49 +++++++++++++++++++++++++++++++++++-- subsys/net/ip/net_tls.h | 12 +++++++++ 4 files changed, 69 insertions(+), 2 deletions(-) diff --git a/include/net/net_context.h b/include/net/net_context.h index b01b015bb0441..050d07631296d 100644 --- a/include/net/net_context.h +++ b/include/net/net_context.h @@ -237,6 +237,10 @@ struct net_context { char rx_ssl_buf[64]; /** TLS packet fifo */ struct k_fifo rx_fifo; + /** last data that came in via TLS */ + struct net_pkt *rx_pkt; + /** offset in the last data */ + int rx_offset; } mbedtls; #endif /** Receive callback for TLS */ diff --git a/subsys/net/ip/net_context.c b/subsys/net/ip/net_context.c index c8d1443864814..e7c45b320ad94 100644 --- a/subsys/net/ip/net_context.c +++ b/subsys/net/ip/net_context.c @@ -1261,6 +1261,12 @@ int net_context_recv(struct net_context *context, #endif /* CONFIG_NET_UDP */ case IPPROTO_TCP: +#if defined(CONFIG_NET_TLS) || defined(CONFIG_NET_DTLS) + if (context->options.tls) { + ret = net_tls_recv(context, cb, user_data); + break; + } +#endif ret = net_tcp_recv(context, cb, user_data); break; diff --git a/subsys/net/ip/net_tls.c b/subsys/net/ip/net_tls.c index cc2d3d658359f..ee6ee09b08b07 100644 --- a/subsys/net/ip/net_tls.c +++ b/subsys/net/ip/net_tls.c @@ -4,8 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include + #include "net_tls.h" #include "net_private.h" +#include "tcp_internal.h" #define TIMEOUT_TLS_RX_MS 100 #define TIMEOUT_TLS_TX_MS 100 @@ -38,10 +41,38 @@ static int tls_tx(void *ctx, const unsigned char *buf, size_t len) static int tls_rx(void *ctx, unsigned char *buf, size_t len) { struct net_context *context = ctx; + int ret; + u16_t len_left; + + if (!context->mbedtls.rx_pkt) { + context->mbedtls.rx_pkt = + k_fifo_get(&context->mbedtls.rx_fifo, K_NO_WAIT); + if (context->mbedtls.rx_pkt) { + context->mbedtls.rx_offset = + net_pkt_appdata(context->mbedtls.rx_pkt) - + context->mbedtls.rx_pkt->frags->data; + } else { + return MBEDTLS_ERR_SSL_WANT_READ; + } + } - ARG_UNUSED(context); + len_left = net_pkt_get_len(context->mbedtls.rx_pkt) - + context->mbedtls.rx_offset; + ret = net_frag_linearize(buf, len, context->mbedtls.rx_pkt, + context->mbedtls.rx_offset, + MIN(len, len_left)); + if (ret > 0) { + context->mbedtls.rx_offset += ret; + } + + if (context->mbedtls.rx_offset >= + net_pkt_get_len(context->mbedtls.rx_pkt)) { + net_pkt_unref(context->mbedtls.rx_pkt); + context->mbedtls.rx_pkt = NULL; + context->mbedtls.rx_offset = 0; + } - return -EOPNOTSUPP; + return ret; } static int tls_mbedtls_ctr_drbg_random(void *p_rng, unsigned char *output, @@ -263,5 +294,19 @@ int net_tls_send(struct net_pkt *pkt) frag = frag->frags; } + net_pkt_unref(pkt); + + return 0; +} + +int net_tls_recv(struct net_context *context, net_context_recv_cb_t cb, + void *user_data) +{ + context->tls_cb = cb; + +#if defined(CONFIG_NET_TCP) + context->tcp->recv_user_data = user_data; +#endif + return 0; } diff --git a/subsys/net/ip/net_tls.h b/subsys/net/ip/net_tls.h index 8494a142eec10..ea3103bbc0035 100644 --- a/subsys/net/ip/net_tls.h +++ b/subsys/net/ip/net_tls.h @@ -43,6 +43,8 @@ int net_tls_enable(struct net_context *context, bool enabled); int net_tls_connect(struct net_context *context, bool listening); int net_tls_send(struct net_pkt *pkt); +int net_tls_recv(struct net_context *context, net_context_recv_cb_t cb, + void *user_data); #else static inline int net_tls_enable(struct net_context *context, bool enabled) @@ -67,6 +69,16 @@ static inline int net_tls_send(struct net_pkt *pkt) return 0; } + +static inline int net_tls_recv(struct net_context *context, + net_context_recv_cb_t cb, void *user_data) +{ + ARG_UNUSED(context); + ARG_UNUSED(cb); + ARG_UNUSED(user_data); + + return 0; +} #endif /* CONFIG_NET_TLS || CONFIG_NET_DTLS */ #endif From 029eee18acb459f58d381f7f565e7e2cca7ff7eb Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Thu, 10 May 2018 11:43:09 +0200 Subject: [PATCH 12/24] net: tls: Add Kconfig options for default configuration This commit introduces Kconfig options that enable to set default certificates to use in TLS/DTLS session. Default certificate selection is done by specifying header file that certificates are present in. The certificates are then preloaded in the net_tls module. To achieve that, simple API for certificate management was added into the net_tls. The idea is, that it could be reused in the future for runtime certificate configuration. Signed-off-by: Robert Lubos --- include/net/net_tls.h | 104 ++++++++++++ subsys/net/ip/Kconfig | 12 +- subsys/net/ip/Kconfig.tls | 45 +++++ subsys/net/ip/net_context.c | 2 +- subsys/net/ip/net_core.c | 3 + subsys/net/ip/net_tls.c | 142 +++++++++++++++- subsys/net/ip/net_tls_default_credentials.h | 154 ++++++++++++++++++ .../net/ip/{net_tls.h => net_tls_internal.h} | 16 +- 8 files changed, 462 insertions(+), 16 deletions(-) create mode 100644 include/net/net_tls.h create mode 100644 subsys/net/ip/Kconfig.tls create mode 100644 subsys/net/ip/net_tls_default_credentials.h rename subsys/net/ip/{net_tls.h => net_tls_internal.h} (88%) diff --git a/include/net/net_tls.h b/include/net/net_tls.h new file mode 100644 index 0000000000000..8a2724ad53cb5 --- /dev/null +++ b/include/net/net_tls.h @@ -0,0 +1,104 @@ +/** @file + * @brief Network TLS definitions + * + * An API for applications to configure TLS credentials. + */ + +/* + * Copyright (c) 2018 Intel Corporation + * Copyright (c) 2018 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __NET_TLS_H +#define __NET_TLS_H + +/** + * @brief Network TLS management + * @defgroup net_tls Network TLS management + * @ingroup networking + * @{ + */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** TLS credential type */ +enum net_tls_credential_type { + NET_TLS_CREDENTIAL_UNUSED, + NET_TLS_CREDENTIAL_CA_CERTIFICATE, + NET_TLS_CREDENTIAL_PSK, + NET_TLS_CREDENTIAL_PSK_ID +}; + +/** Secure tag, a reference for TLS credential */ +typedef int sec_tag_t; + +#if defined(CONFIG_NET_TLS) || defined(CONFIG_NET_DTLS) + +/** + * @brief Add a TLS credential. + * + * @details This function adds a TLS credential, that can be used + * by TLS/DTLS for authentication. + * + * @param tag A security tag that credential will be referenced with. + * @param type A TLS/DTLS credential type. + * @param cred A TLS/DTLS credential. + * @param credlen A TLS/DTLS credential length. + * + * @return 0 if ok, < 0 if error. + */ +int net_tls_credential_add(int tag, enum net_tls_credential_type type, + const void *cred, size_t credlen); + +/** + * @brief Get a TLS credential. + * + * @details This function gets an already registered TLS credential, + * referenced by @p tag secure tag of @p type. + * + * @param tag A security tag of requested credential. + * @param type A TLS/DTLS credential type of requested credential. + * @param cred A TLS/DTLS credential. + * @param credlen A TLS/DTLS credential length. + * + * @return 0 if ok, < 0 if error. + */ +int net_tls_credential_get(int tag, enum net_tls_credential_type type, + void *cred, size_t *credlen); + +/** + * @brief Delete a TLS credential. + * + * @details This function removes a TLS credential, referenced by @p tag + * secure tag of @p type. + * + * @param tag A security tag corresponding to removed credential. + * @param type A TLS/DTLS credential type of removed credential. + * + * @return 0 if ok, < 0 if error. + */ +int net_tls_credential_delete(int tag, enum net_tls_credential_type type); + +#else + +#define net_tls_credential_add(...) +#define net_tls_credential_get(...) +#define net_tls_credential_delete(...) + +#endif /* defined(CONFIG_NET_TLS) || defined(CONFIG_NET_DTLS) */ + +#ifdef __cplusplus +} +#endif + +/** + * @} + */ + +#endif /* __NET_TLS_H */ diff --git a/subsys/net/ip/Kconfig b/subsys/net/ip/Kconfig index ef78ec916e08a..f96672db4decc 100644 --- a/subsys/net/ip/Kconfig +++ b/subsys/net/ip/Kconfig @@ -248,17 +248,7 @@ config NET_DEBUG_UDP help Enables UDP handler output debug messages -config NET_TLS - bool "TCP TLS support" - default n - depends on NET_TCP && MBEDTLS - help - Enable TLS support for TCP connections. TLS is implemented by mbedTLS. - -config NET_DTLS - bool "UDP DTLS placeholder" - default n - depends on NET_UDP && MBEDTLS +source "subsys/net/ip/Kconfig.tls" config NET_MAX_CONN int "How many network connections are supported" diff --git a/subsys/net/ip/Kconfig.tls b/subsys/net/ip/Kconfig.tls new file mode 100644 index 0000000000000..f8f5735dded13 --- /dev/null +++ b/subsys/net/ip/Kconfig.tls @@ -0,0 +1,45 @@ +# Kconfig.stack - TLS/DTLS related options + +# +# Copyright (c) 2018 Intel Corporation +# Copyright (c) 2018 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +menu "TLS options" + +config NET_TLS + bool "TCP TLS support" + default n + depends on NET_TCP && MBEDTLS + help + Enable TLS support for TCP connections. TLS is implemented by mbedTLS. + +config NET_DTLS + bool "UDP DTLS placeholder" + default n + depends on NET_UDP && MBEDTLS + +config NET_MAX_CREDENTIALS_NUMBER + int "Maximum number of TLS/DTLS credentials" + default 4 + depends on NET_TLS || NET_DTLS + help + "Maximum number of TLS/DTLS credentials that can be used simultaneously" + +config NET_PRECONFIGURE_TLS_CREDENTIALS + bool "Use preconfigured credentials for TLS/DTLS" + default n + depends on NET_TLS || NET_DTLS + help + Use preconfigured credentials (CA Certificate, PSK) for TLS/DTLS sessions. + +config NET_TLS_CREDENTIALS_FILE + string "TLS/DTLS credentials to preconfigure" + default "net_tls_default_credentials.h" + depends on NET_PRECONFIGURE_TLS_CREDENTIALS + help + File containing default TLS/DTLS credentials to preconfigure. TODO Extend description. + +endmenu diff --git a/subsys/net/ip/net_context.c b/subsys/net/ip/net_context.c index e7c45b320ad94..dad4e038f2911 100644 --- a/subsys/net/ip/net_context.c +++ b/subsys/net/ip/net_context.c @@ -28,7 +28,7 @@ #include "connection.h" #include "net_private.h" -#include "net_tls.h" +#include "net_tls_internal.h" #include "ipv6.h" #include "ipv4.h" diff --git a/subsys/net/ip/net_core.c b/subsys/net/ip/net_core.c index c850b53b422e1..7b45d49ae6529 100644 --- a/subsys/net/ip/net_core.c +++ b/subsys/net/ip/net_core.c @@ -50,6 +50,8 @@ #include "udp_internal.h" #include "tcp_internal.h" +#include "net_tls_internal.h" + #include "net_stats.h" static inline enum net_verdict process_data(struct net_pkt *pkt, @@ -375,6 +377,7 @@ static inline void l3_init(void) #endif net_udp_init(); net_tcp_init(); + net_tls_init(); net_route_init(); diff --git a/subsys/net/ip/net_tls.c b/subsys/net/ip/net_tls.c index ee6ee09b08b07..c4658f60e5dc8 100644 --- a/subsys/net/ip/net_tls.c +++ b/subsys/net/ip/net_tls.c @@ -6,15 +6,77 @@ #include -#include "net_tls.h" #include "net_private.h" +#include "net_tls_internal.h" #include "tcp_internal.h" #define TIMEOUT_TLS_RX_MS 100 #define TIMEOUT_TLS_TX_MS 100 +#if defined(CONFIG_NET_PRECONFIGURE_TLS_CREDENTIALS) +#include CONFIG_NET_TLS_CREDENTIALS_FILE +#endif + static mbedtls_ctr_drbg_context tls_ctr_drbg; +struct net_tls_credential { + enum net_tls_credential_type type; + int tag; + const void *buf; + size_t len; +}; + +/* Global poll of credentials shared among TLS contexts. */ +static struct net_tls_credential credentials[CONFIG_NET_MAX_CREDENTIALS_NUMBER]; + +static struct net_tls_credential *unused_credential_get(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(credentials); i++) { + if (credentials[i].type == NET_TLS_CREDENTIAL_UNUSED) { + return &credentials[i]; + } + } + + return NULL; +} + +static struct net_tls_credential *credential_get( + sec_tag_t tag, enum net_tls_credential_type type) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(credentials); i++) { + if (credentials[i].type == type && credentials[i].tag == tag) { + return &credentials[i]; + } + } + + return NULL; +} + +static struct net_tls_credential *credential_next_get( + sec_tag_t tag, struct net_tls_credential *iter) +{ + int i; + + if (!iter) { + iter = credentials; + } else { + iter++; + } + + for (i = iter - credentials; i < ARRAY_SIZE(credentials); i++) { + if (credentials[i].type != NET_TLS_CREDENTIAL_UNUSED && + credentials[i].tag == tag) { + return &credentials[i]; + } + } + + return NULL; +} + static int tls_tx(void *ctx, const unsigned char *buf, size_t len) { struct net_context *context = ctx; @@ -164,6 +226,31 @@ static void tls_recv_cb(struct net_context *context, struct net_pkt *pkt, net_pkt_unref(decrypted_pkt); } +void net_tls_init(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(credentials); i++) { + credentials[i].type = NET_TLS_CREDENTIAL_UNUSED; + } + +#if defined(CONFIG_NET_PRECONFIGURE_TLS_CREDENTIALS) +#if defined(MBEDTLS_X509_CRT_PARSE_C) + net_tls_credential_add(NET_TLS_DEFAULT_CA_CERTIFICATE_TAG, + NET_TLS_CREDENTIAL_CA_CERTIFICATE, + ca_certificate, sizeof(ca_certificate)); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + net_tls_credential_add(NET_TLS_DEFAULT_PSK_TAG, + NET_TLS_CREDENTIAL_PSK, + client_psk, sizeof(client_psk)); + net_tls_credential_add(NET_TLS_DEFAULT_PSK_TAG, + NET_TLS_CREDENTIAL_PSK_ID, + client_psk_id, sizeof(client_psk_id)); +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ +#endif /* CONFIG_NET_PRECONFIGURE_TLS_CREDENTIALS */ +} + int net_tls_enable(struct net_context *context, bool enabled) { int state; @@ -310,3 +397,56 @@ int net_tls_recv(struct net_context *context, net_context_recv_cb_t cb, return 0; } + +int net_tls_credential_add(int tag, enum net_tls_credential_type type, + const void *cred, size_t credlen) +{ + struct net_tls_credential *credential = credential_get(tag, type); + + if (credential != NULL) { + return -EEXIST; + } + + credential = unused_credential_get(); + if (credential == NULL) { + return -ENOMEM; + } + + credential->tag = tag; + credential->type = type; + credential->buf = cred; + credential->len = credlen; + + return 0; +} + +int net_tls_credential_get(sec_tag_t tag, enum net_tls_credential_type type, + void *cred, size_t *credlen) +{ + struct net_tls_credential *credential = credential_get(tag, type); + + if (credential == NULL) { + return -ENOENT; + } + + *credlen = credential->len; + memcpy(cred, credential->buf, credential->len); + + return 0; +} + +int net_tls_credential_delete(int tag, enum net_tls_credential_type type) +{ + struct net_tls_credential *credential = NULL; + + credential = credential_get(tag, type); + + if (!credential) { + return -ENOENT; + } + + memset(credential, 0, sizeof(struct net_tls_credential)); + credential->type = NET_TLS_CREDENTIAL_UNUSED; + + return 0; +} diff --git a/subsys/net/ip/net_tls_default_credentials.h b/subsys/net/ip/net_tls_default_credentials.h new file mode 100644 index 0000000000000..9ebd7681d054c --- /dev/null +++ b/subsys/net/ip/net_tls_default_credentials.h @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2018 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __NET_TLS_DEFAULT_CREDENTIALS_H__ +#define __NET_TLS_DEFAULT_CREDENTIALS_H__ + +#define NET_TLS_DEFAULT_CA_CERTIFICATE_TAG 0 +#define NET_TLS_DEFAULT_PSK_TAG 1 + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + +/* By default only certificates in DER format are supported. If you want to use + * certificate in PEM format, you can enable support for it in Kconfig. + */ + +/* GlobalSign Root CA - R2 */ +static const unsigned char ca_certificate[] = { + 0x30, 0x82, 0x03, 0xba, 0x30, 0x82, 0x02, 0xa2, + 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x0b, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x86, 0x26, + 0xe6, 0x0d, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, + 0x00, 0x30, 0x4c, 0x31, 0x20, 0x30, 0x1e, 0x06, + 0x03, 0x55, 0x04, 0x0b, 0x13, 0x17, 0x47, 0x6c, + 0x6f, 0x62, 0x61, 0x6c, 0x53, 0x69, 0x67, 0x6e, + 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, + 0x20, 0x2d, 0x20, 0x52, 0x32, 0x31, 0x13, 0x30, + 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, + 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x53, 0x69, + 0x67, 0x6e, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x0a, 0x47, 0x6c, 0x6f, + 0x62, 0x61, 0x6c, 0x53, 0x69, 0x67, 0x6e, 0x30, + 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x31, 0x32, 0x31, + 0x35, 0x30, 0x38, 0x30, 0x30, 0x30, 0x30, 0x5a, + 0x17, 0x0d, 0x32, 0x31, 0x31, 0x32, 0x31, 0x35, + 0x30, 0x38, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, + 0x4c, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x03, 0x55, + 0x04, 0x0b, 0x13, 0x17, 0x47, 0x6c, 0x6f, 0x62, + 0x61, 0x6c, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x52, + 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2d, + 0x20, 0x52, 0x32, 0x31, 0x13, 0x30, 0x11, 0x06, + 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x47, 0x6c, + 0x6f, 0x62, 0x61, 0x6c, 0x53, 0x69, 0x67, 0x6e, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x0a, 0x47, 0x6c, 0x6f, 0x62, 0x61, + 0x6c, 0x53, 0x69, 0x67, 0x6e, 0x30, 0x82, 0x01, + 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, + 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, + 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xa6, 0xcf, + 0x24, 0x0e, 0xbe, 0x2e, 0x6f, 0x28, 0x99, 0x45, + 0x42, 0xc4, 0xab, 0x3e, 0x21, 0x54, 0x9b, 0x0b, + 0xd3, 0x7f, 0x84, 0x70, 0xfa, 0x12, 0xb3, 0xcb, + 0xbf, 0x87, 0x5f, 0xc6, 0x7f, 0x86, 0xd3, 0xb2, + 0x30, 0x5c, 0xd6, 0xfd, 0xad, 0xf1, 0x7b, 0xdc, + 0xe5, 0xf8, 0x60, 0x96, 0x09, 0x92, 0x10, 0xf5, + 0xd0, 0x53, 0xde, 0xfb, 0x7b, 0x7e, 0x73, 0x88, + 0xac, 0x52, 0x88, 0x7b, 0x4a, 0xa6, 0xca, 0x49, + 0xa6, 0x5e, 0xa8, 0xa7, 0x8c, 0x5a, 0x11, 0xbc, + 0x7a, 0x82, 0xeb, 0xbe, 0x8c, 0xe9, 0xb3, 0xac, + 0x96, 0x25, 0x07, 0x97, 0x4a, 0x99, 0x2a, 0x07, + 0x2f, 0xb4, 0x1e, 0x77, 0xbf, 0x8a, 0x0f, 0xb5, + 0x02, 0x7c, 0x1b, 0x96, 0xb8, 0xc5, 0xb9, 0x3a, + 0x2c, 0xbc, 0xd6, 0x12, 0xb9, 0xeb, 0x59, 0x7d, + 0xe2, 0xd0, 0x06, 0x86, 0x5f, 0x5e, 0x49, 0x6a, + 0xb5, 0x39, 0x5e, 0x88, 0x34, 0xec, 0xbc, 0x78, + 0x0c, 0x08, 0x98, 0x84, 0x6c, 0xa8, 0xcd, 0x4b, + 0xb4, 0xa0, 0x7d, 0x0c, 0x79, 0x4d, 0xf0, 0xb8, + 0x2d, 0xcb, 0x21, 0xca, 0xd5, 0x6c, 0x5b, 0x7d, + 0xe1, 0xa0, 0x29, 0x84, 0xa1, 0xf9, 0xd3, 0x94, + 0x49, 0xcb, 0x24, 0x62, 0x91, 0x20, 0xbc, 0xdd, + 0x0b, 0xd5, 0xd9, 0xcc, 0xf9, 0xea, 0x27, 0x0a, + 0x2b, 0x73, 0x91, 0xc6, 0x9d, 0x1b, 0xac, 0xc8, + 0xcb, 0xe8, 0xe0, 0xa0, 0xf4, 0x2f, 0x90, 0x8b, + 0x4d, 0xfb, 0xb0, 0x36, 0x1b, 0xf6, 0x19, 0x7a, + 0x85, 0xe0, 0x6d, 0xf2, 0x61, 0x13, 0x88, 0x5c, + 0x9f, 0xe0, 0x93, 0x0a, 0x51, 0x97, 0x8a, 0x5a, + 0xce, 0xaf, 0xab, 0xd5, 0xf7, 0xaa, 0x09, 0xaa, + 0x60, 0xbd, 0xdc, 0xd9, 0x5f, 0xdf, 0x72, 0xa9, + 0x60, 0x13, 0x5e, 0x00, 0x01, 0xc9, 0x4a, 0xfa, + 0x3f, 0xa4, 0xea, 0x07, 0x03, 0x21, 0x02, 0x8e, + 0x82, 0xca, 0x03, 0xc2, 0x9b, 0x8f, 0x02, 0x03, + 0x01, 0x00, 0x01, 0xa3, 0x81, 0x9c, 0x30, 0x81, + 0x99, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, + 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, + 0x06, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, + 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, + 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, + 0x0e, 0x04, 0x16, 0x04, 0x14, 0x9b, 0xe2, 0x07, + 0x57, 0x67, 0x1c, 0x1e, 0xc0, 0x6a, 0x06, 0xde, + 0x59, 0xb4, 0x9a, 0x2d, 0xdf, 0xdc, 0x19, 0x86, + 0x2e, 0x30, 0x36, 0x06, 0x03, 0x55, 0x1d, 0x1f, + 0x04, 0x2f, 0x30, 0x2d, 0x30, 0x2b, 0xa0, 0x29, + 0xa0, 0x27, 0x86, 0x25, 0x68, 0x74, 0x74, 0x70, + 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x67, + 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x73, 0x69, 0x67, + 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2f, 0x72, 0x6f, + 0x6f, 0x74, 0x2d, 0x72, 0x32, 0x2e, 0x63, 0x72, + 0x6c, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, + 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x9b, 0xe2, + 0x07, 0x57, 0x67, 0x1c, 0x1e, 0xc0, 0x6a, 0x06, + 0xde, 0x59, 0xb4, 0x9a, 0x2d, 0xdf, 0xdc, 0x19, + 0x86, 0x2e, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, + 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x99, 0x81, + 0x53, 0x87, 0x1c, 0x68, 0x97, 0x86, 0x91, 0xec, + 0xe0, 0x4a, 0xb8, 0x44, 0x0b, 0xab, 0x81, 0xac, + 0x27, 0x4f, 0xd6, 0xc1, 0xb8, 0x1c, 0x43, 0x78, + 0xb3, 0x0c, 0x9a, 0xfc, 0xea, 0x2c, 0x3c, 0x6e, + 0x61, 0x1b, 0x4d, 0x4b, 0x29, 0xf5, 0x9f, 0x05, + 0x1d, 0x26, 0xc1, 0xb8, 0xe9, 0x83, 0x00, 0x62, + 0x45, 0xb6, 0xa9, 0x08, 0x93, 0xb9, 0xa9, 0x33, + 0x4b, 0x18, 0x9a, 0xc2, 0xf8, 0x87, 0x88, 0x4e, + 0xdb, 0xdd, 0x71, 0x34, 0x1a, 0xc1, 0x54, 0xda, + 0x46, 0x3f, 0xe0, 0xd3, 0x2a, 0xab, 0x6d, 0x54, + 0x22, 0xf5, 0x3a, 0x62, 0xcd, 0x20, 0x6f, 0xba, + 0x29, 0x89, 0xd7, 0xdd, 0x91, 0xee, 0xd3, 0x5c, + 0xa2, 0x3e, 0xa1, 0x5b, 0x41, 0xf5, 0xdf, 0xe5, + 0x64, 0x43, 0x2d, 0xe9, 0xd5, 0x39, 0xab, 0xd2, + 0xa2, 0xdf, 0xb7, 0x8b, 0xd0, 0xc0, 0x80, 0x19, + 0x1c, 0x45, 0xc0, 0x2d, 0x8c, 0xe8, 0xf8, 0x2d, + 0xa4, 0x74, 0x56, 0x49, 0xc5, 0x05, 0xb5, 0x4f, + 0x15, 0xde, 0x6e, 0x44, 0x78, 0x39, 0x87, 0xa8, + 0x7e, 0xbb, 0xf3, 0x79, 0x18, 0x91, 0xbb, 0xf4, + 0x6f, 0x9d, 0xc1, 0xf0, 0x8c, 0x35, 0x8c, 0x5d, + 0x01, 0xfb, 0xc3, 0x6d, 0xb9, 0xef, 0x44, 0x6d, + 0x79, 0x46, 0x31, 0x7e, 0x0a, 0xfe, 0xa9, 0x82, + 0xc1, 0xff, 0xef, 0xab, 0x6e, 0x20, 0xc4, 0x50, + 0xc9, 0x5f, 0x9d, 0x4d, 0x9b, 0x17, 0x8c, 0x0c, + 0xe5, 0x01, 0xc9, 0xa0, 0x41, 0x6a, 0x73, 0x53, + 0xfa, 0xa5, 0x50, 0xb4, 0x6e, 0x25, 0x0f, 0xfb, + 0x4c, 0x18, 0xf4, 0xfd, 0x52, 0xd9, 0x8e, 0x69, + 0xb1, 0xe8, 0x11, 0x0f, 0xde, 0x88, 0xd8, 0xfb, + 0x1d, 0x49, 0xf7, 0xaa, 0xde, 0x95, 0xcf, 0x20, + 0x78, 0xc2, 0x60, 0x12, 0xdb, 0x25, 0x40, 0x8c, + 0x6a, 0xfc, 0x7e, 0x42, 0x38, 0x40, 0x64, 0x12, + 0xf7, 0x9e, 0x81, 0xe1, 0x93, 0x2e, +}; + +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +static const unsigned char client_psk[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f +}; + +static const char client_psk_id[] = "Client_identity"; +#endif + +#endif diff --git a/subsys/net/ip/net_tls.h b/subsys/net/ip/net_tls_internal.h similarity index 88% rename from subsys/net/ip/net_tls.h rename to subsys/net/ip/net_tls_internal.h index ea3103bbc0035..acd1ece3297b6 100644 --- a/subsys/net/ip/net_tls.h +++ b/subsys/net/ip/net_tls_internal.h @@ -4,10 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ -#ifndef __NET_TLS_H -#define __NET_TLS_H +#ifndef __NET_TLS_INTERNAL_H +#define __NET_TLS_INTERNAL_H #include +#include #if defined(CONFIG_NET_TLS) || defined(CONFIG_NET_DTLS) @@ -40,6 +41,11 @@ #endif /* CONFIG_MBEDTLS */ + +/** + * @brief Initialize TLS module. + */ +void net_tls_init(void); int net_tls_enable(struct net_context *context, bool enabled); int net_tls_connect(struct net_context *context, bool listening); int net_tls_send(struct net_pkt *pkt); @@ -47,6 +53,10 @@ int net_tls_recv(struct net_context *context, net_context_recv_cb_t cb, void *user_data); #else +static inline void net_tls_init(void) +{ +} + static inline int net_tls_enable(struct net_context *context, bool enabled) { ARG_UNUSED(context); @@ -81,4 +91,4 @@ static inline int net_tls_recv(struct net_context *context, } #endif /* CONFIG_NET_TLS || CONFIG_NET_DTLS */ -#endif +#endif /* __NET_TLS_INTERNAL_H */ From 2c128671a621105b69524eaef1b636d2d49a23ec Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Fri, 11 May 2018 11:34:44 +0200 Subject: [PATCH 13/24] net: socket: Add socket option to select tls credentials This commit adds a socket option to configure which credentials should be used for TLS/DTLS session. After credentials are registered in the system (this part is socket independent) they can be selected to use with specific socket by passing security tags associated with credentials via TLS_SEC_TAG_LIST option. Signed-off-by: Robert Lubos --- include/net/net_context.h | 9 +- include/net/net_tls.h | 16 ++- include/net/socket.h | 10 +- subsys/net/ip/net_context.c | 61 ++++++++++-- subsys/net/ip/net_tls.c | 102 +++++++++++++++++++- subsys/net/ip/net_tls_default_credentials.h | 4 +- subsys/net/ip/net_tls_internal.h | 27 ++++++ subsys/net/lib/sockets/sockets.c | 6 +- subsys/net/lib/sockets/sockets_tls.c | 28 ++++-- tests/net/socket/sockopt/src/main.c | 28 +++--- 10 files changed, 247 insertions(+), 44 deletions(-) diff --git a/include/net/net_context.h b/include/net/net_context.h index 050d07631296d..f9caa0222baaf 100644 --- a/include/net/net_context.h +++ b/include/net/net_context.h @@ -26,6 +26,7 @@ #include #include #include +#include #if defined(CONFIG_NET_TLS) || defined(CONFIG_NET_DTLS) #if defined(CONFIG_MBEDTLS) @@ -225,6 +226,9 @@ struct net_context { #if defined(CONFIG_NET_TLS) || defined(CONFIG_NET_DTLS) /** Enable/disable TLS for the context */ bool tls; + + /** Select which credentials to use with TLS. */ + struct sec_tag_list sec_tag_list; #endif } options; @@ -807,8 +811,9 @@ int net_context_update_recv_wnd(struct net_context *context, s32_t delta); enum net_context_option { - NET_OPT_PRIORITY = 1, - NET_OPT_TLS = 2, + NET_OPT_PRIORITY = 1, + NET_OPT_TLS_ENABLE = 2, + NET_OPT_TLS_SEC_TAG_LIST = 3, }; /** diff --git a/include/net/net_tls.h b/include/net/net_tls.h index 8a2724ad53cb5..d40f29b952c09 100644 --- a/include/net/net_tls.h +++ b/include/net/net_tls.h @@ -40,6 +40,15 @@ typedef int sec_tag_t; #if defined(CONFIG_NET_TLS) || defined(CONFIG_NET_DTLS) +/** A list of secure tags that context should use */ +struct sec_tag_list { + /** An array of secure tags referencing TLS credentials */ + sec_tag_t sec_tags[CONFIG_NET_MAX_CREDENTIALS_NUMBER]; + + /** Number of configured secure tags */ + int sec_tag_count; +}; + /** * @brief Add a TLS credential. * @@ -53,7 +62,7 @@ typedef int sec_tag_t; * * @return 0 if ok, < 0 if error. */ -int net_tls_credential_add(int tag, enum net_tls_credential_type type, +int net_tls_credential_add(sec_tag_t tag, enum net_tls_credential_type type, const void *cred, size_t credlen); /** @@ -69,7 +78,7 @@ int net_tls_credential_add(int tag, enum net_tls_credential_type type, * * @return 0 if ok, < 0 if error. */ -int net_tls_credential_get(int tag, enum net_tls_credential_type type, +int net_tls_credential_get(sec_tag_t tag, enum net_tls_credential_type type, void *cred, size_t *credlen); /** @@ -83,7 +92,8 @@ int net_tls_credential_get(int tag, enum net_tls_credential_type type, * * @return 0 if ok, < 0 if error. */ -int net_tls_credential_delete(int tag, enum net_tls_credential_type type); +int net_tls_credential_delete(sec_tag_t tag, + enum net_tls_credential_type type); #else diff --git a/include/net/socket.h b/include/net/socket.h index a810f4e248db5..81fdc79029e9b 100644 --- a/include/net/socket.h +++ b/include/net/socket.h @@ -46,8 +46,14 @@ struct zsock_pollfd { /* socket option for TCP */ #define SOL_TCP 6 -/* TCP socket options */ -#define TCP_TLS 0xff +/* Socket option for TLS. + * Here, the same socket option level for TLS as in Linux was used. + */ +#define SOL_TLS 282 + +/* TLS socket options */ +#define TLS_ENABLE 1 +#define TLS_SEC_TAG_LIST 2 struct zsock_addrinfo { struct zsock_addrinfo *ai_next; diff --git a/subsys/net/ip/net_context.c b/subsys/net/ip/net_context.c index dad4e038f2911..9f84dd7cda55d 100644 --- a/subsys/net/ip/net_context.c +++ b/subsys/net/ip/net_context.c @@ -1336,8 +1336,8 @@ static int get_context_priority(struct net_context *context, #endif } -static int get_context_tls(struct net_context *context, - void *value, size_t *len) +static int get_context_tls_enable(struct net_context *context, + void *value, size_t *len) { #if defined(CONFIG_NET_TLS) || defined(CONFIG_NET_DTLS) if (!len || *len != sizeof(int)) { @@ -1352,8 +1352,8 @@ static int get_context_tls(struct net_context *context, #endif } -static int set_context_tls(struct net_context *context, - const void *value, size_t len) +static int set_context_tls_enable(struct net_context *context, + const void *value, size_t len) { #if defined(CONFIG_NET_TLS) || defined(CONFIG_NET_DTLS) bool enabled; @@ -1370,6 +1370,44 @@ static int set_context_tls(struct net_context *context, #endif } +static int get_context_tls_sec_tag_list(struct net_context *context, + void *value, size_t *len) +{ +#if defined(CONFIG_NET_TLS) || defined(CONFIG_NET_DTLS) + int ret; + int sec_tag_cnt; + + if (!len || !value || *len % sizeof(sec_tag_t) != 0) + return -EINVAL; + + sec_tag_cnt = *len / sizeof(sec_tag_t); + + ret = net_tls_sec_tag_list_get(context, value, &sec_tag_cnt); + if (ret < 0) + return ret; + + *len = sec_tag_cnt * sizeof(sec_tag_t); + + return 0; +#else + return -ENOTSUP; +#endif /* defined(CONFIG_NET_TLS) || defined(CONFIG_NET_DTLS) */ +} + +static int set_context_tls_sec_tag_list(struct net_context *context, + const void *value, size_t len) +{ +#if defined(CONFIG_NET_TLS) || defined(CONFIG_NET_DTLS) + if (!value || len % sizeof(sec_tag_t) != 0) + return -EINVAL; + + return net_tls_sec_tag_list_set(context, value, + len / sizeof(sec_tag_t)); +#else + return -ENOTSUP; +#endif /* defined(CONFIG_NET_TLS) || defined(CONFIG_NET_DTLS) */ +} + int net_context_set_option(struct net_context *context, enum net_context_option option, const void *value, size_t len) @@ -1391,10 +1429,13 @@ int net_context_set_option(struct net_context *context, ret = set_context_priority(context, value, len); break; - case NET_OPT_TLS: - ret = set_context_tls(context, value, len); + case NET_OPT_TLS_ENABLE: + ret = set_context_tls_enable(context, value, len); break; + case NET_OPT_TLS_SEC_TAG_LIST: + ret = set_context_tls_sec_tag_list(context, value, len); + break; } return ret; @@ -1421,8 +1462,12 @@ int net_context_get_option(struct net_context *context, ret = get_context_priority(context, value, len); break; - case NET_OPT_TLS: - ret = get_context_tls(context, value, len); + case NET_OPT_TLS_ENABLE: + ret = get_context_tls_enable(context, value, len); + break; + + case NET_OPT_TLS_SEC_TAG_LIST: + ret = get_context_tls_sec_tag_list(context, value, len); break; } diff --git a/subsys/net/ip/net_tls.c b/subsys/net/ip/net_tls.c index c4658f60e5dc8..a5296976c7d5a 100644 --- a/subsys/net/ip/net_tls.c +++ b/subsys/net/ip/net_tls.c @@ -21,7 +21,7 @@ static mbedtls_ctr_drbg_context tls_ctr_drbg; struct net_tls_credential { enum net_tls_credential_type type; - int tag; + sec_tag_t tag; const void *buf; size_t len; }; @@ -226,6 +226,39 @@ static void tls_recv_cb(struct net_context *context, struct net_pkt *pkt, net_pkt_unref(decrypted_pkt); } +static int tls_mbedtls_set_credentials(struct net_context *context) +{ + struct net_tls_credential *credential; + sec_tag_t tag; + int i; + + for (i = 0; i < context->options.sec_tag_list.sec_tag_count; i++) { + tag = context->options.sec_tag_list.sec_tags[i]; + credential = NULL; + + while ((credential = credential_next_get(tag, credential)) != NULL) { + switch (credential->type) { + case NET_TLS_CREDENTIAL_CA_CERTIFICATE: + /* TODO configure mbedtls CA CERTIFICATE */ + break; + + case NET_TLS_CREDENTIAL_PSK: + /* TODO configure mbedtls PSK */ + break; + + case NET_TLS_CREDENTIAL_PSK_ID: + /* Ignore PSK Id - it will be used together with PSK */ + break; + + default: + return -EINVAL; + } + } + } + + return 0; +} + void net_tls_init(void) { int i; @@ -324,6 +357,11 @@ int net_tls_connect(struct net_context *context, bool listening) mbedtls_ssl_conf_rng(&context->mbedtls.config, tls_mbedtls_ctr_drbg_random, &tls_ctr_drbg); + err = tls_mbedtls_set_credentials(context); + if (err) { + goto mbed_err_conf; + } + err = mbedtls_ssl_setup(&context->mbedtls.ssl, &context->mbedtls.config); if (err) { @@ -398,7 +436,65 @@ int net_tls_recv(struct net_context *context, net_context_recv_cb_t cb, return 0; } -int net_tls_credential_add(int tag, enum net_tls_credential_type type, +int net_tls_sec_tag_list_get(struct net_context *context, + sec_tag_t *sec_tags, int *sec_tag_cnt) +{ + int tags_to_copy; + + if (!context || !sec_tags || !sec_tag_cnt) { + return -EINVAL; + } + + if (!context->options.tls) { + return -EPERM; + } + + tags_to_copy = MIN(context->options.sec_tag_list.sec_tag_count, + *sec_tag_cnt); + memcpy(sec_tags, context->options.sec_tag_list.sec_tags, + tags_to_copy * sizeof(sec_tag_t)); + *sec_tag_cnt = tags_to_copy; + + return 0; +} + +int net_tls_sec_tag_list_set(struct net_context *context, + const sec_tag_t *sec_tags, int sec_tag_cnt) +{ + enum net_context_state state; + int i; + + if (!context || !sec_tags) { + return -EINVAL; + } + + if (!context->options.tls) { + return -EPERM; + } + + state = net_context_get_state(context); + if (state != NET_CONTEXT_IDLE && state != NET_CONTEXT_UNCONNECTED) { + return -EPERM; + } + + if (sec_tag_cnt > ARRAY_SIZE(context->options.sec_tag_list.sec_tags)) { + return -ENOMEM; + } + + for (i = 0; i < sec_tag_cnt; i++) { + if (credential_next_get(sec_tags[i], NULL) == NULL) { + return -ENOENT; + } + } + + memcpy(context->options.sec_tag_list.sec_tags, sec_tags, + sec_tag_cnt * sizeof(sec_tag_t)); + context->options.sec_tag_list.sec_tag_count = sec_tag_cnt; + + return 0; +} + +int net_tls_credential_add(sec_tag_t tag, enum net_tls_credential_type type, const void *cred, size_t credlen) { struct net_tls_credential *credential = credential_get(tag, type); @@ -435,7 +531,7 @@ int net_tls_credential_get(sec_tag_t tag, enum net_tls_credential_type type, return 0; } -int net_tls_credential_delete(int tag, enum net_tls_credential_type type) +int net_tls_credential_delete(sec_tag_t tag, enum net_tls_credential_type type) { struct net_tls_credential *credential = NULL; diff --git a/subsys/net/ip/net_tls_default_credentials.h b/subsys/net/ip/net_tls_default_credentials.h index 9ebd7681d054c..8c9896ae13e63 100644 --- a/subsys/net/ip/net_tls_default_credentials.h +++ b/subsys/net/ip/net_tls_default_credentials.h @@ -7,8 +7,8 @@ #ifndef __NET_TLS_DEFAULT_CREDENTIALS_H__ #define __NET_TLS_DEFAULT_CREDENTIALS_H__ -#define NET_TLS_DEFAULT_CA_CERTIFICATE_TAG 0 -#define NET_TLS_DEFAULT_PSK_TAG 1 +#define NET_TLS_DEFAULT_CA_CERTIFICATE_TAG 1 +#define NET_TLS_DEFAULT_PSK_TAG 2 #if defined(MBEDTLS_X509_CRT_PARSE_C) diff --git a/subsys/net/ip/net_tls_internal.h b/subsys/net/ip/net_tls_internal.h index acd1ece3297b6..3cdfef77fe101 100644 --- a/subsys/net/ip/net_tls_internal.h +++ b/subsys/net/ip/net_tls_internal.h @@ -51,6 +51,10 @@ int net_tls_connect(struct net_context *context, bool listening); int net_tls_send(struct net_pkt *pkt); int net_tls_recv(struct net_context *context, net_context_recv_cb_t cb, void *user_data); +int net_tls_sec_tag_list_get(struct net_context *context, sec_tag_t *sec_tags, + int *sec_tag_cnt); +int net_tls_sec_tag_list_set(struct net_context *context, + const sec_tag_t *sec_tags, int sec_tag_cnt); #else static inline void net_tls_init(void) @@ -89,6 +93,29 @@ static inline int net_tls_recv(struct net_context *context, return 0; } + +static inline int net_tls_sec_tag_list_get(struct net_context *context, + sec_tag_t *sec_tags, + int *sec_tag_cnt) +{ + ARG_UNUSED(context); + ARG_UNUSED(sec_tags); + ARG_UNUSED(sec_tag_cnt); + + return 0; +} + +static inline int net_tls_sec_tag_list_set(struct net_context *context, + const sec_tag_t *sec_tags, + int sec_tag_cnt) +{ + ARG_UNUSED(context); + ARG_UNUSED(sec_tags); + ARG_UNUSED(sec_tag_cnt); + + return 0; +} + #endif /* CONFIG_NET_TLS || CONFIG_NET_DTLS */ #endif /* __NET_TLS_INTERNAL_H */ diff --git a/subsys/net/lib/sockets/sockets.c b/subsys/net/lib/sockets/sockets.c index 808149a661150..6f29beba345d9 100644 --- a/subsys/net/lib/sockets/sockets.c +++ b/subsys/net/lib/sockets/sockets.c @@ -590,8 +590,7 @@ int zsock_getsockopt(int sock, int level, int optname, } switch (level) { - case SOL_TCP: - /* TLS is the only one implemented right now */ + case SOL_TLS: ret = tls_getsockopt(sock, level, optname, optval, optlen); break; @@ -615,8 +614,7 @@ int zsock_setsockopt(int sock, int level, int optname, } switch (level) { - case SOL_TCP: - /* TLS is the only one implemented right now */ + case SOL_TLS: ret = tls_setsockopt(sock, level, optname, optval, optlen); break; diff --git a/subsys/net/lib/sockets/sockets_tls.c b/subsys/net/lib/sockets/sockets_tls.c index a28dbae9629f2..6208a421bdb02 100644 --- a/subsys/net/lib/sockets/sockets_tls.c +++ b/subsys/net/lib/sockets/sockets_tls.c @@ -24,13 +24,21 @@ int tls_getsockopt(int sock, int level, int optname, } switch (optname) { - case TCP_TLS: + case TLS_ENABLE: if (*optlen != sizeof(int)) { return -EINVAL; } - if (net_context_get_option(ctx, NET_OPT_TLS, optval, - optlen) < 0) { + if (net_context_get_option(ctx, NET_OPT_TLS_ENABLE, + optval, optlen) < 0) { + ret = -EINVAL; + } + + break; + + case TLS_SEC_TAG_LIST: + if (net_context_get_option(ctx, NET_OPT_TLS_SEC_TAG_LIST, + optval, optlen) < 0) { ret = -EINVAL; } @@ -58,13 +66,21 @@ int tls_setsockopt(int sock, int level, int optname, } switch (optname) { - case TCP_TLS: + case TLS_ENABLE: if (optlen != sizeof(int)) { return -EINVAL; } - if (net_context_set_option(ctx, NET_OPT_TLS, optval, - optlen) < 0) { + if (net_context_set_option(ctx, NET_OPT_TLS_ENABLE, + optval, optlen) < 0) { + ret = -EINVAL; + } + + break; + + case TLS_SEC_TAG_LIST: + if (net_context_set_option(ctx, NET_OPT_TLS_SEC_TAG_LIST, + optval, optlen) < 0) { ret = -EINVAL; } diff --git a/tests/net/socket/sockopt/src/main.c b/tests/net/socket/sockopt/src/main.c index 200ed809ec378..03b27bdb555c7 100644 --- a/tests/net/socket/sockopt/src/main.c +++ b/tests/net/socket/sockopt/src/main.c @@ -71,7 +71,7 @@ static void test_getsockopt(void) zassert_equal(errno, EOPNOTSUPP, "getsockopt errno"); errno = 0; - zassert_equal(getsockopt(s6_tcp, SOL_TCP, 0, NULL, NULL), -1, + zassert_equal(getsockopt(s6_tcp, SOL_TLS, 0, NULL, NULL), -1, "getsockopt"); zassert_equal(errno, EFAULT, "getsockopt errno"); @@ -79,46 +79,46 @@ static void test_getsockopt(void) &s6_udp, &addr6); errno = 0; - zassert_equal(getsockopt(s6_udp, SOL_TCP, 0, &enable, &size), -1, + zassert_equal(getsockopt(s6_udp, SOL_TLS, 0, &enable, &size), -1, "getsockopt"); zassert_equal(errno, EBADF, "getsockopt errno"); errno = 0; - zassert_equal(getsockopt(s6_tcp, SOL_TCP, 0, &enable, NULL), -1, + zassert_equal(getsockopt(s6_tcp, SOL_TLS, 0, &enable, NULL), -1, "getsockopt"); zassert_equal(errno, EFAULT, "getsockopt errno"); errno = 0; - zassert_equal(getsockopt(s6_tcp, SOL_TCP, 0, NULL, &size), -1, + zassert_equal(getsockopt(s6_tcp, SOL_TLS, 0, NULL, &size), -1, "getsockopt"); zassert_equal(errno, EFAULT, "getsockopt errno"); errno = 0; - zassert_equal(getsockopt(s6_tcp, SOL_TCP, 0, &enable, NULL), -1, + zassert_equal(getsockopt(s6_tcp, SOL_TLS, 0, &enable, NULL), -1, "getsockopt"); zassert_equal(errno, EFAULT, "getsockopt errno"); errno = 0; size = 0; - zassert_equal(getsockopt(s6_tcp, SOL_TCP, 0, &enable, &size), -1, + zassert_equal(getsockopt(s6_tcp, SOL_TLS, 0, &enable, &size), -1, "getsockopt"); zassert_equal(errno, EFAULT, "getsockopt errno"); size = 0; errno = 0; - zassert_equal(getsockopt(s6_tcp, SOL_TCP, 0, &enable, &size), -1, + zassert_equal(getsockopt(s6_tcp, SOL_TLS, 0, &enable, &size), -1, "getsockopt"); zassert_equal(errno, EFAULT, "getsockopt errno"); size = sizeof(enable); errno = 0; - zassert_equal(getsockopt(s6_tcp, SOL_TCP, 0, &enable, &size), + zassert_equal(getsockopt(s6_tcp, SOL_TLS, 0, &enable, &size), -1, "getsockopt"); zassert_equal(errno, ENOPROTOOPT, "getsockopt errno"); zassert_equal(size, sizeof(enable), "getsockopt errno"); errno = 0; - zassert_equal(getsockopt(s6_tcp, SOL_TCP, TCP_TLS, &enable, &size), + zassert_equal(getsockopt(s6_tcp, SOL_TLS, TLS_ENABLE, &enable, &size), 0, "getsockopt"); zassert_equal(errno, 0, "getsockopt errno"); zassert_equal(size, sizeof(enable), "getsockopt errno"); @@ -144,17 +144,17 @@ static void test_setsockopt(void) zassert_equal(errno, EOPNOTSUPP, "setsockopt errno"); errno = 0; - zassert_equal(setsockopt(s6_tcp, SOL_TCP, 0, NULL, 0), -1, + zassert_equal(setsockopt(s6_tcp, SOL_TLS, 0, NULL, 0), -1, "setsockopt"); zassert_equal(errno, EFAULT, "setsockopt errno"); errno = 0; - zassert_equal(setsockopt(s6_tcp, SOL_TCP, 0, &enable, 0), -1, + zassert_equal(setsockopt(s6_tcp, SOL_TLS, 0, &enable, 0), -1, "setsockopt"); zassert_equal(errno, EFAULT, "setsockopt errno"); errno = 0; - zassert_equal(setsockopt(s6_tcp, SOL_TCP, 0, &enable, sizeof(enable)), + zassert_equal(setsockopt(s6_tcp, SOL_TLS, 0, &enable, sizeof(enable)), -1, "setsockopt"); zassert_equal(errno, ENOPROTOOPT, "setsockopt errno"); @@ -162,12 +162,12 @@ static void test_setsockopt(void) &s6_udp, &addr6); errno = 0; - zassert_equal(setsockopt(s6_udp, SOL_TCP, 0, &enable, sizeof(enable)), + zassert_equal(setsockopt(s6_udp, SOL_TLS, 0, &enable, sizeof(enable)), -1, "setsockopt"); zassert_equal(errno, EBADF, "setsockopt errno"); errno = 0; - zassert_equal(setsockopt(s6_tcp, SOL_TCP, TCP_TLS, + zassert_equal(setsockopt(s6_tcp, SOL_TLS, TLS_ENABLE, &enable, sizeof(enable)), 0, "setsockopt"); zassert_equal(errno, 0, "setsockopt errno"); From ae911caa4a844752a38c957c515df4fb7aa91213 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Tue, 15 May 2018 10:58:41 +0200 Subject: [PATCH 14/24] net: tls: Configure tls credentials in mbedtls Read TLS credentials from the storage and configure them in mbedtls during connection establishement. Signed-off-by: Robert Lubos --- include/net/net_context.h | 3 ++ subsys/net/ip/net_tls.c | 87 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 85 insertions(+), 5 deletions(-) diff --git a/include/net/net_context.h b/include/net/net_context.h index f9caa0222baaf..cb24ea69fe79f 100644 --- a/include/net/net_context.h +++ b/include/net/net_context.h @@ -237,6 +237,9 @@ struct net_context { struct { mbedtls_ssl_context ssl; mbedtls_ssl_config config; +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_x509_crt ca_chain; +#endif /** intermediated mbedTLS buffer to store decrypted content */ char rx_ssl_buf[64]; /** TLS packet fifo */ diff --git a/subsys/net/ip/net_tls.c b/subsys/net/ip/net_tls.c index a5296976c7d5a..0c74a71e11746 100644 --- a/subsys/net/ip/net_tls.c +++ b/subsys/net/ip/net_tls.c @@ -226,28 +226,95 @@ static void tls_recv_cb(struct net_context *context, struct net_pkt *pkt, net_pkt_unref(decrypted_pkt); } +static int tls_add_ca_certificate(struct net_context *context, + struct net_tls_credential *ca_cert) +{ +#if defined(MBEDTLS_X509_CRT_PARSE_C) + int err = mbedtls_x509_crt_parse(&context->mbedtls.ca_chain, + ca_cert->buf, ca_cert->len); + if (err != 0) { + return -EINVAL; + } +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + return 0; +} + +static void tls_set_ca_chain(struct net_context *context) +{ +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_ssl_conf_ca_chain(&context->mbedtls.config, + &context->mbedtls.ca_chain, NULL); + + mbedtls_ssl_conf_authmode(&context->mbedtls.config, + MBEDTLS_SSL_VERIFY_REQUIRED); + + mbedtls_ssl_conf_cert_profile(&context->mbedtls.config, + &mbedtls_x509_crt_profile_default); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ +} + +static int tls_set_psk(struct net_context *context, + struct net_tls_credential *psk, + struct net_tls_credential *psk_id) +{ +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + mbedtls_ssl_conf_psk(&context->mbedtls.config, + psk->buf, psk->len, + (const unsigned char *)psk_id->buf, + psk_id->len - 1); +#endif + + return 0; +} + static int tls_mbedtls_set_credentials(struct net_context *context) { struct net_tls_credential *credential; sec_tag_t tag; - int i; + int i, err; + bool ca_cert_present = false; for (i = 0; i < context->options.sec_tag_list.sec_tag_count; i++) { tag = context->options.sec_tag_list.sec_tags[i]; credential = NULL; - while ((credential = credential_next_get(tag, credential)) != NULL) { + while ((credential = credential_next_get(tag, credential)) + != NULL) { switch (credential->type) { case NET_TLS_CREDENTIAL_CA_CERTIFICATE: - /* TODO configure mbedtls CA CERTIFICATE */ + { + err = tls_add_ca_certificate(context, + credential); + if (err < 0) { + return err; + } + + ca_cert_present = true; + break; + } case NET_TLS_CREDENTIAL_PSK: - /* TODO configure mbedtls PSK */ + { + struct net_tls_credential *psk_id = + credential_get( + tag, NET_TLS_CREDENTIAL_PSK_ID); + + if (!psk_id) { + return -ENOENT; + } + + err = tls_set_psk(context, credential, psk_id); + if (err < 0) { + return err; + } + break; + } case NET_TLS_CREDENTIAL_PSK_ID: - /* Ignore PSK Id - it will be used together with PSK */ + /* Ignore PSK ID - it will be used together with PSK */ break; default: @@ -256,6 +323,10 @@ static int tls_mbedtls_set_credentials(struct net_context *context) } } + if (ca_cert_present) { + tls_set_ca_chain(context); + } + return 0; } @@ -307,7 +378,13 @@ int net_tls_enable(struct net_context *context, bool enabled) mbedtls_ssl_config_init(&context->mbedtls.config); mbedtls_ssl_set_bio(&context->mbedtls.ssl, context, tls_tx, tls_rx, NULL); +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_x509_crt_init(&context->mbedtls.ca_chain); +#endif } else { +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_x509_crt_free(&context->mbedtls.ca_chain); +#endif mbedtls_ssl_set_bio(&context->mbedtls.ssl, NULL, NULL, NULL, NULL); mbedtls_ssl_config_free(&context->mbedtls.config); From d7149298029b78d6819b4b151dc82cb647c68614 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Tue, 15 May 2018 14:29:29 +0200 Subject: [PATCH 15/24] net: tls: Add simple logging Add simple printf-based logging for mbedtls Signed-off-by: Robert Lubos --- subsys/net/ip/Kconfig.tls | 5 +++++ subsys/net/ip/net_tls.c | 41 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/subsys/net/ip/Kconfig.tls b/subsys/net/ip/Kconfig.tls index f8f5735dded13..7683c90251ab5 100644 --- a/subsys/net/ip/Kconfig.tls +++ b/subsys/net/ip/Kconfig.tls @@ -21,6 +21,11 @@ config NET_DTLS default n depends on NET_UDP && MBEDTLS +config NET_TLS_DEBUG + bool "Enable TLS debug log" + default n + depends on NET_TLS || NET_DTLS + config NET_MAX_CREDENTIALS_NUMBER int "Maximum number of TLS/DTLS credentials" default 4 diff --git a/subsys/net/ip/net_tls.c b/subsys/net/ip/net_tls.c index 0c74a71e11746..a917de422b260 100644 --- a/subsys/net/ip/net_tls.c +++ b/subsys/net/ip/net_tls.c @@ -4,6 +4,12 @@ * SPDX-License-Identifier: Apache-2.0 */ +#if defined(CONFIG_NET_TLS_DEBUG) +#define SYS_LOG_DOMAIN "net/tls" +#define NET_LOG_ENABLED 1 +#endif + +#include #include #include "net_private.h" @@ -29,6 +35,33 @@ struct net_tls_credential { /* Global poll of credentials shared among TLS contexts. */ static struct net_tls_credential credentials[CONFIG_NET_MAX_CREDENTIALS_NUMBER]; +#if defined(MBEDTLS_DEBUG_C) && defined(CONFIG_NET_TLS_DEBUG) +static void my_debug(void *ctx, int level, + const char *file, int line, const char *str) +{ + const char *p, *basename; + int len; + + ARG_UNUSED(ctx); + + /* Extract basename from file */ + for (p = basename = file; *p != '\0'; p++) { + if (*p == '/' || *p == '\\') { + basename = p + 1; + } + + } + + /* Avoid printing double newlines */ + len = strlen(str); + if (str[len - 1] == '\n') { + ((char *)str)[len - 1] = '\0'; + } + + NET_DBG("%s:%04d: |%d| %s", basename, line, level, str); +} +#endif /* defined(MBEDTLS_DEBUG_C) && defined(CONFIG_NET_TLS_DEBUG) */ + static struct net_tls_credential *unused_credential_get(void) { int i; @@ -353,6 +386,10 @@ void net_tls_init(void) client_psk_id, sizeof(client_psk_id)); #endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ #endif /* CONFIG_NET_PRECONFIGURE_TLS_CREDENTIALS */ + +#if defined(MBEDTLS_DEBUG_C) && defined(CONFIG_NET_TLS_DEBUG) + mbedtls_debug_set_threshold(CONFIG_MBEDTLS_DEBUG_LEVEL); +#endif } int net_tls_enable(struct net_context *context, bool enabled) @@ -381,6 +418,10 @@ int net_tls_enable(struct net_context *context, bool enabled) #if defined(MBEDTLS_X509_CRT_PARSE_C) mbedtls_x509_crt_init(&context->mbedtls.ca_chain); #endif + +#if defined(MBEDTLS_DEBUG_C) && defined(CONFIG_NET_TLS_DEBUG) + mbedtls_ssl_conf_dbg(&context->mbedtls.config, my_debug, NULL); +#endif } else { #if defined(MBEDTLS_X509_CRT_PARSE_C) mbedtls_x509_crt_free(&context->mbedtls.ca_chain); From 071920ac572b7dd4f75050e3996a7f3896084dd4 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Wed, 16 May 2018 10:46:01 +0200 Subject: [PATCH 16/24] net: tls: Provide a configurable mbedtls config file This commits provides a configfile for mbedtls that can be modifed by Kconfig. In result features like supported ciphersuites can be easily adjusted from Kconfig. Signed-off-by: Robert Lubos --- ext/lib/crypto/mbedtls/Kconfig | 1 + .../mbedtls/configs/config-tls-generic.h | 270 ++++++++++++++++++ subsys/net/ip/Kconfig.tls | 130 ++++++++- 3 files changed, 398 insertions(+), 3 deletions(-) create mode 100644 ext/lib/crypto/mbedtls/configs/config-tls-generic.h diff --git a/ext/lib/crypto/mbedtls/Kconfig b/ext/lib/crypto/mbedtls/Kconfig index 9b49b6f28b3e4..5cd8b950c2bc2 100644 --- a/ext/lib/crypto/mbedtls/Kconfig +++ b/ext/lib/crypto/mbedtls/Kconfig @@ -46,6 +46,7 @@ config MBEDTLS_CFG_FILE string "mbed TLS configuration file" depends on MBEDTLS_BUILTIN default "config-mini-tls1_2.h" + default "config-tls-generic.h" if NET_TLS || NET_DTLS help Use a specific mbed TLS configuration file. The default is suitable to communicate with majority of HTTPS servers on the Internet, but has diff --git a/ext/lib/crypto/mbedtls/configs/config-tls-generic.h b/ext/lib/crypto/mbedtls/configs/config-tls-generic.h new file mode 100644 index 0000000000000..c8041fcf026a6 --- /dev/null +++ b/ext/lib/crypto/mbedtls/configs/config-tls-generic.h @@ -0,0 +1,270 @@ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright (c) 2017 Intel Corporation. + * Copyright (c) 2018 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + * + * Generic configuration for TLS, manageable by Kconfig. + */ + +#ifndef MBEDTLS_CONFIG_H +#define MBEDTLS_CONFIG_H + +/* System support */ +#define MBEDTLS_PLATFORM_C +#define MBEDTLS_PLATFORM_MEMORY +#define MBEDTLS_MEMORY_BUFFER_ALLOC_C +#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS +#define MBEDTLS_PLATFORM_EXIT_ALT +#define MBEDTLS_NO_PLATFORM_ENTROPY +#define MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES +#define MBEDTLS_PLATFORM_PRINTF_ALT + +#if !defined(CONFIG_ARM) +#define MBEDTLS_HAVE_ASM +#endif + +#if defined(CONFIG_MBEDTLS_TEST) +#define MBEDTLS_SELF_TEST +#define MBEDTLS_DEBUG_C +#endif + +/* mbedTLS feature support */ + +/* Supported TLS versions */ +#if defined(CONFIG_NET_TLS) +#if defined(CONFIG_TLS_VERSION_1_0) +#define MBEDTLS_SSL_PROTO_TLS1 +#endif + +#if defined(CONFIG_TLS_VERSION_1_1) +#define MBEDTLS_SSL_PROTO_TLS1_1 +#endif + +#if defined(CONFIG_TLS_VERSION_1_2) +#define MBEDTLS_SSL_PROTO_TLS1_2 +#endif + +/* Module required for TLS */ +#define MBEDTLS_SSL_TLS_C +#define MBEDTLS_SSL_SRV_C +#define MBEDTLS_SSL_CLI_C +#define MBEDTLS_CIPHER_C +#define MBEDTLS_MD_C + +/* TODO Perhaps make this configurable? */ +#define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH +#endif /* CONFIG_NET_TLS */ + +#if defined(CONFIG_NET_DTLS) +#define MBEDTLS_SSL_PROTO_DTLS +#define MBEDTLS_SSL_DTLS_ANTI_REPLAY +#define MBEDTLS_SSL_DTLS_HELLO_VERIFY +#define MBEDTLS_SSL_COOKIE_C +#endif + +/* Supported key exchange methods */ +#if defined(CONFIG_TLS_KEY_EXCHANGE_PSK_ENABLED) +#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED +#endif + +#if defined(CONFIG_TLS_KEY_EXCHANGE_DHE_PSK_ENABLED) +#define MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED +#endif + +#if defined(CONFIG_TLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +#define MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED +#endif + +#if defined(CONFIG_TLS_KEY_EXCHANGE_RSA_PSK_ENABLED) +#define MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED +#endif + +#if defined(CONFIG_TLS_KEY_EXCHANGE_RSA_ENABLED) +#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED +#endif + +#if defined(CONFIG_TLS_KEY_EXCHANGE_DHE_RSA_ENABLED) +#define MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED +#endif + +#if defined(CONFIG_TLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) +#define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED +#endif + +#if defined(CONFIG_TLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +#endif + +#if defined(CONFIG_TLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +#define MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED +#endif + +#if defined(CONFIG_TLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) +#define MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED +#endif + +#if defined(CONFIG_TLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +#define MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED +#endif + +/* Supported cipher modes */ +#if defined(CONFIG_TLS_CIPHER_AES_ENABLED) +#define MBEDTLS_AES_C +#endif + +#if defined(CONFIG_TLS_CIPHER_CAMELLIA_ENABLED) +#define MBEDTLS_CAMELLIA_C +#endif + +#if defined(CONFIG_TLS_CIPHER_DES_ENABLED) +#define MBEDTLS_DES_C +#endif + +#if defined(CONFIG_TLS_CIPHER_CCM_ENABLED) +#define MBEDTLS_CCM_C +#endif + +#if defined(CONFIG_TLS_CIPHER_CBC_ENABLED) +#define MBEDTLS_CIPHER_MODE_CBC +#endif + +/* Supported message authentication methods */ + +#if defined(CONFIG_TLS_MAC_MD5_ENABLED) +#define MBEDTLS_MD5_C +#endif + +#if defined(CONFIG_TLS_MAC_SHA1_ENABLED) +#define MBEDTLS_SHA1_C +#endif + +#if defined(CONFIG_TLS_MAC_SHA256_ENABLED) +#define MBEDTLS_SHA256_C +#endif + +#if defined(CONFIG_TLS_MAC_SHA512_ENABLED) +#define MBEDTLS_SHA512_C +#endif + +/* Automatic dependencies */ + +#if defined (MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) +#define MBEDTLS_DHM_C +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) +#define MBEDTLS_ECDH_C +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) +#define MBEDTLS_RSA_C +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) +#define MBEDTLS_PKCS1_V15 +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) +#define MBEDTLS_X509_CRT_PARSE_C +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +#define MBEDTLS_ECDSA_C +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +#define MBEDTLS_ECJPAKE_C +#endif + +#if defined(MBEDTLS_ECDH_C) || \ + defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_ECJPAKE_C) +#define MBEDTLS_ECP_C +/* For now use single specific curve, can be configurable in the future */ +#define MBEDTLS_ECP_DP_SECP256R1_ENABLED +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#define MBEDTLS_X509_USE_C +#endif + +#if defined(MBEDTLS_X509_USE_C) || \ + defined(MBEDTLS_ECDSA_C) +#define MBEDTLS_ASN1_PARSE_C +#endif + +#if defined(MBEDTLS_ECDSA_C) +#define MBEDTLS_ASN1_WRITE_C +#endif + +#if defined(MBEDTLS_DHM_C) || \ + defined(MBEDTLS_ECP_C) || \ + defined(MBEDTLS_RSA_C) || \ + defined(MBEDTLS_X509_USE_C) +#define MBEDTLS_BIGNUM_C +#endif + +#if defined(MBEDTLS_RSA_C) || \ + defined(MBEDTLS_X509_USE_C) +#define MBEDTLS_OID_C +#endif + +#if defined(MBEDTLS_X509_USE_C) +#define MBEDTLS_PK_PARSE_C +#endif + +#if defined(MBEDTLS_PK_PARSE_C) +#define MBEDTLS_PK_C +#endif + +/* mbedTLS modules */ +#if defined (CONFIG_NET_TLS_PEM_CERTIFICATE_FORMAT) && \ + defined(MBEDTLS_X509_CRT_PARSE_C) +#define MBEDTLS_PEM_PARSE_C +#define MBEDTLS_BASE64_C +#endif + +#if defined(MBEDTLS_AES_C) +#define MBEDTLS_CTR_DRBG_C +#endif + +#if defined(MBEDTLS_SHA256_C) || defined(MBEDTLS_SHA512_C) +#define MBEDTLS_ENTROPY_C +#endif + +/* For test certificates */ +#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_C) +#define MBEDTLS_CERTS_C +#endif + +#if defined(CONFIG_MBEDTLS_DEBUG) +#define MBEDTLS_ERROR_C +#define MBEDTLS_DEBUG_C +#define MBEDTLS_SSL_DEBUG_ALL +#define MBEDTLS_SSL_ALL_ALERT_MESSAGES +#endif + +#define MBEDTLS_SSL_MAX_CONTENT_LEN CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN + +#include "mbedtls/check_config.h" + +#endif /* MBEDTLS_CONFIG_H */ diff --git a/subsys/net/ip/Kconfig.tls b/subsys/net/ip/Kconfig.tls index 7683c90251ab5..f12cdd32adad3 100644 --- a/subsys/net/ip/Kconfig.tls +++ b/subsys/net/ip/Kconfig.tls @@ -21,22 +21,144 @@ config NET_DTLS default n depends on NET_UDP && MBEDTLS +if NET_TLS || NET_DTLS + +menu "Supported TLS version" + +config TLS_VERSION_1_0 + bool "Enable support for TLS 1.0" + depends on NET_TLS + select TLS_MAC_MD5_ENABLED + select TLS_MAC_SHA1_ENABLED + default n + +config TLS_VERSION_1_1 + bool "Enable support for TLS 1.1 (DTLS 1.0)" + select TLS_MAC_MD5_ENABLED + select TLS_MAC_SHA1_ENABLED + default n + +config TLS_VERSION_1_2 + bool "Enable support for TLS 1.2 (DTLS 1.2)" + default y + +endmenu + +menu "Ciphersuite configuration" + +comment "Supported key exchange modes" + +config TLS_KEY_EXCHANGE_PSK_ENABLED + bool "Enable the PSK based ciphersuite modes" + default n + +config TLS_KEY_EXCHANGE_DHE_PSK_ENABLED + bool "Enable the DHE-PSK based ciphersuite modes" + default n + +config TLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED + bool "Enable the ECDHE-PSK based ciphersuite modes" + default n + +config TLS_KEY_EXCHANGE_RSA_PSK_ENABLED + bool "Enable the RSA-PSK based ciphersuite modes" + default n + +config TLS_KEY_EXCHANGE_RSA_ENABLED + bool "Enable the RSA-only based ciphersuite modes" + default y + +config TLS_KEY_EXCHANGE_DHE_RSA_ENABLED + bool "Enable the DHE-RSA based ciphersuite modes" + default n + +config TLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED + bool "Enable the ECDHE-RSA based ciphersuite modes" + default n + +config TLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED + bool "Enable the ECDHE-ECDSA based ciphersuite modes" + default n + +config TLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED + bool "Enable the ECDH-ECDSA based ciphersuite modes" + default n + +config TLS_KEY_EXCHANGE_ECDH_RSA_ENABLED + bool "Enable the ECDH-RSA based ciphersuite modes" + default n + +config TLS_KEY_EXCHANGE_ECJPAKE_ENABLED + bool "Enable the ECJPAKE based ciphersuite modes" + default n + +comment "Supported cipher modes" + +config TLS_CIPHER_AES_ENABLED + bool "Enable the AES block cipher" + default y + +config TLS_CIPHER_CAMELLIA_ENABLED + bool "Enable the Camellia block cipher" + default n + +config TLS_CIPHER_DES_ENABLED + bool "Enable the DES block cipher" + default y + +config TLS_CIPHER_CCM_ENABLED + bool "Enable the Counter with CBC-MAC (CCM) mode for 128-bit block cipher" + default n + depends on TLS_CIPHER_AES_ENABLED || TLS_CIPHER_CAMELLIA_ENABLED + +config TLS_CIPHER_CBC_ENABLED + bool "Enable Cipher Block Chaining mode (CBC) for symmetric ciphers" + default y + +comment "Supported message authentication methods" + +config TLS_MAC_MD5_ENABLED + bool "Enable the MD5 hash algorithm" + default n + default y if TLS_VERSION_1_0 || TLS_VERSION_1_1 + +config TLS_MAC_SHA1_ENABLED + bool "Enable the SHA1 hash algorithm" + default y + +config TLS_MAC_SHA256_ENABLED + bool "Enable the SHA-224 and SHA-256 hash algorithms" + default n + default y if TLS_VERSION_1_2 + +config TLS_MAC_SHA512_ENABLED + bool "Enable the SHA-384 and SHA-512 hash algorithms" + default n + +endmenu + config NET_TLS_DEBUG bool "Enable TLS debug log" default n - depends on NET_TLS || NET_DTLS + +comment "TLS/DTLS credentials configuration" config NET_MAX_CREDENTIALS_NUMBER int "Maximum number of TLS/DTLS credentials" default 4 - depends on NET_TLS || NET_DTLS help "Maximum number of TLS/DTLS credentials that can be used simultaneously" +config NET_TLS_PEM_CERTIFICATE_FORMAT + bool "Enable support for PEM certificate format" + default n + help + By default only DER (binary) format of certificates is supported. Enable + this option to enable support for PEM format. + config NET_PRECONFIGURE_TLS_CREDENTIALS bool "Use preconfigured credentials for TLS/DTLS" default n - depends on NET_TLS || NET_DTLS help Use preconfigured credentials (CA Certificate, PSK) for TLS/DTLS sessions. @@ -47,4 +169,6 @@ config NET_TLS_CREDENTIALS_FILE help File containing default TLS/DTLS credentials to preconfigure. TODO Extend description. +endif + endmenu From 353d667d6232a1005cba10e56d0fbebc10c0165d Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Wed, 23 May 2018 12:36:49 +0200 Subject: [PATCH 17/24] net: samples: Add TLS support to http_get sample Add config file that enables to run http_get sample with TLS enabled and receive the webpage thorugh HTTPS. Signed-off-by: Robert Lubos --- samples/net/sockets/http_get/prj_tls.conf | 43 +++++++++++++++++++++ samples/net/sockets/http_get/src/http_get.c | 30 +++++++++++++- 2 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 samples/net/sockets/http_get/prj_tls.conf diff --git a/samples/net/sockets/http_get/prj_tls.conf b/samples/net/sockets/http_get/prj_tls.conf new file mode 100644 index 0000000000000..17f7b7cf0ed86 --- /dev/null +++ b/samples/net/sockets/http_get/prj_tls.conf @@ -0,0 +1,43 @@ +# General config +CONFIG_NEWLIB_LIBC=y +CONFIG_MAIN_STACK_SIZE=4096 + +# Networking config +CONFIG_NETWORKING=y +CONFIG_NET_IPV4=y +CONFIG_NET_IPV6=y +CONFIG_NET_TCP=y +CONFIG_NET_SOCKETS=y +CONFIG_NET_SOCKETS_POSIX_NAMES=y + +CONFIG_DNS_RESOLVER=y +CONFIG_DNS_SERVER_IP_ADDRESSES=y +CONFIG_DNS_SERVER1="192.0.2.2" + +# Network driver config +CONFIG_TEST_RANDOM_GENERATOR=y + +# Network address config +CONFIG_NET_APP_SETTINGS=y +CONFIG_NET_APP_NEED_IPV4=y +CONFIG_NET_APP_MY_IPV4_ADDR="192.0.2.1" +CONFIG_NET_APP_PEER_IPV4_ADDR="192.0.2.2" +CONFIG_NET_APP_MY_IPV4_GW="192.0.2.2" + +# Network debug config +CONFIG_NET_LOG=y +CONFIG_NET_LOG_GLOBAL=y +CONFIG_SYS_LOG_NET_LEVEL=2 +#CONFIG_NET_DEBUG_SOCKETS=y + +# TLS configuration +CONFIG_MBEDTLS=y +CONFIG_MBEDTLS_BUILTIN=y +CONFIG_MBEDTLS_ENABLE_HEAP=y +CONFIG_MBEDTLS_HEAP_SIZE=30000 +CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=4096 + +CONFIG_NET_SOCKETS_SOCKOPT_TLS=y +CONFIG_NET_TLS=y +CONFIG_NET_DTLS=y +CONFIG_NET_PRECONFIGURE_TLS_CREDENTIALS=y diff --git a/samples/net/sockets/http_get/src/http_get.c b/samples/net/sockets/http_get/src/http_get.c index 8785eb8a554a8..4714ce9244c0f 100644 --- a/samples/net/sockets/http_get/src/http_get.c +++ b/samples/net/sockets/http_get/src/http_get.c @@ -20,16 +20,24 @@ #include #include #include +#include #endif /* HTTP server to connect to */ #define HTTP_HOST "google.com" /* Port to connect to, as string */ +#if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) +#define HTTP_PORT "443" +#else #define HTTP_PORT "80" +#endif /* HTTP path to request */ #define HTTP_PATH "/" +#if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) +#define NET_TLS_DEFAULT_CA_CERTIFICATE_TAG 1 +#endif #define SSTRLEN(s) (sizeof(s) - 1) #define CHECK(r) { if (r == -1) { printf("Error: " #r "\n"); exit(1); } } @@ -77,6 +85,24 @@ int main(void) sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol); CHECK(sock); printf("sock = %d\n", sock); + +#if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) + int tls_opt = 1; + + CHECK(setsockopt(sock, SOL_TLS, TLS_ENABLE, &tls_opt, sizeof(tls_opt))); + +#if defined(CONFIG_NET_PRECONFIGURE_TLS_CREDENTIALS) + sec_tag_t sec_tag_opt[] = { +#if defined(MBEDTLS_X509_CRT_PARSE_C) + NET_TLS_DEFAULT_CA_CERTIFICATE_TAG, +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + }; + + CHECK(setsockopt(sock, SOL_TLS, TLS_SEC_TAG_LIST, + sec_tag_opt, sizeof(sec_tag_opt))); +#endif /* defined(CONFIG_NET_PRECONFIGURE_TLS_CREDENTIALS) */ +#endif /* defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) */ + CHECK(connect(sock, res->ai_addr, res->ai_addrlen)); CHECK(send(sock, REQUEST, SSTRLEN(REQUEST), 0)); @@ -95,9 +121,11 @@ int main(void) } response[len] = 0; - printf("%s\n", response); + printf("%s", response); } + printf("\n"); + (void)close(sock); return 0; From 0af76afb828646e391ce97c522c4736d791185cb Mon Sep 17 00:00:00 2001 From: Patrik Flykt Date: Fri, 1 Jun 2018 15:45:08 +0300 Subject: [PATCH 18/24] samples: net: Decrease memory consumption for test case Decrease memory size when running the setsockopt test so that targets with 42 kB of RAM can be used for testing initial implementation of TLS setsockopt. Signed-off-by: Patrik Flykt --- tests/net/socket/sockopt/prj.conf | 4 +++- tests/net/socket/sockopt/testcase.yaml | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/net/socket/sockopt/prj.conf b/tests/net/socket/sockopt/prj.conf index cded33cbd588b..c06b4d841e656 100644 --- a/tests/net/socket/sockopt/prj.conf +++ b/tests/net/socket/sockopt/prj.conf @@ -27,7 +27,9 @@ CONFIG_NET_APP_NEED_IPV6=y CONFIG_NET_APP_MY_IPV4_ADDR="192.0.2.1" CONFIG_NET_APP_MY_IPV6_ADDR="2001:db8::1" -CONFIG_MAIN_STACK_SIZE=2048 +CONFIG_NET_BUF_TX_COUNT=2 +CONFIG_NET_BUF_RX_COUNT=2 +CONFIG_MAIN_STACK_SIZE=4096 # Required: # Net pkt will be reused since src and dst address are the same. diff --git a/tests/net/socket/sockopt/testcase.yaml b/tests/net/socket/sockopt/testcase.yaml index ccff53bc72ad7..bd65a58daa951 100644 --- a/tests/net/socket/sockopt/testcase.yaml +++ b/tests/net/socket/sockopt/testcase.yaml @@ -1,4 +1,4 @@ tests: test: - min_ram: 32 + min_ram: 42 tags: net socket From d9828bfecd2d7f510c62b7bfda5e9ed772e67805 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Fri, 18 May 2018 09:17:52 +0200 Subject: [PATCH 19/24] net: tls: Provide RNG to mbedTLS that actually works Implement initial RNG. Signed-off-by: Robert Lubos --- subsys/net/ip/net_tls.c | 51 ++++++++++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 14 deletions(-) diff --git a/subsys/net/ip/net_tls.c b/subsys/net/ip/net_tls.c index a917de422b260..437ba7c216e97 100644 --- a/subsys/net/ip/net_tls.c +++ b/subsys/net/ip/net_tls.c @@ -62,6 +62,31 @@ static void my_debug(void *ctx, int level, } #endif /* defined(MBEDTLS_DEBUG_C) && defined(CONFIG_NET_TLS_DEBUG) */ +static int tls_entropy_func(void *ctx, unsigned char *buf, size_t len) +{ + /* TODO Provide a decent entropy source. */ + + ARG_UNUSED(ctx); + + size_t i = len / 4; + u32_t val; + + while (i--) { + val = sys_rand32_get(); + UNALIGNED_PUT(val, (u32_t *)buf); + buf += 4; + } + + i = len & 0x3; + val = sys_rand32_get(); + while (i--) { + *buf++ = val; + val >>= 8; + } + + return 0; +} + static struct net_tls_credential *unused_credential_get(void) { int i; @@ -170,16 +195,6 @@ static int tls_rx(void *ctx, unsigned char *buf, size_t len) return ret; } -static int tls_mbedtls_ctr_drbg_random(void *p_rng, unsigned char *output, - size_t output_len) -{ - static K_MUTEX_DEFINE(mutex); - - ARG_UNUSED(mutex); - - return 0; -} - static void tls_recv_cb(struct net_context *context, struct net_pkt *pkt, int status, void *user_data) { @@ -365,7 +380,8 @@ static int tls_mbedtls_set_credentials(struct net_context *context) void net_tls_init(void) { - int i; + static const unsigned char drbg_seed[] = "zephyr"; + int i, ret; for (i = 0; i < ARRAY_SIZE(credentials); i++) { credentials[i].type = NET_TLS_CREDENTIAL_UNUSED; @@ -387,6 +403,14 @@ void net_tls_init(void) #endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ #endif /* CONFIG_NET_PRECONFIGURE_TLS_CREDENTIALS */ + mbedtls_ctr_drbg_init(&tls_ctr_drbg); + + ret = mbedtls_ctr_drbg_seed(&tls_ctr_drbg, tls_entropy_func, NULL, + drbg_seed, sizeof(drbg_seed)); + if (ret != 0) { + mbedtls_ctr_drbg_free(&tls_ctr_drbg); + } + #if defined(MBEDTLS_DEBUG_C) && defined(CONFIG_NET_TLS_DEBUG) mbedtls_debug_set_threshold(CONFIG_MBEDTLS_DEBUG_LEVEL); #endif @@ -470,10 +494,9 @@ int net_tls_connect(struct net_context *context, bool listening) goto mbed_err_conf; } - mbedtls_ctr_drbg_init(&tls_ctr_drbg); - mbedtls_ssl_conf_rng(&context->mbedtls.config, - tls_mbedtls_ctr_drbg_random, &tls_ctr_drbg); + mbedtls_ctr_drbg_random, + &tls_ctr_drbg); err = tls_mbedtls_set_credentials(context); if (err) { From 87bef222818ad778dca78ff11feec3951923977b Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Mon, 28 May 2018 17:19:57 +0200 Subject: [PATCH 20/24] net: tls: Handle TCP window size in TLS module Manage TCP receive window on TLS layer instead of socket layer when TLS is used. The reason for this is that when TLS is used, TCP packets are consumed on the TLS layer instead of socket layer. Signed-off-by: Robert Lubos --- subsys/net/ip/net_tls.c | 9 +++++++++ subsys/net/lib/sockets/sockets.c | 12 ++++++++++++ 2 files changed, 21 insertions(+) diff --git a/subsys/net/ip/net_tls.c b/subsys/net/ip/net_tls.c index 437ba7c216e97..e5310c070b83c 100644 --- a/subsys/net/ip/net_tls.c +++ b/subsys/net/ip/net_tls.c @@ -187,6 +187,11 @@ static int tls_rx(void *ctx, unsigned char *buf, size_t len) if (context->mbedtls.rx_offset >= net_pkt_get_len(context->mbedtls.rx_pkt)) { + if (net_context_get_type(context) == SOCK_STREAM) { + net_context_update_recv_wnd( + context, + net_pkt_appdatalen(context->mbedtls.rx_pkt)); + } net_pkt_unref(context->mbedtls.rx_pkt); context->mbedtls.rx_pkt = NULL; context->mbedtls.rx_offset = 0; @@ -211,6 +216,10 @@ static void tls_recv_cb(struct net_context *context, struct net_pkt *pkt, k_fifo_put(&context->mbedtls.rx_fifo, pkt); + if (net_context_get_type(context) == SOCK_STREAM) { + net_context_update_recv_wnd(context, -net_pkt_appdatalen(pkt)); + } + /* Process it as application data only after handshake is over, * otherwise packet will be consumed by handshake. */ diff --git a/subsys/net/lib/sockets/sockets.c b/subsys/net/lib/sockets/sockets.c index 6f29beba345d9..f396432926169 100644 --- a/subsys/net/lib/sockets/sockets.c +++ b/subsys/net/lib/sockets/sockets.c @@ -161,7 +161,13 @@ static void zsock_received_cb(struct net_context *ctx, struct net_pkt *pkt, */ header_len = net_pkt_appdata(pkt) - pkt->frags->data; net_buf_pull(pkt->frags, header_len); +#if defined(CONFIG_NET_TLS) || defined(CONFIG_NET_DTLS) + if (!ctx->options.tls) { + net_context_update_recv_wnd(ctx, -net_pkt_appdatalen(pkt)); + } +#else net_context_update_recv_wnd(ctx, -net_pkt_appdatalen(pkt)); +#endif } k_fifo_put(&ctx->recv_q, pkt); @@ -445,7 +451,13 @@ static inline ssize_t zsock_recv_stream(struct net_context *ctx, } while (recv_len == 0); if (!(flags & ZSOCK_MSG_PEEK)) { +#if defined(CONFIG_NET_TLS) || defined(CONFIG_NET_DTLS) + if (!ctx->options.tls) { + net_context_update_recv_wnd(ctx, recv_len); + } +#else net_context_update_recv_wnd(ctx, recv_len); +#endif } return recv_len; From bf8d3f9d9a5f6b3c2806d412667d2e0cbdc9424b Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Tue, 29 May 2018 14:49:23 +0200 Subject: [PATCH 21/24] net: tls: Separate TLS context from net_context Currently TLS context data is hardcoded within net_context structure. This commit moves the TLS context to the separate structure that can be allocated and bound to the socket during socket creation only when secure protocol is going to be used. This way no memory is wasted for TLS data for sockets that are not going to use TLS. To achieve that, protocool types for TLS were introduced, so that socket can be explicitly destined for secure communication during it's creation. Signed-off-by: Robert Lubos --- include/net/net_context.h | 43 +---- include/net/net_ip.h | 3 + include/net/net_tls.h | 9 - samples/net/sockets/http_get/src/http_get.c | 13 +- subsys/net/ip/Kconfig.tls | 6 + subsys/net/ip/net_context.c | 25 ++- subsys/net/ip/net_tls.c | 189 ++++++++++++-------- subsys/net/ip/net_tls_internal.h | 76 ++++++++ subsys/net/lib/sockets/sockets.c | 4 +- 9 files changed, 233 insertions(+), 135 deletions(-) diff --git a/include/net/net_context.h b/include/net/net_context.h index cb24ea69fe79f..4839e546a7057 100644 --- a/include/net/net_context.h +++ b/include/net/net_context.h @@ -26,13 +26,6 @@ #include #include #include -#include - -#if defined(CONFIG_NET_TLS) || defined(CONFIG_NET_DTLS) -#if defined(CONFIG_MBEDTLS) -#include -#endif -#endif #ifdef __cplusplus extern "C" { @@ -191,6 +184,8 @@ struct net_tcp; struct net_conn_handle; +struct net_tls; + /** * Note that we do not store the actual source IP address in the context * because the address is already be set in the network interface struct. @@ -222,38 +217,9 @@ struct net_context { #if defined(CONFIG_NET_CONTEXT_PRIORITY) /** Priority of the network data sent via this net_context */ u8_t priority; -#endif -#if defined(CONFIG_NET_TLS) || defined(CONFIG_NET_DTLS) - /** Enable/disable TLS for the context */ - bool tls; - - /** Select which credentials to use with TLS. */ - struct sec_tag_list sec_tag_list; #endif } options; -#if defined(CONFIG_NET_TLS) || defined(CONFIG_NET_DTLS) -#if defined(CONFIG_MBEDTLS) - struct { - mbedtls_ssl_context ssl; - mbedtls_ssl_config config; -#if defined(MBEDTLS_X509_CRT_PARSE_C) - mbedtls_x509_crt ca_chain; -#endif - /** intermediated mbedTLS buffer to store decrypted content */ - char rx_ssl_buf[64]; - /** TLS packet fifo */ - struct k_fifo rx_fifo; - /** last data that came in via TLS */ - struct net_pkt *rx_pkt; - /** offset in the last data */ - int rx_offset; - } mbedtls; -#endif - /** Receive callback for TLS */ - net_context_recv_cb_t tls_cb; -#endif - /** Connection handle */ struct net_conn_handle *conn_handler; @@ -312,6 +278,11 @@ struct net_context { struct k_fifo accept_q; }; #endif /* CONFIG_NET_SOCKETS */ + +#if defined(CONFIG_NET_TLS) || defined(CONFIG_NET_DTLS) + /** TLS context information */ + struct net_tls *tls; +#endif /* CONFIG_NET_TLS || CONFIG_NET_DTLS */ }; static inline bool net_context_is_used(struct net_context *context) diff --git a/include/net/net_ip.h b/include/net/net_ip.h index fcbfbb369a8de..0a4168ab47adf 100644 --- a/include/net/net_ip.h +++ b/include/net/net_ip.h @@ -52,6 +52,9 @@ enum net_ip_protocol { IPPROTO_TCP = 6, IPPROTO_UDP = 17, IPPROTO_ICMPV6 = 58, + IPPROTO_TLS_1_0 = 256, + IPPROTO_TLS_1_1 = 257, + IPPROTO_TLS_1_2 = 258, }; /** Socket type */ diff --git a/include/net/net_tls.h b/include/net/net_tls.h index d40f29b952c09..e50b91f3bbd92 100644 --- a/include/net/net_tls.h +++ b/include/net/net_tls.h @@ -40,15 +40,6 @@ typedef int sec_tag_t; #if defined(CONFIG_NET_TLS) || defined(CONFIG_NET_DTLS) -/** A list of secure tags that context should use */ -struct sec_tag_list { - /** An array of secure tags referencing TLS credentials */ - sec_tag_t sec_tags[CONFIG_NET_MAX_CREDENTIALS_NUMBER]; - - /** Number of configured secure tags */ - int sec_tag_count; -}; - /** * @brief Add a TLS credential. * diff --git a/samples/net/sockets/http_get/src/http_get.c b/samples/net/sockets/http_get/src/http_get.c index 4714ce9244c0f..1a98af693e681 100644 --- a/samples/net/sockets/http_get/src/http_get.c +++ b/samples/net/sockets/http_get/src/http_get.c @@ -82,25 +82,22 @@ int main(void) dump_addrinfo(res); +#if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) + sock = socket(res->ai_family, res->ai_socktype, IPPROTO_TLS_1_2); +#else sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol); +#endif + CHECK(sock); printf("sock = %d\n", sock); #if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) - int tls_opt = 1; - - CHECK(setsockopt(sock, SOL_TLS, TLS_ENABLE, &tls_opt, sizeof(tls_opt))); - -#if defined(CONFIG_NET_PRECONFIGURE_TLS_CREDENTIALS) sec_tag_t sec_tag_opt[] = { -#if defined(MBEDTLS_X509_CRT_PARSE_C) NET_TLS_DEFAULT_CA_CERTIFICATE_TAG, -#endif /* MBEDTLS_X509_CRT_PARSE_C */ }; CHECK(setsockopt(sock, SOL_TLS, TLS_SEC_TAG_LIST, sec_tag_opt, sizeof(sec_tag_opt))); -#endif /* defined(CONFIG_NET_PRECONFIGURE_TLS_CREDENTIALS) */ #endif /* defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) */ CHECK(connect(sock, res->ai_addr, res->ai_addrlen)); diff --git a/subsys/net/ip/Kconfig.tls b/subsys/net/ip/Kconfig.tls index f12cdd32adad3..64e0ad8f265a8 100644 --- a/subsys/net/ip/Kconfig.tls +++ b/subsys/net/ip/Kconfig.tls @@ -141,6 +141,12 @@ config NET_TLS_DEBUG bool "Enable TLS debug log" default n +config NET_TLS_MAX_CONTEXT + int "Maximum number of TLS/DTLS contexts" + default 1 + help + "This variable specifies maximum number of simultaneous TLS/DLTS connections" + comment "TLS/DTLS credentials configuration" config NET_MAX_CREDENTIALS_NUMBER diff --git a/subsys/net/ip/net_context.c b/subsys/net/ip/net_context.c index 9f84dd7cda55d..84086b61ce323 100644 --- a/subsys/net/ip/net_context.c +++ b/subsys/net/ip/net_context.c @@ -117,6 +117,15 @@ int net_context_get(sa_family_t family, { int i, ret = -ENOENT; +#if defined(CONIFG_NET_TLS) || defined(CONFIG_NET_DTLS) + bool tls = false; + + if (ip_proto >= IPPROTO_TLS_1_0 && ip_proto <= IPPROTO_TLS_1_2) { + tls = true; + ip_proto = (type == SOCK_STREAM) ? IPPROTO_TCP : IPPROTO_UDP; + } +#endif + #if defined(CONFIG_NET_CONTEXT_CHECK) #if !defined(CONFIG_NET_IPV4) @@ -207,6 +216,14 @@ int net_context_get(sa_family_t family, } } +#if defined(CONIFG_NET_TLS) || defined(CONFIG_NET_DTLS) + if (tls) { + if (net_tls_enable(&contexts[i], true) < 0) { + break; + } + } +#endif + contexts[i].iface = 0; contexts[i].flags = 0; atomic_set(&contexts[i].refcount, 1); @@ -343,7 +360,7 @@ int net_context_put(struct net_context *context) } #if defined(CONFIG_NET_TLS) || defined(CONFIG_NET_DTLS) - if (context->options.tls) { + if (context->tls) { net_tls_enable(context, false); } #endif /* defined(CONFIG_NET_TLS) || defined(CONFIG_NET_DTLS) */ @@ -1012,7 +1029,7 @@ static int sendto(struct net_pkt *pkt, net_pkt_set_token(pkt, token); #if defined(CONFIG_NET_TLS) || defined(CONFIG_NET_DTLS) - if (context->options.tls) { + if (context->tls) { return net_tls_send(pkt); } #endif @@ -1262,7 +1279,7 @@ int net_context_recv(struct net_context *context, case IPPROTO_TCP: #if defined(CONFIG_NET_TLS) || defined(CONFIG_NET_DTLS) - if (context->options.tls) { + if (context->tls) { ret = net_tls_recv(context, cb, user_data); break; } @@ -1344,7 +1361,7 @@ static int get_context_tls_enable(struct net_context *context, return -EINVAL; } - *((int *)value) = context->options.tls; + *((int *)value) = (context->tls != 0); return 0; #else diff --git a/subsys/net/ip/net_tls.c b/subsys/net/ip/net_tls.c index e5310c070b83c..9e9ca3d0665d8 100644 --- a/subsys/net/ip/net_tls.c +++ b/subsys/net/ip/net_tls.c @@ -35,6 +35,9 @@ struct net_tls_credential { /* Global poll of credentials shared among TLS contexts. */ static struct net_tls_credential credentials[CONFIG_NET_MAX_CREDENTIALS_NUMBER]; +/* A poll of TLS contexts. */ +static struct net_tls tls_context[CONFIG_NET_TLS_MAX_CONTEXT]; + #if defined(MBEDTLS_DEBUG_C) && defined(CONFIG_NET_TLS_DEBUG) static void my_debug(void *ctx, int level, const char *file, int line, const char *str) @@ -164,37 +167,37 @@ static int tls_rx(void *ctx, unsigned char *buf, size_t len) int ret; u16_t len_left; - if (!context->mbedtls.rx_pkt) { - context->mbedtls.rx_pkt = - k_fifo_get(&context->mbedtls.rx_fifo, K_NO_WAIT); - if (context->mbedtls.rx_pkt) { - context->mbedtls.rx_offset = - net_pkt_appdata(context->mbedtls.rx_pkt) - - context->mbedtls.rx_pkt->frags->data; + if (!context->tls->rx_pkt) { + context->tls->rx_pkt = + k_fifo_get(&context->tls->rx_fifo, K_NO_WAIT); + if (context->tls->rx_pkt) { + context->tls->rx_offset = + net_pkt_appdata(context->tls->rx_pkt) - + context->tls->rx_pkt->frags->data; } else { return MBEDTLS_ERR_SSL_WANT_READ; } } - len_left = net_pkt_get_len(context->mbedtls.rx_pkt) - - context->mbedtls.rx_offset; - ret = net_frag_linearize(buf, len, context->mbedtls.rx_pkt, - context->mbedtls.rx_offset, + len_left = net_pkt_get_len(context->tls->rx_pkt) - + context->tls->rx_offset; + ret = net_frag_linearize(buf, len, context->tls->rx_pkt, + context->tls->rx_offset, MIN(len, len_left)); if (ret > 0) { - context->mbedtls.rx_offset += ret; + context->tls->rx_offset += ret; } - if (context->mbedtls.rx_offset >= - net_pkt_get_len(context->mbedtls.rx_pkt)) { + if (context->tls->rx_offset >= + net_pkt_get_len(context->tls->rx_pkt)) { if (net_context_get_type(context) == SOCK_STREAM) { net_context_update_recv_wnd( context, - net_pkt_appdatalen(context->mbedtls.rx_pkt)); + net_pkt_appdatalen(context->tls->rx_pkt)); } - net_pkt_unref(context->mbedtls.rx_pkt); - context->mbedtls.rx_pkt = NULL; - context->mbedtls.rx_offset = 0; + net_pkt_unref(context->tls->rx_pkt); + context->tls->rx_pkt = NULL; + context->tls->rx_offset = 0; } return ret; @@ -208,13 +211,13 @@ static void tls_recv_cb(struct net_context *context, struct net_pkt *pkt, if (!pkt) { /* Forward EOF */ - if (context->tls_cb) { - context->tls_cb(context, pkt, status, user_data); + if (context->tls->tls_cb) { + context->tls->tls_cb(context, pkt, status, user_data); } return; } - k_fifo_put(&context->mbedtls.rx_fifo, pkt); + k_fifo_put(&context->tls->rx_fifo, pkt); if (net_context_get_type(context) == SOCK_STREAM) { net_context_update_recv_wnd(context, -net_pkt_appdatalen(pkt)); @@ -223,7 +226,7 @@ static void tls_recv_cb(struct net_context *context, struct net_pkt *pkt, /* Process it as application data only after handshake is over, * otherwise packet will be consumed by handshake. */ - if (context->mbedtls.ssl.state == MBEDTLS_SSL_HANDSHAKE_OVER) { + if (context->tls->ssl.state == MBEDTLS_SSL_HANDSHAKE_OVER) { len = net_pkt_appdatalen(pkt); decrypted_pkt = net_pkt_clone(pkt, 0, NET_PKT_CLONE_HDR); @@ -246,9 +249,9 @@ static void tls_recv_cb(struct net_context *context, struct net_pkt *pkt, net_pkt_set_appdatalen(decrypted_pkt, 0); while (1) { - ret = mbedtls_ssl_read(&context->mbedtls.ssl, - context->mbedtls.rx_ssl_buf, - sizeof(context->mbedtls.rx_ssl_buf)); + ret = mbedtls_ssl_read(&context->tls->ssl, + context->tls->rx_ssl_buf, + sizeof(context->tls->rx_ssl_buf)); if (ret == 0 || ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE) { ret = 0; @@ -258,7 +261,7 @@ static void tls_recv_cb(struct net_context *context, struct net_pkt *pkt, if (ret > 0) { ret = net_pkt_append(decrypted_pkt, ret, - context->mbedtls.rx_ssl_buf, + context->tls->rx_ssl_buf, TIMEOUT_TLS_RX_MS); /* Update appdatalen */ net_pkt_set_appdatalen(decrypted_pkt, @@ -270,8 +273,9 @@ static void tls_recv_cb(struct net_context *context, struct net_pkt *pkt, break; } - if (ret >= 0 && context->tls_cb) { - context->tls_cb(context, decrypted_pkt, status, user_data); + if (ret >= 0 && context->tls->tls_cb) { + context->tls->tls_cb(context, decrypted_pkt, + status, user_data); } else { goto err; } @@ -287,7 +291,7 @@ static int tls_add_ca_certificate(struct net_context *context, struct net_tls_credential *ca_cert) { #if defined(MBEDTLS_X509_CRT_PARSE_C) - int err = mbedtls_x509_crt_parse(&context->mbedtls.ca_chain, + int err = mbedtls_x509_crt_parse(&context->tls->ca_chain, ca_cert->buf, ca_cert->len); if (err != 0) { return -EINVAL; @@ -300,13 +304,13 @@ static int tls_add_ca_certificate(struct net_context *context, static void tls_set_ca_chain(struct net_context *context) { #if defined(MBEDTLS_X509_CRT_PARSE_C) - mbedtls_ssl_conf_ca_chain(&context->mbedtls.config, - &context->mbedtls.ca_chain, NULL); + mbedtls_ssl_conf_ca_chain(&context->tls->config, + &context->tls->ca_chain, NULL); - mbedtls_ssl_conf_authmode(&context->mbedtls.config, + mbedtls_ssl_conf_authmode(&context->tls->config, MBEDTLS_SSL_VERIFY_REQUIRED); - mbedtls_ssl_conf_cert_profile(&context->mbedtls.config, + mbedtls_ssl_conf_cert_profile(&context->tls->config, &mbedtls_x509_crt_profile_default); #endif /* MBEDTLS_X509_CRT_PARSE_C */ } @@ -316,7 +320,7 @@ static int tls_set_psk(struct net_context *context, struct net_tls_credential *psk_id) { #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) - mbedtls_ssl_conf_psk(&context->mbedtls.config, + mbedtls_ssl_conf_psk(&context->tls->config, psk->buf, psk->len, (const unsigned char *)psk_id->buf, psk_id->len - 1); @@ -332,8 +336,8 @@ static int tls_mbedtls_set_credentials(struct net_context *context) int i, err; bool ca_cert_present = false; - for (i = 0; i < context->options.sec_tag_list.sec_tag_count; i++) { - tag = context->options.sec_tag_list.sec_tags[i]; + for (i = 0; i < context->tls->options.sec_tag_list.sec_tag_count; i++) { + tag = context->tls->options.sec_tag_list.sec_tags[i]; credential = NULL; while ((credential = credential_next_get(tag, credential)) @@ -425,15 +429,58 @@ void net_tls_init(void) #endif } +struct net_tls *net_tls_alloc(struct net_context *context) +{ + for (int i = 0; i < ARRAY_SIZE(tls_context); i++) { + if (!tls_context[i].context) { + tls_context[i].context = context; + + k_fifo_init(&tls_context[i].rx_fifo); + mbedtls_ssl_init(&tls_context[i].ssl); + mbedtls_ssl_config_init(&tls_context[i].config); + mbedtls_ssl_set_bio(&tls_context[i].ssl, context, + tls_tx, tls_rx, NULL); +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_x509_crt_init(&tls_context[i].ca_chain); +#endif +#if defined(MBEDTLS_DEBUG_C) && defined(CONFIG_NET_TLS_DEBUG) + mbedtls_ssl_conf_dbg(&tls_context[i].config, my_debug, NULL); +#endif + return &tls_context[i]; + } + } + + return NULL; +} + +int net_tls_release(struct net_tls *tls) +{ + if (!tls->context) { + NET_ERR("Deallocating unused TLS context"); + return -EBADF; + } + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_x509_crt_free(&tls->ca_chain); +#endif + mbedtls_ssl_set_bio(&tls->ssl, NULL, NULL, NULL, NULL); + mbedtls_ssl_config_free(&tls->config); + mbedtls_ssl_free(&tls->ssl); + + tls->context = NULL; + + return 0; +} + int net_tls_enable(struct net_context *context, bool enabled) { - int state; + int state, err; if (!context) { return -EINVAL; } - if (context->options.tls == enabled) { + if ((context->tls && enabled) || (!context->tls && !enabled)) { return 0; } @@ -442,30 +489,19 @@ int net_tls_enable(struct net_context *context, bool enabled) return -EBUSY; } - if (enabled) { - k_fifo_init(&context->mbedtls.rx_fifo); - mbedtls_ssl_init(&context->mbedtls.ssl); - mbedtls_ssl_config_init(&context->mbedtls.config); - mbedtls_ssl_set_bio(&context->mbedtls.ssl, context, - tls_tx, tls_rx, NULL); -#if defined(MBEDTLS_X509_CRT_PARSE_C) - mbedtls_x509_crt_init(&context->mbedtls.ca_chain); -#endif + if (!enabled) { + err = net_tls_release(context->tls); + if (err == 0) { + context->tls = NULL; + } -#if defined(MBEDTLS_DEBUG_C) && defined(CONFIG_NET_TLS_DEBUG) - mbedtls_ssl_conf_dbg(&context->mbedtls.config, my_debug, NULL); -#endif - } else { -#if defined(MBEDTLS_X509_CRT_PARSE_C) - mbedtls_x509_crt_free(&context->mbedtls.ca_chain); -#endif - mbedtls_ssl_set_bio(&context->mbedtls.ssl, - NULL, NULL, NULL, NULL); - mbedtls_ssl_config_free(&context->mbedtls.config); - mbedtls_ssl_free(&context->mbedtls.ssl); + return err; } - context->options.tls = enabled; + context->tls = net_tls_alloc(context); + if (!context->tls) { + return -ENOMEM; + } return 0; } @@ -479,7 +515,7 @@ int net_tls_connect(struct net_context *context, bool listening) return -EINVAL; } - if (!context->options.tls) { + if (!context->tls) { return 0; } @@ -496,14 +532,14 @@ int net_tls_connect(struct net_context *context, bool listening) MBEDTLS_SSL_TRANSPORT_STREAM : MBEDTLS_SSL_TRANSPORT_DATAGRAM; - err = mbedtls_ssl_config_defaults(&context->mbedtls.config, role, type, + err = mbedtls_ssl_config_defaults(&context->tls->config, role, type, MBEDTLS_SSL_PRESET_DEFAULT); if (err) { err = -ENOMEM; goto mbed_err_conf; } - mbedtls_ssl_conf_rng(&context->mbedtls.config, + mbedtls_ssl_conf_rng(&context->tls->config, mbedtls_ctr_drbg_random, &tls_ctr_drbg); @@ -512,14 +548,14 @@ int net_tls_connect(struct net_context *context, bool listening) goto mbed_err_conf; } - err = mbedtls_ssl_setup(&context->mbedtls.ssl, - &context->mbedtls.config); + err = mbedtls_ssl_setup(&context->tls->ssl, + &context->tls->config); if (err) { err = -EINVAL; goto mbed_err_conf; } - while ((err = mbedtls_ssl_handshake(&context->mbedtls.ssl)) != 0) { + while ((err = mbedtls_ssl_handshake(&context->tls->ssl)) != 0) { if (err != MBEDTLS_ERR_SSL_WANT_READ && err != MBEDTLS_ERR_SSL_WANT_WRITE) { err = -ENOPROTOOPT; @@ -531,8 +567,8 @@ int net_tls_connect(struct net_context *context, bool listening) mbed_err_handshake: mbed_err_conf: - mbedtls_ssl_session_reset(&context->mbedtls.ssl); - mbedtls_ssl_config_free(&context->mbedtls.config); + mbedtls_ssl_session_reset(&context->tls->ssl); + mbedtls_ssl_config_free(&context->tls->config); return err; } @@ -548,7 +584,7 @@ int net_tls_send(struct net_pkt *pkt) u16_t len = frag->len; while (ret < len) { - ret = mbedtls_ssl_write(&context->mbedtls.ssl, + ret = mbedtls_ssl_write(&context->tls->ssl, data, len); if (ret == len) { break; @@ -577,7 +613,7 @@ int net_tls_send(struct net_pkt *pkt) int net_tls_recv(struct net_context *context, net_context_recv_cb_t cb, void *user_data) { - context->tls_cb = cb; + context->tls->tls_cb = cb; #if defined(CONFIG_NET_TCP) context->tcp->recv_user_data = user_data; @@ -595,13 +631,13 @@ int net_tls_sec_tag_list_get(struct net_context *context, return -EINVAL; } - if (!context->options.tls) { + if (!context->tls) { return -EPERM; } - tags_to_copy = MIN(context->options.sec_tag_list.sec_tag_count, + tags_to_copy = MIN(context->tls->options.sec_tag_list.sec_tag_count, *sec_tag_cnt); - memcpy(sec_tags, context->options.sec_tag_list.sec_tags, + memcpy(sec_tags, context->tls->options.sec_tag_list.sec_tags, tags_to_copy * sizeof(sec_tag_t)); *sec_tag_cnt = tags_to_copy; @@ -618,7 +654,7 @@ int net_tls_sec_tag_list_set(struct net_context *context, return -EINVAL; } - if (!context->options.tls) { + if (!context->tls) { return -EPERM; } @@ -627,7 +663,8 @@ int net_tls_sec_tag_list_set(struct net_context *context, return -EPERM; } - if (sec_tag_cnt > ARRAY_SIZE(context->options.sec_tag_list.sec_tags)) { + if (sec_tag_cnt > + ARRAY_SIZE(context->tls->options.sec_tag_list.sec_tags)) { return -ENOMEM; } @@ -637,9 +674,9 @@ int net_tls_sec_tag_list_set(struct net_context *context, } } - memcpy(context->options.sec_tag_list.sec_tags, sec_tags, + memcpy(context->tls->options.sec_tag_list.sec_tags, sec_tags, sec_tag_cnt * sizeof(sec_tag_t)); - context->options.sec_tag_list.sec_tag_count = sec_tag_cnt; + context->tls->options.sec_tag_list.sec_tag_count = sec_tag_cnt; return 0; } diff --git a/subsys/net/ip/net_tls_internal.h b/subsys/net/ip/net_tls_internal.h index 3cdfef77fe101..bca55ce97c042 100644 --- a/subsys/net/ip/net_tls_internal.h +++ b/subsys/net/ip/net_tls_internal.h @@ -41,11 +41,73 @@ #endif /* CONFIG_MBEDTLS */ +/** A list of secure tags that context should use */ +struct sec_tag_list { + /** An array of secure tags referencing TLS credentials */ + sec_tag_t sec_tags[CONFIG_NET_MAX_CREDENTIALS_NUMBER]; + + /** Number of configured secure tags */ + int sec_tag_count; +}; + +/** TLS context information. */ +struct net_tls { + /** Network context back pointer. */ + struct net_context *context; + + /** TLS specific option values. */ + struct { + /** Select which credentials to use with TLS. */ + struct sec_tag_list sec_tag_list; + } options; + +#if defined(CONFIG_MBEDTLS) + mbedtls_ssl_context ssl; + mbedtls_ssl_config config; +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_x509_crt ca_chain; +#endif /* MBEDTLS_X509_CRT_PARSE_C */ +#endif /* CONFIG_MBEDTLS */ + + /** Intermediated buffer to store decrypted content. */ + char rx_ssl_buf[64]; + + /** Currently processed packet. */ + struct net_pkt *rx_pkt; + + /** Offset in the currently processed packet. */ + int rx_offset; + + /** TLS packet fifo. */ + struct k_fifo rx_fifo; + + /** Receive callback for TLS */ + net_context_recv_cb_t tls_cb; +}; /** * @brief Initialize TLS module. */ void net_tls_init(void); + +/** + * @brief Allocate TLS context. + * + * @param context A pointer to net_context structure that allocates TLS context. + * + * @return A pointer to allocated TLS context. NULL if no context was available. + */ +struct net_tls *net_tls_alloc(struct net_context *context); + +/** + * @brief Release TLS context. + * + * @param tls TLS context to deallocate. + * + * @return 0 if ok, <0 if error. + */ +int net_tls_release(struct net_tls *tls); + int net_tls_enable(struct net_context *context, bool enabled); int net_tls_connect(struct net_context *context, bool listening); int net_tls_send(struct net_pkt *pkt); @@ -61,6 +123,20 @@ static inline void net_tls_init(void) { } +static inline struct net_tls *net_tls_alloc(struct net_context *context) +{ + ARG_UNUSED(context); + + return NULL; +} + +static inline int net_tls_release(struct net_tls *tls) +{ + ARG_UNUSED(tls); + + return 0; +} + static inline int net_tls_enable(struct net_context *context, bool enabled) { ARG_UNUSED(context); diff --git a/subsys/net/lib/sockets/sockets.c b/subsys/net/lib/sockets/sockets.c index f396432926169..6d3ae2db42bc2 100644 --- a/subsys/net/lib/sockets/sockets.c +++ b/subsys/net/lib/sockets/sockets.c @@ -162,7 +162,7 @@ static void zsock_received_cb(struct net_context *ctx, struct net_pkt *pkt, header_len = net_pkt_appdata(pkt) - pkt->frags->data; net_buf_pull(pkt->frags, header_len); #if defined(CONFIG_NET_TLS) || defined(CONFIG_NET_DTLS) - if (!ctx->options.tls) { + if (!ctx->tls) { net_context_update_recv_wnd(ctx, -net_pkt_appdatalen(pkt)); } #else @@ -452,7 +452,7 @@ static inline ssize_t zsock_recv_stream(struct net_context *ctx, if (!(flags & ZSOCK_MSG_PEEK)) { #if defined(CONFIG_NET_TLS) || defined(CONFIG_NET_DTLS) - if (!ctx->options.tls) { + if (!ctx->tls) { net_context_update_recv_wnd(ctx, recv_len); } #else From 4474b2ec7b7772053a7a56d1aa0f07b54d260422 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Mon, 28 May 2018 11:07:14 +0200 Subject: [PATCH 22/24] net: tls: Move default certificate to the example Instead of having a single default certificates file in TLS module, provide per-example default certificates. It makes more sense when certificates are tailored for speicific server and use case. Signed-off-by: Robert Lubos --- samples/net/sockets/http_get/CMakeLists.txt | 2 ++ samples/net/sockets/http_get/src/http_get.c | 7 ++----- .../net/sockets/http_get/src/tls_default_credentials.h | 6 +++--- subsys/net/ip/Kconfig.tls | 2 +- 4 files changed, 8 insertions(+), 9 deletions(-) rename subsys/net/ip/net_tls_default_credentials.h => samples/net/sockets/http_get/src/tls_default_credentials.h (98%) diff --git a/samples/net/sockets/http_get/CMakeLists.txt b/samples/net/sockets/http_get/CMakeLists.txt index e6bf10afba6f5..3b98918c30322 100644 --- a/samples/net/sockets/http_get/CMakeLists.txt +++ b/samples/net/sockets/http_get/CMakeLists.txt @@ -4,4 +4,6 @@ project(NONE) FILE(GLOB app_sources src/*.c) target_sources(app PRIVATE ${app_sources}) +zephyr_include_directories(src) + include($ENV{ZEPHYR_BASE}/samples/net/common/common.cmake) diff --git a/samples/net/sockets/http_get/src/http_get.c b/samples/net/sockets/http_get/src/http_get.c index 1a98af693e681..06aa28180e015 100644 --- a/samples/net/sockets/http_get/src/http_get.c +++ b/samples/net/sockets/http_get/src/http_get.c @@ -22,6 +22,8 @@ #include #include +#include "tls_default_credentials.h" + #endif /* HTTP server to connect to */ @@ -35,10 +37,6 @@ /* HTTP path to request */ #define HTTP_PATH "/" -#if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) -#define NET_TLS_DEFAULT_CA_CERTIFICATE_TAG 1 -#endif - #define SSTRLEN(s) (sizeof(s) - 1) #define CHECK(r) { if (r == -1) { printf("Error: " #r "\n"); exit(1); } } @@ -95,7 +93,6 @@ int main(void) sec_tag_t sec_tag_opt[] = { NET_TLS_DEFAULT_CA_CERTIFICATE_TAG, }; - CHECK(setsockopt(sock, SOL_TLS, TLS_SEC_TAG_LIST, sec_tag_opt, sizeof(sec_tag_opt))); #endif /* defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) */ diff --git a/subsys/net/ip/net_tls_default_credentials.h b/samples/net/sockets/http_get/src/tls_default_credentials.h similarity index 98% rename from subsys/net/ip/net_tls_default_credentials.h rename to samples/net/sockets/http_get/src/tls_default_credentials.h index 8c9896ae13e63..9ae064ac4f9d8 100644 --- a/subsys/net/ip/net_tls_default_credentials.h +++ b/samples/net/sockets/http_get/src/tls_default_credentials.h @@ -4,8 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -#ifndef __NET_TLS_DEFAULT_CREDENTIALS_H__ -#define __NET_TLS_DEFAULT_CREDENTIALS_H__ +#ifndef __TLS_DEFAULT_CREDENTIALS_H__ +#define __TLS_DEFAULT_CREDENTIALS_H__ #define NET_TLS_DEFAULT_CA_CERTIFICATE_TAG 1 #define NET_TLS_DEFAULT_PSK_TAG 2 @@ -151,4 +151,4 @@ static const unsigned char client_psk[] = { static const char client_psk_id[] = "Client_identity"; #endif -#endif +#endif /* __TLS_DEFAULT_CREDENTIALS_H__ */ diff --git a/subsys/net/ip/Kconfig.tls b/subsys/net/ip/Kconfig.tls index 64e0ad8f265a8..b1726ede18c79 100644 --- a/subsys/net/ip/Kconfig.tls +++ b/subsys/net/ip/Kconfig.tls @@ -170,7 +170,7 @@ config NET_PRECONFIGURE_TLS_CREDENTIALS config NET_TLS_CREDENTIALS_FILE string "TLS/DTLS credentials to preconfigure" - default "net_tls_default_credentials.h" + default "tls_default_credentials.h" depends on NET_PRECONFIGURE_TLS_CREDENTIALS help File containing default TLS/DTLS credentials to preconfigure. TODO Extend description. From cf322ec3a51055439f862d652e534b6b55c94110 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Wed, 23 May 2018 15:19:18 +0200 Subject: [PATCH 23/24] net: samples: Add TLS support to big_http_download Add a config file that enables TLS support in big_http_download. Users can use either default config to use non-secured connection or prj_tls.conf to use secured connection. Signed-off-by: Robert Lubos --- .../sockets/big_http_download/CMakeLists.txt | 2 + .../sockets/big_http_download/prj_tls.conf | 48 +++++ .../big_http_download/src/big_http_download.c | 54 +++++- .../src/tls_default_credentials.h | 181 ++++++++++++++++++ 4 files changed, 277 insertions(+), 8 deletions(-) create mode 100644 samples/net/sockets/big_http_download/prj_tls.conf create mode 100644 samples/net/sockets/big_http_download/src/tls_default_credentials.h diff --git a/samples/net/sockets/big_http_download/CMakeLists.txt b/samples/net/sockets/big_http_download/CMakeLists.txt index e6bf10afba6f5..3b98918c30322 100644 --- a/samples/net/sockets/big_http_download/CMakeLists.txt +++ b/samples/net/sockets/big_http_download/CMakeLists.txt @@ -4,4 +4,6 @@ project(NONE) FILE(GLOB app_sources src/*.c) target_sources(app PRIVATE ${app_sources}) +zephyr_include_directories(src) + include($ENV{ZEPHYR_BASE}/samples/net/common/common.cmake) diff --git a/samples/net/sockets/big_http_download/prj_tls.conf b/samples/net/sockets/big_http_download/prj_tls.conf new file mode 100644 index 0000000000000..15d8592e86764 --- /dev/null +++ b/samples/net/sockets/big_http_download/prj_tls.conf @@ -0,0 +1,48 @@ +# General config +CONFIG_NEWLIB_LIBC=y +CONFIG_MAIN_STACK_SIZE=4096 +CONFIG_NET_BUF_RX_COUNT=160 + +# Networking config +CONFIG_NETWORKING=y +CONFIG_NET_IPV4=y +CONFIG_NET_IPV6=y +CONFIG_NET_TCP=y +CONFIG_NET_SOCKETS=y +CONFIG_NET_SOCKETS_POSIX_NAMES=y + +CONFIG_DNS_RESOLVER=y +CONFIG_DNS_SERVER_IP_ADDRESSES=y +CONFIG_DNS_SERVER1="192.0.2.2" + +# Network driver config +CONFIG_TEST_RANDOM_GENERATOR=y + +# Network address config +CONFIG_NET_APP_SETTINGS=y +CONFIG_NET_APP_NEED_IPV4=y +CONFIG_NET_APP_MY_IPV4_ADDR="192.0.2.1" +CONFIG_NET_APP_PEER_IPV4_ADDR="192.0.2.2" +CONFIG_NET_APP_MY_IPV4_GW="192.0.2.2" +# DHCP configuration. Until DHCP address is assigned, +# static configuration above is used instead. +CONFIG_NET_DHCPV4=y + +# Network debug config +CONFIG_NET_LOG=y +CONFIG_NET_LOG_GLOBAL=y +CONFIG_SYS_LOG_NET_LEVEL=2 +#CONFIG_NET_DEBUG_SOCKETS=y +#CONFIG_NET_SHELL=y + +# TLS configuration +CONFIG_MBEDTLS=y +CONFIG_MBEDTLS_BUILTIN=y +CONFIG_MBEDTLS_ENABLE_HEAP=y +CONFIG_MBEDTLS_HEAP_SIZE=60000 +CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=16384 + +CONFIG_NET_SOCKETS_SOCKOPT_TLS=y +CONFIG_NET_TLS=y +CONFIG_NET_DTLS=y +CONFIG_NET_PRECONFIGURE_TLS_CREDENTIALS=y diff --git a/samples/net/sockets/big_http_download/src/big_http_download.c b/samples/net/sockets/big_http_download/src/big_http_download.c index ccd4a9da4d567..dff7a25414269 100644 --- a/samples/net/sockets/big_http_download/src/big_http_download.c +++ b/samples/net/sockets/big_http_download/src/big_http_download.c @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include #include @@ -23,24 +24,42 @@ #include #include #include +#include +#include "tls_default_credentials.h" + #define sleep(x) k_sleep(x * 1000) #endif /* This URL is parsed in-place, so buffer must be non-const. */ static char download_url[] = +#if !defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) "http://archive.ubuntu.com/ubuntu/dists/xenial/main/installer-amd64/current/images/hd-media/vmlinuz"; +#else + "https://www.7-zip.org/a/7z1805.exe"; +#endif /* !defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) */ /* Quick testing. */ /* "http://google.com/foo";*/ /* print("".join(["\\x%02x" % x for x in list(binascii.unhexlify("hash"))])) */ -static uint8_t download_hash[32] = "\x33\x7c\x37\xd7\xec\x00\x34\x84\x14\x22\x4b\xaa\x6b\xdb\x2d\x43\xf2\xa3\x4e\xf5\x67\x6b\xaf\xcd\xca\xd9\x16\xf1\x48\xb5\xb3\x17"; +static uint8_t download_hash[32] = +#if !defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) +"\x33\x7c\x37\xd7\xec\x00\x34\x84\x14\x22\x4b\xaa\x6b\xdb\x2d\x43\xf2\xa3\x4e\xf5\x67\x6b\xaf\xcd\xca\xd9\x16\xf1\x48\xb5\xb3\x17"; +#else +"\x65\xdb\x32\xfb\x76\x31\x6f\x07\x05\xd0\x82\xa4\x3e\x6a\x6a\xef\x6a\xca\xdf\x56\xcf\xd9\xcd\x52\xe1\x46\xc5\xf2\xd0\x0a\xb6\x42"; +#endif /* !defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) */ #define SSTRLEN(s) (sizeof(s) - 1) #define CHECK(r) { if (r == -1) { printf("Error: " #r "\n"); exit(1); } } +#if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) +const bool tls_enabled = true; +#else +const bool tls_enabled; +#endif + const char *host; -const char *port = "80"; +const char *port; const char *uri_path = ""; static char response[1024]; static char response_hash[32]; @@ -119,9 +138,23 @@ void download(struct addrinfo *ai) cur_bytes = 0; +#if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) + sock = socket(ai->ai_family, ai->ai_socktype, IPPROTO_TLS_1_2); +#else sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); +#endif CHECK(sock); printf("sock = %d\n", sock); + +#if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) + sec_tag_t sec_tag_opt[] = { + NET_TLS_DEFAULT_CA_CERTIFICATE_TAG, + }; + + CHECK(setsockopt(sock, SOL_TLS, TLS_SEC_TAG_LIST, + sec_tag_opt, sizeof(sec_tag_opt))); +#endif /* defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) */ + CHECK(connect(sock, ai->ai_addr, ai->ai_addrlen)); sendall(sock, "GET /", SSTRLEN("GET /")); sendall(sock, uri_path, strlen(uri_path)); @@ -186,12 +219,17 @@ int main(void) setbuf(stdout, NULL); - if (strncmp(download_url, "http://", SSTRLEN("http://")) != 0) { - fatal("Only http: URLs are supported"); + if (strncmp(download_url, "http://", SSTRLEN("http://")) == 0) { + port = "80"; + p = download_url + SSTRLEN("http://"); + } else if (strncmp(download_url, "https://", + SSTRLEN("https://")) == 0) { + port = "443"; + p = download_url + SSTRLEN("https://"); + } else { + fatal("Only http: and https: URLs are supported"); } - p = download_url + SSTRLEN("http://"); - /* Parse host part */ host = p; while (*p && *p != ':' && *p != '/') { @@ -214,8 +252,8 @@ int main(void) uri_path = p; } - printf("Preparing HTTP GET request for http://%s:%s/%s\n", - host, port, uri_path); + printf("Preparing HTTP GET request for http%s://%s:%s/%s\n", + (tls_enabled ? "s" : ""), host, port, uri_path); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; diff --git a/samples/net/sockets/big_http_download/src/tls_default_credentials.h b/samples/net/sockets/big_http_download/src/tls_default_credentials.h new file mode 100644 index 0000000000000..f80586abf24e1 --- /dev/null +++ b/samples/net/sockets/big_http_download/src/tls_default_credentials.h @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2018 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __TLS_DEFAULT_CREDENTIALS_H__ +#define __TLS_DEFAULT_CREDENTIALS_H__ + +#define NET_TLS_DEFAULT_CA_CERTIFICATE_TAG 1 +#define NET_TLS_DEFAULT_PSK_TAG 2 + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + +/* By default only certificates in DER format are supported. If you want to use + * certificate in PEM format, you can enable support for it in Kconfig. + */ + +/* Let’s Encrypt Authority X3 */ +static const unsigned char ca_certificate[] = { + 0x30, 0x82, 0x04, 0x92, 0x30, 0x82, 0x03, 0x7a, + 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x0a, + 0x01, 0x41, 0x42, 0x00, 0x00, 0x01, 0x53, 0x85, + 0x73, 0x6a, 0x0b, 0x85, 0xec, 0xa7, 0x08, 0x30, + 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x3f, + 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, + 0x0a, 0x13, 0x1b, 0x44, 0x69, 0x67, 0x69, 0x74, + 0x61, 0x6c, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x20, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x20, 0x43, 0x6f, 0x2e, 0x31, 0x17, + 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x0e, 0x44, 0x53, 0x54, 0x20, 0x52, 0x6f, 0x6f, + 0x74, 0x20, 0x43, 0x41, 0x20, 0x58, 0x33, 0x30, + 0x1e, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x33, 0x31, + 0x37, 0x31, 0x36, 0x34, 0x30, 0x34, 0x36, 0x5a, + 0x17, 0x0d, 0x32, 0x31, 0x30, 0x33, 0x31, 0x37, + 0x31, 0x36, 0x34, 0x30, 0x34, 0x36, 0x5a, 0x30, + 0x4a, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, + 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, + 0x0d, 0x4c, 0x65, 0x74, 0x27, 0x73, 0x20, 0x45, + 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x31, 0x23, + 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x1a, 0x4c, 0x65, 0x74, 0x27, 0x73, 0x20, 0x45, + 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, + 0x20, 0x58, 0x33, 0x30, 0x82, 0x01, 0x22, 0x30, + 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, + 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, + 0x82, 0x01, 0x01, 0x00, 0x9c, 0xd3, 0x0c, 0xf0, + 0x5a, 0xe5, 0x2e, 0x47, 0xb7, 0x72, 0x5d, 0x37, + 0x83, 0xb3, 0x68, 0x63, 0x30, 0xea, 0xd7, 0x35, + 0x26, 0x19, 0x25, 0xe1, 0xbd, 0xbe, 0x35, 0xf1, + 0x70, 0x92, 0x2f, 0xb7, 0xb8, 0x4b, 0x41, 0x05, + 0xab, 0xa9, 0x9e, 0x35, 0x08, 0x58, 0xec, 0xb1, + 0x2a, 0xc4, 0x68, 0x87, 0x0b, 0xa3, 0xe3, 0x75, + 0xe4, 0xe6, 0xf3, 0xa7, 0x62, 0x71, 0xba, 0x79, + 0x81, 0x60, 0x1f, 0xd7, 0x91, 0x9a, 0x9f, 0xf3, + 0xd0, 0x78, 0x67, 0x71, 0xc8, 0x69, 0x0e, 0x95, + 0x91, 0xcf, 0xfe, 0xe6, 0x99, 0xe9, 0x60, 0x3c, + 0x48, 0xcc, 0x7e, 0xca, 0x4d, 0x77, 0x12, 0x24, + 0x9d, 0x47, 0x1b, 0x5a, 0xeb, 0xb9, 0xec, 0x1e, + 0x37, 0x00, 0x1c, 0x9c, 0xac, 0x7b, 0xa7, 0x05, + 0xea, 0xce, 0x4a, 0xeb, 0xbd, 0x41, 0xe5, 0x36, + 0x98, 0xb9, 0xcb, 0xfd, 0x6d, 0x3c, 0x96, 0x68, + 0xdf, 0x23, 0x2a, 0x42, 0x90, 0x0c, 0x86, 0x74, + 0x67, 0xc8, 0x7f, 0xa5, 0x9a, 0xb8, 0x52, 0x61, + 0x14, 0x13, 0x3f, 0x65, 0xe9, 0x82, 0x87, 0xcb, + 0xdb, 0xfa, 0x0e, 0x56, 0xf6, 0x86, 0x89, 0xf3, + 0x85, 0x3f, 0x97, 0x86, 0xaf, 0xb0, 0xdc, 0x1a, + 0xef, 0x6b, 0x0d, 0x95, 0x16, 0x7d, 0xc4, 0x2b, + 0xa0, 0x65, 0xb2, 0x99, 0x04, 0x36, 0x75, 0x80, + 0x6b, 0xac, 0x4a, 0xf3, 0x1b, 0x90, 0x49, 0x78, + 0x2f, 0xa2, 0x96, 0x4f, 0x2a, 0x20, 0x25, 0x29, + 0x04, 0xc6, 0x74, 0xc0, 0xd0, 0x31, 0xcd, 0x8f, + 0x31, 0x38, 0x95, 0x16, 0xba, 0xa8, 0x33, 0xb8, + 0x43, 0xf1, 0xb1, 0x1f, 0xc3, 0x30, 0x7f, 0xa2, + 0x79, 0x31, 0x13, 0x3d, 0x2d, 0x36, 0xf8, 0xe3, + 0xfc, 0xf2, 0x33, 0x6a, 0xb9, 0x39, 0x31, 0xc5, + 0xaf, 0xc4, 0x8d, 0x0d, 0x1d, 0x64, 0x16, 0x33, + 0xaa, 0xfa, 0x84, 0x29, 0xb6, 0xd4, 0x0b, 0xc0, + 0xd8, 0x7d, 0xc3, 0x93, 0x02, 0x03, 0x01, 0x00, + 0x01, 0xa3, 0x82, 0x01, 0x7d, 0x30, 0x82, 0x01, + 0x79, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, + 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, + 0x01, 0xff, 0x02, 0x01, 0x00, 0x30, 0x0e, 0x06, + 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, + 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x7f, 0x06, + 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, + 0x01, 0x04, 0x73, 0x30, 0x71, 0x30, 0x32, 0x06, + 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, + 0x01, 0x86, 0x26, 0x68, 0x74, 0x74, 0x70, 0x3a, + 0x2f, 0x2f, 0x69, 0x73, 0x72, 0x67, 0x2e, 0x74, + 0x72, 0x75, 0x73, 0x74, 0x69, 0x64, 0x2e, 0x6f, + 0x63, 0x73, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, + 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63, 0x6f, + 0x6d, 0x30, 0x3b, 0x06, 0x08, 0x2b, 0x06, 0x01, + 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x2f, 0x68, + 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x61, 0x70, + 0x70, 0x73, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, + 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x72, 0x6f, 0x6f, 0x74, 0x73, 0x2f, 0x64, + 0x73, 0x74, 0x72, 0x6f, 0x6f, 0x74, 0x63, 0x61, + 0x78, 0x33, 0x2e, 0x70, 0x37, 0x63, 0x30, 0x1f, + 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, + 0x16, 0x80, 0x14, 0xc4, 0xa7, 0xb1, 0xa4, 0x7b, + 0x2c, 0x71, 0xfa, 0xdb, 0xe1, 0x4b, 0x90, 0x75, + 0xff, 0xc4, 0x15, 0x60, 0x85, 0x89, 0x10, 0x30, + 0x54, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x4d, + 0x30, 0x4b, 0x30, 0x08, 0x06, 0x06, 0x67, 0x81, + 0x0c, 0x01, 0x02, 0x01, 0x30, 0x3f, 0x06, 0x0b, + 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xdf, 0x13, + 0x01, 0x01, 0x01, 0x30, 0x30, 0x30, 0x2e, 0x06, + 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, + 0x01, 0x16, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, + 0x2f, 0x2f, 0x63, 0x70, 0x73, 0x2e, 0x72, 0x6f, + 0x6f, 0x74, 0x2d, 0x78, 0x31, 0x2e, 0x6c, 0x65, + 0x74, 0x73, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, + 0x74, 0x2e, 0x6f, 0x72, 0x67, 0x30, 0x3c, 0x06, + 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x35, 0x30, 0x33, + 0x30, 0x31, 0xa0, 0x2f, 0xa0, 0x2d, 0x86, 0x2b, + 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, + 0x72, 0x6c, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, + 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x44, 0x53, 0x54, 0x52, 0x4f, 0x4f, 0x54, + 0x43, 0x41, 0x58, 0x33, 0x43, 0x52, 0x4c, 0x2e, + 0x63, 0x72, 0x6c, 0x30, 0x1d, 0x06, 0x03, 0x55, + 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xa8, 0x4a, + 0x6a, 0x63, 0x04, 0x7d, 0xdd, 0xba, 0xe6, 0xd1, + 0x39, 0xb7, 0xa6, 0x45, 0x65, 0xef, 0xf3, 0xa8, + 0xec, 0xa1, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, + 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0xdd, 0x33, + 0xd7, 0x11, 0xf3, 0x63, 0x58, 0x38, 0xdd, 0x18, + 0x15, 0xfb, 0x09, 0x55, 0xbe, 0x76, 0x56, 0xb9, + 0x70, 0x48, 0xa5, 0x69, 0x47, 0x27, 0x7b, 0xc2, + 0x24, 0x08, 0x92, 0xf1, 0x5a, 0x1f, 0x4a, 0x12, + 0x29, 0x37, 0x24, 0x74, 0x51, 0x1c, 0x62, 0x68, + 0xb8, 0xcd, 0x95, 0x70, 0x67, 0xe5, 0xf7, 0xa4, + 0xbc, 0x4e, 0x28, 0x51, 0xcd, 0x9b, 0xe8, 0xae, + 0x87, 0x9d, 0xea, 0xd8, 0xba, 0x5a, 0xa1, 0x01, + 0x9a, 0xdc, 0xf0, 0xdd, 0x6a, 0x1d, 0x6a, 0xd8, + 0x3e, 0x57, 0x23, 0x9e, 0xa6, 0x1e, 0x04, 0x62, + 0x9a, 0xff, 0xd7, 0x05, 0xca, 0xb7, 0x1f, 0x3f, + 0xc0, 0x0a, 0x48, 0xbc, 0x94, 0xb0, 0xb6, 0x65, + 0x62, 0xe0, 0xc1, 0x54, 0xe5, 0xa3, 0x2a, 0xad, + 0x20, 0xc4, 0xe9, 0xe6, 0xbb, 0xdc, 0xc8, 0xf6, + 0xb5, 0xc3, 0x32, 0xa3, 0x98, 0xcc, 0x77, 0xa8, + 0xe6, 0x79, 0x65, 0x07, 0x2b, 0xcb, 0x28, 0xfe, + 0x3a, 0x16, 0x52, 0x81, 0xce, 0x52, 0x0c, 0x2e, + 0x5f, 0x83, 0xe8, 0xd5, 0x06, 0x33, 0xfb, 0x77, + 0x6c, 0xce, 0x40, 0xea, 0x32, 0x9e, 0x1f, 0x92, + 0x5c, 0x41, 0xc1, 0x74, 0x6c, 0x5b, 0x5d, 0x0a, + 0x5f, 0x33, 0xcc, 0x4d, 0x9f, 0xac, 0x38, 0xf0, + 0x2f, 0x7b, 0x2c, 0x62, 0x9d, 0xd9, 0xa3, 0x91, + 0x6f, 0x25, 0x1b, 0x2f, 0x90, 0xb1, 0x19, 0x46, + 0x3d, 0xf6, 0x7e, 0x1b, 0xa6, 0x7a, 0x87, 0xb9, + 0xa3, 0x7a, 0x6d, 0x18, 0xfa, 0x25, 0xa5, 0x91, + 0x87, 0x15, 0xe0, 0xf2, 0x16, 0x2f, 0x58, 0xb0, + 0x06, 0x2f, 0x2c, 0x68, 0x26, 0xc6, 0x4b, 0x98, + 0xcd, 0xda, 0x9f, 0x0c, 0xf9, 0x7f, 0x90, 0xed, + 0x43, 0x4a, 0x12, 0x44, 0x4e, 0x6f, 0x73, 0x7a, + 0x28, 0xea, 0xa4, 0xaa, 0x6e, 0x7b, 0x4c, 0x7d, + 0x87, 0xdd, 0xe0, 0xc9, 0x02, 0x44, 0xa7, 0x87, + 0xaf, 0xc3, 0x34, 0x5b, 0xb4, 0x42, +}; + +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +static const unsigned char client_psk[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f +}; + +static const char client_psk_id[] = "Client_identity"; +#endif + +#endif /* TLS_DEFAULT_CA_CERTIFICATE_TAG */ From 18e80dac32cb90a6c32669d2a3583dd209f0af60 Mon Sep 17 00:00:00 2001 From: Patrik Flykt Date: Mon, 18 Jun 2018 12:44:36 +0300 Subject: [PATCH 24/24] net: ip: Mark socket TLS support experimental Socket TLS support is currently experimental. Signed-off-by: Patrik Flykt --- subsys/net/ip/Kconfig.tls | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subsys/net/ip/Kconfig.tls b/subsys/net/ip/Kconfig.tls index b1726ede18c79..c3d9a24fc0353 100644 --- a/subsys/net/ip/Kconfig.tls +++ b/subsys/net/ip/Kconfig.tls @@ -10,14 +10,14 @@ menu "TLS options" config NET_TLS - bool "TCP TLS support" + bool "TCP TLS support [EXPERIMENTAL]" default n depends on NET_TCP && MBEDTLS help Enable TLS support for TCP connections. TLS is implemented by mbedTLS. config NET_DTLS - bool "UDP DTLS placeholder" + bool "UDP DTLS placeholder [EXPERIMENTAL]" default n depends on NET_UDP && MBEDTLS