1macro_rules! impl_sha3 {
2 (
3 $name:ident, $full_name:ident, $output_size:ident,
4 $rate:ident, $pad:expr, $alg_name:expr $(,)?
5 ) => {
6 #[doc = "Core "]
7 #[doc = $alg_name]
8 #[doc = " hasher state."]
9 #[derive(Clone)]
10 #[allow(non_camel_case_types)]
11 pub struct $name {
12 state: Sha3State,
13 }
14
15 impl HashMarker for $name {}
16
17 impl BlockSizeUser for $name {
18 type BlockSize = $rate;
19 }
20
21 impl BufferKindUser for $name {
22 type BufferKind = Eager;
23 }
24
25 impl OutputSizeUser for $name {
26 type OutputSize = $output_size;
27 }
28
29 impl UpdateCore for $name {
30 #[inline]
31 fn update_blocks(&mut self, blocks: &[Block<Self>]) {
32 for block in blocks {
33 self.state.absorb_block(block)
34 }
35 }
36 }
37
38 impl FixedOutputCore for $name {
39 #[inline]
40 fn finalize_fixed_core(&mut self, buffer: &mut Buffer<Self>, out: &mut Output<Self>) {
41 let pos = buffer.get_pos();
42 let block = buffer.pad_with_zeros();
43 block[pos] = $pad;
44 let n = block.len();
45 block[n - 1] |= 0x80;
46
47 self.state.absorb_block(block);
48
49 self.state.as_bytes(out);
50 }
51 }
52
53 impl Default for $name {
54 #[inline]
55 fn default() -> Self {
56 Self {
57 state: Default::default(),
58 }
59 }
60 }
61
62 impl Reset for $name {
63 #[inline]
64 fn reset(&mut self) {
65 *self = Default::default();
66 }
67 }
68
69 impl AlgorithmName for $name {
70 fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
71 f.write_str(stringify!($full_name))
72 }
73 }
74
75 impl fmt::Debug for $name {
76 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
77 f.write_str(concat!(stringify!($name), " { ... }"))
78 }
79 }
80
81 #[doc = $alg_name]
82 #[doc = " hasher state."]
83 pub type $full_name = CoreWrapper<$name>;
84 };
85 (
86 $name:ident, $full_name:ident, $output_size:ident,
87 $rate:ident, $pad:expr, $alg_name:expr, $oid:literal $(,)?
88 ) => {
89 impl_sha3!($name, $full_name, $output_size, $rate, $pad, $alg_name);
90
91 #[cfg(feature = "oid")]
92 #[cfg_attr(docsrs, doc(cfg(feature = "oid")))]
93 impl AssociatedOid for $name {
94 const OID: ObjectIdentifier = ObjectIdentifier::new_unwrap($oid);
95 }
96 };
97}
98
99macro_rules! impl_shake {
100 (
101 $name:ident, $full_name:ident, $reader:ident, $reader_full:ident,
102 $rate:ident, $pad:expr, $alg_name:expr $(,)?
103 ) => {
104 #[doc = "Core "]
105 #[doc = $alg_name]
106 #[doc = " hasher state."]
107 #[derive(Clone)]
108 #[allow(non_camel_case_types)]
109 pub struct $name {
110 state: Sha3State,
111 }
112
113 impl HashMarker for $name {}
114
115 impl BlockSizeUser for $name {
116 type BlockSize = $rate;
117 }
118
119 impl BufferKindUser for $name {
120 type BufferKind = Eager;
121 }
122
123 impl UpdateCore for $name {
124 #[inline]
125 fn update_blocks(&mut self, blocks: &[Block<Self>]) {
126 for block in blocks {
127 self.state.absorb_block(block)
128 }
129 }
130 }
131
132 impl ExtendableOutputCore for $name {
133 type ReaderCore = $reader;
134
135 #[inline]
136 fn finalize_xof_core(&mut self, buffer: &mut Buffer<Self>) -> Self::ReaderCore {
137 let pos = buffer.get_pos();
138 let block = buffer.pad_with_zeros();
139 block[pos] = $pad;
140 let n = block.len();
141 block[n - 1] |= 0x80;
142
143 self.state.absorb_block(block);
144 $reader {
145 state: self.state.clone(),
146 }
147 }
148 }
149
150 impl Default for $name {
151 #[inline]
152 fn default() -> Self {
153 Self {
154 state: Default::default(),
155 }
156 }
157 }
158
159 impl Reset for $name {
160 #[inline]
161 fn reset(&mut self) {
162 *self = Default::default();
163 }
164 }
165
166 impl AlgorithmName for $name {
167 fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
168 f.write_str(stringify!($full_name))
169 }
170 }
171
172 impl fmt::Debug for $name {
173 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
174 f.write_str(concat!(stringify!($name), " { ... }"))
175 }
176 }
177
178 #[doc = "Core "]
179 #[doc = $alg_name]
180 #[doc = " reader state."]
181 #[derive(Clone)]
182 #[allow(non_camel_case_types)]
183 pub struct $reader {
184 state: Sha3State,
185 }
186
187 impl BlockSizeUser for $reader {
188 type BlockSize = $rate;
189 }
190
191 impl XofReaderCore for $reader {
192 #[inline]
193 fn read_block(&mut self) -> Block<Self> {
194 let mut block = Block::<Self>::default();
195 self.state.as_bytes(&mut block);
196 self.state.permute();
197 block
198 }
199 }
200
201 #[doc = $alg_name]
202 #[doc = " hasher state."]
203 pub type $full_name = CoreWrapper<$name>;
204
205 #[doc = $alg_name]
206 #[doc = " reader state."]
207 pub type $reader_full = XofReaderCoreWrapper<$reader>;
208 };
209 (
210 $name:ident, $full_name:ident, $reader:ident, $reader_full:ident,
211 $rate:ident, $pad:expr, $alg_name:expr, $oid:literal $(,)?
212 ) => {
213 impl_shake!(
214 $name,
215 $full_name,
216 $reader,
217 $reader_full,
218 $rate,
219 $pad,
220 $alg_name
221 );
222
223 #[cfg(feature = "oid")]
224 #[cfg_attr(docsrs, doc(cfg(feature = "oid")))]
225 impl AssociatedOid for $name {
226 const OID: ObjectIdentifier = ObjectIdentifier::new_unwrap($oid);
227 }
228 };
229}
230
231macro_rules! impl_turbo_shake {
232 (
233 $name:ident, $full_name:ident, $reader:ident, $reader_full:ident,
234 $rate:ident, $alg_name:expr $(,)?
235 ) => {
236 #[doc = "Core "]
237 #[doc = $alg_name]
238 #[doc = " hasher state."]
239 #[derive(Clone)]
240 #[allow(non_camel_case_types)]
241 pub struct $name {
242 domain_separation: u8,
243 state: Sha3State,
244 }
245
246 impl $name {
247 pub fn new(domain_separation: u8) -> Self {
251 assert!((0x01..=0x7F).contains(&domain_separation));
252 Self {
253 domain_separation,
254 state: Sha3State::new(TURBO_SHAKE_ROUND_COUNT),
255 }
256 }
257 }
258
259 impl HashMarker for $name {}
260
261 impl BlockSizeUser for $name {
262 type BlockSize = $rate;
263 }
264
265 impl BufferKindUser for $name {
266 type BufferKind = Eager;
267 }
268
269 impl UpdateCore for $name {
270 #[inline]
271 fn update_blocks(&mut self, blocks: &[Block<Self>]) {
272 for block in blocks {
273 self.state.absorb_block(block)
274 }
275 }
276 }
277
278 impl ExtendableOutputCore for $name {
279 type ReaderCore = $reader;
280
281 #[inline]
282 fn finalize_xof_core(&mut self, buffer: &mut Buffer<Self>) -> Self::ReaderCore {
283 let pos = buffer.get_pos();
284 let block = buffer.pad_with_zeros();
285 block[pos] = self.domain_separation;
286 let n = block.len();
287 block[n - 1] |= 0x80;
288
289 self.state.absorb_block(block);
290 $reader {
291 state: self.state.clone(),
292 }
293 }
294 }
295
296 impl Reset for $name {
297 #[inline]
298 fn reset(&mut self) {
299 *self = Self::new(self.domain_separation);
300 }
301 }
302
303 impl AlgorithmName for $name {
304 fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
305 f.write_str(stringify!($full_name))
306 }
307 }
308
309 impl fmt::Debug for $name {
310 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
311 f.write_str(concat!(stringify!($name), " { ... }"))
312 }
313 }
314
315 #[doc = "Core "]
316 #[doc = $alg_name]
317 #[doc = " reader state."]
318 #[derive(Clone)]
319 #[allow(non_camel_case_types)]
320 pub struct $reader {
321 state: Sha3State,
322 }
323
324 impl BlockSizeUser for $reader {
325 type BlockSize = $rate;
326 }
327
328 impl XofReaderCore for $reader {
329 #[inline]
330 fn read_block(&mut self) -> Block<Self> {
331 let mut block = Block::<Self>::default();
332 self.state.as_bytes(&mut block);
333 self.state.permute();
334 block
335 }
336 }
337
338 #[doc = $alg_name]
339 #[doc = " hasher state."]
340 pub type $full_name = CoreWrapper<$name>;
341
342 #[doc = $alg_name]
343 #[doc = " reader state."]
344 pub type $reader_full = XofReaderCoreWrapper<$reader>;
345 };
346 (
347 $name:ident, $full_name:ident, $reader:ident, $reader_full:ident,
348 $rate:ident, $alg_name:expr, $oid:literal $(,)?
349 ) => {
350 impl_turbo_shake!($name, $full_name, $reader, $reader_full, $rate, $alg_name);
351
352 #[cfg(feature = "oid")]
353 #[cfg_attr(docsrs, doc(cfg(feature = "oid")))]
354 impl AssociatedOid for $name {
355 const OID: ObjectIdentifier = ObjectIdentifier::new_unwrap($oid);
356 }
357 };
358}
359
360macro_rules! impl_cshake {
361 (
362 $name:ident, $full_name:ident, $reader:ident, $reader_full:ident,
363 $rate:ident, $shake_pad:expr, $cshake_pad:expr, $alg_name:expr,
364 ) => {
365 #[doc = "Core "]
366 #[doc = $alg_name]
367 #[doc = " hasher state."]
368 #[derive(Clone)]
369 #[allow(non_camel_case_types)]
370 pub struct $name {
371 padding: u8,
372 state: Sha3State,
373 #[cfg(feature = "reset")]
374 initial_state: Sha3State,
375 }
376
377 impl $name {
378 pub fn new(customization: &[u8]) -> Self {
380 Self::new_with_function_name(&[], customization)
381 }
382
383 pub fn new_with_function_name(function_name: &[u8], customization: &[u8]) -> Self {
387 let mut state = Sha3State::default();
388 if function_name.is_empty() && customization.is_empty() {
389 return Self {
390 padding: $shake_pad,
391 state: state.clone(),
392 #[cfg(feature = "reset")]
393 initial_state: state,
394 };
395 }
396
397 let mut buffer = Buffer::<Self>::default();
398 let mut b = [0u8; 9];
399 buffer.digest_blocks(left_encode($rate::to_u64(), &mut b), |blocks| {
400 for block in blocks {
401 state.absorb_block(block);
402 }
403 });
404 buffer.digest_blocks(
405 left_encode((function_name.len() * 8) as u64, &mut b),
406 |blocks| {
407 for block in blocks {
408 state.absorb_block(block);
409 }
410 },
411 );
412 buffer.digest_blocks(function_name, |blocks| {
413 for block in blocks {
414 state.absorb_block(block);
415 }
416 });
417 buffer.digest_blocks(
418 left_encode((customization.len() * 8) as u64, &mut b),
419 |blocks| {
420 for block in blocks {
421 state.absorb_block(block);
422 }
423 },
424 );
425 buffer.digest_blocks(customization, |blocks| {
426 for block in blocks {
427 state.absorb_block(block);
428 }
429 });
430 state.absorb_block(buffer.pad_with_zeros());
431
432 Self {
433 padding: $cshake_pad,
434 state: state.clone(),
435 #[cfg(feature = "reset")]
436 initial_state: state,
437 }
438 }
439 }
440
441 impl HashMarker for $name {}
442
443 impl BlockSizeUser for $name {
444 type BlockSize = $rate;
445 }
446
447 impl BufferKindUser for $name {
448 type BufferKind = Eager;
449 }
450
451 impl UpdateCore for $name {
452 #[inline]
453 fn update_blocks(&mut self, blocks: &[Block<Self>]) {
454 for block in blocks {
455 self.state.absorb_block(block)
456 }
457 }
458 }
459
460 impl ExtendableOutputCore for $name {
461 type ReaderCore = $reader;
462
463 #[inline]
464 fn finalize_xof_core(&mut self, buffer: &mut Buffer<Self>) -> Self::ReaderCore {
465 let pos = buffer.get_pos();
466 let block = buffer.pad_with_zeros();
467 block[pos] = self.padding;
468 let n = block.len();
469 block[n - 1] |= 0x80;
470
471 self.state.absorb_block(block);
472 $reader {
473 state: self.state.clone(),
474 }
475 }
476 }
477
478 #[cfg(feature = "reset")]
479 impl Reset for $name {
480 #[inline]
481 fn reset(&mut self) {
482 self.state = self.initial_state.clone();
483 }
484 }
485
486 impl AlgorithmName for $name {
487 fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
488 f.write_str(stringify!($full_name))
489 }
490 }
491
492 impl fmt::Debug for $name {
493 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
494 f.write_str(concat!(stringify!($name), " { ... }"))
495 }
496 }
497
498 #[doc = "Core "]
499 #[doc = $alg_name]
500 #[doc = " reader state."]
501 #[derive(Clone)]
502 #[allow(non_camel_case_types)]
503 pub struct $reader {
504 state: Sha3State,
505 }
506
507 impl BlockSizeUser for $reader {
508 type BlockSize = $rate;
509 }
510
511 impl XofReaderCore for $reader {
512 #[inline]
513 fn read_block(&mut self) -> Block<Self> {
514 let mut block = Block::<Self>::default();
515 self.state.as_bytes(&mut block);
516 self.state.permute();
517 block
518 }
519 }
520
521 #[doc = $alg_name]
522 #[doc = " hasher state."]
523 pub type $full_name = CoreWrapper<$name>;
524
525 #[doc = $alg_name]
526 #[doc = " reader state."]
527 pub type $reader_full = XofReaderCoreWrapper<$reader>;
528 };
529}