From d4e95821aecc313f7c37879b7b133a5766172032 Mon Sep 17 00:00:00 2001 From: Vladimír Čunát Date: Thu, 20 Jan 2022 19:43:40 +0100 Subject: lib/dnssec: conditionally ignore SHA1 DS, as SHOULD by RFC4509 We're a bit late with this ad-hoc rule; I think it was most useful when SHA256 support in DS algorithms wasn't wide-spread yet. (Note that DNSKEY algos have standardized no similar rule.) Usage of SHA1 as DS algorithm is highly discouraged, but even at this point it does *not* seem unsafe, in the sense of anyone publishing an attack that would come anywhere close to breaking *this* usage of SHA1. --- lib/dnssec/signature.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) (limited to 'lib/dnssec/signature.c') diff --git a/lib/dnssec/signature.c b/lib/dnssec/signature.c index 6fcf3a42..062067a0 100644 --- a/lib/dnssec/signature.c +++ b/lib/dnssec/signature.c @@ -47,18 +47,34 @@ int kr_authenticate_referral(const knot_rrset_t *ref, const dnssec_key_t *key) if (ref->type != KNOT_RRTYPE_DS) return kr_error(EINVAL); - /* Try all possible DS records */ - int ret = 0; + /* Determine whether to ignore SHA1 digests, because: + https://datatracker.ietf.org/doc/html/rfc4509#section-3 + * Now, the RFCs seem to only mention SHA1 and SHA256 (e.g. no SHA384), + * but the most natural extension is to make any other algorithm trump SHA1. + * (Note that the old GOST version is already unsupported by libdnssec.) */ + bool skip_sha1 = false; knot_rdata_t *rd = ref->rrs.rdata; - for (uint16_t i = 0; i < ref->rrs.count; ++i) { + for (int i = 0; i < ref->rrs.count; ++i, rd = knot_rdataset_next(rd)) { + const uint8_t algo = knot_ds_digest_type(rd); + if (algo != DNSSEC_KEY_DIGEST_SHA1 && dnssec_algorithm_digest_support(algo)) { + skip_sha1 = true; + break; + } + } + /* But otherwise try all possible DS records. */ + int ret = 0; + rd = ref->rrs.rdata; + for (int i = 0; i < ref->rrs.count; ++i, rd = knot_rdataset_next(rd)) { + const uint8_t algo = knot_ds_digest_type(rd); + if (skip_sha1 && algo == DNSSEC_KEY_DIGEST_SHA1) + continue; dnssec_binary_t ds_rdata = { .size = rd->len, .data = rd->data }; - ret = authenticate_ds(key, &ds_rdata, knot_ds_digest_type(rd)); + ret = authenticate_ds(key, &ds_rdata, algo); if (ret == 0) /* Found a good DS */ return kr_ok(); - rd = knot_rdataset_next(rd); } return kr_error(ret); -- cgit v1.2.3