libcrux_sha2/
impl_digest_trait.rs

1use crate::impl_hacl::*;
2
3use libcrux_traits::Digest;
4
5use libcrux_traits::digest::{
6    arrayref, slice, DigestIncrementalBase, InitializeDigestState, UpdateError,
7};
8
9// Streaming API - This is the recommended one.
10// For implementations based on hacl_rs (over hacl-c)
11macro_rules! impl_hash {
12    ($hasher_name:ident, $name:ident, $state_name:ty, $digest_size:literal) => {
13        #[derive(Clone, Default)]
14
15        #[doc = concat!("A struct that implements [`libcrux_traits::digest`] traits.")]
16        #[doc = concat!("\n\n")]
17        #[doc = concat!("[`",stringify!($hasher_name), "`] is a convenience hasher for this struct.")]
18        #[allow(non_camel_case_types)]
19        pub struct $name;
20
21        #[doc = concat!("A hasher for [`",stringify!($name), "`].")]
22        pub type $hasher_name = libcrux_traits::digest::Hasher<$digest_size, $name>;
23
24
25        impl arrayref::Hash<$digest_size> for $name {
26            /// Return the digest for the given input byte slice, in immediate mode.
27            /// Will return an error if `payload` is longer than `u32::MAX` to ensure that hacl-rs can
28            /// process it.
29            #[inline(always)]
30            fn hash(digest: &mut [u8; $digest_size], payload: &[u8]) -> Result<(), arrayref::HashError> {
31
32                if payload.len() > u32::MAX as usize {
33                    return Err(arrayref::HashError::InvalidPayloadLength);
34                }
35                <$state_name>::hash(digest, payload);
36
37                Ok(())
38            }
39
40
41        }
42
43        impl InitializeDigestState for $state_name {
44            fn new() -> Self {
45                Self::default()
46            }
47        }
48
49        impl DigestIncrementalBase for $name {
50            type IncrementalState = $state_name;
51            /// Add the `payload` to the digest.
52            /// Will return an error if `payload` is longer than `u32::MAX` to ensure that hacl-rs can
53            /// process it.
54            #[inline(always)]
55            fn update(state: &mut Self::IncrementalState, payload: &[u8])
56            -> Result<(), UpdateError> {
57                if payload.len() > u32::MAX as usize {
58                    return Err(UpdateError::InvalidPayloadLength);
59                }
60                state.update(payload);
61                Ok(())
62            }
63            /// Reset the digest state.
64            #[inline(always)]
65            fn reset(state: &mut Self::IncrementalState) {
66                state.reset()
67            }
68        }
69        impl arrayref::DigestIncremental<$digest_size> for $name {
70
71            #[inline(always)]
72            fn finish(state: &mut Self::IncrementalState, digest: &mut [u8; $digest_size]) {
73                state.finish (digest);
74            }
75
76        }
77        slice::impl_hash_trait!($name => $digest_size);
78        slice::impl_digest_incremental_trait!($name => $state_name, $digest_size);
79
80    };
81}
82
83impl_hash!(Sha224Hasher, Sha224Hash, Sha224, 28);
84impl_hash!(Sha256Hasher, Sha256Hash, Sha256, 32);
85
86impl_hash!(Sha384Hasher, Sha384Hash, Sha384, 48);
87impl_hash!(Sha512Hasher, Sha512Hash, Sha512, 64);