1use crate::consts;
2use core::fmt;
3use digest::{
4 HashMarker, InvalidOutputSize, Output,
5 array::Array,
6 block_api::{
7 AlgorithmName, Block, BlockSizeUser, Buffer, BufferKindUser, Eager, OutputSizeUser,
8 TruncSide, UpdateCore, VariableOutputCore,
9 },
10 common::hazmat::{DeserializeStateError, SerializableState, SerializedState},
11 typenum::{U32, U40, U64, U80, U128, Unsigned},
12};
13
14pub use crate::{sha256::compress256, sha512::compress512};
15
16#[derive(Clone)]
21pub struct Sha256VarCore {
22 state: consts::State256,
23 block_len: u64,
24}
25
26impl HashMarker for Sha256VarCore {}
27
28impl BlockSizeUser for Sha256VarCore {
29 type BlockSize = U64;
30}
31
32impl BufferKindUser for Sha256VarCore {
33 type BufferKind = Eager;
34}
35
36impl UpdateCore for Sha256VarCore {
37 #[inline]
38 fn update_blocks(&mut self, blocks: &[Block<Self>]) {
39 self.block_len += blocks.len() as u64;
40 let blocks = Array::cast_slice_to_core(blocks);
41 compress256(&mut self.state, blocks);
42 }
43}
44
45impl OutputSizeUser for Sha256VarCore {
46 type OutputSize = U32;
47}
48
49impl VariableOutputCore for Sha256VarCore {
50 const TRUNC_SIDE: TruncSide = TruncSide::Left;
51
52 #[inline]
53 fn new(output_size: usize) -> Result<Self, InvalidOutputSize> {
54 let state = match output_size {
55 28 => consts::H256_224,
56 32 => consts::H256_256,
57 _ => return Err(InvalidOutputSize),
58 };
59 let block_len = 0;
60 Ok(Self { state, block_len })
61 }
62
63 #[inline]
64 fn finalize_variable_core(&mut self, buffer: &mut Buffer<Self>, out: &mut Output<Self>) {
65 let bs = Self::BlockSize::U64;
66 let bit_len = 8 * (buffer.get_pos() as u64 + bs * self.block_len);
67 buffer.len64_padding_be(bit_len, |b| compress256(&mut self.state, &[b.0]));
68
69 let (chunks, tail) = out.as_chunks_mut();
70 assert!(tail.is_empty());
71
72 for (chunk, val) in chunks.iter_mut().zip(self.state.iter()) {
73 *chunk = val.to_be_bytes();
74 }
75 }
76}
77
78impl AlgorithmName for Sha256VarCore {
79 #[inline]
80 fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
81 f.write_str("Sha256")
82 }
83}
84
85impl fmt::Debug for Sha256VarCore {
86 #[inline]
87 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
88 f.write_str("Sha256VarCore { ... }")
89 }
90}
91
92impl Drop for Sha256VarCore {
93 fn drop(&mut self) {
94 #[cfg(feature = "zeroize")]
95 {
96 use digest::zeroize::Zeroize;
97 self.state.zeroize();
98 self.block_len.zeroize();
99 }
100 }
101}
102
103#[cfg(feature = "zeroize")]
104impl digest::zeroize::ZeroizeOnDrop for Sha256VarCore {}
105
106impl SerializableState for Sha256VarCore {
107 type SerializedStateSize = U40;
108
109 fn serialize(&self) -> SerializedState<Self> {
110 let mut res = SerializedState::<Self>::default();
111 let (state_dst, len_dst) = res.split_at_mut(32);
112
113 let (chunks, tail) = state_dst.as_chunks_mut();
114 assert!(tail.is_empty());
115 for (val, chunk) in self.state.iter().zip(chunks.iter_mut()) {
116 *chunk = val.to_le_bytes();
117 }
118
119 len_dst.copy_from_slice(&self.block_len.to_le_bytes());
120
121 res
122 }
123
124 fn deserialize(
125 serialized_state: &SerializedState<Self>,
126 ) -> Result<Self, DeserializeStateError> {
127 let (serialized_state, serialized_block_len) = serialized_state.split::<U32>();
128
129 let (chunks, tail) = serialized_state.as_chunks();
130 assert!(tail.is_empty());
131 let state = core::array::from_fn(|i| u32::from_le_bytes(chunks[i]));
132
133 let block_len = u64::from_le_bytes(*serialized_block_len.as_ref());
134
135 Ok(Self { state, block_len })
136 }
137}
138
139#[derive(Clone)]
144pub struct Sha512VarCore {
145 state: consts::State512,
146 block_len: u128,
147}
148
149impl HashMarker for Sha512VarCore {}
150
151impl BlockSizeUser for Sha512VarCore {
152 type BlockSize = U128;
153}
154
155impl BufferKindUser for Sha512VarCore {
156 type BufferKind = Eager;
157}
158
159impl UpdateCore for Sha512VarCore {
160 #[inline]
161 fn update_blocks(&mut self, blocks: &[Block<Self>]) {
162 self.block_len += blocks.len() as u128;
163 let blocks = Array::cast_slice_to_core(blocks);
164 compress512(&mut self.state, blocks);
165 }
166}
167
168impl OutputSizeUser for Sha512VarCore {
169 type OutputSize = U64;
170}
171
172impl VariableOutputCore for Sha512VarCore {
173 const TRUNC_SIDE: TruncSide = TruncSide::Left;
174
175 #[inline]
176 fn new(output_size: usize) -> Result<Self, InvalidOutputSize> {
177 let state = match output_size {
178 28 => consts::H512_224,
179 32 => consts::H512_256,
180 48 => consts::H512_384,
181 64 => consts::H512_512,
182 _ => return Err(InvalidOutputSize),
183 };
184 let block_len = 0;
185 Ok(Self { state, block_len })
186 }
187
188 #[inline]
189 fn finalize_variable_core(&mut self, buffer: &mut Buffer<Self>, out: &mut Output<Self>) {
190 let bs = Self::BlockSize::U64 as u128;
191 let bit_len = 8 * (buffer.get_pos() as u128 + bs * self.block_len);
192 buffer.len128_padding_be(bit_len, |b| compress512(&mut self.state, &[b.0]));
193
194 let (chunks, tail) = out.as_chunks_mut();
195 assert!(tail.is_empty());
196
197 for (chunk, val) in chunks.iter_mut().zip(self.state.iter()) {
198 *chunk = val.to_be_bytes();
199 }
200 }
201}
202
203impl AlgorithmName for Sha512VarCore {
204 #[inline]
205 fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
206 f.write_str("Sha512")
207 }
208}
209
210impl fmt::Debug for Sha512VarCore {
211 #[inline]
212 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
213 f.write_str("Sha512VarCore { ... }")
214 }
215}
216
217impl Drop for Sha512VarCore {
218 fn drop(&mut self) {
219 #[cfg(feature = "zeroize")]
220 {
221 use digest::zeroize::Zeroize;
222 self.state.zeroize();
223 self.block_len.zeroize();
224 }
225 }
226}
227#[cfg(feature = "zeroize")]
228impl digest::zeroize::ZeroizeOnDrop for Sha512VarCore {}
229
230impl SerializableState for Sha512VarCore {
231 type SerializedStateSize = U80;
232
233 fn serialize(&self) -> SerializedState<Self> {
234 let mut res = SerializedState::<Self>::default();
235 let (state_dst, len_dst) = res.split_at_mut(64);
236
237 let (chunks, tail) = state_dst.as_chunks_mut();
238 assert!(tail.is_empty());
239 for (val, chunk) in self.state.iter().zip(chunks.iter_mut()) {
240 *chunk = val.to_le_bytes();
241 }
242
243 len_dst.copy_from_slice(&self.block_len.to_le_bytes());
244
245 res
246 }
247
248 fn deserialize(
249 serialized_state: &SerializedState<Self>,
250 ) -> Result<Self, DeserializeStateError> {
251 let (serialized_state, serialized_block_len) = serialized_state.split::<U64>();
252
253 let (chunks, tail) = serialized_state.as_chunks();
254 assert!(tail.is_empty());
255 let state = core::array::from_fn(|i| u64::from_le_bytes(chunks[i]));
256
257 let block_len = u128::from_le_bytes(*serialized_block_len.as_ref());
258
259 Ok(Self { state, block_len })
260 }
261}