[9.20] new: usr: Support for Offline KSK implemented

Add a new configuration option `offline-ksk` to enable Offline KSK key management. Signed Key Response (SKR) files created with `dnssec-ksr` (or other program) can now be imported into `named` with the new `rndc skr -import` command. Rather than creating new DNSKEY, CDS and CDNSKEY records and generating signatures covering these types, these records are loaded from the currently active bundle from the imported SKR. 

The implementation is loosely based on: https://www.iana.org/dnssec/archive/files/draft-icann-dnssec-keymgmt-01.txt

Closes #1128

Backport of MR !9119

Merge branch 'backport-1128-offline-ksk-rndc-import-skr-9.20' into 'bind-9.20'

See merge request isc-projects/bind9!9389
This commit is contained in:
Matthijs Mekking 2024-08-22 10:17:23 +00:00
commit 3555094a68
43 changed files with 2979 additions and 152 deletions

View file

@ -299,6 +299,7 @@ dnssec-policy \"default\" {\n\
cds-digest-types { 2; };\n\
dnskey-ttl " DNS_KASP_KEY_TTL ";\n\
inline-signing yes;\n\
offline-ksk no;\n\
publish-safety " DNS_KASP_PUBLISH_SAFETY "; \n\
retire-safety " DNS_KASP_RETIRE_SAFETY "; \n\
purge-keys " DNS_KASP_PURGE_KEYS "; \n\

View file

@ -224,6 +224,8 @@ named_control_docommand(isccc_sexpr_t *message, bool readonly,
result = named_server_flushnode(named_g_server, lex, true);
} else if (command_compare(command, NAMED_COMMAND_FREEZE)) {
result = named_server_freeze(named_g_server, true, lex, text);
} else if (command_compare(command, NAMED_COMMAND_SKR)) {
result = named_server_skr(named_g_server, lex, text);
} else if (command_compare(command, NAMED_COMMAND_LOADKEYS) ||
command_compare(command, NAMED_COMMAND_SIGN))
{

View file

@ -58,6 +58,7 @@
#define NAMED_COMMAND_MODZONE "modzone"
#define NAMED_COMMAND_DELZONE "delzone"
#define NAMED_COMMAND_SHOWZONE "showzone"
#define NAMED_COMMAND_SKR "skr"
#define NAMED_COMMAND_SYNC "sync"
#define NAMED_COMMAND_SIGNING "signing"
#define NAMED_COMMAND_DNSSEC "dnssec"

View file

@ -375,3 +375,9 @@ named_server_servestale(named_server_t *server, isc_lex_t *lex,
isc_result_t
named_server_fetchlimit(named_server_t *server, isc_lex_t *lex,
isc_buffer_t **text);
/*%
* Import SKR file for offline KSK signing.
*/
isc_result_t
named_server_skr(named_server_t *server, isc_lex_t *lex, isc_buffer_t **text);

View file

@ -16703,3 +16703,68 @@ cleanup:
return (result);
}
isc_result_t
named_server_skr(named_server_t *server, isc_lex_t *lex, isc_buffer_t **text) {
isc_result_t result = ISC_R_SUCCESS;
dns_zone_t *zone = NULL;
dns_kasp_t *kasp = NULL;
const char *ptr;
char skrfile[PATH_MAX];
/* Skip the command name. */
ptr = next_token(lex, text);
if (ptr == NULL) {
return (ISC_R_UNEXPECTEDEND);
}
/* Find out what we are to do. */
ptr = next_token(lex, text);
if (ptr == NULL) {
return (ISC_R_UNEXPECTEDEND);
}
if (strcasecmp(ptr, "-import") != 0) {
CHECK(DNS_R_SYNTAX);
}
ptr = next_token(lex, NULL);
if (ptr == NULL) {
return (ISC_R_UNEXPECTEDEND);
}
(void)snprintf(skrfile, sizeof(skrfile), "%s", ptr);
CHECK(zone_from_args(server, lex, NULL, &zone, NULL, text, false));
if (zone == NULL) {
CHECK(ISC_R_UNEXPECTEDEND);
}
kasp = dns_zone_getkasp(zone);
if (kasp == NULL) {
CHECK(putstr(text, "zone does not have a dnssec-policy"));
CHECK(putnull(text));
goto cleanup;
}
if (!dns_kasp_offlineksk(kasp)) {
CHECK(putstr(text, "zone does not have offline-ksk enabled"));
CHECK(putnull(text));
goto cleanup;
}
result = dns_zone_import_skr(zone, skrfile);
if (result != ISC_R_SUCCESS) {
CHECK(putstr(text, "import failed: "));
CHECK(putstr(text, isc_result_totext(result)));
CHECK(putnull(text));
} else {
/* Schedule a rekey */
dns_zone_rekey(zone, false);
}
cleanup:
if (zone != NULL) {
dns_zone_detach(&zone);
}
return (result);
}

View file

@ -132,6 +132,9 @@ command is one of the following:\n\
halt Stop the server without saving pending updates.\n\
halt -p Stop the server without saving pending updates reporting\n\
process id.\n\
skr -import file zone [class [view]]\n\
Import a SKR file for the specified zone, for offline KSK\n\
signing.\n\
loadkeys zone [class [view]]\n\
Update keys without signing immediately.\n\
managed-keys refresh [class [view]]\n\

View file

@ -257,6 +257,11 @@ Currently supported commands are:
See also :option:`rndc stop`.
.. option:: skr -import file zone [class [view]]
This command allows you to import a SKR file for the specified zone, to
support offline KSK signing.
.. option:: loadkeys [zone [class [view]]]
This command fetches all DNSSEC keys for the given zone from the key directory. If

View file

@ -30,6 +30,7 @@ dnssec-policy "test" {
};
max-zone-ttl 86400;
nsec3param iterations 0 optout no salt-length 8;
offline-ksk no;
parent-ds-ttl 7200;
parent-propagation-delay PT1H;
publish-safety PT3600S;

View file

@ -0,0 +1,31 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* SPDX-License-Identifier: MPL-2.0
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
/*
* Offline KSK is not possible with CSK
* (even if there are other key roles present).
*/
dnssec-policy "bad-offline-ksk" {
offline-ksk yes;
keys {
ksk lifetime P10Y algorithm rsasha256;
zsk lifetime P10Y algorithm rsasha256;
csk lifetime P10Y algorithm rsasha256;
};
};
zone "example.net" {
type primary;
file "example.db";
dnssec-policy "bad-offline-ksk";
};

View file

@ -676,6 +676,14 @@ grep "dnssec-policy: key with algorithm rsasha256 has invalid key length 511" <c
if [ $ret -ne 0 ]; then echo_i "failed"; fi
status=$((status + ret))
n=$((n + 1))
echo_i "checking named-checkconf kasp offline-ksk with csk errors ($n)"
ret=0
$CHECKCONF kasp-bad-offline-ksk.conf >checkconf.out$n 2>&1 && ret=1
grep "dnssec-policy: csk keys are not allowed when offline-ksk is enabled" <checkconf.out$n >/dev/null || ret=1
if [ $ret -ne 0 ]; then echo_i "failed"; fi
status=$((status + ret))
n=$((n + 1))
echo_i "checking named-checkconf kasp signatures refresh errors ($n)"
ret=0

View file

@ -754,10 +754,12 @@ _check_keys() {
_ret=0
# Clear key ids.
key_set KEY1 ID "no"
key_set KEY2 ID "no"
key_set KEY3 ID "no"
key_set KEY4 ID "no"
if [ "$1" != "keep" ]; then
key_set KEY1 ID "no"
key_set KEY2 ID "no"
key_set KEY3 ID "no"
key_set KEY4 ID "no"
fi
# Check key files.
_ids=$(get_keyids "$DIR" "$ZONE")
@ -808,6 +810,9 @@ _check_keys() {
# Found key identifiers are stored in the right key array.
# Keys are found if they are stored inside $DIR or in a subdirectory up to
# three levels deeper.
#
# If $1 is set, we keep keys that are already found and don't look for them
# again.
check_keys() {
n=$((n + 1))
echo_i "check keys are created for zone ${ZONE} ($n)"
@ -824,7 +829,7 @@ check_keys() {
# Temporarily don't log errors because we are searching multiple files.
disable_logerror
retry_quiet 3 _check_keys || ret=1
retry_quiet 3 _check_keys $1 || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))

View file

@ -17,15 +17,22 @@ rm -f ./*.ksk*
rm -f ./*.zsk*
rm -f ./created.out
rm -f ./footer.*
rm -f ./keygen.out.*
rm -f ./named.conf
rm -f ./now.out
rm -rf ./offline
rm -f ./ns1/*.db
rm -f ./ns1/*.db.jbk
rm -f ./ns1/*.db.signed
rm -f ./ns1/*.db.signed.jnl
rm -f ./ns1/K*
rm -f ./ns1/keygen.out.*
rm -f ./ns1/named.conf
rm -f ./ns1/named.memstats
rm -f ./ns1/named.run
rm -f ./python.out
rm -f ./settime.out.*
rm -f ./K*
rm -rf ./keydir
rm -f ./ksr.*.err.*
rm -f ./ksr.*.expect
rm -f ./ksr.*.expect.*
rm -f ./ksr.*.out.*
rm -rf ./ns1/keydir
rm -rf ./ns1/offline

View file

@ -11,7 +11,31 @@
* information regarding copyright ownership.
*/
options {
query-source address 10.53.0.1;
notify-source 10.53.0.1;
transfer-source 10.53.0.1;
port @PORT@;
pid-file "named.pid";
listen-on { 10.53.0.1; };
listen-on-v6 { none; };
allow-transfer { any; };
recursion no;
dnssec-validation no;
allow-new-zones yes;
};
key rndc_key {
secret "1234abcd8765";
algorithm @DEFAULT_HMAC@;
};
controls {
inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
};
dnssec-policy "common" {
offline-ksk yes;
keys {
ksk lifetime unlimited algorithm @DEFAULT_ALGORITHM@;
zsk lifetime P6M algorithm @DEFAULT_ALGORITHM@;
@ -19,12 +43,14 @@ dnssec-policy "common" {
};
dnssec-policy "csk" {
offline-ksk no;
keys {
csk lifetime P6M algorithm @DEFAULT_ALGORITHM@;
};
};
dnssec-policy "unlimited" {
offline-ksk yes;
keys {
ksk lifetime unlimited algorithm @DEFAULT_ALGORITHM@;
zsk lifetime unlimited algorithm @DEFAULT_ALGORITHM@;
@ -32,6 +58,7 @@ dnssec-policy "unlimited" {
};
dnssec-policy "no-cdnskey" {
offline-ksk yes;
keys {
ksk lifetime unlimited algorithm @DEFAULT_ALGORITHM@;
zsk lifetime unlimited algorithm @DEFAULT_ALGORITHM@;
@ -41,6 +68,7 @@ dnssec-policy "no-cdnskey" {
};
dnssec-policy "no-cds" {
offline-ksk yes;
keys {
ksk lifetime unlimited algorithm @DEFAULT_ALGORITHM@;
zsk lifetime unlimited algorithm @DEFAULT_ALGORITHM@;
@ -49,6 +77,7 @@ dnssec-policy "no-cds" {
};
dnssec-policy "two-tone" {
offline-ksk yes;
keys {
ksk lifetime unlimited algorithm @DEFAULT_ALGORITHM@;
ksk lifetime unlimited algorithm @ALTERNATIVE_ALGORITHM@;

View file

@ -0,0 +1,47 @@
#!/bin/sh -e
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
#
# SPDX-License-Identifier: MPL-2.0
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, you can obtain one at https://mozilla.org/MPL/2.0/.
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
# shellcheck source=conf.sh
. ../../conf.sh
# Key directories
mkdir keydir
mkdir offline
# Zone files
cp template.db.in common.test.db
cp template.db.in past.test.db
cp template.db.in future.test.db
cp template.db.in last-bundle.test.db
cp template.db.in in-the-middle.test.db
# Create KSK for the various policies.
create_ksk() {
KSK=$($KEYGEN -l named.conf -fK -k $2 $1 2>keygen.out.$1)
num=0
for ksk in $KSK; do
num=$(($num + 1))
echo $ksk >"../${1}.ksk${num}.id"
cat "${ksk}.key" | grep -v ";.*" >"../$1.ksk$num"
mv "${ksk}.key" offline/
mv "${ksk}.private" offline/
mv "${ksk}.state" offline/
done
}
create_ksk common.test common
create_ksk past.test common
create_ksk future.test common
create_ksk last-bundle.test common
create_ksk in-the-middle.test common
create_ksk unlimited.test unlimited
create_ksk two-tone.test two-tone

View file

@ -0,0 +1,27 @@
; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
;
; SPDX-License-Identifier: MPL-2.0
;
; This Source Code Form is subject to the terms of the Mozilla Public
; License, v. 2.0. If a copy of the MPL was not distributed with this
; file, you can obtain one at https://mozilla.org/MPL/2.0/.
;
; See the COPYRIGHT file distributed with this work for additional
; information regarding copyright ownership.
$TTL 300
@ IN SOA mname1. . (
1 ; serial
20 ; refresh (20 seconds)
20 ; retry (20 seconds)
1814400 ; expire (3 weeks)
3600 ; minimum (1 hour)
)
NS ns1
ns1 A 10.53.0.1
a A 10.0.0.1
b A 10.0.0.2
c A 10.0.0.3

View file

@ -18,23 +18,9 @@ set -e
$SHELL clean.sh
mkdir keydir
mkdir offline
copy_setports ns1/named.conf.in ns1/named.conf
copy_setports named.conf.in named.conf
# Create KSK for the various policies.
create_ksk() {
KSK=$($KEYGEN -l named.conf -fK -k $2 $1 2>keygen.out.$1)
num=0
for ksk in $KSK; do
num=$(($num + 1))
echo $ksk >"${1}.ksk${num}.id"
cat "${ksk}.key" | grep -v ";.*" >"$1.ksk$num"
cp "${ksk}.key" offline/
cp "${ksk}.private" offline/
done
}
create_ksk common.test common
create_ksk unlimited.test unlimited
create_ksk two-tone.test two-tone
(
cd ns1
$SHELL setup.sh
)

View file

@ -18,6 +18,8 @@
set -e
RNDCCMD="$RNDC -c ../_common/rndc.conf -p ${CONTROLPORT} -s"
CDS_SHA1="no"
CDS_SHA256="yes"
CDS_SHA384="no"
@ -51,9 +53,11 @@ EOF
# output file, ksr.keygen.out.$n.
# $1: zone name
# $2: key directory
check_keys() (
# $3: offset
ksr_check_keys() (
zone=$1
dir=$2
offset=$3
lifetime=$LIFETIME
alg=$ALG
size=$SIZE
@ -64,7 +68,7 @@ check_keys() (
for key in $(grep "K${zone}.+$pad+" ksr.keygen.out.$n); do
grep "; Created:" "${dir}/${key}.key" >created.out || return 1
created=$(awk '{print $3}' <created.out)
test "$num" -eq 0 && retired=$created
test "$num" -eq 0 && retired=$(addtime $created $offset)
# active: retired previous key
active=$retired
# published: 2h5m (dnskey-ttl + publish-safety + propagation)
@ -74,7 +78,7 @@ check_keys() (
# removed: 10d1h5m (ttlsig + retire-safety + sign-delay + propagation)
removed=$(addtime $retired 867900)
echo_i "check metadata on $key"
echo_i "check metadata on $key: $alg $size $lifetime $published $active $retired $removed"
statefile="${dir}/${key}.state"
grep "Algorithm: $alg" $statefile >/dev/null || return 1
grep "Length: $size" $statefile >/dev/null || return 1
@ -116,7 +120,7 @@ print_dnskeys() {
# Call the dnssec-ksr command:
# ksr <policy> [options] <command> <zone>
ksr() {
$KSR -l named.conf -k "$@"
$KSR -l ns1/named.conf -k "$@"
}
# Unknown action.
@ -146,29 +150,29 @@ status=$((status + ret))
n=$((n + 1))
echo_i "check that 'dnssec-ksr keygen' pregenerates right amount of keys in the common case ($n)"
ret=0
ksr common -i now -e +1y keygen common.test >ksr.keygen.out.$n 2>&1 || ret=1
ksr common -K ns1 -i now -e +1y keygen common.test >ksr.keygen.out.$n 2>&1 || ret=1
num=$(cat ksr.keygen.out.$n | wc -l)
[ $num -eq 2 ] || ret=1
set_zsk $DEFAULT_ALGORITHM_NUMBER $DEFAULT_BITS 16070400
check_keys common.test "." || ret=1
ksr_check_keys common.test ns1 0 || ret=1
cp ksr.keygen.out.$n ksr.keygen.out.expect
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
# save now time
key=$(cat common.test.$DEFAULT_ALGORITHM_NUMBER.zsk1.id)
grep "; Created:" "${key}.key" >now.out || ret=1
grep "; Created:" "ns1/${key}.key" >now.out || ret=1
now=$(awk '{print $3}' <now.out)
n=$((n + 1))
echo_i "check that 'dnssec-ksr keygen' selects pregenerated keys for the same time bundle ($n)"
ret=0
ksr common -e +1y keygen common.test >ksr.keygen.out.$n 2>&1 || ret=1
ksr common -K ns1 -e +1y keygen common.test >ksr.keygen.out.$n 2>&1 || ret=1
diff -w ksr.keygen.out.expect ksr.keygen.out.$n >/dev/null || ret=1
for key in $(cat ksr.keygen.out.$n); do
# Ensure the files are not modified.
diff ${key}.key ${key}.key.expect >/dev/null || ret=1
diff ${key}.private ${key}.private.expect >/dev/null || ret=1
diff ${key}.state ${key}.state.expect >/dev/null || ret=1
diff ns1/${key}.key ${key}.key.expect >/dev/null || ret=1
diff ns1/${key}.private ${key}.private.expect >/dev/null || ret=1
diff ns1/${key}.state ${key}.state.expect >/dev/null || ret=1
done
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
@ -177,7 +181,7 @@ status=$((status + ret))
n=$((n + 1))
echo_i "check that 'dnssec-ksr request' errors on missing end date ($n)"
ret=0
ksr common request common.test >ksr.request.out.$n 2>&1 && ret=1
ksr common -K ns1 request common.test >ksr.request.out.$n 2>&1 && ret=1
grep "dnssec-ksr: fatal: request requires an end date" ksr.request.out.$n >/dev/null || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
@ -185,20 +189,20 @@ status=$((status + ret))
n=$((n + 1))
echo_i "check that 'dnssec-ksr request' creates correct KSR in the common case ($n)"
ret=0
ksr common -i $now -e +1y request common.test >ksr.request.out.$n 2>&1 || ret=1
ksr common -K ns1 -i $now -e +1y request common.test >ksr.request.out.$n 2>&1 || ret=1
# Bundle 1: KSK + ZSK1
key=$(cat common.test.$DEFAULT_ALGORITHM_NUMBER.zsk1.id)
inception=$(cat $key.state | grep "Generated" | cut -d' ' -f 2-)
inception=$(cat ns1/$key.state | grep "Generated" | cut -d' ' -f 2-)
echo ";; KeySigningRequest 1.0 $inception" >ksr.request.expect.$n
cat common.test.$DEFAULT_ALGORITHM_NUMBER.zsk1 >>ksr.request.expect.$n
# Bundle 2: KSK + ZSK1 + ZSK2
key=$(cat common.test.$DEFAULT_ALGORITHM_NUMBER.zsk2.id)
inception=$(cat $key.state | grep "Published" | cut -d' ' -f 2-)
inception=$(cat ns1/$key.state | grep "Published" | cut -d' ' -f 2-)
echo ";; KeySigningRequest 1.0 $inception" >>ksr.request.expect.$n
print_dnskeys common.test 1 2 $DEFAULT_ALGORITHM_NUMBER ksr.keygen.out.expect
# Bundle 3: KSK + ZSK2
key=$(cat common.test.$DEFAULT_ALGORITHM_NUMBER.zsk1.id)
inception=$(cat $key.state | grep "Removed" | cut -d' ' -f 2-)
inception=$(cat ns1/$key.state | grep "Removed" | cut -d' ' -f 2-)
echo ";; KeySigningRequest 1.0 $inception" >>ksr.request.expect.$n
cat common.test.$DEFAULT_ALGORITHM_NUMBER.zsk2 >>ksr.request.expect.$n
# Footer
@ -216,7 +220,7 @@ status=$((status + ret))
n=$((n + 1))
echo_i "check that 'dnssec-ksr sign' errors on missing KSR file ($n)"
ret=0
ksr common -i $now -e +1y sign common.test >ksr.sign.out.$n 2>&1 && ret=1
ksr common -K ns1 -i $now -e +1y sign common.test >ksr.sign.out.$n 2>&1 && ret=1
grep "dnssec-ksr: fatal: 'sign' requires a KSR file" ksr.sign.out.$n >/dev/null || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
@ -224,7 +228,7 @@ status=$((status + ret))
n=$((n + 1))
echo_i "check that 'dnssec-ksr sign' creates correct SKR in the common case ($n)"
ret=0
ksr common -i $now -e +1y -K offline -f ksr.request.expect sign common.test >ksr.sign.out.$n 2>&1 || ret=1
ksr common -K ns1 -i $now -e +1y -K ns1/offline -f ksr.request.expect sign common.test >ksr.sign.out.$n 2>&1 || ret=1
_update_expected_zsks() {
zsk=$((zsk + 1))
@ -235,8 +239,8 @@ _update_expected_zsks() {
key2="${zone}.${DEFAULT_ALGORITHM_NUMBER}.zsk${next}"
zsk1=$(cat $key1.id)
zsk2=$(cat $key2.id)
rollover_start=$(cat $zsk2.state | grep "Published" | awk '{print $2}')
rollover_done=$(cat $zsk1.state | grep "Removed" | awk '{print $2}')
rollover_start=$(cat ns1/$zsk2.state | grep "Published" | awk '{print $2}')
rollover_done=$(cat ns1/$zsk1.state | grep "Removed" | awk '{print $2}')
else
# No more expected rollovers.
key1="${zone}.${DEFAULT_ALGORITHM_NUMBER}.zsk${zsk}"
@ -249,13 +253,14 @@ _update_expected_zsks() {
check_skr() {
_ret=0
zone=$1
file=$2
start=$3
end=$4
numzsks=$5
cds1=$($DSFROMKEY -T 3600 -a SHA-1 -C -w $(cat "${zone}.ksk1.id"))
cds2=$($DSFROMKEY -T 3600 -a SHA-256 -C -w $(cat "${zone}.ksk1.id"))
cds4=$($DSFROMKEY -T 3600 -a SHA-384 -C -w $(cat "${zone}.ksk1.id"))
dir=$2
file=$3
start=$4
end=$5
numzsks=$6
cds1=$($DSFROMKEY -T 3600 -a SHA-1 -C -w $dir/$(cat "${zone}.ksk1.id"))
cds2=$($DSFROMKEY -T 3600 -a SHA-256 -C -w $dir/$(cat "${zone}.ksk1.id"))
cds4=$($DSFROMKEY -T 3600 -a SHA-384 -C -w $dir/$(cat "${zone}.ksk1.id"))
cdnskey=$(awk '{sub(/DNSKEY/,"CDNSKEY")}1' <${zone}.ksk1)
echo_i "check skr: zone $1 file $2 from $3 to $4 num-zsk $5"
@ -430,9 +435,9 @@ check_skr() {
}
zsk1=$(cat common.test.$DEFAULT_ALGORITHM_NUMBER.zsk1.id)
start=$(cat $zsk1.state | grep "Generated" | awk '{print $2}')
start=$(cat ns1/$zsk1.state | grep "Generated" | awk '{print $2}')
end=$(addtime $start 31536000) # one year
check_skr "common.test" "ksr.sign.out.$n" $start $end 2 || ret=1
check_skr "common.test" "ns1/offline" "ksr.sign.out.$n" $start $end 2 || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
@ -440,18 +445,18 @@ status=$((status + ret))
n=$((n + 1))
echo_i "check that 'dnssec-ksr keygen' pregenerates keys in the given key-directory ($n)"
ret=0
ksr common -e +1y -K keydir keygen common.test >ksr.keygen.out.$n 2>&1 || ret=1
ksr common -K ns1/keydir -e +1y keygen common.test >ksr.keygen.out.$n 2>&1 || ret=1
num=$(cat ksr.keygen.out.$n | wc -l)
[ $num -eq 2 ] || ret=1
set_zsk $DEFAULT_ALGORITHM_NUMBER $DEFAULT_BITS 16070400
check_keys common.test keydir || ret=1
ksr_check_keys common.test ns1/keydir 0 || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
n=$((n + 1))
echo_i "check that 'dnssec-ksr keygen' selects generates only necessary keys for overlapping time bundle ($n)"
ret=0
ksr common -e +2y -v 1 keygen common.test >ksr.keygen.out.$n 2>&1 || ret=1
ksr common -K ns1 -e +2y -v 1 keygen common.test >ksr.keygen.out.$n 2>&1 || ret=1
num=$(cat ksr.keygen.out.$n | wc -l)
[ $num -eq 4 ] || ret=1
# 2 selected, 2 generated
@ -466,11 +471,11 @@ status=$((status + ret))
n=$((n + 1))
echo_i "run 'dnssec-ksr keygen' again with verbosity 0 ($n)"
ret=0
ksr common -i $now -e +2y keygen common.test >ksr.keygen.out.$n 2>&1 || ret=1
ksr common -K ns1 -i $now -e +2y keygen common.test >ksr.keygen.out.$n 2>&1 || ret=1
num=$(cat ksr.keygen.out.$n | wc -l)
[ $num -eq 4 ] || ret=1
set_zsk $DEFAULT_ALGORITHM_NUMBER $DEFAULT_BITS 16070400
check_keys common.test "." || ret=1
ksr_check_keys common.test ns1 0 || ret=1
cp ksr.keygen.out.$n ksr.keygen.out.expect
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
@ -479,7 +484,7 @@ status=$((status + ret))
n=$((n + 1))
echo_i "check that 'dnssec-ksr request' creates correct KSR if the interval is shorter ($n)"
ret=0
ksr common -i $now -e +1y request common.test >ksr.request.out.$n 2>&1 || ret=1
ksr common -K ns1 -i $now -e +1y request common.test >ksr.request.out.$n 2>&1 || ret=1
# Same as earlier.
cp ksr.request.expect.base ksr.request.expect.$n
grep ";; KeySigningRequest 1.0 generated at" ksr.request.out.$n >footer.$n || ret=1
@ -491,26 +496,26 @@ status=$((status + ret))
n=$((n + 1))
echo_i "check that 'dnssec-ksr request' creates correct KSR with new interval ($n)"
ret=0
ksr common -i $now -e +2y request common.test >ksr.request.out.$n 2>&1 || ret=1
ksr common -K ns1 -i $now -e +2y request common.test >ksr.request.out.$n 2>&1 || ret=1
cp ksr.request.expect.base ksr.request.expect.$n
# Bundle 4: KSK + ZSK2 + ZSK3
key=$(cat common.test.$DEFAULT_ALGORITHM_NUMBER.zsk3.id)
inception=$(cat $key.state | grep "Published" | cut -d' ' -f 2-)
inception=$(cat ns1/$key.state | grep "Published" | cut -d' ' -f 2-)
echo ";; KeySigningRequest 1.0 $inception" >>ksr.request.expect.$n
print_dnskeys common.test 2 3 $DEFAULT_ALGORITHM_NUMBER ksr.keygen.out.expect
# Bundle 5: KSK + ZSK3
key=$(cat common.test.$DEFAULT_ALGORITHM_NUMBER.zsk2.id)
inception=$(cat $key.state | grep "Removed" | cut -d' ' -f 2-)
inception=$(cat ns1/$key.state | grep "Removed" | cut -d' ' -f 2-)
echo ";; KeySigningRequest 1.0 $inception" >>ksr.request.expect.$n
cat common.test.$DEFAULT_ALGORITHM_NUMBER.zsk3 >>ksr.request.expect.$n
# Bundle 6: KSK + ZSK3 + ZSK4
key=$(cat common.test.$DEFAULT_ALGORITHM_NUMBER.zsk4.id)
inception=$(cat $key.state | grep "Published" | cut -d' ' -f 2-)
inception=$(cat ns1/$key.state | grep "Published" | cut -d' ' -f 2-)
echo ";; KeySigningRequest 1.0 $inception" >>ksr.request.expect.$n
print_dnskeys common.test 3 4 $DEFAULT_ALGORITHM_NUMBER ksr.keygen.out.expect
# Bundle 7: KSK + ZSK4
key=$(cat common.test.$DEFAULT_ALGORITHM_NUMBER.zsk3.id)
inception=$(cat $key.state | grep "Removed" | cut -d' ' -f 2-)
inception=$(cat ns1/$key.state | grep "Removed" | cut -d' ' -f 2-)
echo ";; KeySigningRequest 1.0 $inception" >>ksr.request.expect.$n
cat common.test.$DEFAULT_ALGORITHM_NUMBER.zsk4 >>ksr.request.expect.$n
# Footer
@ -526,7 +531,7 @@ status=$((status + ret))
n=$((n + 1))
echo_i "check that 'dnssec-ksr request' errors if there are not enough keys ($n)"
ret=0
ksr common -i $now -e +3y request common.test >ksr.request.out.$n 2>ksr.request.err.$n && ret=1
ksr common -K ns1 -i $now -e +3y request common.test >ksr.request.out.$n 2>ksr.request.err.$n && ret=1
grep "dnssec-ksr: fatal: no common.test/ECDSAP256SHA256 zsk key pair found for bundle" ksr.request.err.$n >/dev/null || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
@ -535,10 +540,424 @@ status=$((status + ret))
n=$((n + 1))
echo_i "check that 'dnssec-ksr sign' creates correct SKR with the new interval ($n)"
ret=0
ksr common -i $now -e +2y -K offline -f ksr.request.expect sign common.test >ksr.sign.out.$n 2>&1 || ret=1
start=$(cat $zsk1.state | grep "Generated" | awk '{print $2}')
ksr common -K ns1 -i $now -e +2y -K ns1/offline -f ksr.request.expect sign common.test >ksr.sign.out.$n 2>&1 || ret=1
start=$(cat ns1/$zsk1.state | grep "Generated" | awk '{print $2}')
end=$(addtime $start 63072000) # two years
check_skr "common.test" "ksr.sign.out.$n" $start $end 4 || ret=1
check_skr "common.test" "ns1/offline" "ksr.sign.out.$n" $start $end 4 || ret=1
# Save response for skr import operation.
cp ksr.sign.out.$n ns1/common.test.skr
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
# Add zone: common
n=$((n + 1))
echo_i "add zone 'common.test' ($n)"
ret=0
$RNDCCMD 10.53.0.1 addzone 'common.test { type primary; file "common.test.db"; dnssec-policy common; };' 2>&1 | sed 's/^/I:ns1 /' || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
# Import skr: common
n=$((n + 1))
echo_i "import ksr to zone 'common.test' ($n)"
ret=0
sleep 2
$RNDCCMD 10.53.0.1 skr -import common.test.skr common.test 2>&1 | sed 's/^/I:ns1 /' || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
# Test that common.test is signed and uses the right DNSKEY and RRSIG records.
n=$((n + 1))
echo_i "test zone 'common.test' is correctly signed ($n)"
ret=0
set_zone "common.test"
set_policy "common" "4" "3600"
set_server "ns1" "10.53.0.1"
# Only ZSKs
set_keyrole "KEY1" "zsk"
set_keylifetime "KEY1" "16070400"
set_keyalgorithm "KEY1" "13" "ECDSAP256SHA256" "256"
set_keysigning "KEY1" "no"
set_zonesigning "KEY1" "yes"
set_keystate "KEY1" "GOAL" "omnipresent"
set_keystate "KEY1" "STATE_DNSKEY" "omnipresent"
set_keystate "KEY1" "STATE_ZRRSIG" "rumoured"
set_keyrole "KEY2" "zsk"
set_keylifetime "KEY2" "16070400"
set_keyalgorithm "KEY2" "13" "ECDSAP256SHA256" "256"
set_keysigning "KEY2" "no"
set_zonesigning "KEY2" "no"
set_keystate "KEY2" "GOAL" "hidden"
set_keystate "KEY2" "STATE_DNSKEY" "hidden"
set_keystate "KEY2" "STATE_ZRRSIG" "hidden"
set_keyrole "KEY3" "zsk"
set_keylifetime "KEY3" "16070400"
set_keyalgorithm "KEY3" "13" "ECDSAP256SHA256" "256"
set_keysigning "KEY3" "no"
set_zonesigning "KEY3" "no"
set_keystate "KEY3" "GOAL" "hidden"
set_keystate "KEY3" "STATE_DNSKEY" "hidden"
set_keystate "KEY3" "STATE_ZRRSIG" "hidden"
set_keyrole "KEY4" "zsk"
set_keylifetime "KEY4" "16070400"
set_keyalgorithm "KEY4" "13" "ECDSAP256SHA256" "256"
set_keysigning "KEY4" "no"
set_zonesigning "KEY4" "no"
set_keystate "KEY4" "GOAL" "hidden"
set_keystate "KEY4" "STATE_DNSKEY" "hidden"
set_keystate "KEY4" "STATE_ZRRSIG" "hidden"
MAXDEPTH=1
check_keys
check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
check_subdomain
dnssec_verify
# For checking the apex, we need to store the expected KSK metadata.
key_clear "KEY2"
key_clear "KEY3"
key_clear "KEY4"
set_policy "common" "1" "3600"
set_server "ns1/offline" "10.53.0.1"
set_keyrole "KEY2" "ksk"
set_keylifetime "KEY2" "0"
set_keyalgorithm "KEY2" "13" "ECDSAP256SHA256" "256"
set_keysigning "KEY2" "yes"
set_zonesigning "KEY2" "no"
check_keys "keep"
DIR="ns1"
set_keystate "KEY2" "STATE_DNSKEY" "omnipresent"
set_keystate "KEY2" "STATE_KRRSIG" "omnipresent"
set_keystate "KEY2" "STATE_DS" "omnipresent"
check_apex
# Check that key id's match expected keys
n=$((n + 1))
zsk1=$(cat common.test.$DEFAULT_ALGORITHM_NUMBER.zsk1.id)
key1=$(key_get "KEY1" BASEFILE)
echo_i "check that published zsk $zsk1 matches first key $key1 in bundle ($n)"
ret=0
[ "ns1/$zsk1" = "$key1" ] || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
n=$((n + 1))
ksk=$(cat common.test.ksk1.id)
key2=$(key_get "KEY2" BASEFILE)
echo_i "check that published ksk $ksk matches ksk $key2 ($n)"
ret=0
[ "ns1/offline/$ksk" = "$key2" ] || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
# Key generation: last-bundle
n=$((n + 1))
echo_i "generate keys for testing an SKR that is in the last bundle ($n)"
ret=0
ksr common -K ns1 -i -1y -e +1d keygen last-bundle.test >ksr.keygen.out.$n 2>&1 || ret=1
num=$(cat ksr.keygen.out.$n | wc -l)
[ $num -eq 2 ] || ret=1
set_zsk $DEFAULT_ALGORITHM_NUMBER $DEFAULT_BITS 16070400
ksr_check_keys last-bundle.test ns1 -31536000 || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
# Create request: last-bundle
n=$((n + 1))
echo_i "create ksr for last bundle test ($n)"
ret=0
ksr common -K ns1 -i -1y -e +1d request last-bundle.test >ksr.request.out.$n 2>&1 || ret=1
cp ksr.request.out.$n last-bundle.test.ksr
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
# Sign request: last-bundle
n=$((n + 1))
echo_i "create skr for last bundle test ($n)"
ret=0
ksr common -i -1y -e +1d -K ns1/offline -f last-bundle.test.ksr sign last-bundle.test >ksr.sign.out.$n 2>&1 || ret=1
cp ksr.sign.out.$n ns1/last-bundle.test.skr
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
# Add zone: last-bundle
n=$((n + 1))
echo_i "add zone 'last-bundle.test' ($n)"
ret=0
$RNDCCMD 10.53.0.1 addzone 'last-bundle.test { type primary; file "last-bundle.test.db"; dnssec-policy common; };' 2>&1 | sed 's/^/I:ns1 /' || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
# Import skr: last-bundle
n=$((n + 1))
echo_i "import ksr to zone 'last-bundle.test' ($n)"
ret=0
sleep 2
$RNDCCMD 10.53.0.1 skr -import last-bundle.test.skr last-bundle.test 2>&1 | sed 's/^/I:ns1 /' || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
# Test that last-bundle.test is signed and uses the right DNSKEY and RRSIG records.
n=$((n + 1))
echo_i "test zone 'last-bundle.test' is correctly signed ($n)"
ret=0
set_zone "last-bundle.test"
set_policy "common" "2" "3600"
set_server "ns1" "10.53.0.1"
# Only ZSKs
key_clear "KEY1"
set_keyrole "KEY1" "zsk"
set_keylifetime "KEY1" "16070400"
set_keyalgorithm "KEY1" "13" "ECDSAP256SHA256" "256"
set_keysigning "KEY1" "no"
set_zonesigning "KEY1" "yes"
set_keystate "KEY1" "GOAL" "omnipresent"
set_keystate "KEY1" "STATE_DNSKEY" "omnipresent"
set_keystate "KEY1" "STATE_ZRRSIG" "omnipresent"
key_clear "KEY2"
set_keyrole "KEY2" "zsk"
set_keylifetime "KEY2" "16070400"
set_keyalgorithm "KEY2" "13" "ECDSAP256SHA256" "256"
set_keysigning "KEY2" "no"
set_zonesigning "KEY2" "no"
set_keystate "KEY2" "GOAL" "hidden"
set_keystate "KEY2" "STATE_DNSKEY" "hidden"
set_keystate "KEY2" "STATE_ZRRSIG" "hidden"
MAXDEPTH=1
check_keys
check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
check_subdomain
dnssec_verify
# For checking the apex, we need to store the expected KSK metadata.
key_clear "KEY2"
key_clear "KEY3"
key_clear "KEY4"
set_policy "common" "1" "3600"
set_server "ns1/offline" "10.53.0.1"
set_keyrole "KEY2" "ksk"
set_keylifetime "KEY2" "0"
set_keyalgorithm "KEY2" "13" "ECDSAP256SHA256" "256"
set_keysigning "KEY2" "yes"
set_zonesigning "KEY2" "no"
check_keys "keep"
DIR="ns1"
set_keystate "KEY2" "STATE_DNSKEY" "omnipresent"
set_keystate "KEY2" "STATE_KRRSIG" "omnipresent"
set_keystate "KEY2" "STATE_DS" "omnipresent"
check_apex
# Check that key id's match expected keys
n=$((n + 1))
zsk2=$(cat last-bundle.test.$DEFAULT_ALGORITHM_NUMBER.zsk2.id)
key1=$(key_get "KEY1" BASEFILE)
echo_i "check that published zsk $zsk2 matches first key $key1 in bundle ($n)"
ret=0
[ "ns1/$zsk2" = "$key1" ] || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
n=$((n + 1))
ksk=$(cat last-bundle.test.ksk1.id)
key2=$(key_get "KEY2" BASEFILE)
echo_i "check that published ksk $ksk matches ksk $key2 ($n)"
ret=0
[ "ns1/offline/$ksk" = "$key2" ] || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
n=$((n + 1))
echo_i "check that last bundle warning is logged ($n)"
wait_for_log 3 "zone last-bundle.test/IN (signed): zone_rekey: last bundle in skr, please import new skr file" ns1/named.run || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
# Key generation: in-the-middle
n=$((n + 1))
echo_i "generate keys for testing an SKR that is in the middle ($n)"
ret=0
ksr common -K ns1 -i -1y -e +1y keygen in-the-middle.test >ksr.keygen.out.$n 2>&1 || ret=1
num=$(cat ksr.keygen.out.$n | wc -l)
[ $num -eq 4 ] || ret=1
set_zsk $DEFAULT_ALGORITHM_NUMBER $DEFAULT_BITS 16070400
ksr_check_keys in-the-middle.test ns1 -31536000 || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
# Create request: in-the-middle
n=$((n + 1))
echo_i "create ksr for in the middle test ($n)"
ret=0
ksr common -K ns1 -i -1y -e +1y request in-the-middle.test >ksr.request.out.$n 2>&1 || ret=1
cp ksr.request.out.$n in-the-middle.test.ksr
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
# Sign request: in-the-middle
n=$((n + 1))
echo_i "create skr for in the middle test ($n)"
ret=0
ksr common -i -1y -e +1y -K ns1/offline -f in-the-middle.test.ksr sign in-the-middle.test >ksr.sign.out.$n 2>&1 || ret=1
cp ksr.sign.out.$n ns1/in-the-middle.test.skr
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
# Add zone: in-the-middle
n=$((n + 1))
echo_i "add zone 'in-the-middle.test' ($n)"
ret=0
$RNDCCMD 10.53.0.1 addzone 'in-the-middle.test { type primary; file "in-the-middle.test.db"; dnssec-policy common; };' 2>&1 | sed 's/^/I:ns1 /' || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
# Import skr: in-the-middle
n=$((n + 1))
echo_i "import ksr to zone 'in-the-middle.test' ($n)"
ret=0
sleep 2
$RNDCCMD 10.53.0.1 skr -import in-the-middle.test.skr in-the-middle.test 2>&1 | sed 's/^/I:ns1 /' || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
# Test that in-the-middle.test is signed and uses the right DNSKEY and RRSIG records.
n=$((n + 1))
echo_i "test zone 'in-the-middle.test' is correctly signed ($n)"
ret=0
set_zone "in-the-middle.test"
set_policy "common" "4" "3600"
set_server "ns1" "10.53.0.1"
# Only ZSKs
key_clear "KEY1"
set_keyrole "KEY1" "zsk"
set_keylifetime "KEY1" "16070400"
set_keyalgorithm "KEY1" "13" "ECDSAP256SHA256" "256"
set_keysigning "KEY1" "no"
set_zonesigning "KEY1" "yes"
set_keystate "KEY1" "GOAL" "omnipresent"
set_keystate "KEY1" "STATE_DNSKEY" "omnipresent"
set_keystate "KEY1" "STATE_ZRRSIG" "omnipresent"
key_clear "KEY2"
set_keyrole "KEY2" "zsk"
set_keylifetime "KEY2" "16070400"
set_keyalgorithm "KEY2" "13" "ECDSAP256SHA256" "256"
set_keysigning "KEY2" "no"
set_zonesigning "KEY2" "no"
set_keystate "KEY2" "GOAL" "hidden"
set_keystate "KEY2" "STATE_DNSKEY" "hidden"
set_keystate "KEY2" "STATE_ZRRSIG" "hidden"
key_clear "KEY3"
set_keyrole "KEY3" "zsk"
set_keylifetime "KEY3" "16070400"
set_keyalgorithm "KEY3" "13" "ECDSAP256SHA256" "256"
set_keysigning "KEY3" "no"
set_zonesigning "KEY3" "no"
set_keystate "KEY3" "GOAL" "hidden"
set_keystate "KEY3" "STATE_DNSKEY" "hidden"
set_keystate "KEY3" "STATE_ZRRSIG" "hidden"
key_clear "KEY4"
set_keyrole "KEY4" "zsk"
set_keylifetime "KEY4" "16070400"
set_keyalgorithm "KEY4" "13" "ECDSAP256SHA256" "256"
set_keysigning "KEY4" "no"
set_zonesigning "KEY4" "no"
set_keystate "KEY4" "GOAL" "hidden"
set_keystate "KEY4" "STATE_DNSKEY" "hidden"
set_keystate "KEY4" "STATE_ZRRSIG" "hidden"
MAXDEPTH=1
check_keys
check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
check_subdomain
dnssec_verify
# For checking the apex, we need to store the expected KSK metadata.
key_clear "KEY2"
key_clear "KEY3"
key_clear "KEY4"
set_policy "common" "1" "3600"
set_server "ns1/offline" "10.53.0.1"
set_keyrole "KEY2" "ksk"
set_keylifetime "KEY2" "0"
set_keyalgorithm "KEY2" "13" "ECDSAP256SHA256" "256"
set_keysigning "KEY2" "yes"
set_zonesigning "KEY2" "no"
check_keys "keep"
DIR="ns1"
set_keystate "KEY2" "STATE_DNSKEY" "omnipresent"
set_keystate "KEY2" "STATE_KRRSIG" "omnipresent"
set_keystate "KEY2" "STATE_DS" "omnipresent"
check_apex
# Check that key id's match expected keys
n=$((n + 1))
zsk2=$(cat in-the-middle.test.$DEFAULT_ALGORITHM_NUMBER.zsk2.id)
key1=$(key_get "KEY1" BASEFILE)
echo_i "check that published zsk $zsk2 matches first key $key1 in bundle ($n)"
ret=0
[ "ns1/$zsk2" = "$key1" ] || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
n=$((n + 1))
ksk=$(cat in-the-middle.test.ksk1.id)
key2=$(key_get "KEY2" BASEFILE)
echo_i "check that published ksk $ksk matches ksk $key2 ($n)"
ret=0
[ "ns1/offline/$ksk" = "$key2" ] || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
n=$((n + 1))
echo_i "check that no last bundle warning is logged ($n)"
grep "zone $zone/IN (signed): zone_rekey failure: no available SKR bundle" ns1/named.run && ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
# Test error conditions
check_rekey_logs_error() {
zone=$1
inc=$2
exp=$3
offset=$4
# Key generation
ksr common -K ns1 -i $inc -e $exp keygen $zone >ksr.keygen.out.$n 2>&1 || return 1
num=$(cat ksr.keygen.out.$n | wc -l)
[ $num -eq 2 ] || return 1
set_zsk $DEFAULT_ALGORITHM_NUMBER $DEFAULT_BITS 16070400
ksr_check_keys $zone ns1 $offset || return 1
# Create request
ksr common -K ns1 -i $inc -e $exp request $zone >ksr.request.out.$n 2>&1 || return 1
cp ksr.request.out.$n $zone.ksr
# Sign request
ksr common -K ns1/offline -i $inc -e $exp -f $zone.ksr sign $zone >ksr.sign.out.$n 2>&1 || return 1
cp ksr.sign.out.$n ns1/$zone.skr
# Import skr
$RNDCCMD 10.53.0.1 skr -import $zone.skr $zone 2>&1 | sed 's/^/I:ns1 /' || return 1
# Test that rekey logs error
wait_for_log 3 "zone $zone/IN (signed): zone_rekey failure: no available SKR bundle" ns1/named.run || return 1
}
n=$((n + 1))
echo_i "check that an SKR that is too old logs error ($n)"
$RNDCCMD 10.53.0.1 addzone 'past.test { type primary; file "past.test.db"; dnssec-policy common; };' 2>&1 | sed 's/^/I:ns1 /' || ret=1
check_rekey_logs_error "past.test" -2y -1y -63072000 || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
n=$((n + 1))
echo_i "check that an SKR that is too new logs error ($n)"
$RNDCCMD 10.53.0.1 addzone 'future.test { type primary; file "future.test.db"; dnssec-policy common; };' 2>&1 | sed 's/^/I:ns1 /' || ret=1
check_rekey_logs_error "future.test" +1mo +1y 2592000 || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
@ -555,25 +974,25 @@ status=$((status + ret))
n=$((n + 1))
echo_i "check that 'dnssec-ksr keygen' creates only one key for zsk with unlimited lifetime ($n)"
ret=0
ksr unlimited -e +2y keygen unlimited.test >ksr.keygen.out.$n 2>&1 || ret=1
ksr unlimited -K ns1 -e +2y keygen unlimited.test >ksr.keygen.out.$n 2>&1 || ret=1
num=$(cat ksr.keygen.out.$n | wc -l)
[ $num -eq 1 ] || ret=1
key=$(cat ksr.keygen.out.$n)
grep "; Created:" "${key}.key" >created.out || ret=1
grep "; Created:" "ns1/${key}.key" >created.out || ret=1
created=$(awk '{print $3}' <created.out)
active=$created
published=$(addtime $active -7500)
echo_i "check metadata on $key"
grep "Algorithm: $DEFAULT_ALGORITHM_NUMBER" ${key}.state >/dev/null || ret=1
grep "Length: $DEFAULT_BITS" ${key}.state >/dev/null || ret=1
grep "Lifetime: 0" ${key}.state >/dev/null || ret=1
grep "KSK: no" ${key}.state >/dev/null || ret=1
grep "ZSK: yes" ${key}.state >/dev/null || ret=1
grep "Published: $published" ${key}.state >/dev/null || ret=1
grep "Active: $active" ${key}.state >/dev/null || ret=1
grep "Retired:" ${key}.state >/dev/null && ret=1
grep "Removed:" ${key}.state >/dev/null && ret=1
cat ${key}.key | grep -v ";.*" >unlimited.test.$DEFAULT_ALGORITHM_NUMBER.zsk1
grep "Algorithm: $DEFAULT_ALGORITHM_NUMBER" ns1/${key}.state >/dev/null || ret=1
grep "Length: $DEFAULT_BITS" ns1/${key}.state >/dev/null || ret=1
grep "Lifetime: 0" ns1/${key}.state >/dev/null || ret=1
grep "KSK: no" ns1/${key}.state >/dev/null || ret=1
grep "ZSK: yes" ns1/${key}.state >/dev/null || ret=1
grep "Published: $published" ns1/${key}.state >/dev/null || ret=1
grep "Active: $active" ns1/${key}.state >/dev/null || ret=1
grep "Retired:" ns1/${key}.state >/dev/null && ret=1
grep "Removed:" ns1/${key}.state >/dev/null && ret=1
cat ns1/${key}.key | grep -v ";.*" >unlimited.test.$DEFAULT_ALGORITHM_NUMBER.zsk1
echo $key >"unlimited.test.${DEFAULT_ALGORITHM_NUMBER}.zsk1.id"
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
@ -582,9 +1001,9 @@ status=$((status + ret))
n=$((n + 1))
echo_i "check that 'dnssec-ksr request' creates correct KSR with unlimited zsk ($n)"
ret=0
ksr unlimited -i $created -e +4y request unlimited.test >ksr.request.out.$n 2>&1 || ret=1
ksr unlimited -K ns1 -i $created -e +4y request unlimited.test >ksr.request.out.$n 2>&1 || ret=1
# Only one bundle: KSK + ZSK
inception=$(cat $key.state | grep "Generated" | cut -d' ' -f 2-)
inception=$(cat ns1/$key.state | grep "Generated" | cut -d' ' -f 2-)
echo ";; KeySigningRequest 1.0 $inception" >ksr.request.expect.$n
cat unlimited.test.$DEFAULT_ALGORITHM_NUMBER.zsk1 >>ksr.request.expect.$n
# Footer
@ -600,10 +1019,10 @@ status=$((status + ret))
n=$((n + 1))
echo_i "check that 'dnssec-ksr sign' creates correct SKR with unlimited zsk ($n)"
ret=0
ksr unlimited -i $created -e +4y -K offline -f ksr.request.expect sign unlimited.test >ksr.sign.out.$n 2>&1 || ret=1
start=$(cat $key.state | grep "Generated" | awk '{print $2}')
ksr unlimited -K ns1 -i $created -e +4y -K ns1/offline -f ksr.request.expect sign unlimited.test >ksr.sign.out.$n 2>&1 || ret=1
start=$(cat ns1/$key.state | grep "Generated" | awk '{print $2}')
end=$(addtime $start 126144000) # four years
check_skr "unlimited.test" "ksr.sign.out.$n" $start $end 1 || ret=1
check_skr "unlimited.test" "ns1/offline" "ksr.sign.out.$n" $start $end 1 || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
@ -611,14 +1030,14 @@ status=$((status + ret))
n=$((n + 1))
echo_i "check that 'dnssec-ksr sign' creates correct SKR with unlimited zsk, no cdnskey ($n)"
ret=0
ksr no-cdnskey -i $created -e +4y -K offline -f ksr.request.expect sign unlimited.test >ksr.sign.out.$n 2>&1 || ret=1
start=$(cat $key.state | grep "Generated" | awk '{print $2}')
ksr no-cdnskey -K ns1 -i $created -e +4y -K ns1/offline -f ksr.request.expect sign unlimited.test >ksr.sign.out.$n 2>&1 || ret=1
start=$(cat ns1/$key.state | grep "Generated" | awk '{print $2}')
end=$(addtime $start 126144000) # four years
CDNSKEY="no"
CDS_SHA1="yes"
CDS_SHA256="yes"
CDS_SHA384="yes"
check_skr "unlimited.test" "ksr.sign.out.$n" $start $end 1 || ret=1
check_skr "unlimited.test" "ns1/offline" "ksr.sign.out.$n" $start $end 1 || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
@ -626,14 +1045,14 @@ status=$((status + ret))
n=$((n + 1))
echo_i "check that 'dnssec-ksr sign' creates correct SKR with unlimited zsk, no cds ($n)"
ret=0
ksr no-cds -i $created -e +4y -K offline -f ksr.request.expect sign unlimited.test >ksr.sign.out.$n 2>&1 || ret=1
start=$(cat $key.state | grep "Generated" | awk '{print $2}')
ksr no-cds -K ns1 -i $created -e +4y -K ns1/offline -f ksr.request.expect sign unlimited.test >ksr.sign.out.$n 2>&1 || ret=1
start=$(cat ns1/$key.state | grep "Generated" | awk '{print $2}')
end=$(addtime $start 126144000) # four years
CDNSKEY="yes"
CDS_SHA1="no"
CDS_SHA256="no"
CDS_SHA384="no"
check_skr "unlimited.test" "ksr.sign.out.$n" $start $end 1 || ret=1
check_skr "unlimited.test" "ns1/offline" "ksr.sign.out.$n" $start $end 1 || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
@ -647,13 +1066,13 @@ CDS_SHA384="no"
n=$((n + 1))
echo_i "check that 'dnssec-ksr keygen' creates keys for different algorithms ($n)"
ret=0
ksr two-tone -e +1y keygen two-tone.test >ksr.keygen.out.$n 2>&1 || ret=1
ksr two-tone -K ns1 -e +1y keygen two-tone.test >ksr.keygen.out.$n 2>&1 || ret=1
# First algorithm keys have a lifetime of 3 months, so there should be 4 created keys.
alg=$(printf "%03d" "$DEFAULT_ALGORITHM_NUMBER")
num=$(grep "Ktwo-tone.test.+$alg+" ksr.keygen.out.$n | wc -l)
[ $num -eq 4 ] || ret=1
set_zsk $DEFAULT_ALGORITHM_NUMBER $DEFAULT_BITS 8035200
check_keys two-tone.test "." || ret=1
ksr_check_keys two-tone.test ns1 0 || ret=1
cp ksr.keygen.out.$n ksr.keygen.out.expect.$DEFAULT_ALGORITHM_NUMBER
# Second algorithm keys have a lifetime of 5 months, so there should be 3 created keys.
# While only two time bundles of 5 months fit into one year, we need to create an
@ -662,7 +1081,7 @@ alg=$(printf "%03d" "$ALTERNATIVE_ALGORITHM_NUMBER")
num=$(grep "Ktwo-tone.test.+$alg+" ksr.keygen.out.$n | wc -l)
[ $num -eq 3 ] || ret=1
set_zsk $ALTERNATIVE_ALGORITHM_NUMBER $ALTERNATIVE_BITS 13392000
check_keys two-tone.test "." $ALTERNATIVE_ALGORITHM_NUMBER 13392000 || ret=1
ksr_check_keys two-tone.test ns1 0 || ret=1
cp ksr.keygen.out.$n ksr.keygen.out.expect.$ALTERNATIVE_ALGORITHM_NUMBER
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
@ -672,9 +1091,9 @@ n=$((n + 1))
echo_i "check that 'dnssec-ksr request' creates correct KSR with multiple algorithms ($n)"
ret=0
key=$(cat two-tone.test.$DEFAULT_ALGORITHM_NUMBER.zsk1.id)
grep "; Created:" "${key}.key" >created.out || ret=1
grep "; Created:" "ns1/${key}.key" >created.out || ret=1
created=$(awk '{print $3}' <created.out)
ksr two-tone -i $created -e +6mo request two-tone.test >ksr.request.out.$n 2>&1 || ret=1
ksr two-tone -K ns1 -i $created -e +6mo request two-tone.test >ksr.request.out.$n 2>&1 || ret=1
# The two-tone policy uses two sets of KSK/ZSK with different algorithms. One
# set uses the default algorithm (denoted as A below), the other is using the
# alternative algorithm (denoted as B). The A-ZSKs roll every three months,
@ -685,31 +1104,31 @@ ksr two-tone -i $created -e +6mo request two-tone.test >ksr.request.out.$n 2>&1
#
# Bundle 1: KSK-A1, KSK-B1, ZSK-A1, ZSK-B1
key=$(cat two-tone.test.$DEFAULT_ALGORITHM_NUMBER.zsk1.id)
inception=$(cat $key.state | grep "Generated" | cut -d' ' -f 2-)
inception=$(cat ns1/$key.state | grep "Generated" | cut -d' ' -f 2-)
echo ";; KeySigningRequest 1.0 $inception" >ksr.request.expect.$n
cat two-tone.test.$DEFAULT_ALGORITHM_NUMBER.zsk1 >>ksr.request.expect.$n
cat two-tone.test.$ALTERNATIVE_ALGORITHM_NUMBER.zsk1 >>ksr.request.expect.$n
# Bundle 2: KSK-A1, KSK-B1, ZSK-A1 + ZSK-A2, ZSK-B1
key=$(cat two-tone.test.$DEFAULT_ALGORITHM_NUMBER.zsk2.id)
inception=$(cat $key.state | grep "Published" | cut -d' ' -f 2-)
inception=$(cat ns1/$key.state | grep "Published" | cut -d' ' -f 2-)
echo ";; KeySigningRequest 1.0 $inception" >>ksr.request.expect.$n
print_dnskeys two-tone.test 1 2 $DEFAULT_ALGORITHM_NUMBER ksr.keygen.out.expect.$DEFAULT_ALGORITHM_NUMBER >>ksr.request.expect.$n
cat two-tone.test.$ALTERNATIVE_ALGORITHM_NUMBER.zsk1 >>ksr.request.expect.$n
# Bundle 3: KSK-A1, KSK-B1, ZSK-A2, ZSK-B1
key=$(cat two-tone.test.$DEFAULT_ALGORITHM_NUMBER.zsk1.id)
inception=$(cat $key.state | grep "Removed" | cut -d' ' -f 2-)
inception=$(cat ns1/$key.state | grep "Removed" | cut -d' ' -f 2-)
echo ";; KeySigningRequest 1.0 $inception" >>ksr.request.expect.$n
cat two-tone.test.$DEFAULT_ALGORITHM_NUMBER.zsk2 >>ksr.request.expect.$n
cat two-tone.test.$ALTERNATIVE_ALGORITHM_NUMBER.zsk1 >>ksr.request.expect.$n
# Bundle 4: KSK-A1, KSK-B1, ZSK-A2, ZSK-B1 + ZSK-B2
key=$(cat two-tone.test.$ALTERNATIVE_ALGORITHM_NUMBER.zsk2.id)
inception=$(cat $key.state | grep "Published" | cut -d' ' -f 2-)
inception=$(cat ns1/$key.state | grep "Published" | cut -d' ' -f 2-)
echo ";; KeySigningRequest 1.0 $inception" >>ksr.request.expect.$n
cat two-tone.test.$DEFAULT_ALGORITHM_NUMBER.zsk2 >>ksr.request.expect.$n
print_dnskeys two-tone.test 1 2 $ALTERNATIVE_ALGORITHM_NUMBER ksr.keygen.out.expect.$ALTERNATIVE_ALGORITHM_NUMBER >>ksr.request.expect.$n
# Bundle 5: KSK-A1, KSK-B1, ZSK-A2, ZSK-B2
key=$(cat two-tone.test.$ALTERNATIVE_ALGORITHM_NUMBER.zsk1.id)
inception=$(cat $key.state | grep "Removed" | cut -d' ' -f 2-)
inception=$(cat ns1/$key.state | grep "Removed" | cut -d' ' -f 2-)
echo ";; KeySigningRequest 1.0 $inception" >>ksr.request.expect.$n
cat two-tone.test.$DEFAULT_ALGORITHM_NUMBER.zsk2 >>ksr.request.expect.$n
cat two-tone.test.$ALTERNATIVE_ALGORITHM_NUMBER.zsk2 >>ksr.request.expect.$n
@ -744,7 +1163,7 @@ num_occurrences() {
n=$((n + 1))
echo_i "check that 'dnssec-ksr sign' creates correct SKR with multiple algorithms ($n)"
ret=0
ksr two-tone -i $created -e +6mo -K offline -f ksr.request.expect sign two-tone.test >ksr.sign.out.$n 2>&1 || ret=1
ksr two-tone -i $created -e +6mo -K ns1/offline -f ksr.request.expect sign two-tone.test >ksr.sign.out.$n 2>&1 || ret=1
test "$ret" -eq 0 || echo_i "failed"
# Weak testing:
zone="two-tone.test"

View file

@ -6536,6 +6536,20 @@ The following options can be specified in a :any:`dnssec-policy` statement:
``insecure``. In this specific case you should move the existing key files
to the zone's ``key-directory`` from the new configuration.
.. namedconf:statement:: offline-ksk
:tags: dnssec
:short: Specifies whether the DNSKEY, CDS, and CDNSKEY RRsets are being signed offline.
If enabled, BIND 9 does not generate signatures for the DNSKEY, CDS, and
CDNSKEY RRsets. Instead, the signed DNSKEY, CDS and CDNSKEY RRsets are
looked up from Signed Key Response (SKR) files.
Any existing DNSKEY, CDS, and CDNSKEY RRsets in the unsigned version of the
zone are filtered and replaced with RRsets from the SKR file.
This feature is off by default. Configuring ``offline-ksk`` in conjunction
with a CSK is a configuration error.
.. namedconf:statement:: purge-keys
:tags: dnssec
:short: Specifies the amount of time after which DNSSEC keys that have been deleted from the zone can be removed from disk.

View file

@ -1319,3 +1319,139 @@ for the next fifty years all at once and set the key times appropriately.
Whether the increased risk in having the private key files for future keys
available on disk offsets the overhead of having to remember to create a new
key before a rollover depends on your organization's security policy.
.. _advanced_discussions_offline_ksk:
Offline KSK
~~~~~~~~~~~
For operational reasons, it is possible to keep the KSK offline. Doing so
minimizes the risk of the key being compromised through theft or loss.
This effectively means that the private keys of the KSKs and the ZSKs are
located in two physically separate places. The KSK is kept completely offline,
and the ZSK is used in the primary DNS server to sign the zone data. The
DNSKEY, CDS, and CDNSKEY RRsets are signed separately by the KSK.
Because of this, CSKs are incompatible with Offline KSK.
To enable Offline KSK in BIND 9, add the following to the :any:`dnssec-policy`
configuration:
::
dnssec-policy "offline-ksk" {
...
offline-ksk yes;
};
With this configuration, BIND 9 will no longer generate signatures for the
DNSKEY, CDS, and CDNSKEY RRsets, nor will it generate keys for rollovers.
Before enabling Offline KSK, the keys and signed RRsets must be pregenerated.
This can be done with the :iscman:`dnssec-ksr` program, which is used to
create Signed Key Response (SKR) files that can be imported into BIND 9.
Creating SKR files is a four-step process. First, the ZSKs must be
pregenerated; then, a Key Signing Request (KSR) is created. This file is
presented to the KSK operators to be signed. The result is a SKR file that
is returned to the ZSK operators, to be imported into the DNS server.
Pregenerating ZSKs
^^^^^^^^^^^^^^^^^^
First we need to pregenerate ZSKs for the future. Let's say we want to
generate enough keys for the next two years; this will create several key
files, depending on the :any:`dnssec-policy` used. If the ZSK lifetime
is six months, this will create about four keys (other timing metadata may
cause an extra key to be generated).
This can be done with the :iscman:`dnssec-ksr` program:
.. code-block:: none
# dnssec-ksr -i now -e +2y -k offline-ksk -l named.conf keygen example.net
Kexample.net.+013+63278
Kexample.net.+013+13211
Kexample.net.+013+50958
Kexample.net.+013+12403
The timing metadata is set accordingly in the key files. Keys that already
exist in the :any:`key-directory` are taken into consideration when
pregenerating keys; if the above command is run multiple times quickly in
succession, no additional keys are generated.
Key Signing Request
^^^^^^^^^^^^^^^^^^^
Now that we have keys that can be published in the zone, we need to get
signatures for the DNSKEY RRset to be used in the future. For that,
we generate a Key Signing Request (KSR). In this example, we are using the
same DNSSEC policy and interval.
.. code-block:: none
# dnssec-ksr -i now -e +2y -k offline-ksk -l named.conf keygen example.net
;; KeySigningRequest 1.0 20240813133035 (Tue Aug 13 15:30:35 2024)
example.net. 3600 IN DNSKEY 256 3 13 Z8WRuXJr9v7cSUZpJuQKN/1pZuLPEgoWx4eQOhVI8Edz49F7xpbxnGar aLelIIIlWuRyjdvUtsnitAfWvyGjqQ==
;; KeySigningRequest 1.0 20250215111826 (Sat Feb 15 12:18:26 2025)
example.net. 3600 IN DNSKEY 256 3 13 ph7zZ/QgvwHuq2U1aYoMT3MqPUZYEq6y4qNwOb8uzurVISxL0XyhYH+Q ngEOV2ECgndMjn8e1ujH/d0H3cPX8A==
example.net. 3600 IN DNSKEY 256 3 13 Z8WRuXJr9v7cSUZpJuQKN/1pZuLPEgoWx4eQOhVI8Edz49F7xpbxnGar aLelIIIlWuRyjdvUtsnitAfWvyGjqQ==
;; KeySigningRequest 1.0 20250225142826 (Tue Feb 25 15:28:26 2025)
example.net. 3600 IN DNSKEY 256 3 13 ph7zZ/QgvwHuq2U1aYoMT3MqPUZYEq6y4qNwOb8uzurVISxL0XyhYH+Q ngEOV2ECgndMjn8e1ujH/d0H3cPX8A==
...
The output shows that the ZSK rollovers are pre-planned, which will result
in a number of key bundles. Each bundle contains a start time and the ZSKs that
need to be published from that time.
The data needs to be stored in a file and can be handed over to the KSK
operators, and can be secured by encryption and/or digital signature.
Signed Key Response
^^^^^^^^^^^^^^^^^^^
The KSK operators receive a KSR file that contain ZSK sets for a given
interval. By signing the KSR, a Signed Key Response (SKR) is created that
consists of numerous response bundles; for each bundle, the DNSKEY RRset
needs to be constructed by combining the records of the KSK and ZSKs. Then,
a signature is generated for the constructed RRset. In addition, the signed
CDS and CDNSKEY RRsets are added.
Again the same interval and DNSSEC policy should be used. Below is the command
for signing a KSR file "example.net.ksr".
.. code-block:: none
# dnssec-ksr -i now -e +2y -k offline-ksk -l named.conf -K ksk -f example.net.ksr sign example.net
;; SignedKeyResponse 1.0 20240813134020 (Tue Aug 13 15:40:20 2024)
example.net. 3600 IN DNSKEY 257 3 13 vV2+6W+cFd3nn8eLrswUnhrPIxdgmslFWwF45MlCPIhjXIp6PpvaHC8k Y2RH46UrbWINDEo7k5wqvUncakKhJw==
example.net. 3600 IN DNSKEY 256 3 13 Z8WRuXJr9v7cSUZpJuQKN/1pZuLPEgoWx4eQOhVI8Edz49F7xpbxnGar aLelIIIlWuRyjdvUtsnitAfWvyGjqQ==
example.net. 3600 IN RRSIG DNSKEY 13 2 3600 20240827134020 20240813124020 6221 example.net. gkiw6M72Gi8XDu8XEAnPVR+AF4K7j1fApt2puLWgChayvaWrMPIbG2jP gvd/RJiJSsdGBx4P3GYdNqfFskNKIA==
example.net. 3600 IN CDNSKEY 257 3 13 vV2+6W+cFd3nn8eLrswUnhrPIxdgmslFWwF45MlCPIhjXIp6PpvaHC8k Y2RH46UrbWINDEo7k5wqvUncakKhJw==
example.net. 3600 IN RRSIG CDNSKEY 13 2 3600 20240827134020 20240813124020 6221 example.net. 1hAwRv2Nbkwfv8KWXdM9eBedgFZapECZJN4iTKj/yb50mjrPjK9JiQ92 m/xSFUC6gRxMkoPnaULYs+3Qc/XqDA==
example.net. 3600 IN CDS 6221 13 2 A9EEDE51FA154B90259A1B8788D26C53C20AFE759D3B5FEA0349675A EEC0479D
example.net. 3600 IN RRSIG CDS 13 2 3600 20240827134020 20240813124020 6221 example.net. TtbCbxTP4WEm5W8ZOdD3DgVlDSz0sdimm5YO28Bi+kP2ZVEM72A0B9QP pCiXKrRjCLN2aguqNlRzupWiwb22cA==
;; SignedKeyResponse 1.0 20240822134020 (Thu Aug 22 15:40:20 2024)
example.net. 3600 IN DNSKEY 257 3 13 vV2+6W+cFd3nn8eLrswUnhrPIxdgmslFWwF45MlCPIhjXIp6PpvaHC8k Y2RH46UrbWINDEo7k5wqvUncakKhJw==
example.net. 3600 IN DNSKEY 256 3 13 Z8WRuXJr9v7cSUZpJuQKN/1pZuLPEgoWx4eQOhVI8Edz49F7xpbxnGar aLelIIIlWuRyjdvUtsnitAfWvyGjqQ==
...
The output is stored in a file and can be given back to the ZSK operators.
Importing the SKR
^^^^^^^^^^^^^^^^^
Now that we have an SKR file, it needs to be imported into the DNS server,
via the :option:`rndc skr` command. Let's say the SKR is stored
in a file "example.net.skr":
.. code-block:: none
# rndc skr -import example.net.skr example.net
From now on, when it is time for a new signature for the DNSKEY, CDS, or CDNSKEY
RRset, instead of it being generated, it will be looked up in the SKR data.
When the SKR data is nearing the end of its lifetime, simply repeat the
four-step process for the next period.

View file

@ -13,6 +13,7 @@
dnssec-policy "default" {
// Keys
offline-ksk no;
keys {
csk key-directory lifetime unlimited algorithm 13;
};

View file

@ -18,6 +18,7 @@ dnssec-policy <string> {
keys { ( csk | ksk | zsk ) [ key-directory | key-store <string> ] lifetime <duration_or_unlimited> algorithm <string> [ <integer> ]; ... };
max-zone-ttl <duration>;
nsec3param [ iterations <integer> ] [ optout <boolean> ] [ salt-length <integer> ];
offline-ksk <boolean>;
parent-ds-ttl <duration>;
parent-propagation-delay <duration>;
publish-safety <duration>;

View file

@ -122,6 +122,7 @@ libdns_la_HEADERS = \
include/dns/sdlz.h \
include/dns/secalg.h \
include/dns/secproto.h \
include/dns/skr.h \
include/dns/soa.h \
include/dns/ssu.h \
include/dns/stats.h \
@ -241,6 +242,7 @@ libdns_la_SOURCES = \
rrl.c \
rriterator.c \
sdlz.c \
skr.c \
soa.c \
ssu.c \
ssu_external.c \

View file

@ -1601,6 +1601,13 @@ dns_dnssec_keylistfromrdataset(const dns_name_t *origin, dns_kasp_t *kasp,
}
RETERR(result);
if (kasp != NULL && dns_kasp_offlineksk(kasp) &&
(dst_key_flags(dnskey) & DNS_KEYFLAG_KSK) != 0)
{
result = ISC_R_NOPERM;
goto addkey;
}
/* Now read the private key. */
result = keyfromfile(
kasp, directory, dnskey,
@ -1666,6 +1673,7 @@ dns_dnssec_keylistfromrdataset(const dns_name_t *origin, dns_kasp_t *kasp,
filename, isc_result_totext(result));
}
addkey:
if (result == ISC_R_FILENOTFOUND || result == ISC_R_NOPERM) {
if (pubkey != NULL) {
addkey(keylist, &pubkey, savekeys, mctx);

View file

@ -325,6 +325,9 @@ dns_dnssec_keylistfromrdataset(const dns_name_t *origin, dns_kasp_t *kasp,
* 'keysigs' and 'soasigs', if not NULL and associated, contain the
* RRSIGS for the DNSKEY and SOA records respectively and are used to mark
* whether a key is already active in the zone.
*
* Private key files for keys with the KSK role are skipped if kasp is in
* offline-ksk mode.
*/
isc_result_t

View file

@ -90,6 +90,7 @@ struct dns_kasp {
uint32_t signatures_validity_dnskey;
/* Configuration: Keys */
bool offlineksk;
bool cdnskey;
dns_kasp_digestlist_t digests;
dns_kasp_keylist_t keys;
@ -809,6 +810,28 @@ dns_kasp_setnsec3param(dns_kasp_t *kasp, uint8_t iter, bool optout,
*
*/
bool
dns_kasp_offlineksk(dns_kasp_t *kasp);
/*%<
* Should we be using Offline KSK key management?
*
* Requires:
*
*\li 'kasp' is a valid, frozen kasp.
*
*/
void
dns_kasp_setofflineksk(dns_kasp_t *kasp, bool offlineksk);
/*%<
* Enable/disable Offline KSK.
*
* Requires:
*
*\li 'kasp' is a valid, unfrozen kasp.
*
*/
bool
dns_kasp_cdnskey(dns_kasp_t *kasp);
/*%<
@ -823,7 +846,7 @@ dns_kasp_cdnskey(dns_kasp_t *kasp);
void
dns_kasp_setcdnskey(dns_kasp_t *kasp, bool cdnskey);
/*%<
* Set to enable publication of CDNSKEY records.
* Enable/disable publication of CDNSKEY records.
*
* Requires:
*

View file

@ -52,6 +52,29 @@ dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass,
*\li On error, keypool is unchanged
*/
isc_result_t
dns_keymgr_offline(const dns_name_t *origin, dns_dnsseckeylist_t *keyring,
dns_kasp_t *kasp, isc_stdtime_t now,
isc_stdtime_t *nexttime);
/*%<
* Manage keys in 'keyring' when in offline-ksk mode, and update timing data
* according to the metadata in the key files. KSKs are skipped.
*
* Update key states and store changes back to disk. Store when to run next
* in 'nexttime'.
*
* Requires:
*\li 'origin' is a valid FQDN.
*\li 'mctx' is a valid memory context.
*\li 'keyring' is not NULL.
*\li 'kasp' is not NULL.
*
* Returns:
*\li #ISC_R_SUCCESS
*\li any error returned by dst_key_getstate(), dst_key_gettime(),
* isc_dir_open(), or dst_key_to_file().
*/
isc_result_t
dns_keymgr_checkds(dns_kasp_t *kasp, dns_dnsseckeylist_t *keyring,
isc_stdtime_t now, isc_stdtime_t when, bool dspublish);

149
lib/dns/include/dns/skr.h Normal file
View file

@ -0,0 +1,149 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* SPDX-License-Identifier: MPL-2.0
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
#pragma once
/*! \file dns/skr.h
* \brief
* A skr is a convenience type representing a Signed Key Response (SKR),
* determining which DNSKEY, CDS, CDNSKEY and corresponding signatures
* should be published at a given time. It is based on terminology used in
* https://www.iana.org/dnssec/archive/files/draft-icann-dnssec-keymgmt-01.txt
*/
#include <isc/stdtime.h>
#include <dns/diff.h>
#include <dns/types.h>
ISC_LANG_BEGINDECLS
#define DNS_SKR_MAGIC ISC_MAGIC('S', 'K', 'R', '-')
#define DNS_SKR_VALID(t) ISC_MAGIC_VALID(t, DNS_SKR_MAGIC)
#define DNS_SKRBUNDLE_MAGIC ISC_MAGIC('S', 'K', 'R', 'B')
#define DNS_SKRBUNDLE_VALID(t) ISC_MAGIC_VALID(t, DNS_SKRBUNDLE_MAGIC)
typedef struct dns_skrbundle dns_skrbundle_t;
typedef ISC_LIST(dns_skrbundle_t) dns_skrbundlelist_t;
/* Stores a Signed Key Response (SKR) */
struct dns_skr {
unsigned int magic;
isc_mem_t *mctx;
char *filename;
isc_time_t loadtime;
dns_skrbundlelist_t bundles;
isc_refcount_t references;
};
struct dns_skrbundle {
unsigned int magic;
isc_stdtime_t inception;
dns_diff_t diff;
ISC_LINK(dns_skrbundle_t) link;
};
isc_result_t
dns_skrbundle_getsig(dns_skrbundle_t *bundle, dst_key_t *key,
dns_rdatatype_t covering_type, dns_rdata_t *sigrdata);
/*%<
* Retrieve the RRSIG rdata for 'covering_type' generated by 'key' from the
* given 'bundle'.
*
* Requires:
* \li 'bundle' is a valid bundle
*
* Returns:
* \li a possible error if we fail to convert the rdata to a struct
* \li ISC_R_SUCCESS if the signature is found
* \li ISC_R_NOTFOUND otherwise
*/
void
dns_skr_create(isc_mem_t *mctx, const char *filename, dns_name_t *origin,
dns_rdataclass_t rdclass, dns_skr_t **skrp);
/*%<
* Create a SKR.
*
* Requires:
* \li mctx != NULL
* \li *skrp != NULL && *skrp == NULL
*/
isc_result_t
dns_skr_read(isc_mem_t *mctx, const char *filename, dns_name_t *origin,
dns_rdataclass_t rdclass, dns_ttl_t dnskeyttl, dns_skr_t **skrp);
/*%<
* Read a SKR from 'filename'.
*
* Requires:
* \li mctx != NULL
* \li *skrp != NULL && *skrp == NULL
*/
dns_skrbundle_t *
dns_skr_lookup(dns_skr_t *skr, isc_stdtime_t time, uint32_t sigval);
/*%<
* Look up the currently active bundle. The active bundle is the one which
* inception time is prior to 'time' and the next bundle inception is after
" 'time'. In case of the last bundle in the SKR, 'time' is expected to be
* lower than the last bundle inception time plus 'sigval'.
*
* Requires:
* \li 'skr' is a valid SKR
*
* Returns:
* \li The currently active bundle, or NULL if no such bundle is found.
*/
void
dns_skr_attach(dns_skr_t *source, dns_skr_t **targetp);
/*%<
* Attach '*targetp' to 'source'.
*
* Requires:
*
*\li 'source' is a valid SKR.
*
*\li 'targetp' points to a NULL dns_skr_t *.
*
* Ensures:
*
*\li *targetp is attached to source.
*/
void
dns_skr_detach(dns_skr_t **skrp);
/*%<
* Detach SKR.
*
* Requires:
*
*\li 'skrp' points to a valid dns_skr_t *
*
* Ensures:
*
*\li *skrp is NULL.
*/
void
dns_skr_destroy(dns_skr_t *skr);
/*%<
* Destroy a SKR.
*
* Requires:
* \li 'skr' is a valid SKR
*/
ISC_LANG_ENDDECLS

View file

@ -150,6 +150,7 @@ typedef struct dns_qpnode dns_qpnode_t;
typedef uint8_t dns_secalg_t;
typedef uint8_t dns_secproto_t;
typedef struct dns_signature dns_signature_t;
typedef struct dns_skr dns_skr_t;
typedef struct dns_slabheader dns_slabheader_t;
typedef ISC_LIST(dns_slabheader_t) dns_slabheaderlist_t;
typedef struct dns_sortlist_arg dns_sortlist_arg_t;

View file

@ -34,6 +34,7 @@
#include <dns/masterdump.h>
#include <dns/rdatastruct.h>
#include <dns/rpz.h>
#include <dns/skr.h>
#include <dns/types.h>
#include <dns/xfrin.h>
#include <dns/zt.h>
@ -761,6 +762,15 @@ dns_zone_setdefaultkasp(dns_zone_t *zone, dns_kasp_t *kasp);
*\li 'zone' to be a valid zone.
*/
dns_skrbundle_t *
dns_zone_getskrbundle(dns_zone_t *zone);
/*%<
* Returns the current SKR bundle.
*
* Require:
*\li 'zone' to be a valid zone.
*/
void
dns_zone_setoption(dns_zone_t *zone, dns_zoneopt_t option, bool value);
/*%<
@ -2743,13 +2753,26 @@ dns_zone_check_dnskey_nsec3(dns_zone_t *zone, dns_db_t *db,
*
* Requires:
* \li 'zone' to be a valid zone.
* \li 'db'is not NULL.
* \li 'db' is not NULL.
*
* Returns:
* \li 'true' if the check passes, that is the zone remains consistent,
* 'false' if the zone would have NSEC only DNSKEYs and an NSEC3 chain.
*/
isc_result_t
dns_zone_import_skr(dns_zone_t *zone, const char *file);
/**<
* Import a Signed Key Response (SKR) from file.
*
* Requires:
* \li 'zone' to be a valid zone.
* \li 'file' is not NULL.
*
* Returns:
* \li ISC_R_SUCCESS if there were no errors loading the SKR.
*/
#if DNS_ZONE_TRACE
#define dns_zone_ref(ptr) dns_zone__ref(ptr, __func__, __FILE__, __LINE__)
#define dns_zone_unref(ptr) dns_zone__unref(ptr, __func__, __FILE__, __LINE__)

View file

@ -595,6 +595,22 @@ dns_kasp_setnsec3param(dns_kasp_t *kasp, uint8_t iter, bool optout,
kasp->nsec3param.saltlen = saltlen;
}
bool
dns_kasp_offlineksk(dns_kasp_t *kasp) {
REQUIRE(kasp != NULL);
REQUIRE(kasp->frozen);
return kasp->offlineksk;
}
void
dns_kasp_setofflineksk(dns_kasp_t *kasp, bool offlineksk) {
REQUIRE(kasp != NULL);
REQUIRE(!kasp->frozen);
kasp->offlineksk = offlineksk;
}
bool
dns_kasp_cdnskey(dns_kasp_t *kasp) {
REQUIRE(kasp != NULL);

View file

@ -2664,3 +2664,177 @@ dns_keymgr_rollover(dns_kasp_t *kasp, dns_dnsseckeylist_t *keyring,
return (result);
}
isc_result_t
dns_keymgr_offline(const dns_name_t *origin, dns_dnsseckeylist_t *keyring,
dns_kasp_t *kasp, isc_stdtime_t now,
isc_stdtime_t *nexttime) {
isc_result_t result = ISC_R_SUCCESS;
int options = (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC | DST_TYPE_STATE);
char keystr[DST_KEY_FORMATSIZE];
*nexttime = 0;
/* Store key states and update hints. */
for (dns_dnsseckey_t *dkey = ISC_LIST_HEAD(*keyring); dkey != NULL;
dkey = ISC_LIST_NEXT(dkey, link))
{
bool modified;
bool ksk = false, zsk = false;
isc_stdtime_t active = 0, published = 0, inactive = 0,
remove = 0;
isc_stdtime_t lastchange = 0, nextchange = 0;
dst_key_state_t dnskey_state = HIDDEN, zrrsig_state = HIDDEN,
goal_state = HIDDEN;
dst_key_state_t current_dnskey, current_zrrsig, current_goal;
(void)dst_key_role(dkey->key, &ksk, &zsk);
if (ksk || !zsk) {
continue;
}
keymgr_key_init(dkey, kasp, now, false);
/* Get current metadata */
RETERR(dst_key_getstate(dkey->key, DST_KEY_DNSKEY,
&current_dnskey));
RETERR(dst_key_getstate(dkey->key, DST_KEY_ZRRSIG,
&current_zrrsig));
RETERR(dst_key_getstate(dkey->key, DST_KEY_GOAL,
&current_goal));
RETERR(dst_key_gettime(dkey->key, DST_TIME_PUBLISH,
&published));
RETERR(dst_key_gettime(dkey->key, DST_TIME_ACTIVATE, &active));
RETERR(dst_key_gettime(dkey->key, DST_TIME_INACTIVE,
&inactive));
RETERR(dst_key_gettime(dkey->key, DST_TIME_DELETE, &remove));
/* Determine key states from the metadata. */
if (active <= now) {
dns_ttl_t ttlsig = dns_kasp_zonemaxttl(kasp, true);
ttlsig += dns_kasp_zonepropagationdelay(kasp);
if ((active + ttlsig) <= now) {
zrrsig_state = OMNIPRESENT;
} else {
zrrsig_state = RUMOURED;
(void)dst_key_gettime(dkey->key,
DST_TIME_ZRRSIG,
&lastchange);
nextchange = lastchange + ttlsig +
dns_kasp_retiresafety(kasp);
}
goal_state = OMNIPRESENT;
}
if (published <= now) {
dns_ttl_t key_ttl = dst_key_getttl(dkey->key);
key_ttl += dns_kasp_zonepropagationdelay(kasp);
if ((published + key_ttl) <= now) {
dnskey_state = OMNIPRESENT;
} else {
dnskey_state = RUMOURED;
(void)dst_key_gettime(dkey->key,
DST_TIME_DNSKEY,
&lastchange);
nextchange = lastchange + key_ttl +
dns_kasp_publishsafety(kasp);
}
goal_state = OMNIPRESENT;
}
if (inactive <= now) {
dns_ttl_t ttlsig = dns_kasp_zonemaxttl(kasp, true);
ttlsig += dns_kasp_zonepropagationdelay(kasp);
if ((inactive + ttlsig) <= now) {
zrrsig_state = HIDDEN;
} else {
zrrsig_state = UNRETENTIVE;
(void)dst_key_gettime(dkey->key,
DST_TIME_ZRRSIG,
&lastchange);
nextchange = lastchange + ttlsig +
dns_kasp_retiresafety(kasp);
}
goal_state = HIDDEN;
}
if (remove <= now) {
dns_ttl_t key_ttl = dst_key_getttl(dkey->key);
key_ttl += dns_kasp_zonepropagationdelay(kasp);
if ((remove + key_ttl) <= now) {
dnskey_state = HIDDEN;
} else {
dnskey_state = UNRETENTIVE;
(void)dst_key_gettime(dkey->key,
DST_TIME_DNSKEY,
&lastchange);
nextchange =
lastchange + key_ttl +
dns_kasp_zonepropagationdelay(kasp);
}
zrrsig_state = HIDDEN;
goal_state = HIDDEN;
}
if ((*nexttime == 0 || *nexttime > nextchange) &&
nextchange > 0)
{
*nexttime = nextchange;
}
/* Update key states if necessary. */
if (goal_state != current_goal) {
dst_key_setstate(dkey->key, DST_KEY_GOAL, goal_state);
}
if (dnskey_state != current_dnskey) {
dst_key_setstate(dkey->key, DST_KEY_DNSKEY,
dnskey_state);
dst_key_settime(dkey->key, DST_TIME_DNSKEY, now);
}
if (zrrsig_state != current_zrrsig) {
dst_key_setstate(dkey->key, DST_KEY_ZRRSIG,
zrrsig_state);
dst_key_settime(dkey->key, DST_TIME_ZRRSIG, now);
if (zrrsig_state == RUMOURED) {
dkey->first_sign = true;
}
}
modified = dst_key_ismodified(dkey->key);
if (modified) {
const char *directory = dst_key_directory(dkey->key);
if (directory == NULL) {
directory = ".";
}
dns_dnssec_get_hints(dkey, now);
RETERR(dst_key_tofile(dkey->key, options, directory));
dst_key_setmodified(dkey->key, false);
if (!isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
continue;
}
dst_key_format(dkey->key, keystr, sizeof(keystr));
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC,
DNS_LOGMODULE_DNSSEC, ISC_LOG_DEBUG(3),
"keymgr: DNSKEY %s (%s) "
"saved to directory %s, policy %s",
keystr, keymgr_keyrole(dkey->key),
directory, dns_kasp_getname(kasp));
}
dst_key_setmodified(dkey->key, false);
}
result = ISC_R_SUCCESS;
failure:
if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
char namebuf[DNS_NAME_FORMATSIZE];
dns_name_format(origin, namebuf, sizeof(namebuf));
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC,
DNS_LOGMODULE_DNSSEC, ISC_LOG_DEBUG(3),
"keymgr: %s (offline-ksk) done", namebuf);
}
return (result);
}

455
lib/dns/skr.c Normal file
View file

@ -0,0 +1,455 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* SPDX-License-Identifier: MPL-2.0
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
/*! \file */
#include <isc/lex.h>
#include <isc/log.h>
#include <dns/callbacks.h>
#include <dns/fixedname.h>
#include <dns/rdata.h>
#include <dns/rdataclass.h>
#include <dns/rdatatype.h>
#include <dns/skr.h>
#include <dns/time.h>
#include <dns/ttl.h>
#define CHECK(op) \
do { \
result = (op); \
if (result != ISC_R_SUCCESS) \
goto failure; \
} while (0)
#define READLINE(lex, opt, token)
#define NEXTTOKEN(lex, opt, token) \
{ \
ret = isc_lex_gettoken(lex, opt, token); \
if (ret != ISC_R_SUCCESS) \
goto cleanup; \
}
#define BADTOKEN() \
{ \
ret = ISC_R_UNEXPECTEDTOKEN; \
goto cleanup; \
}
#define TOKENSIZ (8 * 1024)
#define STR(t) ((t).value.as_textregion.base)
static isc_result_t
parse_rr(isc_lex_t *lex, isc_mem_t *mctx, char *owner, dns_name_t *origin,
dns_rdataclass_t rdclass, isc_buffer_t *buf, dns_ttl_t *ttl,
dns_rdatatype_t *rdtype, dns_rdata_t **rdata) {
dns_rdatacallbacks_t callbacks;
dns_fixedname_t dfname;
dns_name_t *dname = NULL;
dns_rdataclass_t clas;
isc_buffer_t b;
isc_token_t token;
unsigned int opt = ISC_LEXOPT_EOL;
isc_result_t ret = ISC_R_SUCCESS;
isc_lex_setcomments(lex, ISC_LEXCOMMENT_DNSMASTERFILE);
/* Read the domain name */
if (!strcmp(owner, "@")) {
BADTOKEN();
}
dname = dns_fixedname_initname(&dfname);
isc_buffer_init(&b, owner, strlen(owner));
isc_buffer_add(&b, strlen(owner));
ret = dns_name_fromtext(dname, &b, dns_rootname, 0, NULL);
if (ret != ISC_R_SUCCESS) {
return (ret);
}
if (dns_name_compare(dname, origin) != 0) {
return (DNS_R_BADOWNERNAME);
}
isc_buffer_clear(&b);
/* Read the next word: either TTL, class, or type */
NEXTTOKEN(lex, opt, &token);
if (token.type != isc_tokentype_string) {
BADTOKEN();
}
/* If it's a TTL, read the next one */
ret = dns_ttl_fromtext(&token.value.as_textregion, ttl);
if (ret == ISC_R_SUCCESS) {
NEXTTOKEN(lex, opt, &token);
}
if (token.type != isc_tokentype_string) {
BADTOKEN();
}
/* If it's a class, read the next one */
ret = dns_rdataclass_fromtext(&clas, &token.value.as_textregion);
if (ret == ISC_R_SUCCESS) {
if (clas != rdclass) {
BADTOKEN();
}
NEXTTOKEN(lex, opt, &token);
}
if (token.type != isc_tokentype_string) {
BADTOKEN();
}
/* Must be the record type */
ret = dns_rdatatype_fromtext(rdtype, &token.value.as_textregion);
if (ret != ISC_R_SUCCESS) {
BADTOKEN();
}
switch (*rdtype) {
case dns_rdatatype_dnskey:
case dns_rdatatype_cdnskey:
case dns_rdatatype_cds:
case dns_rdatatype_rrsig:
/* Allowed record types */
break;
default:
BADTOKEN();
}
dns_rdatacallbacks_init(&callbacks);
ret = dns_rdata_fromtext(*rdata, rdclass, *rdtype, lex, dname, 0, mctx,
buf, &callbacks);
cleanup:
isc_lex_setcomments(lex, 0);
return (ret);
}
static void
skrbundle_create(isc_mem_t *mctx, isc_stdtime_t inception,
dns_skrbundle_t **bp) {
dns_skrbundle_t *b;
REQUIRE(bp != NULL && *bp == NULL);
b = isc_mem_get(mctx, sizeof(*b));
b->magic = DNS_SKRBUNDLE_MAGIC;
b->inception = inception;
dns_diff_init(mctx, &b->diff);
ISC_LINK_INIT(b, link);
*bp = b;
}
static void
skrbundle_addtuple(dns_skrbundle_t *bundle, dns_difftuple_t **tuple) {
REQUIRE(DNS_DIFFTUPLE_VALID(*tuple));
REQUIRE(DNS_SKRBUNDLE_VALID(bundle));
REQUIRE(DNS_DIFF_VALID(&bundle->diff));
dns_diff_append(&bundle->diff, tuple);
}
isc_result_t
dns_skrbundle_getsig(dns_skrbundle_t *bundle, dst_key_t *key,
dns_rdatatype_t covering_type, dns_rdata_t *sigrdata) {
isc_result_t result = ISC_R_SUCCESS;
REQUIRE(DNS_SKRBUNDLE_VALID(bundle));
REQUIRE(DNS_DIFF_VALID(&bundle->diff));
dns_difftuple_t *tuple = ISC_LIST_HEAD(bundle->diff.tuples);
while (tuple != NULL) {
dns_rdata_rrsig_t rrsig;
if (tuple->op != DNS_DIFFOP_ADDRESIGN) {
tuple = ISC_LIST_NEXT(tuple, link);
continue;
}
INSIST(tuple->rdata.type == dns_rdatatype_rrsig);
result = dns_rdata_tostruct(&tuple->rdata, &rrsig, NULL);
if (result != ISC_R_SUCCESS) {
return (result);
}
/*
* Check if covering type matches, and if the signature is
* generated by 'key'.
*/
if (rrsig.covered == covering_type &&
rrsig.keyid == dst_key_id(key))
{
dns_rdata_clone(&tuple->rdata, sigrdata);
return (ISC_R_SUCCESS);
}
tuple = ISC_LIST_NEXT(tuple, link);
}
return (ISC_R_NOTFOUND);
}
void
dns_skr_create(isc_mem_t *mctx, const char *filename, dns_name_t *origin,
dns_rdataclass_t rdclass, dns_skr_t **skrp) {
isc_time_t now;
dns_skr_t *skr = NULL;
REQUIRE(skrp != NULL && *skrp == NULL);
REQUIRE(mctx != NULL);
UNUSED(origin);
UNUSED(rdclass);
now = isc_time_now();
skr = isc_mem_get(mctx, sizeof(*skr));
*skr = (dns_skr_t){
.magic = DNS_SKR_MAGIC,
.filename = isc_mem_strdup(mctx, filename),
.loadtime = now,
};
/*
* A list is not the best structure to store bundles that
* we need to look up, but we don't expect many bundles
* per SKR so it is acceptable for now.
*/
ISC_LIST_INIT(skr->bundles);
isc_mem_attach(mctx, &skr->mctx);
isc_refcount_init(&skr->references, 1);
*skrp = skr;
}
static void
addbundle(dns_skr_t *skr, dns_skrbundle_t **bundlep) {
REQUIRE(DNS_SKR_VALID(skr));
REQUIRE(DNS_SKRBUNDLE_VALID(*bundlep));
ISC_LIST_APPEND(skr->bundles, *bundlep, link);
*bundlep = NULL;
}
isc_result_t
dns_skr_read(isc_mem_t *mctx, const char *filename, dns_name_t *origin,
dns_rdataclass_t rdclass, dns_ttl_t dnskeyttl, dns_skr_t **skrp) {
isc_result_t result;
dns_skrbundle_t *bundle = NULL;
char bundlebuf[1024];
uint32_t bundle_id;
isc_lex_t *lex = NULL;
isc_lexspecials_t specials;
isc_token_t token;
unsigned int opt = ISC_LEXOPT_EOL;
REQUIRE(DNS_SKR_VALID(*skrp));
isc_lex_create(mctx, TOKENSIZ, &lex);
memset(specials, 0, sizeof(specials));
specials['('] = 1;
specials[')'] = 1;
specials['"'] = 1;
isc_lex_setspecials(lex, specials);
result = isc_lex_openfile(lex, filename);
if (result != ISC_R_SUCCESS) {
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
DNS_LOGMODULE_ZONE, ISC_LOG_ERROR,
"unable to open ksr file %s: %s", filename,
isc_result_totext(result));
isc_lex_destroy(&lex);
return (result);
}
for (result = isc_lex_gettoken(lex, opt, &token);
result == ISC_R_SUCCESS;
result = isc_lex_gettoken(lex, opt, &token))
{
if (token.type == isc_tokentype_eol) {
continue;
}
if (token.type != isc_tokentype_string) {
CHECK(DNS_R_SYNTAX);
}
if (strcmp(STR(token), ";;") == 0) {
/* New bundle */
CHECK(isc_lex_gettoken(lex, opt, &token));
if (token.type != isc_tokentype_string ||
strcmp(STR(token), "SignedKeyResponse") != 0)
{
CHECK(DNS_R_SYNTAX);
}
/* Version */
CHECK(isc_lex_gettoken(lex, opt, &token));
if (token.type != isc_tokentype_string ||
strcmp(STR(token), "1.0") != 0)
{
CHECK(DNS_R_SYNTAX);
}
/* Date and time of bundle */
CHECK(isc_lex_gettoken(lex, opt, &token));
if (token.type != isc_tokentype_string) {
CHECK(DNS_R_SYNTAX);
}
if (strcmp(STR(token), "generated") == 0) {
/* Final bundle */
goto readline;
}
if (token.type != isc_tokentype_string) {
CHECK(DNS_R_SYNTAX);
}
/* Add previous bundle */
if (bundle != NULL) {
addbundle(*skrp, &bundle);
}
/* Create new bundle */
sscanf(STR(token), "%s", bundlebuf);
CHECK(dns_time32_fromtext(bundlebuf, &bundle_id));
bundle = NULL;
skrbundle_create(mctx, (isc_stdtime_t)bundle_id,
&bundle);
readline:
/* Read remainder of header line */
do {
CHECK(isc_lex_gettoken(lex, opt, &token));
} while (token.type != isc_tokentype_eol);
} else {
isc_buffer_t buf;
dns_rdata_t *rdata = NULL;
u_char rdatabuf[DST_KEY_MAXSIZE];
dns_rdatatype_t rdtype;
/* Parse record */
rdata = isc_mem_get(mctx, sizeof(*rdata));
dns_rdata_init(rdata);
isc_buffer_init(&buf, rdatabuf, sizeof(rdatabuf));
result = parse_rr(lex, mctx, STR(token), origin,
rdclass, &buf, &dnskeyttl, &rdtype,
&rdata);
if (result != ISC_R_SUCCESS) {
isc_log_write(
dns_lctx, DNS_LOGCATEGORY_GENERAL,
DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(1),
"read skr file %s(%lu) parse rr "
"failed: %s",
filename, isc_lex_getsourceline(lex),
isc_result_totext(result));
isc_mem_put(mctx, rdata, sizeof(*rdata));
goto failure;
}
/* Create new diff tuple */
dns_diffop_t op = (rdtype == dns_rdatatype_rrsig)
? DNS_DIFFOP_ADDRESIGN
: DNS_DIFFOP_ADD;
dns_difftuple_t *tuple = NULL;
dns_difftuple_create((*skrp)->mctx, op, origin,
dnskeyttl, rdata, &tuple);
skrbundle_addtuple(bundle, &tuple);
INSIST(tuple == NULL);
isc_mem_put(mctx, rdata, sizeof(*rdata));
}
}
if (result != ISC_R_EOF) {
CHECK(DNS_R_SYNTAX);
}
result = ISC_R_SUCCESS;
/* Add final bundle */
if (bundle != NULL) {
addbundle(*skrp, &bundle);
}
failure:
if (result != ISC_R_SUCCESS) {
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(1),
"read skr file %s(%lu) failed: %s", filename,
isc_lex_getsourceline(lex),
isc_result_totext(result));
}
/* Clean up */
isc_lex_destroy(&lex);
return (result);
}
dns_skrbundle_t *
dns_skr_lookup(dns_skr_t *skr, isc_stdtime_t time, uint32_t sigval) {
dns_skrbundle_t *b, *next;
REQUIRE(DNS_SKR_VALID(skr));
for (b = ISC_LIST_HEAD(skr->bundles); b != NULL; b = next) {
next = ISC_LIST_NEXT(b, link);
if (next == NULL) {
isc_stdtime_t expired = b->inception + sigval;
if (b->inception <= time && time < expired) {
return (b);
}
return (NULL);
}
if (b->inception <= time && time < next->inception) {
return (b);
}
}
return (NULL);
}
void
dns_skr_attach(dns_skr_t *source, dns_skr_t **targetp) {
REQUIRE(DNS_SKR_VALID(source));
REQUIRE(targetp != NULL && *targetp == NULL);
isc_refcount_increment(&source->references);
*targetp = source;
}
void
dns_skr_detach(dns_skr_t **skrp) {
REQUIRE(skrp != NULL && DNS_SKR_VALID(*skrp));
dns_skr_t *skr = *skrp;
*skrp = NULL;
if (isc_refcount_decrement(&skr->references) == 1) {
dns_skr_destroy(skr);
}
}
void
dns_skr_destroy(dns_skr_t *skr) {
dns_skrbundle_t *b, *next;
REQUIRE(DNS_SKR_VALID(skr));
for (b = ISC_LIST_HEAD(skr->bundles); b != NULL; b = next) {
next = ISC_LIST_NEXT(b, link);
ISC_LIST_UNLINK(skr->bundles, b, link);
dns_diff_clear(&b->diff);
isc_mem_put(skr->mctx, b, sizeof(*b));
}
INSIST(ISC_LIST_EMPTY(skr->bundles));
isc_mem_free(skr->mctx, skr->filename);
isc_mem_putanddetach(&skr->mctx, skr, sizeof(*skr));
}

View file

@ -46,6 +46,7 @@
#include <dns/rdatasetiter.h>
#include <dns/rdatastruct.h>
#include <dns/rdatatype.h>
#include <dns/skr.h>
#include <dns/soa.h>
#include <dns/ssu.h>
#include <dns/stats.h>
@ -1121,10 +1122,12 @@ add_sigs(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
unsigned int i;
bool added_sig = false;
bool use_kasp = false;
bool offlineksk = false;
isc_mem_t *mctx = diff->mctx;
if (kasp != NULL) {
use_kasp = true;
offlineksk = dns_kasp_offlineksk(kasp);
}
dns_rdataset_init(&rdataset);
@ -1154,10 +1157,10 @@ add_sigs(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
bool both = false;
/* Don't add signatures for offline or inactive keys */
if (!dst_key_isprivate(keys[i])) {
if (!dst_key_isprivate(keys[i]) && !offlineksk) {
continue;
}
if (dst_key_inactive(keys[i])) {
if (dst_key_inactive(keys[i]) && !offlineksk) {
continue;
}
@ -1184,6 +1187,13 @@ add_sigs(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
}
}
if (!dst_key_isprivate(keys[i]) && offlineksk && zsk) {
continue;
}
if (dst_key_inactive(keys[i]) && offlineksk && zsk) {
continue;
}
if (dns_rdatatype_iskeymaterial(type)) {
/*
* DNSKEY RRset is signed with KSK.
@ -1238,8 +1248,19 @@ add_sigs(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
}
/* Calculate the signature, creating a RRSIG RDATA. */
CHECK(dns_dnssec_sign(name, &rdataset, keys[i], &inception,
&expire, mctx, &buffer, &sig_rdata));
if (offlineksk && dns_rdatatype_iskeymaterial(type)) {
/* Look up the signature in the SKR bundle */
dns_skrbundle_t *bundle = dns_zone_getskrbundle(zone);
if (bundle == NULL) {
CHECK(DNS_R_NOSKRBUNDLE);
}
CHECK(dns_skrbundle_getsig(bundle, keys[i], type,
&sig_rdata));
} else {
CHECK(dns_dnssec_sign(name, &rdataset, keys[i],
&inception, &expire, mctx,
&buffer, &sig_rdata));
}
/* Update the database and journal with the RRSIG. */
/* XXX inefficient - will cause dataset merging */

View file

@ -79,11 +79,13 @@
#include <dns/request.h>
#include <dns/resolver.h>
#include <dns/rriterator.h>
#include <dns/skr.h>
#include <dns/soa.h>
#include <dns/ssu.h>
#include <dns/stats.h>
#include <dns/time.h>
#include <dns/tsig.h>
#include <dns/ttl.h>
#include <dns/update.h>
#include <dns/xfrin.h>
#include <dns/zone.h>
@ -499,6 +501,12 @@ struct dns_zone {
dns_update_state_t *rss_state;
isc_stats_t *gluecachestats;
/*%
* Offline KSK signed key responses.
*/
dns_skr_t *skr;
dns_skrbundle_t *skrbundle;
};
#define zonediff_init(z, d) \
@ -1273,6 +1281,10 @@ zone_free(dns_zone_t *zone) {
if (!ISC_LIST_EMPTY(zone->checkds_ok)) {
clear_keylist(&zone->checkds_ok, zone->mctx);
}
if (zone->skr != NULL) {
zone->skrbundle = NULL;
dns_skr_detach(&zone->skr);
}
zone->journalsize = -1;
if (zone->journal != NULL) {
@ -5734,6 +5746,38 @@ dns_zone_getkasp(dns_zone_t *zone) {
return (kasp);
}
static void
dns_zone_setskr(dns_zone_t *zone, dns_skr_t *skr) {
REQUIRE(DNS_ZONE_VALID(zone));
LOCK_ZONE(zone);
zone->skrbundle = NULL;
if (zone->skr != NULL) {
dns_skr_detach(&zone->skr);
}
if (skr != NULL) {
dns_skr_attach(skr, &zone->skr);
}
UNLOCK_ZONE(zone);
}
dns_skrbundle_t *
dns_zone_getskrbundle(dns_zone_t *zone) {
dns_skrbundle_t *bundle;
REQUIRE(DNS_ZONE_VALID(zone));
LOCK_ZONE(zone);
if (inline_raw(zone) && zone->secure != NULL) {
bundle = zone->secure->skrbundle;
} else {
bundle = zone->skrbundle;
}
UNLOCK_ZONE(zone);
return (bundle);
}
void
dns_zone_setoption(dns_zone_t *zone, dns_zoneopt_t option, bool value) {
REQUIRE(DNS_ZONE_VALID(zone));
@ -6558,12 +6602,17 @@ del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
dns_rdataset_t rdataset;
unsigned int i;
dns_rdata_rrsig_t rrsig;
bool kasp = zone->kasp;
dns_kasp_t *kasp = zone->kasp;
bool found;
bool offlineksk = false;
int64_t timewarn = 0, timemaybe = 0;
dns_rdataset_init(&rdataset);
if (kasp != NULL) {
offlineksk = dns_kasp_offlineksk(kasp);
}
if (type == dns_rdatatype_nsec3) {
result = dns_db_findnsec3node(db, name, false, &node);
} else {
@ -6599,7 +6648,9 @@ del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
if (!dns_rdatatype_iskeymaterial(type)) {
bool warn = false, deleted = false;
if (delsig_ok(&rrsig, keys, nkeys, kasp, &warn)) {
if (delsig_ok(&rrsig, keys, nkeys, (kasp != NULL),
&warn))
{
result = update_one_rr(db, ver, zonediff->diff,
DNS_DIFFOP_DELRESIGN,
name, rdataset.ttl,
@ -6669,7 +6720,7 @@ del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
* iff there is a new offline signature.
*/
if (!dst_key_inactive(keys[i]) &&
!dst_key_isprivate(keys[i]))
!dst_key_isprivate(keys[i]) && !offlineksk)
{
int64_t timeexpire = dns_time64_from32(
rrsig.timeexpire);
@ -6756,9 +6807,11 @@ add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_zone_t *zone,
isc_buffer_t buffer;
unsigned int i;
bool use_kasp = false;
bool offlineksk = false;
if (zone->kasp != NULL) {
use_kasp = true;
offlineksk = dns_kasp_offlineksk(zone->kasp);
}
dns_rdataset_init(&rdataset);
@ -6789,10 +6842,10 @@ add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_zone_t *zone,
for (i = 0; i < nkeys; i++) {
/* Don't add signatures for offline or inactive keys */
if (!dst_key_isprivate(keys[i])) {
if (!dst_key_isprivate(keys[i]) && !offlineksk) {
continue;
}
if (dst_key_inactive(keys[i])) {
if (dst_key_inactive(keys[i]) && !offlineksk) {
continue;
}
@ -6823,9 +6876,20 @@ add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_zone_t *zone,
/*
* Don't consider inactive keys or offline keys.
*/
(void)dst_key_have_ksk_and_zsk(keys, nkeys, i, true,
ksk, zsk, NULL,
&have_zsk);
if (!dst_key_isprivate(keys[i]) && offlineksk && zsk) {
continue;
}
if (dst_key_inactive(keys[i]) && offlineksk && zsk) {
continue;
}
if (offlineksk) {
have_zsk = true;
} else {
(void)dst_key_have_ksk_and_zsk(keys, nkeys, i,
true, ksk, zsk,
NULL, &have_zsk);
}
if (dns_rdatatype_iskeymaterial(type)) {
/*
@ -6888,8 +6952,20 @@ add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_zone_t *zone,
/* Calculate the signature, creating a RRSIG RDATA. */
isc_buffer_clear(&buffer);
CHECK(dns_dnssec_sign(name, &rdataset, keys[i], &inception,
&expire, mctx, &buffer, &sig_rdata));
if (offlineksk && dns_rdatatype_iskeymaterial(type)) {
/* Look up the signature in the SKR bundle */
dns_skrbundle_t *bundle = dns_zone_getskrbundle(zone);
if (bundle == NULL) {
CHECK(DNS_R_NOSKRBUNDLE);
}
CHECK(dns_skrbundle_getsig(bundle, keys[i], type,
&sig_rdata));
} else {
CHECK(dns_dnssec_sign(name, &rdataset, keys[i],
&inception, &expire, mctx,
&buffer, &sig_rdata));
}
/* Update the database and journal with the RRSIG. */
/* XXX inefficient - will cause dataset merging */
@ -7383,11 +7459,15 @@ sign_a_node(dns_db_t *db, dns_zone_t *zone, dns_name_t *name,
dns_rdataset_t rdataset;
dns_rdata_t rdata = DNS_RDATA_INIT;
dns_stats_t *dnssecsignstats;
bool offlineksk = false;
isc_buffer_t buffer;
unsigned char data[1024];
bool seen_soa, seen_ns, seen_rr, seen_nsec, seen_nsec3, seen_ds;
if (zone->kasp != NULL) {
offlineksk = dns_kasp_offlineksk(zone->kasp);
}
result = dns_db_allrdatasets(db, node, version, 0, 0, &iterator);
if (result != ISC_R_SUCCESS) {
if (result == ISC_R_NOTFOUND) {
@ -7491,8 +7571,19 @@ sign_a_node(dns_db_t *db, dns_zone_t *zone, dns_name_t *name,
/* Calculate the signature, creating a RRSIG RDATA. */
isc_buffer_clear(&buffer);
CHECK(dns_dnssec_sign(name, &rdataset, key, &inception, &expire,
mctx, &buffer, &rdata));
if (offlineksk && dns_rdatatype_iskeymaterial(rdataset.type)) {
/* Look up the signature in the SKR bundle */
dns_skrbundle_t *bundle = dns_zone_getskrbundle(zone);
if (bundle == NULL) {
CHECK(DNS_R_NOSKRBUNDLE);
}
CHECK(dns_skrbundle_getsig(bundle, key, rdataset.type,
&rdata));
} else {
CHECK(dns_dnssec_sign(name, &rdataset, key, &inception,
&expire, mctx, &buffer, &rdata));
}
/* Update the database and journal with the RRSIG. */
/* XXX inefficient - will cause dataset merging */
CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADDRESIGN,
@ -21874,6 +21965,71 @@ update_ttl(dns_rdataset_t *rdataset, dns_name_t *name, dns_ttl_t ttl,
return (ISC_R_SUCCESS);
}
static void
remove_rdataset(dns_zone_t *zone, dns_diff_t *diff, dns_rdataset_t *rdataset) {
if (!dns_rdataset_isassociated(rdataset)) {
return;
}
for (isc_result_t result = dns_rdataset_first(rdataset);
result == ISC_R_SUCCESS; result = dns_rdataset_next(rdataset))
{
dns_rdata_t rdata = DNS_RDATA_INIT;
dns_difftuple_t *tuple = NULL;
dns_rdataset_current(rdataset, &rdata);
dns_difftuple_create(zone->mctx, DNS_DIFFOP_DEL, &zone->origin,
rdataset->ttl, &rdata, &tuple);
dns_diff_append(diff, &tuple);
}
return;
}
static void
add_tuple(dns_diff_t *diff, dns_difftuple_t *tuple) {
dns_difftuple_t *copy = NULL;
dns_difftuple_copy(tuple, &copy);
dns_diff_appendminimal(diff, &copy);
}
static void
zone_apply_skrbundle(dns_zone_t *zone, dns_skrbundle_t *bundle,
dns_rdataset_t *dnskeyset, dns_rdataset_t *cdsset,
dns_rdataset_t *cdnskeyset, dns_diff_t *diff) {
dns_kasp_t *kasp = zone->kasp;
REQUIRE(DNS_ZONE_VALID(zone));
REQUIRE(DNS_KASP_VALID(kasp));
REQUIRE(DNS_SKRBUNDLE_VALID(bundle));
/* Remove existing DNSKEY, CDS, and CDNSKEY records. */
remove_rdataset(zone, diff, dnskeyset);
remove_rdataset(zone, diff, cdsset);
remove_rdataset(zone, diff, cdnskeyset);
/* Add the records from the bundle. */
dns_difftuple_t *tuple = ISC_LIST_HEAD(bundle->diff.tuples);
while (tuple != NULL) {
switch (tuple->rdata.type) {
case dns_rdatatype_dnskey:
add_tuple(diff, tuple);
break;
case dns_rdatatype_cdnskey:
case dns_rdatatype_cds:
add_tuple(diff, tuple);
break;
case dns_rdatatype_rrsig:
/* Not interested in right now */
break;
default:
INSIST(0);
}
tuple = ISC_LIST_NEXT(tuple, link);
}
}
static void
zone_rekey(dns_zone_t *zone) {
isc_result_t result;
@ -21885,10 +22041,13 @@ zone_rekey(dns_zone_t *zone) {
dns_dnsseckey_t *key = NULL;
dns_diff_t diff, _sig_diff;
dns_kasp_t *kasp;
dns_skrbundle_t *bundle = NULL;
dns__zonediff_t zonediff;
bool commit = false, newactive = false;
bool newalg = false;
bool fullsign;
bool offlineksk = false;
uint32_t sigval = 0;
dns_ttl_t ttl = 3600;
const char *dir = NULL;
isc_mem_t *mctx = NULL;
@ -21931,14 +22090,13 @@ zone_rekey(dns_zone_t *zone) {
ttl = soaset.ttl;
dns_rdataset_disassociate(&soaset);
/*
* Only update DNSKEY TTL if we have a policy.
*/
if (kasp != NULL) {
ttl = dns_kasp_dnskeyttl(kasp);
offlineksk = dns_kasp_offlineksk(kasp);
sigval = dns_kasp_sigvalidity_dnskey(kasp);
}
/* Get the DNSKEY rdataset */
/* Get the current DNSKEY rdataset */
result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
dns_rdatatype_none, 0, &keyset, &keysigs);
if (result == ISC_R_SUCCESS) {
@ -21949,7 +22107,7 @@ zone_rekey(dns_zone_t *zone) {
*/
if (kasp == NULL) {
ttl = keyset.ttl;
} else if (ttl != keyset.ttl) {
} else if (ttl != keyset.ttl && !offlineksk) {
result = update_ttl(&keyset, &zone->origin, ttl, &diff);
if (result != ISC_R_SUCCESS) {
dnssec_log(zone, ISC_LOG_ERROR,
@ -21980,12 +22138,13 @@ zone_rekey(dns_zone_t *zone) {
goto failure;
}
/* Get the CDS rdataset */
/* Get the current CDS rdataset */
result = dns_db_findrdataset(db, node, ver, dns_rdatatype_cds,
dns_rdatatype_none, 0, &cdsset, NULL);
if (result != ISC_R_SUCCESS && dns_rdataset_isassociated(&cdsset)) {
dns_rdataset_disassociate(&cdsset);
} else if (result == ISC_R_SUCCESS && kasp != NULL && ttl != cdsset.ttl)
} else if (result == ISC_R_SUCCESS && kasp != NULL &&
ttl != cdsset.ttl && !offlineksk)
{
result = update_ttl(&cdsset, &zone->origin, ttl, &diff);
if (result != ISC_R_SUCCESS) {
@ -21999,13 +22158,13 @@ zone_rekey(dns_zone_t *zone) {
cdsset.ttl = ttl;
}
/* Get the CDNSKEY rdataset */
/* Get the current CDNSKEY rdataset */
result = dns_db_findrdataset(db, node, ver, dns_rdatatype_cdnskey,
dns_rdatatype_none, 0, &cdnskeyset, NULL);
if (result != ISC_R_SUCCESS && dns_rdataset_isassociated(&cdnskeyset)) {
dns_rdataset_disassociate(&cdnskeyset);
} else if (result == ISC_R_SUCCESS && kasp != NULL &&
ttl != cdnskeyset.ttl)
ttl != cdnskeyset.ttl && !offlineksk)
{
result = update_ttl(&cdnskeyset, &zone->origin, ttl, &diff);
if (result != ISC_R_SUCCESS) {
@ -22027,6 +22186,59 @@ zone_rekey(dns_zone_t *zone) {
*/
fullsign = DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_FULLSIGN);
if (offlineksk) {
/* Lookup the correct bundle in the SKR. */
LOCK_ZONE(zone);
if (zone->skr == NULL) {
UNLOCK_ZONE(zone);
dnssec_log(zone, ISC_LOG_DEBUG(1),
"zone_rekey:dns_skr_lookup failed: "
"no SKR available");
result = DNS_R_NOSKRFILE;
goto failure;
}
bundle = dns_skr_lookup(zone->skr, now, sigval);
zone->skrbundle = bundle;
UNLOCK_ZONE(zone);
if (bundle == NULL) {
char nowstr[26]; /* Minimal buf per ctime_r() spec. */
char utc[sizeof("YYYYMMDDHHSSMM")];
isc_buffer_t b;
isc_region_t r;
isc_buffer_init(&b, utc, sizeof(utc));
isc_stdtime_tostring(now, nowstr, sizeof(nowstr));
(void)dns_time32_totext(now, &b);
isc_buffer_usedregion(&b, &r);
dnssec_log(zone, ISC_LOG_DEBUG(1),
"zone_rekey:dns_skr_lookup failed: "
"no available SKR bundle for time "
"%.*s (%s)",
(int)r.length, r.base, nowstr);
result = DNS_R_NOSKRBUNDLE;
goto failure;
}
zone_apply_skrbundle(zone, bundle, &keyset, &cdsset,
&cdnskeyset, &diff);
dns_skrbundle_t *next = ISC_LIST_NEXT(bundle, link);
if (next != NULL) {
if (nexttime == 0) {
nexttime = next->inception;
}
} else {
dnssec_log(zone, ISC_LOG_WARNING,
"zone_rekey: last bundle in skr, please "
"import new skr file");
}
}
/*
* DNSSEC Key and Signing Policy
*/
KASP_LOCK(kasp);
dns_zone_lock_keyfiles(zone);
@ -22040,7 +22252,7 @@ zone_rekey(dns_zone_t *zone) {
isc_result_totext(result));
}
if (kasp != NULL) {
if (kasp != NULL && !offlineksk) {
/*
* Check DS at parental agents. Clear ongoing checks.
*/
@ -22080,6 +22292,15 @@ zone_rekey(dns_zone_t *zone) {
goto failure;
}
}
} else if (offlineksk) {
/*
* With offline-ksk enabled we don't run the keymgr.
* Instead we derive the states from the timing metadata.
*/
dns_zone_lock_keyfiles(zone);
result = dns_keymgr_offline(&zone->origin, &keys, kasp, now,
&nexttime);
dns_zone_unlock_keyfiles(zone);
}
KASP_UNLOCK(kasp);
@ -22098,6 +22319,25 @@ zone_rekey(dns_zone_t *zone) {
bool sane_diff, sane_dnskey;
isc_stdtime_t when;
result = dns_dnssec_updatekeys(&dnskeys, &keys, &rmkeys,
&zone->origin, ttl, &diff, mctx,
dnssec_report);
/*
* Keys couldn't be updated for some reason;
* try again later.
*/
if (result != ISC_R_SUCCESS) {
dnssec_log(zone, ISC_LOG_ERROR,
"zone_rekey:couldn't update zone keys: %s",
isc_result_totext(result));
goto failure;
}
if (offlineksk) {
/* We can skip a lot of things */
goto post_sync;
}
/*
* Publish CDS/CDNSKEY DELETE records if the zone is
* transitioning from secure to insecure.
@ -22163,20 +22403,6 @@ zone_rekey(dns_zone_t *zone) {
digests = dns_kasp_digests(zone->defaultkasp);
}
result = dns_dnssec_updatekeys(&dnskeys, &keys, &rmkeys,
&zone->origin, ttl, &diff, mctx,
dnssec_report);
/*
* Keys couldn't be updated for some reason;
* try again later.
*/
if (result != ISC_R_SUCCESS) {
dnssec_log(zone, ISC_LOG_ERROR,
"zone_rekey:couldn't update zone keys: %s",
isc_result_totext(result));
goto failure;
}
/*
* Update CDS / CDNSKEY records.
*/
@ -22229,6 +22455,7 @@ zone_rekey(dns_zone_t *zone) {
goto failure;
}
post_sync:
/*
* See if any pre-existing keys have newly become active;
* also, see if any new key is for a new algorithm, as in that
@ -24229,3 +24456,26 @@ dns_zone_makedb(dns_zone_t *zone, dns_db_t **dbp) {
return (ISC_R_SUCCESS);
}
isc_result_t
dns_zone_import_skr(dns_zone_t *zone, const char *file) {
dns_skr_t *skr = NULL;
isc_result_t result;
REQUIRE(DNS_ZONE_VALID(zone));
REQUIRE(zone->kasp != NULL);
REQUIRE(file != NULL);
dns_skr_create(zone->mctx, file, &zone->origin, zone->rdclass, &skr);
CHECK(dns_skr_read(zone->mctx, file, &zone->origin, zone->rdclass,
dns_kasp_dnskeyttl(zone->kasp), &skr));
dns_zone_setskr(zone, skr);
dnssec_log(zone, ISC_LOG_DEBUG(1), "imported skr file %s", file);
failure:
dns_skr_detach(&skr);
return (result);
}

View file

@ -226,6 +226,8 @@ typedef enum isc_result {
DNS_R_HAVEPARMKEYS,
DNS_R_NOALPN,
DNS_R_NODOHPATH,
DNS_R_NOSKRFILE,
DNS_R_NOSKRBUNDLE,
DST_R_UNSUPPORTEDALG,
DST_R_CRYPTOFAILURE,

View file

@ -225,6 +225,8 @@ static const char *description[ISC_R_NRESULTS] = {
[DNS_R_HAVEPARMKEYS] = "unexpected service parameter keys",
[DNS_R_NOALPN] = "no ALPN",
[DNS_R_NODOHPATH] = "no DOHPATH",
[DNS_R_NOSKRFILE] = "no SKR file",
[DNS_R_NOSKRBUNDLE] = "no available SKR bundle",
[DST_R_UNSUPPORTEDALG] = "algorithm is unsupported",
[DST_R_CRYPTOFAILURE] = "crypto failure",
@ -477,6 +479,8 @@ static const char *identifier[ISC_R_NRESULTS] = {
[DNS_R_HAVEPARMKEYS] = "DNS_R_HAVEPARMKEYS",
[DNS_R_NOALPN] = "DNS_R_NOALPN",
[DNS_R_NODOHPATH] = "DNS_R_NODOHPATH",
[DNS_R_NOSKRFILE] = "DNS_R_NOSKRFILE",
[DNS_R_NOSKRBUNDLE] = "DNS_R_NOSKRBUNDLE",
[DST_R_UNSUPPORTEDALG] = "DST_R_UNSUPPORTEDALG",
[DST_R_CRYPTOFAILURE] = "DST_R_CRYPTOFAILURE",

View file

@ -113,7 +113,7 @@ get_string(const cfg_obj_t **maps, const char *option) {
static isc_result_t
cfg_kaspkey_fromconfig(const cfg_obj_t *config, dns_kasp_t *kasp,
bool check_algorithms, isc_log_t *logctx,
dns_keystorelist_t *keystorelist,
bool offline_ksk, dns_keystorelist_t *keystorelist,
uint32_t ksk_min_lifetime, uint32_t zsk_min_lifetime) {
isc_result_t result;
dns_kasp_key_t *key = NULL;
@ -126,6 +126,7 @@ cfg_kaspkey_fromconfig(const cfg_obj_t *config, dns_kasp_t *kasp,
if (config == NULL) {
/* We are creating a key reference for the default kasp. */
INSIST(!offline_ksk);
key->role |= DNS_KASP_KEY_ROLE_KSK | DNS_KASP_KEY_ROLE_ZSK;
key->lifetime = 0; /* unlimited */
key->algorithm = DNS_KEYALG_ECDSA256;
@ -149,6 +150,14 @@ cfg_kaspkey_fromconfig(const cfg_obj_t *config, dns_kasp_t *kasp,
} else if (strcmp(rolestr, "zsk") == 0) {
key->role |= DNS_KASP_KEY_ROLE_ZSK;
} else if (strcmp(rolestr, "csk") == 0) {
if (offline_ksk) {
cfg_obj_log(
config, logctx, ISC_LOG_ERROR,
"dnssec-policy: csk keys are not "
"allowed when offline-ksk is enabled");
result = ISC_R_FAILURE;
goto cleanup;
}
key->role |= DNS_KASP_KEY_ROLE_KSK;
key->role |= DNS_KASP_KEY_ROLE_ZSK;
}
@ -418,6 +427,7 @@ cfg_kasp_fromconfig(const cfg_obj_t *config, dns_kasp_t *default_kasp,
uint32_t zonepropdelay = 0, parentpropdelay = 0;
uint32_t ipub = 0, iret = 0;
uint32_t ksk_min_lifetime = 0, zsk_min_lifetime = 0;
bool offline_ksk = false;
REQUIRE(config != NULL);
REQUIRE(kaspp != NULL && *kaspp == NULL);
@ -539,6 +549,13 @@ cfg_kasp_fromconfig(const cfg_obj_t *config, dns_kasp_t *default_kasp,
dns_kasp_setparentpropagationdelay(kasp, parentpropdelay);
/* Configuration: Keys */
obj = NULL;
(void)confget(maps, "offline-ksk", &obj);
if (obj != NULL) {
offline_ksk = cfg_obj_asboolean(obj);
}
dns_kasp_setofflineksk(kasp, offline_ksk);
obj = NULL;
(void)confget(maps, "cdnskey", &obj);
if (obj != NULL) {
@ -596,7 +613,7 @@ cfg_kasp_fromconfig(const cfg_obj_t *config, dns_kasp_t *default_kasp,
cfg_obj_t *kobj = cfg_listelt_value(element);
result = cfg_kaspkey_fromconfig(
kobj, kasp, check_algorithms, logctx,
keystorelist, ksk_min_lifetime,
offline_ksk, keystorelist, ksk_min_lifetime,
zsk_min_lifetime);
if (result != ISC_R_SUCCESS) {
cfg_obj_log(kobj, logctx, ISC_LOG_ERROR,

View file

@ -2278,6 +2278,7 @@ static cfg_clausedef_t dnssecpolicy_clauses[] = {
{ "keys", &cfg_type_kaspkeys, 0 },
{ "max-zone-ttl", &cfg_type_duration, 0 },
{ "nsec3param", &cfg_type_nsec3, 0 },
{ "offline-ksk", &cfg_type_boolean, 0 },
{ "parent-ds-ttl", &cfg_type_duration, 0 },
{ "parent-propagation-delay", &cfg_type_duration, 0 },
{ "parent-registration-delay", &cfg_type_duration,

View file

@ -44,6 +44,7 @@ check_PROGRAMS = \
resolver_test \
rsa_test \
sigs_test \
skr_test \
time_test \
tsig_test \
update_test \

502
tests/dns/skr_test.c Normal file
View file

@ -0,0 +1,502 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* SPDX-License-Identifier: MPL-2.0
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
#include <inttypes.h>
#include <sched.h> /* IWYU pragma: keep */
#include <setjmp.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define UNIT_TESTING
#include <cmocka.h>
#include <isc/file.h>
#include <isc/hex.h>
#include <isc/lex.h>
#include <isc/result.h>
#include <isc/stdio.h>
#include <isc/string.h>
#include <isc/util.h>
#include <dns/dnssec.h>
#include <dns/name.h>
#include <dns/rdatalist.h>
#include <dns/rdataset.h>
#include <dns/secalg.h>
#include <dns/skr.h>
#include <dns/time.h>
#include "zone_p.h"
#include <tests/dns.h>
typedef struct {
isc_stdtime_t btime;
isc_stdtime_t inception;
isc_stdtime_t expiration;
char kskbuf[1024];
dns_rdata_t ksk;
char zsk1buf[1024];
dns_rdata_t zsk1;
char zsk2buf[1024];
dns_rdata_t zsk2;
char cdnskeybuf[1024];
dns_rdata_t cdnskey;
char cdsbuf[1024];
dns_rdata_t cds;
char rrsig1buf[1024];
dns_rdata_t dnskey_rrsig;
char rrsig2buf[1024];
dns_rdata_t cdnskey_rrsig;
char rrsig3buf[1024];
dns_rdata_t cds_rrsig;
} skr__testbundle_t;
static skr__testbundle_t test_bundles[42];
static dns_dnsseckeylist_t keys;
static const char *file = TESTS_DIR "/testdata/skr/test.skr";
static const char *kskstr =
"257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm "
"McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==";
static const char *zsk1str =
"256 3 13 GIyBcxr9uBJvybXw2eOeZ1nWjRd+0INxUPlKaWI1KQxJwWRJTOJMw33g "
"SSCz++TBmKyXm5ghl+56vOkoO33ppg==";
static const char *zsk2str =
"256 3 13 1oC9YpShKeL5HQnYIMX7y77b9qbnAsKIjVuU0AUoo2kTA1D2fXxB9W95 "
"+uqIiJuiteHK/oGmeDy4UsiTd2W1DQ==";
static const char *cdsstr =
"52433 13 2 90C4668A53D8BE06049BABD2DFC93F4C6B46C9055E20D91166381E22 "
"11BD9615";
static dns_name_t *dname = NULL;
#define BUNDLE_HAS_ZSK1 10
#define BUNDLE_HAS_ZSK2 20
#define OFFSET 3600
#define TTL 3600
#define LIFETIME 864000
#define SIG_FORMATSIZE \
(DNS_NAME_FORMATSIZE + DNS_SECALG_FORMATSIZE + sizeof("65535"))
static void
print_rdata(FILE *fp, dns_rdata_t *rdata) {
dns_rdataset_t rrset = DNS_RDATASET_INIT;
dns_rdatalist_t *rdatalist = isc_mem_get(mctx, sizeof(*rdatalist));
dns_rdatalist_init(rdatalist);
rdatalist->rdclass = dns_rdataclass_in;
rdatalist->type = rdata->type;
rdatalist->ttl = TTL;
ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
dns_rdatalist_tordataset(rdatalist, &rrset);
isc_buffer_t target;
isc_region_t r;
isc_result_t ret;
char buf[4096];
isc_buffer_init(&target, buf, sizeof(buf));
ret = dns_rdataset_totext(&rrset, dname, false, false, &target);
assert_int_equal(ret, ISC_R_SUCCESS);
isc_buffer_usedregion(&target, &r);
fprintf(fp, "%.*s", (int)r.length, (char *)r.base);
for (dns_rdata_t *rd = ISC_LIST_HEAD(rdatalist->rdata); rd != NULL;
rd = ISC_LIST_HEAD(rdatalist->rdata))
{
ISC_LIST_UNLINK(rdatalist->rdata, rdata, link);
}
isc_mem_put(mctx, rdatalist, sizeof(*rdatalist));
}
static void
sign_rrset(FILE *fp, isc_stdtime_t inception, isc_stdtime_t expiration,
dns_rdataset_t *rrset, char *target_mem, dns_rdata_t *rrsig) {
dns_dnsseckey_t *ksk = ISC_LIST_HEAD(keys);
isc_stdtime_t clockskew = inception - OFFSET;
isc_result_t ret;
isc_buffer_t target;
isc_buffer_init(&target, target_mem, 1024);
ret = dns_dnssec_sign(dname, rrset, ksk->key, &clockskew, &expiration,
mctx, &target, rrsig);
assert_int_equal(ret, ISC_R_SUCCESS);
print_rdata(fp, rrsig);
}
static void
write_record(FILE *fp, dns_rdatatype_t rdtype, const char *rdatastr,
char *target_mem, dns_rdata_t *rdata) {
isc_buffer_t source, target;
isc_lex_t *lex = NULL;
isc_lexspecials_t specials = { 0 };
isc_result_t ret;
/* Set up source to hold the input string. */
isc_buffer_init(&target, target_mem, 1024);
isc_buffer_constinit(&source, rdatastr, strlen(rdatastr));
isc_buffer_add(&source, strlen(rdatastr));
/* Create a lexer as one is required by dns_rdata_fromtext(). */
isc_lex_create(mctx, 64, &lex);
specials[0] = 1;
specials['('] = 1;
specials[')'] = 1;
specials['"'] = 1;
isc_lex_setspecials(lex, specials);
isc_lex_setcomments(lex, ISC_LEXCOMMENT_DNSMASTERFILE);
ret = isc_lex_openbuffer(lex, &source);
assert_int_equal(ret, ISC_R_SUCCESS);
ret = dns_rdata_fromtext(rdata, dns_rdataclass_in, rdtype, lex, dname,
0, mctx, &target, NULL);
assert_int_equal(ret, ISC_R_SUCCESS);
print_rdata(fp, rdata);
isc_lex_destroy(&lex);
}
static void
create_bundle(FILE *fp, isc_stdtime_t btime, int bnum) {
char timestr[26]; /* Minimal buf as per ctime_r() spec. */
char utc[sizeof("YYYYMMDDHHSSMM")];
dns_rdatalist_t *dnskeylist, *cdnskeylist, *cdslist;
dns_rdataset_t *dnskeyset = NULL;
dns_rdataset_t *cdnskeyset = NULL;
dns_rdataset_t *cdsset = NULL;
isc_buffer_t b, timebuf;
isc_region_t r;
isc_result_t ret;
/* Write header to file. */
test_bundles[bnum].btime = btime;
isc_buffer_init(&timebuf, timestr, sizeof(timestr));
isc_stdtime_tostring(btime, timestr, sizeof(timestr));
isc_buffer_init(&b, utc, sizeof(utc));
ret = dns_time32_totext(btime, &b);
assert_int_equal(ret, ISC_R_SUCCESS);
isc_buffer_usedregion(&b, &r);
fprintf(fp, ";; SignedKeyResponse 1.0 %.*s (%s)\n", (int)r.length,
r.base, timestr);
/* Write records to file. */
dns_rdata_init(&test_bundles[bnum].ksk);
write_record(fp, dns_rdatatype_dnskey, kskstr,
test_bundles[bnum].kskbuf, &test_bundles[bnum].ksk);
if (bnum < BUNDLE_HAS_ZSK2) {
dns_rdata_init(&test_bundles[bnum].zsk1);
write_record(fp, dns_rdatatype_dnskey, zsk1str,
test_bundles[bnum].zsk1buf,
&test_bundles[bnum].zsk1);
}
if (bnum > BUNDLE_HAS_ZSK1) {
dns_rdata_init(&test_bundles[bnum].zsk2);
write_record(fp, dns_rdatatype_dnskey, zsk2str,
test_bundles[bnum].zsk2buf,
&test_bundles[bnum].zsk2);
}
/* Create the DNSKEY signature. */
dnskeylist = isc_mem_get(mctx, sizeof(*dnskeylist));
dnskeyset = isc_mem_get(mctx, sizeof(*dnskeyset));
dns_rdatalist_init(dnskeylist);
dns_rdataset_init(dnskeyset);
dnskeylist->rdclass = dns_rdataclass_in;
dnskeylist->type = dns_rdatatype_dnskey;
dnskeylist->ttl = TTL;
ISC_LIST_APPEND(dnskeylist->rdata, &test_bundles[bnum].ksk, link);
dns_rdatalist_tordataset(dnskeylist, dnskeyset);
dns_rdata_init(&test_bundles[bnum].dnskey_rrsig);
sign_rrset(fp, btime, (btime + LIFETIME), dnskeyset,
test_bundles[bnum].rrsig1buf,
&test_bundles[bnum].dnskey_rrsig);
for (dns_rdata_t *rd = ISC_LIST_HEAD(dnskeylist->rdata); rd != NULL;
rd = ISC_LIST_HEAD(dnskeylist->rdata))
{
ISC_LIST_UNLINK(dnskeylist->rdata, rd, link);
}
isc_mem_put(mctx, dnskeylist, sizeof(*dnskeylist));
isc_mem_put(mctx, dnskeyset, sizeof(*dnskeyset));
/* CDNSKEY */
dns_rdata_init(&test_bundles[bnum].cdnskey);
write_record(fp, dns_rdatatype_cdnskey, kskstr,
test_bundles[bnum].cdnskeybuf,
&test_bundles[bnum].cdnskey);
cdnskeylist = isc_mem_get(mctx, sizeof(*cdnskeylist));
cdnskeyset = isc_mem_get(mctx, sizeof(*cdnskeyset));
dns_rdatalist_init(cdnskeylist);
dns_rdataset_init(cdnskeyset);
cdnskeylist->rdclass = dns_rdataclass_in;
cdnskeylist->type = dns_rdatatype_cdnskey;
cdnskeylist->ttl = TTL;
ISC_LIST_APPEND(cdnskeylist->rdata, &test_bundles[bnum].cdnskey, link);
dns_rdatalist_tordataset(cdnskeylist, cdnskeyset);
dns_rdata_init(&test_bundles[bnum].cdnskey_rrsig);
sign_rrset(fp, btime, (btime + LIFETIME), cdnskeyset,
test_bundles[bnum].rrsig2buf,
&test_bundles[bnum].cdnskey_rrsig);
for (dns_rdata_t *rd = ISC_LIST_HEAD(cdnskeylist->rdata); rd != NULL;
rd = ISC_LIST_HEAD(cdnskeylist->rdata))
{
ISC_LIST_UNLINK(cdnskeylist->rdata, rd, link);
}
isc_mem_put(mctx, cdnskeylist, sizeof(*cdnskeylist));
isc_mem_put(mctx, cdnskeyset, sizeof(*cdnskeyset));
/* CDS */
dns_rdata_init(&test_bundles[bnum].cds);
write_record(fp, dns_rdatatype_cds, cdsstr, test_bundles[bnum].cdsbuf,
&test_bundles[bnum].cds);
cdslist = isc_mem_get(mctx, sizeof(*cdslist));
cdsset = isc_mem_get(mctx, sizeof(*cdsset));
dns_rdatalist_init(cdslist);
dns_rdataset_init(cdsset);
cdslist->rdclass = dns_rdataclass_in;
cdslist->type = dns_rdatatype_cds;
cdslist->ttl = TTL;
ISC_LIST_APPEND(cdslist->rdata, &test_bundles[bnum].cds, link);
dns_rdatalist_tordataset(cdslist, cdsset);
dns_rdata_init(&test_bundles[bnum].cds_rrsig);
sign_rrset(fp, btime, (btime + LIFETIME), cdsset,
test_bundles[bnum].rrsig3buf, &test_bundles[bnum].cds_rrsig);
for (dns_rdata_t *rd = ISC_LIST_HEAD(cdslist->rdata); rd != NULL;
rd = ISC_LIST_HEAD(cdslist->rdata))
{
ISC_LIST_UNLINK(cdslist->rdata, rd, link);
}
isc_mem_put(mctx, cdslist, sizeof(*cdslist));
isc_mem_put(mctx, cdsset, sizeof(*cdsset));
/* Signature times. */
test_bundles[bnum].btime = btime;
test_bundles[bnum].inception = (btime - OFFSET);
test_bundles[bnum].expiration = (btime + LIFETIME);
}
static void
check_rrsig(dns_skrbundle_t *bundle, skr__testbundle_t *tb,
dns_rdatatype_t rrtype, isc_result_t ret) {
isc_result_t r;
dns_dnsseckey_t *key = ISC_LIST_HEAD(keys);
dns_rdata_t sigrdata = DNS_RDATA_INIT;
r = dns_skrbundle_getsig(bundle, key->key, rrtype, &sigrdata);
assert_int_equal(r, ret);
if (r == ISC_R_SUCCESS) {
int cmp = 1;
dns_rdata_rrsig_t sig;
switch (rrtype) {
case dns_rdatatype_dnskey:
cmp = dns_rdata_compare(&sigrdata, &tb->dnskey_rrsig);
break;
case dns_rdatatype_cdnskey:
cmp = dns_rdata_compare(&sigrdata, &tb->cdnskey_rrsig);
break;
case dns_rdatatype_cds:
cmp = dns_rdata_compare(&sigrdata, &tb->cds_rrsig);
break;
default:
cmp = 1;
}
assert_int_equal(cmp, 0);
r = dns_rdata_tostruct(&sigrdata, &sig, NULL);
assert_int_equal(r, ISC_R_SUCCESS);
assert_int_equal(sig.timesigned, tb->inception);
assert_int_equal(sig.timeexpire, tb->expiration);
}
}
static void
check_bundle(dns_skrbundle_t *bundle, skr__testbundle_t *tb, int bnum) {
int dnskey = 0;
assert_int_equal(bundle->inception, tb->btime);
dns_difftuple_t *tuple = ISC_LIST_HEAD(bundle->diff.tuples);
while (tuple != NULL) {
int cmp = 1;
switch (tuple->rdata.type) {
case dns_rdatatype_dnskey:
switch (dnskey) {
case 0:
cmp = dns_rdata_compare(&tuple->rdata,
&tb->ksk);
break;
case 1:
if (bnum < BUNDLE_HAS_ZSK2) {
cmp = dns_rdata_compare(&tuple->rdata,
&tb->zsk1);
} else {
cmp = dns_rdata_compare(&tuple->rdata,
&tb->zsk2);
}
break;
case 2:
cmp = dns_rdata_compare(&tuple->rdata,
&tb->zsk2);
break;
default:
cmp = 1;
}
dnskey++;
break;
case dns_rdatatype_cdnskey:
cmp = dns_rdata_compare(&tuple->rdata, &tb->cdnskey);
break;
case dns_rdatatype_cds:
cmp = dns_rdata_compare(&tuple->rdata, &tb->cds);
break;
case dns_rdatatype_rrsig:
cmp = 0;
break;
default:
cmp = 1;
}
assert_int_equal(cmp, 0);
tuple = ISC_LIST_NEXT(tuple, link);
}
check_rrsig(bundle, tb, dns_rdatatype_dnskey, ISC_R_SUCCESS);
check_rrsig(bundle, tb, dns_rdatatype_cdnskey, ISC_R_SUCCESS);
check_rrsig(bundle, tb, dns_rdatatype_cds, ISC_R_SUCCESS);
check_rrsig(bundle, tb, dns_rdatatype_a, ISC_R_NOTFOUND);
}
static void
create_skr_file(void) {
isc_result_t ret;
isc_stdtime_t start_time;
size_t tempfilelen;
char *tempfile = NULL;
FILE *outfp = NULL;
/* Set up output file */
tempfilelen = strlen(TESTS_DIR "/testdata/skr/") + 20;
tempfile = isc_mem_get(mctx, tempfilelen);
ret = isc_file_mktemplate(file, tempfile, tempfilelen);
assert_int_equal(ret, ISC_R_SUCCESS);
ret = isc_file_openunique(tempfile, &outfp);
assert_int_equal(ret, ISC_R_SUCCESS);
start_time = isc_stdtime_now();
for (int i = 0; i < 42; i++) {
create_bundle(outfp, start_time, i);
start_time += LIFETIME;
}
fprintf(outfp, ";; SignedKeyResponse 1.0 generated by test-dev\n");
ret = isc_stdio_close(outfp);
assert_int_equal(ret, ISC_R_SUCCESS);
ret = isc_file_rename(tempfile, file);
assert_int_equal(ret, ISC_R_SUCCESS);
isc_file_remove(tempfile);
isc_mem_put(mctx, tempfile, tempfilelen);
}
ISC_RUN_TEST_IMPL(skr_read) {
char *name = UNCONST("test");
dns_fixedname_t dfname;
dns_skr_t *skr = NULL;
isc_buffer_t b;
isc_result_t result;
size_t count = 0;
dst_lib_init(mctx, NULL);
/* Owner name */
dname = dns_fixedname_initname(&dfname);
isc_buffer_init(&b, name, strlen(name));
isc_buffer_add(&b, strlen(name));
result = dns_name_fromtext(dname, &b, dns_rootname, 0, NULL);
assert_int_equal(result, ISC_R_SUCCESS);
/* Get the KSK */
ISC_LIST_INIT(keys);
result = dns_dnssec_findmatchingkeys(
dname, NULL, TESTS_DIR "/testdata/skr/", NULL, 0, mctx, &keys);
assert_int_equal(result, ISC_R_SUCCESS);
/* Create/read the SKR file */
create_skr_file();
dns_skr_create(mctx, file, dname, dns_rdataclass_in, &skr);
result = dns_skr_read(mctx, file, dname, dns_rdataclass_in, TTL, &skr);
assert_int_equal(result, ISC_R_SUCCESS);
/* Test bundles */
for (dns_skrbundle_t *bundle = ISC_LIST_HEAD(skr->bundles);
bundle != NULL; bundle = ISC_LIST_NEXT(bundle, link))
{
count++;
}
assert_int_equal(count, 42);
for (int i = 0; i < 42; i++) {
skr__testbundle_t tb = test_bundles[i];
dns_skrbundle_t *lb;
lb = dns_skr_lookup(skr, tb.btime, LIFETIME);
check_bundle(lb, &tb, i);
lb = dns_skr_lookup(skr, tb.btime + 1, LIFETIME);
check_bundle(lb, &tb, i);
}
/* Clean up */
dns_skr_destroy(skr);
while (!ISC_LIST_EMPTY(keys)) {
dns_dnsseckey_t *key = ISC_LIST_HEAD(keys);
ISC_LIST_UNLINK(keys, key, link);
dst_key_free(&key->key);
dns_dnsseckey_destroy(mctx, &key);
}
dst_lib_destroy();
}
ISC_TEST_LIST_START
ISC_TEST_ENTRY(skr_read)
ISC_TEST_LIST_END
ISC_TEST_MAIN

View file

@ -0,0 +1,5 @@
; This is a key-signing key, keyid 43204, for test.
; Created: 20240801135058 (Thu Aug 1 15:50:58 2024)
; Publish: 20240801135058 (Thu Aug 1 15:50:58 2024)
; Activate: 20240801135058 (Thu Aug 1 15:50:58 2024)
test. IN DNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==

View file

@ -0,0 +1,6 @@
Private-key-format: v1.3
Algorithm: 13 (ECDSAP256SHA256)
PrivateKey: 4N0l7eVTTy7Hvf/iaYen8nNmsMWClm56a1W6SFImF/4=
Created: 20240801135058
Publish: 20240801135058
Activate: 20240801135058

346
tests/dns/testdata/skr/test.skr vendored Normal file
View file

@ -0,0 +1,346 @@
;; SignedKeyResponse 1.0 20240813095451 (Tue Aug 13 11:54:51 2024)
test. 3600 IN DNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN DNSKEY 256 3 13 GIyBcxr9uBJvybXw2eOeZ1nWjRd+0INxUPlKaWI1KQxJwWRJTOJMw33g SSCz++TBmKyXm5ghl+56vOkoO33ppg==
test. 3600 IN RRSIG DNSKEY 13 1 3600 20240823095451 20240813085451 43204 test. v7TY2u81mFfOsL3b3kGk1vV+dUdOBbBb2YrIAvAJ6v9T7/wS2U4X8125 QuYPNo2OpQEvcNI//LZFjtFDiz1foQ==
test. 3600 IN CDNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN RRSIG CDNSKEY 13 1 3600 20240823095451 20240813085451 43204 test. zA/Ia+miTFmdriALov2J3SZftWJnpiTinyxuQr/2spkLt3aBG1ZgEr7V 25/8hW4vEYYBdP6CTbNClMWlh1FTGA==
test. 3600 IN CDS 52433 13 2 90C4668A53D8BE06049BABD2DFC93F4C6B46C9055E20D91166381E22 11BD9615
test. 3600 IN RRSIG CDS 13 1 3600 20240823095451 20240813085451 43204 test. 4JB80KVFz2ItklsP5uJeER0GhCL239JXQntqQzWcjXwpxMijFw5GIGSt m8ylKPtwwSjJQjH+sc4DNeZWLIX8Sg==
;; SignedKeyResponse 1.0 20240823095451 (Fri Aug 23 11:54:51 2024)
test. 3600 IN DNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN DNSKEY 256 3 13 GIyBcxr9uBJvybXw2eOeZ1nWjRd+0INxUPlKaWI1KQxJwWRJTOJMw33g SSCz++TBmKyXm5ghl+56vOkoO33ppg==
test. 3600 IN RRSIG DNSKEY 13 1 3600 20240902095451 20240823085451 43204 test. xHYiJck0EGGAZ1tE8+F+rpaxr/7WSeEg+CsOJwXUcgkzo9xZUB4bLsHF aXkNYHRnOMeIa3W7DgcfR8//ay4Jog==
test. 3600 IN CDNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN RRSIG CDNSKEY 13 1 3600 20240902095451 20240823085451 43204 test. xIX4zQFKDyNI9Fw38MQtTjYcbxPJ2xlfRhS8f1V/a+CaoyZh/hZTKHyG sCtx2YqkzoBXfQ3dq/W1PT+2oIFPYQ==
test. 3600 IN CDS 52433 13 2 90C4668A53D8BE06049BABD2DFC93F4C6B46C9055E20D91166381E22 11BD9615
test. 3600 IN RRSIG CDS 13 1 3600 20240902095451 20240823085451 43204 test. LIaV7hwaP+pjzxf7dMZh0OQwLcJdDJNBz2+uMj09azuhSyLyxZ9pmqv6 2b0yxuI5XmVK8i4+XL9zZR1Ardr25A==
;; SignedKeyResponse 1.0 20240902095451 (Mon Sep 2 11:54:51 2024)
test. 3600 IN DNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN DNSKEY 256 3 13 GIyBcxr9uBJvybXw2eOeZ1nWjRd+0INxUPlKaWI1KQxJwWRJTOJMw33g SSCz++TBmKyXm5ghl+56vOkoO33ppg==
test. 3600 IN RRSIG DNSKEY 13 1 3600 20240912095451 20240902085451 43204 test. MzXOtDe60W/FlCzEKVXD3A7PTOdpieUrVx5tJdNQfEC8HuxOtjd6+di/ 395u39pytPz1NSTbj2SRF4bb3r3uyw==
test. 3600 IN CDNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN RRSIG CDNSKEY 13 1 3600 20240912095451 20240902085451 43204 test. vKwQpP6FmsSB2acYqp+JBBPZcb8Yb9AokFADNAayoRCIK5nLrh8TEVi8 T1sIs/MXirQeVxGfgX1WOvE/KdVpzA==
test. 3600 IN CDS 52433 13 2 90C4668A53D8BE06049BABD2DFC93F4C6B46C9055E20D91166381E22 11BD9615
test. 3600 IN RRSIG CDS 13 1 3600 20240912095451 20240902085451 43204 test. hScttj4vrrHHL0GVRhAiTL/JpWdszbjkCAxlVaR8lw2gQAIoIxz3ib9O fswPmwwJARJzhgR7JSYYcupjGMBV/Q==
;; SignedKeyResponse 1.0 20240912095451 (Thu Sep 12 11:54:51 2024)
test. 3600 IN DNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN DNSKEY 256 3 13 GIyBcxr9uBJvybXw2eOeZ1nWjRd+0INxUPlKaWI1KQxJwWRJTOJMw33g SSCz++TBmKyXm5ghl+56vOkoO33ppg==
test. 3600 IN RRSIG DNSKEY 13 1 3600 20240922095451 20240912085451 43204 test. TgEEEXXaQ8b7u/aK6ir9vpuFP2i4V/hljtvJLVmle4Na4nbZKKeAa5Dy x72Tr9Uj5+1EK7KTqRp198AeuAs0Ew==
test. 3600 IN CDNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN RRSIG CDNSKEY 13 1 3600 20240922095451 20240912085451 43204 test. 4K3MilIylkthheSBb7iwjh5WxzmRyD3GssyZfCEVmvI6qEGP84zYDDo3 xfhExMsKhvSi+zKfIGFHXnJyVcuJGw==
test. 3600 IN CDS 52433 13 2 90C4668A53D8BE06049BABD2DFC93F4C6B46C9055E20D91166381E22 11BD9615
test. 3600 IN RRSIG CDS 13 1 3600 20240922095451 20240912085451 43204 test. nbe6dBGEhxly8y1au/7XILE05Mg71YvHOTRlh51grerMRvFAED2i3yBu /EL6exUB7RPhr6fPNSsRKOlrDzTuhA==
;; SignedKeyResponse 1.0 20240922095451 (Sun Sep 22 11:54:51 2024)
test. 3600 IN DNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN DNSKEY 256 3 13 GIyBcxr9uBJvybXw2eOeZ1nWjRd+0INxUPlKaWI1KQxJwWRJTOJMw33g SSCz++TBmKyXm5ghl+56vOkoO33ppg==
test. 3600 IN RRSIG DNSKEY 13 1 3600 20241002095451 20240922085451 43204 test. cwuV+Ahfwu8GpX8NaZeEvAPES0yYRtLeH5AnDNG8V+mWzW22hRblkz9i y4UrvmoqELYdOL6L0w+uJOiM3vtldA==
test. 3600 IN CDNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN RRSIG CDNSKEY 13 1 3600 20241002095451 20240922085451 43204 test. K5cfX1wA4PRBPgNLXxVht7UMOmw1j2p61LHjnD5V0OdgNkCZPDFyu9Xt uWhsjozW/D8PS+1jXacllhdqS0NTPg==
test. 3600 IN CDS 52433 13 2 90C4668A53D8BE06049BABD2DFC93F4C6B46C9055E20D91166381E22 11BD9615
test. 3600 IN RRSIG CDS 13 1 3600 20241002095451 20240922085451 43204 test. Ve7k2euF/Z3eIt0M4mxPmPkIr+Ckj0V1HMgoGAAZCTw70JTpvtHZ+nbt mm++Usq6okyUAR/H+TVxVc5ylfYhxg==
;; SignedKeyResponse 1.0 20241002095451 (Wed Oct 2 11:54:51 2024)
test. 3600 IN DNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN DNSKEY 256 3 13 GIyBcxr9uBJvybXw2eOeZ1nWjRd+0INxUPlKaWI1KQxJwWRJTOJMw33g SSCz++TBmKyXm5ghl+56vOkoO33ppg==
test. 3600 IN RRSIG DNSKEY 13 1 3600 20241012095451 20241002085451 43204 test. qgTlzcJ/tL5USUFkP77uMujV9uzz3klEZiALFemZ9tvMgzpDosFnC5cu CtsPaiT23ALJdXb7K2BMvDMHqEFtfA==
test. 3600 IN CDNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN RRSIG CDNSKEY 13 1 3600 20241012095451 20241002085451 43204 test. Sc0/YGe0MGsKvgH58F3Dlk8kkW8YMjJnV255tVLZZHx2QyO4US9BSPRS VkwcEN44g5Fb+dpRVUj7J+BHesGLzg==
test. 3600 IN CDS 52433 13 2 90C4668A53D8BE06049BABD2DFC93F4C6B46C9055E20D91166381E22 11BD9615
test. 3600 IN RRSIG CDS 13 1 3600 20241012095451 20241002085451 43204 test. 3+Jjb5VrWZ9LrAJADgnwXEnss9Vl1EONxJO1IHRu/y1iq1PsXmgoskvA Ix0/kl39JzebtGftBI7+Y7Z8H9XK0g==
;; SignedKeyResponse 1.0 20241012095451 (Sat Oct 12 11:54:51 2024)
test. 3600 IN DNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN DNSKEY 256 3 13 GIyBcxr9uBJvybXw2eOeZ1nWjRd+0INxUPlKaWI1KQxJwWRJTOJMw33g SSCz++TBmKyXm5ghl+56vOkoO33ppg==
test. 3600 IN RRSIG DNSKEY 13 1 3600 20241022095451 20241012085451 43204 test. E11HghozDLjvqBMyJzA6324Qo1A4KJxSN+2AuxygV7J6IUk3ijNG9/m4 fBwnZszdOqhuCCGa1HrixRFGrbgRsA==
test. 3600 IN CDNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN RRSIG CDNSKEY 13 1 3600 20241022095451 20241012085451 43204 test. V+sxVxzMzR9Z9DmIXVg8XrixIzyBGaffJyXyLTB8HaLrZxJAeKH7fdsi 3y4i382bqbU+AMPyeFNnwhjuHSyn+Q==
test. 3600 IN CDS 52433 13 2 90C4668A53D8BE06049BABD2DFC93F4C6B46C9055E20D91166381E22 11BD9615
test. 3600 IN RRSIG CDS 13 1 3600 20241022095451 20241012085451 43204 test. NMB8UFr7jOTGI0dIEV6Lb0VPhk9Lha9jRziwdrXWrRT7XEhYdkzA4kpb +dYx5vswckoB0rPYQBks+458ohVQFg==
;; SignedKeyResponse 1.0 20241022095451 (Tue Oct 22 11:54:51 2024)
test. 3600 IN DNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN DNSKEY 256 3 13 GIyBcxr9uBJvybXw2eOeZ1nWjRd+0INxUPlKaWI1KQxJwWRJTOJMw33g SSCz++TBmKyXm5ghl+56vOkoO33ppg==
test. 3600 IN RRSIG DNSKEY 13 1 3600 20241101095451 20241022085451 43204 test. VJEjw8rOHAaMZxZirR6IDOpuuQW9x8g9TGC9qJsQhZwFEpX+s4TbqxE3 IkbX7V9+ANPog2Q3iS2FmUavvzVLRg==
test. 3600 IN CDNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN RRSIG CDNSKEY 13 1 3600 20241101095451 20241022085451 43204 test. B0D814zbrUtY9zibEEChAb6uIk1ZpwBkMa+BQNd9u1/cTPaUoyG1WmvI lpE6t2zpnRifvhM2BTxd/F6Avyxacg==
test. 3600 IN CDS 52433 13 2 90C4668A53D8BE06049BABD2DFC93F4C6B46C9055E20D91166381E22 11BD9615
test. 3600 IN RRSIG CDS 13 1 3600 20241101095451 20241022085451 43204 test. RCiquNBaFs1tHhOohzrbmQI+QW2r17+BDNAXvGzfJChlcFg/jRFqH3/4 dIozLGn3s/x4iN5x/jNB7wxW4tzvlw==
;; SignedKeyResponse 1.0 20241101095451 (Fri Nov 1 10:54:51 2024)
test. 3600 IN DNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN DNSKEY 256 3 13 GIyBcxr9uBJvybXw2eOeZ1nWjRd+0INxUPlKaWI1KQxJwWRJTOJMw33g SSCz++TBmKyXm5ghl+56vOkoO33ppg==
test. 3600 IN RRSIG DNSKEY 13 1 3600 20241111095451 20241101085451 43204 test. UYh3eWJCznyIcXAcCpI+gZZmDsVgaMg/bR1AALmmHonGUgKbj5+AQjmG bRHfWlX3lAubQxf5d7vFV+vUbmTbag==
test. 3600 IN CDNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN RRSIG CDNSKEY 13 1 3600 20241111095451 20241101085451 43204 test. ikGo7G+hguJTqtxwfn1Ay+Lvv22hoK8RrVLCuj5m6ZrFFcZ8kHJaPKnZ wxAlR0e2pmcjry/yzHZcWSJ1DbQP4w==
test. 3600 IN CDS 52433 13 2 90C4668A53D8BE06049BABD2DFC93F4C6B46C9055E20D91166381E22 11BD9615
test. 3600 IN RRSIG CDS 13 1 3600 20241111095451 20241101085451 43204 test. tgTEKbwAKKL2lIM1TMZBwpb+fFwLlIEQJnqLpV0YfmVH9iUjSF3H+96u aBnnLv/RwyiSaWfqy8xqQVzpr7nGCA==
;; SignedKeyResponse 1.0 20241111095451 (Mon Nov 11 10:54:51 2024)
test. 3600 IN DNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN DNSKEY 256 3 13 GIyBcxr9uBJvybXw2eOeZ1nWjRd+0INxUPlKaWI1KQxJwWRJTOJMw33g SSCz++TBmKyXm5ghl+56vOkoO33ppg==
test. 3600 IN RRSIG DNSKEY 13 1 3600 20241121095451 20241111085451 43204 test. EjOS5+otlVxYVyQ+bQSDQEIqP5h+PXPrshCWG++tFfwO0JeqDRGbm9Xe vz+PzUjlD8gckfgiNsTOgVBCOupYTg==
test. 3600 IN CDNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN RRSIG CDNSKEY 13 1 3600 20241121095451 20241111085451 43204 test. Fc1Yj6wyn6axYYJ4GHTL48uOc+jtiyq38lrzmPeaACHShWSj6U4vLoW8 /7Ufh5lgG/ljQpFzVmsQKocB0lpIHg==
test. 3600 IN CDS 52433 13 2 90C4668A53D8BE06049BABD2DFC93F4C6B46C9055E20D91166381E22 11BD9615
test. 3600 IN RRSIG CDS 13 1 3600 20241121095451 20241111085451 43204 test. PQfJpveN3My6L65TN7xTtSmGowrnARlg5cWdUxhBeaNRAbaw6KzR4xp5 N7ZWXdz/qZ99IGvkBodd20XI8n9Njg==
;; SignedKeyResponse 1.0 20241121095451 (Thu Nov 21 10:54:51 2024)
test. 3600 IN DNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN DNSKEY 256 3 13 GIyBcxr9uBJvybXw2eOeZ1nWjRd+0INxUPlKaWI1KQxJwWRJTOJMw33g SSCz++TBmKyXm5ghl+56vOkoO33ppg==
test. 3600 IN RRSIG DNSKEY 13 1 3600 20241201095451 20241121085451 43204 test. +tQvobdw5fSTk3BgQcFkdJbVdBLD4PjhTGgpgosRbqGJke46WBHoDz/9 VVBcZkdTljrFtZzVojqa/8KMEZv/+w==
test. 3600 IN CDNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN RRSIG CDNSKEY 13 1 3600 20241201095451 20241121085451 43204 test. kqvofyE61YUxKBUkhY1dt27RYFj3i196Fv7tSwz8Xrib3UtC3yF1n+bL gJqh24d73D7azboQWf7a85HQkL62Dg==
test. 3600 IN CDS 52433 13 2 90C4668A53D8BE06049BABD2DFC93F4C6B46C9055E20D91166381E22 11BD9615
test. 3600 IN RRSIG CDS 13 1 3600 20241201095451 20241121085451 43204 test. Ef2VNywQAic7JdPuV+bF3m8iuVT70j6DH2JOQDFSJbh3+6WrILKm7Ahs lfznCp7/sTMX8uBJfuCxmfHxukZW/g==
;; SignedKeyResponse 1.0 20241201095451 (Sun Dec 1 10:54:51 2024)
test. 3600 IN DNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN DNSKEY 256 3 13 GIyBcxr9uBJvybXw2eOeZ1nWjRd+0INxUPlKaWI1KQxJwWRJTOJMw33g SSCz++TBmKyXm5ghl+56vOkoO33ppg==
test. 3600 IN DNSKEY 256 3 13 1oC9YpShKeL5HQnYIMX7y77b9qbnAsKIjVuU0AUoo2kTA1D2fXxB9W95 +uqIiJuiteHK/oGmeDy4UsiTd2W1DQ==
test. 3600 IN RRSIG DNSKEY 13 1 3600 20241211095451 20241201085451 43204 test. krQOJGDOsKzmr2GLPj2+vLs5L8qcbQivdYJcu2Zrj9ZvR+faoyejdXm/ HCz0U3s25WffuMelEqwyuSXoipt8eA==
test. 3600 IN CDNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN RRSIG CDNSKEY 13 1 3600 20241211095451 20241201085451 43204 test. S5hbsWVhecF5lqKzFHUA5MFxv0hIIOunlRw5+6SX2EUgogE0qFvK4biZ 9viHxRJxEDBkwdtazsCDOZvz3lfkTw==
test. 3600 IN CDS 52433 13 2 90C4668A53D8BE06049BABD2DFC93F4C6B46C9055E20D91166381E22 11BD9615
test. 3600 IN RRSIG CDS 13 1 3600 20241211095451 20241201085451 43204 test. 7KtZao11Rr0evvQOaaqYKQTr23TMZhM1cNcsd+KRC65aldwP7iGiryVj eDQseXDz6yt1QAqJJGCMzcD83hBcWA==
;; SignedKeyResponse 1.0 20241211095451 (Wed Dec 11 10:54:51 2024)
test. 3600 IN DNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN DNSKEY 256 3 13 GIyBcxr9uBJvybXw2eOeZ1nWjRd+0INxUPlKaWI1KQxJwWRJTOJMw33g SSCz++TBmKyXm5ghl+56vOkoO33ppg==
test. 3600 IN DNSKEY 256 3 13 1oC9YpShKeL5HQnYIMX7y77b9qbnAsKIjVuU0AUoo2kTA1D2fXxB9W95 +uqIiJuiteHK/oGmeDy4UsiTd2W1DQ==
test. 3600 IN RRSIG DNSKEY 13 1 3600 20241221095451 20241211085451 43204 test. 3ne53jD1h6gGnwUx3tkM76EcO5kBQgjGCY2eU9wNiBw/6mUwZV6jadnT JCeMAyh5HvbwU67PMGT7riWvUs5sUQ==
test. 3600 IN CDNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN RRSIG CDNSKEY 13 1 3600 20241221095451 20241211085451 43204 test. m5W3TpPINxRynokN29pGjH85/3WZ6lHgSdM3ZBuIwMat8nU6foiwO13t rMHfyru7xCjRJjMJdAAQJCRa/lmDHw==
test. 3600 IN CDS 52433 13 2 90C4668A53D8BE06049BABD2DFC93F4C6B46C9055E20D91166381E22 11BD9615
test. 3600 IN RRSIG CDS 13 1 3600 20241221095451 20241211085451 43204 test. laL05a0VWqW0zvSb2jH8AllhKeSooLfqsNuChJfsiLTXR/I+6YkmTi5q tbagskUggKmevsXGiSypFZjlM8EZvw==
;; SignedKeyResponse 1.0 20241221095451 (Sat Dec 21 10:54:51 2024)
test. 3600 IN DNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN DNSKEY 256 3 13 GIyBcxr9uBJvybXw2eOeZ1nWjRd+0INxUPlKaWI1KQxJwWRJTOJMw33g SSCz++TBmKyXm5ghl+56vOkoO33ppg==
test. 3600 IN DNSKEY 256 3 13 1oC9YpShKeL5HQnYIMX7y77b9qbnAsKIjVuU0AUoo2kTA1D2fXxB9W95 +uqIiJuiteHK/oGmeDy4UsiTd2W1DQ==
test. 3600 IN RRSIG DNSKEY 13 1 3600 20241231095451 20241221085451 43204 test. +nDXVxSmoOGX4O3N4A8AbT+9nVg8aOQIlthL5mxF/Ojhl+o/5rzQIMW9 OLZ86HusqlOxdS5tgH8HiJ6m+8U3Ag==
test. 3600 IN CDNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN RRSIG CDNSKEY 13 1 3600 20241231095451 20241221085451 43204 test. yEofYMsEAWnHQKrtsdqLv61XB2GT++80EEOzwf3R4SLJU35Ms4r8YN0y kRPxy2V8bdZZFeSIsiiPrAjzNR40FA==
test. 3600 IN CDS 52433 13 2 90C4668A53D8BE06049BABD2DFC93F4C6B46C9055E20D91166381E22 11BD9615
test. 3600 IN RRSIG CDS 13 1 3600 20241231095451 20241221085451 43204 test. 1dA8nHaDhfqHsmaCnDBRijeJTo+wDFBH354YIgko3Ji3EK9TltdHB2lE XSmJrVepFKcZrVYgd4Lubdhw4ngZFw==
;; SignedKeyResponse 1.0 20241231095451 (Tue Dec 31 10:54:51 2024)
test. 3600 IN DNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN DNSKEY 256 3 13 GIyBcxr9uBJvybXw2eOeZ1nWjRd+0INxUPlKaWI1KQxJwWRJTOJMw33g SSCz++TBmKyXm5ghl+56vOkoO33ppg==
test. 3600 IN DNSKEY 256 3 13 1oC9YpShKeL5HQnYIMX7y77b9qbnAsKIjVuU0AUoo2kTA1D2fXxB9W95 +uqIiJuiteHK/oGmeDy4UsiTd2W1DQ==
test. 3600 IN RRSIG DNSKEY 13 1 3600 20250110095451 20241231085451 43204 test. pxHW1Zy+v1ytZUCGq+hgxRn6H51no6P2iCdB2GwdGELYXkaTnWwWvie8 PBwCXlwWz0BrQ6mregR5WK6oJZNRfg==
test. 3600 IN CDNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN RRSIG CDNSKEY 13 1 3600 20250110095451 20241231085451 43204 test. lMe5NYIzX3AAU0yk07/Bj4xAxEYRwxD/knj85GGmfcvYSHktTJ48nC3+ OxI0WxCB1H1+VT86N9KmBa2N9QoSgA==
test. 3600 IN CDS 52433 13 2 90C4668A53D8BE06049BABD2DFC93F4C6B46C9055E20D91166381E22 11BD9615
test. 3600 IN RRSIG CDS 13 1 3600 20250110095451 20241231085451 43204 test. 8pPZEMLaKUpAeHMPKyUjJsXtmfUvKcjzry3A1vRjKyN+3jpD/oGFxwyI M1OGHQ+gkkpLV8fzZAxmSY0vQcdolw==
;; SignedKeyResponse 1.0 20250110095451 (Fri Jan 10 10:54:51 2025)
test. 3600 IN DNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN DNSKEY 256 3 13 GIyBcxr9uBJvybXw2eOeZ1nWjRd+0INxUPlKaWI1KQxJwWRJTOJMw33g SSCz++TBmKyXm5ghl+56vOkoO33ppg==
test. 3600 IN DNSKEY 256 3 13 1oC9YpShKeL5HQnYIMX7y77b9qbnAsKIjVuU0AUoo2kTA1D2fXxB9W95 +uqIiJuiteHK/oGmeDy4UsiTd2W1DQ==
test. 3600 IN RRSIG DNSKEY 13 1 3600 20250120095451 20250110085451 43204 test. oxU/d3PecgTBxPUwxW5Kljp9TkMaOmVLkEis7ixp2xrdGAwA/RewCYCl XLSGY8QmmoNlmVZfJZB8CLpojYA/cg==
test. 3600 IN CDNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN RRSIG CDNSKEY 13 1 3600 20250120095451 20250110085451 43204 test. UCPEA/T2IW5izN6mUZnSjpq+4Kogn7v63rXVhXeKaezzJIKZVQq8Igz2 59nv/9wPitx9BtLPcGcFcAH03o/2fQ==
test. 3600 IN CDS 52433 13 2 90C4668A53D8BE06049BABD2DFC93F4C6B46C9055E20D91166381E22 11BD9615
test. 3600 IN RRSIG CDS 13 1 3600 20250120095451 20250110085451 43204 test. YJQg5rh4P7GhGQrmwOnTDxUsrhypCFnJnNE9eC0P3diNFBIzyeWR6MIF MwJd2IgroOt3UfWW5Gy2/cO/U549qg==
;; SignedKeyResponse 1.0 20250120095451 (Mon Jan 20 10:54:51 2025)
test. 3600 IN DNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN DNSKEY 256 3 13 GIyBcxr9uBJvybXw2eOeZ1nWjRd+0INxUPlKaWI1KQxJwWRJTOJMw33g SSCz++TBmKyXm5ghl+56vOkoO33ppg==
test. 3600 IN DNSKEY 256 3 13 1oC9YpShKeL5HQnYIMX7y77b9qbnAsKIjVuU0AUoo2kTA1D2fXxB9W95 +uqIiJuiteHK/oGmeDy4UsiTd2W1DQ==
test. 3600 IN RRSIG DNSKEY 13 1 3600 20250130095451 20250120085451 43204 test. 4hpbld7y3KQDyWrfGfjufr7h7gibiC47MmTtfqwWviFmjWe2/8dp4yMc LJz5Nsa8R7TA9OIPuPc1beb5hJgYPA==
test. 3600 IN CDNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN RRSIG CDNSKEY 13 1 3600 20250130095451 20250120085451 43204 test. osZHI0/tWhzkEkX/+FB54AZ1gtxnNvHf7a3vQJwPI4608u523ZHHvL1Q QM2KHSGVdwnWuZCEV7LMj5dOkNiLtg==
test. 3600 IN CDS 52433 13 2 90C4668A53D8BE06049BABD2DFC93F4C6B46C9055E20D91166381E22 11BD9615
test. 3600 IN RRSIG CDS 13 1 3600 20250130095451 20250120085451 43204 test. Mbs2YA2hRmfHye3Hm+2hnG5PUzIALU94l6AZE/+l5DypWdGoU2ZOpvHB RhOiQ7tn9meKTWT4tKIiwypo+NsROw==
;; SignedKeyResponse 1.0 20250130095451 (Thu Jan 30 10:54:51 2025)
test. 3600 IN DNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN DNSKEY 256 3 13 GIyBcxr9uBJvybXw2eOeZ1nWjRd+0INxUPlKaWI1KQxJwWRJTOJMw33g SSCz++TBmKyXm5ghl+56vOkoO33ppg==
test. 3600 IN DNSKEY 256 3 13 1oC9YpShKeL5HQnYIMX7y77b9qbnAsKIjVuU0AUoo2kTA1D2fXxB9W95 +uqIiJuiteHK/oGmeDy4UsiTd2W1DQ==
test. 3600 IN RRSIG DNSKEY 13 1 3600 20250209095451 20250130085451 43204 test. 3iHC6NePWW4TWadU3soh8U86HtDpUUixEVEzMvvDe8KIEhGYQV0GH8hT nLaPDfJ/MMp87loT9IYHdYG5bxf9kw==
test. 3600 IN CDNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN RRSIG CDNSKEY 13 1 3600 20250209095451 20250130085451 43204 test. fkKDOYUGpUMIA3+tkxxlHSaJQr8mh/UHaYu7LYNoLTMEKgcV2vEx0IJn X8aLLD1+dfC+qZZkhCcVDdaDNlAEYA==
test. 3600 IN CDS 52433 13 2 90C4668A53D8BE06049BABD2DFC93F4C6B46C9055E20D91166381E22 11BD9615
test. 3600 IN RRSIG CDS 13 1 3600 20250209095451 20250130085451 43204 test. RxHOslq45bs1LT6Tj0BBSHQJRFxM3bqVDq2+FtThYPEGkWWpHq+05YXJ phQNHYBT3Bs6O9taCE207UZGtyQURQ==
;; SignedKeyResponse 1.0 20250209095451 (Sun Feb 9 10:54:51 2025)
test. 3600 IN DNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN DNSKEY 256 3 13 GIyBcxr9uBJvybXw2eOeZ1nWjRd+0INxUPlKaWI1KQxJwWRJTOJMw33g SSCz++TBmKyXm5ghl+56vOkoO33ppg==
test. 3600 IN DNSKEY 256 3 13 1oC9YpShKeL5HQnYIMX7y77b9qbnAsKIjVuU0AUoo2kTA1D2fXxB9W95 +uqIiJuiteHK/oGmeDy4UsiTd2W1DQ==
test. 3600 IN RRSIG DNSKEY 13 1 3600 20250219095451 20250209085451 43204 test. FTktmdqq0PJH4boctPD6auwj2xFTVYArgonR4OcmlV2cr7L3lfGNel+j iFF4PRvwcQwOQ6kYKCstm5hcV7DOOg==
test. 3600 IN CDNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN RRSIG CDNSKEY 13 1 3600 20250219095451 20250209085451 43204 test. AuU3mRo1VN8lGVrwihyKBOZEJPPdvj9BsLp9MQAH83IxRx5Qx5ucWs+X wmDY+tAQNA7iM47DV3hbJVhjmzdRTA==
test. 3600 IN CDS 52433 13 2 90C4668A53D8BE06049BABD2DFC93F4C6B46C9055E20D91166381E22 11BD9615
test. 3600 IN RRSIG CDS 13 1 3600 20250219095451 20250209085451 43204 test. 1RVf9OxKaSCvWz8wJ0g3Y4nt0jzolmhLF/eEy9ZTxBft4o0HUaVoe7FV MbTTlfX8v0DrVDrA3oXjw6/a9LRrJA==
;; SignedKeyResponse 1.0 20250219095451 (Wed Feb 19 10:54:51 2025)
test. 3600 IN DNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN DNSKEY 256 3 13 GIyBcxr9uBJvybXw2eOeZ1nWjRd+0INxUPlKaWI1KQxJwWRJTOJMw33g SSCz++TBmKyXm5ghl+56vOkoO33ppg==
test. 3600 IN DNSKEY 256 3 13 1oC9YpShKeL5HQnYIMX7y77b9qbnAsKIjVuU0AUoo2kTA1D2fXxB9W95 +uqIiJuiteHK/oGmeDy4UsiTd2W1DQ==
test. 3600 IN RRSIG DNSKEY 13 1 3600 20250301095451 20250219085451 43204 test. VzZPLWIeFZcM2nDu5okXatpZAK5y4YiTTiygK7M22A+U/h8vFOfdImgJ DE4Ym2RtQmKaNJUHcde5ldNoJrx+Yg==
test. 3600 IN CDNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN RRSIG CDNSKEY 13 1 3600 20250301095451 20250219085451 43204 test. kLGW2+rSAvqqNAVx8uvZcmtLVfb//UDGpJgWd+zFn1IhrmPZ72RfSl4b tRWwunSiaMBl25lD0AKlA2RkenP64w==
test. 3600 IN CDS 52433 13 2 90C4668A53D8BE06049BABD2DFC93F4C6B46C9055E20D91166381E22 11BD9615
test. 3600 IN RRSIG CDS 13 1 3600 20250301095451 20250219085451 43204 test. XjZZYdTpk5LlLGQHZ/KdS+tO81DMZ+LpLFFQzXAWS0z74ccWZRzOK638 TvhlWPS+djCGQBDMckH6vTya5qWDcQ==
;; SignedKeyResponse 1.0 20250301095451 (Sat Mar 1 10:54:51 2025)
test. 3600 IN DNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN DNSKEY 256 3 13 1oC9YpShKeL5HQnYIMX7y77b9qbnAsKIjVuU0AUoo2kTA1D2fXxB9W95 +uqIiJuiteHK/oGmeDy4UsiTd2W1DQ==
test. 3600 IN RRSIG DNSKEY 13 1 3600 20250311095451 20250301085451 43204 test. awCdWEX+LBm/5JL9EtxdOVFi1ocFZkapL9+ihmPZFGxkjy8k8MjCoC5N QIcD+u+2TTXDjPIv/kuPLvX+d1AfLQ==
test. 3600 IN CDNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN RRSIG CDNSKEY 13 1 3600 20250311095451 20250301085451 43204 test. u9qMR7cvoROTr0JL9ESc2AtbEiGjbURZZDIqDS16+OMABV/rK+zprJIZ luz254CwR1Avg7vioCJ8oQ96866kxA==
test. 3600 IN CDS 52433 13 2 90C4668A53D8BE06049BABD2DFC93F4C6B46C9055E20D91166381E22 11BD9615
test. 3600 IN RRSIG CDS 13 1 3600 20250311095451 20250301085451 43204 test. EP7sW229U9PxehZWqBnpz0cDp/ldIFeersRlYo1i2aC78UOadYzWm2kW 8sCYqnSg/n3FOjnUAVDFFTLNqxmmMQ==
;; SignedKeyResponse 1.0 20250311095451 (Tue Mar 11 10:54:51 2025)
test. 3600 IN DNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN DNSKEY 256 3 13 1oC9YpShKeL5HQnYIMX7y77b9qbnAsKIjVuU0AUoo2kTA1D2fXxB9W95 +uqIiJuiteHK/oGmeDy4UsiTd2W1DQ==
test. 3600 IN RRSIG DNSKEY 13 1 3600 20250321095451 20250311085451 43204 test. h6RkdFZ2Svu4pIWZl08rSjVn8T6e8bGu2xDe1yht9Ub3uLPcWbLqLkSt SBTG5JzNM4kMh1/BeA9VZJw21SFrAA==
test. 3600 IN CDNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN RRSIG CDNSKEY 13 1 3600 20250321095451 20250311085451 43204 test. pDR72obgPGMJgYPQXpXjWXuyyqFZarm7k+qRtsflk6HYbL2lObkoyazH T5+HVEMJh1Z7/7SttUMx7f3HyIKxuQ==
test. 3600 IN CDS 52433 13 2 90C4668A53D8BE06049BABD2DFC93F4C6B46C9055E20D91166381E22 11BD9615
test. 3600 IN RRSIG CDS 13 1 3600 20250321095451 20250311085451 43204 test. Ylpmzo26Xz2nJ8qoVHAGt2bFIFJgsBONMqa8+zF9rYDmapjaP7TOQQ4V F6mV2qnyDj9i+fkNg0Wd6biIvoWCHw==
;; SignedKeyResponse 1.0 20250321095451 (Fri Mar 21 10:54:51 2025)
test. 3600 IN DNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN DNSKEY 256 3 13 1oC9YpShKeL5HQnYIMX7y77b9qbnAsKIjVuU0AUoo2kTA1D2fXxB9W95 +uqIiJuiteHK/oGmeDy4UsiTd2W1DQ==
test. 3600 IN RRSIG DNSKEY 13 1 3600 20250331095451 20250321085451 43204 test. BytwfF1sGpgsqodbvOGUULu8PqX2up0Fe0LHvohTOnr/n8dDUFpD4ivh jsLl9URAJP942J4R8UW5qNXh4x1k0A==
test. 3600 IN CDNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN RRSIG CDNSKEY 13 1 3600 20250331095451 20250321085451 43204 test. 07j7VA7GOTqq3Gu2RulknUc9HS4p9oXZWluqqCVuJKl+71YWg+fwc8TT GJDDleFld8/MvrWjrzlEgCSCXOLD1A==
test. 3600 IN CDS 52433 13 2 90C4668A53D8BE06049BABD2DFC93F4C6B46C9055E20D91166381E22 11BD9615
test. 3600 IN RRSIG CDS 13 1 3600 20250331095451 20250321085451 43204 test. 5SBlf+mrH1hPAptudxPLzoFhwBx3Z9KJLyKe2B/qbEyAoRHUV0jmMTpW uHgczPDfZuBpyvhyi+m/0Lz2oPf7HQ==
;; SignedKeyResponse 1.0 20250331095451 (Mon Mar 31 11:54:51 2025)
test. 3600 IN DNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN DNSKEY 256 3 13 1oC9YpShKeL5HQnYIMX7y77b9qbnAsKIjVuU0AUoo2kTA1D2fXxB9W95 +uqIiJuiteHK/oGmeDy4UsiTd2W1DQ==
test. 3600 IN RRSIG DNSKEY 13 1 3600 20250410095451 20250331085451 43204 test. Gqx+ThdaBcgRMUQAnkEDvb/fx+9PjxE5qpF/inJ82ZGvmPUIruSbNtCx J7i4eoWqyPbF72x9RGnSaGabbyWqJw==
test. 3600 IN CDNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN RRSIG CDNSKEY 13 1 3600 20250410095451 20250331085451 43204 test. KL9J1pJ1Uv8z1HJWsWNp9XXHMd1qkLULWAls/nqqZVPsY6E1wdxhA7dt aLWsoiBQtiPSodSvBLVe5ZkrjcF9+w==
test. 3600 IN CDS 52433 13 2 90C4668A53D8BE06049BABD2DFC93F4C6B46C9055E20D91166381E22 11BD9615
test. 3600 IN RRSIG CDS 13 1 3600 20250410095451 20250331085451 43204 test. tZRaOR5EisYVv/CrWZHm937mAubm83cpMIi9EIduKNVeitZVA+I3KqmH SmT19gHy3yPFpBLurYF/WTb8Zem+aw==
;; SignedKeyResponse 1.0 20250410095451 (Thu Apr 10 11:54:51 2025)
test. 3600 IN DNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN DNSKEY 256 3 13 1oC9YpShKeL5HQnYIMX7y77b9qbnAsKIjVuU0AUoo2kTA1D2fXxB9W95 +uqIiJuiteHK/oGmeDy4UsiTd2W1DQ==
test. 3600 IN RRSIG DNSKEY 13 1 3600 20250420095451 20250410085451 43204 test. kTmCcp83QKNHq8mrb2ASdmlefMz1jcWrdznPYXQZLfWijlaCjqeHP0P+ Vr4PFvsZoDAo/JLyNQNGRgvD1Jzjsw==
test. 3600 IN CDNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN RRSIG CDNSKEY 13 1 3600 20250420095451 20250410085451 43204 test. JK4FHWg7BH1UTzefCHvsGkk1YmrO9cA33YLjcZjF2nfbIjxr2HCtBQKf HjRhrS3U/RJrKpHL3POHXeDPi6kfjA==
test. 3600 IN CDS 52433 13 2 90C4668A53D8BE06049BABD2DFC93F4C6B46C9055E20D91166381E22 11BD9615
test. 3600 IN RRSIG CDS 13 1 3600 20250420095451 20250410085451 43204 test. +TCwCmu1zPCWxf0lU8gGo7i0WIesj91nUtjuT9dKJ0xZ7gDM5kwhhrR+ AHgUsjbjKW1Cs5mG/mZ41Tj2mrqcHw==
;; SignedKeyResponse 1.0 20250420095451 (Sun Apr 20 11:54:51 2025)
test. 3600 IN DNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN DNSKEY 256 3 13 1oC9YpShKeL5HQnYIMX7y77b9qbnAsKIjVuU0AUoo2kTA1D2fXxB9W95 +uqIiJuiteHK/oGmeDy4UsiTd2W1DQ==
test. 3600 IN RRSIG DNSKEY 13 1 3600 20250430095451 20250420085451 43204 test. 2mXzGfb6FOk3oIkft0yhYFWCa6GTsXX8xx7X8Ky79AiDD+STdI9ASwZn adabWj8L/XUiTeEvQxx+Xm1Mz2cV+A==
test. 3600 IN CDNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN RRSIG CDNSKEY 13 1 3600 20250430095451 20250420085451 43204 test. +pmWPjkgBb7HLlMOooBZ6k2F9k1/dR2rOYwTbmsWdWvKr3RDVyqm4Soo G7SHVbaAaM+I+BgDR75j61pvhTkrFw==
test. 3600 IN CDS 52433 13 2 90C4668A53D8BE06049BABD2DFC93F4C6B46C9055E20D91166381E22 11BD9615
test. 3600 IN RRSIG CDS 13 1 3600 20250430095451 20250420085451 43204 test. Fk39EKvhrsttX/Bnyx/Tc0ep8hi/9iBVAkhQ1+a0zYALJTbU/6ZJzng3 sawanjZE/WPdmkj87QaZj+wudd7GUA==
;; SignedKeyResponse 1.0 20250430095451 (Wed Apr 30 11:54:51 2025)
test. 3600 IN DNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN DNSKEY 256 3 13 1oC9YpShKeL5HQnYIMX7y77b9qbnAsKIjVuU0AUoo2kTA1D2fXxB9W95 +uqIiJuiteHK/oGmeDy4UsiTd2W1DQ==
test. 3600 IN RRSIG DNSKEY 13 1 3600 20250510095451 20250430085451 43204 test. ERK8JbzsSNxrKKZGWpe58n10owOhgDhSHhVuO7IdiEnhLzxSVaU+187f VmDzXYEtYqFEK8yX9wJS95zuggaQcg==
test. 3600 IN CDNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN RRSIG CDNSKEY 13 1 3600 20250510095451 20250430085451 43204 test. JHMu0uxWe22hZyg4fNr1/i8S0B6pALrAZ6sOfioeDB0p3LmzSioBSkC+ JOxpH0giEP4MF04rwXISsk29vUA5Vg==
test. 3600 IN CDS 52433 13 2 90C4668A53D8BE06049BABD2DFC93F4C6B46C9055E20D91166381E22 11BD9615
test. 3600 IN RRSIG CDS 13 1 3600 20250510095451 20250430085451 43204 test. 5NqL582nBFUtLMDs/LWZYFTihgKmoA9mjzECi7QFdWIyh8kDJ+ABiFmv hGErth4d659n0kT1ui9cY5NFvCC81A==
;; SignedKeyResponse 1.0 20250510095451 (Sat May 10 11:54:51 2025)
test. 3600 IN DNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN DNSKEY 256 3 13 1oC9YpShKeL5HQnYIMX7y77b9qbnAsKIjVuU0AUoo2kTA1D2fXxB9W95 +uqIiJuiteHK/oGmeDy4UsiTd2W1DQ==
test. 3600 IN RRSIG DNSKEY 13 1 3600 20250520095451 20250510085451 43204 test. Hu01ZiDF6F7t8P4OGDpsYY7Y6HdglbVXEHV6WDXPTqe7pVielrSl8qpE IBNrYkmVTxFTtpvl8zvyyGTZ4cQvuA==
test. 3600 IN CDNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN RRSIG CDNSKEY 13 1 3600 20250520095451 20250510085451 43204 test. IDkt1YeLRcV/8WG/5IiY/oyJ2SjfNXByUn8uxQ8CwTZvCsTz8M4xZMnR z/bPPGEZ7eDfQ2K/tdm/ZqnqfFf4AQ==
test. 3600 IN CDS 52433 13 2 90C4668A53D8BE06049BABD2DFC93F4C6B46C9055E20D91166381E22 11BD9615
test. 3600 IN RRSIG CDS 13 1 3600 20250520095451 20250510085451 43204 test. kZINQ+quLGIiMvn+uyon/BIXBdXYPN2UcfbDEwjHuADTvh49b9S46/eV NLJOciOw69kfpiVZHMghSZFb6ayV1g==
;; SignedKeyResponse 1.0 20250520095451 (Tue May 20 11:54:51 2025)
test. 3600 IN DNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN DNSKEY 256 3 13 1oC9YpShKeL5HQnYIMX7y77b9qbnAsKIjVuU0AUoo2kTA1D2fXxB9W95 +uqIiJuiteHK/oGmeDy4UsiTd2W1DQ==
test. 3600 IN RRSIG DNSKEY 13 1 3600 20250530095451 20250520085451 43204 test. fr38j/4aT3TwHEQtQidnAwW/iE9NJSm+Zj5Sc/MIODqU/tKRJtAP6kL7 b27H6lV2rpOpqOju7Vh5XT4fMoZRqg==
test. 3600 IN CDNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN RRSIG CDNSKEY 13 1 3600 20250530095451 20250520085451 43204 test. C3wKQ9HW2cLNIX9X3XN4jr2nLzTLcrhb+zFohfvHgV/mvg+MgZKLoz3k XAJGwXLCtC607TQtAD+S2u6zW+9QzQ==
test. 3600 IN CDS 52433 13 2 90C4668A53D8BE06049BABD2DFC93F4C6B46C9055E20D91166381E22 11BD9615
test. 3600 IN RRSIG CDS 13 1 3600 20250530095451 20250520085451 43204 test. bMthdNbLgcgLt7nxmENEiNSJAjFN6becNCu8GK/NHNdCQMOnHyLOmhAW cgVsVQvs31F2sW2vmuWXdIrT7JtfaA==
;; SignedKeyResponse 1.0 20250530095451 (Fri May 30 11:54:51 2025)
test. 3600 IN DNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN DNSKEY 256 3 13 1oC9YpShKeL5HQnYIMX7y77b9qbnAsKIjVuU0AUoo2kTA1D2fXxB9W95 +uqIiJuiteHK/oGmeDy4UsiTd2W1DQ==
test. 3600 IN RRSIG DNSKEY 13 1 3600 20250609095451 20250530085451 43204 test. ExWenclwHV7d4bomcDzlUBuxZxL1l0GRUupnkfT6BF+rGIvN7IXzPys1 g6sQItAOm6yLk2UI7EK8og+zAsJO/w==
test. 3600 IN CDNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN RRSIG CDNSKEY 13 1 3600 20250609095451 20250530085451 43204 test. RLdCWbSPnMfNAor1t3EecdB3yR9q8uiKGWQSnAA51Nx8Zvxx4lVIwKkX UG1AmaCNAO2FVINNXP0Xv1totxpmTg==
test. 3600 IN CDS 52433 13 2 90C4668A53D8BE06049BABD2DFC93F4C6B46C9055E20D91166381E22 11BD9615
test. 3600 IN RRSIG CDS 13 1 3600 20250609095451 20250530085451 43204 test. w0EcE+oX9P2TR3opkrPznnC4GK54yedMcfXBI2tEU4qP7sfz/fGJ+qBF tRT3kXlPIJzjVSL4dv3xGDLy6Z1OnA==
;; SignedKeyResponse 1.0 20250609095451 (Mon Jun 9 11:54:51 2025)
test. 3600 IN DNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN DNSKEY 256 3 13 1oC9YpShKeL5HQnYIMX7y77b9qbnAsKIjVuU0AUoo2kTA1D2fXxB9W95 +uqIiJuiteHK/oGmeDy4UsiTd2W1DQ==
test. 3600 IN RRSIG DNSKEY 13 1 3600 20250619095451 20250609085451 43204 test. NbsrdkNipQDvqd6/1haCKCuA50/wQuhHixwFkSBAF28UwH/kZJYNW9px 2ipgkX2A0yTkX1GFyGZ+7CNrQXjigg==
test. 3600 IN CDNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN RRSIG CDNSKEY 13 1 3600 20250619095451 20250609085451 43204 test. j9l3dm3YPscVY1AlPXvXndYlZVMg20UkVbyqh0CnyHfLmc9CryXKNs3I 7Ji+zQYe+u8FUjRitW+LhuX/tBedKw==
test. 3600 IN CDS 52433 13 2 90C4668A53D8BE06049BABD2DFC93F4C6B46C9055E20D91166381E22 11BD9615
test. 3600 IN RRSIG CDS 13 1 3600 20250619095451 20250609085451 43204 test. WfWSgoLhWwRi2BYMfoOV7sXSuFECZH7U8339A02R1qHo3B5wsUJ3O3Q5 HD5bMns74aG8z43pDxEe0zhtGZlf4Q==
;; SignedKeyResponse 1.0 20250619095451 (Thu Jun 19 11:54:51 2025)
test. 3600 IN DNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN DNSKEY 256 3 13 1oC9YpShKeL5HQnYIMX7y77b9qbnAsKIjVuU0AUoo2kTA1D2fXxB9W95 +uqIiJuiteHK/oGmeDy4UsiTd2W1DQ==
test. 3600 IN RRSIG DNSKEY 13 1 3600 20250629095451 20250619085451 43204 test. 0jrKaRUXDyBX2L8cId1Pv616joiuJhsaHoQMJoDxg14ovnNlRf9VpjMA vTgo5HSMb1JtT5LlrwkYeTfky/1aIQ==
test. 3600 IN CDNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN RRSIG CDNSKEY 13 1 3600 20250629095451 20250619085451 43204 test. oiNVkAjk7+ZwSfFaoEXQSWMPrDXKBEp5pLvWKwhQ/8aweDbAqGM/KKPg s6hN68z8YH/9BpRyc29pvPiY94761Q==
test. 3600 IN CDS 52433 13 2 90C4668A53D8BE06049BABD2DFC93F4C6B46C9055E20D91166381E22 11BD9615
test. 3600 IN RRSIG CDS 13 1 3600 20250629095451 20250619085451 43204 test. 2+a0WiP3tdCXAm7MhoZf7KatWh8IJbvRUFQA/6aFMenxYItRCkLm/Ryx PZ6VzQE+ck1d0i+IH/bbDLkod+0yxQ==
;; SignedKeyResponse 1.0 20250629095451 (Sun Jun 29 11:54:51 2025)
test. 3600 IN DNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN DNSKEY 256 3 13 1oC9YpShKeL5HQnYIMX7y77b9qbnAsKIjVuU0AUoo2kTA1D2fXxB9W95 +uqIiJuiteHK/oGmeDy4UsiTd2W1DQ==
test. 3600 IN RRSIG DNSKEY 13 1 3600 20250709095451 20250629085451 43204 test. doz5m1au2uYaBuK3gzCtuB6A2msfISq0TXaM8k2sgrvlODlGTZYFvB5A b1EtgKpBjXBMmRjepsuLg3kkHvIonA==
test. 3600 IN CDNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN RRSIG CDNSKEY 13 1 3600 20250709095451 20250629085451 43204 test. h6hBio76Q3jlzKHZw2a2aHSe6eCTg5xOG4tUFcMdpN4twdIEfzCx/4Bx k7Z+fP5NBhXISMWhq+KFncNR4Xuolg==
test. 3600 IN CDS 52433 13 2 90C4668A53D8BE06049BABD2DFC93F4C6B46C9055E20D91166381E22 11BD9615
test. 3600 IN RRSIG CDS 13 1 3600 20250709095451 20250629085451 43204 test. PAMB5ikXVSciWLDj3X0B/SOFwpvKpvseYqFBHNZf8Dt/AoGkM3HBNLeE id6IoLKDmycxnIFF9CWuDw642bEUkw==
;; SignedKeyResponse 1.0 20250709095451 (Wed Jul 9 11:54:51 2025)
test. 3600 IN DNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN DNSKEY 256 3 13 1oC9YpShKeL5HQnYIMX7y77b9qbnAsKIjVuU0AUoo2kTA1D2fXxB9W95 +uqIiJuiteHK/oGmeDy4UsiTd2W1DQ==
test. 3600 IN RRSIG DNSKEY 13 1 3600 20250719095451 20250709085451 43204 test. ZZbY45fTc+BE1vjJy9PSjVc9SuIkYzlG80MJa+I2S/h1C7kcjd9jbRTN agw0GLd5Z8arjxwvclmOxgFPRQNL0Q==
test. 3600 IN CDNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN RRSIG CDNSKEY 13 1 3600 20250719095451 20250709085451 43204 test. UzlPHvtZu4AkKATGPCB1TUcwYu1VIPACyR9oyEjEuWLgrQInatELkAcu yyrMlrUS+HsI6weDFhqMHEJCEeDvyQ==
test. 3600 IN CDS 52433 13 2 90C4668A53D8BE06049BABD2DFC93F4C6B46C9055E20D91166381E22 11BD9615
test. 3600 IN RRSIG CDS 13 1 3600 20250719095451 20250709085451 43204 test. O55KkvO6oD4DVA3oKoSpvfFAQwCDI+mR6Q6HPcdtsEO7K1mDTmcuhyxK cdqa3iT4r/rUX61On+voqLTMxLfISA==
;; SignedKeyResponse 1.0 20250719095451 (Sat Jul 19 11:54:51 2025)
test. 3600 IN DNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN DNSKEY 256 3 13 1oC9YpShKeL5HQnYIMX7y77b9qbnAsKIjVuU0AUoo2kTA1D2fXxB9W95 +uqIiJuiteHK/oGmeDy4UsiTd2W1DQ==
test. 3600 IN RRSIG DNSKEY 13 1 3600 20250729095451 20250719085451 43204 test. umIJxEdYBI88eRQFvcyKRrqrIFpDRWsoo3rkbi1TMvIEEN3xeEhDbmRq /Kd5AYvyXrPtpzew5puAUiTq+KoBOQ==
test. 3600 IN CDNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN RRSIG CDNSKEY 13 1 3600 20250729095451 20250719085451 43204 test. UafqgwC5uaqmQTJP8ZFAqzTdUlahjgvWESiXBZ/Zf5y02s02oJ+ZjDWK c1w2z+7+lWay+AY/o1U3kAQgPHJxhQ==
test. 3600 IN CDS 52433 13 2 90C4668A53D8BE06049BABD2DFC93F4C6B46C9055E20D91166381E22 11BD9615
test. 3600 IN RRSIG CDS 13 1 3600 20250729095451 20250719085451 43204 test. xhqsifmVM4JhSWrl57v+z2SDcI982CVJOlJzsI6TeLLUDwaJ7aFfSJuD rVmiJW2L67t0PQraqVMGK7SYYxAqJw==
;; SignedKeyResponse 1.0 20250729095451 (Tue Jul 29 11:54:51 2025)
test. 3600 IN DNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN DNSKEY 256 3 13 1oC9YpShKeL5HQnYIMX7y77b9qbnAsKIjVuU0AUoo2kTA1D2fXxB9W95 +uqIiJuiteHK/oGmeDy4UsiTd2W1DQ==
test. 3600 IN RRSIG DNSKEY 13 1 3600 20250808095451 20250729085451 43204 test. YR8S+IhFYQDRSDg1CO1qqfrnsBAKyzmVx9dNv/oQfyeoXFVBaaJfUGXI QaOBlNa8guWdN+HiNbwIPAOA/C7+dA==
test. 3600 IN CDNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN RRSIG CDNSKEY 13 1 3600 20250808095451 20250729085451 43204 test. CncEO/fjzNOMca289UgfW/cNmz20W82a0ZiTg5Bm5yEqkzcJQ2CZt9mV Dps2sbmjXarxbpLKjyk+AVepWJD5+g==
test. 3600 IN CDS 52433 13 2 90C4668A53D8BE06049BABD2DFC93F4C6B46C9055E20D91166381E22 11BD9615
test. 3600 IN RRSIG CDS 13 1 3600 20250808095451 20250729085451 43204 test. vi++/+pQYrP9C+oVUuIhghZyNp21/QAS+qLEUb8FuqaVPmXtkRU8ZAG5 bente5qCUA5QJZwDeDWyrLKJvg5AAw==
;; SignedKeyResponse 1.0 20250808095451 (Fri Aug 8 11:54:51 2025)
test. 3600 IN DNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN DNSKEY 256 3 13 1oC9YpShKeL5HQnYIMX7y77b9qbnAsKIjVuU0AUoo2kTA1D2fXxB9W95 +uqIiJuiteHK/oGmeDy4UsiTd2W1DQ==
test. 3600 IN RRSIG DNSKEY 13 1 3600 20250818095451 20250808085451 43204 test. Up4NJhAw8aXDs9C8MXn4hI4G/23EYClOCu4cNpoS111debrLecMUEl91 piysr5JiaG9Didq33ZVLhJ5ShVNU9Q==
test. 3600 IN CDNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN RRSIG CDNSKEY 13 1 3600 20250818095451 20250808085451 43204 test. LYP3vPq+cLW7QZb78B6ZFBss0nGimOchcDp50u3vzZGr5OdaZUdaDFyh hYj4PKQ183MMv6vXQ4bqxvh5tUIbQA==
test. 3600 IN CDS 52433 13 2 90C4668A53D8BE06049BABD2DFC93F4C6B46C9055E20D91166381E22 11BD9615
test. 3600 IN RRSIG CDS 13 1 3600 20250818095451 20250808085451 43204 test. L3uCEIuMkUFPSoYliiUakloOkCCFbx8ytZhdhsXDjo75yQkDG41/1EzI MShUfW6ekyG6n4t4cvIEvAQlE/46dQ==
;; SignedKeyResponse 1.0 20250818095451 (Mon Aug 18 11:54:51 2025)
test. 3600 IN DNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN DNSKEY 256 3 13 1oC9YpShKeL5HQnYIMX7y77b9qbnAsKIjVuU0AUoo2kTA1D2fXxB9W95 +uqIiJuiteHK/oGmeDy4UsiTd2W1DQ==
test. 3600 IN RRSIG DNSKEY 13 1 3600 20250828095451 20250818085451 43204 test. QC/kdb/A5wNYI8we2/S/zAaHl4kx9d6DGdmxnbo7QRQiy9H7cwgs0ya3 2Ic0SoCN79NW7NMt5JtwSUUtGh3Anw==
test. 3600 IN CDNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN RRSIG CDNSKEY 13 1 3600 20250828095451 20250818085451 43204 test. wuhXlACKuwPuEo8/ko67TbInu0/NIVs5yH1lvAOTiD8l+pj71l1zjHbz v5nGeU1Q51Gb+Mm+y79cLOGX91y5vA==
test. 3600 IN CDS 52433 13 2 90C4668A53D8BE06049BABD2DFC93F4C6B46C9055E20D91166381E22 11BD9615
test. 3600 IN RRSIG CDS 13 1 3600 20250828095451 20250818085451 43204 test. 7vOgohLRLLzlC1pK56fkZ5UyE7l++KULHN8p4g8CtBhBRSslE+sPUOyt AjPx7j/FoO3yGKy5EVx3F/Pk0tD6sw==
;; SignedKeyResponse 1.0 20250828095451 (Thu Aug 28 11:54:51 2025)
test. 3600 IN DNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN DNSKEY 256 3 13 1oC9YpShKeL5HQnYIMX7y77b9qbnAsKIjVuU0AUoo2kTA1D2fXxB9W95 +uqIiJuiteHK/oGmeDy4UsiTd2W1DQ==
test. 3600 IN RRSIG DNSKEY 13 1 3600 20250907095451 20250828085451 43204 test. G1/A81q5OUOSw0dualwTZYyKqcV1kbKXAs6BLkhlft44S6W7f22vKxkr JiEDEgAiVxvINYbjwoJmNmjtr3ifcA==
test. 3600 IN CDNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN RRSIG CDNSKEY 13 1 3600 20250907095451 20250828085451 43204 test. oDcqk3/hDibJAVrnp39DIl1zkO+l0H31hQd8OA+54FztZWqL+jodpNWm Qz6CvMHxiNGZe6TbX9VO0ylZqPK/NA==
test. 3600 IN CDS 52433 13 2 90C4668A53D8BE06049BABD2DFC93F4C6B46C9055E20D91166381E22 11BD9615
test. 3600 IN RRSIG CDS 13 1 3600 20250907095451 20250828085451 43204 test. +YtInvaXrzlnH+wXJJavmYiWRpMdC5tvzYszWRJkO61FlDm6oGL0XIjs G+UP8bvHt9JkzVJ1BrrnDBdEKEITrQ==
;; SignedKeyResponse 1.0 20250907095451 (Sun Sep 7 11:54:51 2025)
test. 3600 IN DNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN DNSKEY 256 3 13 1oC9YpShKeL5HQnYIMX7y77b9qbnAsKIjVuU0AUoo2kTA1D2fXxB9W95 +uqIiJuiteHK/oGmeDy4UsiTd2W1DQ==
test. 3600 IN RRSIG DNSKEY 13 1 3600 20250917095451 20250907085451 43204 test. z5Wqyk/D3v8WWt3ATX6Ami8qNjQDTvUQxMU5lM+zMlFnHK3q59kmUnZR 8My0WT6gaNcAdqGsD+IYvTOMtFgu9w==
test. 3600 IN CDNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN RRSIG CDNSKEY 13 1 3600 20250917095451 20250907085451 43204 test. ijhg2claxX6K1TGBuo9d7SpT7NkKYYnom/h/bxf7XEfL9gvqtoMRmp6m 64xgaS3YheQUQ/Uf2W2T4qymSy3elQ==
test. 3600 IN CDS 52433 13 2 90C4668A53D8BE06049BABD2DFC93F4C6B46C9055E20D91166381E22 11BD9615
test. 3600 IN RRSIG CDS 13 1 3600 20250917095451 20250907085451 43204 test. Vj5Fcc0S61m3rsA4a5JkUfmyKJrMnpMgqQR6+7JGadaKAIyHqyU1tPfC Nu+/i7HPmHFxgdMnCyN+UyXrQw8zYw==
;; SignedKeyResponse 1.0 20250917095451 (Wed Sep 17 11:54:51 2025)
test. 3600 IN DNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN DNSKEY 256 3 13 1oC9YpShKeL5HQnYIMX7y77b9qbnAsKIjVuU0AUoo2kTA1D2fXxB9W95 +uqIiJuiteHK/oGmeDy4UsiTd2W1DQ==
test. 3600 IN RRSIG DNSKEY 13 1 3600 20250927095451 20250917085451 43204 test. I6+BxqnCi7t22ebx1evBwkjbpX1H+llByokERIXJvmIITGnld6EEuW8c nDr9qyUK8MKzGg1h40f4nriOA22GtA==
test. 3600 IN CDNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN RRSIG CDNSKEY 13 1 3600 20250927095451 20250917085451 43204 test. uZDnd/VxJ1E5lE3g75vdwwP/df/b+YONT00PKE2/fWhICQrSXOOy/kpm aFyfU8aUqaeSJf+3HcJVpmjoZCSLjA==
test. 3600 IN CDS 52433 13 2 90C4668A53D8BE06049BABD2DFC93F4C6B46C9055E20D91166381E22 11BD9615
test. 3600 IN RRSIG CDS 13 1 3600 20250927095451 20250917085451 43204 test. r3XSyiFLRfKsX+jvw+Ri8vvT6GvxP9K5tbkrVu8zXC8BznqOJVxsGXIl 599kL+kCf9cTDRP69o6gnrBb0H6tiA==
;; SignedKeyResponse 1.0 20250927095451 (Sat Sep 27 11:54:51 2025)
test. 3600 IN DNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN DNSKEY 256 3 13 1oC9YpShKeL5HQnYIMX7y77b9qbnAsKIjVuU0AUoo2kTA1D2fXxB9W95 +uqIiJuiteHK/oGmeDy4UsiTd2W1DQ==
test. 3600 IN RRSIG DNSKEY 13 1 3600 20251007095451 20250927085451 43204 test. PfIx8uGT3fPwC5qXy+0wBwNZqtudJQdVhCdJWhlAIYKDW5yJAHVa9bnW OHcJeSQtbTtIm9JzgZDc/tg/cmCXQw==
test. 3600 IN CDNSKEY 257 3 13 evPZ03dt9VeWNQKqw1fpuL0V1RcyPRge4s306hGOVYg1a1IttOf3ZKIm McMgdT1K4nxJ+S7BtX6RVECqzp1rAA==
test. 3600 IN RRSIG CDNSKEY 13 1 3600 20251007095451 20250927085451 43204 test. og+6/mh07tDOQwyH5J3lwiWKt7n2i6m176MWGk/jfe+Qn+N3W6Rkd3ea QNEZwAiGTb21XckitJa3Ij5yfB2D+A==
test. 3600 IN CDS 52433 13 2 90C4668A53D8BE06049BABD2DFC93F4C6B46C9055E20D91166381E22 11BD9615
test. 3600 IN RRSIG CDS 13 1 3600 20251007095451 20250927085451 43204 test. J69bILiYw/TVkuoPeGurhwdq5UniueHH+MvdTbjR7SGyiG9jK/XrT8pB ZPE49FwKUyrtci3K58WuKf1Xr/1wQw==
;; SignedKeyResponse 1.0 generated by test-dev