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 crypto_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 for (chunk, v) in out.chunks_exact_mut(4).zip(self.state.iter()) {
70 chunk.copy_from_slice(&v.to_be_bytes());
71 }
72 }
73}
74
75impl AlgorithmName for Sha256VarCore {
76 #[inline]
77 fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
78 f.write_str("Sha256")
79 }
80}
81
82impl fmt::Debug for Sha256VarCore {
83 #[inline]
84 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85 f.write_str("Sha256VarCore { ... }")
86 }
87}
88
89impl Drop for Sha256VarCore {
90 fn drop(&mut self) {
91 #[cfg(feature = "zeroize")]
92 {
93 use digest::zeroize::Zeroize;
94 self.state.zeroize();
95 self.block_len.zeroize();
96 }
97 }
98}
99
100#[cfg(feature = "zeroize")]
101impl digest::zeroize::ZeroizeOnDrop for Sha256VarCore {}
102
103impl SerializableState for Sha256VarCore {
104 type SerializedStateSize = U40;
105
106 fn serialize(&self) -> SerializedState<Self> {
107 let mut serialized_state = SerializedState::<Self>::default();
108
109 for (val, chunk) in self.state.iter().zip(serialized_state.chunks_exact_mut(4)) {
110 chunk.copy_from_slice(&val.to_le_bytes());
111 }
112
113 serialized_state[32..].copy_from_slice(&self.block_len.to_le_bytes());
114 serialized_state
115 }
116
117 fn deserialize(
118 serialized_state: &SerializedState<Self>,
119 ) -> Result<Self, DeserializeStateError> {
120 let (serialized_state, serialized_block_len) = serialized_state.split::<U32>();
121
122 let mut state = consts::State256::default();
123 for (val, chunk) in state.iter_mut().zip(serialized_state.chunks_exact(4)) {
124 *val = u32::from_le_bytes(chunk.try_into().unwrap());
125 }
126
127 let block_len = u64::from_le_bytes(*serialized_block_len.as_ref());
128
129 Ok(Self { state, block_len })
130 }
131}
132
133#[derive(Clone)]
138pub struct Sha512VarCore {
139 state: consts::State512,
140 block_len: u128,
141}
142
143impl HashMarker for Sha512VarCore {}
144
145impl BlockSizeUser for Sha512VarCore {
146 type BlockSize = U128;
147}
148
149impl BufferKindUser for Sha512VarCore {
150 type BufferKind = Eager;
151}
152
153impl UpdateCore for Sha512VarCore {
154 #[inline]
155 fn update_blocks(&mut self, blocks: &[Block<Self>]) {
156 self.block_len += blocks.len() as u128;
157 let blocks = Array::cast_slice_to_core(blocks);
158 compress512(&mut self.state, blocks);
159 }
160}
161
162impl OutputSizeUser for Sha512VarCore {
163 type OutputSize = U64;
164}
165
166impl VariableOutputCore for Sha512VarCore {
167 const TRUNC_SIDE: TruncSide = TruncSide::Left;
168
169 #[inline]
170 fn new(output_size: usize) -> Result<Self, InvalidOutputSize> {
171 let state = match output_size {
172 28 => consts::H512_224,
173 32 => consts::H512_256,
174 48 => consts::H512_384,
175 64 => consts::H512_512,
176 _ => return Err(InvalidOutputSize),
177 };
178 let block_len = 0;
179 Ok(Self { state, block_len })
180 }
181
182 #[inline]
183 fn finalize_variable_core(&mut self, buffer: &mut Buffer<Self>, out: &mut Output<Self>) {
184 let bs = Self::BlockSize::U64 as u128;
185 let bit_len = 8 * (buffer.get_pos() as u128 + bs * self.block_len);
186 buffer.len128_padding_be(bit_len, |b| compress512(&mut self.state, &[b.0]));
187
188 for (chunk, v) in out.chunks_exact_mut(8).zip(self.state.iter()) {
189 chunk.copy_from_slice(&v.to_be_bytes());
190 }
191 }
192}
193
194impl AlgorithmName for Sha512VarCore {
195 #[inline]
196 fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
197 f.write_str("Sha512")
198 }
199}
200
201impl fmt::Debug for Sha512VarCore {
202 #[inline]
203 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
204 f.write_str("Sha512VarCore { ... }")
205 }
206}
207
208impl Drop for Sha512VarCore {
209 fn drop(&mut self) {
210 #[cfg(feature = "zeroize")]
211 {
212 use digest::zeroize::Zeroize;
213 self.state.zeroize();
214 self.block_len.zeroize();
215 }
216 }
217}
218#[cfg(feature = "zeroize")]
219impl digest::zeroize::ZeroizeOnDrop for Sha512VarCore {}
220
221impl SerializableState for Sha512VarCore {
222 type SerializedStateSize = U80;
223
224 fn serialize(&self) -> SerializedState<Self> {
225 let mut serialized_state = SerializedState::<Self>::default();
226
227 for (val, chunk) in self.state.iter().zip(serialized_state.chunks_exact_mut(8)) {
228 chunk.copy_from_slice(&val.to_le_bytes());
229 }
230
231 serialized_state[64..].copy_from_slice(&self.block_len.to_le_bytes());
232
233 serialized_state
234 }
235
236 fn deserialize(
237 serialized_state: &SerializedState<Self>,
238 ) -> Result<Self, DeserializeStateError> {
239 let (serialized_state, serialized_block_len) = serialized_state.split::<U64>();
240
241 let mut state = consts::State512::default();
242 for (val, chunk) in state.iter_mut().zip(serialized_state.chunks_exact(8)) {
243 *val = u64::from_le_bytes(chunk.try_into().unwrap());
244 }
245
246 let block_len = u128::from_le_bytes(*serialized_block_len.as_ref());
247
248 Ok(Self { state, block_len })
249 }
250}