]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Replace get_dnsalg() with kasp.Key.algorithm
authorNicki Křížek <nicki@isc.org>
Tue, 16 Jun 2026 15:56:00 +0000 (17:56 +0200)
committerNicki Křížek <nicki@isc.org>
Thu, 2 Jul 2026 12:51:41 +0000 (14:51 +0200)
The get_dnsalg() was just a compatibility layer for 9.18 which lacked
the Algorithm support - remove it in favor of using the .algorithm
property.

In order to properly support private OID algorithms, use the DST value
which is unique across all algorithms.

Also fix private_type_record(): the choice between the 5- and 7-byte
signing record depends on the DST value (256/257 for the private-OID
algorithms), not the on-wire number, which never reaches 256.

Assisted-by: Claude:claude-opus-4-8
bin/tests/system/isctest/kasp.py
bin/tests/system/isctest/vars/algorithms.py
bin/tests/system/ksr/tests_ksr.py

index 2bbcfce95abb74d91a58be1fdb8b693e3d2e3796..2c82cce37b5648e96f957e983f1e6be3358aba2b 100644 (file)
@@ -31,7 +31,7 @@ import dns.zone
 
 from isctest.instance import NamedInstance
 from isctest.run import EnvCmd
-from isctest.vars.algorithms import ALL_ALGORITHMS_BY_NUM, Algorithm
+from isctest.vars.algorithms import ALL_ALGORITHMS_BY_DST, ECDSAP256SHA256, Algorithm
 from isctest.zone import FileZoneKey
 
 import isctest.log
@@ -215,7 +215,7 @@ class KeyProperties:
     @staticmethod
     def default(with_state=True) -> "KeyProperties":
         metadata = {
-            "Algorithm": isctest.vars.algorithms.ECDSAP256SHA256.number,
+            "Algorithm": ECDSAP256SHA256.number,
             "Length": 256,
             "Lifetime": 0,
             "KSK": "yes",
@@ -487,14 +487,6 @@ class Key(FileZoneKey):
 
         return ksigning, zsigning
 
-    def get_dnsalg(self) -> int:
-        alg = int(self.get_metadata("Algorithm"))
-        if alg == isctest.vars.algorithms.RSASHA256OID.dst:
-            return isctest.vars.algorithms.RSASHA256OID.number
-        if alg == isctest.vars.algorithms.RSASHA512OID.dst:
-            return isctest.vars.algorithms.RSASHA512OID.number
-        return alg
-
     def is_ksk(self) -> bool:
         # KASP role follows the .state KSK metadata, not the DNSKEY SEP flag:
         # a CSK may be configured without SEP (see the csk-nosep test).
@@ -512,8 +504,15 @@ class Key(FileZoneKey):
 
     @property
     def algorithm(self) -> Algorithm:
-        num = int(self.get_metadata("Algorithm"))
-        return ALL_ALGORITHMS_BY_NUM[num]
+        """
+        Obtain the algorithm from key metadata.
+
+        The .state Algorithm field holds the DST identifier, which (unlike the
+        on-wire DNSKEY algorithm number) distinguishes the private-OID variants
+        RSASHA256OID and RSASHA512OID, both of which appear as 254 on the wire.
+        """
+        dst = int(self.get_metadata("Algorithm"))
+        return ALL_ALGORITHMS_BY_DST[dst]
 
     def dnskey_equals(self, value, cdnskey=False):
         dnskey = value.split()
@@ -951,7 +950,7 @@ def _check_signatures(
             offline_ksk=offline_ksk, zsk_missing=zsk_missing, smooth=smooth
         )
 
-        alg = key.get_dnsalg()
+        alg = key.algorithm.number
         rtype = dns.rdatatype.to_text(covers)
 
         expect = rf"IN RRSIG {rtype} {alg} (\d) (\d+) (\d+) (\d+) {key.tag} {signer}"
@@ -1716,10 +1715,10 @@ def private_type_record(zone: str, key: Key, rrtype: int = 65534) -> str:
     indicating that the signing process for this key is completed.
     """
     keyid = key.tag
-    algorithm = key.get_dnsalg()
-    secalg = int(key.get_metadata("Algorithm"))
+    wire_alg = key.algorithm.number
+    dst_alg = key.algorithm.dst
 
-    if algorithm < 256:
-        return f"{zone}. 0 IN TYPE{rrtype} \\# 5 {secalg:02x}{keyid:04x}0000"
+    if dst_alg < 256:
+        return f"{zone}. 0 IN TYPE{rrtype} \\# 5 {wire_alg:02x}{keyid:04x}0000"
 
-    return f"{zone}. 0 IN TYPE{rrtype} \\# 7 {secalg:02x}{keyid:04x}0000{algorithm:04x}"
+    return f"{zone}. 0 IN TYPE{rrtype} \\# 7 {wire_alg:02x}{keyid:04x}0000{dst_alg:04x}"
index 0ff211da95a37dd5aa62d0f393472fa2fcd45a31..a0081e0c47c1c67be3ad95a4a78f202ff7f39e6d 100644 (file)
@@ -111,6 +111,10 @@ ALL_ALGORITHMS = [
 ]
 
 ALL_ALGORITHMS_BY_NUM = {alg.number: alg for alg in ALL_ALGORITHMS}
+# Keyed by the DST identifier rather than the on-wire number: unlike `number`
+# (where both private-OID variants collide at 254), `dst` is unique, so this
+# map distinguishes RSASHA256OID (256) from RSASHA512OID (257).
+ALL_ALGORITHMS_BY_DST = {alg.dst: alg for alg in ALL_ALGORITHMS}
 
 ALGORITHM_SETS = {
     "stable": AlgorithmSet(
index 32060acd3c08a3fd42b41b50657913493ca05d96..b1e1be907eb7f9fed15c894f213ed720e54f7c82 100644 (file)
@@ -318,7 +318,7 @@ def check_rrsig_bundle(bundle_keys, bundle_lines, zone, rrtype, sigend, sigstart
     count = 0
     for key in bundle_keys:
         found = False
-        alg = key.get_dnsalg()
+        alg = key.algorithm.number
         expect = f"{zone}. {ttl} IN RRSIG {rrtype} {alg} 2 {ttl} {sigend} {sigstart} {key.tag} {zone}."
         # there must be a signature of this ksk
         for line in bundle_lines: