sha3/
macros.rs

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            /// Creates a new TurboSHAKE instance with the given domain separation.
248            /// Note that the domain separation needs to be a byte with a value in
249            /// the range [0x01, . . . , 0x7F]
250            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            /// Creates a new CSHAKE instance with the given customization.
379            pub fn new(customization: &[u8]) -> Self {
380                Self::new_with_function_name(&[], customization)
381            }
382
383            /// Creates a new CSHAKE instance with the given function name and customization.
384            /// Note that the function name is intended for use by NIST and should only be set to
385            /// values defined by NIST. You probably don't need to use this function.
386            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}