1use universal_hash::{
16 consts::{U1, U16},
17 crypto_common::{BlockSizeUser, ParBlocksSizeUser},
18 UhfBackend, UniversalHash,
19};
20
21use crate::{Block, Key, Tag};
22
23#[derive(Clone, Default)]
24pub(crate) struct State {
25 r: [u32; 5],
26 h: [u32; 5],
27 pad: [u32; 4],
28}
29
30impl State {
31 pub(crate) fn new(key: &Key) -> State {
33 let mut poly = State::default();
34
35 poly.r[0] = (u32::from_le_bytes(key[0..4].try_into().unwrap())) & 0x3ff_ffff;
37 poly.r[1] = (u32::from_le_bytes(key[3..7].try_into().unwrap()) >> 2) & 0x3ff_ff03;
38 poly.r[2] = (u32::from_le_bytes(key[6..10].try_into().unwrap()) >> 4) & 0x3ff_c0ff;
39 poly.r[3] = (u32::from_le_bytes(key[9..13].try_into().unwrap()) >> 6) & 0x3f0_3fff;
40 poly.r[4] = (u32::from_le_bytes(key[12..16].try_into().unwrap()) >> 8) & 0x00f_ffff;
41
42 poly.pad[0] = u32::from_le_bytes(key[16..20].try_into().unwrap());
43 poly.pad[1] = u32::from_le_bytes(key[20..24].try_into().unwrap());
44 poly.pad[2] = u32::from_le_bytes(key[24..28].try_into().unwrap());
45 poly.pad[3] = u32::from_le_bytes(key[28..32].try_into().unwrap());
46
47 poly
48 }
49
50 pub(crate) fn compute_block(&mut self, block: &Block, partial: bool) {
52 let hibit = if partial { 0 } else { 1 << 24 };
53
54 let r0 = self.r[0];
55 let r1 = self.r[1];
56 let r2 = self.r[2];
57 let r3 = self.r[3];
58 let r4 = self.r[4];
59
60 let s1 = r1 * 5;
61 let s2 = r2 * 5;
62 let s3 = r3 * 5;
63 let s4 = r4 * 5;
64
65 let mut h0 = self.h[0];
66 let mut h1 = self.h[1];
67 let mut h2 = self.h[2];
68 let mut h3 = self.h[3];
69 let mut h4 = self.h[4];
70
71 h0 += (u32::from_le_bytes(block[0..4].try_into().unwrap())) & 0x3ff_ffff;
73 h1 += (u32::from_le_bytes(block[3..7].try_into().unwrap()) >> 2) & 0x3ff_ffff;
74 h2 += (u32::from_le_bytes(block[6..10].try_into().unwrap()) >> 4) & 0x3ff_ffff;
75 h3 += (u32::from_le_bytes(block[9..13].try_into().unwrap()) >> 6) & 0x3ff_ffff;
76 h4 += (u32::from_le_bytes(block[12..16].try_into().unwrap()) >> 8) | hibit;
77
78 let d0 = (u64::from(h0) * u64::from(r0))
80 + (u64::from(h1) * u64::from(s4))
81 + (u64::from(h2) * u64::from(s3))
82 + (u64::from(h3) * u64::from(s2))
83 + (u64::from(h4) * u64::from(s1));
84
85 let mut d1 = (u64::from(h0) * u64::from(r1))
86 + (u64::from(h1) * u64::from(r0))
87 + (u64::from(h2) * u64::from(s4))
88 + (u64::from(h3) * u64::from(s3))
89 + (u64::from(h4) * u64::from(s2));
90
91 let mut d2 = (u64::from(h0) * u64::from(r2))
92 + (u64::from(h1) * u64::from(r1))
93 + (u64::from(h2) * u64::from(r0))
94 + (u64::from(h3) * u64::from(s4))
95 + (u64::from(h4) * u64::from(s3));
96
97 let mut d3 = (u64::from(h0) * u64::from(r3))
98 + (u64::from(h1) * u64::from(r2))
99 + (u64::from(h2) * u64::from(r1))
100 + (u64::from(h3) * u64::from(r0))
101 + (u64::from(h4) * u64::from(s4));
102
103 let mut d4 = (u64::from(h0) * u64::from(r4))
104 + (u64::from(h1) * u64::from(r3))
105 + (u64::from(h2) * u64::from(r2))
106 + (u64::from(h3) * u64::from(r1))
107 + (u64::from(h4) * u64::from(r0));
108
109 let mut c: u32;
111 c = (d0 >> 26) as u32;
112 h0 = d0 as u32 & 0x3ff_ffff;
113 d1 += u64::from(c);
114
115 c = (d1 >> 26) as u32;
116 h1 = d1 as u32 & 0x3ff_ffff;
117 d2 += u64::from(c);
118
119 c = (d2 >> 26) as u32;
120 h2 = d2 as u32 & 0x3ff_ffff;
121 d3 += u64::from(c);
122
123 c = (d3 >> 26) as u32;
124 h3 = d3 as u32 & 0x3ff_ffff;
125 d4 += u64::from(c);
126
127 c = (d4 >> 26) as u32;
128 h4 = d4 as u32 & 0x3ff_ffff;
129 h0 += c * 5;
130
131 c = h0 >> 26;
132 h0 &= 0x3ff_ffff;
133 h1 += c;
134
135 self.h[0] = h0;
136 self.h[1] = h1;
137 self.h[2] = h2;
138 self.h[3] = h3;
139 self.h[4] = h4;
140 }
141
142 pub(crate) fn finalize_mut(&mut self) -> Tag {
144 let mut h0 = self.h[0];
146 let mut h1 = self.h[1];
147 let mut h2 = self.h[2];
148 let mut h3 = self.h[3];
149 let mut h4 = self.h[4];
150
151 let mut c: u32;
152 c = h1 >> 26;
153 h1 &= 0x3ff_ffff;
154 h2 += c;
155
156 c = h2 >> 26;
157 h2 &= 0x3ff_ffff;
158 h3 += c;
159
160 c = h3 >> 26;
161 h3 &= 0x3ff_ffff;
162 h4 += c;
163
164 c = h4 >> 26;
165 h4 &= 0x3ff_ffff;
166 h0 += c * 5;
167
168 c = h0 >> 26;
169 h0 &= 0x3ff_ffff;
170 h1 += c;
171
172 let mut g0 = h0.wrapping_add(5);
174 c = g0 >> 26;
175 g0 &= 0x3ff_ffff;
176
177 let mut g1 = h1.wrapping_add(c);
178 c = g1 >> 26;
179 g1 &= 0x3ff_ffff;
180
181 let mut g2 = h2.wrapping_add(c);
182 c = g2 >> 26;
183 g2 &= 0x3ff_ffff;
184
185 let mut g3 = h3.wrapping_add(c);
186 c = g3 >> 26;
187 g3 &= 0x3ff_ffff;
188
189 let mut g4 = h4.wrapping_add(c).wrapping_sub(1 << 26);
190
191 let mut mask = (g4 >> (32 - 1)).wrapping_sub(1);
193 g0 &= mask;
194 g1 &= mask;
195 g2 &= mask;
196 g3 &= mask;
197 g4 &= mask;
198 mask = !mask;
199 h0 = (h0 & mask) | g0;
200 h1 = (h1 & mask) | g1;
201 h2 = (h2 & mask) | g2;
202 h3 = (h3 & mask) | g3;
203 h4 = (h4 & mask) | g4;
204
205 h0 |= h1 << 26;
207 h1 = (h1 >> 6) | (h2 << 20);
208 h2 = (h2 >> 12) | (h3 << 14);
209 h3 = (h3 >> 18) | (h4 << 8);
210
211 let mut f: u64;
213 f = u64::from(h0) + u64::from(self.pad[0]);
214 h0 = f as u32;
215
216 f = u64::from(h1) + u64::from(self.pad[1]) + (f >> 32);
217 h1 = f as u32;
218
219 f = u64::from(h2) + u64::from(self.pad[2]) + (f >> 32);
220 h2 = f as u32;
221
222 f = u64::from(h3) + u64::from(self.pad[3]) + (f >> 32);
223 h3 = f as u32;
224
225 let mut tag = Block::default();
226 tag[0..4].copy_from_slice(&h0.to_le_bytes());
227 tag[4..8].copy_from_slice(&h1.to_le_bytes());
228 tag[8..12].copy_from_slice(&h2.to_le_bytes());
229 tag[12..16].copy_from_slice(&h3.to_le_bytes());
230
231 tag
232 }
233}
234
235#[cfg(feature = "zeroize")]
236impl Drop for State {
237 fn drop(&mut self) {
238 use zeroize::Zeroize;
239 self.r.zeroize();
240 self.h.zeroize();
241 self.pad.zeroize();
242 }
243}
244
245impl BlockSizeUser for State {
246 type BlockSize = U16;
247}
248
249impl ParBlocksSizeUser for State {
250 type ParBlocksSize = U1;
251}
252
253impl UhfBackend for State {
254 fn proc_block(&mut self, block: &Block) {
255 self.compute_block(block, false);
256 }
257}
258
259impl UniversalHash for State {
260 fn update_with_backend(
261 &mut self,
262 f: impl universal_hash::UhfClosure<BlockSize = Self::BlockSize>,
263 ) {
264 f.call(self);
265 }
266
267 fn finalize(mut self) -> Tag {
269 self.finalize_mut()
270 }
271}