From: Karel Slany Date: Mon, 20 Jul 2015 13:54:17 +0000 (+0200) Subject: layer/validate: implemented kr_rrset_validate() X-Git-Tag: v1.0.0-beta1~53^2~147 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ee394661ea6a565a35ec5694da991398a19c35fa;p=thirdparty%2Fknot-resolver.git layer/validate: implemented kr_rrset_validate() --- diff --git a/lib/dnssec.c b/lib/dnssec.c index 1f3605a07..cce33c543 100644 --- a/lib/dnssec.c +++ b/lib/dnssec.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -114,20 +115,21 @@ fail: } /* RFC4035 5.3.1 */ -static int validate_rrsig_rr(const knot_rrset_t *rrset, const knot_rrset_t *rrsig, - const knot_rrset_t *keys, size_t pos, const dnssec_key_t *key, +static int validate_rrsig_rr(const knot_rrset_t *covered, + const knot_rrset_t *rrsigs, size_t sig_pos, + const knot_rrset_t *keys, size_t key_pos, const dnssec_key_t *key, const knot_dname_t *zone_name, uint32_t timestamp) { - if (!rrset || !rrsig || !keys || !key || !zone_name) { + if (!covered || !rrsigs || !keys || !key || !zone_name) { return kr_error(EINVAL); } #warning TODO: Make the comparison case-insensitive. /* bullet 1 */ - if ((rrset->rclass != rrsig->rclass) || (knot_dname_cmp(rrset->owner, rrsig->owner) != 0)) { + if ((covered->rclass != rrsigs->rclass) || (knot_dname_cmp(covered->owner, rrsigs->owner) != 0)) { return kr_error(EINVAL); } /* bullet 2 */ - const knot_dname_t *signer_name = knot_rrsig_signer_name(&rrsig->rrs, 0); + const knot_dname_t *signer_name = knot_rrsig_signer_name(&rrsigs->rrs, sig_pos); if (signer_name == NULL) { return kr_error(EINVAL); } @@ -135,26 +137,26 @@ static int validate_rrsig_rr(const knot_rrset_t *rrset, const knot_rrset_t *rrsi return kr_error(EINVAL); } /* bullet 3 */ - uint16_t tcovered = knot_rrsig_type_covered(&rrsig->rrs, 0); - if (tcovered != rrset->type) { + uint16_t tcovered = knot_rrsig_type_covered(&rrsigs->rrs, sig_pos); + if (tcovered != covered->type) { return kr_error(EINVAL); } /* bullet 4 */ - if (knot_rrsig_labels(&rrsig->rrs, 0) > knot_dname_labels(rrset->owner, NULL)) { + if (knot_rrsig_labels(&rrsigs->rrs, sig_pos) > knot_dname_labels(covered->owner, NULL)) { return kr_error(EINVAL); } /* bullet 5 */ - if (knot_rrsig_sig_expiration(&rrsig->rrs, 0) < timestamp) { + if (knot_rrsig_sig_expiration(&rrsigs->rrs, sig_pos) < timestamp) { return kr_error(EINVAL); } /* bullet 6 */ - if (knot_rrsig_sig_inception(&rrsig->rrs, 0) > timestamp) { + if (knot_rrsig_sig_inception(&rrsigs->rrs, sig_pos) > timestamp) { return kr_error(EINVAL); } /* bullet 7 */ if ((knot_dname_cmp(keys->owner, signer_name) != 0) || - (knot_dnskey_alg(&keys->rrs, pos) != knot_rrsig_algorithm(&rrsig->rrs, 0)) || - (dnssec_key_get_keytag(key) != knot_rrsig_key_tag(&rrsig->rrs, 0))) { + (knot_dnskey_alg(&keys->rrs, key_pos) != knot_rrsig_algorithm(&rrsigs->rrs, sig_pos)) || + (dnssec_key_get_keytag(key) != knot_rrsig_key_tag(&rrsigs->rrs, sig_pos))) { return kr_error(EINVAL); } /* bullet 8 */ @@ -269,7 +271,7 @@ static int sign_ctx_add_data(dnssec_sign_ctx_t *ctx, /* RFC4035 5.3.3 and 5.3.2 */ static int check_signature(const knot_rrset_t *rrsigs, size_t pos, - const dnssec_key_t *key, const dnssec_key_t *covered) + const dnssec_key_t *key, const knot_rrset_t *covered) { if (!rrsigs || !key || !dnssec_key_can_verify(key)) { return kr_error(EINVAL); @@ -278,7 +280,6 @@ static int check_signature(const knot_rrset_t *rrsigs, size_t pos, int ret; dnssec_sign_ctx_t *sign_ctx = NULL; dnssec_binary_t signature = {0, }; - dnssec_binary_t new_signed = {0, }; knot_rrsig_signature(&rrsigs->rrs, pos, &signature.data, &signature.size); if (!signature.data || !signature.size) { @@ -315,28 +316,44 @@ fail: return ret; } -/** Validate RRSet in canonical format. */ -static int crrset_validate(const knot_pktsection_t *sec, const knot_rrset_t *rrset, - const knot_rrset_t *keys, size_t pos, const dnssec_key_t *key, - const knot_dname_t *zone_name, uint32_t timestamp) +int kr_rrset_validate(const knot_pktsection_t *sec, const knot_rrset_t *covered, + const knot_rrset_t *keys, size_t key_pos, const struct dseckey *key, + const knot_dname_t *zone_name, uint32_t timestamp) { - int ret = kr_error(KNOT_DNSSEC_ENOKEY); + int ret; + struct dseckey *created_key = NULL; + if (key == NULL) { + const knot_rdata_t *krr = knot_rdataset_at(&keys->rrs, key_pos); + ret = kr_dnssec_key_from_rdata(&created_key, krr, keys->owner); + if (ret != 0) { + return ret; + } + key = created_key; + } + + ret = kr_error(KNOT_DNSSEC_ENOKEY); for (unsigned i = 0; i < sec->count; ++i) { /* Try every RRSIG. */ - const knot_rrset_t *rr = knot_pkt_rr(sec, i); - if (rr->type != KNOT_RRTYPE_RRSIG) { + const knot_rrset_t *rrsig = knot_pkt_rr(sec, i); + if (rrsig->type != KNOT_RRTYPE_RRSIG) { continue; } - if (validate_rrsig_rr(rrset, rr, keys, pos, key, zone_name, timestamp) != 0) { - continue; + for (uint16_t j = 0; j < rrsig->rrs.rr_count; ++j) { + if (validate_rrsig_rr(covered, rrsig, j, keys, key_pos, (dnssec_key_t *) key, zone_name, timestamp) != 0) { + continue; + } + if (check_signature(rrsig, j, (dnssec_key_t *) key, keys) != 0) { + continue; + } + ret = kr_ok(); + break; } - if (check_signature(rr, 0, key, keys) != 0) { - continue; + if (ret == kr_ok()) { + break; } - ret = kr_ok(); - break; } + kr_dnssec_key_free(&created_key); return ret; } @@ -370,7 +387,7 @@ int kr_dnskeys_trusted(const knot_pktsection_t *sec, const knot_rrset_t *keys, kr_dnssec_key_free(&key); continue; } - if (crrset_validate(sec, keys, keys, i, (dnssec_key_t *) key, zone_name, timestamp) != 0) { + if (kr_rrset_validate(sec, keys, keys, i, key, zone_name, timestamp) != 0) { kr_dnssec_key_free(&key); continue; } diff --git a/lib/dnssec.h b/lib/dnssec.h index f10cbc5db..e74dc04bb 100644 --- a/lib/dnssec.h +++ b/lib/dnssec.h @@ -34,11 +34,28 @@ void kr_crypto_cleanup(void); */ void kr_crypto_reinit(void); +/** Opaque DNSSEC key pointer. */ +struct dseckey; + +/** + * Validate RRSet. + * @param sec Packet section containing the RRSet to be validated. + * @param covered RRSet covered by a signature. It must be in canonical format. + * @param keys DNSKEY RRSet. + * @param key_pos Position of the key to be validated with. + * @param key Key to be used to validate. If NULL, then key from DNSKEY RRSet is used. + * @param zone_name Name of the zone containing the RRSIG RRSet. + * @param timestamp Validation time. + */ +int kr_rrset_validate(const knot_pktsection_t *sec, const knot_rrset_t *covered, + const knot_rrset_t *keys, size_t key_pos, const struct dseckey *key, + const knot_dname_t *zone_name, uint32_t timestamp); + /** * Check whether the DNSKEY rrset matches the supplied trust anchor RRSet. * @param sec Packet section containing the DNSKEY RRSet including its signatures. - * @param key DNSKEY RRSet to check. - * @param ta Trust anchor RRSet agains which to validate the DNSKEY. + * @param keys DNSKEY RRSet to check. + * @param ta Trust anchor RRSet against which to validate the DNSKEY RRSet. * @param zone_name Name of the zone containing the RRSet. * @param timestamp Time stamp. * @return 0 or error code. @@ -46,9 +63,6 @@ void kr_crypto_reinit(void); int kr_dnskeys_trusted(const knot_pktsection_t *sec, const knot_rrset_t *keys, const knot_rrset_t *ta, const knot_dname_t *zone_name, uint32_t timestamp); -/** Opaque DNSSEC key pointer. */ -struct dseckey; - /** * Construct a DNSSEC key. * @param key Pointer to be set to newly created DNSSEC key.