Clean up and better comment math somewhat further
[dnssec-prover] / src / validation.rs
index e6b585fd44921c70b3c48a4f4e742f81423186bc..57ba096d53bd64169eb213fbaed47c7c31925da8 100644 (file)
@@ -5,8 +5,6 @@ use alloc::vec::Vec;
 use alloc::vec;
 use core::cmp::{self, Ordering};
 
-use ring::signature;
-
 use crate::base32;
 use crate::crypto;
 use crate::rr::*;
@@ -47,28 +45,7 @@ pub enum ValidationError {
        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() {
@@ -82,15 +59,23 @@ where Keys: IntoIterator<Item = &'a DnsKey> {
                        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();
 
@@ -106,50 +91,27 @@ where Keys: IntoIterator<Item = &'a DnsKey> {
                                        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)] {