diff --git a/digest/src/lib.rs b/digest/src/lib.rs index b0febdf1a..6537d84a9 100644 --- a/digest/src/lib.rs +++ b/digest/src/lib.rs @@ -55,6 +55,7 @@ pub mod core_api; mod digest; #[cfg(feature = "mac")] mod mac; +mod xof_fixed; #[cfg(feature = "core-api")] pub use block_buffer; @@ -70,6 +71,7 @@ pub use crypto_common::{InnerInit, InvalidLength, Key, KeyInit}; pub use crypto_common::{Output, OutputSizeUser, Reset, array, typenum, typenum::consts}; #[cfg(feature = "mac")] pub use mac::{CtOutput, Mac, MacError, MacMarker}; +pub use xof_fixed::XofFixedWrapper; use core::fmt; diff --git a/digest/src/xof_fixed.rs b/digest/src/xof_fixed.rs new file mode 100644 index 000000000..d852904bf --- /dev/null +++ b/digest/src/xof_fixed.rs @@ -0,0 +1,146 @@ +use core::fmt; +use core::marker::PhantomData; + +use crypto_common::array::ArraySize; +use crypto_common::hazmat::SerializableState; +use crypto_common::{BlockSizeUser, KeyInit, KeySizeUser, OutputSizeUser, Reset}; + +use crate::{ + CustomizedInit, ExtendableOutput, ExtendableOutputReset, FixedOutput, FixedOutputReset, + HashMarker, Update, +}; + +/// Wrapper around [`ExtendableOutput`] types adding [`OutputSizeUser`] with the given size of `S`. +pub struct XofFixedWrapper { + hash: T, + size: PhantomData, +} + +impl Clone for XofFixedWrapper { + fn clone(&self) -> Self { + Self { + hash: self.hash.clone(), + size: PhantomData, + } + } +} + +impl fmt::Debug for XofFixedWrapper { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("XofFixedWrapper") + .field("hash", &self.hash) + .field("_size", &self.size) + .finish() + } +} + +impl Default for XofFixedWrapper { + fn default() -> Self { + Self { + hash: Default::default(), + size: PhantomData, + } + } +} + +impl HashMarker for XofFixedWrapper {} + +#[cfg(feature = "mac")] +impl crate::MacMarker + for XofFixedWrapper +{ +} + +// this blanket impl is needed for HMAC +impl BlockSizeUser for XofFixedWrapper { + type BlockSize = T::BlockSize; +} + +impl KeySizeUser for XofFixedWrapper { + type KeySize = T::KeySize; +} + +impl KeyInit for XofFixedWrapper { + fn new(key: &crypto_common::Key) -> Self { + Self { + hash: T::new(key), + size: PhantomData, + } + } +} + +impl Reset for XofFixedWrapper { + fn reset(&mut self) { + self.hash.reset(); + } +} + +impl Update for XofFixedWrapper { + fn update(&mut self, data: &[u8]) { + self.hash.update(data) + } +} + +impl OutputSizeUser for XofFixedWrapper { + type OutputSize = S; +} + +impl FixedOutput for XofFixedWrapper { + fn finalize_into(self, out: &mut crypto_common::Output) { + self.hash.finalize_xof_into(out); + } +} + +impl FixedOutputReset for XofFixedWrapper { + fn finalize_into_reset(&mut self, out: &mut crypto_common::Output) { + self.hash.finalize_xof_reset_into(out); + } +} + +impl ExtendableOutput for XofFixedWrapper { + type Reader = T::Reader; + + fn finalize_xof(self) -> Self::Reader { + self.hash.finalize_xof() + } +} + +impl ExtendableOutputReset for XofFixedWrapper { + fn finalize_xof_reset(&mut self) -> Self::Reader { + self.hash.finalize_xof_reset() + } +} + +#[cfg(feature = "zeroize")] +impl zeroize::ZeroizeOnDrop + for XofFixedWrapper +{ +} + +impl CustomizedInit for XofFixedWrapper { + fn new_customized(customization: &[u8]) -> Self { + Self { + hash: T::new_customized(customization), + size: PhantomData, + } + } +} + +impl SerializableState + for XofFixedWrapper +{ + type SerializedStateSize = T::SerializedStateSize; + + fn serialize(&self) -> crypto_common::hazmat::SerializedState { + self.hash.serialize() + } + + fn deserialize( + serialized_state: &crypto_common::hazmat::SerializedState, + ) -> Result { + T::deserialize(serialized_state).map(|hash| Self { + hash, + size: PhantomData, + }) + } +}