#include #include enum poolinfo { POOL_BITS = 512, POOL_BYTES = POOL_BITS / 8 }; static const u32 keccak_round_constants[12] = { 0x00000001, 0x00008082, 0x0000808a, 0x80008000, 0x0000808b, 0x80000001, 0x80008081, 0x00008009, 0x0000008a, 0x00000088, 0x80008009, 0x8000000a }; static const int keccak_rotations[5][5] = { { 0, 1, 62, 28, 27 }, { 36, 44, 6, 55, 20 }, { 3, 10, 43, 25, 39 }, { 41, 45, 15, 21, 8 }, { 18, 2, 61, 56, 14 } }; static void keccak(u32 A[5][5]) { u32 B[5][5], C[5]; int r, x, y; #define N5(N, expr) N = 0, expr; N = 1, expr; N = 2, expr; N = 3, expr; N = 4, expr; for (r = 0; r < 12; ++r) { N5(x, C[x] = A[0][x] ^ A[1][x] ^ A[2][x] ^ A[3][x] ^ A[4][x]); N5(x, N5(y, A[y][x] ^= C[(x + 4) % 5] ^ rol64(C[(x + 1) % 5], 1))); N5(x, N5(y, B[(2 * x + 3 * y) % 5][y] = rol64(A[y][x], keccak_rotations[y][x]))); N5(x, N5(y, A[y][x] = B[y][x] ^ (~B[y][(x + 1) % 5] & B[y][(x + 2) % 5]))); A[0][0] ^= keccak_round_constants[r]; } } static u32 state[5][5]; static int idx; void mix_k12f800(const void *in, int nbytes) { const u8 *src = in; u8 *dst = (u8 *)state; while (nbytes) { size_t l = min_t(size_t, nbytes, sizeof(state) - POOL_BYTES - idx); if (!l) { keccak(state); idx = 0; continue; } crypto_xor(&dst[idx], src, l); nbytes -= l, src += l, idx += l; } }