]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Support PRIVATEOID/PRIVATEDNS in zone.c
authorMark Andrews <marka@isc.org>
Tue, 8 Apr 2025 18:26:55 +0000 (13:26 -0500)
committerMark Andrews <marka@isc.org>
Wed, 18 Jun 2025 21:15:20 +0000 (07:15 +1000)
- dns_zone_cdscheck() has been extended to extract the key algorithms
  from DNSKEY data when the CDS algorithm is PRIVATEOID or PRIVATEDNS.

- dns_zone_signwithkey() has been extended to support signing with
  PRIVATEDNS and PRIVATEOID algorithms.  The signing record (type 65534)
  added at the zone apex to indicate the current state of automatic zone
  signing can now contain an additional two-byte field for the DST
  algorithm value, when the DNS secalg value isn't enough information.

bin/tests/system/autosign/tests.sh
bin/tests/system/conf.sh
bin/tests/system/dnssec/tests.sh
lib/dns/include/dns/zone.h
lib/dns/private.c
lib/dns/validator.c
lib/dns/zone.c

index 14064affe2bc9a4167d7b302e39bd25dc4f4c329..298de9196c944444b735ea711aa85f8735936767 100755 (executable)
@@ -31,12 +31,13 @@ showprivate() {
   $DIG $DIGOPTS +nodnssec +short @$2 -t ${4:-type65534} $1 | cut -f3 -d' ' \
     | while read record; do
       $PERL -e 'my $rdata = pack("H*", @ARGV[0]);
-                die "invalid record" unless length($rdata) == 5;
-                my ($alg, $key, $remove, $complete) = unpack("CnCC", $rdata);
+                die "invalid record" unless length($rdata) == 5 || length($rdata) == 7;
+                my ($dns, $key, $remove, $complete, $alg) = unpack("CnCCn", $rdata);
                 my $action = "signing";
                 $action = "removing" if $remove;
                 my $state = " (incomplete)";
                 $state = " (complete)" if $complete;
+                $alg = $dns if ! defined($alg);
                 print ("$action: alg: $alg, key: $key$state\n");' $record
     done
 }
index e17e83116c2d58c49e441a641d4fd51696cefb04..86059196dd80b721f43cba81e5e36027a0fc4af4 100644 (file)
@@ -211,10 +211,15 @@ private_type_record() {
   _zone=$1
   _algorithm=$2
   _keyfile=$3
+  _secalg=$2
 
   _id=$(keyfile_to_key_id "$_keyfile")
 
-  printf "%s. 0 IN TYPE65534 %s 5 %02x%04x0000\n" "$_zone" "\\#" "$_algorithm" "$_id"
+  if test "$_algorithm" -lt 256; then
+    printf "%s. 0 IN TYPE65534 %s 5 %02x%04x0000\n" "$_zone" "\\#" "$_secalg" "$_id"
+  else
+    printf "%s. 0 IN TYPE65534 %s 7 %02x%04x0000%04x\n" "$_zone" "\\#" "$_secalg" "$_id" "$_algorithm"
+  fi
 }
 
 # nextpart*() - functions for reading files incrementally
index 845adc306d76e5066df2d4c80d26a2265f961d67..746dc57ed9beef421e81f4eddc30c559190d2f80 100644 (file)
@@ -53,18 +53,20 @@ dnssec_loadkeys_on() {
 # convert private-type records to readable form
 showprivate() {
   echo "-- $* --"
-  dig_with_opts +nodnssec +short "@$2" -t type65534 "$1" | cut -f3 -d' ' \
-    | while read -r record; do
-      # shellcheck disable=SC2016
-      $PERL -e 'my $rdata = pack("H*", @ARGV[0]);
-                die "invalid record" unless length($rdata) == 5;
-                my ($alg, $key, $remove, $complete) = unpack("CnCC", $rdata);
-                my $action = "signing";
-                $action = "removing" if $remove;
-                my $state = " (incomplete)";
-                $state = " (complete)" if $complete;
-                print ("$action: alg: $alg, key: $key$state\n");' "$record"
-    done
+  dig_with_opts +nodnssec +short "@$2" -t type65534 "$1" >dig.out.$1.test$n
+  cut -f3 -d' ' <dig.out.$1.$n | while read -r record; do
+    # shellcheck disable=SC2016
+    $PERL -e 'my $rdata = pack("H*", @ARGV[0]);
+              die "invalid record" unless length($rdata) == 5 || length($rdata) == 7;
+              my ($dns, $key, $remove, $complete, $alg) = unpack("CnCCn", $rdata);
+              die "invalid record" unless $dns != 0;
+              my $action = "signing";
+              $action = "removing" if $remove;
+              my $state = " (incomplete)";
+              $state = " (complete)" if $complete;
+              $alg = $dns if ! defined($alg);
+              print ("$action: alg: $alg, key: $key$state\n");' "$record"
+  done
 }
 
 # check that signing records are marked as complete
index dcf796f4c13fcb357ec31d51ec303e214944d758..20b5f885b18ef9e43581ceae21b1aee35c5e47bc 100644 (file)
@@ -2187,8 +2187,8 @@ dns_zone_getsignatures(dns_zone_t *zone);
  */
 
 isc_result_t
-dns_zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, uint16_t keyid,
-                    bool deleteit);
+dns_zone_signwithkey(dns_zone_t *zone, dst_algorithm_t algorithm,
+                    uint16_t keyid, bool deleteit);
 /*%<
  * Initiate/resume signing of the entire zone with the zone DNSKEY(s)
  * that match the given algorithm and keyid.
index 57f724c82e2f61f9cfb94e23af47a8bc1e632957..e16514cdeb1445ee41383734fceda2b9f0b6a908 100644 (file)
@@ -354,6 +354,7 @@ dns_private_totext(dns_rdata_t *private, isc_buffer_t *buf) {
                        isc_buffer_putstr(buf, " / creating NSEC chain");
                }
        } else if (private->length == 5) {
+               /* Old Form */
                unsigned char alg = private->data[0];
                dns_keytag_t keyid = (private->data[2] | private->data[1] << 8);
                char keybuf[DNS_SECALG_FORMATSIZE + BUFSIZ],
@@ -371,6 +372,33 @@ dns_private_totext(dns_rdata_t *private, isc_buffer_t *buf) {
                        isc_buffer_putstr(buf, "Signing with ");
                }
 
+               dns_secalg_format(alg, algbuf, sizeof(algbuf));
+               snprintf(keybuf, sizeof(keybuf), "key %d/%s", keyid, algbuf);
+               isc_buffer_putstr(buf, keybuf);
+       } else if (private->length == 7) {
+               /* New Form - supports private types */
+               dns_keytag_t keyid = private->data[2] | (private->data[1] << 8);
+               char keybuf[DNS_SECALG_FORMATSIZE + BUFSIZ],
+                       algbuf[DNS_SECALG_FORMATSIZE];
+               bool del = private->data[3];
+               bool complete = private->data[4];
+               dst_algorithm_t alg = private->data[6] |
+                                     (private->data[5] << 8);
+
+               if (dst_algorithm_tosecalg(alg) != private->data[0]) {
+                       return ISC_R_NOTFOUND;
+               }
+
+               if (del && complete) {
+                       isc_buffer_putstr(buf, "Done removing signatures for ");
+               } else if (del) {
+                       isc_buffer_putstr(buf, "Removing signatures for ");
+               } else if (complete) {
+                       isc_buffer_putstr(buf, "Done signing with ");
+               } else {
+                       isc_buffer_putstr(buf, "Signing with ");
+               }
+
                dns_secalg_format(alg, algbuf, sizeof(algbuf));
                snprintf(keybuf, sizeof(keybuf), "key %d/%s", keyid, algbuf);
                isc_buffer_putstr(buf, keybuf);
index a7da3f4cdb8383cce3bab64e67d5bef5df42ceb3..369b4316f37f506ad726a21153ce341be18961d5 100644 (file)
@@ -1680,6 +1680,9 @@ validate_answer_process(void *arg) {
        {
                if (val->unsupported_algorithm == 0) {
                        val->unsupported_algorithm = val->siginfo->algorithm;
+                       /*
+                        * XXXMPA save PRIVATEOID/PRIVATEDNS identifier here
+                        */
                }
                goto next_key;
        }
@@ -2084,6 +2087,9 @@ validate_dnskey_dsset(dns_validator_t *val) {
                {
                        if (val->unsupported_algorithm == 0) {
                                val->unsupported_algorithm = key.algorithm;
+                               /*
+                                * XXXMPA Save PRIVATEOID / PRIVATEDNS here.
+                                */
                        }
                        return DNS_R_BADALG;
                }
index d3e62bbb0cbe665596df719cd34f8e6899be2230..1e3ae54d18d9b0911405ef15655642ab01ca2369 100644 (file)
 #define KSK(x)   ((dst_key_flags(x) & DNS_KEYFLAG_KSK) != 0)
 #define ID(x)    dst_key_id(x)
 #define ALG(x)   dst_key_alg(x)
-#define DNSALG(x) dst_algorithm_tosecalg(dst_key_alg(x))
 
 /*%
  * KASP flags
@@ -729,7 +728,7 @@ struct dns_signing {
        unsigned int magic;
        dns_db_t *db;
        dns_dbiterator_t *dbiterator;
-       dns_secalg_t algorithm;
+       dst_algorithm_t algorithm;
        uint16_t keyid;
        bool deleteit;
        bool done;
@@ -973,7 +972,7 @@ zone_notify(dns_zone_t *zone, isc_time_t *now);
 static void
 dump_done(void *arg, isc_result_t result);
 static isc_result_t
-zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, uint16_t keyid,
+zone_signwithkey(dns_zone_t *zone, dst_algorithm_t algorithm, uint16_t keyid,
                 bool deleteit);
 static isc_result_t
 delete_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
@@ -3756,6 +3755,9 @@ cleanup:
        }
 }
 
+#define OLD_SIGNING_RECORD_SIZE 5
+#define SIGNING_RECORD_SIZE    7
+
 static void
 resume_signingwithkey(dns_zone_t *zone) {
        dns_dbnode_t *node = NULL;
@@ -3789,14 +3791,22 @@ resume_signingwithkey(dns_zone_t *zone) {
 
        DNS_RDATASET_FOREACH (&rdataset) {
                dns_rdata_t rdata = DNS_RDATA_INIT;
+               dst_algorithm_t alg;
+
                dns_rdataset_current(&rdataset, &rdata);
-               if (rdata.length != 5 || rdata.data[0] == 0 ||
-                   rdata.data[4] != 0)
+               /*
+                * Old or New Forms
+                */
+               if ((rdata.length != OLD_SIGNING_RECORD_SIZE &&
+                    rdata.length != SIGNING_RECORD_SIZE) ||
+                   rdata.data[0] == 0 || rdata.data[4] != 0)
                {
                        continue;
                }
-
-               result = zone_signwithkey(zone, rdata.data[0],
+               alg = (rdata.length == OLD_SIGNING_RECORD_SIZE)
+                             ? rdata.data[0]
+                             : ((rdata.data[5] << 8) | rdata.data[6]);
+               result = zone_signwithkey(zone, alg,
                                          (rdata.data[1] << 8) | rdata.data[2],
                                          rdata.data[3]);
                if (result != ISC_R_SUCCESS) {
@@ -7968,18 +7978,25 @@ updatesignwithkey(dns_zone_t *zone, dns_signing_t *signing,
                INSIST(!dns_rdataset_isassociated(&rdataset));
                goto failure;
        }
+
        DNS_RDATASET_FOREACH (&rdataset) {
                dns_rdata_t rdata = DNS_RDATA_INIT;
+               unsigned char alg = dst_algorithm_tosecalg(signing->algorithm);
+
                dns_rdataset_current(&rdataset, &rdata);
                /*
                 * If we don't match the algorithm or keyid skip the record.
                 */
-               if (rdata.length != 5 || rdata.data[0] != signing->algorithm ||
+               if ((rdata.length != SIGNING_RECORD_SIZE &&
+                    rdata.length != OLD_SIGNING_RECORD_SIZE) ||
+                   rdata.data[0] == 0 || rdata.data[0] != alg ||
                    rdata.data[1] != ((signing->keyid >> 8) & 0xff) ||
-                   rdata.data[2] != (signing->keyid & 0xff))
+                   rdata.data[2] != (signing->keyid & 0xff) ||
+                   (rdata.length == SIGNING_RECORD_SIZE &&
+                    (rdata.data[5] != (signing->algorithm >> 8 & 0xff) ||
+                     rdata.data[6] != (signing->algorithm & 0xff))))
                {
                        have_rr = true;
-                       dns_rdata_reset(&rdata);
                        continue;
                }
                /*
@@ -8009,20 +8026,32 @@ updatesignwithkey(dns_zone_t *zone, dns_signing_t *signing,
                 * finished signing the zone with this key.  If it is already
                 * there we don't need to add it a second time.
                 */
-               unsigned char data[5] = {
-                       signing->algorithm,
+               unsigned char data[SIGNING_RECORD_SIZE] = {
+                       dst_algorithm_tosecalg(signing->algorithm),
                        (signing->keyid >> 8) & 0xff,
                        signing->keyid & 0xff,
                        0,
                        1,
+                       (signing->algorithm >> 8) & 0xff,
+                       signing->algorithm & 0xff,
                };
                dns_rdata_t rdata = (dns_rdata_t){
-                       .length = sizeof(data),
+                       .length = signing->algorithm < 256
+                                         ? OLD_SIGNING_RECORD_SIZE
+                                         : sizeof(data),
                        .data = data,
                        .type = zone->privatetype,
                        .rdclass = dns_db_class(signing->db),
                        .link = ISC_LINK_INITIALIZER,
                };
+               /*
+                * data[0] can't be 0 as that is used to signal that the
+                * record is being used to for NSEC/NSEC3 chains generation.
+                * Set it to 255 instead.
+                */
+               if (data[0] == 0) {
+                       data[0] = 255;
+               }
                CHECK(update_one_rr(signing->db, version, diff, DNS_DIFFOP_ADD,
                                    &zone->origin, rdataset.ttl, &rdata));
        } else if (!have_rr) {
@@ -9351,7 +9380,7 @@ failure:
  */
 static isc_result_t
 del_sig(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
-       dns_dbnode_t *node, unsigned int nkeys, dns_secalg_t algorithm,
+       dns_dbnode_t *node, unsigned int nkeys, dst_algorithm_t algorithm,
        uint16_t keyid, bool *has_algp, dns_diff_t *diff) {
        dns_rdata_rrsig_t rrsig;
        dns_rdataset_t rdataset;
@@ -9392,12 +9421,17 @@ del_sig(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
                }
                DNS_RDATASET_FOREACH (&rdataset) {
                        dns_rdata_t rdata = DNS_RDATA_INIT;
+                       dst_algorithm_t sigalg;
+
                        dns_rdataset_current(&rdataset, &rdata);
                        CHECK(dns_rdata_tostruct(&rdata, &rrsig, NULL));
-                       if (nkeys != 0 && (rrsig.algorithm != algorithm ||
-                                          rrsig.keyid != keyid))
+
+                       sigalg = dst_algorithm_fromdata(
+                               rrsig.algorithm, rrsig.signature, rrsig.siglen);
+                       if (nkeys != 0 &&
+                           (sigalg != algorithm || rrsig.keyid != keyid))
                        {
-                               if (rrsig.algorithm == algorithm) {
+                               if (sigalg == algorithm) {
                                        has_alg = true;
                                }
                                continue;
@@ -9687,8 +9721,7 @@ zone_sign(dns_zone_t *zone) {
                                /*
                                 * Find the key we want to remove.
                                 */
-                               if (DNSALG(zone_keys[i]) ==
-                                           signing->algorithm &&
+                               if (ALG(zone_keys[i]) == signing->algorithm &&
                                    dst_key_id(zone_keys[i]) == signing->keyid)
                                {
                                        dst_key_free(&zone_keys[i]);
@@ -9763,7 +9796,7 @@ zone_sign(dns_zone_t *zone) {
                         * When adding look for the specific key.
                         */
                        if (!signing->deleteit &&
-                           (DNSALG(zone_keys[i]) != signing->algorithm ||
+                           (ALG(zone_keys[i]) != signing->algorithm ||
                             dst_key_id(zone_keys[i]) != signing->keyid))
                        {
                                continue;
@@ -9774,7 +9807,7 @@ zone_sign(dns_zone_t *zone) {
                         * with the algorithm that was being removed.
                         */
                        if (signing->deleteit &&
-                           DNSALG(zone_keys[i]) != signing->algorithm)
+                           ALG(zone_keys[i]) != signing->algorithm)
                        {
                                continue;
                        }
@@ -20108,8 +20141,8 @@ dns_zone_setnotifydelay(dns_zone_t *zone, uint32_t delay) {
 }
 
 isc_result_t
-dns_zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, uint16_t keyid,
-                    bool deleteit) {
+dns_zone_signwithkey(dns_zone_t *zone, dst_algorithm_t algorithm,
+                    uint16_t keyid, bool deleteit) {
        isc_result_t result;
        REQUIRE(DNS_ZONE_VALID(zone));
 
@@ -20193,7 +20226,7 @@ dns_zone_getprivatetype(dns_zone_t *zone) {
 }
 
 static isc_result_t
-zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, uint16_t keyid,
+zone_signwithkey(dns_zone_t *zone, dst_algorithm_t algorithm, uint16_t keyid,
                 bool deleteit) {
        dns_signing_t *signing = NULL;
        isc_result_t result = ISC_R_SUCCESS;
@@ -20350,7 +20383,7 @@ add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype,
        isc_region_t r;
        isc_result_t result = ISC_R_SUCCESS;
        uint16_t keyid;
-       unsigned char buf[5];
+       unsigned char data[SIGNING_RECORD_SIZE];
        dns_name_t *name = dns_db_origin(db);
        dns_difftuplelist_t add = ISC_LIST_INITIALIZER;
        dns_difftuplelist_t del = ISC_LIST_INITIALIZER;
@@ -20425,17 +20458,23 @@ add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype,
         * or added.
         */
        ISC_LIST_FOREACH (tuples, tuple, link) {
+               dst_algorithm_t algorithm;
                dns_rdata_toregion(&tuple->rdata, &r);
 
                keyid = dst_region_computeid(&r);
 
-               buf[0] = dnskey.algorithm;
-               buf[1] = (keyid & 0xff00) >> 8;
-               buf[2] = (keyid & 0xff);
-               buf[3] = (tuple->op == DNS_DIFFOP_ADD) ? 0 : 1;
-               buf[4] = 0;
-               rdata.data = buf;
-               rdata.length = sizeof(buf);
+               algorithm = dst_algorithm_fromdata(dnskey.algorithm,
+                                                  dnskey.data, dnskey.datalen);
+               data[0] = dnskey.algorithm;
+               data[1] = (keyid & 0xff00) >> 8;
+               data[2] = (keyid & 0xff);
+               data[3] = (tuple->op == DNS_DIFFOP_ADD) ? 0 : 1;
+               data[4] = 0;
+               data[5] = (algorithm & 0xff00) >> 8;
+               data[6] = (algorithm & 0xff);
+               rdata.data = data;
+               rdata.length = algorithm < 256 ? OLD_SIGNING_RECORD_SIZE
+                                              : sizeof(data);
                rdata.type = privatetype;
                rdata.rdclass = tuple->rdata.rdclass;
 
@@ -20455,7 +20494,7 @@ add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype,
                 * Remove any record which says this operation has already
                 * completed.
                 */
-               buf[4] = 1;
+               data[4] = 1;
                CHECK(rr_exists(db, ver, name, &rdata, &flag));
                if (flag) {
                        dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL, name,
@@ -22900,21 +22939,49 @@ dns_zone_cdscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version) {
                        }
 
                        CHECK(dns_rdata_tostruct(&crdata, &structcds, NULL));
-                       if (algorithms[structcds.algorithm] == 0) {
-                               algorithms[structcds.algorithm] = expected;
-                       }
-                       DNS_RDATASET_FOREACH (&dnskey) {
+                       if (structcds.algorithm != DNS_KEYALG_PRIVATEDNS &&
+                           structcds.algorithm != DNS_KEYALG_PRIVATEOID)
+                       {
+                               if (algorithms[structcds.algorithm] == 0) {
+                                       algorithms[structcds.algorithm] =
+                                               expected;
+                               }
+                               DNS_RDATASET_FOREACH (&dnskey) {
+                                       dns_rdata_t rdata = DNS_RDATA_INIT;
+                                       dns_rdata_dnskey_t structdnskey;
+
+                                       dns_rdataset_current(&dnskey, &rdata);
+                                       dns_rdata_tostruct(&rdata,
+                                                          &structdnskey, NULL);
+
+                                       if (structdnskey.algorithm ==
+                                           structcds.algorithm)
+                                       {
+                                               algorithms[structcds.algorithm] =
+                                                       found;
+                                       }
+                               }
+                       } else {
                                dns_rdata_t rdata = DNS_RDATA_INIT;
                                dns_rdata_dnskey_t structdnskey;
+                               dst_algorithm_t dnskeyalg;
 
-                               dns_rdataset_current(&dnskey, &rdata);
-                               dns_rdata_tostruct(&rdata, &structdnskey, NULL);
-
-                               if (structdnskey.algorithm ==
-                                   structcds.algorithm)
-                               {
-                                       algorithms[structcds.algorithm] = found;
+                               /* Convert CDS to DS */
+                               crdata.type = dns_rdatatype_ds;
+                               result = dns_dnssec_matchdskey(&zone->origin,
+                                                              &crdata, &dnskey,
+                                                              &rdata);
+                               if (result != ISC_R_SUCCESS) {
+                                       result = DNS_R_BADCDS;
+                                       goto failure;
                                }
+                               CHECK(dns_rdata_tostruct(&rdata, &structdnskey,
+                                                        NULL));
+                               dnskeyalg = dst_algorithm_fromdata(
+                                       structdnskey.algorithm,
+                                       structdnskey.data,
+                                       structdnskey.datalen);
+                               algorithms[dnskeyalg] = found;
                        }
                }
                for (i = 0; i < sizeof(algorithms); i++) {
@@ -22941,6 +23008,7 @@ dns_zone_cdscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version) {
                DNS_RDATASET_FOREACH (&cdnskey) {
                        dns_rdata_t crdata = DNS_RDATA_INIT;
                        dns_rdata_cdnskey_t structcdnskey;
+                       dst_algorithm_t cdnskeyalg;
 
                        dns_rdataset_current(&cdnskey, &crdata);
                        /*
@@ -22963,22 +23031,27 @@ dns_zone_cdscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version) {
 
                        CHECK(dns_rdata_tostruct(&crdata, &structcdnskey,
                                                 NULL));
-                       if (algorithms[structcdnskey.algorithm] == 0) {
-                               algorithms[structcdnskey.algorithm] = expected;
+                       cdnskeyalg = dst_algorithm_fromdata(
+                               structcdnskey.algorithm, structcdnskey.data,
+                               structcdnskey.datalen);
+                       if (algorithms[cdnskeyalg] == 0) {
+                               algorithms[cdnskeyalg] = expected;
                        }
                        DNS_RDATASET_FOREACH (&dnskey) {
                                dns_rdata_t rdata = DNS_RDATA_INIT;
                                dns_rdata_dnskey_t structdnskey;
+                               dst_algorithm_t dnskeyalg;
 
                                dns_rdataset_current(&dnskey, &rdata);
                                CHECK(dns_rdata_tostruct(&rdata, &structdnskey,
                                                         NULL));
+                               dnskeyalg = dst_algorithm_fromdata(
+                                       structdnskey.algorithm,
+                                       structdnskey.data,
+                                       structdnskey.datalen);
 
-                               if (structdnskey.algorithm ==
-                                   structcdnskey.algorithm)
-                               {
-                                       algorithms[structcdnskey.algorithm] =
-                                               found;
+                               if (dnskeyalg == cdnskeyalg) {
+                                       algorithms[cdnskeyalg] = found;
                                }
                        }
                }
@@ -23232,7 +23305,7 @@ dns_zone_issecure(dns_zone_t *zone) {
 
 struct keydone {
        bool all;
-       unsigned char data[5];
+       unsigned char data[SIGNING_RECORD_SIZE];
        dns_zone_t *zone;
 };
 
@@ -23300,8 +23373,11 @@ keydone(void *arg) {
                dns_rdataset_current(&rdataset, &rdata);
 
                if (kd->all) {
-                       if (rdata.length == 5 && rdata.data[0] != 0 &&
-                           rdata.data[3] == 0 && rdata.data[4] == 1)
+                       /* Old (5) and new (7) forms */
+                       if ((rdata.length == OLD_SIGNING_RECORD_SIZE ||
+                            rdata.length == SIGNING_RECORD_SIZE) &&
+                           rdata.data[0] != 0 && rdata.data[3] == 0 &&
+                           rdata.data[4] == 1)
                        {
                                found = true;
                        } else if (rdata.data[0] == 0 &&
@@ -23310,8 +23386,14 @@ keydone(void *arg) {
                                found = true;
                                clear_pending = true;
                        }
-               } else if (rdata.length == 5 &&
-                          memcmp(rdata.data, kd->data, 5) == 0)
+               } else if (rdata.length == OLD_SIGNING_RECORD_SIZE &&
+                          memcmp(rdata.data, kd->data,
+                                 OLD_SIGNING_RECORD_SIZE) == 0)
+               {
+                       found = true;
+               } else if (rdata.length == SIGNING_RECORD_SIZE &&
+                          memcmp(rdata.data, kd->data, SIGNING_RECORD_SIZE) ==
+                                  0)
                {
                        found = true;
                }
@@ -23388,7 +23470,7 @@ dns_zone_keydone(dns_zone_t *zone, const char *keystr) {
                isc_textregion_t r;
                const char *algstr = NULL;
                dns_keytag_t keyid;
-               dns_secalg_t alg;
+               dst_algorithm_t alg;
                size_t n;
 
                n = sscanf(keystr, "%hu/", &keyid);
@@ -23403,20 +23485,20 @@ dns_zone_keydone(dns_zone_t *zone, const char *keystr) {
                        CHECK(ISC_R_FAILURE);
                }
 
-               n = sscanf(algstr, "%hhu", &alg);
+               n = sscanf(algstr, "%u", &alg);
                if (n == 0U) {
                        r.base = UNCONST(algstr);
                        r.length = strlen(algstr);
-                       CHECK(dns_secalg_fromtext(&alg, &r));
+                       CHECK(dst_algorithm_fromtext(&alg, &r));
                }
 
                /* construct a private-type rdata */
                isc_buffer_init(&b, kd->data, sizeof(kd->data));
-               isc_buffer_putuint8(&b, alg);
-               isc_buffer_putuint8(&b, (keyid & 0xff00) >> 8);
-               isc_buffer_putuint8(&b, (keyid & 0xff));
+               isc_buffer_putuint8(&b, dst_algorithm_tosecalg(alg));
+               isc_buffer_putuint16(&b, keyid);
                isc_buffer_putuint8(&b, 0);
                isc_buffer_putuint8(&b, 1);
+               isc_buffer_putuint16(&b, alg);
        }
 
        zone_iattach(zone, &kd->zone);