diff options
Diffstat (limited to 'src/knot/dnssec/zone-sign.c')
-rw-r--r-- | src/knot/dnssec/zone-sign.c | 34 |
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; } /*! |