From b7e6638fd870074ba1e772a9fbfa9f1efb915604 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Tue, 1 Dec 2020 10:45:10 +0000 Subject: [PATCH] Add `ciphers_tls1.3` option, to allow setting TLS v1.3 ciphersuites. Closes #1825. Thanks to Valentin Dimov. --- ChangeLog.txt | 2 ++ man/mosquitto.conf.5.xml | 22 +++++++++++++++++----- mosquitto.conf | 9 +++++++-- src/conf.c | 10 ++++++++++ src/mosquitto_broker_internal.h | 1 + src/net.c | 10 ++++++++++ src/websockets.c | 3 +++ 7 files changed, 50 insertions(+), 7 deletions(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index 409b0805..d6e6b02f 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -86,6 +86,8 @@ Broker: - Fix file logging on Windows. Closes #1880. - Fix bridge sock not being removed from sock hash on error. Closes #1897. - Default for max_queued_messages has been changed to 1000. +- Add `ciphers_tls1.3` option, to allow setting TLS v1.3 ciphersuites. + Closes #1825. Client library: - Client no longer generates random client ids for v3.1.1 clients, these are diff --git a/man/mosquitto.conf.5.xml b/man/mosquitto.conf.5.xml index 86aa656c..fa909a68 100644 --- a/man/mosquitto.conf.5.xml +++ b/man/mosquitto.conf.5.xml @@ -1171,8 +1171,8 @@ log_timestamp_format %Y-%m-%dT%H:%M:%S default at compile time. Certificate based TLS may be used with websockets, except that only the , , - and - options are + , , and + options are supported. Not reloaded on reload signal. @@ -1289,9 +1289,21 @@ log_timestamp_format %Y-%m-%dT%H:%M:%S cipher:list - The list of allowed ciphers, each separated with - a colon. Available ciphers can be obtained using - the "openssl ciphers" command. + + The list of allowed ciphers for this listener, for + TLS v1.2 and earlier only, each separated with + a colon. Available ciphers can be obtained using + the "openssl ciphers" command. + + + + + cipher:list + + + The list of allowed ciphersuites for this listener, + for TLS v1.3, each separated with a colon. + diff --git a/mosquitto.conf b/mosquitto.conf index adb1cac7..243964d0 100644 --- a/mosquitto.conf +++ b/mosquitto.conf @@ -257,7 +257,7 @@ # Choose the protocol to use when listening. # This can be either mqtt or websockets. # Certificate based TLS may be used with websockets, except that only the -# cafile, certfile, keyfile and ciphers options are supported. +# cafile, certfile, keyfile, ciphers, and ciphers_tls13 options are supported. #protocol mqtt # Set use_username_as_clientid to true to replace the clientid that a client @@ -300,9 +300,14 @@ # If you wish to control which encryption ciphers are used, use the ciphers # option. The list of available ciphers can be optained using the "openssl # ciphers" command and should be provided in the same format as the output of -# that command. +# that command. This applies to TLS 1.2 and earlier versions only. Use +# ciphers_tls1.3 for TLS v1.3. #ciphers +# Choose which TLS v1.3 ciphersuites are used for this listener. +# Defaults to "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256" +#ciphers_tls1.3 + # If you have require_certificate set to true, you can create a certificate # revocation list file to revoke access to particular client certificates. If # you have done this, use crlfile to point to the PEM encoded revocation file. diff --git a/src/conf.c b/src/conf.c index c2db4216..aca38d02 100644 --- a/src/conf.c +++ b/src/conf.c @@ -278,6 +278,7 @@ void config__cleanup(struct mosquitto__config *config) mosquitto__free(config->listeners[i].certfile); mosquitto__free(config->listeners[i].keyfile); mosquitto__free(config->listeners[i].ciphers); + mosquitto__free(config->listeners[i].ciphers_tls13); mosquitto__free(config->listeners[i].psk_hint); mosquitto__free(config->listeners[i].crlfile); mosquitto__free(config->listeners[i].dhparamfile); @@ -428,6 +429,7 @@ int config__parse_args(struct mosquitto__config *config, int argc, char *argv[]) || config->default_listener.tls_keyform != mosq_k_pem || config->default_listener.tls_engine_kpass_sha1 || config->default_listener.ciphers + || config->default_listener.ciphers_tls13 || config->default_listener.dhparamfile || config->default_listener.psk_hint || config->default_listener.require_certificate @@ -492,6 +494,7 @@ int config__parse_args(struct mosquitto__config *config, int argc, char *argv[]) config->listeners[config->listener_count-1].certfile = config->default_listener.certfile; config->listeners[config->listener_count-1].keyfile = config->default_listener.keyfile; config->listeners[config->listener_count-1].ciphers = config->default_listener.ciphers; + config->listeners[config->listener_count-1].ciphers_tls13 = config->default_listener.ciphers_tls13; config->listeners[config->listener_count-1].dhparamfile = config->default_listener.dhparamfile; config->listeners[config->listener_count-1].psk_hint = config->default_listener.psk_hint; config->listeners[config->listener_count-1].require_certificate = config->default_listener.require_certificate; @@ -1173,6 +1176,13 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct if(conf__parse_string(&token, "ciphers", &cur_listener->ciphers, saveptr)) return MOSQ_ERR_INVAL; #else log__printf(NULL, MOSQ_LOG_WARNING, "Warning: TLS support not available."); +#endif + }else if(!strcmp(token, "ciphers_tls1.3")){ +#ifdef WITH_TLS + if(reload) continue; /* Listeners not valid for reloading. */ + if(conf__parse_string(&token, "ciphers_tls1.3", &cur_listener->ciphers_tls13, saveptr)) return MOSQ_ERR_INVAL; +#else + log__printf(NULL, MOSQ_LOG_WARNING, "Warning: TLS support not available."); #endif }else if(!strcmp(token, "clientid") || !strcmp(token, "remote_clientid")){ #ifdef WITH_BRIDGE diff --git a/src/mosquitto_broker_internal.h b/src/mosquitto_broker_internal.h index 18315270..231e4447 100644 --- a/src/mosquitto_broker_internal.h +++ b/src/mosquitto_broker_internal.h @@ -228,6 +228,7 @@ struct mosquitto__listener { char *tls_engine; char *tls_engine_kpass_sha1; char *ciphers; + char *ciphers_tls13; char *psk_hint; SSL_CTX *ssl_ctx; char *crlfile; diff --git a/src/net.c b/src/net.c index 78a1dc56..acd60025 100644 --- a/src/net.c +++ b/src/net.c @@ -386,6 +386,16 @@ int net__tls_server_ctx(struct mosquitto__listener *listener) return MOSQ_ERR_TLS; } } +#if OPENSSL_VERSION_NUMBER >= 0x10101000 + if(listener->ciphers_tls13){ + rc = SSL_CTX_set_ciphersuites(listener->ssl_ctx, listener->ciphers_tls13); + if(rc == 0){ + log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to set TLS 1.3 ciphersuites. Check cipher_tls13 list \"%s\".", listener->ciphers_tls13); + return MOSQ_ERR_TLS; + } + } +#endif + if(listener->dhparamfile){ dhparamfile = fopen(listener->dhparamfile, "r"); if(!dhparamfile){ diff --git a/src/websockets.c b/src/websockets.c index f39214c4..63527937 100644 --- a/src/websockets.c +++ b/src/websockets.c @@ -753,6 +753,9 @@ struct libwebsocket_context *mosq_websockets_init(struct mosquitto__listener *li info.ssl_cert_filepath = listener->certfile; info.ssl_private_key_filepath = listener->keyfile; info.ssl_cipher_list = listener->ciphers; +#if defined(WITH_WEBSOCKETS) && LWS_LIBRARY_VERSION_NUMBER>=3001000 + info->tls_1_3_plus_cipher_list = listener->ciphers_tls13; +#endif if(listener->require_certificate){ info.options |= LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT; }