Skip to main content

libcrux_sha2/
impl_hacl.rs

1use super::*;
2use libcrux_traits::Digest;
3
4/// The different Sha2 algorithms.
5#[derive(Clone, Copy, Debug)]
6pub enum Algorithm {
7    Sha224,
8    Sha256,
9    Sha384,
10    Sha512,
11}
12
13impl Algorithm {
14    // The length of the digest by algorithm.
15    pub const fn hash_len(&self) -> usize {
16        match self {
17            Algorithm::Sha224 => SHA224_LENGTH,
18            Algorithm::Sha256 => SHA256_LENGTH,
19            Algorithm::Sha384 => SHA384_LENGTH,
20            Algorithm::Sha512 => SHA512_LENGTH,
21        }
22    }
23}
24
25impl Algorithm {
26    /// Sha2
27    ///
28    /// Write the Sha2 hash of `payload` into `digest`.
29    pub fn hash(&self, payload: &[u8], digest: &mut [u8]) {
30        match self {
31            Algorithm::Sha224 => Sha224::hash(digest, payload),
32            Algorithm::Sha256 => Sha256::hash(digest, payload),
33            Algorithm::Sha384 => Sha384::hash(digest, payload),
34            Algorithm::Sha512 => Sha512::hash(digest, payload),
35        }
36    }
37}
38
39/// SHA2 224
40/// Will panic if `payload` is longer than `u32::MAX` to ensure that hacl-rs can
41/// process it.
42#[inline(always)]
43pub fn sha224(payload: &[u8]) -> [u8; SHA224_LENGTH] {
44    let mut digest = [0u8; SHA224_LENGTH];
45    Sha224::hash(&mut digest, payload);
46    digest
47}
48
49/// SHA2 256
50/// Will panic if `payload` is longer than `u32::MAX` to ensure that hacl-rs can
51/// process it.
52#[inline(always)]
53pub fn sha256(payload: &[u8]) -> [u8; SHA256_LENGTH] {
54    let mut digest = [0u8; SHA256_LENGTH];
55    Sha256::hash(&mut digest, payload);
56    digest
57}
58
59/// SHA2 384
60/// Will panic if `payload` is longer than `u32::MAX` to ensure that hacl-rs can
61/// process it.
62#[inline(always)]
63pub fn sha384(payload: &[u8]) -> [u8; SHA384_LENGTH] {
64    let mut digest = [0u8; SHA384_LENGTH];
65    Sha384::hash(&mut digest, payload);
66    digest
67}
68
69/// SHA2 512
70/// Will panic if `payload` is longer than `u32::MAX` to ensure that hacl-rs can
71/// process it.
72#[inline(always)]
73pub fn sha512(payload: &[u8]) -> [u8; SHA512_LENGTH] {
74    let mut digest = [0u8; SHA512_LENGTH];
75    Sha512::hash(&mut digest, payload);
76    digest
77}
78
79// Streaming API - This is the recommended one.
80// For implementations based on hacl_rs (over hacl-c)
81macro_rules! impl_hash {
82    ($name:ident, $digest_size:literal, $state:ty, $malloc:expr, $reset:expr, $update:expr, $finish:expr, $copy:expr, $hash:expr) => {
83        #[allow(non_camel_case_types)]
84        pub struct $name {
85            state: $state,
86        }
87
88        impl $name {
89            /// Initialize a new digest state for streaming use.
90            pub fn new() -> $name {
91                $name { state: $malloc() }
92            }
93        }
94
95        impl libcrux_traits::Digest<$digest_size> for $name {
96            /// Return the digest for the given input byte slice, in immediate mode.
97            /// Will panic if `payload` is longer than `u32::MAX` to ensure that hacl-rs can
98            /// process it.
99            #[inline(always)]
100            fn hash(digest: &mut [u8], payload: &[u8]) {
101                debug_assert!(digest.len() == $digest_size);
102                let payload_len = payload.len().try_into().unwrap();
103                $hash(digest, payload, payload_len)
104            }
105
106            /// Add the `payload` to the digest.
107            /// Will panic if `payload` is longer than `u32::MAX` to ensure that hacl-rs can
108            /// process it.
109            #[inline(always)]
110            fn update(&mut self, payload: &[u8]) {
111                let payload_len = payload.len().try_into().unwrap();
112                $update(&mut self.state, payload, payload_len);
113            }
114
115            /// Get the digest.
116            ///
117            /// Note that the digest state can be continued to be used, to extend the
118            /// digest.
119            #[inline(always)]
120            fn finish(&self, digest: &mut [u8; $digest_size]) {
121                $finish(&self.state, digest);
122            }
123
124            /// Reset the digest state.
125            #[inline(always)]
126            fn reset(&mut self) {
127                $reset(&mut self.state);
128            }
129        }
130
131        impl Default for $name {
132            #[inline(always)]
133            fn default() -> Self {
134                Self::new()
135            }
136        }
137
138        impl Clone for $name {
139            #[inline(always)]
140            fn clone(&self) -> Self {
141                Self {
142                    state: $copy(&self.state),
143                }
144            }
145        }
146    };
147}
148
149impl_hash!(
150    Sha256,
151    32,
152    libcrux_hacl_rs::streaming_types::state_32,
153    crate::hacl::malloc_256,
154    crate::hacl::reset_256,
155    crate::hacl::update_256,
156    crate::hacl::digest_256,
157    crate::hacl::copy_256,
158    crate::hacl::hash_256
159);
160impl_hash!(
161    Sha224,
162    28,
163    libcrux_hacl_rs::streaming_types::state_32,
164    crate::hacl::malloc_224,
165    crate::hacl::reset_224,
166    crate::hacl::update_224,
167    crate::hacl::digest_224,
168    crate::hacl::copy_256,
169    crate::hacl::hash_224
170);
171
172impl_hash!(
173    Sha512,
174    64,
175    libcrux_hacl_rs::streaming_types::state_64,
176    crate::hacl::malloc_512,
177    crate::hacl::reset_512,
178    crate::hacl::update_512,
179    crate::hacl::digest_512,
180    crate::hacl::copy_512,
181    crate::hacl::hash_512
182);
183impl_hash!(
184    Sha384,
185    48,
186    libcrux_hacl_rs::streaming_types::state_64,
187    crate::hacl::malloc_384,
188    crate::hacl::reset_384,
189    crate::hacl::update_384,
190    crate::hacl::digest_384,
191    crate::hacl::copy_512,
192    crate::hacl::hash_384
193);