DH-parameters loading support

This commit adds support for loading DH-parameters (Diffie-Hellman
parameters) via the new "dhparam-file" option within "tls" clause. In
particular, Diffie-Hellman parameters are needed to enable the range
of forward-secrecy enabled cyphers for TLSv1.2, which are getting
silently disabled otherwise.
This commit is contained in:
Artem Boldariev 2021-09-16 14:48:30 +03:00
parent 992f815770
commit f2ae4c8480
17 changed files with 126 additions and 10 deletions

View file

@ -564,7 +564,7 @@ TLS
ca-file quoted_string;
cert-file quoted_string;
ciphers string; // experimental
dh-param quoted_string; // experimental
dhparam-file quoted_string;
hostname quoted_string;
key-file quoted_string;
protocols { string; ... };

View file

@ -11023,7 +11023,7 @@ listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config,
const cfg_obj_t *http_server = NULL;
in_port_t port = 0;
isc_dscp_t dscp = -1;
const char *key = NULL, *cert = NULL;
const char *key = NULL, *cert = NULL, *dhparam_file = NULL;
bool do_tls = false, no_tls = false, http = false;
ns_listenelt_t *delt = NULL;
uint32_t tls_protos = 0;
@ -11043,7 +11043,8 @@ listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config,
} else if (strcasecmp(tlsname, "ephemeral") == 0) {
do_tls = true;
} else {
const cfg_obj_t *keyobj = NULL, *certobj = NULL;
const cfg_obj_t *keyobj = NULL, *certobj = NULL,
*dhparam_obj = NULL;
const cfg_obj_t *tlsmap = NULL;
const cfg_obj_t *tls_proto_list = NULL;
@ -11084,12 +11085,18 @@ listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config,
tls_protos |= ver;
}
}
if (cfg_map_get(tlsmap, "dhparam-file", &dhparam_obj) ==
ISC_R_SUCCESS) {
dhparam_file = cfg_obj_asstring(dhparam_obj);
}
}
}
tls_params = (ns_listen_tls_params_t){ .key = key,
.cert = cert,
.protocols = tls_protos };
.protocols = tls_protos,
.dhparam_file = dhparam_file };
httpobj = cfg_tuple_get(ltup, "http");
if (httpobj != NULL && cfg_obj_isstring(httpobj)) {

View file

@ -13,6 +13,7 @@ tls local-tls {
protocols { TLSv1.2; };
key-file "key.pem";
cert-file "cert.pem";
dhparam-file "dhparam.pem";
};
http local-http-server {

View file

@ -13,6 +13,7 @@ tls local-tls {
protocols { TLSv1.2; };
key-file "key.pem";
cert-file "cert.pem";
dhparam-file "dhparam.pem";
};
options {

View file

@ -0,0 +1,11 @@
-----BEGIN DH PARAMETERS-----
MIIBiAKCAYEA5D/Oioe+G+EMf/9RVxmcV4rZAtqZpVTFHcX0ZulvdiQGCQmopm6K
3+0uoU2J6WVMjhna5nHD2NO9miRDI/jIxX9g9k6PedSB4o3fSTtkAnGtUbB8S+Ab
EHtWfd7FTES8P1n16HN7BfPXVbP8zTcK+jO63KdQoxueYoETcrw0Myi9Lm8ri8os
O4oQ+XAH7GzZ60bcYV9jge0XIRUGVnYZDjWMlnwMvZyjLivxKXTC9HPNA6FF1/0H
0LPhsfjdoLNsVHFzfQz7QELMfHbTd0C8y0UMDQw9FqUp0esHZ5gsTlqnDHp2ZHoR
JDfNl4yVO5Gv4HiFJ0NSdggefhESU3FRAOhMmUkctOCxk5hyPqGMsvofOajY2MBp
eCffrKuAU6/dGUeq8inwrZlAMIZ20WyskHmbHnc4DXo2Uo6xSZo3xyEq1ofXXwTZ
vPw4e12so3RJAT2a8UsHf7DG1tH+9ke7HCAJQWxUizRFRsMi1Nl/7ikS4f3zgIbX
GKz9+uk5eS6jAgEC
-----END DH PARAMETERS-----

View file

@ -18,6 +18,7 @@ controls {
tls local {
key-file "key.pem";
cert-file "cert.pem";
dhparam-file "dhparam3072.pem";
};
http local {

View file

@ -293,7 +293,7 @@ The following statements are supported:
Declares communication channels to get access to ``named`` statistics.
``tls``
Specifies configuration information for a TLS connection, including a ``key-file``, ``cert-file``, ``ca-file``, ``hostname``, and ``protocols``.
Specifies configuration information for a TLS connection, including a ``key-file``, ``cert-file``, ``ca-file``, ``dhparam-file``, ``hostname``, and ``protocols``.
``http``
Specifies configuration information for an HTTP connection, including ``endponts``, ``listener-clients`` and ``streams-per-connection``.
@ -4769,6 +4769,13 @@ The following options can be specified in a ``tls`` statement:
``ca-file``
Path to a file containing trusted TLS certificates.
``dhparam-file``
Path to a file containing Diffie-Hellman parameters,
which is needed to enable the cipher suites depending on the
Diffie-Hellman ephemeral key exchange (DHE). Having these parameters
specified is essential for enabling perfect forward secrecy capable
ciphers in TLSv1.2.
``hostname``
The hostname associated with the certificate.

View file

@ -655,7 +655,7 @@ tls string {
ca\-file quoted_string;
cert\-file quoted_string;
ciphers string; // experimental
dh\-param quoted_string; // experimental
dhparam\-file quoted_string;
hostname quoted_string;
key\-file quoted_string;
protocols { string; ... };

View file

@ -460,7 +460,7 @@ tls <string> {
ca-file <quoted_string>;
cert-file <quoted_string>;
ciphers <string>; // experimental
dh-param <quoted_string>; // experimental
dhparam-file <quoted_string>;
hostname <quoted_string>;
key-file <quoted_string>;
protocols { <string>; ... };

View file

@ -457,7 +457,7 @@ tls <string> {
ca-file <quoted_string>;
cert-file <quoted_string>;
ciphers <string>; // experimental
dh-param <quoted_string>; // experimental
dhparam-file <quoted_string>;
hostname <quoted_string>;
key-file <quoted_string>;
protocols { <string>; ... };

View file

@ -4,7 +4,7 @@
ca-file <quoted_string>;
cert-file <quoted_string>;
ciphers <string>; // experimental
dh-param <quoted_string>; // experimental
dhparam-file <quoted_string>;
hostname <quoted_string>;
key-file <quoted_string>;
protocols { <string>; ... };

View file

@ -84,6 +84,17 @@ isc_tls_protocol_name_to_version(const char *name);
*\li 'name' != NULL.
*/
bool
isc_tlsctx_load_dhparams(isc_tlsctx_t *ctx, const char *dhparams_file);
/*%<
* Load Diffie-Hellman parameters file and apply it to the given TLS context
* 'ctx'.
*
* Requires:
* \li 'ctx' != NULL;
* \li 'dhaprams_file' a valid pointer to a non empty string.
*/
isc_tls_t *
isc_tls_create(isc_tlsctx_t *ctx);
/*%<

View file

@ -17,6 +17,7 @@
#include <openssl/bn.h>
#include <openssl/conf.h>
#include <openssl/dh.h>
#include <openssl/err.h>
#include <openssl/opensslv.h>
#include <openssl/rand.h>
@ -460,6 +461,71 @@ isc_tlsctx_set_protocols(isc_tlsctx_t *ctx, const uint32_t tls_versions) {
(void)SSL_CTX_clear_options(ctx, clear_options);
}
bool
isc_tlsctx_load_dhparams(isc_tlsctx_t *ctx, const char *dhparams_file) {
REQUIRE(ctx != NULL);
REQUIRE(dhparams_file != NULL);
REQUIRE(*dhparams_file != '\0');
#ifdef SSL_CTX_set_tmp_dh
/* OpenSSL < 3.0 */
DH *dh = NULL;
FILE *paramfile;
paramfile = fopen(dhparams_file, "r");
if (paramfile) {
int check = 0;
dh = PEM_read_DHparams(paramfile, NULL, NULL, NULL);
fclose(paramfile);
if (dh == NULL) {
return (false);
} else if (DH_check(dh, &check) != 1 || check != 0) {
DH_free(dh);
return (false);
}
} else {
return (false);
}
if (SSL_CTX_set_tmp_dh(ctx, dh) != 1) {
DH_free(dh);
return (false);
}
DH_free(dh);
#else
/* OpenSSL >= 3.0: SSL_CTX_set_tmp_dh() is deprecated in OpenSSL 3.0 */
EVP_PKEY *dh = NULL;
BIO *bio = NULL;
bio = BIO_new_file(dhparams_file, "r");
if (bio == NULL) {
return (false);
}
dh = PEM_read_bio_Parameters(bio, NULL);
if (dh == NULL) {
BIO_free(bio);
return (false);
}
if (SSL_CTX_set0_tmp_dh_pkey(ctx, dh) != 1) {
BIO_free(bio);
EVP_PKEY_free(dh);
return (false);
}
/* No need to call EVP_PKEY_free(dh) as the "dh" is owned by the
* SSL context at this point. */
BIO_free(bio);
#endif
return (true);
}
isc_tls_t *
isc_tls_create(isc_tlsctx_t *ctx) {
isc_tls_t *newctx = NULL;

View file

@ -3887,7 +3887,7 @@ static cfg_clausedef_t tls_clauses[] = {
{ "cert-file", &cfg_type_qstring, 0 },
{ "ca-file", &cfg_type_qstring, 0 },
{ "hostname", &cfg_type_qstring, 0 },
{ "dh-param", &cfg_type_qstring, CFG_CLAUSEFLAG_EXPERIMENTAL },
{ "dhparam-file", &cfg_type_qstring, 0 },
{ "protocols", &cfg_type_tlsprotos, 0 },
{ "ciphers", &cfg_type_astring, CFG_CLAUSEFLAG_EXPERIMENTAL },
{ NULL, NULL, 0 }

View file

@ -63,6 +63,7 @@ typedef struct ns_listen_tls_params {
const char *key;
const char *cert;
uint32_t protocols;
const char *dhparam_file;
} ns_listen_tls_params_t;
/***

View file

@ -46,6 +46,15 @@ ns_listenelt_create(isc_mem_t *mctx, in_port_t port, isc_dscp_t dscp,
if (tls_params->protocols != 0) {
isc_tlsctx_set_protocols(sslctx, tls_params->protocols);
}
if (tls_params->dhparam_file != NULL) {
if (!isc_tlsctx_load_dhparams(sslctx,
tls_params->dhparam_file))
{
isc_tlsctx_free(&sslctx);
return (ISC_R_FAILURE);
}
}
}
elt = isc_mem_get(mctx, sizeof(*elt));

View file

@ -276,6 +276,7 @@
./bin/tests/system/doth/clean.sh SH 2020,2021
./bin/tests/system/doth/example.axfr.good X 2021
./bin/tests/system/doth/ns2/cert.pem X 2021
./bin/tests/system/doth/ns2/dhparam3072.pem X 2021
./bin/tests/system/doth/ns2/key.pem X 2021
./bin/tests/system/doth/setup.sh SH 2021
./bin/tests/system/doth/stress_http_quota.py PYTHON-BIN 2021