From 0aacbde897980f8b67e9106ee7b2295f4d1dfd24 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Thu, 8 Feb 2024 23:53:29 +0000 Subject: [PATCH 1/1] Allow validating SHA1 DS records While these really shouldn't be used, they sometimes are, and importantly we don't allow them for RRSig signature validation, ensuring that if we find a SHA1 DS record it really is what was meant in the parent zone and wasn't forged. --- src/query.rs | 16 ++++++++++++++++ src/validation.rs | 6 ++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/query.rs b/src/query.rs index 6f68e09..adf687a 100644 --- a/src/query.rs +++ b/src/query.rs @@ -217,6 +217,22 @@ mod tests { assert!(verified_rrs.expires > now); } + #[test] + fn test_sha1_query() { + let sockaddr = "8.8.8.8:53".to_socket_addrs().unwrap().next().unwrap(); + let query_name = "benthecarman.com.".try_into().unwrap(); + let proof = build_a_proof(sockaddr, &query_name).unwrap(); + + let mut rrs = parse_rr_stream(&proof).unwrap(); + rrs.shuffle(&mut rand::rngs::OsRng); + let verified_rrs = verify_rr_stream(&rrs).unwrap(); + assert!(verified_rrs.verified_rrs.len() >= 1); + + let now = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_secs(); + assert!(verified_rrs.valid_from < now); + assert!(verified_rrs.expires > now); + } + #[test] fn test_txt_query() { let sockaddr = "8.8.8.8:53".to_socket_addrs().unwrap().next().unwrap(); diff --git a/src/validation.rs b/src/validation.rs index 999f787..615146e 100644 --- a/src/validation.rs +++ b/src/validation.rs @@ -162,7 +162,7 @@ where T: IntoIterator, I: Iterator + Clone { let mut had_ds = false; for ds in dses.clone() { had_ds = true; - if ds.digest_type == 2 || ds.digest_type == 4 { + if ds.digest_type == 1 || ds.digest_type == 2 || ds.digest_type == 4 { had_known_digest_type = true; break; } @@ -171,11 +171,13 @@ where T: IntoIterator, I: Iterator + Clone { if !had_known_digest_type { return Err(ValidationError::UnsupportedAlgorithm); } for dnskey in records.iter() { + // Only use SHA1 DS records if we don't have any SHA256/SHA384 DS RRs. + let trust_sha1 = dses.clone().all(|ds| ds.digest_type != 2 && ds.digest_type != 4); for ds in dses.clone() { - if ds.digest_type != 2 && ds.digest_type != 4 { continue; } if ds.alg != dnskey.alg { continue; } if dnskey.key_tag() == ds.key_tag { let alg = match ds.digest_type { + 1 if trust_sha1 => &ring::digest::SHA1_FOR_LEGACY_USE_ONLY, 2 => &ring::digest::SHA256, 4 => &ring::digest::SHA384, _ => continue, -- 2.30.2