From: Mark Andrews Date: Thu, 5 Jun 2025 04:49:10 +0000 (+1000) Subject: Warn about deprecated DNSKEY and DS algorithms / digest types X-Git-Tag: v9.21.11~46^2~7 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cb6903c55e9ff6135a37c987fb6cee327967f0db;p=thirdparty%2Fbind9.git Warn about deprecated DNSKEY and DS algorithms / digest types 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. --- diff --git a/bin/dnssec/dnssec-dsfromkey.c b/bin/dnssec/dnssec-dsfromkey.c index 15acead6425..2d2583f58dd 100644 --- a/bin/dnssec/dnssec-dsfromkey.c +++ b/bin/dnssec/dnssec-dsfromkey.c @@ -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 " diff --git a/bin/dnssec/dnssec-keyfromlabel.c b/bin/dnssec/dnssec-keyfromlabel.c index 49ddb8ad7a6..34c49e81ab9 100644 --- a/bin/dnssec/dnssec-keyfromlabel.c +++ b/bin/dnssec/dnssec-keyfromlabel.c @@ -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) { diff --git a/bin/dnssec/dnssec-keygen.c b/bin/dnssec/dnssec-keygen.c index 9212f321858..283fc7eaffc 100644 --- a/bin/dnssec/dnssec-keygen.c +++ b/bin/dnssec/dnssec-keygen.c @@ -140,7 +140,8 @@ usage(void) { "statement\n"); fprintf(stderr, " -a :\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 :\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: diff --git a/bin/tests/system/checkconf/tests.sh b/bin/tests/system/checkconf/tests.sh index 57637cf0cf9..08d706a06e3 100644 --- a/bin/tests/system/checkconf/tests.sh +++ b/bin/tests/system/checkconf/tests.sh @@ -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" /dev/null || ret=1 diff --git a/lib/dns/dnssec.c b/lib/dns/dnssec.c index 414324ca087..3c6673eb56c 100644 --- a/lib/dns/dnssec.c +++ b/lib/dns/dnssec.c @@ -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) { diff --git a/lib/dns/include/dns/ds.h b/lib/dns/include/dns/ds.h index 734d93e6473..9f1e7938de9 100644 --- a/lib/dns/include/dns/ds.h +++ b/lib/dns/include/dns/ds.h @@ -33,6 +33,8 @@ #define DNS_DSDIGEST_SM3PRIVATE (9) #endif +#define DNS_DSDIGEST_MAX (255) + /* * Assuming SHA-384 digest type + maximal PRIVATEDNS name. */ diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 52c897c2a7b..c36e0b65a89 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -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) { diff --git a/lib/isccfg/kaspconf.c b/lib/isccfg/kaspconf.c index a7a71585a39..aba487a33b2 100644 --- a/lib/isccfg/kaspconf.c +++ b/lib/isccfg/kaspconf.c @@ -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;