libcrux_sha2/
impl_hacl.rs

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