From 76ecde48af58ad444a4619b9ff1325e3bbc84bc2 Mon Sep 17 00:00:00 2001 From: Matthijs Mekking Date: Tue, 19 Aug 2025 12:37:29 +0200 Subject: [PATCH] Force full sign to generate new signatures When introducing the kasp logic, a full sign of the zone did not generate new signatures for the new active keys during a ZSK rollover. The introduced kasp logic ensured that the rollover is performed smoothly, as in the signatures are only replaced if the old signature is close to expiring (depending on the signatures-refresh option). Fix by maintaining a fullsign boolean value in the signing structure, that will ensure the RRsets are signed with the correct key, rather than a similar good key. In case of a fullsign, we can also remove signatures from inactive keys. Remove the unused dns_zone_signwithkey function. (cherry picked from commit 844bde0c70bca83f9f46d1b6356804c0a44e9dcd) --- lib/dns/include/dns/zone.h | 8 ----- lib/dns/zone.c | 65 +++++++++++++++++++++----------------- 2 files changed, 36 insertions(+), 37 deletions(-) diff --git a/lib/dns/include/dns/zone.h b/lib/dns/include/dns/zone.h index b83e447f01..e5d99e4d3f 100644 --- a/lib/dns/include/dns/zone.h +++ b/lib/dns/include/dns/zone.h @@ -2301,14 +2301,6 @@ dns_zone_getsignatures(dns_zone_t *zone); * Get the number of signatures that will be generated per quantum. */ -isc_result_t -dns_zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, uint16_t keyid, - bool deleteit); -/*%< - * Initiate/resume signing of the entire zone with the zone DNSKEY(s) - * that match the given algorithm and keyid. - */ - isc_result_t dns_zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param); /*%< diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 1b20918f43..09cf734eaa 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -750,6 +750,7 @@ struct dns_signing { dns_secalg_t algorithm; uint16_t keyid; bool deleteit; + bool fullsign; bool done; ISC_LINK(dns_signing_t) link; }; @@ -992,7 +993,7 @@ static void dump_done(void *arg, isc_result_t result); static isc_result_t zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, uint16_t keyid, - bool deleteit); + bool deleteit, bool fullsign); static isc_result_t delete_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node, dns_name_t *name, dns_diff_t *diff); @@ -3678,7 +3679,7 @@ resume_signingwithkey(dns_zone_t *zone) { result = zone_signwithkey(zone, rdata.data[0], (rdata.data[1] << 8) | rdata.data[2], - rdata.data[3]); + rdata.data[3], false); if (result != ISC_R_SUCCESS) { dnssec_log(zone, ISC_LOG_ERROR, "zone_signwithkey failed: %s", @@ -7505,7 +7506,7 @@ failure: static bool signed_with_good_key(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, dns_rdatatype_t type, - dst_key_t *key) { + dst_key_t *key, bool fullsign) { isc_result_t result; dns_rdataset_t rdataset; dns_rdata_t rdata = DNS_RDATA_INIT; @@ -7538,7 +7539,7 @@ signed_with_good_key(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node, dns_rdata_reset(&rdata); } - if (zone->kasp != NULL) { + if (zone->kasp != NULL && !fullsign) { dns_kasp_key_t *kkey; int zsk_count = 0; bool approved; @@ -7650,8 +7651,9 @@ sign_a_node(dns_db_t *db, dns_zone_t *zone, dns_name_t *name, dns_dbnode_t *node, dns_dbversion_t *version, bool build_nsec3, bool build_nsec, dst_key_t *key, isc_stdtime_t now, isc_stdtime_t inception, isc_stdtime_t expire, dns_ttl_t nsecttl, - bool both, bool is_ksk, bool is_zsk, bool is_bottom_of_zone, - dns_diff_t *diff, int32_t *signatures, isc_mem_t *mctx) { + bool both, bool is_ksk, bool is_zsk, bool fullsign, + bool is_bottom_of_zone, dns_diff_t *diff, int32_t *signatures, + isc_mem_t *mctx) { isc_result_t result; dns_rdatasetiter_t *iterator = NULL; dns_rdataset_t rdataset; @@ -7762,7 +7764,7 @@ sign_a_node(dns_db_t *db, dns_zone_t *zone, dns_name_t *name, goto next_rdataset; } if (signed_with_good_key(zone, db, node, version, rdataset.type, - key)) + key, fullsign)) { goto next_rdataset; } @@ -9816,8 +9818,8 @@ zone_sign(dns_zone_t *zone) { db, zone, name, node, version, build_nsec3, build_nsec, zone_keys[i], now, inception, expire, zone_nsecttl(zone), both, is_ksk, - is_zsk, is_bottom_of_zone, zonediff.diff, - &signatures, zone->mctx)); + is_zsk, signing->fullsign, is_bottom_of_zone, + zonediff.diff, &signatures, zone->mctx)); /* * If we are adding we are done. Look for other keys * of the same algorithm if deleting. @@ -20412,22 +20414,6 @@ dns_zone_setnotifydelay(dns_zone_t *zone, uint32_t delay) { UNLOCK_ZONE(zone); } -isc_result_t -dns_zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, uint16_t keyid, - bool deleteit) { - isc_result_t result; - REQUIRE(DNS_ZONE_VALID(zone)); - - dnssec_log(zone, ISC_LOG_NOTICE, - "dns_zone_signwithkey(algorithm=%u, keyid=%u)", algorithm, - keyid); - LOCK_ZONE(zone); - result = zone_signwithkey(zone, algorithm, keyid, deleteit); - UNLOCK_ZONE(zone); - - return result; -} - /* * Called when a dynamic update for an NSEC3PARAM record is received. * @@ -20499,7 +20485,7 @@ dns_zone_getprivatetype(dns_zone_t *zone) { static isc_result_t zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, uint16_t keyid, - bool deleteit) { + bool deleteit, bool fullsign) { dns_signing_t *signing; dns_signing_t *current; isc_result_t result = ISC_R_SUCCESS; @@ -20514,6 +20500,7 @@ zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, uint16_t keyid, signing->algorithm = algorithm; signing->keyid = keyid; signing->deleteit = deleteit; + signing->fullsign = fullsign; signing->done = false; now = isc_time_now(); @@ -22952,7 +22939,7 @@ zone_rekey(dns_zone_t *zone) { { result = zone_signwithkey( zone, dst_key_alg(key->key), - dst_key_id(key->key), true); + dst_key_id(key->key), true, false); if (result != ISC_R_SUCCESS) { dnssec_log(zone, ISC_LOG_ERROR, "zone_signwithkey failed: " @@ -22992,7 +22979,7 @@ zone_rekey(dns_zone_t *zone) { result = zone_signwithkey( zone, dst_key_alg(key->key), - dst_key_id(key->key), false); + dst_key_id(key->key), false, true); if (result != ISC_R_SUCCESS) { dnssec_log(zone, ISC_LOG_ERROR, "zone_signwithkey failed: " @@ -23000,6 +22987,26 @@ zone_rekey(dns_zone_t *zone) { isc_result_totext(result)); } } + /* + * ...and remove signatures for all inactive keys. + */ + ISC_LIST_FOREACH(dnskeys, key, link) { + if (!key->force_sign && !key->hint_sign) { + result = zone_signwithkey( + zone, dst_key_alg(key->key), + dst_key_id(key->key), true, + false); + if (result != ISC_R_SUCCESS) { + dnssec_log(zone, ISC_LOG_ERROR, + "zone_signwithkey " + "failed: " + "%s", + isc_result_totext( + result)); + } + } + } + } else if (newalg) { /* * We haven't been told to sign fully, but a new @@ -23016,7 +23023,7 @@ zone_rekey(dns_zone_t *zone) { result = zone_signwithkey( zone, dst_key_alg(key->key), - dst_key_id(key->key), false); + dst_key_id(key->key), false, false); if (result != ISC_R_SUCCESS) { dnssec_log(zone, ISC_LOG_ERROR, "zone_signwithkey failed: "