1#![allow(clippy::needless_range_loop)]
2use crate::table::TABLE;
3use core::{convert::TryInto, u64};
4
5pub(crate) const COLS: usize = 8;
6const ROUNDS: u64 = 10;
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, 7, 0, 2, 4, 6]),
26 column(&x, [2, 4, 6, 0, 1, 3, 5, 7]),
27 column(&x, [3, 5, 7, 1, 2, 4, 6, 0]),
28 column(&x, [4, 6, 0, 2, 3, 5, 7, 1]),
29 column(&x, [5, 7, 1, 3, 4, 6, 0, 2]),
30 column(&x, [6, 0, 2, 4, 5, 7, 1, 3]),
31 column(&x, [7, 1, 3, 5, 6, 0, 2, 4]),
32 column(&x, [0, 2, 4, 6, 7, 1, 3, 5]),
33 ]
34}
35
36#[inline(always)]
37fn rndp(mut x: [u64; COLS], r: u64) -> [u64; COLS] {
38 for i in 0..COLS {
39 x[i] ^= ((i as u64) << 60) ^ r;
40 }
41 [
42 column(&x, [0, 1, 2, 3, 4, 5, 6, 7]),
43 column(&x, [1, 2, 3, 4, 5, 6, 7, 0]),
44 column(&x, [2, 3, 4, 5, 6, 7, 0, 1]),
45 column(&x, [3, 4, 5, 6, 7, 0, 1, 2]),
46 column(&x, [4, 5, 6, 7, 0, 1, 2, 3]),
47 column(&x, [5, 6, 7, 0, 1, 2, 3, 4]),
48 column(&x, [6, 7, 0, 1, 2, 3, 4, 5]),
49 column(&x, [7, 0, 1, 2, 3, 4, 5, 6]),
50 ]
51}
52
53pub(crate) fn compress(h: &mut [u64; COLS], block: &[u8; 64]) {
54 let mut q = [0u64; COLS];
55 for (chunk, v) in block.chunks_exact(8).zip(q.iter_mut()) {
56 *v = u64::from_be_bytes(chunk.try_into().unwrap());
57 }
58 let mut p = [0u64; COLS];
59 for i in 0..COLS {
60 p[i] = h[i] ^ q[i];
61 }
62 for i in 0..ROUNDS {
63 q = rndq(q, i);
64 }
65 for i in 0..ROUNDS {
66 p = rndp(p, i << 56);
67 }
68 for i in 0..COLS {
69 h[i] ^= q[i] ^ p[i];
70 }
71}
72
73pub(crate) fn p(h: &[u64; COLS]) -> [u64; COLS] {
74 let mut p = *h;
75 for i in 0..ROUNDS {
76 p = rndp(p, i << 56);
77 }
78 for i in 0..COLS {
79 p[i] ^= h[i];
80 }
81 p
82}