From 96bef440f36a9da9a4b7b3ccfdb6b0f102bd6050 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2=20=5BArtyom=20Pavlov=5D?= Date: Fri, 25 Jul 2025 15:40:52 +0300 Subject: [PATCH 1/4] Migrate to const blobby parsing --- Cargo.lock | 25 +++++++-------- Cargo.toml | 5 +++ blake2/tests/mac.rs | 10 +++--- sha3/tests/cshake.rs | 69 ++++++++++++++++++++-------------------- sha3/tests/turboshake.rs | 30 +++++++++++------ 5 files changed, 78 insertions(+), 61 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0e749de8c..e0e4bc7e7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -57,8 +57,7 @@ dependencies = [ [[package]] name = "blobby" version = "0.4.0-pre.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a859067dcb257cb2ae028cb821399b55140b76fb8b2a360e052fe109019db43" +source = "git+https://github.com/RustCrypto/utils#1227836d92c56dce5fddb3ed36003277f053267b" [[package]] name = "block-buffer" @@ -94,8 +93,7 @@ dependencies = [ [[package]] name = "crypto-common" version = "0.2.0-rc.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a23fa214dea9efd4dacee5a5614646b30216ae0f05d4bb51bafb50e9da1c5be" +source = "git+https://github.com/RustCrypto/traits?branch=const_blobby#c47895ce9a1859f13b082740c13913a102e55727" dependencies = [ "hybrid-array", ] @@ -103,8 +101,7 @@ dependencies = [ [[package]] name = "digest" version = "0.11.0-rc.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "460dd7f37e4950526b54a5a6b1f41b6c8e763c58eb9a8fc8fc05ba5c2f44ca7b" +source = "git+https://github.com/RustCrypto/traits?branch=const_blobby#c47895ce9a1859f13b082740c13913a102e55727" dependencies = [ "blobby", "block-buffer", @@ -202,9 +199,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.172" +version = "0.2.174" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" +checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" [[package]] name = "md-5" @@ -364,9 +361,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.101" +version = "2.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" +checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" dependencies = [ "proc-macro2", "quote", @@ -414,18 +411,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.25" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb" +checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.25" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" +checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index c6411fa5a..1e57d8d93 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,3 +33,8 @@ opt-level = 2 sha1 = { path = "sha1" } sha3 = { path = "sha3" } whirlpool = { path = "whirlpool" } + +# https://github.com/RustCrypto/utils/pull/1187 +blobby = { git = "https://github.com/RustCrypto/utils" } +# https://github.com/RustCrypto/traits/pull/1916 +digest = { git = "https://github.com/RustCrypto/traits", branch = "const_blobby" } diff --git a/blake2/tests/mac.rs b/blake2/tests/mac.rs index 370fae092..c53f6ed97 100644 --- a/blake2/tests/mac.rs +++ b/blake2/tests/mac.rs @@ -1,10 +1,12 @@ #[cfg(not(feature = "reset"))] -use digest::new_mac_test as new_test; +use digest::dev::mac_test as test_fn; #[cfg(feature = "reset")] -use digest::new_resettable_mac_test as new_test; +use digest::dev::reset_mac_test as test_fn; -new_test!(blake2b_mac, "blake2b/mac", blake2::Blake2bMac512); -new_test!(blake2s_mac, "blake2s/mac", blake2::Blake2sMac256); +use digest::new_mac_test; + +new_mac_test!(blake2b_mac, "blake2b/mac", blake2::Blake2bMac512, test_fn); +new_mac_test!(blake2s_mac, "blake2s/mac", blake2::Blake2sMac256, test_fn); #[test] fn blake2b_new_test() { diff --git a/sha3/tests/cshake.rs b/sha3/tests/cshake.rs index c373f19ee..0ca4fb48f 100644 --- a/sha3/tests/cshake.rs +++ b/sha3/tests/cshake.rs @@ -1,12 +1,23 @@ -use core::fmt::Debug; use digest::{CustomizedInit, ExtendableOutputReset}; -pub(crate) fn cshake_reset_test(input: &[u8], output: &[u8], new: F) -> Option<&'static str> +#[derive(Debug, Clone, Copy)] +pub struct TestVector { + pub customization: &'static [u8], + pub input: &'static [u8], + pub output: &'static [u8], +} + +pub(crate) fn cshake_reset_test( + &TestVector { + customization, + input, + output, + }: &TestVector, +) -> Result<(), &'static str> where - D: ExtendableOutputReset + Debug + Clone, - F: Fn() -> D, + D: CustomizedInit + ExtendableOutputReset + Clone, { - let mut hasher = new(); + let mut hasher = D::new_customized(customization); let mut buf = [0u8; 1024]; let buf = &mut buf[..output.len()]; // Test that it works when accepting the message all at once @@ -14,7 +25,7 @@ where let mut hasher2 = hasher.clone(); hasher.finalize_xof_into(buf); if buf != output { - return Some("whole message"); + return Err("whole message"); } buf.iter_mut().for_each(|b| *b = 0); @@ -23,51 +34,51 @@ where hasher2.update(input); hasher2.finalize_xof_reset_into(buf); if buf != output { - return Some("whole message after reset"); + return Err("whole message after reset"); } buf.iter_mut().for_each(|b| *b = 0); // Test that it works when accepting the message in chunks for n in 1..core::cmp::min(17, input.len()) { - let mut hasher = new(); + let mut hasher = D::new_customized(customization); for chunk in input.chunks(n) { hasher.update(chunk); hasher2.update(chunk); } hasher.finalize_xof_into(buf); if buf != output { - return Some("message in chunks"); + return Err("message in chunks"); } buf.iter_mut().for_each(|b| *b = 0); hasher2.finalize_xof_reset_into(buf); if buf != output { - return Some("message in chunks"); + return Err("message in chunks"); } buf.iter_mut().for_each(|b| *b = 0); } - None + Ok(()) } macro_rules! new_cshake_test { - ($name:ident, $test_name:expr, $hasher:ty, $test_func:ident $(,)?) => { + ($name:ident, $test_name:expr, $hasher:ty $(,)?) => { #[test] fn $name() { - use digest::dev::blobby::Blob3Iterator; - let data = include_bytes!(concat!("data/", $test_name, ".blb")); + digest::dev::blobby::parse_into_structs!( + include_bytes!(concat!("data/", $test_name, ".blb")); + static TEST_VECTORS: &[TestVector { customization, input, output }]; + ); - for (i, row) in Blob3Iterator::new(data).unwrap().enumerate() { - let [customization, input, output] = row.unwrap(); - if let Some(desc) = - $test_func(input, output, || <$hasher>::new_customized(customization)) + for (i, tv) in TEST_VECTORS.iter().enumerate() { + if let Err(reason) = + cshake_reset_test::<$hasher>(tv) { panic!( "\n\ - Failed test №{}: {}\n\ - input:\t{:?}\n\ - output:\t{:?}\n", - i, desc, input, output, + Failed test #{i}\n\ + reason:\t{reason} + test vector:\t{tv:?}\n" ); } } @@ -75,15 +86,5 @@ macro_rules! new_cshake_test { }; } -new_cshake_test!( - cshake128_reset, - "cshake128", - sha3::CShake128, - cshake_reset_test -); -new_cshake_test!( - cshake256_reset, - "cshake256", - sha3::CShake256, - cshake_reset_test -); +new_cshake_test!(cshake128_reset, "cshake128", sha3::CShake128); +new_cshake_test!(cshake256_reset, "cshake256", sha3::CShake256); diff --git a/sha3/tests/turboshake.rs b/sha3/tests/turboshake.rs index 08a38c509..f350f3f92 100644 --- a/sha3/tests/turboshake.rs +++ b/sha3/tests/turboshake.rs @@ -1,11 +1,19 @@ use core::fmt::Debug; use digest::ExtendableOutput; +#[derive(Debug, Clone, Copy)] +pub struct TestVector { + pub input: &'static [u8], + pub input_pattern_length: &'static [u8], + pub output: &'static [u8], + pub truncate_output: &'static [u8], +} + pub(crate) fn turbo_shake_test( input: &[u8], output: &[u8], truncate_output: usize, -) -> Option<&'static str> +) -> Result<(), &'static str> where D: ExtendableOutput + Default + Debug + Clone, { @@ -17,7 +25,7 @@ where let mut hasher2 = hasher.clone(); hasher.finalize_xof_into(buf); if &buf[truncate_output..] != output { - return Some("whole message"); + return Err("whole message"); } buf.iter_mut().for_each(|b| *b = 0); @@ -30,23 +38,27 @@ where } hasher.finalize_xof_into(buf); if &buf[truncate_output..] != output { - return Some("message in chunks"); + return Err("message in chunks"); } buf.iter_mut().for_each(|b| *b = 0); } - None + Ok(()) } macro_rules! new_turbo_shake_test { ($name:ident, $test_name:expr, $hasher:ty, $test_func:ident $(,)?) => { #[test] fn $name() { - use digest::dev::blobby::Blob4Iterator; - let data = include_bytes!(concat!("data/", $test_name, ".blb")); + digest::dev::blobby::parse_into_structs!( + include_bytes!(concat!("data/", $test_name, ".blb")); + static TEST_VECTORS: &[TestVector { + input, input_pattern_length, output, truncate_output + }]; + ); - for (i, row) in Blob4Iterator::new(data).unwrap().enumerate() { - let [input, input_pattern_length, output, truncate_output] = row.unwrap(); + for (i, tv) in TEST_VECTORS.iter().enumerate() { + let &TestVector { input, input_pattern_length, output, truncate_output } = tv; let input = if (input_pattern_length.len() == 0) { input.to_vec() @@ -70,7 +82,7 @@ macro_rules! new_turbo_shake_test { println!("before func: {:?}", truncate_output.len()); - if let Some(desc) = $test_func::<$hasher>( + if let Err(desc) = $test_func::<$hasher>( &input, output, u64::from_be_bytes(truncate_output.try_into().unwrap()) From d718b5d2f59f5e5f0feaaf2024a886fef2413834 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2=20=5BArtyom=20Pavlov=5D?= Date: Mon, 11 Aug 2025 16:11:07 +0300 Subject: [PATCH 2/4] use `digest` from the master branch --- Cargo.lock | 14 +++++++------- Cargo.toml | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e0e4bc7e7..822ed1b6e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -57,7 +57,7 @@ dependencies = [ [[package]] name = "blobby" version = "0.4.0-pre.0" -source = "git+https://github.com/RustCrypto/utils#1227836d92c56dce5fddb3ed36003277f053267b" +source = "git+https://github.com/RustCrypto/utils#0e7e6e662608a3a862a4beb930b8ffedbea6563d" [[package]] name = "block-buffer" @@ -93,7 +93,7 @@ dependencies = [ [[package]] name = "crypto-common" version = "0.2.0-rc.3" -source = "git+https://github.com/RustCrypto/traits?branch=const_blobby#c47895ce9a1859f13b082740c13913a102e55727" +source = "git+https://github.com/RustCrypto/traits#832c889be55234ec3f6271d0b2133017a0f5703b" dependencies = [ "hybrid-array", ] @@ -101,7 +101,7 @@ dependencies = [ [[package]] name = "digest" version = "0.11.0-rc.0" -source = "git+https://github.com/RustCrypto/traits?branch=const_blobby#c47895ce9a1859f13b082740c13913a102e55727" +source = "git+https://github.com/RustCrypto/traits#832c889be55234ec3f6271d0b2133017a0f5703b" dependencies = [ "blobby", "block-buffer", @@ -199,9 +199,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.174" +version = "0.2.175" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" +checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" [[package]] name = "md-5" @@ -242,9 +242,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.95" +version = "1.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +checksum = "beef09f85ae72cea1ef96ba6870c51e6382ebfa4f0e85b643459331f3daa5be0" dependencies = [ "unicode-ident", ] diff --git a/Cargo.toml b/Cargo.toml index 1e57d8d93..fd79d2662 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,4 +37,4 @@ whirlpool = { path = "whirlpool" } # https://github.com/RustCrypto/utils/pull/1187 blobby = { git = "https://github.com/RustCrypto/utils" } # https://github.com/RustCrypto/traits/pull/1916 -digest = { git = "https://github.com/RustCrypto/traits", branch = "const_blobby" } +digest = { git = "https://github.com/RustCrypto/traits" } From b51624c68e4badd52d0be5e16e830373c1fd976e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2=20=5BArtyom=20Pavlov=5D?= Date: Mon, 11 Aug 2025 16:25:24 +0300 Subject: [PATCH 3/4] fix compilation error --- Cargo.lock | 3 +-- Cargo.toml | 1 + ascon-hash/src/lib.rs | 22 ++++++++++++++++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 822ed1b6e..aebad4dfb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -62,8 +62,7 @@ source = "git+https://github.com/RustCrypto/utils#0e7e6e662608a3a862a4beb930b8ff [[package]] name = "block-buffer" version = "0.11.0-rc.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a229bfd78e4827c91b9b95784f69492c1b77c1ab75a45a8a037b139215086f94" +source = "git+https://github.com/RustCrypto/utils#0e7e6e662608a3a862a4beb930b8ffedbea6563d" dependencies = [ "hybrid-array", "zeroize", diff --git a/Cargo.toml b/Cargo.toml index fd79d2662..8a6af534a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,3 +38,4 @@ whirlpool = { path = "whirlpool" } blobby = { git = "https://github.com/RustCrypto/utils" } # https://github.com/RustCrypto/traits/pull/1916 digest = { git = "https://github.com/RustCrypto/traits" } +block-buffer = { git = "https://github.com/RustCrypto/utils" } diff --git a/ascon-hash/src/lib.rs b/ascon-hash/src/lib.rs index 489fa878c..ab2d5b12b 100644 --- a/ascon-hash/src/lib.rs +++ b/ascon-hash/src/lib.rs @@ -73,6 +73,17 @@ struct HashCore { phantom: PhantomData

, } +#[cfg(feature = "zeroize")] +impl digest::zeroize::ZeroizeOnDrop for HashCore

{} + +#[allow(dead_code)] +const _: () = { + // State is the only field in AsconCore + fn check_core(v: &State) { + let _ = v as &dyn digest::zeroize::ZeroizeOnDrop; + } +}; + impl HashCore

{ fn absorb_block(&mut self, block: &[u8; 8]) { self.state[0] ^= u64::from_le_bytes(*block); @@ -195,6 +206,17 @@ impl SerializableState for AsconCore { } } +#[cfg(feature = "zeroize")] +impl digest::zeroize::ZeroizeOnDrop for AsconCore {} + +#[allow(dead_code)] +const _: () = { + // HashCore is the only field in AsconCore + fn check_core(v: &HashCore) { + let _ = v as &dyn digest::zeroize::ZeroizeOnDrop; + } +}; + /// Ascon XOF #[derive(Clone, Debug, Default)] pub struct AsconXofCore { From cc61a52269b28ffc9ecff30740f6b27f505f1acb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2=20=5BArtyom=20Pavlov=5D?= Date: Mon, 11 Aug 2025 16:27:18 +0300 Subject: [PATCH 4/4] Fix `ZeroizeOnDrop` check --- ascon-hash/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ascon-hash/src/lib.rs b/ascon-hash/src/lib.rs index ab2d5b12b..875eec2aa 100644 --- a/ascon-hash/src/lib.rs +++ b/ascon-hash/src/lib.rs @@ -77,6 +77,7 @@ struct HashCore { impl digest::zeroize::ZeroizeOnDrop for HashCore

{} #[allow(dead_code)] +#[cfg(feature = "zeroize")] const _: () = { // State is the only field in AsconCore fn check_core(v: &State) { @@ -210,6 +211,7 @@ impl SerializableState for AsconCore { impl digest::zeroize::ZeroizeOnDrop for AsconCore {} #[allow(dead_code)] +#[cfg(feature = "zeroize")] const _: () = { // HashCore is the only field in AsconCore fn check_core(v: &HashCore) {