net: lib: sockets: added ALPN extension option to TLS

Adds the socket option TLS_ALPN_LIST for SOL_TLS sockets

Passes the configured alpn list to the mbedtls config
on mbedtls init

Signed-off-by: Emil Hammarstrom <emil.hammarstrom@assaabloy.com>
This commit is contained in:
Emil Hammarstrom 2020-10-19 16:53:44 +02:00 committed by Jukka Rissanen
parent a8a92ce592
commit ec00feef35
4 changed files with 106 additions and 0 deletions

View File

@ -119,6 +119,12 @@ struct zsock_pollfd {
* - 1 - server
*/
#define TLS_DTLS_ROLE 6
/** Socket option for setting the supported Application Layer Protocols.
* It accepts and returns a const char array of NULL terminated strings
* representing the supported application layer protocols listed during
* the TLS handshake.
*/
#define TLS_ALPN_LIST 7
/** @} */

View File

@ -37,6 +37,10 @@ config MBEDTLS_SSL_EXPORT_KEYS
bool "Enable support for exporting SSL key block and master secret"
depends on MBEDTLS_TLS_VERSION_1_0 || MBEDTLS_TLS_VERSION_1_1 || MBEDTLS_TLS_VERSION_1_2
config MBEDTLS_SSL_ALPN
bool "Enable support for setting the supported Application Layer Protocols"
depends on MBEDTLS_TLS_VERSION_1_0 || MBEDTLS_TLS_VERSION_1_1 || MBEDTLS_TLS_VERSION_1_2
endmenu
menu "Ciphersuite configuration"

View File

@ -100,6 +100,15 @@ config NET_SOCKETS_TLS_MAX_CIPHERSUITES
By default, all ciphersuites that are available in the system are
available to the socket.
config NET_SOCKETS_TLS_MAX_APP_PROTOCOLS
int "Maximum number of supported application layer protocols"
default 2
depends on NET_SOCKETS_SOCKOPT_TLS && MBEDTLS_SSL_ALPN
help
This variable sets maximum number of supported application layer
protocols over TLS/DTL that can be set explicitly by a socket option.
By default, no supported application layer protocol is set.
config NET_SOCKETS_OFFLOAD
bool "Offload Socket APIs [EXPERIMENTAL]"
help

View File

@ -39,6 +39,12 @@ LOG_MODULE_REGISTER(net_sock_tls, CONFIG_NET_SOCKETS_LOG_LEVEL);
#include "sockets_internal.h"
#include "tls_internal.h"
#if defined(CONFIG_NET_SOCKETS_TLS_MAX_APP_PROTOCOLS)
#define ALPN_MAX_PROTOCOLS (CONFIG_NET_SOCKETS_TLS_MAX_APP_PROTOCOLS + 1)
#else
#define ALPN_MAX_PROTOCOLS 0
#endif /* CONFIG_NET_SOCKETS_TLS_MAX_APP_PROTOCOLS */
static const struct socket_op_vtable tls_sock_fd_op_vtable;
/** A list of secure tags that TLS context should use. */
@ -109,6 +115,11 @@ struct tls_context {
/** DTLS role, client by default. */
int8_t role;
/** NULL-terminated list of allowed application layer
* protocols.
*/
const char *alpn_list[ALPN_MAX_PROTOCOLS];
} options;
#if defined(CONFIG_NET_SOCKETS_ENABLE_DTLS)
@ -920,6 +931,16 @@ static int tls_mbedtls_init(struct tls_context *context, bool is_server)
return ret;
}
#if defined(CONFIG_MBEDTLS_SSL_ALPN)
if (ALPN_MAX_PROTOCOLS && context->options.alpn_list[0] != NULL) {
ret = mbedtls_ssl_conf_alpn_protocols(&context->config,
context->options.alpn_list);
if (ret != 0) {
return -EINVAL;
}
}
#endif /* CONFIG_MBEDTLS_SSL_ALPN */
ret = mbedtls_ssl_setup(&context->ssl,
&context->config);
if (ret != 0) {
@ -1072,6 +1093,64 @@ static int tls_opt_ciphersuite_used_get(struct tls_context *context,
return 0;
}
static int tls_opt_alpn_list_set(struct tls_context *context,
const void *optval, socklen_t optlen)
{
int alpn_cnt;
if (!ALPN_MAX_PROTOCOLS) {
return -EINVAL;
}
if (!optval) {
return -EINVAL;
}
if (optlen % sizeof(const char *) != 0) {
return -EINVAL;
}
alpn_cnt = optlen / sizeof(const char *);
/* + 1 for NULL-termination. */
if (alpn_cnt + 1 > ARRAY_SIZE(context->options.alpn_list)) {
return -EINVAL;
}
memcpy(context->options.alpn_list, optval, optlen);
context->options.alpn_list[alpn_cnt] = NULL;
return 0;
}
static int tls_opt_alpn_list_get(struct tls_context *context,
void *optval, socklen_t *optlen)
{
const char **alpn_list = context->options.alpn_list;
int alpn_cnt, i = 0;
const char **ret_list = optval;
if (!ALPN_MAX_PROTOCOLS) {
return -EINVAL;
}
if (*optlen % sizeof(const char *) != 0 || *optlen == 0) {
return -EINVAL;
}
alpn_cnt = *optlen / sizeof(const char *);
while (alpn_list[i] != NULL) {
ret_list[i] = alpn_list[i];
if (++i == alpn_cnt) {
break;
}
}
*optlen = i * sizeof(const char *);
return 0;
}
static int tls_opt_peer_verify_set(struct tls_context *context,
const void *optval, socklen_t optlen)
{
@ -1922,6 +2001,10 @@ int ztls_getsockopt_ctx(struct tls_context *ctx, int level, int optname,
err = tls_opt_ciphersuite_used_get(ctx, optval, optlen);
break;
case TLS_ALPN_LIST:
err = tls_opt_alpn_list_get(ctx, optval, optlen);
break;
default:
/* Unknown or write-only option. */
err = -ENOPROTOOPT;
@ -1967,6 +2050,10 @@ int ztls_setsockopt_ctx(struct tls_context *ctx, int level, int optname,
err = tls_opt_dtls_role_set(ctx, optval, optlen);
break;
case TLS_ALPN_LIST:
err = tls_opt_alpn_list_set(ctx, optval, optlen);
break;
default:
/* Unknown or read-only option. */
err = -ENOPROTOOPT;