#ifndef __KECCAK_H__
#define __KECCAK_H__
#include <libecc/words/words.h>
#define _KECCAK_ROTL_(x, y) (((x) << (y)) | ((x) >> ((sizeof(u64) * 8) - (y))))
#define KECCAK_ROTL(x, y) ((((y) < (sizeof(u64) * 8)) && ((y) > 0)) ? (_KECCAK_ROTL_(x, y)) : (x))
#define KECCAK_WORD_LOG 6
#define KECCAK_ROUNDS (12 + (2 * KECCAK_WORD_LOG))
#define KECCAK_SLICES 5
static const u64 keccak_rc[KECCAK_ROUNDS] =
{
0x0000000000000001ULL, 0x0000000000008082ULL,
0x800000000000808AULL, 0x8000000080008000ULL,
0x000000000000808BULL, 0x0000000080000001ULL,
0x8000000080008081ULL, 0x8000000000008009ULL,
0x000000000000008AULL, 0x0000000000000088ULL,
0x0000000080008009ULL, 0x000000008000000AULL,
0x000000008000808BULL, 0x800000000000008BULL,
0x8000000000008089ULL, 0x8000000000008003ULL,
0x8000000000008002ULL, 0x8000000000000080ULL,
0x000000000000800AULL, 0x800000008000000AULL,
0x8000000080008081ULL, 0x8000000000008080ULL,
0x0000000080000001ULL, 0x8000000080008008ULL
};
static const u8 keccak_rot[KECCAK_SLICES][KECCAK_SLICES] =
{
{ 0, 36, 3, 41, 18 },
{ 1, 44, 10, 45, 2 },
{ 62, 6, 43, 15, 61 },
{ 28, 55, 25, 21, 56 },
{ 27, 20, 39, 8, 14 },
};
#define SWAP64_Idx(a) ((sizeof(u64) * ((u8)(a) / sizeof(u64))) + (sizeof(u64) - 1 - ((u8)(a) % sizeof(u64))))
#define Idx_slices(x, y) ((x) + (KECCAK_SLICES * (y)))
#define Idx(A, x, y) ((A)[Idx_slices(x, y)])
#define KECCAKROUND(A, RC) do { \
int x, y; \
u64 tmp; \
\
u64 BCD[KECCAK_SLICES * KECCAK_SLICES]; \
\
for(x = 0; x < KECCAK_SLICES; x++){ \
Idx(BCD, x, 0) = Idx(A, x, 0) ^ Idx(A, x, 1) ^ Idx(A, x, 2) ^ \
Idx(A, x, 3) ^ Idx(A, x, 4); \
} \
for(x = 0; x < KECCAK_SLICES; x++){ \
tmp = Idx(BCD, (x + 4) % 5, 0) ^ \
KECCAK_ROTL(Idx(BCD, (x + 1) % 5, 0), 1); \
for(y = 0; y < KECCAK_SLICES; y++){ \
Idx(A, x, y) ^= tmp; \
} \
} \
\
for(x = 0; x < KECCAK_SLICES; x++){ \
for(y = 0; y < KECCAK_SLICES; y++){ \
Idx(BCD, y, ((2*x)+(3*y)) % 5) = \
KECCAK_ROTL(Idx(A, x, y), keccak_rot[x][y]); \
} \
} \
\
for(x = 0; x < KECCAK_SLICES; x++){ \
for(y = 0; y < KECCAK_SLICES; y++){ \
Idx(A, x, y) = Idx(BCD, x, y) ^ \
(~Idx(BCD, (x+1) % 5, y) & Idx(BCD, (x+2)%5, y)); \
} \
} \
\
Idx(A, 0, 0) ^= (RC); \
} while(0)
#define KECCAKF(A) do { \
int round; \
for(round = 0; round < KECCAK_ROUNDS; round++){ \
KECCAKROUND(A, keccak_rc[round]); \
} \
} while(0)
#endif