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/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/include/net/net_context.h b/include/net/net_context.h index 63a622936fa73..4839e546a7057 100644 --- a/include/net/net_context.h +++ b/include/net/net_context.h @@ -184,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. @@ -276,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) @@ -778,7 +785,9 @@ int net_context_update_recv_wnd(struct net_context *context, s32_t delta); enum net_context_option { - NET_OPT_PRIORITY = 1, + NET_OPT_PRIORITY = 1, + NET_OPT_TLS_ENABLE = 2, + NET_OPT_TLS_SEC_TAG_LIST = 3, }; /** 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_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/include/net/net_tls.h b/include/net/net_tls.h new file mode 100644 index 0000000000000..e50b91f3bbd92 --- /dev/null +++ b/include/net/net_tls.h @@ -0,0 +1,105 @@ +/** @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(sec_tag_t 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(sec_tag_t 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(sec_tag_t 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/include/net/socket.h b/include/net/socket.h index f7890ab1cc0e6..81fdc79029e9b 100644 --- a/include/net/socket.h +++ b/include/net/socket.h @@ -43,6 +43,18 @@ struct zsock_pollfd { #define ZSOCK_MSG_PEEK 0x02 #define ZSOCK_MSG_DONTWAIT 0x40 +/* socket option for TCP */ +#define SOL_TCP 6 + +/* 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; int ai_flags; @@ -75,6 +87,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 +191,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/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 */ 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/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..06aa28180e015 100644 --- a/samples/net/sockets/http_get/src/http_get.c +++ b/samples/net/sockets/http_get/src/http_get.c @@ -20,17 +20,23 @@ #include #include #include +#include + +#include "tls_default_credentials.h" #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 "/" - #define SSTRLEN(s) (sizeof(s) - 1) #define CHECK(r) { if (r == -1) { printf("Error: " #r "\n"); exit(1); } } @@ -74,9 +80,23 @@ 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) + 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, res->ai_addr, res->ai_addrlen)); CHECK(send(sock, REQUEST, SSTRLEN(REQUEST), 0)); @@ -95,9 +115,11 @@ int main(void) } response[len] = 0; - printf("%s\n", response); + printf("%s", response); } + printf("\n"); + (void)close(sock); return 0; diff --git a/samples/net/sockets/http_get/src/tls_default_credentials.h b/samples/net/sockets/http_get/src/tls_default_credentials.h new file mode 100644 index 0000000000000..9ae064ac4f9d8 --- /dev/null +++ b/samples/net/sockets/http_get/src/tls_default_credentials.h @@ -0,0 +1,154 @@ +/* + * 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. + */ + +/* 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 /* __TLS_DEFAULT_CREDENTIALS_H__ */ 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..f96672db4decc 100644 --- a/subsys/net/ip/Kconfig +++ b/subsys/net/ip/Kconfig @@ -248,6 +248,8 @@ config NET_DEBUG_UDP help Enables UDP handler output debug messages +source "subsys/net/ip/Kconfig.tls" + config NET_MAX_CONN int "How many network connections are supported" depends on NET_UDP || NET_TCP diff --git a/subsys/net/ip/Kconfig.tls b/subsys/net/ip/Kconfig.tls new file mode 100644 index 0000000000000..c3d9a24fc0353 --- /dev/null +++ b/subsys/net/ip/Kconfig.tls @@ -0,0 +1,180 @@ +# 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 [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 [EXPERIMENTAL]" + 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 + +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 + int "Maximum number of TLS/DTLS credentials" + default 4 + 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 + help + Use preconfigured credentials (CA Certificate, PSK) for TLS/DTLS sessions. + +config NET_TLS_CREDENTIALS_FILE + string "TLS/DTLS credentials to preconfigure" + default "tls_default_credentials.h" + depends on NET_PRECONFIGURE_TLS_CREDENTIALS + help + File containing default TLS/DTLS credentials to preconfigure. TODO Extend description. + +endif + +endmenu 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_context.c b/subsys/net/ip/net_context.c index 032d0f8673846..84086b61ce323 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_internal.h" #include "ipv6.h" #include "ipv4.h" @@ -116,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) @@ -206,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); @@ -341,6 +359,12 @@ int net_context_put(struct net_context *context) return 0; } +#if defined(CONFIG_NET_TLS) || defined(CONFIG_NET_DTLS) + if (context->tls) { + net_tls_enable(context, false); + } +#endif /* defined(CONFIG_NET_TLS) || defined(CONFIG_NET_DTLS) */ + net_context_unref(context); return 0; } @@ -617,7 +641,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; @@ -767,19 +791,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, @@ -873,6 +903,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, @@ -882,7 +970,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; @@ -924,6 +1011,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( @@ -933,53 +1024,17 @@ 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; +#if defined(CONFIG_NET_TLS) || defined(CONFIG_NET_DTLS) + if (context->tls) { + return net_tls_send(pkt); } +#endif + + return net_context_output(context, pkt, dst_addr); } int net_context_send(struct net_pkt *pkt, @@ -1223,6 +1278,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->tls) { + ret = net_tls_recv(context, cb, user_data); + break; + } +#endif ret = net_tcp_recv(context, cb, user_data); break; @@ -1292,6 +1353,78 @@ static int get_context_priority(struct net_context *context, #endif } +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)) { + return -EINVAL; + } + + *((int *)value) = (context->tls != 0); + + return 0; +#else + return -ENOTSUP; +#endif +} + +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; + + if (len != sizeof(int)) { + return -EINVAL; + } + + enabled = !!*(int *)value; + + return net_tls_enable(context, enabled); +#else + return -ENOTSUP; +#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) @@ -1304,10 +1437,22 @@ 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_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; @@ -1325,10 +1470,22 @@ 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_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; } return ret; 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_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/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); diff --git a/subsys/net/ip/net_tls.c b/subsys/net/ip/net_tls.c new file mode 100644 index 0000000000000..9e9ca3d0665d8 --- /dev/null +++ b/subsys/net/ip/net_tls.c @@ -0,0 +1,735 @@ +/* + * Copyright (c) 2018 Intel Corporation + * + * 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" +#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; + sec_tag_t 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]; + +/* 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) +{ + 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 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; + + 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; + struct net_pkt *pkt; + int bytes, ret; + + pkt = net_pkt_get_tx(context, TIMEOUT_TLS_TX_MS); + + 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) +{ + struct net_context *context = ctx; + int ret; + u16_t len_left; + + 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->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->tls->rx_offset += ret; + } + + 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->tls->rx_pkt)); + } + net_pkt_unref(context->tls->rx_pkt); + context->tls->rx_pkt = NULL; + context->tls->rx_offset = 0; + } + + return ret; +} + +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->tls_cb) { + context->tls->tls_cb(context, pkt, status, user_data); + } + return; + } + + 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)); + } + + /* Process it as application data only after handshake is over, + * otherwise packet will be consumed by handshake. + */ + 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); + 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->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; + + break; + } + + if (ret > 0) { + ret = net_pkt_append(decrypted_pkt, ret, + context->tls->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->tls_cb) { + context->tls->tls_cb(context, decrypted_pkt, + status, user_data); + } else { + goto err; + } + } + + return; + +err: + 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->tls->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->tls->config, + &context->tls->ca_chain, NULL); + + mbedtls_ssl_conf_authmode(&context->tls->config, + MBEDTLS_SSL_VERIFY_REQUIRED); + + mbedtls_ssl_conf_cert_profile(&context->tls->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->tls->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, err; + bool ca_cert_present = false; + + 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)) + != NULL) { + switch (credential->type) { + case NET_TLS_CREDENTIAL_CA_CERTIFICATE: + { + err = tls_add_ca_certificate(context, + credential); + if (err < 0) { + return err; + } + + ca_cert_present = true; + + break; + } + + case NET_TLS_CREDENTIAL_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 */ + break; + + default: + return -EINVAL; + } + } + } + + if (ca_cert_present) { + tls_set_ca_chain(context); + } + + return 0; +} + +void net_tls_init(void) +{ + 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; + } + +#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 */ + + 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 +} + +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, err; + + if (!context) { + return -EINVAL; + } + + if ((context->tls && enabled) || (!context->tls && !enabled)) { + return 0; + } + + state = net_context_get_state(context); + if (state != NET_CONTEXT_IDLE && state != NET_CONTEXT_UNCONNECTED) { + return -EBUSY; + } + + if (!enabled) { + err = net_tls_release(context->tls); + if (err == 0) { + context->tls = NULL; + } + + return err; + } + + context->tls = net_tls_alloc(context); + if (!context->tls) { + return -ENOMEM; + } + + 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->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->tls->config, role, type, + MBEDTLS_SSL_PRESET_DEFAULT); + if (err) { + err = -ENOMEM; + goto mbed_err_conf; + } + + mbedtls_ssl_conf_rng(&context->tls->config, + mbedtls_ctr_drbg_random, + &tls_ctr_drbg); + + err = tls_mbedtls_set_credentials(context); + if (err) { + goto mbed_err_conf; + } + + err = mbedtls_ssl_setup(&context->tls->ssl, + &context->tls->config); + if (err) { + err = -EINVAL; + goto mbed_err_conf; + } + + while ((err = mbedtls_ssl_handshake(&context->tls->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->tls->ssl); + mbedtls_ssl_config_free(&context->tls->config); + + 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->tls->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; + } + + 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->tls_cb = cb; + +#if defined(CONFIG_NET_TCP) + context->tcp->recv_user_data = user_data; +#endif + + return 0; +} + +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->tls) { + return -EPERM; + } + + tags_to_copy = MIN(context->tls->options.sec_tag_list.sec_tag_count, + *sec_tag_cnt); + memcpy(sec_tags, context->tls->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->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->tls->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->tls->options.sec_tag_list.sec_tags, sec_tags, + sec_tag_cnt * sizeof(sec_tag_t)); + context->tls->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); + + 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(sec_tag_t 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_internal.h b/subsys/net/ip/net_tls_internal.h new file mode 100644 index 0000000000000..bca55ce97c042 --- /dev/null +++ b/subsys/net/ip/net_tls_internal.h @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2018 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __NET_TLS_INTERNAL_H +#define __NET_TLS_INTERNAL_H + +#include +#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 */ + +/** 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); +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) +{ +} + +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); + ARG_UNUSED(enabled); + + return 0; +} + +static inline int net_tls_connect(struct net_context *context, bool listening) +{ + ARG_UNUSED(context); + ARG_UNUSED(listening); + + return 0; +} + +static inline int net_tls_send(struct net_pkt *pkt) +{ + ARG_UNUSED(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; +} + +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/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; diff --git a/subsys/net/lib/sockets/CMakeLists.txt b/subsys/net/lib/sockets/CMakeLists.txt index 94ed549b22131..1df7be6ca8017 100644 --- a/subsys/net/lib/sockets/CMakeLists.txt +++ b/subsys/net/lib/sockets/CMakeLists.txt @@ -3,3 +3,7 @@ zephyr_sources( getaddrinfo.c sockets.c ) + +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/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 5bcd771f5909d..6d3ae2db42bc2 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 @@ -159,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->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); @@ -443,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->tls) { + net_context_update_recv_wnd(ctx, recv_len); + } +#else net_context_update_recv_wnd(ctx, recv_len); +#endif } return recv_len; @@ -577,3 +591,51 @@ 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) +{ + int ret = 0; + + if (!sock) { + SET_ERRNO(-ENOTSOCK); + } + + switch (level) { + case SOL_TLS: + ret = tls_getsockopt(sock, level, optname, optval, optlen); + break; + + default: + ret = -EOPNOTSUPP; + break; + } + + SET_ERRNO(ret); + + return 0; +} + +int zsock_setsockopt(int sock, int level, int optname, + const void *optval, socklen_t optlen) +{ + int ret = 0; + + if (!sock) { + SET_ERRNO(-ENOTSOCK); + } + + switch (level) { + case SOL_TLS: + 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..6208a421bdb02 --- /dev/null +++ b/subsys/net/lib/sockets/sockets_tls.c @@ -0,0 +1,94 @@ +/* + * 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 TLS_ENABLE: + if (*optlen != sizeof(int)) { + return -EINVAL; + } + + 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; + } + + 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 TLS_ENABLE: + if (optlen != sizeof(int)) { + return -EINVAL; + } + + 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; + } + + 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 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..c06b4d841e656 --- /dev/null +++ b/tests/net/socket/sockopt/prj.conf @@ -0,0 +1,40 @@ +# 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 +CONFIG_MBEDTLS=y +CONFIG_NET_TLS=y +CONFIG_NET_DTLS=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_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. +# 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..03b27bdb555c7 --- /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_TLS, 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_TLS, 0, &enable, &size), -1, + "getsockopt"); + zassert_equal(errno, EBADF, "getsockopt errno"); + + errno = 0; + 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_TLS, 0, NULL, &size), -1, + "getsockopt"); + zassert_equal(errno, EFAULT, "getsockopt errno"); + + errno = 0; + 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_TLS, 0, &enable, &size), -1, + "getsockopt"); + zassert_equal(errno, EFAULT, "getsockopt errno"); + + size = 0; + errno = 0; + 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_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_TLS, TLS_ENABLE, &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_TLS, 0, NULL, 0), -1, + "setsockopt"); + zassert_equal(errno, EFAULT, "setsockopt errno"); + + errno = 0; + 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_TLS, 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_TLS, 0, &enable, sizeof(enable)), + -1, "setsockopt"); + zassert_equal(errno, EBADF, "setsockopt errno"); + + errno = 0; + zassert_equal(setsockopt(s6_tcp, SOL_TLS, TLS_ENABLE, + &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..bd65a58daa951 --- /dev/null +++ b/tests/net/socket/sockopt/testcase.yaml @@ -0,0 +1,4 @@ +tests: + test: + min_ram: 42 + tags: net socket