MEDIUM: ssl: add support for ciphersuites option for TLSv1.3

OpenSSL released support for TLSv1.3. It also added a separate function
SSL_CTX_set_ciphersuites that is used to set the ciphers used in the
TLS 1.3 handshake. This change adds support for that new configuration
option by adding a ciphersuites configuration variable that works
essentially the same as the existing ciphers setting.

Note that it should likely be backported to 1.8 in order to ease usage
of the now released openssl-1.1.1.
diff --git a/doc/configuration.txt b/doc/configuration.txt
index d890b0b..7c6684b 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -583,8 +583,10 @@
    - setenv
    - stats
    - ssl-default-bind-ciphers
+   - ssl-default-bind-ciphersuites
    - ssl-default-bind-options
    - ssl-default-server-ciphers
+   - ssl-default-server-ciphersuites
    - ssl-default-server-options
    - ssl-dh-param-file
    - ssl-server-verify
@@ -988,11 +990,25 @@
 ssl-default-bind-ciphers <ciphers>
   This setting is only available when support for OpenSSL was built in. It sets
   the default string describing the list of cipher algorithms ("cipher suite")
-  that are negotiated during the SSL/TLS handshake for all "bind" lines which
-  do not explicitly define theirs. The format of the string is defined in
-  "man 1 ciphers" from OpenSSL man pages, and can be for instance a string such
-  as "AES:ALL:!aNULL:!eNULL:+RC4:@STRENGTH" (without quotes). Please check the
-  "bind" keyword for more information.
+  that are negotiated during the SSL/TLS handshake except for TLSv1.3 for all
+  "bind" lines which do not explicitly define theirs. The format of the string
+  is defined in "man 1 ciphers" from OpenSSL man pages, and can be for instance
+  a string such as "AES:ALL:!aNULL:!eNULL:+RC4:@STRENGTH" (without quotes). For
+  TLSv1.3 cipher configuration, please check the "ssl-default-bind-ciphersuites"
+  keyword. Please check the "bind" keyword for more information.
+
+ssl-default-bind-ciphersuites <ciphersuites>
+  This setting is only available when support for OpenSSL was built in and
+  OpenSSL 1.1.1 or later was used to build HAProxy. It sets the default string
+  describing the list of cipher algorithms ("cipher suite") that are negotiated
+  during the TLSv1.3 handshake for all "bind" lines which do not explicitly define
+  theirs. The format of the string is defined in
+  "man 1 ciphers" from OpenSSL man pages under the section "ciphersuites", and can
+  be for instance a string such as
+  "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256"
+  (without quotes). For cipher configuration for TLSv1.2 and earlier, please check
+  the "ssl-default-bind-ciphers" keyword. Please check the "bind" keyword for more
+  information.
 
 ssl-default-bind-options [<option>]...
   This setting is only available when support for OpenSSL was built in. It sets
@@ -1006,10 +1022,21 @@
 ssl-default-server-ciphers <ciphers>
   This setting is only available when support for OpenSSL was built in. It
   sets the default string describing the list of cipher algorithms that are
-  negotiated during the SSL/TLS handshake with the server, for all "server"
-  lines which do not explicitly define theirs. The format of the string is
-  defined in "man 1 ciphers". Please check the "server" keyword for more
-  information.
+  negotiated during the SSL/TLS handshake except for TLSv1.3 with the server,
+  for all "server" lines which do not explicitly define theirs. The format of
+  the string is defined in "man 1 ciphers". For TLSv1.3 cipher configuration,
+  please check the "ssl-default-server-ciphersuites" keyword. Please check the
+  "server" keyword for more information.
+
+ssl-default-server-ciphersuites <ciphersuites>
+  This setting is only available when support for OpenSSL was built in and
+  OpenSSL 1.1.1 or later was used to build HAProxy. It sets the default
+  string describing the list of cipher algorithms that are negotiated during
+  the TLSv1.3 handshake with the server, for all "server" lines which do not
+  explicitly define theirs. The format of the string is defined in
+  "man 1 ciphers" under the "ciphersuites" section. For cipher configuration for
+  TLSv1.2 and earlier, please check the "ssl-default-server-ciphers" keyword.
+  Please check the "server" keyword for more information.
 
 ssl-default-server-options [<option>]...
   This setting is only available when support for OpenSSL was built in. It sets
@@ -10618,13 +10645,26 @@
 ciphers <ciphers>
   This setting is only available when support for OpenSSL was built in. It sets
   the string describing the list of cipher algorithms ("cipher suite") that are
-  negotiated during the SSL/TLS handshake. The format of the string is defined
-  in "man 1 ciphers" from OpenSSL man pages, and can be for instance a string
-  such as "AES:ALL:!aNULL:!eNULL:+RC4:@STRENGTH" (without quotes).
-  Depending on the compatibility and security requirements, the list of suitable
-  ciphers depends on a variety of variables. For background information and
-  recommendations see e. g. (https://wiki.mozilla.org/Security/Server_Side_TLS)
-  and (https://mozilla.github.io/server-side-tls/ssl-config-generator/).
+  negotiated during the SSL/TLS handshake except for TLSv1.3. The format of the
+  string is defined in "man 1 ciphers" from OpenSSL man pages, and can be for
+  instance a string such as "AES:ALL:!aNULL:!eNULL:+RC4:@STRENGTH" (without
+  quotes). Depending on the compatibility and security requirements, the list
+  of suitable ciphers depends on a variety of variables. For background
+  information and recommendations see e.g.
+  (https://wiki.mozilla.org/Security/Server_Side_TLS) and
+  (https://mozilla.github.io/server-side-tls/ssl-config-generator/). For TLSv1.3
+  cipher configuration, please check the "ciphersuites" keyword.
+
+ciphersuites <ciphersuites>
+  This setting is only available when support for OpenSSL was built in and
+  OpenSSL 1.1.1 or later was used to build HAProxy. It sets the string describing
+  the list of cipher algorithms ("cipher suite") that are negotiated during the
+  TLSv1.3 handshake. The format of the string is defined in "man 1 ciphers" from
+  OpenSSL man pages under the "ciphersuites" section, and can be for instance a
+  string such as
+  "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256"
+  (without quotes). For cipher configuration for TLSv1.2 and earlier, please check
+  the "ciphers" keyword.
 
 crl-file <crlfile>
   This setting is only available when support for OpenSSL was built in. It
@@ -11347,8 +11387,9 @@
   this option.
 
 ciphers <ciphers>
-  This option sets the string describing the list of cipher algorithms that is
-  is negotiated during the SSL/TLS handshake with the server. The format of the
+  This setting is only available when support for OpenSSL was built in. This
+  option sets the string describing the list of cipher algorithms that is
+  negotiated during the SSL/TLS handshake with the server. The format of the
   string is defined in "man 1 ciphers". When SSL is used to communicate with
   servers on the local network, it is common to see a weaker set of algorithms
   than what is used over the internet. Doing so reduces CPU usage on both the
@@ -11356,6 +11397,13 @@
   Some algorithms such as RC4-SHA1 are reasonably cheap. If no security at all
   is needed and just connectivity, using DES can be appropriate.
 
+ciphersuites <ciphersuites>
+  This setting is only available when support for OpenSSL was built in and
+  OpenSSL 1.1.1 or later was used to build HAProxy. This option sets the string
+  describing the list of cipher algorithms that is negotiated during the TLS
+  1.3 handshake with the server. The format of the string is defined in
+  "man 1 ciphers" under the "ciphersuites" section.
+
 cookie <value>
   The "cookie" parameter sets the cookie value assigned to the server to
   <value>. This value will be checked in incoming requests, and the first
diff --git a/include/common/defaults.h b/include/common/defaults.h
index f5c74db..b2c2583 100644
--- a/include/common/defaults.h
+++ b/include/common/defaults.h
@@ -239,11 +239,21 @@
 #define CONNECT_DEFAULT_CIPHERS NULL
 #endif
 
+/* ciphers used as defaults on TLS 1.3 connect */
+#ifndef CONNECT_DEFAULT_CIPHERSUITES
+#define CONNECT_DEFAULT_CIPHERSUITES NULL
+#endif
+
 /* ciphers used as defaults on listeners */
 #ifndef LISTEN_DEFAULT_CIPHERS
 #define LISTEN_DEFAULT_CIPHERS NULL
 #endif
 
+/* cipher suites used as defaults on TLS 1.3 listeners */
+#ifndef LISTEN_DEFAULT_CIPHERSUITES
+#define LISTEN_DEFAULT_CIPHERSUITES NULL
+#endif
+
 /* named curve used as defaults for ECDHE ciphers */
 #ifndef ECDHE_DEFAULT_CURVE
 #define ECDHE_DEFAULT_CURVE "prime256v1"
diff --git a/include/types/listener.h b/include/types/listener.h
index 816d111..50f1936 100644
--- a/include/types/listener.h
+++ b/include/types/listener.h
@@ -129,6 +129,9 @@
 	char *ca_file;             /* CAfile to use on verify */
 	char *crl_file;            /* CRLfile to use on verify */
 	char *ciphers;             /* cipher suite to use if non-null */
+#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
+	char *ciphersuites;        /* TLS 1.3 cipher suite to use if non-null */
+#endif
 	char *curves;	           /* curves suite to use for ECDHE */
 	char *ecdhe;               /* named curve to use for ECDHE */
 	struct tls_version_filter ssl_methods; /* ssl methods */
diff --git a/include/types/server.h b/include/types/server.h
index 8adc29b..a2e11c3 100644
--- a/include/types/server.h
+++ b/include/types/server.h
@@ -288,6 +288,9 @@
 			int allocated_size;
 		} * reused_sess;
 		char *ciphers;			/* cipher suite to use if non-null */
+#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
+		char *ciphersuites;			/* TLS 1.3 cipher suite to use if non-null */
+#endif
 		int options;			/* ssl options */
 		int verify;			/* verify method (set of SSL_VERIFY_* flags) */
 		struct tls_version_filter methods;	/* ssl methods */
diff --git a/src/server.c b/src/server.c
index e6944c2..c817c39 100644
--- a/src/server.c
+++ b/src/server.c
@@ -1480,6 +1480,10 @@
 		srv->ssl_ctx.verify_host = strdup(src->ssl_ctx.verify_host);
 	if (src->ssl_ctx.ciphers != NULL)
 		srv->ssl_ctx.ciphers = strdup(src->ssl_ctx.ciphers);
+#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
+	if (src->ssl_ctx.ciphersuites != NULL)
+		srv->ssl_ctx.ciphersuites = strdup(src->ssl_ctx.ciphersuites);
+#endif
 	if (src->sni_expr != NULL)
 		srv->sni_expr = strdup(src->sni_expr);
 }
diff --git a/src/ssl_sock.c b/src/ssl_sock.c
index c11acb3..07e039f 100644
--- a/src/ssl_sock.c
+++ b/src/ssl_sock.c
@@ -171,6 +171,10 @@
 
 	char *listen_default_ciphers;
 	char *connect_default_ciphers;
+#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
+	char *listen_default_ciphersuites;
+	char *connect_default_ciphersuites;
+#endif
 	int listen_default_ssloptions;
 	int connect_default_ssloptions;
 	struct tls_version_filter listen_default_sslmethods;
@@ -189,6 +193,14 @@
 #ifdef CONNECT_DEFAULT_CIPHERS
 	.connect_default_ciphers = CONNECT_DEFAULT_CIPHERS,
 #endif
+#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
+#ifdef LISTEN_DEFAULT_CIPHERSUITES
+	.listen_default_ciphersuites = LISTEN_DEFAULT_CIPHERSUITES,
+#endif
+#ifdef CONNECT_DEFAULT_CIPHERSUITES
+	.connect_default_ciphersuites = CONNECT_DEFAULT_CIPHERSUITES,
+#endif
+#endif
 	.listen_default_ssloptions = BC_SSL_O_NONE,
 	.connect_default_ssloptions = SRV_SSL_O_NONE,
 
@@ -3548,6 +3560,10 @@
 		conf->crl_file = NULL;
 		free(conf->ciphers);
 		conf->ciphers = NULL;
+#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
+		free(conf->ciphersuites);
+		conf->ciphersuites = NULL;
+#endif
 		free(conf->curves);
 		conf->curves = NULL;
 		free(conf->ecdhe);
@@ -4082,6 +4098,9 @@
 	int verify = SSL_VERIFY_NONE;
 	struct ssl_bind_conf __maybe_unused *ssl_conf_cur;
 	const char *conf_ciphers;
+#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
+	const char *conf_ciphersuites;
+#endif
 	const char *conf_curves = NULL;
 
 	if (ssl_conf) {
@@ -4181,6 +4200,16 @@
 		cfgerr++;
 	}
 
+#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
+	conf_ciphersuites = (ssl_conf && ssl_conf->ciphersuites) ? ssl_conf->ciphersuites : bind_conf->ssl_conf.ciphersuites;
+	if (conf_ciphersuites &&
+	    !SSL_CTX_set_ciphersuites(ctx, conf_ciphersuites)) {
+		ha_alert("Proxy '%s': unable to set TLS 1.3 cipher suites to '%s' for bind '%s' at [%s:%d].\n",
+			 curproxy->id, conf_ciphersuites, bind_conf->arg, bind_conf->file, bind_conf->line);
+		cfgerr++;
+	}
+#endif
+
 #ifndef OPENSSL_NO_DH
 	/* If tune.ssl.default-dh-param has not been set,
 	   neither has ssl-default-dh-file and no static DH
@@ -4662,6 +4691,16 @@
 			 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
 		cfgerr++;
 	}
+
+#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
+	if (srv->ssl_ctx.ciphersuites &&
+		!SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphersuites)) {
+		ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set TLS 1.3 cipher suites to '%s'.\n",
+			 curproxy->id, srv->id,
+			 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphersuites);
+		cfgerr++;
+	}
+#endif
 
 	return cfgerr;
 }
@@ -7243,6 +7282,26 @@
 {
 	return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
 }
+
+#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
+/* parse the "ciphersuites" bind keyword */
+static int ssl_bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
+{
+	if (!*args[cur_arg + 1]) {
+		memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
+		return ERR_ALERT | ERR_FATAL;
+	}
+
+	free(conf->ciphersuites);
+	conf->ciphersuites = strdup(args[cur_arg + 1]);
+	return 0;
+}
+static int bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
+{
+	return ssl_bind_parse_ciphersuites(args, cur_arg, px, &conf->ssl_conf, err);
+}
+#endif
+
 /* parse the "crt" bind keyword */
 static int bind_parse_crt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
 {
@@ -7634,6 +7693,10 @@
 
 	if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
 		conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
+#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
+	if (global_ssl.listen_default_ciphersuites && !conf->ssl_conf.ciphersuites)
+		conf->ssl_conf.ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
+#endif
 	conf->ssl_options |= global_ssl.listen_default_ssloptions;
 	conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
 	if (!conf->ssl_conf.ssl_methods.min)
@@ -7831,6 +7894,10 @@
 	newsrv->check.use_ssl = 1;
 	if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
 		newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
+#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
+	if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
+		newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
+#endif
 	newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
 	newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
 	if (!newsrv->ssl_ctx.methods.min)
@@ -7853,6 +7920,21 @@
 	newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
 	return 0;
 }
+
+#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
+/* parse the "ciphersuites" server keyword */
+static int srv_parse_ciphersuites(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
+{
+	if (!*args[*cur_arg + 1]) {
+		memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
+		return ERR_ALERT | ERR_FATAL;
+	}
+
+	free(newsrv->ssl_ctx.ciphersuites);
+	newsrv->ssl_ctx.ciphersuites = strdup(args[*cur_arg + 1]);
+	return 0;
+}
+#endif
 
 /* parse the "crl-file" server keyword */
 static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
@@ -7995,6 +8077,10 @@
 	newsrv->use_ssl = 1;
 	if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
 		newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
+#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
+	if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
+		newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
+#endif
 	return 0;
 }
 
@@ -8233,6 +8319,32 @@
 	*target = strdup(args[1]);
 	return 0;
 }
+
+#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
+/* parse the "ssl-default-bind-ciphersuites" / "ssl-default-server-ciphersuites" keywords
+ * in global section. Returns <0 on alert, >0 on warning, 0 on success.
+ */
+static int ssl_parse_global_ciphersuites(char **args, int section_type, struct proxy *curpx,
+                                    struct proxy *defpx, const char *file, int line,
+                                    char **err)
+{
+	char **target;
+
+	target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphersuites : &global_ssl.connect_default_ciphersuites;
+
+	if (too_many_args(1, args, err, NULL))
+		return -1;
+
+	if (*(args[1]) == 0) {
+		memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
+		return -1;
+	}
+
+	free(*target);
+	*target = strdup(args[1]);
+	return 0;
+}
+#endif
 
 /* parse various global tune.ssl settings consisting in positive integers.
  * Returns <0 on alert, >0 on warning, 0 on success.
@@ -8773,6 +8885,9 @@
 	{ "alpn",                  ssl_bind_parse_alpn,             1 }, /* set ALPN supported protocols */
 	{ "ca-file",               ssl_bind_parse_ca_file,          1 }, /* set CAfile to process verify on client cert */
 	{ "ciphers",               ssl_bind_parse_ciphers,          1 }, /* set SSL cipher suite */
+#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
+	{ "ciphersuites",          ssl_bind_parse_ciphersuites,     1 }, /* set TLS 1.3 cipher suite */
+#endif
 	{ "crl-file",              ssl_bind_parse_crl_file,         1 }, /* set certificat revocation list file use on client cert verify */
 	{ "curves",                ssl_bind_parse_curves,           1 }, /* set SSL curve suite */
 	{ "ecdhe",                 ssl_bind_parse_ecdhe,            1 }, /* defines named curve for elliptic curve Diffie-Hellman */
@@ -8792,6 +8907,9 @@
 	{ "ca-sign-file",          bind_parse_ca_sign_file,       1 }, /* set CAFile used to generate and sign server certs */
 	{ "ca-sign-pass",          bind_parse_ca_sign_pass,       1 }, /* set CAKey passphrase */
 	{ "ciphers",               bind_parse_ciphers,            1 }, /* set SSL cipher suite */
+#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
+	{ "ciphersuites",          bind_parse_ciphersuites,       1 }, /* set TLS 1.3 cipher suite */
+#endif
 	{ "crl-file",              bind_parse_crl_file,           1 }, /* set certificat revocation list file use on client cert verify */
 	{ "crt",                   bind_parse_crt,                1 }, /* load SSL certificates from this location */
 	{ "crt-ignore-err",        bind_parse_ignore_err,         1 }, /* set error IDs to ingore on verify depth == 0 */
@@ -8835,6 +8953,9 @@
 	{ "check-sni",               srv_parse_check_sni,          1, 1 }, /* set SNI */
 	{ "check-ssl",               srv_parse_check_ssl,          0, 1 }, /* enable SSL for health checks */
 	{ "ciphers",                 srv_parse_ciphers,            1, 1 }, /* select the cipher suite */
+#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
+	{ "ciphersuites",            srv_parse_ciphersuites,       1, 1 }, /* select the cipher suite */
+#endif
 	{ "crl-file",                srv_parse_crl_file,           1, 1 }, /* set certificate revocation list file use on server cert verify */
 	{ "crt",                     srv_parse_crt,                1, 1 }, /* set client certificate */
 	{ "force-sslv3",             srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
@@ -8890,6 +9011,10 @@
 	{ CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
 	{ CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
 	{ CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
+#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
+	{ CFG_GLOBAL, "ssl-default-bind-ciphersuites", ssl_parse_global_ciphersuites },
+	{ CFG_GLOBAL, "ssl-default-server-ciphersuites", ssl_parse_global_ciphersuites },
+#endif
 	{ 0, NULL, NULL },
 }};
 
@@ -8971,6 +9096,12 @@
 		global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers);
 	if (global_ssl.connect_default_ciphers)
 		global_ssl.connect_default_ciphers = strdup(global_ssl.connect_default_ciphers);
+#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
+	if (global_ssl.listen_default_ciphersuites)
+		global_ssl.listen_default_ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
+	if (global_ssl.connect_default_ciphersuites)
+		global_ssl.connect_default_ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
+#endif
 
 	xprt_register(XPRT_SSL, &ssl_sock);
 	SSL_library_init();