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 844bde0c70)
This commit is contained in:
Matthijs Mekking 2025-08-19 12:37:29 +02:00
parent 44f36e2763
commit 76ecde48af
2 changed files with 36 additions and 37 deletions

View file

@ -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);
/*%<

View file

@ -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: "