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

@@ -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));