1#![allow(clippy::needless_range_loop)]
2use crate::table::TABLE;
3use core::{convert::TryInto, u64};
4
5pub(crate) const COLS: usize = 16;
6const ROUNDS: u64 = 14;
7
8#[inline(always)]
9fn column(x: &[u64; COLS], c: [usize; 8]) -> u64 {
10 let mut t = 0;
11 for i in 0..8 {
12 let sl = 8 * (7 - i);
13 let idx = ((x[c[i]] >> sl) & 0xFF) as usize;
14 t ^= TABLE[i][idx];
15 }
16 t
17}
18
19#[inline(always)]
20fn rndq(mut x: [u64; COLS], r: u64) -> [u64; COLS] {
21 for i in 0..COLS {
22 x[i] ^= u64::MAX.wrapping_sub((i as u64) << 4) ^ r;
23 }
24 [
25 column(&x, [1, 3, 5, 11, 0, 2, 4, 6]),
26 column(&x, [2, 4, 6, 12, 1, 3, 5, 7]),
27 column(&x, [3, 5, 7, 13, 2, 4, 6, 8]),
28 column(&x, [4, 6, 8, 14, 3, 5, 7, 9]),
29 column(&x, [5, 7, 9, 15, 4, 6, 8, 10]),
30 column(&x, [6, 8, 10, 0, 5, 7, 9, 11]),
31 column(&x, [7, 9, 11, 1, 6, 8, 10, 12]),
32 column(&x, [8, 10, 12, 2, 7, 9, 11, 13]),
33 column(&x, [9, 11, 13, 3, 8, 10, 12, 14]),
34 column(&x, [10, 12, 14, 4, 9, 11, 13, 15]),
35 column(&x, [11, 13, 15, 5, 10, 12, 14, 0]),
36 column(&x, [12, 14, 0, 6, 11, 13, 15, 1]),
37 column(&x, [13, 15, 1, 7, 12, 14, 0, 2]),
38 column(&x, [14, 0, 2, 8, 13, 15, 1, 3]),
39 column(&x, [15, 1, 3, 9, 14, 0, 2, 4]),
40 column(&x, [0, 2, 4, 10, 15, 1, 3, 5]),
41 ]
42}
43
44#[inline(always)]
45fn rndp(mut x: [u64; COLS], r: u64) -> [u64; COLS] {
46 for i in 0..COLS {
47 x[i] ^= ((i as u64) << 60) ^ r;
48 }
49 [
50 column(&x, [0, 1, 2, 3, 4, 5, 6, 11]),
51 column(&x, [1, 2, 3, 4, 5, 6, 7, 12]),
52 column(&x, [2, 3, 4, 5, 6, 7, 8, 13]),
53 column(&x, [3, 4, 5, 6, 7, 8, 9, 14]),
54 column(&x, [4, 5, 6, 7, 8, 9, 10, 15]),
55 column(&x, [5, 6, 7, 8, 9, 10, 11, 0]),
56 column(&x, [6, 7, 8, 9, 10, 11, 12, 1]),
57 column(&x, [7, 8, 9, 10, 11, 12, 13, 2]),
58 column(&x, [8, 9, 10, 11, 12, 13, 14, 3]),
59 column(&x, [9, 10, 11, 12, 13, 14, 15, 4]),
60 column(&x, [10, 11, 12, 13, 14, 15, 0, 5]),
61 column(&x, [11, 12, 13, 14, 15, 0, 1, 6]),
62 column(&x, [12, 13, 14, 15, 0, 1, 2, 7]),
63 column(&x, [13, 14, 15, 0, 1, 2, 3, 8]),
64 column(&x, [14, 15, 0, 1, 2, 3, 4, 9]),
65 column(&x, [15, 0, 1, 2, 3, 4, 5, 10]),
66 ]
67}
68
69pub(crate) fn compress(h: &mut [u64; COLS], block: &[u8; 128]) {
70 let mut q = [0u64; COLS];
71 for (chunk, v) in block.chunks_exact(8).zip(q.iter_mut()) {
72 *v = u64::from_be_bytes(chunk.try_into().unwrap());
73 }
74 let mut p = [0u64; COLS];
75 for i in 0..COLS {
76 p[i] = h[i] ^ q[i];
77 }
78 for i in 0..ROUNDS {
79 q = rndq(q, i);
80 }
81 for i in 0..ROUNDS {
82 p = rndp(p, i << 56);
83 }
84 for i in 0..COLS {
85 h[i] ^= q[i] ^ p[i];
86 }
87}
88
89pub(crate) fn p(h: &[u64; COLS]) -> [u64; COLS] {
90 let mut p = *h;
91 for i in 0..ROUNDS {
92 p = rndp(p, i << 56);
93 }
94 for i in 0..COLS {
95 p[i] ^= h[i];
96 }
97 p
98}