keccak-rust 1.0.2

Keccak implementation in Rust
Documentation
use crunchy::unroll;

use super::*;

type WordLen = usize;
type Log = usize;

pub struct KeccakF {
    perm_num: PermutationsNum,
}

impl KeccakF {
    pub fn new(width: StateBitsWidth) -> KeccakF {
        let perm_num = match width {
            StateBitsWidth::F25 => PERMUTATIONS_NUM[0],
            StateBitsWidth::F50 => PERMUTATIONS_NUM[1],
            StateBitsWidth::F100 => PERMUTATIONS_NUM[2],
            StateBitsWidth::F200 => PERMUTATIONS_NUM[3],
            StateBitsWidth::F400 => PERMUTATIONS_NUM[4],
            StateBitsWidth::F800 => PERMUTATIONS_NUM[5],
            StateBitsWidth::F1600 => PERMUTATIONS_NUM[6],
            StateBitsWidth::Custom(width) => {
                let wl: WordLen = width / 25;
                let l: Log = (wl as f32).log2() as Log;
                12 + 2 * l
            }
        };
        KeccakF { perm_num: perm_num }
    }

    pub fn permutations(&self, mut a: &mut State) {
        assert!(self.perm_num < 25, "Wrong permutations number");

        for i in 0..self.perm_num {
            KeccakF::round_b(&mut a, ROUND_CONSTANTS[i]);
        }
    }

    #[inline]
    fn round_b(mut a: &mut State, rc: u64) {
        KeccakF::theta(&mut a);
        let mut temp = KeccakF::rho_pi(&mut a);
        KeccakF::hi(&mut a, &mut temp);
        KeccakF::iota(&mut a, rc);
    }

    #[inline]
    fn theta(a: &mut State) {
        let mut c: [u64; 5] = [0; 5];
        let mut d: [u64; 5] = [0; 5];

        unroll! {
            for i in 0..5 {
                c[i] = a[i][0]
                    ^ a[i][1]
                    ^ a[i][2]
                    ^ a[i][3]
                    ^ a[i][4];
            }
        }

        unroll! {
            for i in 0..5 {
                d[i] = c[(i + 4) % 5] ^ c[(i + 1) % 5].rotate_left(1);
            }
        }

        unroll! {
            for i in 0..5 {
                unroll! {
                    for j in 0..5 {
                        a[i][j] ^= d[i];
                    }
                }
            }
        }
    }

    #[inline]
    fn rho_pi(a: &mut State) -> State {
        let mut temp: State = [[0; 5]; 5];
        unroll! {
            for i in 0..5 {
                unroll! {
                    for j in 0..5 {
                        temp[1 * j][(2 * i + 3 * j) % 5]
                            = a[i][j].rotate_left(ROTATION_CONSTANTS[i][j] as u32);
                    }
                }
            }
        }
        temp
    }

    #[inline]
    fn hi(a: &mut State, temp: &mut State) {
        unroll! {
            for i in 0..5 {
                unroll! {
                    for j in 0..5 {
                        a[i][j] = temp[i][j]
                            ^ (!temp[(i + 1) % 5][j]
                                & temp[(i + 2) % 5][j]);
                    }
                }
            }
        }
    }

    #[inline]
    fn iota(a: &mut State, rc: u64) {
        a[0][0] ^= rc;
    }
}