pub mod consts {
pub const K: [u64; 24] = [
0x0000000000000001, 0x0000000000008082,
0x800000000000808a, 0x8000000080008000,
0x000000000000808b, 0x0000000080000001,
0x8000000080008081, 0x8000000000008009,
0x000000000000008a, 0x0000000000000088,
0x0000000080008009, 0x000000008000000a,
0x000000008000808b, 0x800000000000008b,
0x8000000000008089, 0x8000000000008003,
0x8000000000008002, 0x8000000000000080,
0x000000000000800a, 0x800000008000000a,
0x8000000080008081, 0x8000000000008080,
0x0000000080000001, 0x8000000080008008,
];
}
pub mod ops {
use bswap::leu64;
macro_rules! rotate_left {
($a:expr, $b:expr) => (($a << $b) ^ ($a >> (64 - $b)))
}
macro_rules! digest_round {
($a:ident, $b:ident, $c:ident, $d:ident, $e:ident,
$f:ident, $g:ident, $h:ident, $i:ident, $j:ident,
$k:ident, $m:ident, $n:ident, $o:ident, $p:ident,
$q:ident, $r:ident, $s:ident, $t:ident, $u:ident,
$v:ident, $w:ident, $x:ident, $y:ident, $z:ident, $ir:ident, $ty:ident) => {
{
use super::consts::K;
let tmp: $ty;
let tca: $ty;
let tcb: $ty;
let tcc: $ty;
let tcd: $ty;
let tce: $ty;
let mut tda: $ty;
let mut tdb: $ty;
let mut tdc: $ty;
let mut tdd: $ty;
let mut tde: $ty;
tca = $a ^ $f ^ $k ^ $q ^ $v;
tcb = $b ^ $g ^ $m ^ $r ^ $w;
tcc = $c ^ $h ^ $n ^ $s ^ $x;
tcd = $d ^ $i ^ $o ^ $t ^ $y;
tce = $e ^ $j ^ $p ^ $u ^ $z;
tda = tce ^ rotate_left!(tcb, 1);
tdb = tca ^ rotate_left!(tcc, 1);
tdc = tcb ^ rotate_left!(tcd, 1);
tdd = tcc ^ rotate_left!(tce, 1);
tde = tcd ^ rotate_left!(tca, 1);
$a ^= tda;
$b ^= tdb;
$c ^= tdc;
$d ^= tdd;
$e ^= tde;
$f ^= tda;
$g ^= tdb;
$h ^= tdc;
$i ^= tdd;
$j ^= tde;
$k ^= tda;
$m ^= tdb;
$n ^= tdc;
$o ^= tdd;
$p ^= tde;
$q ^= tda;
$r ^= tdb;
$s ^= tdc;
$t ^= tdd;
$u ^= tde;
$v ^= tda;
$w ^= tdb;
$x ^= tdc;
$y ^= tdd;
$z ^= tde;
tmp = rotate_left!($b, 1);
$b = rotate_left!($g, 44);
$g = rotate_left!($j, 20);
$j = rotate_left!($x, 61);
$x = rotate_left!($p, 39);
$p = rotate_left!($v, 18);
$v = rotate_left!($c, 62);
$c = rotate_left!($n, 43);
$n = rotate_left!($o, 25);
$o = rotate_left!($u, 8);
$u = rotate_left!($y, 56);
$y = rotate_left!($q, 41);
$q = rotate_left!($e, 27);
$e = rotate_left!($z, 14);
$z = rotate_left!($w, 2);
$w = rotate_left!($i, 55);
$i = rotate_left!($r, 45);
$r = rotate_left!($f, 36);
$f = rotate_left!($d, 28);
$d = rotate_left!($t, 21);
$t = rotate_left!($s, 15);
$s = rotate_left!($m, 10);
$m = rotate_left!($h, 6);
$h = rotate_left!($k, 3);
$k = tmp;
tda = !$b & $c;
tdb = !$c & $d;
tdc = !$d & $e;
tdd = !$e & $a;
tde = !$a & $b;
$a ^= tda ^ K[$ir];
$b ^= tdb;
$c ^= tdc;
$d ^= tdd;
$e ^= tde;
tda = !$g & $h;
tdb = !$h & $i;
tdc = !$i & $j;
tdd = !$j & $f;
tde = !$f & $g;
$f ^= tda;
$g ^= tdb;
$h ^= tdc;
$i ^= tdd;
$j ^= tde;
tda = !$m & $n;
tdb = !$n & $o;
tdc = !$o & $p;
tdd = !$p & $k;
tde = !$k & $m;
$k ^= tda;
$m ^= tdb;
$n ^= tdc;
$o ^= tdd;
$p ^= tde;
tda = !$r & $s;
tdb = !$s & $t;
tdc = !$t & $u;
tdd = !$u & $q;
tde = !$q & $r;
$q ^= tda;
$r ^= tdb;
$s ^= tdc;
$t ^= tdd;
$u ^= tde;
tda = !$w & $x;
tdb = !$x & $y;
tdc = !$y & $z;
tdd = !$z & $v;
tde = !$v & $w;
$v ^= tda;
$w ^= tdb;
$x ^= tdc;
$y ^= tdd;
$z ^= tde;
}
}
}
pub fn digest_block(state: &mut [u64; 25], block: &[u8]) {
assert!(block.len() <= 200);
let mut block2 = [0u64; 25];
leu64::decode_slice(&mut block2[..block.len()/8], block);
for il in 0..block.len()/8 {
state[il] ^= block2[il];
}
let mut a = state[0];
let mut b = state[1];
let mut c = state[2];
let mut d = state[3];
let mut e = state[4];
let mut f = state[5];
let mut g = state[6];
let mut h = state[7];
let mut i = state[8];
let mut j = state[9];
let mut k = state[10];
let mut m = state[11];
let mut n = state[12];
let mut o = state[13];
let mut p = state[14];
let mut q = state[15];
let mut r = state[16];
let mut s = state[17];
let mut t = state[18];
let mut u = state[19];
let mut v = state[20];
let mut w = state[21];
let mut x = state[22];
let mut y = state[23];
let mut z = state[24];
for ir in 0..24 {
digest_round!(a, b, c, d, e,
f, g, h, i, j,
k, m, n, o, p,
q, r, s, t, u,
v, w, x, y, z, ir, u64);
}
*state = [a, b, c, d, e,
f, g, h, i, j,
k, m, n, o, p,
q, r, s, t, u,
v, w, x, y, z];
}
}