]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Future: DS private algorithm support
authorMark Andrews <marka@isc.org>
Wed, 21 May 2025 00:13:04 +0000 (10:13 +1000)
committerMark Andrews <marka@isc.org>
Wed, 18 Jun 2025 21:15:20 +0000 (07:15 +1000)
Add support for proposed DS digest types that encode the private
algorithm identifier at the start of the DS digest as is done for
DNSKEY and RRSIG.  This allows a DS record to identify the specific
DNSSEC algorithm, rather than a set of algorithms, when the algorithm
field is set to PRIVATEDNS or PRIVATEOID.

17 files changed:
bin/dnssec/dnssec-cds.c
bin/dnssec/dnssec-dsfromkey.c
bin/dnssec/dnssec-ksr.c
bin/dnssec/dnssec-signzone.c
bin/named/server.c
bin/tests/system/feature-test.c
lib/dns/dnssec.c
lib/dns/ds.c
lib/dns/dst_api.c
lib/dns/include/dns/ds.h
lib/dns/keytable.c
lib/dns/rcode.c
lib/dns/validator.c
lib/dns/view.c
lib/dns/zone.c
lib/dns/zoneverify.c
tests/dns/keytable_test.c

index 3c7db4d0eda1359e6cfcde8010235225fa3a57c5..1d8c25185a678a17cbcb1d23c15260d96ecd1c61 100644 (file)
@@ -482,7 +482,7 @@ match_key_dsset(keyinfo_t *ki, dns_rdataset_t *dsset, strictness_t strictness) {
                }
 
                result = dns_ds_buildrdata(name, &ki->rdata, ds.digest_type,
-                                          dsbuf, &newdsrdata);
+                                          dsbuf, sizeof(dsbuf), &newdsrdata);
                if (result != ISC_R_SUCCESS) {
                        vbprintf(3,
                                 "dns_ds_buildrdata("
@@ -769,7 +769,7 @@ ds_from_cdnskey(isc_buffer_t *buf, dns_rdata_t *ds, dns_dsdigest_t dt,
                return ISC_R_NOSPACE;
        }
 
-       result = dns_ds_buildrdata(name, cdnskey, dt, r.base, ds);
+       result = dns_ds_buildrdata(name, cdnskey, dt, r.base, r.length, ds);
        if (result == ISC_R_SUCCESS) {
                isc_buffer_add(buf, DNS_DS_BUFFERSIZE);
        }
index 6fd0d35dcb3e2b0d6ad1637bf8e5e482f0706ac9..15acead642587e5a8bf9833f7d5a0aa28171402b 100644 (file)
@@ -270,7 +270,7 @@ emit(dns_dsdigest_t dt, bool showall, bool cds, dns_rdata_t *rdata) {
                return;
        }
 
-       result = dns_ds_buildrdata(name, rdata, dt, buf, &ds);
+       result = dns_ds_buildrdata(name, rdata, dt, buf, sizeof(buf), &ds);
        if (result != ISC_R_SUCCESS) {
                fatal("can't build record");
        }
index b4a4e5736abf0ab6d06b4ec95c1eebb66dfe3ebd..14def7621935bee5017badfe0e13dedbda17bd73 100644 (file)
@@ -851,7 +851,7 @@ get_keymaterial(ksr_ctx_t *ksr, dns_kasp_t *kasp, isc_stdtime_t inception,
                        dns_rdata_init(rdata2);
 
                        CHECK(dns_ds_buildrdata(name, rdata, alg->digest,
-                                               cdsbuf, &cds));
+                                               cdsbuf, sizeof(cdsbuf), &cds));
                        cds.type = dns_rdatatype_cds;
                        dns_rdata_toregion(&cds, &rcds);
                        isc_buffer_allocate(mctx, &newbuf2, rcds.length);
index e2a01429e018883489d338ba8c1a659f3b4e43ee..4ceb483bde13d16ccfdf16f245912e1066b4080c 100644 (file)
@@ -1073,7 +1073,7 @@ loadds(dns_name_t *name, uint32_t ttl, dns_rdataset_t *dsset) {
                dns_rdata_t ds = DNS_RDATA_INIT;
                dns_rdataset_current(&keyset, &key);
                result = dns_ds_buildrdata(name, &key, DNS_DSDIGEST_SHA256,
-                                          dsbuf, &ds);
+                                          dsbuf, sizeof(dsbuf), &ds);
                check_result(result, "dns_ds_buildrdata");
 
                dns_difftuple_create(mctx, DNS_DIFFOP_ADDRESIGN, name, ttl, &ds,
@@ -3055,7 +3055,7 @@ writeset(const char *prefix, dns_rdatatype_t type) {
                if (type != dns_rdatatype_dnskey) {
                        result = dns_ds_buildrdata(gorigin, &rdata,
                                                   DNS_DSDIGEST_SHA256, dsbuf,
-                                                  &ds);
+                                                  sizeof(dsbuf), &ds);
                        check_result(result, "dns_ds_buildrdata");
                        dns_difftuple_create(mctx, DNS_DIFFOP_ADDRESIGN, name,
                                             0, &ds, &tuple);
index 5a333cc937af2019bd08eba4566de048fdc2e269..6cbfc245c8c2cba5cbfda60417eb77ae5f5ec5b5 100644 (file)
@@ -677,7 +677,7 @@ cleanup:
 
 static isc_result_t
 ta_fromconfig(const cfg_obj_t *key, bool *initialp, const char **namestrp,
-             unsigned char *digest, dns_rdata_ds_t *ds) {
+             unsigned char *digest, size_t digest_len, dns_rdata_ds_t *ds) {
        isc_result_t result;
        dns_rdata_dnskey_t keystruct;
        dns_rdata_t rdata = DNS_RDATA_INIT;
@@ -805,7 +805,7 @@ ta_fromconfig(const cfg_obj_t *key, bool *initialp, const char **namestrp,
                                           keystruct.common.rdtype, &keystruct,
                                           &rrdatabuf));
                CHECK(dns_ds_fromkeyrdata(name, &rdata, DNS_DSDIGEST_SHA256,
-                                         digest, ds));
+                                         digest, digest_len, ds));
                break;
 
        case INIT_DS:
@@ -844,6 +844,20 @@ ta_fromconfig(const cfg_obj_t *key, bool *initialp, const char **namestrp,
                                CHECK(ISC_R_UNEXPECTEDEND);
                        }
                        break;
+#if defined(DNS_DSDIGEST_SHA256PRIVATE)
+               case DNS_DSDIGEST_SHA256PRIVATE:
+                       if (r.length < ISC_SHA256_DIGESTLENGTH) {
+                               CHECK(ISC_R_UNEXPECTEDEND);
+                       }
+                       break;
+#endif
+#if defined(DNS_DSDIGEST_SHA384PRIVATE)
+               case DNS_DSDIGEST_SHA384PRIVATE:
+                       if (r.length < ISC_SHA384_DIGESTLENGTH) {
+                               CHECK(ISC_R_UNEXPECTEDEND);
+                       }
+                       break;
+#endif
                default:
                        cfg_obj_log(key, ISC_LOG_ERROR,
                                    "key '%s': "
@@ -854,12 +868,46 @@ ta_fromconfig(const cfg_obj_t *key, bool *initialp, const char **namestrp,
                        break;
                }
 
+               if (r.length > digest_len) {
+                       CHECK(ISC_R_NOSPACE);
+               }
                ds->length = r.length;
                ds->digest = digest;
-               INSIST(r.length <= ISC_MAX_MD_SIZE);
                memmove(ds->digest, r.base, r.length);
 
-               if (!dst_algorithm_supported(ds->algorithm)) {
+               algorithm = ds->algorithm;
+
+#if defined(DNS_DSDIGEST_SHA256PRIVATE) && defined(DNS_DSDIGEST_SHA384PRIVATE)
+               /*
+                * Extract the private algorithm from the start
+                * of the hash field.
+                */
+               switch (ds->digest_type) {
+               /*
+                * Digest types that do not encode the private DNSSEC algorithm
+                * at the start of the digest field.
+                */
+               case DNS_DSDIGEST_SHA1:
+               case DNS_DSDIGEST_SHA256:
+               case DNS_DSDIGEST_SHA384:
+                       break;
+               /*
+                * Digest types that encode the private DNSSEC algorithm
+                * at the start of the digest field.
+                */
+               case DNS_DSDIGEST_SHA256PRIVATE:
+               case DNS_DSDIGEST_SHA384PRIVATE:
+                       algorithm = dst_algorithm_fromdata(
+                               ds->algorithm, ds->digest, ds->length);
+                       break;
+               /*
+                * Unknown digest types.
+                */
+               default:
+                       break;
+               }
+#endif
+               if (!dst_algorithm_supported(algorithm)) {
                        CHECK(DST_R_UNSUPPORTEDALG);
                }
 
@@ -902,10 +950,11 @@ process_key(const cfg_obj_t *key, dns_keytable_t *secroots,
        dns_rdata_ds_t ds;
        isc_result_t result;
        bool initializing = managed;
-       unsigned char digest[ISC_MAX_MD_SIZE];
+       unsigned char digest[DNS_DS_BUFFERSIZE];
        isc_buffer_t b;
 
-       result = ta_fromconfig(key, &initializing, &namestr, digest, &ds);
+       result = ta_fromconfig(key, &initializing, &namestr, digest,
+                              sizeof(digest), &ds);
 
        switch (result) {
        case ISC_R_SUCCESS:
index 8f58e133f11abfb0ff381b5f79dd984fc897445b..73d0e73e660490bf893ecf9831a37981da943675 100644 (file)
@@ -30,6 +30,7 @@
 #include <isc/net.h>
 #include <isc/util.h>
 
+#include <dns/ds.h>
 #include <dns/edns.h>
 #include <dns/lib.h>
 
@@ -42,6 +43,7 @@ usage(void) {
        fprintf(stderr, "\t--edns-version\n");
        fprintf(stderr, "\t--enable-dnstap\n");
        fprintf(stderr, "\t--enable-querytrace\n");
+       fprintf(stderr, "\t--extended-ds-digest\n");
        fprintf(stderr, "\t--fips-provider\n");
        fprintf(stderr, "\t--gethostname\n");
        fprintf(stderr, "\t--gssapi\n");
@@ -93,6 +95,14 @@ main(int argc, char **argv) {
 #endif /* ifdef WANT_QUERYTRACE */
        }
 
+       if (strcasecmp(argv[1], "--extended-ds-digest") == 0) {
+#if defined(DNS_DSDIGEST_SHA256PRIVATE) && defined(DNS_DSDIGEST_SHA384PRIVATE)
+               return 0;
+#else
+               return 1;
+#endif
+       }
+
        if (strcasecmp(argv[1], "--fips-provider") == 0) {
 #if OPENSSL_VERSION_NUMBER >= 0x30000000L
                OSSL_PROVIDER *fips = OSSL_PROVIDER_load(NULL, "fips");
index 6e73674d2b5e331774259c519d13ff974a339093..993168e3dc79772b5805420618ecde50700cc635 100644 (file)
@@ -1841,7 +1841,8 @@ add_cds(dns_dnsseckey_t *key, dns_rdata_t *keyrdata, const char *keystr,
        dns_rdata_t cdsrdata = DNS_RDATA_INIT;
        dns_name_t *origin = dst_key_name(key->key);
 
-       r = dns_ds_buildrdata(origin, keyrdata, digesttype, dsbuf, &cdsrdata);
+       r = dns_ds_buildrdata(origin, keyrdata, digesttype, dsbuf,
+                             sizeof(dsbuf), &cdsrdata);
        if (r != ISC_R_SUCCESS) {
                char algbuf[DNS_DSDIGEST_FORMATSIZE];
                dns_dsdigest_format(digesttype, algbuf,
@@ -1876,7 +1877,8 @@ delete_cds(dns_dnsseckey_t *key, dns_rdata_t *keyrdata, const char *keystr,
        dns_rdata_t cdsrdata = DNS_RDATA_INIT;
        dns_name_t *origin = dst_key_name(key->key);
 
-       r = dns_ds_buildrdata(origin, keyrdata, digesttype, dsbuf, &cdsrdata);
+       r = dns_ds_buildrdata(origin, keyrdata, digesttype, dsbuf,
+                             sizeof(dsbuf), &cdsrdata);
        if (r != ISC_R_SUCCESS) {
                return r;
        }
@@ -2364,7 +2366,7 @@ dns_dnssec_matchdskey(dns_name_t *name, dns_rdata_t *dsrdata,
                }
 
                result = dns_ds_buildrdata(name, keyrdata, ds.digest_type, buf,
-                                          &newdsrdata);
+                                          sizeof(buf), &newdsrdata);
                if (result != ISC_R_SUCCESS) {
                        continue;
                }
index c56691bf19aab6e775c95ed6cdb60d85ddc98583..773a880127a0a1214ae1e6879cfceb8e19e1fdcd 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <dns/ds.h>
 #include <dns/fixedname.h>
+#include <dns/keyvalues.h>
 #include <dns/name.h>
 #include <dns/rdata.h>
 #include <dns/rdatastruct.h>
 isc_result_t
 dns_ds_fromkeyrdata(const dns_name_t *owner, dns_rdata_t *key,
                    dns_dsdigest_t digest_type, unsigned char *digest,
-                   dns_rdata_ds_t *dsrdata) {
+                   size_t len, dns_rdata_ds_t *dsrdata) {
        isc_result_t result;
        dns_fixedname_t fname;
        dns_name_t *name;
-       unsigned int digestlen;
+       unsigned int digestlen = 0;
+       unsigned int privatelen = 0;
        isc_region_t r;
        isc_md_t *md;
        const isc_md_type_t *md_type = NULL;
@@ -44,6 +46,7 @@ dns_ds_fromkeyrdata(const dns_name_t *owner, dns_rdata_t *key,
        REQUIRE(key != NULL);
        REQUIRE(key->type == dns_rdatatype_dnskey ||
                key->type == dns_rdatatype_cdnskey);
+       REQUIRE(digest != NULL);
 
        if (!dst_ds_digest_supported(digest_type)) {
                return ISC_R_NOTIMPLEMENTED;
@@ -55,10 +58,16 @@ dns_ds_fromkeyrdata(const dns_name_t *owner, dns_rdata_t *key,
                break;
 
        case DNS_DSDIGEST_SHA384:
+#ifdef DNS_DSDIGEST_SHA384PRIVATE
+       case DNS_DSDIGEST_SHA384PRIVATE:
+#endif
                md_type = ISC_MD_SHA384;
                break;
 
        case DNS_DSDIGEST_SHA256:
+#ifdef DNS_DSDIGEST_SHA256PRIVATE
+       case DNS_DSDIGEST_SHA256PRIVATE:
+#endif
                md_type = ISC_MD_SHA256;
                break;
 
@@ -91,6 +100,64 @@ dns_ds_fromkeyrdata(const dns_name_t *owner, dns_rdata_t *key,
                goto end;
        }
 
+#if defined(DNS_DSDIGEST_SHA256PRIVATE) && defined(DNS_DSDIGEST_SHA384PRIVATE)
+       /*
+        * Insert PRIVATE algorithm identify at start of digest.
+        */
+       switch (digest_type) {
+       case DNS_DSDIGEST_SHA1:
+       case DNS_DSDIGEST_SHA256:
+       case DNS_DSDIGEST_SHA384:
+               break;
+       case DNS_DSDIGEST_SHA256PRIVATE:
+       case DNS_DSDIGEST_SHA384PRIVATE:
+               switch (r.base[3]) {
+               case DNS_KEYALG_PRIVATEDNS: {
+                       isc_region_t r2 = r;
+                       INSIST(r2.length >= 5);
+                       isc_region_consume(&r2, 4);
+                       dns_name_fromregion(name, &r2);
+                       dns_name_toregion(name, &r2);
+                       privatelen = r2.length;
+                       if (r2.length > len) {
+                               result = ISC_R_NOSPACE;
+                               goto end;
+                       }
+                       memmove(digest, r2.base, privatelen);
+                       digest += privatelen;
+                       len -= privatelen;
+                       break;
+               }
+               case DNS_KEYALG_PRIVATEOID: {
+                       isc_region_t r2 = r;
+                       INSIST(r2.length >= 5);
+                       isc_region_consume(&r2, 4);
+                       privatelen = r2.base[0] + 1;
+                       if (r2.base[0] > len) {
+                               result = ISC_R_NOSPACE;
+                               goto end;
+                       }
+                       INSIST(r2.length >= privatelen);
+                       memmove(digest, r2.base, privatelen);
+                       digest += privatelen;
+                       len -= privatelen;
+                       break;
+               }
+               default:
+                       break;
+               }
+               break;
+       default:
+               break;
+       }
+#endif
+
+       size_t mdsize = isc_md_get_size(md);
+       if (mdsize > len) {
+               result = ISC_R_NOSPACE;
+               goto end;
+       }
+
        result = isc_md_final(md, digest, &digestlen);
        if (result != ISC_R_SUCCESS) {
                goto end;
@@ -102,8 +169,8 @@ dns_ds_fromkeyrdata(const dns_name_t *owner, dns_rdata_t *key,
        dsrdata->algorithm = r.base[3];
        dsrdata->key_tag = dst_region_computeid(&r);
        dsrdata->digest_type = digest_type;
-       dsrdata->digest = digest;
-       dsrdata->length = digestlen;
+       dsrdata->digest = digest - privatelen;
+       dsrdata->length = digestlen + privatelen;
 
 end:
        isc_md_free(md);
@@ -112,14 +179,14 @@ end:
 
 isc_result_t
 dns_ds_buildrdata(dns_name_t *owner, dns_rdata_t *key,
-                 dns_dsdigest_t digest_type, unsigned char *buffer,
+                 dns_dsdigest_t digest_type, unsigned char *buffer, size_t len,
                  dns_rdata_t *rdata) {
        isc_result_t result;
        unsigned char digest[ISC_MAX_MD_SIZE];
        dns_rdata_ds_t ds;
        isc_buffer_t b;
 
-       result = dns_ds_fromkeyrdata(owner, key, digest_type, digest, &ds);
+       result = dns_ds_fromkeyrdata(owner, key, digest_type, digest, len, &ds);
        if (result != ISC_R_SUCCESS) {
                return result;
        }
index 19fd35d0ae7720d5e4437c88219490ab40368343..4f8f9dc95831b094469e088ee093184257671a39 100644 (file)
@@ -233,7 +233,13 @@ dst_algorithm_supported(unsigned int alg) {
 bool
 dst_ds_digest_supported(unsigned int digest_type) {
        return digest_type == DNS_DSDIGEST_SHA1 ||
+#if defined(DNS_DSDIGEST_SHA256PRIVATE)
+              digest_type == DNS_DSDIGEST_SHA256PRIVATE ||
+#endif
               digest_type == DNS_DSDIGEST_SHA256 ||
+#if defined(DNS_DSDIGEST_SHA256PRIVATE)
+              digest_type == DNS_DSDIGEST_SHA384PRIVATE ||
+#endif
               digest_type == DNS_DSDIGEST_SHA384;
 }
 
index a1cad49683312b793349da668ad2e3d503b515ae..734d93e64732c3d839fbd94735c3ab26669fbaae 100644 (file)
 #define DNS_DSDIGEST_GOST2012 (5)
 #define DNS_DSDIGEST_SM3      (6)
 
+#if TEST_PRIVATE_DSDIGEST
 /*
- * Assuming SHA-384 digest type.
+ * Possible future digest types that encode the PRIVATEDNS and
+ * PRIVATEOID identifiers before the cryptographic digest value.
  */
-#define DNS_DS_BUFFERSIZE (52)
+#define DNS_DSDIGEST_SHA256PRIVATE (7)
+#define DNS_DSDIGEST_SHA384PRIVATE (8)
+#define DNS_DSDIGEST_SM3PRIVATE           (9)
+#endif
+
+/*
+ * Assuming SHA-384 digest type + maximal PRIVATEDNS name.
+ */
+#define DNS_DS_BUFFERSIZE (52 + 255)
 
 isc_result_t
 dns_ds_fromkeyrdata(const dns_name_t *owner, dns_rdata_t *key,
                    dns_dsdigest_t digest_type, unsigned char *digest,
-                   dns_rdata_ds_t *dsrdata);
+                   size_t len, dns_rdata_ds_t *dsrdata);
 /*%<
  * Build a DS rdata structure from a key.
  *
@@ -43,7 +53,7 @@ dns_ds_fromkeyrdata(const dns_name_t *owner, dns_rdata_t *key,
 
 isc_result_t
 dns_ds_buildrdata(dns_name_t *owner, dns_rdata_t *key,
-                 dns_dsdigest_t digest_type, unsigned char *buffer,
+                 dns_dsdigest_t digest_type, unsigned char *buffer, size_t len,
                  dns_rdata_t *rdata);
 /*%<
  * Similar to dns_ds_fromkeyrdata(), but copies the DS into a
index 2caae9612c780bf1afae8830c0497c217d5075e9..280740b99146cb73126c09a7c86f3309ffdf870e 100644 (file)
@@ -453,7 +453,7 @@ dns_keytable_deletekey(dns_keytable_t *keytable, const dns_name_t *keyname,
        }
 
        result = dns_ds_fromkeyrdata(keyname, &rdata, DNS_DSDIGEST_SHA256,
-                                    digest, &ds);
+                                    digest, sizeof(digest), &ds);
        if (result != ISC_R_SUCCESS) {
                goto finish;
        }
index f77daa414149c2c9a76f144bb8d10c5f5df86831..414a7915387c33484ab193db3c5c42ad59aa2354 100644 (file)
 
 /* RFC3658, RFC4509, RFC5933, RFC6605, RFC9558, RFC9563 */
 
+#if defined(DNS_DSDIGEST_SHA256PRIVATE) &&     \
+       defined(DNS_DSDIGEST_SHA384PRIVATE) && \
+       defined(DNS_DSDIGEST_SM3PRIVATE)
+#define DSDIGESTPRIVATENAMES                                          \
+       { DNS_DSDIGEST_SHA256PRIVATE, "SHA-256-PRIVATE", 0 },         \
+               { DNS_DSDIGEST_SHA256PRIVATE, "SHA256PRIVATE", 0 },   \
+               { DNS_DSDIGEST_SHA384PRIVATE, "SHA-384-PRIVATE", 0 }, \
+               { DNS_DSDIGEST_SHA384PRIVATE, "SHA384PRIVATE", 0 },   \
+               { DNS_DSDIGEST_SM3PRIVATE, "SM3-PRIVATE", 0 },        \
+               { DNS_DSDIGEST_SM3PRIVATE, "SM3PRIVATE", 0 },
+#else
+#define DSDIGESTPRIVATENAMES
+#endif
+
 #define DSDIGESTNAMES                                                        \
        { DNS_DSDIGEST_SHA1, "SHA-1", 0 }, { DNS_DSDIGEST_SHA1, "SHA1", 0 }, \
                { DNS_DSDIGEST_SHA256, "SHA-256", 0 },                       \
                { DNS_DSDIGEST_SHA384, "SHA-384", 0 },                       \
                { DNS_DSDIGEST_SHA384, "SHA384", 0 },                        \
                { DNS_DSDIGEST_GOST2012, "GOST-2012", 0 },                   \
-               { DNS_DSDIGEST_GOST2012, "GOST2012", 0 }, SENTINEL
+               { DNS_DSDIGEST_GOST2012, "GOST2012", 0 },                    \
+               DSDIGESTPRIVATENAMES SENTINEL
 
 struct tbl {
        unsigned int value;
index 369b4316f37f506ad726a21153ce341be18961d5..82a839977abca0a2a459368ed7a3366047ef396f 100644 (file)
@@ -2030,6 +2030,8 @@ validate_dnskey_dsset(dns_validator_t *val) {
        isc_result_t result;
        dns_rdata_ds_t ds;
        dns_rdata_dnskey_t key;
+       unsigned char *data = 0;
+       unsigned int datalen = 0;
 
        dns_rdata_reset(&dsrdata);
        dns_rdataset_current(val->dsset, &dsrdata);
@@ -2049,12 +2051,31 @@ validate_dnskey_dsset(dns_validator_t *val) {
                return DNS_R_BADALG;
        }
 
-       if (ds.algorithm != DNS_KEYALG_PRIVATEDNS &&
-           ds.algorithm != DNS_KEYALG_PRIVATEOID)
+       switch (ds.algorithm) {
+       case DNS_KEYALG_PRIVATEDNS:
+       case DNS_KEYALG_PRIVATEOID:
+               switch (ds.digest_type) {
+#if defined(DNS_DSDIGEST_SHA256PRIVATE) && defined(DNS_DSDIGEST_SHA384PRIVATE)
+               case DNS_DSDIGEST_SHA256PRIVATE:
+               case DNS_DSDIGEST_SHA384PRIVATE:
+                       data = ds.digest;
+                       datalen = ds.length;
+                       break;
+#endif
+               default:
+                       break;
+               }
+               break;
+       default:
+               break;
+       }
+
+       if (data != NULL || (ds.algorithm != DNS_KEYALG_PRIVATEDNS &&
+                            ds.algorithm != DNS_KEYALG_PRIVATEOID))
        {
                if (!dns_resolver_algorithm_supported(val->view->resolver,
                                                      val->name, ds.algorithm,
-                                                     NULL, 0))
+                                                     data, datalen))
                {
                        if (val->unsupported_algorithm == 0) {
                                val->unsupported_algorithm = ds.algorithm;
@@ -2078,8 +2099,8 @@ validate_dnskey_dsset(dns_validator_t *val) {
         * found a matching dnskey.
         */
        dns_rdata_tostruct(&keyrdata, &key, NULL);
-       if (ds.algorithm == DNS_KEYALG_PRIVATEDNS ||
-           ds.algorithm == DNS_KEYALG_PRIVATEOID)
+       if (data == NULL && (ds.algorithm == DNS_KEYALG_PRIVATEDNS ||
+                            ds.algorithm == DNS_KEYALG_PRIVATEOID))
        {
                if (!dns_resolver_algorithm_supported(val->view->resolver,
                                                      val->name, key.algorithm,
@@ -3020,6 +3041,13 @@ check_ds_algs(dns_validator_t *val, dns_name_t *name,
                    ds.algorithm == DNS_KEYALG_PRIVATEDNS)
                {
                        switch (ds.digest_type) {
+#if defined(DNS_DSDIGEST_SHA256PRIVATE) && defined(DNS_DSDIGEST_SHA384PRIVATE)
+                       case DNS_DSDIGEST_SHA256PRIVATE:
+                       case DNS_DSDIGEST_SHA384PRIVATE:
+                               data = ds.digest;
+                               datalen = ds.length;
+                               break;
+#endif
                        case DNS_DSDIGEST_SHA1:
                        case DNS_DSDIGEST_SHA256:
                        case DNS_DSDIGEST_SHA384:
@@ -3065,11 +3093,12 @@ check_ds_algs(dns_validator_t *val, dns_name_t *name,
         * it would be raised already.
         *
         * If we have seen a private algorithm for which we couldn't find a
-        * DNSKEY we must assume the child zone is secure. With PRIVATEDNS and
-        * PRIVATEOID we can only make that determination if we match a DNSKEY
-        * for every DS with these algorithms. Since we don't know whether the
-        * private algorithm is unsupported or not, we are required to treat it
-        * as supported.
+        * DNSKEY nor extract it from the digest field we must assume the child
+        * zone is secure. With PRIVATEDNS and PRIVATEOID we can make that
+        * determination if we match a DNSKEY for every DS with these algorithms
+        * or extract the algorithm from the digest field. Since we don't know
+        * whether the private algorithm is unsupported or not, we are required
+        * to treat it as supported.
         */
        if (seen_private) {
                char namebuf[DNS_NAME_FORMATSIZE];
index 12b02669e52b19e94ec4edd3f847c84d786070ce..36619b2989a7053c761df09134c8cf2e97f5d306 100644 (file)
@@ -1648,9 +1648,9 @@ dns_view_istrusted(dns_view_t *view, const dns_name_t *keyname,
                                goto finish;
                        }
 
-                       result = dns_ds_fromkeyrdata(keyname, &rdata,
-                                                    DNS_DSDIGEST_SHA256,
-                                                    digest, &ds);
+                       result = dns_ds_fromkeyrdata(
+                               keyname, &rdata, DNS_DSDIGEST_SHA256, digest,
+                               sizeof(digest), &ds);
                        if (result != ISC_R_SUCCESS) {
                                goto finish;
                        }
@@ -2311,7 +2311,7 @@ dns_view_addtrustedkey(dns_view_t *view, dns_rdatatype_t rdtype,
        isc_result_t result;
        dns_name_t *name = UNCONST(keyname);
        char rdatabuf[DST_KEY_MAXSIZE];
-       unsigned char digest[ISC_MAX_MD_SIZE];
+       unsigned char digest[DNS_DS_BUFFERSIZE];
        dns_rdata_ds_t ds;
        dns_rdata_t rdata;
        isc_buffer_t b;
@@ -2334,7 +2334,7 @@ dns_view_addtrustedkey(dns_view_t *view, dns_rdatatype_t rdtype,
                CHECK(dns_rdata_tostruct(&rdata, &ds, NULL));
        } else {
                CHECK(dns_ds_fromkeyrdata(name, &rdata, DNS_DSDIGEST_SHA256,
-                                         digest, &ds));
+                                         digest, sizeof(digest), &ds));
        }
 
        CHECK(dns_keytable_add(view->secroots_priv, false, false, name, &ds,
index 1e3ae54d18d9b0911405ef15655642ab01ca2369..ffe1b658877e999e967ff767f2713e705346329c 100644 (file)
@@ -4433,7 +4433,7 @@ trust_key(dns_zone_t *zone, dns_name_t *keyname, dns_rdata_dnskey_t *dnskey,
          bool initial) {
        isc_result_t result;
        dns_rdata_t rdata = DNS_RDATA_INIT;
-       unsigned char data[4096], digest[ISC_MAX_MD_SIZE];
+       unsigned char data[4096], digest[DNS_DS_BUFFERSIZE];
        isc_buffer_t buffer;
        dns_keytable_t *sr = NULL;
        dns_rdata_ds_t ds;
@@ -4448,7 +4448,7 @@ trust_key(dns_zone_t *zone, dns_name_t *keyname, dns_rdata_dnskey_t *dnskey,
        dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
                             dns_rdatatype_dnskey, dnskey, &buffer);
        CHECK(dns_ds_fromkeyrdata(keyname, &rdata, DNS_DSDIGEST_SHA256, digest,
-                                 &ds));
+                                 sizeof(digest), &ds));
        CHECK(dns_keytable_add(sr, true, initial, keyname, &ds, sfd_add,
                               zone->view));
 
@@ -16501,7 +16501,8 @@ cds_inuse(dns_zone_t *zone, dns_rdata_t *rdata, dns_dnsseckeylist_t *keylist,
                        return result;
                }
                result = dns_ds_buildrdata(dns_zone_getorigin(zone), &dnskey,
-                                          cds.digest_type, cdsbuf, &cdsrdata);
+                                          cds.digest_type, cdsbuf,
+                                          sizeof(cdsbuf), &cdsrdata);
                if (result != ISC_R_SUCCESS) {
                        dns_zone_log(zone, ISC_LOG_ERROR,
                                     "dns_ds_buildrdata(keytag=%d, algo=%d, "
@@ -21033,7 +21034,8 @@ checkds_done(void *arg) {
                        /* Derive DS from DNSKEY, see if the rdata is equal. */
                        make_dnskey(key->key, keybuf, sizeof(keybuf), &dnskey);
                        r = dns_ds_buildrdata(&zone->origin, &dnskey,
-                                             ds.digest_type, dsbuf, &dsrdata);
+                                             ds.digest_type, dsbuf,
+                                             sizeof(dsbuf), &dsrdata);
                        if (r != ISC_R_SUCCESS) {
                                continue;
                        }
index d6cce894ebb03465877cd44c6377d7076d8f6d4d..9acab371e716bf9f92891df45bf20cb0eab5a2a5 100644 (file)
@@ -1521,7 +1521,7 @@ check_dnskey_sigs(vctx_t *vctx, const dns_rdata_dnskey_t *dnskey,
 
                        result = dns_ds_buildrdata(vctx->origin, keyrdata,
                                                   ds.digest_type, buf,
-                                                  &newdsrdata);
+                                                  sizeof(buf), &newdsrdata);
                        if (result != ISC_R_SUCCESS) {
                                continue;
                        }
index 538a98bfebb62b31840cc440ef2fbff63a4173ba..c125c18c65d37ecf7dd10dca70710e76a1eaac5d 100644 (file)
@@ -130,7 +130,7 @@ create_keystruct(uint16_t flags, uint8_t proto, uint8_t alg, const char *keystr,
 
 static void
 create_dsstruct(dns_name_t *name, uint16_t flags, uint8_t proto, uint8_t alg,
-               const char *keystr, unsigned char *digest,
+               const char *keystr, unsigned char *digest, size_t digest_len,
                dns_rdata_ds_t *dsstruct) {
        isc_result_t result;
        unsigned char rrdata[4096];
@@ -156,7 +156,7 @@ create_dsstruct(dns_name_t *name, uint16_t flags, uint8_t proto, uint8_t alg,
         * Build DS rdata struct.
         */
        result = dns_ds_fromkeyrdata(name, &rdata, DNS_DSDIGEST_SHA256, digest,
-                                    dsstruct);
+                                    digest_len, dsstruct);
        assert_int_equal(result, ISC_R_SUCCESS);
 
        dns_rdata_freestruct(&dnskey);
@@ -165,7 +165,7 @@ create_dsstruct(dns_name_t *name, uint16_t flags, uint8_t proto, uint8_t alg,
 /* Common setup: create a keytable and ntatable to test with a few keys */
 static void
 create_tables(void) {
-       unsigned char digest[ISC_MAX_MD_SIZE];
+       unsigned char digest[DNS_DS_BUFFERSIZE];
        dns_rdata_ds_t ds;
        dns_fixedname_t fn;
        dns_name_t *keyname = dns_fixedname_name(&fn);
@@ -179,14 +179,16 @@ create_tables(void) {
 
        /* Add a normal key */
        dns_test_namefromstring("example.com.", &fn);
-       create_dsstruct(keyname, 257, 3, 5, keystr1, digest, &ds);
+       create_dsstruct(keyname, 257, 3, 5, keystr1, digest, sizeof(digest),
+                       &ds);
        assert_int_equal(dns_keytable_add(keytable, false, false, keyname, &ds,
                                          NULL, NULL),
                         ISC_R_SUCCESS);
 
        /* Add an initializing managed key */
        dns_test_namefromstring("managed.com.", &fn);
-       create_dsstruct(keyname, 257, 3, 5, keystr1, digest, &ds);
+       create_dsstruct(keyname, 257, 3, 5, keystr1, digest, sizeof(digest),
+                       &ds);
        assert_int_equal(dns_keytable_add(keytable, true, true, keyname, &ds,
                                          NULL, NULL),
                         ISC_R_SUCCESS);
@@ -220,7 +222,7 @@ destroy_tables(void) {
 ISC_LOOP_TEST_IMPL(add) {
        dns_keynode_t *keynode = NULL;
        dns_keynode_t *null_keynode = NULL;
-       unsigned char digest[ISC_MAX_MD_SIZE];
+       unsigned char digest[DNS_DS_BUFFERSIZE];
        dns_rdata_ds_t ds;
        dns_fixedname_t fn;
        dns_name_t *keyname = dns_fixedname_name(&fn);
@@ -241,7 +243,8 @@ ISC_LOOP_TEST_IMPL(add) {
         * report success.
         */
        dns_test_namefromstring("example.com.", &fn);
-       create_dsstruct(keyname, 257, 3, 5, keystr1, digest, &ds);
+       create_dsstruct(keyname, 257, 3, 5, keystr1, digest, sizeof(digest),
+                       &ds);
        assert_int_equal(dns_keytable_add(keytable, false, false, keyname, &ds,
                                          NULL, NULL),
                         ISC_R_SUCCESS);
@@ -252,7 +255,8 @@ ISC_LOOP_TEST_IMPL(add) {
 
        /* Add another key (different keydata) */
        dns_keynode_detach(&keynode);
-       create_dsstruct(keyname, 257, 3, 5, keystr2, digest, &ds);
+       create_dsstruct(keyname, 257, 3, 5, keystr2, digest, sizeof(digest),
+                       &ds);
        assert_int_equal(dns_keytable_add(keytable, false, false, keyname, &ds,
                                          NULL, NULL),
                         ISC_R_SUCCESS);
@@ -280,7 +284,8 @@ ISC_LOOP_TEST_IMPL(add) {
         * node, the node should *not* be marked as initializing.
         */
        dns_test_namefromstring("managed.com.", &fn);
-       create_dsstruct(keyname, 257, 3, 5, keystr2, digest, &ds);
+       create_dsstruct(keyname, 257, 3, 5, keystr2, digest, sizeof(digest),
+                       &ds);
        assert_int_equal(dns_keytable_add(keytable, true, true, keyname, &ds,
                                          NULL, NULL),
                         ISC_R_SUCCESS);
@@ -310,7 +315,8 @@ ISC_LOOP_TEST_IMPL(add) {
         * initializing key.
         */
        dns_test_namefromstring("two.com.", &fn);
-       create_dsstruct(keyname, 257, 3, 5, keystr1, digest, &ds);
+       create_dsstruct(keyname, 257, 3, 5, keystr1, digest, sizeof(digest),
+                       &ds);
        assert_int_equal(dns_keytable_add(keytable, true, true, keyname, &ds,
                                          NULL, NULL),
                         ISC_R_SUCCESS);
@@ -326,7 +332,8 @@ ISC_LOOP_TEST_IMPL(add) {
         * trust anchor for two.com and we haven't run dns_keynode_trust(),
         * the initialization status should not change.
         */
-       create_dsstruct(keyname, 257, 3, 5, keystr2, digest, &ds);
+       create_dsstruct(keyname, 257, 3, 5, keystr2, digest, sizeof(digest),
+                       &ds);
        assert_int_equal(dns_keytable_add(keytable, true, false, keyname, &ds,
                                          NULL, NULL),
                         ISC_R_SUCCESS);
@@ -344,7 +351,8 @@ ISC_LOOP_TEST_IMPL(add) {
                                           &null_keynode),
                         ISC_R_SUCCESS);
        dns_test_namefromstring("null.example.", &fn);
-       create_dsstruct(keyname, 257, 3, 5, keystr2, digest, &ds);
+       create_dsstruct(keyname, 257, 3, 5, keystr2, digest, sizeof(digest),
+                       &ds);
        assert_int_equal(dns_keytable_add(keytable, false, false, keyname, &ds,
                                          NULL, NULL),
                         ISC_R_SUCCESS);
@@ -598,7 +606,7 @@ ISC_LOOP_TEST_IMPL(nta) {
        bool issecure, covered;
        dns_fixedname_t fn;
        dns_name_t *keyname = dns_fixedname_name(&fn);
-       unsigned char digest[ISC_MAX_MD_SIZE];
+       unsigned char digest[DNS_DS_BUFFERSIZE];
        dns_rdata_ds_t ds;
        dns_view_t *myview = NULL;
        isc_stdtime_t now = isc_stdtime_now();
@@ -616,7 +624,8 @@ ISC_LOOP_TEST_IMPL(nta) {
        assert_int_equal(result, ISC_R_SUCCESS);
 
        dns_test_namefromstring("example.", &fn);
-       create_dsstruct(keyname, 257, 3, 5, keystr1, digest, &ds);
+       create_dsstruct(keyname, 257, 3, 5, keystr1, digest, sizeof(digest),
+                       &ds);
        result = dns_keytable_add(keytable, false, false, keyname, &ds, NULL,
                                  NULL),
        assert_int_equal(result, ISC_R_SUCCESS);