# STATE_DS=18
# EXPECT_ZRRSIG=19
# EXPECT_KRRSIG=20
+# LEGACY=21
key_key() {
echo "${1}__${2}"
key_set "$1" "STATE_DS" 'none'
key_set "$1" "EXPECT_ZRRSIG" 'no'
key_set "$1" "EXPECT_KRRSIG" 'no'
+ key_set "$1" "LEGACY" 'no'
}
# Start clear.
_length=$(key_get "$1" "ALG_LEN")
_dnskey_ttl="$DNSKEY_TTL"
_lifetime=$(key_get "$1" LIFETIME)
+ _legacy=$(key_get "$1" LEGACY)
_published=$(key_get "$1" PUBLISHED)
_active=$(key_get "$1" ACTIVE)
# Check file existence.
[ -s "$KEY_FILE" ] || ret=1
[ -s "$PRIVATE_FILE" ] || ret=1
- [ -s "$STATE_FILE" ] || ret=1
+ if [ "$_legacy" == "no" ]; then
+ [ -s "$STATE_FILE" ] || ret=1
+ fi
+ [ "$ret" -eq 0 ] || log_error "${BASE_FILE} files missing"
[ "$ret" -eq 0 ] || return
test $_log -eq 1 && echo_i "check key $BASE_FILE"
grep "Private-key-format: v1.3" "$PRIVATE_FILE" > /dev/null || log_error "mismatch private key format in $PRIVATE_FILE"
grep "Algorithm: ${_alg_num} (${_alg_string})" "$PRIVATE_FILE" > /dev/null || log_error "mismatch algorithm in $PRIVATE_FILE"
# Now check the key state file.
- grep "This is the state of key ${_key_id}, for ${_zone}." "$STATE_FILE" > /dev/null || log_error "mismatch top comment in $STATE_FILE"
- grep "Lifetime: ${_lifetime}" "$STATE_FILE" > /dev/null || log_error "mismatch lifetime in $STATE_FILE"
- grep "Algorithm: ${_alg_num}" "$STATE_FILE" > /dev/null || log_error "mismatch algorithm in $STATE_FILE"
- grep "Length: ${_length}" "$STATE_FILE" > /dev/null || log_error "mismatch length in $STATE_FILE"
- grep "KSK: ${_ksk}" "$STATE_FILE" > /dev/null || log_error "mismatch ksk in $STATE_FILE"
- grep "ZSK: ${_zsk}" "$STATE_FILE" > /dev/null || log_error "mismatch zsk in $STATE_FILE"
-
- # Check key states.
- if [ "$_goal" = "none" ]; then
- grep "GoalState: " "$STATE_FILE" > /dev/null && log_error "unexpected goal state in $STATE_FILE"
- else
- grep "GoalState: ${_goal}" "$STATE_FILE" > /dev/null || log_error "mismatch goal state in $STATE_FILE"
- fi
+ if [ "$_legacy" == "no" ]; then
+ grep "This is the state of key ${_key_id}, for ${_zone}." "$STATE_FILE" > /dev/null || log_error "mismatch top comment in $STATE_FILE"
+ grep "Lifetime: ${_lifetime}" "$STATE_FILE" > /dev/null || log_error "mismatch lifetime in $STATE_FILE"
+ grep "Algorithm: ${_alg_num}" "$STATE_FILE" > /dev/null || log_error "mismatch algorithm in $STATE_FILE"
+ grep "Length: ${_length}" "$STATE_FILE" > /dev/null || log_error "mismatch length in $STATE_FILE"
+ grep "KSK: ${_ksk}" "$STATE_FILE" > /dev/null || log_error "mismatch ksk in $STATE_FILE"
+ grep "ZSK: ${_zsk}" "$STATE_FILE" > /dev/null || log_error "mismatch zsk in $STATE_FILE"
+
+ # Check key states.
+ if [ "$_goal" = "none" ]; then
+ grep "GoalState: " "$STATE_FILE" > /dev/null && log_error "unexpected goal state in $STATE_FILE"
+ else
+ grep "GoalState: ${_goal}" "$STATE_FILE" > /dev/null || log_error "mismatch goal state in $STATE_FILE"
+ fi
- if [ "$_state_dnskey" = "none" ]; then
- grep "DNSKEYState: " "$STATE_FILE" > /dev/null && log_error "unexpected dnskey state in $STATE_FILE"
- grep "DNSKEYChange: " "$STATE_FILE" > /dev/null && log_error "unexpected dnskey change in $STATE_FILE"
- else
- grep "DNSKEYState: ${_state_dnskey}" "$STATE_FILE" > /dev/null || log_error "mismatch dnskey state in $STATE_FILE"
- grep "DNSKEYChange: " "$STATE_FILE" > /dev/null || log_error "mismatch dnskey change in $STATE_FILE"
- fi
+ if [ "$_state_dnskey" = "none" ]; then
+ grep "DNSKEYState: " "$STATE_FILE" > /dev/null && log_error "unexpected dnskey state in $STATE_FILE"
+ grep "DNSKEYChange: " "$STATE_FILE" > /dev/null && log_error "unexpected dnskey change in $STATE_FILE"
+ else
+ grep "DNSKEYState: ${_state_dnskey}" "$STATE_FILE" > /dev/null || log_error "mismatch dnskey state in $STATE_FILE"
+ grep "DNSKEYChange: " "$STATE_FILE" > /dev/null || log_error "mismatch dnskey change in $STATE_FILE"
+ fi
- if [ "$_state_zrrsig" = "none" ]; then
- grep "ZRRSIGState: " "$STATE_FILE" > /dev/null && log_error "unexpected zrrsig state in $STATE_FILE"
- grep "ZRRSIGChange: " "$STATE_FILE" > /dev/null && log_error "unexpected zrrsig change in $STATE_FILE"
- else
- grep "ZRRSIGState: ${_state_zrrsig}" "$STATE_FILE" > /dev/null || log_error "mismatch zrrsig state in $STATE_FILE"
- grep "ZRRSIGChange: " "$STATE_FILE" > /dev/null || log_error "mismatch zrrsig change in $STATE_FILE"
- fi
+ if [ "$_state_zrrsig" = "none" ]; then
+ grep "ZRRSIGState: " "$STATE_FILE" > /dev/null && log_error "unexpected zrrsig state in $STATE_FILE"
+ grep "ZRRSIGChange: " "$STATE_FILE" > /dev/null && log_error "unexpected zrrsig change in $STATE_FILE"
+ else
+ grep "ZRRSIGState: ${_state_zrrsig}" "$STATE_FILE" > /dev/null || log_error "mismatch zrrsig state in $STATE_FILE"
+ grep "ZRRSIGChange: " "$STATE_FILE" > /dev/null || log_error "mismatch zrrsig change in $STATE_FILE"
+ fi
- if [ "$_state_krrsig" = "none" ]; then
- grep "KRRSIGState: " "$STATE_FILE" > /dev/null && log_error "unexpected krrsig state in $STATE_FILE"
- grep "KRRSIGChange: " "$STATE_FILE" > /dev/null && log_error "unexpected krrsig change in $STATE_FILE"
- else
- grep "KRRSIGState: ${_state_krrsig}" "$STATE_FILE" > /dev/null || log_error "mismatch krrsig state in $STATE_FILE"
- grep "KRRSIGChange: " "$STATE_FILE" > /dev/null || log_error "mismatch krrsig change in $STATE_FILE"
- fi
+ if [ "$_state_krrsig" = "none" ]; then
+ grep "KRRSIGState: " "$STATE_FILE" > /dev/null && log_error "unexpected krrsig state in $STATE_FILE"
+ grep "KRRSIGChange: " "$STATE_FILE" > /dev/null && log_error "unexpected krrsig change in $STATE_FILE"
+ else
+ grep "KRRSIGState: ${_state_krrsig}" "$STATE_FILE" > /dev/null || log_error "mismatch krrsig state in $STATE_FILE"
+ grep "KRRSIGChange: " "$STATE_FILE" > /dev/null || log_error "mismatch krrsig change in $STATE_FILE"
+ fi
- if [ "$_state_ds" = "none" ]; then
- grep "DSState: " "$STATE_FILE" > /dev/null && log_error "unexpected ds state in $STATE_FILE"
- grep "DSChange: " "$STATE_FILE" > /dev/null && log_error "unexpected ds change in $STATE_FILE"
- else
- grep "DSState: ${_state_ds}" "$STATE_FILE" > /dev/null || log_error "mismatch ds state in $STATE_FILE"
- grep "DSChange: " "$STATE_FILE" > /dev/null || log_error "mismatch ds change in $STATE_FILE"
+ if [ "$_state_ds" = "none" ]; then
+ grep "DSState: " "$STATE_FILE" > /dev/null && log_error "unexpected ds state in $STATE_FILE"
+ grep "DSChange: " "$STATE_FILE" > /dev/null && log_error "unexpected ds change in $STATE_FILE"
+ else
+ grep "DSState: ${_state_ds}" "$STATE_FILE" > /dev/null || log_error "mismatch ds state in $STATE_FILE"
+ grep "DSChange: " "$STATE_FILE" > /dev/null || log_error "mismatch ds change in $STATE_FILE"
+ fi
fi
# Check timing metadata.
if [ "$_published" = "none" ]; then
grep "; Publish:" "$KEY_FILE" > /dev/null && log_error "unexpected publish comment in $KEY_FILE"
grep "Publish:" "$PRIVATE_FILE" > /dev/null && log_error "unexpected publish in $PRIVATE_FILE"
- grep "Published: " "$STATE_FILE" > /dev/null && log_error "unexpected publish in $STATE_FILE"
+ if [ "$_legacy" == "no" ]; then
+ grep "Published: " "$STATE_FILE" > /dev/null && log_error "unexpected publish in $STATE_FILE"
+ fi
else
- grep "; Publish:" "$KEY_FILE" > /dev/null || log_error "mismatch publish comment in $KEY_FILE ($KEY_PUBLISHED)"
- grep "Publish:" "$PRIVATE_FILE" > /dev/null || log_error "mismatch publish in $PRIVATE_FILE ($KEY_PUBLISHED)"
- grep "Published:" "$STATE_FILE" > /dev/null || log_error "mismatch publish in $STATE_FILE ($KEY_PUBLISHED)"
+ grep "; Publish:" "$KEY_FILE" > /dev/null || log_error "mismatch publish comment in $KEY_FILE"
+ grep "Publish:" "$PRIVATE_FILE" > /dev/null || log_error "mismatch publish in $PRIVATE_FILE"
+ if [ "$_legacy" == "no" ]; then
+ grep "Published:" "$STATE_FILE" > /dev/null || log_error "mismatch publish in $STATE_FILE"
+ fi
fi
if [ "$_active" = "none" ]; then
grep "; Activate:" "$KEY_FILE" > /dev/null && log_error "unexpected active comment in $KEY_FILE"
grep "Activate:" "$PRIVATE_FILE" > /dev/null && log_error "unexpected active in $PRIVATE_FILE"
- grep "Active: " "$STATE_FILE" > /dev/null && log_error "unexpected active in $STATE_FILE"
+ if [ "$_legacy" == "no" ]; then
+ grep "Active: " "$STATE_FILE" > /dev/null && log_error "unexpected active in $STATE_FILE"
+ fi
else
grep "; Activate:" "$KEY_FILE" > /dev/null || log_error "mismatch active comment in $KEY_FILE"
grep "Activate:" "$PRIVATE_FILE" > /dev/null || log_error "mismatch active in $PRIVATE_FILE"
- grep "Active: " "$STATE_FILE" > /dev/null || log_error "mismatch active in $STATE_FILE"
+ if [ "$_legacy" == "no" ]; then
+ grep "Active: " "$STATE_FILE" > /dev/null || log_error "mismatch active in $STATE_FILE"
+ fi
fi
if [ "$_retired" = "none" ]; then
grep "; Inactive:" "$KEY_FILE" > /dev/null && log_error "unexpected retired comment in $KEY_FILE"
grep "Inactive:" "$PRIVATE_FILE" > /dev/null && log_error "unexpected retired in $PRIVATE_FILE"
- grep "Retired: " "$STATE_FILE" > /dev/null && log_error "unexpected retired in $STATE_FILE"
+ if [ "$_legacy" == "no" ]; then
+ grep "Retired: " "$STATE_FILE" > /dev/null && log_error "unexpected retired in $STATE_FILE"
+ fi
else
grep "; Inactive:" "$KEY_FILE" > /dev/null || log_error "mismatch retired comment in $KEY_FILE"
grep "Inactive:" "$PRIVATE_FILE" > /dev/null || log_error "mismatch retired in $PRIVATE_FILE"
- grep "Retired: " "$STATE_FILE" > /dev/null || log_error "mismatch retired in $STATE_FILE"
+ if [ "$_legacy" == "no" ]; then
+ grep "Retired: " "$STATE_FILE" > /dev/null || log_error "mismatch retired in $STATE_FILE"
+ fi
fi
if [ "$_revoked" = "none" ]; then
grep "; Revoke:" "$KEY_FILE" > /dev/null && log_error "unexpected revoked comment in $KEY_FILE"
grep "Revoke:" "$PRIVATE_FILE" > /dev/null && log_error "unexpected revoked in $PRIVATE_FILE"
- grep "Revoked: " "$STATE_FILE" > /dev/null && log_error "unexpected revoked in $STATE_FILE"
+ if [ "$_legacy" == "no" ]; then
+ grep "Revoked: " "$STATE_FILE" > /dev/null && log_error "unexpected revoked in $STATE_FILE"
+ fi
else
grep "; Revoke:" "$KEY_FILE" > /dev/null || log_error "mismatch revoked comment in $KEY_FILE"
grep "Revoke:" "$PRIVATE_FILE" > /dev/null || log_error "mismatch revoked in $PRIVATE_FILE"
- grep "Revoked: " "$STATE_FILE" > /dev/null || log_error "mismatch revoked in $STATE_FILE"
+ if [ "$_legacy" == "no" ]; then
+ grep "Revoked: " "$STATE_FILE" > /dev/null || log_error "mismatch revoked in $STATE_FILE"
+ fi
fi
if [ "$_removed" = "none" ]; then
grep "; Delete:" "$KEY_FILE" > /dev/null && log_error "unexpected removed comment in $KEY_FILE"
grep "Delete:" "$PRIVATE_FILE" > /dev/null && log_error "unexpected removed in $PRIVATE_FILE"
- grep "Removed: " "$STATE_FILE" > /dev/null && log_error "unexpected removed in $STATE_FILE"
+ if [ "$_legacy" == "no" ]; then
+ grep "Removed: " "$STATE_FILE" > /dev/null && log_error "unexpected removed in $STATE_FILE"
+ fi
else
grep "; Delete:" "$KEY_FILE" > /dev/null || log_error "mismatch removed comment in $KEY_FILE"
grep "Delete:" "$PRIVATE_FILE" > /dev/null || log_error "mismatch removed in $PRIVATE_FILE"
- grep "Removed: " "$STATE_FILE" > /dev/null || log_error "mismatch removed in $STATE_FILE"
+ if [ "$_legacy" == "no" ]; then
+ grep "Removed: " "$STATE_FILE" > /dev/null || log_error "mismatch removed in $STATE_FILE"
+ fi
fi
grep "; Created:" "$KEY_FILE" > /dev/null || log_error "mismatch created comment in $KEY_FILE"
grep "Created:" "$PRIVATE_FILE" > /dev/null || log_error "mismatch created in $PRIVATE_FILE"
- grep "Generated: " "$STATE_FILE" > /dev/null || log_error "mismatch generated in $STATE_FILE"
+ if [ "$_legacy" == "no" ]; then
+ grep "Generated: " "$STATE_FILE" > /dev/null || log_error "mismatch generated in $STATE_FILE"
+ fi
}
# Check the key with key id $1 and see if it is unused.
# Check timing metadata.
grep "; Publish:" "$KEY_FILE" > /dev/null && log_error "unexpected publish comment in $KEY_FILE"
- grep "Publish:" "$PRIVATE_FILE" > /dev/null && log_error "unexpected publish in $PRIVATE_FILE"
- grep "Published: " "$STATE_FILE" > /dev/null && log_error "unexpected publish in $STATE_FILE"
grep "; Activate:" "$KEY_FILE" > /dev/null && log_error "unexpected active comment in $KEY_FILE"
- grep "Activate:" "$PRIVATE_FILE" > /dev/null && log_error "unexpected active in $PRIVATE_FILE"
- grep "Active: " "$STATE_FILE" > /dev/null && log_error "unexpected active in $STATE_FILE"
grep "; Inactive:" "$KEY_FILE" > /dev/null && log_error "unexpected retired comment in $KEY_FILE"
- grep "Inactive:" "$PRIVATE_FILE" > /dev/null && log_error "unexpected retired in $PRIVATE_FILE"
- grep "Retired: " "$STATE_FILE" > /dev/null && log_error "unexpected retired in $STATE_FILE"
grep "; Revoke:" "$KEY_FILE" > /dev/null && log_error "unexpected revoked comment in $KEY_FILE"
- grep "Revoke:" "$PRIVATE_FILE" > /dev/null && log_error "unexpected revoked in $PRIVATE_FILE"
- grep "Revoked: " "$STATE_FILE" > /dev/null && log_error "unexpected revoked in $STATE_FILE"
grep "; Delete:" "$KEY_FILE" > /dev/null && log_error "unexpected removed comment in $KEY_FILE"
+
+ grep "Publish:" "$PRIVATE_FILE" > /dev/null && log_error "unexpected publish in $PRIVATE_FILE"
+ grep "Activate:" "$PRIVATE_FILE" > /dev/null && log_error "unexpected active in $PRIVATE_FILE"
+ grep "Inactive:" "$PRIVATE_FILE" > /dev/null && log_error "unexpected retired in $PRIVATE_FILE"
+ grep "Revoke:" "$PRIVATE_FILE" > /dev/null && log_error "unexpected revoked in $PRIVATE_FILE"
grep "Delete:" "$PRIVATE_FILE" > /dev/null && log_error "unexpected removed in $PRIVATE_FILE"
- grep "Removed: " "$STATE_FILE" > /dev/null && log_error "unexpected removed in $STATE_FILE"
+
+ if [ "$_legacy" == "no" ]; then
+ grep "Published: " "$STATE_FILE" > /dev/null && log_error "unexpected publish in $STATE_FILE"
+ grep "Active: " "$STATE_FILE" > /dev/null && log_error "unexpected active in $STATE_FILE"
+ grep "Retired: " "$STATE_FILE" > /dev/null && log_error "unexpected retired in $STATE_FILE"
+ grep "Revoked: " "$STATE_FILE" > /dev/null && log_error "unexpected revoked in $STATE_FILE"
+ grep "Removed: " "$STATE_FILE" > /dev/null && log_error "unexpected removed in $STATE_FILE"
+ fi
}
# Test: dnssec-verify zone $1.
# interval.
check_next_key_event 3600
-# Reconfig dnssec-policy (triggering algorithm roll).
+#
+# Testing good migration.
+#
+set_zone "migrate.kasp"
+set_policy "none" "2" "300"
+set_server "ns6" "10.53.0.6"
+
+init_migration_match() {
+ key_clear "KEY1"
+ key_set "KEY1" "LEGACY" "yes"
+ set_keyrole "KEY1" "ksk"
+ set_keylifetime "KEY1" "0"
+ set_keyalgorithm "KEY1" "13" "ECDSAP256SHA256" "256"
+ set_keysigning "KEY1" "yes"
+ set_zonesigning "KEY1" "no"
+
+ key_clear "KEY2"
+ key_set "KEY2" "LEGACY" "yes"
+ set_keyrole "KEY2" "zsk"
+ set_keylifetime "KEY2" "5184000"
+ set_keyalgorithm "KEY2" "13" "ECDSAP256SHA256" "256"
+ set_keysigning "KEY2" "no"
+ set_zonesigning "KEY2" "yes"
+
+ key_clear "KEY3"
+ key_clear "KEY4"
+
+ set_keytime "KEY1" "PUBLISHED" "yes"
+ set_keytime "KEY1" "ACTIVE" "yes"
+ set_keytime "KEY1" "RETIRED" "none"
+ set_keystate "KEY1" "GOAL" "omnipresent"
+ set_keystate "KEY1" "STATE_DNSKEY" "rumoured"
+ set_keystate "KEY1" "STATE_KRRSIG" "rumoured"
+ set_keystate "KEY1" "STATE_DS" "rumoured"
+
+ set_keytime "KEY2" "PUBLISHED" "yes"
+ set_keytime "KEY2" "ACTIVE" "yes"
+ set_keytime "KEY2" "RETIRED" "none"
+ set_keystate "KEY2" "GOAL" "omnipresent"
+ set_keystate "KEY2" "STATE_DNSKEY" "rumoured"
+ set_keystate "KEY2" "STATE_ZRRSIG" "rumoured"
+}
+init_migration_match
+
+# Make sure the zone is signed with legacy keys.
+check_keys
+check_apex
+check_subdomain
+dnssec_verify
+
+# Remember legacy key tags.
+_migrate_ksk=$(key_get KEY1 ID)
+_migrate_zsk=$(key_get KEY2 ID)
+
+# Reconfig dnssec-policy (triggering algorithm roll and other dnssec-policy
+# changes).
echo_i "reconfig dnssec-policy to trigger algorithm rollover"
copy_setports ns6/named2.conf.in ns6/named.conf
rndc_reconfig ns6 10.53.0.6
next_key_event_threshold=$((next_key_event_threshold+i))
+#
+# Testing migration.
+#
+set_zone "migrate.kasp"
+set_policy "migrate" "2" "300"
+set_server "ns6" "10.53.0.6"
+
+# Key properties, timings and metadata should be the same as legacy keys above.
+# However, because the zsk has a lifetime, kasp will set the retired time.
+init_migration_match
+
+key_set "KEY1" "LEGACY" "no"
+
+key_set "KEY2" "LEGACY" "no"
+set_keytime "KEY2" "RETIRED" "yes"
+
+check_keys
+check_apex
+check_subdomain
+dnssec_verify
+
+# Check key tags, should be the same.
+n=$((n+1))
+echo_i "check that of zone ${ZONE} migration to dnssec-policy uses the same keys ($n)"
+ret=0
+[ $_migrate_ksk == $(key_get KEY1 ID) ] || log_error "mismatch ksk tag"
+[ $_migrate_zsk == $(key_get KEY2 ID) ] || log_error "mismatch zsk tag"
+status=$((status+ret))
+
#
# Testing KSK/ZSK algorithm rollover.
#
* Set key state to HIDDEN and change last changed to now,
* only if key state has not been set before.
*/
-#define INITIALIZE_STATE(key, state, time) \
+#define INITIALIZE_STATE(key, state, time, target) \
do { \
dst_key_state_t s; \
if (dst_key_getstate((key), (state), &s) == ISC_R_NOTFOUND) { \
isc_stdtime_t t; \
dst_key_gettime((key), DST_TIME_CREATED, &t); \
- dst_key_setstate((key), (state), HIDDEN); \
+ dst_key_setstate((key), (state), target); \
dst_key_settime((key), (time), t); \
} \
} while (0)
keymgr_prepublication_time(dns_dnsseckey_t *key, dns_kasp_t *kasp,
uint32_t lifetime, isc_stdtime_t now) {
isc_result_t ret;
- isc_stdtime_t active, retire, prepub;
+ isc_stdtime_t active, retire, pub, prepub;
bool ksk = false;
REQUIRE(key != NULL);
if (ret != ISC_R_SUCCESS) {
uint32_t klifetime = 0;
/*
- * An active key must have an activate timing metadata.
+ * An active key must have publish and activate timing
+ * metadata.
*/
ret = dst_key_gettime(key->key, DST_TIME_ACTIVATE, &active);
if (ret != ISC_R_SUCCESS) {
dst_key_settime(key->key, DST_TIME_ACTIVATE, now);
active = now;
}
+ ret = dst_key_gettime(key->key, DST_TIME_PUBLISH, &pub);
+ if (ret != ISC_R_SUCCESS) {
+ /* Super weird, but if it happens, set it to now. */
+ dst_key_settime(key->key, DST_TIME_PUBLISH, now);
+ pub = now;
+ }
ret = dst_key_getnum(key->key, DST_NUM_LIFETIME, &klifetime);
if (ret != ISC_R_SUCCESS) {
}
/*
- * See if this key needs to be initialized with a role. A key created and
- * derived from a dnssec-policy will have the required metadata available,
- * otherwise these may be missing and need to be initialized.
+ * See if this key needs to be initialized with properties. A key created
+ * and derived from a dnssec-policy will have the required metadata available,
+ * otherwise these may be missing and need to be initialized. The key states
+ * will be initialized according to existing timing metadata.
*
*/
static void
-keymgr_key_init_role(dns_dnsseckey_t *key) {
+keymgr_key_init(dns_dnsseckey_t *key, isc_stdtime_t now) {
bool ksk, zsk;
isc_result_t ret;
+ isc_stdtime_t active = 0, pub = 0, syncpub = 0;
+ dst_key_state_t dnskey_state = HIDDEN;
+ dst_key_state_t ds_state = HIDDEN;
+ dst_key_state_t zrrsig_state = HIDDEN;
REQUIRE(key != NULL);
REQUIRE(key->key != NULL);
+ /* Initialize role. */
ret = dst_key_getbool(key->key, DST_BOOL_KSK, &ksk);
if (ret != ISC_R_SUCCESS) {
ksk = ((dst_key_flags(key->key) & DNS_KEYFLAG_KSK) != 0);
zsk = ((dst_key_flags(key->key) & DNS_KEYFLAG_KSK) == 0);
dst_key_setbool(key->key, DST_BOOL_ZSK, zsk);
}
+
+ /* Get time metadata. */
+ ret = dst_key_gettime(key->key, DST_TIME_ACTIVATE, &active);
+ if (active <= now && ret == ISC_R_SUCCESS) {
+ dnskey_state = RUMOURED;
+ }
+ ret = dst_key_gettime(key->key, DST_TIME_PUBLISH, &pub);
+ if (pub <= now && ret == ISC_R_SUCCESS) {
+ zrrsig_state = RUMOURED;
+ }
+ ret = dst_key_gettime(key->key, DST_TIME_SYNCPUBLISH, &syncpub);
+ if (syncpub <= now && ret == ISC_R_SUCCESS) {
+ ds_state = RUMOURED;
+ }
+
+ /* Set key states for all keys that do not have them. */
+ INITIALIZE_STATE(key->key, DST_KEY_DNSKEY, DST_TIME_DNSKEY,
+ dnskey_state);
+ if (ksk) {
+ INITIALIZE_STATE(key->key, DST_KEY_KRRSIG, DST_TIME_KRRSIG,
+ dnskey_state);
+ INITIALIZE_STATE(key->key, DST_KEY_DS, DST_TIME_DS, ds_state);
+ }
+ if (zsk) {
+ INITIALIZE_STATE(key->key, DST_KEY_ZRRSIG, DST_TIME_ZRRSIG,
+ zrrsig_state);
+ }
}
/*
{
bool found_match = false;
- /* Make sure this key knows about roles. */
- keymgr_key_init_role(dkey);
+ keymgr_key_init(dkey, now);
for (kkey = ISC_LIST_HEAD(dns_kasp_keys(kasp)); kkey != NULL;
kkey = ISC_LIST_NEXT(kkey, link))
{
if (keymgr_dnsseckey_kaspkey_match(dkey, kkey)) {
found_match = true;
- dst_key_format(dkey->key, keystr,
- sizeof(keystr));
- isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC,
- DNS_LOGMODULE_DNSSEC,
- ISC_LOG_DEBUG(1),
- "keymgr: DNSKEY %s (%s) matches "
- "policy %s",
- keystr, keymgr_keyrole(dkey->key),
- dns_kasp_getname(kasp));
break;
}
}
{
if (keymgr_dnsseckey_kaspkey_match(dkey, kkey)) {
/* Found a match. */
+ dst_key_format(dkey->key, keystr,
+ sizeof(keystr));
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC,
+ DNS_LOGMODULE_DNSSEC,
+ ISC_LOG_DEBUG(1),
+ "keymgr: DNSKEY %s (%s) matches "
+ "policy %s",
+ keystr, keymgr_keyrole(dkey->key),
+ dns_kasp_getname(kasp));
- /* Initialize lifetime. */
+ /* Initialize lifetime and goal, if not set. */
uint32_t l;
if (dst_key_getnum(dkey->key, DST_NUM_LIFETIME,
&l) != ISC_R_SUCCESS) {
lifetime);
}
- if (dst_key_goal(dkey->key) == OMNIPRESENT) {
- if (active_key != NULL) {
+ dst_key_state_t goal;
+ if (dst_key_getstate(dkey->key, DST_KEY_GOAL,
+ &goal) != ISC_R_SUCCESS) {
+ dst_key_setstate(dkey->key,
+ DST_KEY_GOAL,
+ OMNIPRESENT);
+ }
+
+ if (active_key) {
+ /* We already have an active key that
+ * matches the kasp policy.
+ */
+ if (!dst_key_is_unused(dkey->key) &&
+ (dst_key_goal(dkey->key) ==
+ OMNIPRESENT) &&
+ !keymgr_key_is_successor(
+ dkey->key,
+ active_key->key) &&
+ !keymgr_key_is_successor(
+ active_key->key, dkey->key))
+ {
/*
* Multiple signing keys match
* the kasp key configuration.
- * Retire excess keys.
+ * Retire excess keys in use.
*/
keymgr_key_retire(dkey, now);
- } else {
- /* Save the matched key. */
- active_key = dkey;
}
+ continue;
+ }
+
+ /*
+ * Save the matched key only if it is active
+ * or desires to be active.
+ */
+ if (dst_key_goal(dkey->key) == OMNIPRESENT ||
+ dst_key_is_active(dkey->key, now)) {
+ active_key = dkey;
}
}
}
isc_log_write(
dns_lctx, DNS_LOGCATEGORY_DNSSEC,
DNS_LOGMODULE_DNSSEC, ISC_LOG_DEBUG(1),
- "keymgr: DNSKEY %s (%s) matches "
+ "keymgr: DNSKEY %s (%s) is active in "
"policy %s",
keystr, keymgr_keyrole(active_key->key),
dns_kasp_getname(kasp));
dst_key_setttl(dst_key, dns_kasp_dnskeyttl(kasp));
dst_key_settime(dst_key, DST_TIME_CREATED, now);
RETERR(dns_dnsseckey_create(mctx, &dst_key, &newkey));
+ keymgr_key_init(newkey, now);
} else {
newkey = candidate;
dst_key_setnum(newkey->key, DST_NUM_LIFETIME, lifetime);
ISC_LIST_APPENDLIST(*keyring, newkeys, link);
}
- /* Initialize key states (for keys that don't have them yet). */
- for (dns_dnsseckey_t *dkey = ISC_LIST_HEAD(*keyring); dkey != NULL;
- dkey = ISC_LIST_NEXT(dkey, link))
- {
- bool ksk = false, zsk = false;
-
- /* Set key states for all keys that do not have them. */
- INITIALIZE_STATE(dkey->key, DST_KEY_DNSKEY, DST_TIME_DNSKEY);
- (void)dst_key_getbool(dkey->key, DST_BOOL_KSK, &ksk);
- if (ksk) {
- INITIALIZE_STATE(dkey->key, DST_KEY_KRRSIG,
- DST_TIME_KRRSIG);
- INITIALIZE_STATE(dkey->key, DST_KEY_DS, DST_TIME_DS);
- }
- (void)dst_key_getbool(dkey->key, DST_BOOL_ZSK, &zsk);
- if (zsk) {
- INITIALIZE_STATE(dkey->key, DST_KEY_ZRRSIG,
- DST_TIME_ZRRSIG);
- }
- }
-
/* Read to update key states. */
keymgr_update(keyring, kasp, now, nexttime);