lib_q_sha3/
turbo_shake.rs1use core::fmt;
6
7use digest::block_api::{
8 AlgorithmName,
9 BlockSizeUser,
10 ExtendableOutputCore,
11 Reset,
12 UpdateCore,
13 XofReaderCore,
14};
15use digest::block_buffer::{
16 EagerBuffer,
17 ReadBuffer,
18};
19use digest::consts::{
20 U0,
21 U16,
22 U32,
23 U136,
24 U168,
25};
26use digest::{
27 CollisionResistance,
28 ExtendableOutput,
29 ExtendableOutputReset,
30 HashMarker,
31 Update,
32 XofReader,
33};
34
35use crate::{
36 SpongeHasherCore,
37 SpongeReaderCore,
38};
39
40const TURBO_SHAKE_ROUND_COUNT: usize = 12;
41
42macro_rules! impl_turbo_shake {
43 (
44 $name:ident, $reader_name:ident, $rate:ty, $alg_name:expr
45 ) => {
46 #[doc = $alg_name]
47 #[doc = " hasher."]
48 #[derive(Clone)]
49 pub struct $name<const DS: u8> {
50 core: SpongeHasherCore<$rate, U0, DS, TURBO_SHAKE_ROUND_COUNT>,
51 buffer: EagerBuffer<$rate>,
52 }
53
54 impl<const DS: u8> Default for $name<DS> {
55 #[inline]
56 fn default() -> Self {
57 assert!((0x01..=0x7F).contains(&DS), "invalid domain separator");
58 Self {
59 core: Default::default(),
60 buffer: Default::default(),
61 }
62 }
63 }
64
65 impl<const DS: u8> HashMarker for $name<DS> {}
66
67 impl<const DS: u8> BlockSizeUser for $name<DS> {
68 type BlockSize = $rate;
69 }
70
71 impl<const DS: u8> Update for $name<DS> {
72 #[inline]
73 fn update(&mut self, data: &[u8]) {
74 let Self { core, buffer } = self;
75 buffer.digest_blocks(data, |blocks| core.update_blocks(blocks));
76 }
77 }
78
79 impl<const DS: u8> ExtendableOutput for $name<DS> {
80 type Reader = $reader_name;
81
82 #[inline]
83 fn finalize_xof(mut self) -> Self::Reader {
84 let Self { core, buffer } = &mut self;
85 let core = core.finalize_xof_core(buffer);
86 let buffer = Default::default();
87 Self::Reader { core, buffer }
88 }
89 }
90
91 impl<const DS: u8> ExtendableOutputReset for $name<DS> {
92 #[inline]
93 fn finalize_xof_reset(&mut self) -> Self::Reader {
94 let Self { core, buffer } = self;
95 let core = core.finalize_xof_core(buffer);
96 self.reset();
97 let buffer = Default::default();
98 Self::Reader { core, buffer }
99 }
100 }
101
102 impl<const DS: u8> Reset for $name<DS> {
103 #[inline]
104 fn reset(&mut self) {
105 *self = Default::default();
106 }
107 }
108
109 impl<const DS: u8> AlgorithmName for $name<DS> {
110 fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
111 f.write_str($alg_name)
112 }
113 }
114
115 impl<const DS: u8> fmt::Debug for $name<DS> {
116 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
117 f.write_str(concat!(stringify!($name), " { ... }"))
118 }
119 }
120
121 #[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))]
122 #[cfg(feature = "zeroize")]
123 impl<const DS: u8> digest::zeroize::ZeroizeOnDrop for $name<DS> {}
124
125 #[doc = $alg_name]
126 #[doc = " XOF reader."]
127 #[derive(Clone)]
128 pub struct $reader_name {
129 core: SpongeReaderCore<$rate, TURBO_SHAKE_ROUND_COUNT>,
130 buffer: ReadBuffer<$rate>,
131 }
132
133 impl XofReader for $reader_name {
134 #[inline]
135 fn read(&mut self, buf: &mut [u8]) {
136 let Self { core, buffer } = self;
137 buffer.read(buf, |block| {
138 *block = core.read_block();
139 });
140 }
141 }
142
143 impl fmt::Debug for $reader_name {
144 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
145 f.write_str(concat!(stringify!($reader_name), " { ... }"))
146 }
147 }
148 };
149}
150
151impl_turbo_shake!(TurboShake128, TurboShake128Reader, U168, "TurboSHAKE128");
152impl_turbo_shake!(TurboShake256, TurboShake256Reader, U136, "TurboSHAKE256");
153
154impl<const DS: u8> CollisionResistance for TurboShake128<DS> {
155 type CollisionResistance = U16;
157}
158
159impl<const DS: u8> CollisionResistance for TurboShake256<DS> {
160 type CollisionResistance = U32;
162}