-
Notifications
You must be signed in to change notification settings - Fork 228
digest: add buffering macros #1799
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 26 commits
Commits
Show all changes
35 commits
Select commit
Hold shift + click to select a range
bae5896
digest: add `newtype!` macro
newpavlov f86022a
Gate tests
newpavlov 5356490
Merge branch 'master' into digest/newtype
newpavlov 740b5fa
Remove outdated docs
newpavlov 1261c02
Remove `io::Write` impl
newpavlov 9938471
Merge branch 'master' into digest/newtype
newpavlov 6b9c5a9
Move dummy hash to the tests folder
newpavlov f4d7559
rename dummy to dummy fixed
newpavlov eb0f258
Add delegate template, improve macro robustness
newpavlov 4f68309
Add OID helper
newpavlov 3e59212
add ExtendableOutputHash template
newpavlov dbcd0bd
fix CustomizedInit delegation
newpavlov c0725f1
Introduce separate newtype macros
newpavlov 17c5263
Merge branch 'master' into digest/newtype
newpavlov 24d0f6a
add variable newtype and support generics in fixed newtype
newpavlov 185b475
remove old code
newpavlov 19b2e43
update newtype_variable_hash
newpavlov 75445cc
Add HashMarker checks
newpavlov de0daef
Implement fixed traits directly instead of delegating
newpavlov 727f9f5
tweak newtype_xof
newpavlov 01f3055
introduce separate `newtype_rt_variable_hash` macro
newpavlov 2aced1d
change `newtype_ct_variable_hash!`
newpavlov e3794b0
Rename CtVariableCoreWrapper to CtOutWrapper
newpavlov 58d65d9
Update macros
newpavlov 0bd68a4
tweak cof macro
newpavlov f3d7a4f
rename macros
newpavlov 844f043
Add MAC support to `buffer_fixed`
newpavlov b3cd57b
remove wrappers
newpavlov b5bac43
fix docs
newpavlov 954e8ff
rename `core_api` to `block_api`
newpavlov 774c061
fix docs
newpavlov 3e7a605
Merge branch 'master' into digest/newtype
newpavlov 99be71b
Update changelog
newpavlov 161c42b
Add changelog entry for #1820
newpavlov c61b646
Tweak `buffer_fixed`
newpavlov File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| mod fixed; | ||
| mod variable_ct; | ||
| mod variable_rt; | ||
| mod xof; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,330 @@ | ||
| /// Creates a buffered wrapper around block-level "core" type which implements fixed output size traits. | ||
| #[macro_export] | ||
| macro_rules! buffer_fixed { | ||
| ( | ||
| $(#[$attr:meta])* | ||
| $v:vis struct $name:ident$(<$gp:ident: $bound:ident>)?($core_ty:ty); | ||
| impl: $($trait_name:ident)*; | ||
| ) => { | ||
| $(#[$attr])* | ||
| $v struct $name$(<$gp: $bound>)? { | ||
| core: $core_ty, | ||
| buffer: $crate::core_api::Buffer<$core_ty>, | ||
| } | ||
|
|
||
| $crate::buffer_fixed!( | ||
| impl_inner: $name$(<$gp: $bound>)?($core_ty); | ||
| $($trait_name)*; | ||
| ); | ||
| }; | ||
|
|
||
| ( | ||
| $(#[$attr:meta])* | ||
| $v:vis struct $name:ident$(<$gp:ident: $bound:ident>)?($core_ty:ty); | ||
| oid: $oid:literal; | ||
| impl: $($trait_name:ident)*; | ||
| ) => { | ||
| $crate::buffer_fixed!( | ||
| $(#[$attr])* | ||
| $v struct $name$(<$gp: $bound>)?($core_ty); | ||
| impl: $($trait_name)*; | ||
| ); | ||
|
|
||
| #[cfg(feature = "oid")] | ||
| impl$(<$gp: $bound>)? $crate::const_oid::AssociatedOid for $name$(<$gp>)? { | ||
| const OID: $crate::const_oid::ObjectIdentifier = | ||
| $crate::const_oid::ObjectIdentifier::new_unwrap($oid); | ||
| } | ||
| }; | ||
|
|
||
| // Terminates `impl_inner` sequences. | ||
| ( | ||
| impl_inner: $name:ident$(<$gp:ident: $bound:ident>)?($core_ty:ty); ; | ||
| ) => {}; | ||
|
|
||
| // Implements the set of traits common for fixed output hashes: | ||
| // `Default`, `Clone`, `HashMarker`, `Reset`, `FixedOutputReset`, `SerializableState` | ||
| ( | ||
| impl_inner: $name:ident$(<$gp:ident: $bound:ident>)?($core_ty:ty); | ||
| FixedHashTraits $($trait_name:ident)*; | ||
| ) => { | ||
| $crate::buffer_fixed!( | ||
| impl_inner: $name$(<$gp: $bound>)?($core_ty); | ||
| BaseFixedTraits Default Clone HashMarker Reset FixedOutputReset SerializableState $($trait_name)*; | ||
| ); | ||
| }; | ||
|
|
||
| // Implements basic fixed traits: | ||
| // `Debug`, `AlgorithmName`, `BlockSizeUser`, `OutputSizeUser`, | ||
| // `CoreProxy`, `Update`, and `FixedOutput`. | ||
| ( | ||
| impl_inner: $name:ident$(<$gp:ident: $bound:ident>)?($core_ty:ty); | ||
| BaseFixedTraits $($trait_name:ident)*; | ||
| ) => { | ||
| $crate::buffer_fixed!( | ||
| impl_inner: $name$(<$gp: $bound>)?($core_ty); | ||
| Debug AlgorithmName BlockSizeUser OutputSizeUser CoreProxy Update FixedOutput $($trait_name)*; | ||
| ); | ||
| }; | ||
|
|
||
| // Implements `Debug` | ||
| ( | ||
| impl_inner: $name:ident$(<$gp:ident: $bound:ident>)?($core_ty:ty); | ||
| Debug $($trait_name:ident)*; | ||
| ) => { | ||
| impl$(<$gp: $bound>)? core::fmt::Debug for $name$(<$gp>)? { | ||
| #[inline] | ||
| fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { | ||
| f.write_str(concat!(stringify!($name), " { ... }")) | ||
| } | ||
| } | ||
|
|
||
| $crate::buffer_fixed!(impl_inner: $name$(<$gp: $bound>)?($core_ty); $($trait_name)*;); | ||
| }; | ||
|
|
||
| // Implements `AlgorithmName` | ||
| ( | ||
| impl_inner: $name:ident$(<$gp:ident: $bound:ident>)?($core_ty:ty); | ||
| AlgorithmName $($trait_name:ident)*; | ||
| ) => { | ||
| impl$(<$gp: $bound>)? $crate::crypto_common::AlgorithmName for $name$(<$gp>)? { | ||
| #[inline] | ||
| fn write_alg_name(f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> { | ||
| <$core_ty as $crate::crypto_common::AlgorithmName>::write_alg_name(f) | ||
| } | ||
| } | ||
|
|
||
| $crate::buffer_fixed!(impl_inner: $name$(<$gp: $bound>)?($core_ty); $($trait_name)*;); | ||
| }; | ||
|
|
||
| // Implements `BlockSizeUser` | ||
| ( | ||
| impl_inner: $name:ident$(<$gp:ident: $bound:ident>)?($core_ty:ty); | ||
| BlockSizeUser $($trait_name:ident)*; | ||
| ) => { | ||
| impl$(<$gp: $bound>)? $crate::core_api::BlockSizeUser for $name$(<$gp>)? { | ||
| type BlockSize = <$core_ty as $crate::crypto_common::BlockSizeUser>::BlockSize; | ||
| } | ||
|
|
||
| $crate::buffer_fixed!(impl_inner: $name$(<$gp: $bound>)?($core_ty); $($trait_name)*;); | ||
| }; | ||
|
|
||
| // Implements `OutputSizeUser` | ||
| ( | ||
| impl_inner: $name:ident$(<$gp:ident: $bound:ident>)?($core_ty:ty); | ||
| OutputSizeUser $($trait_name:ident)*; | ||
| ) => { | ||
| impl$(<$gp: $bound>)? $crate::OutputSizeUser for $name$(<$gp>)? { | ||
| type OutputSize = <$core_ty as $crate::core_api::OutputSizeUser>::OutputSize; | ||
| } | ||
|
|
||
| $crate::buffer_fixed!(impl_inner: $name$(<$gp: $bound>)?($core_ty); $($trait_name)*;); | ||
| }; | ||
|
|
||
| // Implements `CoreProxy` | ||
| ( | ||
| impl_inner: $name:ident$(<$gp:ident: $bound:ident>)?($core_ty:ty); | ||
| CoreProxy $($trait_name:ident)*; | ||
| ) => { | ||
| impl$(<$gp: $bound>)? $crate::core_api::CoreProxy for $name$(<$gp>)? { | ||
| type Core = $core_ty; | ||
| } | ||
|
|
||
| $crate::buffer_fixed!(impl_inner: $name$(<$gp: $bound>)?($core_ty); $($trait_name)*;); | ||
| }; | ||
|
|
||
| // Implements `Update` | ||
| ( | ||
| impl_inner: $name:ident$(<$gp:ident: $bound:ident>)?($core_ty:ty); | ||
| Update $($trait_name:ident)*; | ||
| ) => { | ||
| impl$(<$gp: $bound>)? $crate::Update for $name$(<$gp>)? { | ||
| #[inline] | ||
| fn update(&mut self, data: &[u8]) { | ||
| let Self { core, buffer } = self; | ||
| buffer.digest_blocks(data, |blocks| { | ||
| $crate::core_api::UpdateCore::update_blocks(core, blocks) | ||
| }); | ||
| } | ||
| } | ||
|
|
||
| $crate::buffer_fixed!(impl_inner: $name$(<$gp: $bound>)?($core_ty); $($trait_name)*;); | ||
| }; | ||
|
|
||
| // Implements `FixedOutput` | ||
| ( | ||
| impl_inner: $name:ident$(<$gp:ident: $bound:ident>)?($core_ty:ty); | ||
| FixedOutput $($trait_name:ident)*; | ||
| ) => { | ||
| impl$(<$gp: $bound>)? $crate::FixedOutput for $name$(<$gp>)? { | ||
| #[inline] | ||
| fn finalize_into(mut self, out: &mut $crate::Output<Self>) { | ||
| let Self { core, buffer } = &mut self; | ||
| $crate::core_api::FixedOutputCore::finalize_fixed_core(core, buffer, out); | ||
| } | ||
| } | ||
|
|
||
| $crate::buffer_fixed!(impl_inner: $name$(<$gp: $bound>)?($core_ty); $($trait_name)*;); | ||
| }; | ||
|
|
||
| // Implements `Default` | ||
| ( | ||
| impl_inner: $name:ident$(<$gp:ident: $bound:ident>)?($core_ty:ty); | ||
| Default $($trait_name:ident)*; | ||
| ) => { | ||
| impl$(<$gp: $bound>)? Default for $name$(<$gp>)? { | ||
| #[inline] | ||
| fn default() -> Self { | ||
| Self { | ||
| core: Default::default(), | ||
| buffer: Default::default(), | ||
| } | ||
| } | ||
| } | ||
|
|
||
| $crate::buffer_fixed!(impl_inner: $name$(<$gp: $bound>)?($core_ty); $($trait_name)*;); | ||
| }; | ||
|
|
||
| // Implements `CustomizedInit` | ||
| ( | ||
| impl_inner: $name:ident$(<$gp:ident: $bound:ident>)?($core_ty:ty); | ||
| CustomizedInit $($trait_name:ident)*; | ||
| ) => { | ||
| impl$(<$gp: $bound>)? $crate::CustomizedInit for $name$(<$gp>)? { | ||
| #[inline] | ||
| fn new_customized(customization: &[u8]) -> Self { | ||
| Self { | ||
| core: $crate::CustomizedInit::new_customized(customization), | ||
| buffer: Default::default(), | ||
| } | ||
| } | ||
| } | ||
|
|
||
| $crate::buffer_fixed!(impl_inner: $name$(<$gp: $bound>)?($core_ty); $($trait_name)*;); | ||
| }; | ||
|
|
||
| // Implements `Clone` | ||
| ( | ||
| impl_inner: $name:ident$(<$gp:ident: $bound:ident>)?($core_ty:ty); | ||
| Clone $($trait_name:ident)*; | ||
| ) => { | ||
| impl$(<$gp: $bound>)? Clone for $name$(<$gp>)? { | ||
| #[inline] | ||
| fn clone(&self) -> Self { | ||
| Self { | ||
| core: Clone::clone(&self.core), | ||
| buffer: Clone::clone(&self.buffer), | ||
| } | ||
| } | ||
| } | ||
|
|
||
| $crate::buffer_fixed!(impl_inner: $name$(<$gp: $bound>)?($core_ty); $($trait_name)*;); | ||
| }; | ||
|
|
||
| // Implements `HashMarker` and asserts that `$core_ty` implements it | ||
| ( | ||
| impl_inner: $name:ident$(<$gp:ident: $bound:ident>)?($core_ty:ty); | ||
| HashMarker $($trait_name:ident)*; | ||
| ) => { | ||
| impl$(<$gp: $bound>)? $crate::HashMarker for $name$(<$gp>)? {} | ||
|
|
||
| // Verify that `$core_ty` implements `HashMarker` | ||
| const _: () = { | ||
| fn check$(<$gp: $bound>)?(v: &$core_ty) { | ||
| v as &dyn $crate::HashMarker; | ||
| } | ||
| }; | ||
|
|
||
| $crate::buffer_fixed!(impl_inner: $name$(<$gp: $bound>)?($core_ty); $($trait_name)*;); | ||
| }; | ||
|
|
||
| // Implements `Reset` | ||
| ( | ||
| impl_inner: $name:ident$(<$gp:ident: $bound:ident>)?($core_ty:ty); | ||
| Reset $($trait_name:ident)*; | ||
| ) => { | ||
| impl$(<$gp: $bound>)? $crate::Reset for $name$(<$gp>)? { | ||
| #[inline] | ||
| fn reset(&mut self) { | ||
| $crate::Reset::reset(&mut self.core); | ||
| self.buffer.reset(); | ||
| } | ||
| } | ||
|
|
||
| $crate::buffer_fixed!(impl_inner: $name$(<$gp: $bound>)?($core_ty); $($trait_name)*;); | ||
| }; | ||
|
|
||
| // Implements `FixedOutputReset` | ||
| ( | ||
| impl_inner: $name:ident$(<$gp:ident: $bound:ident>)?($core_ty:ty); | ||
| FixedOutputReset $($trait_name:ident)*; | ||
| ) => { | ||
| impl$(<$gp: $bound>)? $crate::FixedOutputReset for $name$(<$gp>)? { | ||
| #[inline] | ||
| fn finalize_into_reset(&mut self, out: &mut $crate::Output<Self>) { | ||
| let Self { core, buffer } = self; | ||
| $crate::core_api::FixedOutputCore::finalize_fixed_core(core, buffer, out); | ||
| $crate::Reset::reset(self); | ||
| } | ||
| } | ||
|
|
||
| $crate::buffer_fixed!(impl_inner: $name$(<$gp: $bound>)?($core_ty); $($trait_name)*;); | ||
| }; | ||
|
|
||
| // Implements `SerializableState` | ||
| ( | ||
| impl_inner: $name:ident$(<$gp:ident: $bound:ident>)?($core_ty:ty); | ||
| SerializableState $($trait_name:ident)*; | ||
| ) => { | ||
| impl$(<$gp: $bound>)? $crate::crypto_common::hazmat::SerializableState for $name$(<$gp>)? { | ||
| type SerializedStateSize = $crate::typenum::Sum< | ||
| <$core_ty as $crate::crypto_common::hazmat::SerializableState>::SerializedStateSize, | ||
| $crate::typenum::Add1< | ||
| <$core_ty as $crate::core_api::BlockSizeUser>::BlockSize | ||
| > | ||
| >; | ||
|
|
||
| #[inline] | ||
| fn serialize(&self) -> $crate::crypto_common::hazmat::SerializedState<Self> { | ||
| use $crate::{ | ||
| array::Array, | ||
| consts::U1, | ||
| block_buffer::BlockBuffer, | ||
| crypto_common::hazmat::SerializableState, | ||
| }; | ||
|
|
||
| let serialized_core = self.core.serialize(); | ||
| let pos = u8::try_from(self.buffer.get_pos()).unwrap(); | ||
| let serialized_pos: Array<u8, U1> = Array([pos]); | ||
| let serialized_data = self.buffer.clone().pad_with_zeros(); | ||
|
|
||
| serialized_core | ||
| .concat(serialized_pos) | ||
| .concat(serialized_data) | ||
| } | ||
|
|
||
| #[inline] | ||
| fn deserialize( | ||
| serialized_state: &$crate::crypto_common::hazmat::SerializedState<Self>, | ||
| ) -> Result<Self, $crate::crypto_common::hazmat::DeserializeStateError> { | ||
| use $crate::{ | ||
| block_buffer::BlockBuffer, | ||
| consts::U1, | ||
| crypto_common::hazmat::{SerializableState, DeserializeStateError}, | ||
| }; | ||
|
|
||
| let (serialized_core, remaining_buffer) = serialized_state | ||
| .split_ref::<<$core_ty as SerializableState>::SerializedStateSize>(); | ||
| let (serialized_pos, serialized_data) = remaining_buffer.split_ref::<U1>(); | ||
|
|
||
| Ok(Self { | ||
| core: <$core_ty as SerializableState>::deserialize(serialized_core)?, | ||
| buffer: BlockBuffer::try_new(&serialized_data[..serialized_pos[0].into()]) | ||
| .map_err(|_| DeserializeStateError)?, | ||
| }) | ||
| } | ||
| } | ||
|
|
||
| $crate::buffer_fixed!(impl_inner: $name$(<$gp: $bound>)?($core_ty); $($trait_name)*;); | ||
| } | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could simplify the macro by removing the
$(<$gp:ident: $bound:ident>)?part. Currently it's used only bygost94andskein.My initial intent was for this macro to support cases covered by the
buffer_ct_variablemacro, but, unfortunately, the required pattern becomes annoyingly complex, so I decided against it.