1#![no_std]
5#![cfg_attr(docsrs, feature(doc_auto_cfg))]
6#![doc = include_str!("../README.md")]
7#![doc(
8 html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg",
9 html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg"
10)]
11#![forbid(unsafe_code)]
12#![warn(missing_docs)]
13
14use core::mem::size_of;
15#[cfg(feature = "zeroize")]
16use zeroize::{Zeroize, ZeroizeOnDrop};
17
18#[inline(always)]
20pub const fn pad(n: usize) -> u64 {
21 0x80_u64 << (56 - 8 * n)
22}
23
24#[inline(always)]
26const fn round_constant(round: u64) -> u64 {
27 ((0xfu64 - round) << 4) | round
28}
29
30#[derive(Clone, Debug, Default)]
34pub struct State {
35 x: [u64; 5],
36}
37
38const fn round(x: [u64; 5], c: u64) -> [u64; 5] {
40 let x0 = x[0] ^ x[4];
42 let x2 = x[2] ^ x[1] ^ c; let x4 = x[4] ^ x[3];
44
45 let tx0 = x0 ^ (!x[1] & x2);
46 let tx1 = x[1] ^ (!x2 & x[3]);
47 let tx2 = x2 ^ (!x[3] & x4);
48 let tx3 = x[3] ^ (!x4 & x0);
49 let tx4 = x4 ^ (!x0 & x[1]);
50 let tx1 = tx1 ^ tx0;
51 let tx3 = tx3 ^ tx2;
52 let tx0 = tx0 ^ tx4;
53
54 let x0 = tx0 ^ tx0.rotate_right(9);
56 let x1 = tx1 ^ tx1.rotate_right(22);
57 let x2 = tx2 ^ tx2.rotate_right(5);
58 let x3 = tx3 ^ tx3.rotate_right(7);
59 let x4 = tx4 ^ tx4.rotate_right(34);
60 [
61 tx0 ^ x0.rotate_right(19),
62 tx1 ^ x1.rotate_right(39),
63 !(tx2 ^ x2.rotate_right(1)),
64 tx3 ^ x3.rotate_right(10),
65 tx4 ^ x4.rotate_right(7),
66 ]
67}
68
69impl State {
70 pub fn new(x0: u64, x1: u64, x2: u64, x3: u64, x4: u64) -> Self {
72 State {
73 x: [x0, x1, x2, x3, x4],
74 }
75 }
76
77 #[cfg(not(feature = "no_unroll"))]
78 pub fn permute_12(&mut self) {
80 self.x = round(
84 round(
85 round(
86 round(
87 round(
88 round(
89 round(
90 round(
91 round(round(round(round(self.x, 0xf0), 0xe1), 0xd2), 0xc3),
92 0xb4,
93 ),
94 0xa5,
95 ),
96 0x96,
97 ),
98 0x87,
99 ),
100 0x78,
101 ),
102 0x69,
103 ),
104 0x5a,
105 ),
106 0x4b,
107 );
108 }
109
110 #[cfg(feature = "no_unroll")]
111 pub fn permute_12(&mut self) {
113 self.x = [
114 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87, 0x78, 0x69, 0x5a, 0x4b,
115 ]
116 .into_iter()
117 .fold(self.x, round);
118 }
119
120 #[cfg(not(feature = "no_unroll"))]
121 pub fn permute_8(&mut self) {
123 self.x = round(
124 round(
125 round(
126 round(
127 round(round(round(round(self.x, 0xb4), 0xa5), 0x96), 0x87),
128 0x78,
129 ),
130 0x69,
131 ),
132 0x5a,
133 ),
134 0x4b,
135 );
136 }
137
138 #[cfg(feature = "no_unroll")]
139 pub fn permute_8(&mut self) {
141 self.x = [0xb4, 0xa5, 0x96, 0x87, 0x78, 0x69, 0x5a, 0x4b]
142 .into_iter()
143 .fold(self.x, round);
144 }
145
146 #[cfg(not(feature = "no_unroll"))]
147 pub fn permute_6(&mut self) {
149 self.x = round(
150 round(
151 round(round(round(round(self.x, 0x96), 0x87), 0x78), 0x69),
152 0x5a,
153 ),
154 0x4b,
155 );
156 }
157
158 #[cfg(feature = "no_unroll")]
159 pub fn permute_6(&mut self) {
161 self.x = [0x96, 0x87, 0x78, 0x69, 0x5a, 0x4b]
162 .into_iter()
163 .fold(self.x, round);
164 }
165
166 pub fn permute_1(&mut self) {
168 self.x = round(self.x, 0x4b);
169 }
170
171 pub fn permute_n(&mut self, rounds: usize) {
175 debug_assert!(rounds <= 12);
176
177 let start = 12 - rounds;
178 self.x = (start..12).fold(self.x, |x, round_index| {
179 round(x, round_constant(round_index as u64))
180 });
181 }
182
183 pub fn as_bytes(&self) -> [u8; 40] {
185 let mut bytes = [0u8; size_of::<u64>() * 5];
186 for (dst, src) in bytes
187 .chunks_exact_mut(size_of::<u64>())
188 .zip(self.x.into_iter())
189 {
190 dst.copy_from_slice(&u64::to_be_bytes(src));
191 }
192 bytes
193 }
194}
195
196impl core::ops::Index<usize> for State {
197 type Output = u64;
198
199 #[inline(always)]
200 fn index(&self, index: usize) -> &Self::Output {
201 &self.x[index]
202 }
203}
204
205impl core::ops::IndexMut<usize> for State {
206 #[inline(always)]
207 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
208 &mut self.x[index]
209 }
210}
211
212impl TryFrom<&[u64]> for State {
213 type Error = ();
214
215 fn try_from(value: &[u64]) -> Result<Self, Self::Error> {
216 match value.len() {
217 5 => Ok(Self::new(value[0], value[1], value[2], value[3], value[4])),
218 _ => Err(()),
219 }
220 }
221}
222
223impl From<&[u64; 5]> for State {
224 fn from(value: &[u64; 5]) -> Self {
225 Self { x: *value }
226 }
227}
228
229impl TryFrom<&[u8]> for State {
230 type Error = ();
231
232 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
233 if value.len() != core::mem::size_of::<u64>() * 5 {
234 return Err(());
235 }
236
237 let mut state = Self::default();
238 for (src, dst) in value
239 .chunks_exact(core::mem::size_of::<u64>())
240 .zip(state.x.iter_mut())
241 {
242 *dst = u64::from_be_bytes(src.try_into().unwrap());
243 }
244 Ok(state)
245 }
246}
247
248impl From<&[u8; size_of::<u64>() * 5]> for State {
249 fn from(value: &[u8; size_of::<u64>() * 5]) -> Self {
250 let mut state = Self::default();
251 for (src, dst) in value
252 .chunks_exact(core::mem::size_of::<u64>())
253 .zip(state.x.iter_mut())
254 {
255 *dst = u64::from_be_bytes(src.try_into().unwrap());
256 }
257 state
258 }
259}
260
261impl AsRef<[u64]> for State {
262 fn as_ref(&self) -> &[u64] {
263 &self.x
264 }
265}
266
267#[cfg(feature = "zeroize")]
268impl Drop for State {
269 fn drop(&mut self) {
270 self.x.zeroize();
271 }
272}
273
274#[cfg(feature = "zeroize")]
275impl ZeroizeOnDrop for State {}
276
277#[cfg(test)]
278mod tests {
279 use super::*;
280
281 #[test]
282 fn pad_0to7() {
283 assert_eq!(pad(0), 0x8000000000000000);
284 assert_eq!(pad(1), 0x80000000000000);
285 assert_eq!(pad(2), 0x800000000000);
286 assert_eq!(pad(3), 0x8000000000);
287 assert_eq!(pad(4), 0x80000000);
288 assert_eq!(pad(5), 0x800000);
289 assert_eq!(pad(6), 0x8000);
290 assert_eq!(pad(7), 0x80);
291 }
292
293 #[test]
294 fn round_constants() {
295 assert_eq!(round_constant(0), 0xf0);
296 assert_eq!(round_constant(1), 0xe1);
297 assert_eq!(round_constant(2), 0xd2);
298 assert_eq!(round_constant(3), 0xc3);
299 assert_eq!(round_constant(4), 0xb4);
300 assert_eq!(round_constant(5), 0xa5);
301 assert_eq!(round_constant(6), 0x96);
302 assert_eq!(round_constant(7), 0x87);
303 assert_eq!(round_constant(8), 0x78);
304 assert_eq!(round_constant(9), 0x69);
305 assert_eq!(round_constant(10), 0x5a);
306 assert_eq!(round_constant(11), 0x4b);
307 }
308
309 #[test]
310 fn one_round() {
311 let state = round(
312 [
313 0x0123456789abcdef,
314 0x23456789abcdef01,
315 0x456789abcdef0123,
316 0x6789abcdef012345,
317 0x89abcde01234567f,
318 ],
319 0x1f,
320 );
321 assert_eq!(
322 state,
323 [
324 0x3c1748c9be2892ce,
325 0x5eafb305cd26164f,
326 0xf9470254bb3a4213,
327 0xf0428daf0c5d3948,
328 0x281375af0b294899
329 ]
330 );
331 }
332
333 #[test]
334 fn state_permute_12() {
335 let mut state = State::new(
336 0x0123456789abcdef,
337 0xef0123456789abcd,
338 0xcdef0123456789ab,
339 0xabcdef0123456789,
340 0x89abcdef01234567,
341 );
342 state.permute_12();
343 assert_eq!(state[0], 0x206416dfc624bb14);
344 assert_eq!(state[1], 0x1b0c47a601058aab);
345 assert_eq!(state[2], 0x8934cfc93814cddd);
346 assert_eq!(state[3], 0xa9738d287a748e4b);
347 assert_eq!(state[4], 0xddd934f058afc7e1);
348 }
349
350 #[test]
351 fn state_permute_6() {
352 let mut state = State::new(
353 0x0123456789abcdef,
354 0xef0123456789abcd,
355 0xcdef0123456789ab,
356 0xabcdef0123456789,
357 0x89abcdef01234567,
358 );
359 state.permute_6();
360 assert_eq!(state[0], 0xc27b505c635eb07f);
361 assert_eq!(state[1], 0xd388f5d2a72046fa);
362 assert_eq!(state[2], 0x9e415c204d7b15e7);
363 assert_eq!(state[3], 0xce0d71450fe44581);
364 assert_eq!(state[4], 0xdd7c5fef57befe48);
365 }
366
367 #[test]
368 fn state_permute_8() {
369 let mut state = State::new(
370 0x0123456789abcdef,
371 0xef0123456789abcd,
372 0xcdef0123456789ab,
373 0xabcdef0123456789,
374 0x89abcdef01234567,
375 );
376 state.permute_8();
377 assert_eq!(state[0], 0x67ed228272f46eee);
378 assert_eq!(state[1], 0x80bc0b097aad7944);
379 assert_eq!(state[2], 0x2fa599382c6db215);
380 assert_eq!(state[3], 0x368133fae2f7667a);
381 assert_eq!(state[4], 0x28cefb195a7c651c);
382 }
383
384 #[test]
385 fn state_permute_n() {
386 let mut state = State::new(
387 0x0123456789abcdef,
388 0xef0123456789abcd,
389 0xcdef0123456789ab,
390 0xabcdef0123456789,
391 0x89abcdef01234567,
392 );
393 let mut state2 = state.clone();
394
395 state.permute_6();
396 state2.permute_n(6);
397 assert_eq!(state.x, state2.x);
398
399 state.permute_8();
400 state2.permute_n(8);
401 assert_eq!(state.x, state2.x);
402
403 state.permute_12();
404 state2.permute_n(12);
405 assert_eq!(state.x, state2.x);
406 }
407
408 #[test]
409 fn state_convert_bytes() {
410 let state = State::new(
411 0x0123456789abcdef,
412 0xef0123456789abcd,
413 0xcdef0123456789ab,
414 0xabcdef0123456789,
415 0x89abcdef01234567,
416 );
417 let bytes = state.as_bytes();
418
419 let state2 = State::try_from(&bytes[..]);
421 assert_eq!(state2.expect("try_from bytes").x, state.x);
422
423 let state2 = State::from(&bytes);
424 assert_eq!(state2.x, state.x);
425 }
426}