diff options
Diffstat (limited to 'k12f1600.c')
-rw-r--r-- | k12f1600.c | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/k12f1600.c b/k12f1600.c new file mode 100644 index 0000000..26d974b --- /dev/null +++ b/k12f1600.c @@ -0,0 +1,54 @@ +#include <linux/kernel.h> +#include <crypto/algapi.h> + +enum poolinfo { + POOL_BITS = 512, + POOL_BYTES = POOL_BITS / 8 +}; + +static const u64 keccak_round_constants[12] = { + 0x0000000000000001ULL, 0x0000000000008082ULL, 0x800000000000808aULL, 0x8000000080008000ULL, + 0x000000000000808bULL, 0x0000000080000001ULL, 0x8000000080008081ULL, 0x8000000000008009ULL, + 0x000000000000008aULL, 0x0000000000000088ULL, 0x0000000080008009ULL, 0x000000008000000aULL +}; + +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(u64 A[5][5]) +{ + u64 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 u64 state[5][5]; +static int idx; + +void mix_k12f1600(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; + } +} |