]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
DH-parameters loading support
authorArtem Boldariev <artem@boldariev.com>
Thu, 16 Sep 2021 11:48:30 +0000 (14:48 +0300)
committerArtem Boldariev <artem@boldariev.com>
Fri, 1 Oct 2021 12:50:43 +0000 (15:50 +0300)
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.

17 files changed:
bin/named/named.conf.rst
bin/named/server.c
bin/tests/system/checkconf/good-doh-tlsopts.conf
bin/tests/system/checkconf/good-dot-tlsopts.conf
bin/tests/system/doth/ns2/dhparam3072.pem [new file with mode: 0644]
bin/tests/system/doth/ns2/named.conf.in
doc/arm/reference.rst
doc/man/named.conf.5in
doc/misc/options
doc/misc/options.active
doc/misc/tls.grammar.rst
lib/isc/include/isc/tls.h
lib/isc/tls.c
lib/isccfg/namedconf.c
lib/ns/include/ns/listenlist.h
lib/ns/listenlist.c
util/copyrights

index 051f9bf3fee3681f276d8c96bf9bd790f3345d09..5d2c011f1cab65bc151f9ec891ac243ad270add7 100644 (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; ... };
index d73210f38ecef1146c72c8d77f5d33967dfbc4d4..aacc18845a738726427fa0bfde2861b092b19bd5 100644 (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)) {
index 90a2f957337235bce2b06c5b45f5d806832b2bcc..4ef244a01e945d35c7004a3f7d2fd4b328aaa640 100644 (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 {
index 3552eef0aa4411c40363cd460fb71bd88fecc501..62d4b8066d5f6a7794dbaadca8f54dc594972872 100644 (file)
@@ -13,6 +13,7 @@ tls local-tls {
        protocols { TLSv1.2; };
        key-file "key.pem";
        cert-file "cert.pem";
+       dhparam-file "dhparam.pem";
 };
 
 options {
diff --git a/bin/tests/system/doth/ns2/dhparam3072.pem b/bin/tests/system/doth/ns2/dhparam3072.pem
new file mode 100644 (file)
index 0000000..9c2e0aa
--- /dev/null
@@ -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-----
index 0a77cf99520c695494ffe3e2ec694fc65bf33bcd..9d747c9f6aaf0b56ba64a14c3bcd06f035706a24 100644 (file)
@@ -18,6 +18,7 @@ controls {
 tls local {
        key-file "key.pem";
        cert-file "cert.pem";
+       dhparam-file "dhparam3072.pem";
 };
 
 http local {
index b36db11467ec61dc4a0b8f5ac6a143ab82204c86..7b61d2862a7fad6ad75ed46dee487a53fd930ce5 100644 (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.
 
index 0cce71b6771c3611489b2a9193b764fda014aeff..1c6d7c90757d8030d53570fd70b56d8dbf0105df 100644 (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; ... };
index aa89cd4ed18a3aaf3ec601e34c0acf9bdafbf539..72b32fb9f40d31cb1bf769a4a6d9c21b9d8f500c 100644 (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>; ... };
index a745dc632734d31fd247d2d410f5d549cffb1017..b2fecd6f69ec17ef9080ca313bf1108d2973b53e 100644 (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>; ... };
index c0b5a48819f9575d92cc15286a71cf28ff8d62cc..60035e5ae8438a5a89d92eca20069df838bcc8ba 100644 (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>; ... };
index 452079564466bccc6aff9dab9a2028e40879fcc6..594d40bf4d7b329121bea6664a4643d480f75a3a 100644 (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);
 /*%<
index 76fbe28690f1446871e14ee1f9ed862476e9ad47..1fc1362a13d2a7e93578aeb1ccea045d04ae0175 100644 (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;
index 1427d4fd5e127bd2741f1d8b590d901eb3f3a01f..63c66da7b00c1d66c6fe5e9ea06d2dac89451acd 100644 (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 }
index ae13f6732758ec3e9b4ddc40f0b5ae4447cadd0a..2fd341318e83fa2f17fa2a019a0f2973aeb77b2e 100644 (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;
 
 /***
index 92ffac7979f4d8045ac5d3c84486ad9f03e7a3e7..001821246e0ef195c2b6960d39fc14e768021d09 100644 (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));
index 2d0d2faf534a736d197f241aab8b665f3ebbe209..0e24a2361dda1cba03fb36149070429aa8ccd2db 100644 (file)
 ./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