From 1e523fdd415597eaaa660fad675a116af0f4dc99 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Wed, 21 Feb 2024 07:08:20 +0000 Subject: [PATCH] Iteratively hash rather than building a vec then hashing ... in signature checking. Now that we control the signature checking API, we don't have to pass a full buffer and can build our own hashes, avoiding the allocation. --- src/validation.rs | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/src/validation.rs b/src/validation.rs index 692bb63..57ba096 100644 --- a/src/validation.rs +++ b/src/validation.rs @@ -45,7 +45,7 @@ pub enum ValidationError { Invalid, } -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 { for record in records.iter() { @@ -68,15 +68,14 @@ where Keys: IntoIterator { _ => return Err(ValidationError::UnsupportedAlgorithm), }; - 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); + 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(); @@ -92,19 +91,18 @@ where Keys: IntoIterator { 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); } - hash_ctx.update(&signed_data); let hash = hash_ctx.finish(); let sig_validation = match sig.alg { 8|10 => crypto::rsa::validate_rsa(&dnskey.pubkey, &sig.signature, hash.as_ref()) -- 2.30.2