1use core::fmt;
2
3use digest::block_api::{
4 AlgorithmName,
5 Block,
6 BlockSizeUser,
7 Buffer,
8 BufferKindUser,
9 Eager,
10 ExtendableOutputCore,
11 UpdateCore,
12};
13use digest::common::hazmat::{
14 DeserializeStateError,
15 SerializableState,
16 SerializedState,
17};
18use digest::consts::{
19 U16,
20 U32,
21 U136,
22 U168,
23 U400,
24};
25use digest::typenum::Unsigned;
26use digest::{
27 CollisionResistance,
28 CustomizedInit,
29 HashMarker,
30 Reset,
31};
32
33#[cfg(not(feature = "simd"))]
34use crate::DEFAULT_ROUND_COUNT as ROUNDS;
35use crate::internal_block_api::{
36 Sha3ReaderCore,
37 xor_block,
38};
39use crate::{
40 CSHAKE_PAD,
41 PLEN,
42 SHAKE_PAD,
43};
44
45macro_rules! impl_cshake {
46 (
47 $name:ident, $full_name:ident, $reader_name:ident, $rate:ident, $alg_name:expr
48 ) => {
49 #[doc = $alg_name]
50 #[doc = " core hasher."]
51 #[derive(Clone, Default)]
52 pub struct $name {
53 state: [u64; PLEN],
54 initial_state: [u64; PLEN],
55 }
56
57 impl $name {
58 pub fn new_with_function_name(function_name: &[u8], customization: &[u8]) -> Self {
63 let mut state = Self::default();
64
65 if function_name.is_empty() && customization.is_empty() {
66 return state;
67 }
68
69 #[inline(always)]
70 pub(crate) fn left_encode(val: u64, b: &mut [u8; 9]) -> &[u8] {
71 b[1..].copy_from_slice(&val.to_be_bytes());
72 let i = b[1..8].iter().take_while(|&&a| a == 0).count();
73 b[i] = (8 - i) as u8;
74 &b[i..]
75 }
76
77 let mut buffer = Buffer::<Self>::default();
78 let mut b = [0u8; 9];
79 buffer.digest_blocks(left_encode($rate::to_u64(), &mut b), |blocks| {
80 state.update_blocks(blocks)
81 });
82 buffer.digest_blocks(
83 left_encode(8 * (function_name.len() as u64), &mut b),
84 |blocks| state.update_blocks(blocks),
85 );
86 buffer.digest_blocks(function_name, |blocks| state.update_blocks(blocks));
87 buffer.digest_blocks(
88 left_encode(8 * (customization.len() as u64), &mut b),
89 |blocks| state.update_blocks(blocks),
90 );
91 buffer.digest_blocks(customization, |blocks| state.update_blocks(blocks));
92 state.update_blocks(&[buffer.pad_with_zeros()]);
93 state.initial_state = state.state;
94 state
95 }
96 }
97
98 impl CustomizedInit for $name {
99 #[inline]
100 fn new_customized(customization: &[u8]) -> Self {
101 Self::new_with_function_name(&[], customization)
102 }
103 }
104
105 impl BlockSizeUser for $name {
106 type BlockSize = $rate;
107 }
108
109 impl BufferKindUser for $name {
110 type BufferKind = Eager;
111 }
112
113 impl HashMarker for $name {}
114
115 impl UpdateCore for $name {
116 #[inline]
117 fn update_blocks(&mut self, blocks: &[Block<Self>]) {
118 for block in blocks {
119 xor_block(&mut self.state, block);
120 #[cfg(feature = "simd")]
121 {
122 lib_q_keccak::p1600_optimized(&mut self.state, lib_q_keccak::OptimizationLevel::best_available());
123 }
124 #[cfg(not(feature = "simd"))]
125 {
126 lib_q_keccak::p1600(&mut self.state, ROUNDS);
127 }
128 }
129 }
130 }
131
132 impl ExtendableOutputCore for $name {
133 type ReaderCore = Sha3ReaderCore<$rate>;
134
135 #[inline]
136 fn finalize_xof_core(&mut self, buffer: &mut Buffer<Self>) -> Self::ReaderCore {
137 let pos = buffer.get_pos();
138 let mut block = buffer.pad_with_zeros();
139 let pad = if self.initial_state == [0; PLEN] {
140 SHAKE_PAD
141 } else {
142 CSHAKE_PAD
143 };
144 block[pos] = pad;
145 let n = block.len();
146 block[n - 1] |= 0x80;
147
148 xor_block(&mut self.state, &block);
149 #[cfg(feature = "simd")]
150 {
151 lib_q_keccak::p1600_optimized(&mut self.state, lib_q_keccak::OptimizationLevel::best_available());
152 }
153 #[cfg(not(feature = "simd"))]
154 {
155 lib_q_keccak::p1600(&mut self.state, ROUNDS);
156 }
157
158 Sha3ReaderCore::new(&self.state)
159 }
160 }
161
162 impl Reset for $name {
163 #[inline]
164 fn reset(&mut self) {
165 self.state = self.initial_state;
166 }
167 }
168
169 impl AlgorithmName for $name {
170 fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
171 f.write_str($alg_name)
172 }
173 }
174
175 impl fmt::Debug for $name {
176 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
177 f.write_str(concat!(stringify!($name), " { ... }"))
178 }
179 }
180
181 impl Drop for $name {
182 fn drop(&mut self) {
183 #[cfg(feature = "zeroize")]
184 {
185 use digest::zeroize::Zeroize;
186 self.state.zeroize();
187 self.initial_state.zeroize();
188 }
189 }
190 }
191
192 #[cfg(feature = "zeroize")]
193 impl digest::zeroize::ZeroizeOnDrop for $name {}
194
195 impl SerializableState for $name {
196 type SerializedStateSize = U400;
197
198 fn serialize(&self) -> SerializedState<Self> {
199 let mut serialized_state = SerializedState::<Self>::default();
200 let mut chunks = serialized_state.chunks_exact_mut(8);
201
202 for (val, chunk) in self.state.iter().zip(&mut chunks) {
203 chunk.copy_from_slice(&val.to_le_bytes());
204 }
205 for (val, chunk) in self.initial_state.iter().zip(&mut chunks) {
206 chunk.copy_from_slice(&val.to_le_bytes());
207 }
208
209 serialized_state
210 }
211
212 fn deserialize(
213 serialized_state: &SerializedState<Self>,
214 ) -> Result<Self, DeserializeStateError> {
215 let (state_src, initial_state_src) = serialized_state.split_at(200);
216 let state = core::array::from_fn(|i| {
217 let chunk = state_src[8 * i..][..8].try_into().unwrap();
218 u64::from_le_bytes(chunk)
219 });
220 let initial_state = core::array::from_fn(|i| {
221 let chunk = initial_state_src[8 * i..][..8].try_into().unwrap();
222 u64::from_le_bytes(chunk)
223 });
224 Ok(Self{ state, initial_state })
225 }
226 }
227
228 digest::buffer_xof!(
229 #[doc = $alg_name]
230 #[doc = " hasher."]
231 pub struct $full_name($name);
232 impl: Debug AlgorithmName Clone Default BlockSizeUser CoreProxy HashMarker Update Reset ExtendableOutputReset CustomizedInit;
235 #[doc = $alg_name]
236 #[doc = " XOF reader."]
237 pub struct $reader_name(Sha3ReaderCore<$rate>);
238 impl: XofReaderTraits;
239 );
240
241 impl $full_name {
242 pub fn new_with_function_name(function_name: &[u8], customization: &[u8]) -> Self {
247 Self {
248 core: $name::new_with_function_name(function_name, customization),
249 buffer: Default::default(),
250 }
251 }
252 }
253 };
254}
255
256impl_cshake!(CShake128Core, CShake128, CShake128Reader, U168, "cSHAKE128");
257impl_cshake!(CShake256Core, CShake256, CShake256Reader, U136, "cSHAKE256");
258
259impl CollisionResistance for CShake128 {
260 type CollisionResistance = U16;
262}
263
264impl CollisionResistance for CShake256 {
265 type CollisionResistance = U32;
267}
268
269impl SerializableState for CShake128 {
272 type SerializedStateSize = U400;
273
274 fn serialize(&self) -> SerializedState<Self> {
275 self.core.serialize()
276 }
277
278 fn deserialize(
279 serialized_state: &SerializedState<Self>,
280 ) -> Result<Self, DeserializeStateError> {
281 let core = CShake128Core::deserialize(serialized_state)?;
282 Ok(Self {
283 core,
284 buffer: Default::default(),
285 })
286 }
287}
288
289impl SerializableState for CShake256 {
290 type SerializedStateSize = U400;
291
292 fn serialize(&self) -> SerializedState<Self> {
293 self.core.serialize()
294 }
295
296 fn deserialize(
297 serialized_state: &SerializedState<Self>,
298 ) -> Result<Self, DeserializeStateError> {
299 let core = CShake256Core::deserialize(serialized_state)?;
300 Ok(Self {
301 core,
302 buffer: Default::default(),
303 })
304 }
305}