]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Warn about deprecated DNSKEY and DS algorithms / digest types
authorMark Andrews <marka@isc.org>
Thu, 5 Jun 2025 04:49:10 +0000 (14:49 +1000)
committerMark Andrews <marka@isc.org>
Tue, 15 Jul 2025 13:53:57 +0000 (23:53 +1000)
DNSKEY algorithms RSASHA1 and RSASHA-NSEC3-SHA1 and DS digest type
SHA1 are deprecated.  Log when these are present in primary zone
files and when generating new DNSKEYs, DS and CDS records.

bin/dnssec/dnssec-dsfromkey.c
bin/dnssec/dnssec-keyfromlabel.c
bin/dnssec/dnssec-keygen.c
bin/tests/system/checkconf/tests.sh
lib/dns/dnssec.c
lib/dns/include/dns/ds.h
lib/dns/zone.c
lib/isccfg/kaspconf.c

index 15acead642587e5a8bf9833f7d5a0aa28171402b..2d2583f58dde86c08e9c330ee748e94bde156cdd 100644 (file)
@@ -318,6 +318,11 @@ emits(bool showall, bool cds, dns_rdata_t *rdata) {
 
        n = sizeof(dtype) / sizeof(dtype[0]);
        for (i = 0; i < n; i++) {
+               if (dtype[i] == DNS_DSDIGEST_SHA1) {
+                       fprintf(stderr,
+                               "WARNING: DS digest type %u is deprecated\n",
+                               i);
+               }
                if (dtype[i] != 0) {
                        emit(dtype[i], showall, cds, rdata);
                }
@@ -339,10 +344,10 @@ usage(void) {
        fprintf(stderr, "    %s [-h|-V]\n\n", isc_commandline_progname);
        fprintf(stderr, "Version: %s\n", PACKAGE_VERSION);
        fprintf(stderr, "Options:\n"
-                       "    -1: digest algorithm SHA-1\n"
+                       "    -1: digest algorithm SHA-1 (deprecated)\n"
                        "    -2: digest algorithm SHA-256\n"
-                       "    -a algorithm: digest algorithm (SHA-1, SHA-256 or "
-                       "SHA-384)\n"
+                       "    -a algorithm: digest algorithm (SHA-1 "
+                       "(deprecated), SHA-256 or SHA-384)\n"
                        "    -A: include all keys in DS set, not just KSKs (-f "
                        "only)\n"
                        "    -c class: rdata class for DS set (default IN) (-f "
index 49ddb8ad7a6dbd66af723b7f2ddf51132a3cd60b..34c49e81ab9dfc298ee10cd8388d035647e9a605 100644 (file)
@@ -59,8 +59,8 @@ usage(void) {
        fprintf(stderr, "    name: owner of the key\n");
        fprintf(stderr, "Other options:\n");
        fprintf(stderr, "    -a algorithm: \n"
-                       "        RSASHA1 |\n"
-                       "        NSEC3RSASHA1 |\n"
+                       "        RSASHA1 (deprecated) |\n"
+                       "        NSEC3RSASHA1 (deprecated) |\n"
                        "        RSASHA256 | RSASHA512 |\n"
                        "        ECDSAP256SHA256 | ECDSAP384SHA384 |\n"
                        "        ED25519 | ED448\n");
@@ -524,6 +524,21 @@ main(int argc, char **argv) {
                setpub = setact = true;
        }
 
+       switch (alg) {
+       case DST_ALG_RSASHA1:
+       case DST_ALG_NSEC3RSASHA1: {
+               char algstr[DNS_SECALG_FORMATSIZE];
+               dns_secalg_format(alg, algstr, sizeof(algstr));
+               fprintf(stderr,
+                       "WARNING: DNSKEY algorithm '%s' is deprecated. Please "
+                       "migrate to another algorithm\n",
+                       algstr);
+               break;
+       }
+       default:
+               break;
+       }
+
        rdclass = strtoclass(classname);
 
        if (directory == NULL) {
index 9212f321858464fd706d01819284050bf0ec7ad9..283fc7eaffc093e5d3cd6f363a1b5a4b606fb511 100644 (file)
@@ -140,7 +140,8 @@ usage(void) {
                        "statement\n");
        fprintf(stderr, "    -a <algorithm>:\n");
        if (!isc_crypto_fips_mode()) {
-               fprintf(stderr, "        RSASHA1 | NSEC3RSASHA1 |\n");
+               fprintf(stderr, "        RSASHA1 (deprecated) | NSEC3RSASHA1 "
+                               "(deprecated) |\n");
        }
        fprintf(stderr, "        RSASHA256 | RSASHA512 |\n");
        fprintf(stderr, "        ECDSAP256SHA256 | ECDSAP384SHA384 |\n");
@@ -148,10 +149,11 @@ usage(void) {
        fprintf(stderr, "    -3: use NSEC3-capable algorithm\n");
        fprintf(stderr, "    -b <key size in bits>:\n");
        if (!isc_crypto_fips_mode()) {
-               fprintf(stderr, "        RSASHA1:\t[%d..%d]\n", min_rsa,
-                       MAX_RSA);
-               fprintf(stderr, "        NSEC3RSASHA1:\t[%d..%d]\n", min_rsa,
-                       MAX_RSA);
+               fprintf(stderr, "        RSASHA1 (deprecated) :\t[%d..%d]\n",
+                       min_rsa, MAX_RSA);
+               fprintf(stderr,
+                       "        NSEC3RSASHA1 (deprecated) :\t[%d..%d]\n",
+                       min_rsa, MAX_RSA);
        }
        fprintf(stderr, "        RSASHA256:\t[%d..%d]\n", min_rsa, MAX_RSA);
        fprintf(stderr, "        RSASHA512:\t[%d..%d]\n", min_rsa, MAX_RSA);
@@ -457,6 +459,19 @@ keygen(keygen_ctx_t *ctx, isc_mem_t *mctx, int argc, char **argv) {
                ctx->setpub = ctx->setact = true;
        }
 
+       switch (ctx->alg) {
+       case DST_ALG_RSASHA1:
+       case DST_ALG_NSEC3RSASHA1:
+               dns_secalg_format(ctx->alg, algstr, sizeof(algstr));
+               fprintf(stderr,
+                       "WARNING: DNSKEY algorithm '%s' is deprecated. Please "
+                       "migrate to another algorithm\n",
+                       algstr);
+               break;
+       default:
+               break;
+       }
+
        switch (ctx->alg) {
        case DST_ALG_RSASHA1:
        case DST_ALG_NSEC3RSASHA1:
index 57637cf0cf9818b330362bfe87fb96824f6e1d51..08d706a06e326867b2861a0e651f925ba676f198 100644 (file)
@@ -606,7 +606,7 @@ if [ $RSASHA1_SUPPORTED = 0 ]; then
   expect=2
 else
   conf=kasp-bad-nsec3-iter.conf
-  expect=3
+  expect=5
 fi
 $CHECKCONF $conf >checkconf.out$n 2>&1 && ret=1
 grep "dnssec-policy: nsec3 iterations value 1 not allowed, must be zero" <checkconf.out$n >/dev/null || ret=1
index 414324ca08744e70e19d3bdbae5145643e07fba1..3c6673eb56c18315f95a0aa64a9f37b661357f61 100644 (file)
@@ -406,7 +406,7 @@ dns_dnssec_verify(const dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
        }
 
        /*
-        * NS, SOA and DNSSKEY records are signed by their owner.
+        * NS, SOA and DNSKEY records are signed by their owner.
         * DS records are signed by the parent.
         */
        switch (set->type) {
index 734d93e64732c3d839fbd94735c3ab26669fbaae..9f1e7938de95b8b98dd871671d73d60738c3869b 100644 (file)
@@ -33,6 +33,8 @@
 #define DNS_DSDIGEST_SM3PRIVATE           (9)
 #endif
 
+#define DNS_DSDIGEST_MAX (255)
+
 /*
  * Assuming SHA-384 digest type + maximal PRIVATEDNS name.
  */
index 52c897c2a7bbd35b46e7a909fc2b377eaec34a71..c36e0b65a899dfcf1b7893c78e2cbd1663393a32 100644 (file)
@@ -3416,6 +3416,8 @@ integrity_checks(dns_zone_t *zone, dns_db_t *db) {
        bool has_aaaa = false;
        int level;
        char namebuf[DNS_NAME_FORMATSIZE];
+       bool logged_algorithm[DST_MAX_ALGS];
+       bool logged_digest_type[DNS_DSDIGEST_MAX + 1];
 
        name = dns_fixedname_initname(&fixed);
        bottom = dns_fixedname_initname(&fixedbottom);
@@ -3444,6 +3446,52 @@ integrity_checks(dns_zone_t *zone, dns_db_t *db) {
 
                dns_dbiterator_pause(dbiterator);
 
+               /*
+                * Check for deprecated KEY algorithms
+                */
+               result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_key,
+                                            0, 0, &rdataset, NULL);
+               if (result != ISC_R_SUCCESS) {
+                       goto checkforns;
+               }
+
+               memset(logged_algorithm, 0, sizeof(logged_algorithm));
+               DNS_RDATASET_FOREACH (&rdataset) {
+                       dns_rdata_t rdata = DNS_RDATA_INIT;
+                       dns_rdata_key_t key;
+                       dns_rdataset_current(&rdataset, &rdata);
+
+                       result = dns_rdata_tostruct(&rdata, &key, NULL);
+                       RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+                       /*
+                        * If we ever deprecate a private algorithm use
+                        * dst_algorithm_fromdata() here.
+                        */
+                       switch (key.algorithm) {
+                       case DNS_KEYALG_RSASHA1:
+                       case DNS_KEYALG_NSEC3RSASHA1:
+                               if (!logged_algorithm[key.algorithm]) {
+                                       char algbuf[DNS_SECALG_FORMATSIZE];
+                                       dns_name_format(name, namebuf,
+                                                       sizeof(namebuf));
+                                       dns_secalg_format(key.algorithm, algbuf,
+                                                         sizeof(algbuf));
+                                       dnssec_log(zone, ISC_LOG_WARNING,
+                                                  "%s/KEY deprecated "
+                                                  "algorithm %u (%s)",
+                                                  namebuf, key.algorithm,
+                                                  algbuf);
+                                       logged_algorithm[key.algorithm] = true;
+                               }
+                               break;
+                       default:
+                               break;
+                       }
+               }
+               dns_rdataset_disassociate(&rdataset);
+
+       checkforns:
                /*
                 * Don't check the NS records at the origin.
                 */
@@ -3456,6 +3504,7 @@ integrity_checks(dns_zone_t *zone, dns_db_t *db) {
                if (result != ISC_R_SUCCESS) {
                        goto checkfords;
                }
+
                /*
                 * Remember bottom of zone due to NS.
                 */
@@ -3474,6 +3523,70 @@ integrity_checks(dns_zone_t *zone, dns_db_t *db) {
                        }
                }
                dns_rdataset_disassociate(&rdataset);
+
+               /*
+                * Check for deprecated DS digest types.
+                */
+               result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ds,
+                                            0, 0, &rdataset, NULL);
+               if (result != ISC_R_SUCCESS) {
+                       goto next;
+               }
+
+               memset(logged_algorithm, 0, sizeof(logged_algorithm));
+               memset(logged_digest_type, 0, sizeof(logged_digest_type));
+               DNS_RDATASET_FOREACH (&rdataset) {
+                       dns_rdata_t rdata = DNS_RDATA_INIT;
+                       dns_rdataset_current(&rdataset, &rdata);
+                       dns_rdata_ds_t ds;
+
+                       result = dns_rdata_tostruct(&rdata, &ds, NULL);
+                       RUNTIME_CHECK(result == ISC_R_SUCCESS);
+                       switch (ds.digest_type) {
+                       case DNS_DSDIGEST_SHA1:
+                               if (!logged_digest_type[ds.digest_type]) {
+                                       char algbuf[DNS_DSDIGEST_FORMATSIZE];
+                                       dns_name_format(name, namebuf,
+                                                       sizeof(namebuf));
+                                       dns_dsdigest_format(ds.digest_type,
+                                                           algbuf,
+                                                           sizeof(algbuf));
+                                       dnssec_log(zone, ISC_LOG_WARNING,
+                                                  "%s/DS deprecated digest "
+                                                  "type %u (%s)",
+                                                  namebuf, ds.digest_type,
+                                                  algbuf);
+                                       logged_digest_type[ds.digest_type] =
+                                               true;
+                               }
+                               break;
+                       }
+
+                       /*
+                        * If we ever deprecate a private algorithm use
+                        * dst_algorithm_fromdata() here.
+                        */
+                       switch (ds.algorithm) {
+                       case DNS_KEYALG_RSASHA1:
+                       case DNS_KEYALG_NSEC3RSASHA1:
+                               if (!logged_algorithm[ds.algorithm]) {
+                                       char algbuf[DNS_SECALG_FORMATSIZE];
+                                       dns_name_format(name, namebuf,
+                                                       sizeof(namebuf));
+                                       dns_secalg_format(ds.algorithm, algbuf,
+                                                         sizeof(algbuf));
+                                       dnssec_log(zone, ISC_LOG_WARNING,
+                                                  "%s/DS deprecated algorithm "
+                                                  "%u (%s)",
+                                                  namebuf, ds.algorithm,
+                                                  algbuf);
+                                       logged_algorithm[ds.algorithm] = true;
+                               }
+                               break;
+                       }
+               }
+               dns_rdataset_disassociate(&rdataset);
+
                goto next;
 
        checkfords:
@@ -3699,6 +3812,8 @@ zone_check_dnskeys(dns_zone_t *zone, dns_db_t *db) {
        dns_rdata_dnskey_t dnskey;
        dns_rdataset_t rdataset;
        isc_result_t result;
+       bool logged_algorithm[DST_MAX_ALGS] = { 0 };
+       bool alldeprecated = true;
 
        result = dns_db_findnode(db, &zone->origin, false, &node);
        if (result != ISC_R_SUCCESS) {
@@ -3714,6 +3829,7 @@ zone_check_dnskeys(dns_zone_t *zone, dns_db_t *db) {
        }
 
        DNS_RDATASET_FOREACH (&rdataset) {
+               char algbuf[DNS_SECALG_FORMATSIZE];
                dns_rdata_t rdata = DNS_RDATA_INIT;
                dns_rdataset_current(&rdataset, &rdata);
                result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
@@ -3756,9 +3872,35 @@ zone_check_dnskeys(dns_zone_t *zone, dns_db_t *db) {
                                   algorithm, dnskey.algorithm,
                                   dst_region_computeid(&r));
                }
+               switch (dnskey.algorithm) {
+               case DNS_KEYALG_RSAMD5:
+               case DNS_KEYALG_DSA:
+               case DNS_KEYALG_RSASHA1:
+               case DNS_KEYALG_NSEC3DSA:
+               case DNS_KEYALG_NSEC3RSASHA1:
+               case DNS_KEYALG_ECCGOST:
+                       if (!logged_algorithm[dnskey.algorithm]) {
+                               dns_secalg_format(dnskey.algorithm, algbuf,
+                                                 sizeof(algbuf));
+                               dnssec_log(zone, ISC_LOG_WARNING,
+                                          "deprecated DNSKEY algorithm found: "
+                                          "%u (%s)\n",
+                                          dnskey.algorithm, algbuf);
+                               logged_algorithm[dnskey.algorithm] = true;
+                       }
+                       break;
+               default:
+                       alldeprecated = false;
+                       break;
+               }
        }
        dns_rdataset_disassociate(&rdataset);
 
+       if (alldeprecated) {
+               dnssec_log(zone, ISC_LOG_WARNING,
+                          "all DNSKEY algorithms found are deprecated");
+       }
+
 cleanup:
        if (node != NULL) {
                dns_db_detachnode(db, &node);
@@ -22932,6 +23074,7 @@ dns_zone_cdscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version) {
         * record which must be by itself.
         */
        if (dns_rdataset_isassociated(&cds)) {
+               bool logged_digest_type[DNS_DSDIGEST_MAX + 1] = { 0 };
                bool delete = false;
                memset(algorithms, notexpected, sizeof(algorithms));
                DNS_RDATASET_FOREACH (&cds) {
@@ -22957,6 +23100,29 @@ dns_zone_cdscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version) {
                        }
 
                        CHECK(dns_rdata_tostruct(&crdata, &structcds, NULL));
+
+                       /*
+                        * Log deprecated CDS digest types.
+                        */
+                       switch (structcds.digest_type) {
+                       case DNS_DSDIGEST_SHA1:
+                               if (!logged_digest_type[structcds.digest_type])
+                               {
+                                       char algbuf[DNS_DSDIGEST_FORMATSIZE];
+                                       dns_dsdigest_format(
+                                               structcds.digest_type, algbuf,
+                                               sizeof(algbuf));
+                                       dnssec_log(zone, ISC_LOG_WARNING,
+                                                  "deprecated CDS digest type "
+                                                  "%u (%s)",
+                                                  structcds.digest_type,
+                                                  algbuf);
+                                       logged_digest_type[structcds.digest_type] =
+                                               true;
+                               }
+                               break;
+                       }
+
                        if (structcds.algorithm != DNS_KEYALG_PRIVATEDNS &&
                            structcds.algorithm != DNS_KEYALG_PRIVATEOID)
                        {
index a7a71585a394ed90bf73fbd9eebcc19d1ee1128c..aba487a33b215f184b76d26f0515a811a893dd4d 100644 (file)
@@ -250,6 +250,18 @@ cfg_kaspkey_fromconfig(const cfg_obj_t *config, dns_kasp_t *kasp,
                        goto cleanup;
                }
 
+               switch (key->algorithm) {
+               case DST_ALG_RSASHA1:
+               case DST_ALG_NSEC3RSASHA1:
+                       cfg_obj_log(obj, ISC_LOG_WARNING,
+                                   "dnssec-policy: DNSSEC algorithm %s is "
+                                   "deprecated",
+                                   alg.base);
+                       break;
+               default:
+                       break;
+               }
+
                obj = cfg_tuple_get(config, "length");
                if (cfg_obj_isuint32(obj)) {
                        uint32_t min, size;
@@ -428,6 +440,12 @@ add_digest(dns_kasp_t *kasp, const cfg_obj_t *digest) {
                            str);
                result = DST_R_UNSUPPORTEDALG;
        } else {
+               if (alg == DNS_DSDIGEST_SHA1) {
+                       cfg_obj_log(
+                               digest, ISC_LOG_WARNING,
+                               "dnssec-policy: deprecated CDS digest-type %s",
+                               str);
+               }
                dns_kasp_adddigest(kasp, alg);
        }
        return result;