Add ciphers_tls1.3 option, to allow setting TLS v1.3 ciphersuites.

Closes #1825. Thanks to Valentin Dimov.
This commit is contained in:
Roger A. Light 2020-12-01 10:45:10 +00:00
parent ed28c416e9
commit b7e6638fd8
7 changed files with 50 additions and 7 deletions

View File

@ -86,6 +86,8 @@ Broker:
- Fix file logging on Windows. Closes #1880. - Fix file logging on Windows. Closes #1880.
- Fix bridge sock not being removed from sock hash on error. Closes #1897. - Fix bridge sock not being removed from sock hash on error. Closes #1897.
- Default for max_queued_messages has been changed to 1000. - 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 library:
- Client no longer generates random client ids for v3.1.1 clients, these are - Client no longer generates random client ids for v3.1.1 clients, these are

View File

@ -1171,8 +1171,8 @@ log_timestamp_format %Y-%m-%dT%H:%M:%S
default at compile time. Certificate based TLS may be used default at compile time. Certificate based TLS may be used
with websockets, except that only the with websockets, except that only the
<option>cafile</option>, <option>certfile</option>, <option>cafile</option>, <option>certfile</option>,
<option>keyfile</option> and <option>keyfile</option>, <option>ciphers</option>, and
<option>ciphers</option> options are <option>ciphers_tls1.3</option> options are
supported.</para> supported.</para>
<para>Not reloaded on reload signal.</para> <para>Not reloaded on reload signal.</para>
</listitem> </listitem>
@ -1289,9 +1289,21 @@ log_timestamp_format %Y-%m-%dT%H:%M:%S
<varlistentry> <varlistentry>
<term><option>ciphers</option> <replaceable>cipher:list</replaceable></term> <term><option>ciphers</option> <replaceable>cipher:list</replaceable></term>
<listitem> <listitem>
<para>The list of allowed ciphers, each separated with <para>
a colon. Available ciphers can be obtained using The list of allowed ciphers for this listener, for
the "openssl ciphers" command.</para> TLS v1.2 and earlier only, each separated with
a colon. Available ciphers can be obtained using
the "openssl ciphers" command.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>ciphers_tls1.3</option> <replaceable>cipher:list</replaceable></term>
<listitem>
<para>
The list of allowed ciphersuites for this listener,
for TLS v1.3, each separated with a colon.
</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>

View File

@ -257,7 +257,7 @@
# Choose the protocol to use when listening. # Choose the protocol to use when listening.
# This can be either mqtt or websockets. # This can be either mqtt or websockets.
# Certificate based TLS may be used with websockets, except that only the # 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 #protocol mqtt
# Set use_username_as_clientid to true to replace the clientid that a client # 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 # 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 # 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 # 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 #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 # If you have require_certificate set to true, you can create a certificate
# revocation list file to revoke access to particular client certificates. If # 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. # you have done this, use crlfile to point to the PEM encoded revocation file.

View File

@ -278,6 +278,7 @@ void config__cleanup(struct mosquitto__config *config)
mosquitto__free(config->listeners[i].certfile); mosquitto__free(config->listeners[i].certfile);
mosquitto__free(config->listeners[i].keyfile); mosquitto__free(config->listeners[i].keyfile);
mosquitto__free(config->listeners[i].ciphers); 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].psk_hint);
mosquitto__free(config->listeners[i].crlfile); mosquitto__free(config->listeners[i].crlfile);
mosquitto__free(config->listeners[i].dhparamfile); 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_keyform != mosq_k_pem
|| config->default_listener.tls_engine_kpass_sha1 || config->default_listener.tls_engine_kpass_sha1
|| config->default_listener.ciphers || config->default_listener.ciphers
|| config->default_listener.ciphers_tls13
|| config->default_listener.dhparamfile || config->default_listener.dhparamfile
|| config->default_listener.psk_hint || config->default_listener.psk_hint
|| config->default_listener.require_certificate || 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].certfile = config->default_listener.certfile;
config->listeners[config->listener_count-1].keyfile = config->default_listener.keyfile; 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 = 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].dhparamfile = config->default_listener.dhparamfile;
config->listeners[config->listener_count-1].psk_hint = config->default_listener.psk_hint; 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; 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; if(conf__parse_string(&token, "ciphers", &cur_listener->ciphers, saveptr)) return MOSQ_ERR_INVAL;
#else #else
log__printf(NULL, MOSQ_LOG_WARNING, "Warning: TLS support not available."); 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 #endif
}else if(!strcmp(token, "clientid") || !strcmp(token, "remote_clientid")){ }else if(!strcmp(token, "clientid") || !strcmp(token, "remote_clientid")){
#ifdef WITH_BRIDGE #ifdef WITH_BRIDGE

View File

@ -228,6 +228,7 @@ struct mosquitto__listener {
char *tls_engine; char *tls_engine;
char *tls_engine_kpass_sha1; char *tls_engine_kpass_sha1;
char *ciphers; char *ciphers;
char *ciphers_tls13;
char *psk_hint; char *psk_hint;
SSL_CTX *ssl_ctx; SSL_CTX *ssl_ctx;
char *crlfile; char *crlfile;

View File

@ -386,6 +386,16 @@ int net__tls_server_ctx(struct mosquitto__listener *listener)
return MOSQ_ERR_TLS; 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){ if(listener->dhparamfile){
dhparamfile = fopen(listener->dhparamfile, "r"); dhparamfile = fopen(listener->dhparamfile, "r");
if(!dhparamfile){ if(!dhparamfile){

View File

@ -753,6 +753,9 @@ struct libwebsocket_context *mosq_websockets_init(struct mosquitto__listener *li
info.ssl_cert_filepath = listener->certfile; info.ssl_cert_filepath = listener->certfile;
info.ssl_private_key_filepath = listener->keyfile; info.ssl_private_key_filepath = listener->keyfile;
info.ssl_cipher_list = listener->ciphers; 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){ if(listener->require_certificate){
info.options |= LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT; info.options |= LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT;
} }