Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 14 additions & 18 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,9 @@ 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" }
block-buffer = { git = "https://github.com/RustCrypto/utils" }
24 changes: 24 additions & 0 deletions ascon-hash/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,18 @@ struct HashCore<P: HashParameters> {
phantom: PhantomData<P>,
}

#[cfg(feature = "zeroize")]
impl<P: HashParameters> digest::zeroize::ZeroizeOnDrop for HashCore<P> {}

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

impl<P: HashParameters> HashCore<P> {
fn absorb_block(&mut self, block: &[u8; 8]) {
self.state[0] ^= u64::from_le_bytes(*block);
Expand Down Expand Up @@ -195,6 +207,18 @@ impl SerializableState for AsconCore {
}
}

#[cfg(feature = "zeroize")]
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<Parameters>) {
let _ = v as &dyn digest::zeroize::ZeroizeOnDrop;
}
};

/// Ascon XOF
#[derive(Clone, Debug, Default)]
pub struct AsconXofCore {
Expand Down
10 changes: 6 additions & 4 deletions blake2/tests/mac.rs
Original file line number Diff line number Diff line change
@@ -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() {
Expand Down
69 changes: 35 additions & 34 deletions sha3/tests/cshake.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,31 @@
use core::fmt::Debug;
use digest::{CustomizedInit, ExtendableOutputReset};

pub(crate) fn cshake_reset_test<D, F>(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<D>(
&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
hasher.update(input);
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);

Expand All @@ -23,67 +34,57 @@ 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"
);
}
}
}
};
}

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);
30 changes: 21 additions & 9 deletions sha3/tests/turboshake.rs
Original file line number Diff line number Diff line change
@@ -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<D>(
input: &[u8],
output: &[u8],
truncate_output: usize,
) -> Option<&'static str>
) -> Result<(), &'static str>
where
D: ExtendableOutput + Default + Debug + Clone,
{
Expand All @@ -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);

Expand All @@ -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()
Expand All @@ -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())
Expand Down
Loading