]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Convert ksk rollover test case to pytest
authorMatthijs Mekking <matthijs@isc.org>
Tue, 18 Mar 2025 13:20:54 +0000 (14:20 +0100)
committerMatthijs Mekking <matthijs@isc.org>
Mon, 2 Jun 2025 09:21:06 +0000 (09:21 +0000)
Move the 'ksk-doubleksk' zones to the rollover test dir and convert KSK
rollover test to pytest.

Since the 'ksk-doubleksk' policy publishes different CDNSKEY/CDS RRsets,
update the 'check_rollover_step' to check which CDNSKEY/CDS RRsets should
be published and which should be prohibited. Update 'isctest.kasp'
accordingly.

We are changing the ZSK lifetime to unlimited in this test case as it
is of no importance (this actually discovered a bug in setting the
next time the keymgr should run).

bin/tests/system/isctest/kasp.py
bin/tests/system/kasp/ns3/named-fips.conf.in
bin/tests/system/kasp/ns3/setup.sh
bin/tests/system/kasp/tests.sh
bin/tests/system/rollover/ns3/kasp.conf.j2
bin/tests/system/rollover/ns3/named.conf.j2
bin/tests/system/rollover/ns3/setup.sh
bin/tests/system/rollover/tests_rollover.py

index 8233f1807bf5aa7f8c70ecf717ef3f41298f9e22..537ebce0ba6c49bfdcf5650222b39606ab300c9f 100644 (file)
@@ -909,8 +909,9 @@ def _check_dnskeys(dnskeys, keys, cdnskey=False):
                 has_dnskey = True
                 break
 
-        if not cdnskey:
-            assert has_dnskey
+        if not published or removed:
+            if not cdnskey:
+                assert has_dnskey
 
         if has_dnskey:
             numkeys += 1
@@ -940,22 +941,13 @@ def check_dnskeys(rrset, ksks, zsks, cdnskey=False):
     assert numkeys == len(dnskeys)
 
 
-def check_cds(rrset, keys):
+def check_cds(cdss, keys, alg):
     # Check if the correct CDS records are published. If the current time
     # is between the timing metadata 'publish' and 'delete', the key must have
-    # a DNSKEY record published. If 'cdnskey' is True, check against CDNSKEY
-    # records instead.
+    # a CDS record published.
     now = KeyTimingMetadata.now()
     numcds = 0
 
-    cdss = []
-    for rr in rrset:
-        for rdata in rr:
-            rdclass = dns.rdataclass.to_text(rr.rdclass)
-            rdtype = dns.rdatatype.to_text(rr.rdtype)
-            cds = f"{rr.name} {rr.ttl} {rdclass} {rdtype} {rdata}"
-            cdss.append(cds)
-
     for key in keys:
         assert key.is_ksk()
 
@@ -965,19 +957,31 @@ def check_cds(rrset, keys):
         removed = delete is not None and delete <= now
         if not published or removed:
             for cds in cdss:
-                assert not key.cds_equals(cds, "SHA-256")
+                assert not key.cds_equals(cds, alg)
             continue
 
         has_cds = False
         for cds in cdss:
-            if key.cds_equals(cds, "SHA-256"):
+            if key.cds_equals(cds, alg):
                 has_cds = True
                 break
 
-        assert has_cds
-        numcds += 1
+        if not published or removed:
+            assert has_cds
+
+        if has_cds:
+            numcds += 1
+
+    return numcds
 
-    assert numcds == len(cdss)
+
+def check_cds_prohibit(cdss, keys, alg):
+    # Check if the CDS records are not published. This does not take into
+    # account the timing metadata, just making sure that the given algorithm
+    # does not get published.
+    for key in keys:
+        for cds in cdss:
+            assert not key.cds_equals(cds, alg)
 
 
 def check_cdslog(server, zone, key, substr):
@@ -1015,12 +1019,15 @@ def _query_rrset(server, fqdn, qtype, tsig=None):
 
 
 def check_apex(
-    server, zone, ksks, zsks, offline_ksk=False, zsk_missing=False, tsig=None
+    server, zone, ksks, zsks, cdss=None, offline_ksk=False, zsk_missing=False, tsig=None
 ):
     # Test the apex of a zone. This checks that the SOA and DNSKEY RRsets
     # are signed correctly and with the appropriate keys.
     fqdn = f"{zone}."
 
+    if cdss is None:
+        cdss = ["CDNSKEY", "CDS (SHA-256)"]
+
     # test dnskey query
     dnskeys, rrsigs = _query_rrset(server, fqdn, dns.rdatatype.DNSKEY, tsig=tsig)
     check_dnskeys(dnskeys, ksks, zsks)
@@ -1044,7 +1051,12 @@ def check_apex(
 
     # test cdnskey query
     cdnskeys, rrsigs = _query_rrset(server, fqdn, dns.rdatatype.CDNSKEY, tsig=tsig)
-    check_dnskeys(cdnskeys, ksks, zsks, cdnskey=True)
+
+    if "CDNSKEY" in cdss:
+        check_dnskeys(cdnskeys, ksks, zsks, cdnskey=True)
+    else:
+        assert len(cdnskeys) == 0
+
     if len(cdnskeys) > 0:
         assert len(rrsigs) > 0
         check_signatures(
@@ -1053,13 +1065,30 @@ def check_apex(
 
     # test cds query
     cds, rrsigs = _query_rrset(server, fqdn, dns.rdatatype.CDS, tsig=tsig)
-    check_cds(cds, ksks)
+    cdsrrs = []
+    for rr in cds:
+        for rdata in rr:
+            rdclass = dns.rdataclass.to_text(rr.rdclass)
+            rdtype = dns.rdatatype.to_text(rr.rdtype)
+            cds = f"{rr.name} {rr.ttl} {rdclass} {rdtype} {rdata}"
+            cdsrrs.append(cds)
+
+    numcds = 0
+
+    for alg in ["SHA-256", "SHA-384"]:
+        if f"CDS ({alg})" in cdss:
+            numcds += check_cds(cdsrrs, ksks, alg)
+        else:
+            check_cds_prohibit(cdsrrs, ksks, alg)
+
     if len(cds) > 0:
         assert len(rrsigs) > 0
         check_signatures(
             rrsigs, dns.rdatatype.CDS, fqdn, ksks, zsks, offline_ksk=offline_ksk
         )
 
+    assert numcds == len(cdsrrs)
+
 
 def check_subdomain(
     server, zone, ksks, zsks, offline_ksk=False, smooth=False, tsig=None
index 9247a12350c9ec6210a57b93124d41c96c1b7f74..85636adbb47a925a56fe276b71272b4d46ee6ae1 100644 (file)
@@ -324,40 +324,6 @@ zone "zsk-retired.autosign" {
        dnssec-policy "autosign";
 };
 
-/*
- * Zones for testing KSK Double-KSK steps.
- */
-zone "step1.ksk-doubleksk.autosign" {
-       type primary;
-       file "step1.ksk-doubleksk.autosign.db";
-       dnssec-policy "ksk-doubleksk";
-};
-zone "step2.ksk-doubleksk.autosign" {
-       type primary;
-       file "step2.ksk-doubleksk.autosign.db";
-       dnssec-policy "ksk-doubleksk";
-};
-zone "step3.ksk-doubleksk.autosign" {
-       type primary;
-       file "step3.ksk-doubleksk.autosign.db";
-       dnssec-policy "ksk-doubleksk";
-};
-zone "step4.ksk-doubleksk.autosign" {
-       type primary;
-       file "step4.ksk-doubleksk.autosign.db";
-       dnssec-policy "ksk-doubleksk";
-};
-zone "step5.ksk-doubleksk.autosign" {
-       type primary;
-       file "step5.ksk-doubleksk.autosign.db";
-       dnssec-policy "ksk-doubleksk";
-};
-zone "step6.ksk-doubleksk.autosign" {
-       type primary;
-       file "step6.ksk-doubleksk.autosign.db";
-       dnssec-policy "ksk-doubleksk";
-};
-
 /*
  * Zones for testing CSK rollover steps.
  */
index 4e4cc1d808750655cd4b470325442baf8c3820c2..cf4d0a98e8f5e16d7d2336e6c5dd573ef79436a9 100644 (file)
@@ -281,283 +281,6 @@ oldtimes="-P $T2 -A $T2 -I $T1 -D $T1"
 OLD=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 $oldtimes $zone 2>keygen.out.$zone.3)
 $SETTIME -s -g $H -k $H $T1 -z $H $T1 "$OLD" >settime.out.$zone.3 2>&1
 
-#
-# The zones at ksk-doubleksk.autosign represent the various steps of a KSK
-# Double-KSK rollover.
-#
-
-# Step 1:
-# Introduce the first key. This will immediately be active.
-setup step1.ksk-doubleksk.autosign
-TactN="now"
-ksktimes="-P ${TactN} -A ${TactN} -P sync ${TactN}"
-zsktimes="-P ${TactN} -A ${TactN}"
-KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $ksktimes $zone 2>keygen.out.$zone.1)
-ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $zsktimes $zone 2>keygen.out.$zone.2)
-$SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN "$KSK" >settime.out.$zone.1 2>&1
-$SETTIME -s -g $O -k $O $TactN -z $O $TactN "$ZSK" >settime.out.$zone.2 2>&1
-cat template.db.in "${KSK}.key" "${ZSK}.key" >"$infile"
-cp $infile $zonefile
-$SIGNER -S -x -G "cds:sha-256" -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1
-
-# Step 2:
-# It is time to submit the introduce the new KSK.
-setup step2.ksk-doubleksk.autosign
-# According to RFC 7583:
-#
-# Tpub(N+1) <= Tact(N) + Lksk - Dreg - IpubC
-# IpubC = DprpC + TTLkey (+publish-safety)
-#
-#                       |1|       |2|   |3|      |4|
-#                        |         |     |        |
-#       Key N            |<-IpubC->|<--->|<-Dreg->|<-----Lksk--- - -
-#                        |         |     |        |
-#       Key N+1          |         |     |        |
-#                        |         |     |        |
-#       Key N           Tpub      Trdy  Tsbm     Tact
-#       Key N+1
-#
-#               (continued ...)
-#
-#                   |5|       |6|   |7|      |8|      |9|    |10|
-#                    |         |     |        |        |       |
-#       Key N   - - --------------Lksk------->|<-Iret->|<----->|
-#                    |         |     |        |        |       |
-#       Key N+1      |<-IpubC->|<--->|<-Dreg->|<--------Lksk----- - -
-#                    |         |     |        |        |       |
-#       Key N                                Tret     Tdea    Trem
-#       Key N+1     Tpub      Trdy  Tsbm     Tact
-#
-#                   Tnow
-#
-# Lksk:           60d
-# Dreg:           1d
-# DprpC:          1h
-# TTLkey:         2h
-# publish-safety: 1d
-# IpubC:          27h
-#
-# Tact(N) = Tnow - Lksk + Dreg + IpubC = now - 60d + 27h
-#         = now - 1440h + 27h = now - 1413h
-TactN="now-1413h"
-ksktimes="-P ${TactN} -A ${TactN} -P sync ${TactN}"
-zsktimes="-P ${TactN} -A ${TactN}"
-KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $ksktimes $zone 2>keygen.out.$zone.1)
-ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $zsktimes $zone 2>keygen.out.$zone.2)
-$SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN "$KSK" >settime.out.$zone.1 2>&1
-$SETTIME -s -g $O -k $O $TactN -z $O $TactN "$ZSK" >settime.out.$zone.2 2>&1
-cat template.db.in "${KSK}.key" "${ZSK}.key" >"$infile"
-private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >>"$infile"
-private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile"
-cp $infile $zonefile
-$SIGNER -S -x -G "cds:sha-256" -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1
-
-# Step 3:
-# It is time to submit the DS.
-setup step3.ksk-doubleksk.autosign
-# According to RFC 7583:
-#
-# Tsbm(N+1) >= Trdy(N+1)
-# Tact(N+1) = Tsbm(N+1) + Dreg
-# Iret = DprpP + TTLds (+retire-safety)
-#
-#                   |5|       |6|   |7|      |8|      |9|    |10|
-#                    |         |     |        |        |       |
-#       Key N   - - --------------Lksk------->|<-Iret->|<----->|
-#                    |         |     |        |        |       |
-#       Key N+1      |<-IpubC->|<--->|<-Dreg->|<--------Lksk----- - -
-#                    |         |     |        |        |       |
-#       Key N                                Tret     Tdea    Trem
-#       Key N+1     Tpub      Trdy  Tsbm     Tact
-#
-#                                   Tnow
-#
-# Lksk:           60d
-# Dreg:           N/A
-# DprpP:          1h
-# TTLds:          1h
-# retire-safety:  2d
-# Iret:           50h
-# DprpC:          1h
-# TTLkey:         2h
-# publish-safety: 1d
-# IpubC:          27h
-#
-# Tact(N)    = Tnow + Lksk = now - 60d = now - 60d
-# Tret(N)    = now
-# Trem(N)    = Tnow + Iret = now + 50h
-# Tpub(N+1)  = Tnow - IpubC = now - 27h
-# Tsbm(N+1)  = now
-# Tact(N+1)  = Tret(N)
-# Tret(N+1)  = Tnow + Lksk = now + 60d
-# Trem(N+1)  = Tnow + Lksk + Iret = now + 60d + 50h
-#            = now + 1440h + 50h = 1490h
-TactN="now-60d"
-TretN="now"
-TremN="now+50h"
-TpubN1="now-27h"
-TsbmN1="now"
-TactN1="${TretN}"
-TretN1="now+60d"
-TremN1="now+1490h"
-ksktimes="-P ${TactN}  -A ${TactN}  -P sync ${TactN}  -I ${TretN}  -D ${TremN}"
-newtimes="-P ${TpubN1} -A ${TactN1} -P sync ${TsbmN1} -I ${TretN1} -D ${TremN1}"
-zsktimes="-P ${TactN}  -A ${TactN}"
-KSK1=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $ksktimes $zone 2>keygen.out.$zone.1)
-KSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $newtimes $zone 2>keygen.out.$zone.2)
-ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $zsktimes $zone 2>keygen.out.$zone.3)
-$SETTIME -s -g $H -k $O $TactN -r $O $TactN -d $O $TactN "$KSK1" >settime.out.$zone.1 2>&1
-$SETTIME -s -g $O -k $R $TpubN1 -r $R $TpubN1 -d $H $TpubN1 "$KSK2" >settime.out.$zone.2 2>&1
-$SETTIME -s -g $O -k $O $TactN -z $O $TactN "$ZSK" >settime.out.$zone.3 2>&1
-# Set key rollover relationship.
-key_successor $KSK1 $KSK2
-# Sign zone.
-cat template.db.in "${KSK1}.key" "${KSK2}.key" "${ZSK}.key" >"$infile"
-private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK1" >>"$infile"
-private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK2" >>"$infile"
-private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile"
-cp $infile $zonefile
-$SIGNER -S -x -G "cds:sha-256" -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1
-
-# Step 4:
-# The DS should be swapped now.
-setup step4.ksk-doubleksk.autosign
-# According to RFC 7583:
-#
-# Tret(N)   = Tsbm(N+1)
-# Tdea(N)   = Tret(N) + Iret
-# Tact(N+1) = Tret(N)
-#
-#                   |5|       |6|   |7|      |8|      |9|    |10|
-#                    |         |     |        |        |       |
-#       Key N   - - --------------Lksk------->|<-Iret->|<----->|
-#                    |         |     |        |        |       |
-#       Key N+1      |<-IpubC->|<--->|<-Dreg->|<--------Lksk----- - -
-#                    |         |     |        |        |       |
-#       Key N                                Tret     Tdea    Trem
-#       Key N+1     Tpub      Trdy  Tsbm     Tact
-#
-#                                                             Tnow
-#
-# Lksk: 60d
-# Dreg: N/A
-# Iret: 50h
-#
-# Tact(N)   = Tnow - Lksk - Iret = now - 60d - 50h
-#           = now - 1440h - 50h = now - 1490h
-# Tret(N)   = Tnow - Iret = now - 50h
-# Trem(N)   = Tnow
-# Tpub(N+1) = Tnow - Iret - IpubC = now - 50h - 27h
-#           = now - 77h
-# Tsbm(N+1) = Tnow - Iret = now - 50h
-# Tact(N+1) = Tret(N)
-# Tret(N+1) = Tnow + Lksk - Iret = now + 60d - 50h = now + 1390h
-# Trem(N+1) = Tnow + Lksk = now + 60d
-TactN="now-1490h"
-TretN="now-50h"
-TremN="now"
-TpubN1="now-77h"
-TsbmN1="now-50h"
-TactN1="${TretN}"
-TretN1="now+1390h"
-TremN1="now+60d"
-ksktimes="-P ${TactN}  -A ${TactN} -P sync ${TactN}  -I ${TretN}  -D ${TremN}"
-newtimes="-P ${TpubN1} -A ${TretN} -P sync ${TsbmN1} -I ${TretN1} -D ${TremN1}"
-zsktimes="-P ${TactN}  -A ${TactN}"
-KSK1=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $ksktimes $zone 2>keygen.out.$zone.1)
-KSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $newtimes $zone 2>keygen.out.$zone.2)
-ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $zsktimes $zone 2>keygen.out.$zone.3)
-$SETTIME -s -g $H -k $O $TactN -r $O $TactN -d $U $TsbmN1 -D ds $TsbmN1 "$KSK1" >settime.out.$zone.1 2>&1
-$SETTIME -s -g $O -k $O $TsbmN1 -r $O $TsbmN1 -d $R $TsbmN1 -P ds $TsbmN1 "$KSK2" >settime.out.$zone.2 2>&1
-$SETTIME -s -g $O -k $O $TactN -z $O $TactN "$ZSK" >settime.out.$zone.3 2>&1
-# Set key rollover relationship.
-key_successor $KSK1 $KSK2
-# Sign zone.
-cat template.db.in "${KSK1}.key" "${KSK2}.key" "${ZSK}.key" >"$infile"
-private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK1" >>"$infile"
-private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK2" >>"$infile"
-private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile"
-cp $infile $zonefile
-$SIGNER -S -x -G "cds:sha-256" -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1
-
-# Step 5:
-# The predecessor DNSKEY is removed long enough that is has become HIDDEN.
-setup step5.ksk-doubleksk.autosign
-# Subtract DNSKEY TTL from all the times (2h).
-# Tact(N)   = now - 1490h - 2h = now - 1492h
-# Tret(N)   = now - 50h - 2h = now - 52h
-# Trem(N)   = now - 2h
-# Tpub(N+1) = now - 77h - 2h = now - 79h
-# Tsbm(N+1) = now - 50h - 2h = now - 52h
-# Tact(N+1) = Tret(N)
-# Tret(N+1) = now + 1390h - 2h = now + 1388h
-# Trem(N+1) = now + 60d - 2h = now + 1442h
-TactN="now-1492h"
-TretN="now-52h"
-TremN="now-2h"
-TpubN1="now-79h"
-TsbmN1="now-52h"
-TactN1="${TretN}"
-TretN1="now+1388h"
-TremN1="now+1442h"
-ksktimes="-P ${TactN}  -A ${TactN} -P sync ${TactN}  -I ${TretN}  -D ${TremN}"
-newtimes="-P ${TpubN1} -A ${TretN} -P sync ${TsbmN1} -I ${TretN1} -D ${TremN1}"
-zsktimes="-P ${TactN}  -A ${TactN}"
-KSK1=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $ksktimes $zone 2>keygen.out.$zone.1)
-KSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $newtimes $zone 2>keygen.out.$zone.2)
-ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $zsktimes $zone 2>keygen.out.$zone.3)
-$SETTIME -s -g $H -k $U $TretN -r $U $TretN -d $H $TretN "$KSK1" >settime.out.$zone.1 2>&1
-$SETTIME -s -g $O -k $O $TactN1 -r $O $TactN1 -d $O $TactN1 "$KSK2" >settime.out.$zone.2 2>&1
-$SETTIME -s -g $O -k $O $TactN -z $O $TactN "$ZSK" >settime.out.$zone.3 2>&1
-# Set key rollover relationship.
-key_successor $KSK1 $KSK2
-# Sign zone.
-cat template.db.in "${KSK1}.key" "${KSK2}.key" "${ZSK}.key" >"$infile"
-private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK1" >>"$infile"
-private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK2" >>"$infile"
-private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile"
-cp $infile $zonefile
-$SIGNER -S -x -G "cds:sha-256" -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1
-
-# Step 6:
-# The predecessor DNSKEY can be purged.
-setup step6.ksk-doubleksk.autosign
-# Subtract purge-keys interval from all the times (1h).
-# Tact(N)   = now - 1492h - 1h = now - 1493h
-# Tret(N)   = now - 52h - 1h = now - 53h
-# Trem(N)   = now - 2h - 1h = now - 3h
-# Tpub(N+1) = now - 79h - 1h = now - 80h
-# Tsbm(N+1) = now - 52h - 1h = now - 53h
-# Tact(N+1) = Tret(N)
-# Tret(N+1) = now + 1388h - 1h = now + 1387h
-# Trem(N+1) = now + 1442h - 1h = now + 1441h
-TactN="now-1493h"
-TretN="now-53h"
-TremN="now-3h"
-TpubN1="now-80h"
-TsbmN1="now-53h"
-TactN1="${TretN}"
-TretN1="now+1387h"
-TremN1="now+1441h"
-ksktimes="-P ${TactN}  -A ${TactN} -P sync ${TactN}  -I ${TretN}  -D ${TremN}"
-newtimes="-P ${TpubN1} -A ${TretN} -P sync ${TsbmN1} -I ${TretN1} -D ${TremN1}"
-zsktimes="-P ${TactN}  -A ${TactN}"
-KSK1=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $ksktimes $zone 2>keygen.out.$zone.1)
-KSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $newtimes $zone 2>keygen.out.$zone.2)
-ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $zsktimes $zone 2>keygen.out.$zone.3)
-$SETTIME -s -g $H -k $H $TretN -r $H $TretN -d $H $TretN "$KSK1" >settime.out.$zone.1 2>&1
-$SETTIME -s -g $O -k $O $TactN1 -r $O $TactN1 -d $O $TactN1 "$KSK2" >settime.out.$zone.2 2>&1
-$SETTIME -s -g $O -k $O $TactN -z $O $TactN "$ZSK" >settime.out.$zone.3 2>&1
-# Set key rollover relationship.
-key_successor $KSK1 $KSK2
-# Sign zone.
-cat template.db.in "${KSK1}.key" "${KSK2}.key" "${ZSK}.key" >"$infile"
-private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK1" >>"$infile"
-private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK2" >>"$infile"
-private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile"
-cp $infile $zonefile
-$SIGNER -S -x -G "cds:sha-256" -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1
-
 #
 # The zones at csk-roll.autosign represent the various steps of a CSK rollover
 # (which is essentially a ZSK Pre-Publication / KSK Double-KSK rollover).
index 26759298b0ac8b9a995fdfa18406443069f69a12..b8de25dd80fe86bb88e5d05a0b02d9c847ff0cb9 100644 (file)
@@ -266,273 +266,6 @@ rollover_predecessor_keytimes() {
   [ "$Lzsk" = 0 ] || set_retired_removed "KEY2" "${Lzsk}" "${IretZSK}"
 }
 
-#
-# Testing KSK Double-KSK rollover.
-#
-
-# Policy parameters.
-# Lksk:      60 days (16070400 seconds)
-# Lzsk:      1 year (31536000 seconds)
-# Iret(KSK): DS TTL (1h) + DprpP (1h) + retire-safety (2d)
-# Iret(KSK): 50h (180000 seconds)
-# Iret(ZSK): RRSIG TTL (1d) + Dprp (1h) + Dsgn (1w) + retire-safety (2d)
-# Iret(ZSK): 10d1h (867600 seconds)
-Lksk=5184000
-Lzsk=31536000
-IretKSK=180000
-IretZSK=867600
-
-#
-# Zone: step1.ksk-doubleksk.autosign.
-#
-set_zone "step1.ksk-doubleksk.autosign"
-set_policy "ksk-doubleksk" "2" "7200"
-CDNSKEY="no"
-set_server "ns3" "10.53.0.3"
-# Key properties.
-key_clear "KEY1"
-set_keyrole "KEY1" "ksk"
-set_keylifetime "KEY1" "${Lksk}"
-set_keyalgorithm "KEY1" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS"
-set_keysigning "KEY1" "yes"
-set_zonesigning "KEY1" "no"
-
-key_clear "KEY2"
-set_keyrole "KEY2" "zsk"
-set_keylifetime "KEY2" "${Lzsk}"
-set_keyalgorithm "KEY2" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS"
-set_keysigning "KEY2" "no"
-set_zonesigning "KEY2" "yes"
-# Both KSK (KEY1) and ZSK (KEY2) start in OMNIPRESENT.
-set_keystate "KEY1" "GOAL" "omnipresent"
-set_keystate "KEY1" "STATE_DNSKEY" "omnipresent"
-set_keystate "KEY1" "STATE_KRRSIG" "omnipresent"
-set_keystate "KEY1" "STATE_DS" "omnipresent"
-
-set_keystate "KEY2" "GOAL" "omnipresent"
-set_keystate "KEY2" "STATE_DNSKEY" "omnipresent"
-set_keystate "KEY2" "STATE_ZRRSIG" "omnipresent"
-# Initially only two keys.
-key_clear "KEY3"
-key_clear "KEY4"
-
-# Various signing policy checks.
-check_keys
-check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
-# These keys are immediately published and activated.
-rollover_predecessor_keytimes 0
-check_keytimes
-check_apex
-check_subdomain
-dnssec_verify
-
-# Next key event is when the successor KSK needs to be published.  That is
-# the KSK lifetime - prepublication time.  The prepublication time is
-# DNSKEY TTL plus publish safety plus the zone propagation delay.
-# For the ksk-doubleksk policy that means: 60d - (1d3h) = 5086800 seconds.
-check_next_key_event 5086800
-
-#
-# Zone: step2.ksk-doubleksk.autosign.
-#
-set_zone "step2.ksk-doubleksk.autosign"
-set_policy "ksk-doubleksk" "3" "7200"
-CDNSKEY="no"
-set_server "ns3" "10.53.0.3"
-# New KSK (KEY3) is prepublished (and signs DNSKEY RRset).
-key_clear "KEY3"
-set_keyrole "KEY3" "ksk"
-set_keylifetime "KEY3" "${Lksk}"
-set_keyalgorithm "KEY3" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS"
-set_keysigning "KEY3" "yes"
-set_zonesigning "KEY3" "no"
-# Key states.
-set_keystate "KEY1" "GOAL" "hidden"
-set_keystate "KEY3" "GOAL" "omnipresent"
-set_keystate "KEY3" "STATE_DNSKEY" "rumoured"
-set_keystate "KEY3" "STATE_KRRSIG" "rumoured"
-set_keystate "KEY3" "STATE_DS" "hidden"
-
-# Various signing policy checks.
-check_keys
-check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
-
-# Set expected key times:
-# - The old keys were activated 1413 hours ago (5086800 seconds).
-rollover_predecessor_keytimes -5086800
-# - The new KSK is published now.
-created=$(key_get KEY3 CREATED)
-set_keytime "KEY3" "PUBLISHED" "${created}"
-# The new KSK should publish the CDS after the prepublication time.
-# TTLkey:         2h
-# DprpC:          1h
-# publish-safety: 1d
-# IpubC:          27h (97200 seconds)
-IpubC=97200
-set_addkeytime "KEY3" "SYNCPUBLISH" "${created}" "${IpubC}"
-set_addkeytime "KEY3" "ACTIVE" "${created}" "${IpubC}"
-set_retired_removed "KEY3" "${Lksk}" "${IretKSK}"
-
-# Continue signing policy checks.
-check_keytimes
-check_apex
-check_subdomain
-dnssec_verify
-
-# Next key event is when the successor KSK becomes OMNIPRESENT.  That is the
-# DNSKEY TTL plus the zone propagation delay, plus the publish-safety.  For
-# the ksk-doubleksk policy, this means: 7200s + 1h + 1d = 97200 seconds.
-check_next_key_event 97200
-
-#
-# Zone: step3.ksk-doubleksk.autosign.
-#
-set_zone "step3.ksk-doubleksk.autosign"
-set_policy "ksk-doubleksk" "3" "7200"
-CDNSKEY="no"
-set_server "ns3" "10.53.0.3"
-
-# The DNSKEY RRset has become omnipresent.
-# Check keys before we tell named that we saw the DS has been replaced.
-set_keystate "KEY3" "STATE_DNSKEY" "omnipresent"
-set_keystate "KEY3" "STATE_KRRSIG" "omnipresent"
-# The old DS (KEY1) can be withdrawn and the new DS (KEY3) can be introduced.
-set_keystate "KEY1" "STATE_DS" "unretentive"
-set_keystate "KEY3" "STATE_DS" "rumoured"
-
-# Various signing policy checks.
-check_keys
-check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
-# Check that CDS publication is logged.
-check_cdslog "$DIR" "$ZONE" KEY3
-
-# Set expected key times:
-# - The old keys were activated 60 days ago (5184000 seconds).
-rollover_predecessor_keytimes -5184000
-# - The new KSK is published 27 hours ago (97200 seconds).
-created=$(key_get KEY3 CREATED)
-set_addkeytime "KEY3" "PUBLISHED" "${created}" -97200
-# - The new KSK CDS is published now.
-set_keytime "KEY3" "SYNCPUBLISH" "${created}"
-syncpub=$(key_get KEY3 SYNCPUBLISH)
-set_keytime "KEY3" "ACTIVE" "${syncpub}"
-set_retired_removed "KEY3" "${Lksk}" "${IretKSK}"
-
-# Continue signing policy checks.
-check_keytimes
-check_apex
-check_subdomain
-dnssec_verify
-
-# We ignore any parent registration delay, so set the DS publish time to now.
-rndc_checkds "$SERVER" "$DIR" KEY1 "now" "withdrawn" "$ZONE"
-rndc_checkds "$SERVER" "$DIR" KEY3 "now" "published" "$ZONE"
-# Next key event is when the predecessor DS has been replaced with the
-# successor DS and enough time has passed such that the all validators that
-# have this DS RRset cached only know about the successor DS.  This is the
-# the retire interval, which is the parent propagation delay plus the DS TTL
-# plus the retire-safety.  For the ksk-double-ksk policy this means:
-# 1h + 3600s + 2d = 2d2h = 180000 seconds.
-check_next_key_event 180000
-
-#
-# Zone: step4.ksk-doubleksk.autosign.
-#
-set_zone "step4.ksk-doubleksk.autosign"
-set_policy "ksk-doubleksk" "3" "7200"
-CDNSKEY="no"
-set_server "ns3" "10.53.0.3"
-# KSK (KEY1) DNSKEY can be removed.
-set_keysigning "KEY1" "no"
-set_keystate "KEY1" "STATE_DNSKEY" "unretentive"
-set_keystate "KEY1" "STATE_KRRSIG" "unretentive"
-set_keystate "KEY1" "STATE_DS" "hidden"
-# New KSK (KEY3) DS is now OMNIPRESENT.
-set_keystate "KEY3" "STATE_DS" "omnipresent"
-
-# Various signing policy checks.
-check_keys
-check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
-
-# Set expected key times:
-# - The old keys were activated 1490 hours ago (5364000 seconds).
-rollover_predecessor_keytimes -5364000
-# - The new KSK is published 77 hours ago (277200 seconds).
-created=$(key_get KEY3 CREATED)
-set_addkeytime "KEY3" "PUBLISHED" "${created}" -277200
-published=$(key_get KEY3 PUBLISHED)
-set_addkeytime "KEY3" "SYNCPUBLISH" "${published}" "${IpubC}"
-syncpub=$(key_get KEY3 SYNCPUBLISH)
-set_keytime "KEY3" "ACTIVE" "${syncpub}"
-set_retired_removed "KEY3" "${Lksk}" "${IretKSK}"
-
-# Continue signing policy checks.
-check_keytimes
-check_apex
-check_subdomain
-dnssec_verify
-
-# Next key event is when the DNSKEY enters the HIDDEN state.  This is the
-# DNSKEY TTL plus zone propagation delay. For the ksk-doubleksk policy this is:
-# 7200s + 1h = 10800s
-check_next_key_event 10800
-
-#
-# Zone: step5.ksk-doubleksk.autosign.
-#
-set_zone "step5.ksk-doubleksk.autosign"
-set_policy "ksk-doubleksk" "3" "7200"
-CDNSKEY="no"
-set_server "ns3" "10.53.0.3"
-# KSK (KEY1) DNSKEY is now HIDDEN.
-set_keystate "KEY1" "STATE_DNSKEY" "hidden"
-set_keystate "KEY1" "STATE_KRRSIG" "hidden"
-
-# Various signing policy checks.
-check_keys
-check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
-
-# Set expected key times:
-# - The old KSK is activated 1492 hours ago (5371200 seconds).
-rollover_predecessor_keytimes -5371200
-# - The new KSK is published 79 hours ago (284400 seconds).
-created=$(key_get KEY3 CREATED)
-set_addkeytime "KEY3" "PUBLISHED" "${created}" -284400
-published=$(key_get KEY3 PUBLISHED)
-set_addkeytime "KEY3" "SYNCPUBLISH" "${published}" "${IpubC}"
-syncpub=$(key_get KEY3 SYNCPUBLISH)
-set_keytime "KEY3" "ACTIVE" "${syncpub}"
-set_retired_removed "KEY3" "${Lksk}" "${IretKSK}"
-
-# Various signing policy checks.
-check_keytimes
-check_apex
-check_subdomain
-dnssec_verify
-
-# Next key event is when the new successor needs to be published.  This is the
-# KSK lifetime minus Ipub minus Iret minus DNSKEY TTL.  For the
-# ksk-doubleksk this is: 60d - 1d3h - 1d - 2d2h - 2h =
-# 5184000 - 97200 - 180000 - 7200 = 4813200 seconds.
-check_next_key_event 4899600
-
-#
-# Zone: step6.ksk-doubleksk.autosign.
-#
-set_zone "step6.ksk-doubleksk.autosign"
-set_policy "ksk-doubleksk" "2" "7200"
-CDNSKEY="no"
-set_server "ns3" "10.53.0.3"
-# KSK (KEY1) DNSKEY is purged.
-key_clear "KEY1"
-
-# Various signing policy checks.
-check_keys
-check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
-check_apex
-check_subdomain
-dnssec_verify
-
 #
 # Testing CSK key rollover (1).
 #
index 209d72cb09e4067cdd6dbeb78a45086fd255af18..80e76fae87a2fe46015b5ab21377fab75a249927 100644 (file)
@@ -67,3 +67,26 @@ dnssec-policy "zsk-prepub" {
        zone-propagation-delay PT1H;
        max-zone-ttl 1d;
 };
+
+dnssec-policy "ksk-doubleksk" {
+       signatures-refresh P1W;
+       signatures-validity P2W;
+       signatures-validity-dnskey P2W;
+
+       dnskey-ttl 2h;
+       publish-safety P1D;
+       retire-safety P2D;
+       purge-keys PT1H;
+
+       cdnskey no;
+       keys {
+               ksk key-directory lifetime P60D algorithm @DEFAULT_ALGORITHM@;
+               zsk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@;
+       };
+
+       zone-propagation-delay PT1H;
+       max-zone-ttl 1d;
+
+       parent-ds-ttl 3600;
+       parent-propagation-delay PT1H;
+};
index 309014cb1ba54f8666a8482be6a1c959597a9432..141d75c0e2495416fd8c54ee42a5bfbdfdc20cef 100644 (file)
@@ -125,3 +125,37 @@ zone "step6.zsk-prepub.autosign" {
        file "step6.zsk-prepub.autosign.db";
        dnssec-policy "zsk-prepub";
 };
+
+/*
+ * Zones for testing KSK Double-KSK steps.
+ */
+zone "step1.ksk-doubleksk.autosign" {
+       type primary;
+       file "step1.ksk-doubleksk.autosign.db";
+       dnssec-policy "ksk-doubleksk";
+};
+zone "step2.ksk-doubleksk.autosign" {
+       type primary;
+       file "step2.ksk-doubleksk.autosign.db";
+       dnssec-policy "ksk-doubleksk";
+};
+zone "step3.ksk-doubleksk.autosign" {
+       type primary;
+       file "step3.ksk-doubleksk.autosign.db";
+       dnssec-policy "ksk-doubleksk";
+};
+zone "step4.ksk-doubleksk.autosign" {
+       type primary;
+       file "step4.ksk-doubleksk.autosign.db";
+       dnssec-policy "ksk-doubleksk";
+};
+zone "step5.ksk-doubleksk.autosign" {
+       type primary;
+       file "step5.ksk-doubleksk.autosign.db";
+       dnssec-policy "ksk-doubleksk";
+};
+zone "step6.ksk-doubleksk.autosign" {
+       type primary;
+       file "step6.ksk-doubleksk.autosign.db";
+       dnssec-policy "ksk-doubleksk";
+};
index 23920a0ab89bd52aaf8259f8eefc6b78147b71f3..dd13005a3d700472695318e2234e9b801c010254 100644 (file)
@@ -316,4 +316,203 @@ private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK2" >>"$infile"
 cp $infile $zonefile
 $SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1
 
+#
+# The zones at ksk-doubleksk.autosign represent the various steps of a KSK
+# Double-KSK rollover.
+#
+
+# Step 1:
+# Introduce the first key. This will immediately be active.
+setup step1.ksk-doubleksk.autosign
+TactN="now-7d"
+keytimes="-P ${TactN} -A ${TactN}"
+KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $keytimes $zone 2>keygen.out.$zone.1)
+ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $keytimes $zone 2>keygen.out.$zone.2)
+$SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN "$KSK" >settime.out.$zone.1 2>&1
+$SETTIME -s -g $O -k $O $TactN -z $O $TactN "$ZSK" >settime.out.$zone.2 2>&1
+cat template.db.in "${KSK}.key" "${ZSK}.key" >"$infile"
+cp $infile $zonefile
+$SIGNER -S -x -G "cds:sha-256" -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1
+
+# Step 2:
+# It is time to submit the introduce the new KSK.
+setup step2.ksk-doubleksk.autosign
+# Lksk:           60d
+# Dreg:           n/a
+# DprpC:          1h
+# TTLds:          1d
+# TTLkey:         2h
+# publish-safety: 1d
+# retire-safety:  2d
+#
+# According to RFC 7583:
+# Tpub(N+1) <= Tact(N) + Lksk - Dreg - IpubC
+# IpubC = DprpC + TTLkey (+publish-safety)
+#
+# IpubC   = 27h
+# Tact(N) = now - Lksk + Dreg + IpubC = now - 60d + 27h
+#         = now - 1440h + 27h = now - 1413h
+TactN="now-1413h"
+keytimes="-P ${TactN} -A ${TactN}"
+KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $keytimes $zone 2>keygen.out.$zone.1)
+ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $keytimes $zone 2>keygen.out.$zone.2)
+$SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN "$KSK" >settime.out.$zone.1 2>&1
+$SETTIME -s -g $O -k $O $TactN -z $O $TactN "$ZSK" >settime.out.$zone.2 2>&1
+cat template.db.in "${KSK}.key" "${ZSK}.key" >"$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >>"$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile"
+cp $infile $zonefile
+$SIGNER -S -x -G "cds:sha-256" -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1
+
+# Step 3:
+# It is time to submit the DS.
+setup step3.ksk-doubleksk.autosign
+# According to RFC 7583:
+# Iret = DprpP + TTLds (+retire-safety)
+#
+# Iret       = 50h
+# Tpub(N)    = now - Lksk = now - 60d = now - 60d
+# Tact(N)    = now - 1413h
+# Tret(N)    = now
+# Trem(N)    = now + Iret = now + 50h
+# Tpub(N+1)  = now - IpubC = now - 27h
+# Tact(N+1)  = now
+# Tret(N+1)  = now + Lksk = now + 60d
+# Trem(N+1)  = now + Lksk + Iret = now + 60d + 50h
+#            = now + 1440h + 50h = 1490h
+TpubN="now-60d"
+TactN="now-1413h"
+TretN="now"
+TremN="now+50h"
+TpubN1="now-27h"
+TactN1="now"
+TretN1="now+60d"
+TremN1="now+1490h"
+ksktimes="-P ${TpubN}  -A ${TpubN}  -P sync ${TactN}  -I ${TretN}  -D ${TremN} -D sync ${TactN1}"
+newtimes="-P ${TpubN1} -A ${TactN1} -P sync ${TactN1} -I ${TretN1} -D ${TremN1}"
+zsktimes="-P ${TpubN}  -A ${TpubN}"
+KSK1=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $ksktimes $zone 2>keygen.out.$zone.1)
+KSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $newtimes $zone 2>keygen.out.$zone.2)
+ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $zsktimes $zone 2>keygen.out.$zone.3)
+$SETTIME -s -g $H -k $O $TpubN -r $O $TpubN -d $O $TactN "$KSK1" >settime.out.$zone.1 2>&1
+$SETTIME -s -g $O -k $R $TpubN1 -r $R $TpubN1 -d $H $TpubN1 "$KSK2" >settime.out.$zone.2 2>&1
+$SETTIME -s -g $O -k $O $TpubN -z $O $TpubN "$ZSK" >settime.out.$zone.3 2>&1
+# Set key rollover relationship.
+key_successor $KSK1 $KSK2
+# Sign zone.
+cat template.db.in "${KSK1}.key" "${KSK2}.key" "${ZSK}.key" >"$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK1" >>"$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK2" >>"$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile"
+cp $infile $zonefile
+$SIGNER -S -x -G "cds:sha-256" -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1
+
+# Step 4:
+# The DS should be swapped now.
+setup step4.ksk-doubleksk.autosign
+# Tpub(N)    = now - Lksk - Iret = now - 60d - 50h
+#            = now - 1440h - 50h = now - 1490h
+# Tact(N)    = now - 1490h + 27h = now - 1463h
+# Tret(N)    = now - Iret = now - 50h
+# Trem(N)    = now
+# Tpub(N+1)  = now - Iret - IpubC = now - 50h - 27h
+#            = now - 77h
+# Tact(N+1)  = Tret(N)
+# Tret(N+1)  = now + Lksk - Iret = now + 60d - 50h = now + 1390h
+# Trem(N+1)  = now + Lksk = now + 60d
+TpubN="now-1490h"
+TactN="now-1463h"
+TretN="now-50h"
+TremN="now"
+TpubN1="now-77h"
+TactN1="${TretN}"
+TretN1="now+1390h"
+TremN1="now+60d"
+ksktimes="-P ${TpubN}  -A ${TpubN}  -P sync ${TactN}  -I ${TretN}   -D ${TremN} -D sync ${TactN1}"
+newtimes="-P ${TpubN1} -A ${TactN1} -P sync ${TactN1} -I ${TretN1}  -D ${TremN1}"
+zsktimes="-P ${TpubN}  -A ${TpubN}"
+KSK1=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $ksktimes $zone 2>keygen.out.$zone.1)
+KSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $newtimes $zone 2>keygen.out.$zone.2)
+ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $zsktimes $zone 2>keygen.out.$zone.3)
+$SETTIME -s -g $H -k $O $TactN -r $O $TactN -d $U $TretN -D ds $TretN "$KSK1" >settime.out.$zone.1 2>&1
+$SETTIME -s -g $O -k $O $TactN1 -r $O $TactN1 -d $R $TactN1 -P ds $TactN1 "$KSK2" >settime.out.$zone.2 2>&1
+$SETTIME -s -g $O -k $O $TactN -z $O $TactN "$ZSK" >settime.out.$zone.3 2>&1
+# Set key rollover relationship.
+key_successor $KSK1 $KSK2
+# Sign zone.
+cat template.db.in "${KSK1}.key" "${KSK2}.key" "${ZSK}.key" >"$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK1" >>"$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK2" >>"$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile"
+cp $infile $zonefile
+$SIGNER -S -x -G "cds:sha-256" -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1
 
+# Step 5:
+# The predecessor DNSKEY is removed long enough that is has become HIDDEN.
+setup step5.ksk-doubleksk.autosign
+# Subtract DNSKEY TTL + zone-propagation-delay from all the times (3h).
+# Tpub(N)    = now - 1490h - 3h = now - 1493h
+# Tact(N)    = now - 1463h - 3h = now - 1466h
+# Tret(N)    = now - 50h - 3h = now - 53h
+# Trem(N)    = now - 3h
+# Tpub(N+1)  = now - 77h - 3h = now - 80h
+# Tact(N+1)  = Tret(N)
+# Tret(N+1)  = now + 1390h - 3h = now + 1387h
+# Trem(N+1)  = now + 60d - 3h = now + 1441h
+TpubN="now-1493h"
+TactN="now-1466h"
+TretN="now-53h"
+TremN="now-3h"
+TpubN1="now-80h"
+TactN1="${TretN}"
+TretN1="now+1387h"
+TremN1="now+1441h"
+ksktimes="-P ${TpubN}  -A ${TpubN}  -P sync ${TactN}  -I ${TretN}  -D ${TremN} -D sync ${TactN1}"
+newtimes="-P ${TpubN1} -A ${TactN1} -P sync ${TactN1} -I ${TretN1} -D ${TremN1}"
+zsktimes="-P ${TpubN}  -A ${TpubN}"
+KSK1=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $ksktimes $zone 2>keygen.out.$zone.1)
+KSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $newtimes $zone 2>keygen.out.$zone.2)
+ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $zsktimes $zone 2>keygen.out.$zone.3)
+$SETTIME -s -g $H -k $U $TretN -r $U $TretN -d $H $TretN "$KSK1" >settime.out.$zone.1 2>&1
+$SETTIME -s -g $O -k $O $TactN1 -r $O $TactN1 -d $O $TactN1 "$KSK2" >settime.out.$zone.2 2>&1
+$SETTIME -s -g $O -k $O $TactN -z $O $TactN "$ZSK" >settime.out.$zone.3 2>&1
+# Set key rollover relationship.
+key_successor $KSK1 $KSK2
+# Sign zone.
+cat template.db.in "${KSK1}.key" "${KSK2}.key" "${ZSK}.key" >"$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK1" >>"$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK2" >>"$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile"
+cp $infile $zonefile
+$SIGNER -S -x -G "cds:sha-256" -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1
+
+# Step 6:
+# The predecessor DNSKEY can be purged.
+setup step6.ksk-doubleksk.autosign
+# Subtract purge-keys interval from all the times (1h).
+TpubN="now-1494h"
+TactN="now-1467h"
+TretN="now-54h"
+TremN="now-4h"
+TpubN1="now-81h"
+TactN1="${TretN}"
+TretN1="now+1386h"
+TremN1="now+1440h"
+ksktimes="-P ${TpubN}  -A ${TpubN}  -P sync ${TactN}  -I ${TretN}  -D ${TremN} -D sync ${TactN1}"
+newtimes="-P ${TpubN1} -A ${TactN1} -P sync ${TactN1} -I ${TretN1} -D ${TremN1}"
+zsktimes="-P ${TpubN}  -A ${TpubN}"
+KSK1=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $ksktimes $zone 2>keygen.out.$zone.1)
+KSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $newtimes $zone 2>keygen.out.$zone.2)
+ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $zsktimes $zone 2>keygen.out.$zone.3)
+$SETTIME -s -g $H -k $H $TretN -r $H $TretN -d $H $TretN "$KSK1" >settime.out.$zone.1 2>&1
+$SETTIME -s -g $O -k $O $TactN1 -r $O $TactN1 -d $O $TactN1 "$KSK2" >settime.out.$zone.2 2>&1
+$SETTIME -s -g $O -k $O $TactN -z $O $TactN "$ZSK" >settime.out.$zone.3 2>&1
+# Set key rollover relationship.
+key_successor $KSK1 $KSK2
+# Sign zone.
+cat template.db.in "${KSK1}.key" "${KSK2}.key" "${ZSK}.key" >"$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK1" >>"$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK2" >>"$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile"
+cp $infile $zonefile
+$SIGNER -S -x -G "cds:sha-256" -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1
index 45e252307e208cec0857921714d4cb07f413c4be..2fc796b1ad8b83c0b3570fa10e700ed4fa86dec5 100644 (file)
@@ -388,6 +388,9 @@ def check_rollover_step(server, config, policy, step):
     zone = step["zone"]
     keyprops = step["keyprops"]
     nextev = step["nextev"]
+    cdss = []
+    if step.get("cdss"):
+        cdss = step["cdss"]
     keyrelationships = None
     if step.get("keyrelationships"):
         keyrelationships = step["keyrelationships"]
@@ -423,9 +426,13 @@ def check_rollover_step(server, config, policy, step):
         key = kp.key
 
         if kp.metadata["DSState"] == "rumoured":
-            isctest.kasp.check_cdslog(server, zone, key, "CDS (SHA-256)")
-            isctest.kasp.check_cdslog(server, zone, key, "CDNSKEY")
-            isctest.kasp.check_cdslog_prohibit(server, zone, key, "CDS (SHA-384)")
+            assert cdss is not None
+
+            for algstr in ["CDNSKEY", "CDS (SHA-256)", "CDS (SHA-384)"]:
+                if algstr in cdss:
+                    isctest.kasp.check_cdslog(server, zone, key, algstr)
+                else:
+                    isctest.kasp.check_cdslog_prohibit(server, zone, key, algstr)
 
             # The DS can be introduced. We ignore any parent registration delay,
             # so set the DS publish time to now.
@@ -451,6 +458,7 @@ def check_rollover_step(server, config, policy, step):
 def test_rollover_enable_dnssec(servers):
     server = servers["ns3"]
     policy = "enable-dnssec"
+    cdss = ["CDNSKEY", "CDS (SHA-256)"]
     config = {
         "dnskey-ttl": timedelta(seconds=300),
         "ds-ttl": timedelta(hours=2),
@@ -480,6 +488,7 @@ def test_rollover_enable_dnssec(servers):
         {
             # Step 1.
             "zone": "step1.enable-dnssec.autosign",
+            "cdss": cdss,
             "keyprops": [
                 f"csk unlimited {alg} {size} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden offset:{offsets['step1']}",
             ],
@@ -490,6 +499,7 @@ def test_rollover_enable_dnssec(servers):
         {
             # Step 2.
             "zone": "step2.enable-dnssec.autosign",
+            "cdss": cdss,
             # The DNSKEY is omnipresent, but the zone signatures not yet.
             # Thus, the DS remains hidden.
             # dnskey: rumoured -> omnipresent
@@ -504,6 +514,7 @@ def test_rollover_enable_dnssec(servers):
         {
             # Step 3.
             "zone": "step3.enable-dnssec.autosign",
+            "cdss": cdss,
             # All signatures should be omnipresent, so the DS can be submitted.
             # zrrsig: rumoured -> omnipresent
             # ds: hidden -> rumoured
@@ -517,6 +528,7 @@ def test_rollover_enable_dnssec(servers):
         {
             # Step 4.
             "zone": "step4.enable-dnssec.autosign",
+            "cdss": cdss,
             # DS has been published long enough.
             # ds: rumoured -> omnipresent
             "keyprops": [
@@ -669,3 +681,153 @@ def test_rollover_zsk_prepublication(servers):
 
     for step in steps:
         check_rollover_step(server, config, policy, step)
+
+
+def test_rollover_ksk_doubleksk(servers):
+    server = servers["ns3"]
+    policy = "ksk-doubleksk"
+    cdss = ["CDS (SHA-256)"]
+    config = {
+        "dnskey-ttl": timedelta(hours=2),
+        "ds-ttl": timedelta(seconds=3600),
+        "max-zone-ttl": timedelta(days=1),
+        "parent-propagation-delay": timedelta(hours=1),
+        "publish-safety": timedelta(days=1),
+        "purge-keys": timedelta(hours=1),
+        "retire-safety": timedelta(days=2),
+        "signatures-refresh": timedelta(days=7),
+        "signatures-validity": timedelta(days=14),
+        "zone-propagation-delay": timedelta(hours=1),
+    }
+    ttl = int(config["dnskey-ttl"].total_seconds())
+    alg = os.environ["DEFAULT_ALGORITHM_NUMBER"]
+    size = os.environ["DEFAULT_BITS"]
+    ksk_lifetime = timedelta(days=60)
+    lifetime_policy = int(ksk_lifetime.total_seconds())
+
+    ipub = Ipub(config)
+    ipubc = IpubC(config)
+    iret = Iret(config, zsk=False, ksk=True)
+    keyttlprop = config["dnskey-ttl"] + config["zone-propagation-delay"]
+    offsets = {}
+    offsets["step1-p"] = -int(timedelta(days=7).total_seconds())
+    offsets["step2-p"] = -int(ksk_lifetime.total_seconds() - ipubc.total_seconds())
+    offsets["step2-s"] = 0
+    offsets["step3-p"] = -int(ksk_lifetime.total_seconds())
+    offsets["step3-s"] = -int(ipubc.total_seconds())
+    offsets["step4-p"] = offsets["step3-p"] - int(iret.total_seconds())
+    offsets["step4-s"] = offsets["step3-s"] - int(iret.total_seconds())
+    offsets["step5-p"] = offsets["step4-p"] - int(keyttlprop.total_seconds())
+    offsets["step5-s"] = offsets["step4-s"] - int(keyttlprop.total_seconds())
+    offsets["step6-p"] = offsets["step5-p"] - int(config["purge-keys"].total_seconds())
+    offsets["step6-s"] = offsets["step5-s"] - int(config["purge-keys"].total_seconds())
+
+    steps = [
+        {
+            # Step 1.
+            # Introduce the first key. This will immediately be active.
+            "zone": "step1.ksk-doubleksk.autosign",
+            "cdss": cdss,
+            "keyprops": [
+                f"zsk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{offsets['step1-p']}",
+                f"ksk {lifetime_policy} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{offsets['step1-p']}",
+            ],
+            # Next key event is when the successor KSK needs to be published.
+            # That is the KSK lifetime - prepublication time (minus time
+            # already passed).
+            "nextev": ksk_lifetime - ipub - timedelta(days=7),
+        },
+        {
+            # Step 2.
+            # Successor KSK is prepublished (and signs DNSKEY RRset).
+            # KSK1 goal: omnipresent -> hidden
+            # KSK2 goal: hidden -> omnipresent
+            # KSK2 dnskey: hidden -> rumoured
+            # KSK2 krrsig: hidden -> rumoured
+            "zone": "step2.ksk-doubleksk.autosign",
+            "cdss": cdss,
+            "keyprops": [
+                f"zsk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{offsets['step2-p']}",
+                f"ksk {lifetime_policy} {alg} {size} goal:hidden dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{offsets['step2-p']}",
+                f"ksk {lifetime_policy} {alg} {size} goal:omnipresent dnskey:rumoured krrsig:rumoured ds:hidden offset:{offsets['step2-s']}",
+            ],
+            "keyrelationships": [1, 2],
+            # Next key event is when the successor KSK becomes OMNIPRESENT.
+            "nextev": ipub,
+        },
+        {
+            # Step 3.
+            # The successor DNSKEY RRset has become omnipresent.  The
+            # predecessor DS  can be withdrawn and the successor DS can be
+            # introduced.
+            # KSK1 ds: omnipresent -> unretentive
+            # KSK2 dnskey: rumoured -> omnipresent
+            # KSK2 krrsig: rumoured -> omnipresent
+            # KSK2 ds: hidden -> rumoured
+            "zone": "step3.ksk-doubleksk.autosign",
+            "cdss": cdss,
+            "keyprops": [
+                f"zsk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{offsets['step3-p']}",
+                f"ksk {lifetime_policy} {alg} {size} goal:hidden dnskey:omnipresent krrsig:omnipresent ds:unretentive offset:{offsets['step3-p']}",
+                f"ksk {lifetime_policy} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:rumoured offset:{offsets['step3-s']}",
+            ],
+            "keyrelationships": [1, 2],
+            # Next key event is when the predecessor DS has been replaced with
+            # the successor DS and enough time has passed such that the all
+            # validators that have this DS RRset cached only know about the
+            # successor DS.  This is the the retire interval.
+            "nextev": iret,
+        },
+        {
+            # Step 4.
+            # The predecessor DNSKEY may be removed, the successor DS is
+            # omnipresent.
+            # KSK1 dnskey: omnipresent -> unretentive
+            # KSK1 krrsig: omnipresent -> unretentive
+            # KSK1 ds: unretentive -> hidden
+            # KSK2 ds: rumoured -> omnipresent
+            "zone": "step4.ksk-doubleksk.autosign",
+            "cdss": cdss,
+            "keyprops": [
+                f"zsk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{offsets['step4-p']}",
+                f"ksk {lifetime_policy} {alg} {size} goal:hidden dnskey:unretentive krrsig:unretentive ds:hidden offset:{offsets['step4-p']}",
+                f"ksk {lifetime_policy} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{offsets['step4-s']}",
+            ],
+            "keyrelationships": [1, 2],
+            # Next key event is when the DNSKEY enters the HIDDEN state.
+            # This is the DNSKEY TTL plus zone propagation delay.
+            "nextev": keyttlprop,
+        },
+        {
+            # Step 5.
+            # The predecessor DNSKEY is long enough removed from the zone it
+            # has become hidden.
+            # KSK1 dnskey: unretentive -> hidden
+            # KSK1 krrsig: unretentive -> hidden
+            "zone": "step5.ksk-doubleksk.autosign",
+            "cdss": cdss,
+            "keyprops": [
+                f"zsk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{offsets['step5-p']}",
+                f"ksk {lifetime_policy} {alg} {size} goal:hidden dnskey:hidden krrsig:hidden ds:hidden offset:{offsets['step5-p']}",
+                f"ksk {lifetime_policy} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{offsets['step5-s']}",
+            ],
+            "keyrelationships": [1, 2],
+            # Next key event is when the new successor needs to be published.
+            # This is the KSK lifetime minus Ipub minus Iret minus time elapsed.
+            "nextev": ksk_lifetime - ipub - iret - keyttlprop,
+        },
+        {
+            # Step 6.
+            # Predecessor KSK is now purged.
+            "zone": "step6.ksk-doubleksk.autosign",
+            "cdss": cdss,
+            "keyprops": [
+                f"zsk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{offsets['step6-p']}",
+                f"ksk {lifetime_policy} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{offsets['step6-s']}",
+            ],
+            "nextev": None,
+        },
+    ]
+
+    for step in steps:
+        check_rollover_step(server, config, policy, step)