summaryrefslogtreecommitdiffstats
path: root/src/knot/dnssec/zone-sign.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/knot/dnssec/zone-sign.c')
-rw-r--r--src/knot/dnssec/zone-sign.c34
1 files changed, 26 insertions, 8 deletions
diff --git a/src/knot/dnssec/zone-sign.c b/src/knot/dnssec/zone-sign.c
index 9293c02..62f809e 100644
--- a/src/knot/dnssec/zone-sign.c
+++ b/src/knot/dnssec/zone-sign.c
@@ -89,6 +89,9 @@ static bool apex_dnssec_changed(zone_update_t *update)
/*- private API - signing of in-zone nodes -----------------------------------*/
+#define VALID_SIG_FOUND (1 << 7)
+#define VALID_KEYTAG_LIMIT 3
+
/*!
* \brief Check if there is a valid signature for a given RR set and key.
*
@@ -99,7 +102,8 @@ static bool apex_dnssec_changed(zone_update_t *update)
* \param policy DNSSEC policy.
* \param skip_crypto All RRSIGs in this node have been verified, just check validity.
* \param refresh Consider RRSIG expired when gonna expire this soon.
- * \param found_invalid Out: some matching but expired%invalid RRSIG found.
+ * \param invalid_map Out: found valid (bit VALID_SIG_FOUND) and invalid count
+ * positions of RRSIG with matching algo+keytag+type.
* \param at Out: RRSIG position.
*
* \return The signature exists and is valid.
@@ -111,7 +115,7 @@ static bool valid_signature_exists(const knot_rrset_t *covered,
const kdnssec_ctx_t *dnssec_ctx,
knot_timediff_t refresh,
bool skip_crypto,
- int *found_invalid,
+ uint8_t *invalid_map,
uint16_t *at)
{
assert(key);
@@ -141,13 +145,16 @@ static bool valid_signature_exists(const knot_rrset_t *covered,
if (at != NULL) {
*at = i;
}
- if (found_invalid == NULL) {
+ if (invalid_map == NULL) {
return true;
} else {
+ invalid_map[i] |= VALID_SIG_FOUND;
found_valid = true; // continue searching for invalid RRSIG
}
- } else if (found_invalid != NULL) {
- *found_invalid = ret;
+ } else if (invalid_map != NULL) {
+ if ((++invalid_map[i] & ~VALID_SIG_FOUND) == VALID_KEYTAG_LIMIT) {
+ return found_valid;
+ }
}
}
@@ -305,8 +312,10 @@ int knot_validate_rrsigs(const knot_rrset_t *covered,
return KNOT_EINVAL;
}
+ uint8_t val_inval_map[1 + rrsigs->rrs.count]; // Ensure the size isn't 0 (UBSAN).
+ memset(val_inval_map, 0, sizeof(val_inval_map));
+
bool valid_exists = false;
- int ret = KNOT_EOK;
for (size_t i = 0; i < sign_ctx->count; i++) {
const knot_kasp_key_t *key = &sign_ctx->dnssec_ctx->zone->keys[i];
if (!key_used(key->is_ksk, key->is_zsk, covered->type,
@@ -316,12 +325,21 @@ int knot_validate_rrsigs(const knot_rrset_t *covered,
uint16_t valid_at;
if (valid_signature_exists(covered, rrsigs, key->key, sign_ctx->sign_ctxs[i],
- sign_ctx->dnssec_ctx, 0, skip_crypto, &ret, &valid_at)) {
+ sign_ctx->dnssec_ctx, 0, skip_crypto, val_inval_map, &valid_at)) {
valid_exists = true;
}
}
- return valid_exists ? ret : KNOT_DNSSEC_ENOSIG;
+ for (int i = 0; i < rrsigs->rrs.count; i++) {
+ uint8_t val = val_inval_map[i];
+ if (val > 0 && val < VALID_KEYTAG_LIMIT /* found invalid && not found valid */) {
+ return KNOT_DNSSEC_ENOSIG;
+ } else if ((val & ~VALID_SIG_FOUND) >= VALID_KEYTAG_LIMIT) {
+ return KNOT_DNSSEC_EKEYTAG_LIMIT;
+ }
+ }
+
+ return valid_exists ? KNOT_EOK : KNOT_DNSSEC_ENOSIG;
}
/*!