use alloc::vec;
use core::cmp::{self, Ordering};
-use ring::signature;
-
use crate::base32;
use crate::crypto;
use crate::rr::*;
Invalid,
}
-pub(crate) fn bytes_to_rsa_pk<'a>(pubkey: &'a [u8])
--> Result<signature::RsaPublicKeyComponents<&'a [u8]>, ()> {
- if pubkey.len() <= 3 { return Err(()); }
-
- let mut pos = 0;
- let exponent_length;
- if pubkey[0] == 0 {
- exponent_length = ((pubkey[1] as usize) << 8) | (pubkey[2] as usize);
- pos += 3;
- } else {
- exponent_length = pubkey[0] as usize;
- pos += 1;
- }
-
- if pubkey.len() <= pos + exponent_length { return Err(()); }
- Ok(signature::RsaPublicKeyComponents {
- n: &pubkey[pos + exponent_length..],
- e: &pubkey[pos..pos + exponent_length]
- })
-}
-
-fn verify_rrsig<'a, RR: Record, Keys>(sig: &RRSig, dnskeys: Keys, mut records: Vec<&RR>)
+fn verify_rrsig<'a, RR: WriteableRecord, Keys>(sig: &RRSig, dnskeys: Keys, mut records: Vec<&RR>)
-> Result<(), ValidationError>
where Keys: IntoIterator<Item = &'a DnsKey> {
for record in records.iter() {
if dnskey.flags & 0b1_0000_0000 == 0 { continue; }
if dnskey.alg != sig.alg { continue; }
- let mut signed_data = Vec::with_capacity(2048);
- signed_data.extend_from_slice(&sig.ty.to_be_bytes());
- signed_data.extend_from_slice(&sig.alg.to_be_bytes());
- signed_data.extend_from_slice(&sig.labels.to_be_bytes());
- signed_data.extend_from_slice(&sig.orig_ttl.to_be_bytes());
- signed_data.extend_from_slice(&sig.expiration.to_be_bytes());
- signed_data.extend_from_slice(&sig.inception.to_be_bytes());
- signed_data.extend_from_slice(&sig.key_tag.to_be_bytes());
- write_name(&mut signed_data, &sig.key_name);
+ let mut hash_ctx = match sig.alg {
+ 8 => crypto::hash::Hasher::sha256(),
+ 10 => crypto::hash::Hasher::sha512(),
+ 13 => crypto::hash::Hasher::sha256(),
+ 14 => crypto::hash::Hasher::sha384(),
+ 15 => crypto::hash::Hasher::sha512(),
+ _ => return Err(ValidationError::UnsupportedAlgorithm),
+ };
+
+ hash_ctx.update(&sig.ty.to_be_bytes());
+ hash_ctx.update(&sig.alg.to_be_bytes());
+ hash_ctx.update(&sig.labels.to_be_bytes());
+ hash_ctx.update(&sig.orig_ttl.to_be_bytes());
+ hash_ctx.update(&sig.expiration.to_be_bytes());
+ hash_ctx.update(&sig.inception.to_be_bytes());
+ hash_ctx.update(&sig.key_tag.to_be_bytes());
+ write_name(&mut hash_ctx, &sig.key_name);
records.sort_unstable();
let signed_name = record.name().trailing_n_labels(sig.labels);
debug_assert!(signed_name.is_some());
if let Some(name) = signed_name {
- signed_data.extend_from_slice(b"\x01*");
- write_name(&mut signed_data, name);
+ hash_ctx.update(b"\x01*");
+ write_name(&mut hash_ctx, name);
} else { return Err(ValidationError::Invalid); }
} else {
- write_name(&mut signed_data, record.name());
+ write_name(&mut hash_ctx, record.name());
}
- signed_data.extend_from_slice(&record.ty().to_be_bytes());
- signed_data.extend_from_slice(&1u16.to_be_bytes()); // The INternet class
- signed_data.extend_from_slice(&sig.orig_ttl.to_be_bytes());
- record.write_u16_len_prefixed_data(&mut signed_data);
+ hash_ctx.update(&record.ty().to_be_bytes());
+ hash_ctx.update(&1u16.to_be_bytes()); // The INternet class
+ hash_ctx.update(&sig.orig_ttl.to_be_bytes());
+ record.serialize_u16_len_prefixed(&mut hash_ctx);
}
+ let hash = hash_ctx.finish();
let sig_validation = match sig.alg {
- 8|10 => {
- let alg = if sig.alg == 8 {
- &signature::RSA_PKCS1_1024_8192_SHA256_FOR_LEGACY_USE_ONLY
- } else {
- &signature::RSA_PKCS1_1024_8192_SHA512_FOR_LEGACY_USE_ONLY
- };
- bytes_to_rsa_pk(&dnskey.pubkey).map_err(|_| ValidationError::Invalid)?
- .verify(alg, &signed_data, &sig.signature)
- .map_err(|_| ValidationError::Invalid)
- },
- 13|14 => {
- let alg = if sig.alg == 13 {
- &signature::ECDSA_P256_SHA256_FIXED
- } else {
- &signature::ECDSA_P384_SHA384_FIXED
- };
-
- // Add 0x4 identifier to the ECDSA pubkey as expected by ring.
- let mut key = Vec::with_capacity(dnskey.pubkey.len() + 1);
- key.push(0x4);
- key.extend_from_slice(&dnskey.pubkey);
-
- signature::UnparsedPublicKey::new(alg, &key)
- .verify(&signed_data, &sig.signature)
- .map_err(|_| ValidationError::Invalid)
- },
- 15 => {
- signature::UnparsedPublicKey::new(&signature::ED25519, &dnskey.pubkey)
- .verify(&signed_data, &sig.signature)
- .map_err(|_| ValidationError::Invalid)
- },
+ 8|10 => crypto::rsa::validate_rsa(&dnskey.pubkey, &sig.signature, hash.as_ref())
+ .map_err(|_| ValidationError::Invalid),
+ 13 => crypto::secp256r1::validate_ecdsa(&dnskey.pubkey, &sig.signature, hash.as_ref())
+ .map_err(|_| ValidationError::Invalid),
+ 14 => crypto::secp384r1::validate_ecdsa(&dnskey.pubkey, &sig.signature, hash.as_ref())
+ .map_err(|_| ValidationError::Invalid),
+ // TODO: 15 => ED25519
_ => return Err(ValidationError::UnsupportedAlgorithm),
};
#[cfg(fuzzing)] {