diff --git a/ChangeLog.txt b/ChangeLog.txt
index e0f5bc0a..c2322855 100644
--- a/ChangeLog.txt
+++ b/ChangeLog.txt
@@ -12,6 +12,8 @@ Broker features:
specific network interface, in a similar fashion to the `bind_address` option.
Linux only.
- Add improved bridge restart interval based on Decorrelated Jitter.
+- Add `dhparamfile` option, to allow DH parameters to be loaded for Ephemeral
+ DH support
Client library features:
- Add mosquitto_subscribe_multiple() for sending subscriptions to multiple
diff --git a/man/mosquitto.conf.5.xml b/man/mosquitto.conf.5.xml
index edf1309f..a34feefb 100644
--- a/man/mosquitto.conf.5.xml
+++ b/man/mosquitto.conf.5.xml
@@ -1041,6 +1041,18 @@
encoded revocation file.
+
+ file path
+
+ To allow the use of ephemeral DH key exchange,
+ which provides forward security, the listener must
+ load DH parameters. This can be specified with the
+ dhparamfile option. The dhparamfile can be
+ generated with the command e.g.
+
+openssl dhparam -out dhparam.pem 2048
+
+
file path
diff --git a/mosquitto.conf b/mosquitto.conf
index 9bd0a708..2927a610 100644
--- a/mosquitto.conf
+++ b/mosquitto.conf
@@ -312,6 +312,12 @@
# If unset defaults to DEFAULT:!aNULL:!eNULL:!LOW:!EXPORT:!SSLv2:@STRENGTH
#ciphers DEFAULT:!aNULL:!eNULL:!LOW:!EXPORT:!SSLv2:@STRENGTH
+# To allow the use of ephemeral DH key exchange, which provides forward
+# security, the listener must load DH parameters. This can be specified with
+# the dhparamfile option. The dhparamfile can be generated with the command
+# e.g. "openssl dhparam -out dhparam.pem 2048"
+#dhparamfile
+
# -----------------------------------------------------------------
# Pre-shared-key based SSL/TLS support
# -----------------------------------------------------------------
@@ -463,6 +469,12 @@
# that command.
#ciphers
+# To allow the use of ephemeral DH key exchange, which provides forward
+# security, the listener must load DH parameters. This can be specified with
+# the dhparamfile option. The dhparamfile can be generated with the command
+# e.g. "openssl dhparam -out dhparam.pem 2048"
+#dhparamfile
+
# -----------------------------------------------------------------
# Pre-shared-key based SSL/TLS support
# -----------------------------------------------------------------
diff --git a/src/conf.c b/src/conf.c
index 810f342b..941becb3 100644
--- a/src/conf.c
+++ b/src/conf.c
@@ -306,6 +306,7 @@ void config__cleanup(struct mosquitto__config *config)
mosquitto__free(config->listeners[i].ciphers);
mosquitto__free(config->listeners[i].psk_hint);
mosquitto__free(config->listeners[i].crlfile);
+ mosquitto__free(config->listeners[i].dhparamfile);
mosquitto__free(config->listeners[i].tls_version);
mosquitto__free(config->listeners[i].tls_engine);
mosquitto__free(config->listeners[i].tls_engine_kpass_sha1);
@@ -448,6 +449,7 @@ int config__parse_args(struct mosquitto_db *db, struct mosquitto__config *config
|| config->default_listener.tls_keyform != mosq_k_pem
|| config->default_listener.tls_engine_kpass_sha1
|| config->default_listener.ciphers
+ || config->default_listener.dhparamfile
|| config->default_listener.psk_hint
|| config->default_listener.require_certificate
|| config->default_listener.crlfile
@@ -509,6 +511,7 @@ int config__parse_args(struct mosquitto_db *db, struct mosquitto__config *config
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].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;
config->listeners[config->listener_count-1].ssl_ctx = NULL;
@@ -1203,6 +1206,13 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
if(conf__parse_string(&token, "crlfile", &cur_listener->crlfile, saveptr)) return MOSQ_ERR_INVAL;
#else
log__printf(NULL, MOSQ_LOG_WARNING, "Warning: TLS support not available.");
+#endif
+ }else if(!strcmp(token, "dhparamfile")){
+#ifdef WITH_TLS
+ if(reload) continue; // Listeners not valid for reloading.
+ if(conf__parse_string(&token, "dhparamfile", &cur_listener->dhparamfile, saveptr)) return MOSQ_ERR_INVAL;
+#else
+ log__printf(NULL, MOSQ_LOG_WARNING, "Warning: TLS support not available.");
#endif
}else if(!strcmp(token, "http_dir")){
#ifdef WITH_WEBSOCKETS
diff --git a/src/mosquitto_broker_internal.h b/src/mosquitto_broker_internal.h
index 2677e1d0..dfbe0fa5 100644
--- a/src/mosquitto_broker_internal.h
+++ b/src/mosquitto_broker_internal.h
@@ -234,6 +234,7 @@ struct mosquitto__listener {
SSL_CTX *ssl_ctx;
char *crlfile;
char *tls_version;
+ char *dhparamfile;
bool use_identity_as_username;
bool use_subject_as_username;
bool require_certificate;
diff --git a/src/net.c b/src/net.c
index 63516ab7..d6220a0f 100644
--- a/src/net.c
+++ b/src/net.c
@@ -312,7 +312,8 @@ static int mosquitto__tls_server_ctx(struct mosquitto__listener *listener)
{
char buf[256];
int rc;
-
+ FILE *dhparamfile;
+ DH *dhparam = NULL;
#if OPENSSL_VERSION_NUMBER < 0x10100000L
listener->ssl_ctx = SSL_CTX_new(SSLv23_server_method());
@@ -371,6 +372,20 @@ static int mosquitto__tls_server_ctx(struct mosquitto__listener *listener)
return 1;
}
}
+ if(listener->dhparamfile){
+ dhparamfile = fopen(listener->dhparamfile, "r");
+ if(!dhparamfile){
+ log__printf(NULL, MOSQ_LOG_ERR, "Error loading dhparamfile \"%s\".", listener->dhparamfile);
+ return 1;
+ }
+ dhparam = PEM_read_DHparams(dhparamfile, NULL, NULL, NULL);
+ fclose(dhparamfile);
+
+ if(dhparam == NULL || SSL_CTX_set_tmp_dh(listener->ssl_ctx, dhparam) != 1){
+ log__printf(NULL, MOSQ_LOG_ERR, "Error loading dhparamfile \"%s\".", listener->dhparamfile);
+ return 1;
+ }
+ }
return MOSQ_ERR_SUCCESS;
}
#endif