|
|
|
@@ -20,18 +20,21 @@ typedef unsigned char UINT8;
|
|
|
|
|
typedef unsigned long long int UINT64;
|
|
|
|
|
|
|
|
|
|
#define nrRounds 24
|
|
|
|
|
UINT64 KeccakRoundConstants[nrRounds];
|
|
|
|
|
static UINT64 KeccakRoundConstants[nrRounds];
|
|
|
|
|
#define nrLanes 25
|
|
|
|
|
unsigned int KeccakRhoOffsets[nrLanes];
|
|
|
|
|
static unsigned int KeccakRhoOffsets[nrLanes];
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
void KeccakPermutationOnWords(UINT64 *state);
|
|
|
|
|
void theta(UINT64 *A);
|
|
|
|
|
void rho(UINT64 *A);
|
|
|
|
|
void pi(UINT64 *A);
|
|
|
|
|
void chi(UINT64 *A);
|
|
|
|
|
void iota(UINT64 *A, unsigned int indexRound);
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void fromBytesToWords(UINT64 *stateAsWords, const unsigned char *state)
|
|
|
|
|
#if (PLATFORM_BYTE_ORDER != IS_LITTLE_ENDIAN)
|
|
|
|
|
static void fromBytesToWords(UINT64 *stateAsWords, const unsigned char *state)
|
|
|
|
|
{
|
|
|
|
|
unsigned int i, j;
|
|
|
|
|
|
|
|
|
@@ -42,7 +45,7 @@ void fromBytesToWords(UINT64 *stateAsWords, const unsigned char *state)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void fromWordsToBytes(unsigned char *state, const UINT64 *stateAsWords)
|
|
|
|
|
static void fromWordsToBytes(unsigned char *state, const UINT64 *stateAsWords)
|
|
|
|
|
{
|
|
|
|
|
unsigned int i, j;
|
|
|
|
|
|
|
|
|
@@ -50,6 +53,97 @@ void fromWordsToBytes(unsigned char *state, const UINT64 *stateAsWords)
|
|
|
|
|
for(j=0; j<(64/8); j++)
|
|
|
|
|
state[i*(64/8)+j] = (stateAsWords[i] >> (8*j)) & 0xFF;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
void KeccakPermutationAfterXor(unsigned char *state, const unsigned char *data, unsigned int dataLengthInBytes)
|
|
|
|
|
{
|
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
|
|
for(i=0; i<dataLengthInBytes; i++)
|
|
|
|
|
state[i] ^= data[i];
|
|
|
|
|
KeccakPermutation(state);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define index(x, y) (((x)%5)+5*((y)%5))
|
|
|
|
|
#define ROL64(a, offset) ((offset != 0) ? ((((UINT64)a) << offset) ^ (((UINT64)a) >> (64-offset))) : a)
|
|
|
|
|
|
|
|
|
|
static void theta(UINT64 *A)
|
|
|
|
|
{
|
|
|
|
|
unsigned int x, y;
|
|
|
|
|
UINT64 C[5], D[5];
|
|
|
|
|
|
|
|
|
|
for(x=0; x<5; x++) {
|
|
|
|
|
C[x] = 0;
|
|
|
|
|
for(y=0; y<5; y++)
|
|
|
|
|
C[x] ^= A[index(x, y)];
|
|
|
|
|
}
|
|
|
|
|
for(x=0; x<5; x++)
|
|
|
|
|
D[x] = ROL64(C[(x+1)%5], 1) ^ C[(x+4)%5];
|
|
|
|
|
for(x=0; x<5; x++)
|
|
|
|
|
for(y=0; y<5; y++)
|
|
|
|
|
A[index(x, y)] ^= D[x];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void rho(UINT64 *A)
|
|
|
|
|
{
|
|
|
|
|
unsigned int x, y;
|
|
|
|
|
|
|
|
|
|
for(x=0; x<5; x++) for(y=0; y<5; y++)
|
|
|
|
|
A[index(x, y)] = ROL64(A[index(x, y)], KeccakRhoOffsets[index(x, y)]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void pi(UINT64 *A)
|
|
|
|
|
{
|
|
|
|
|
unsigned int x, y;
|
|
|
|
|
UINT64 tempA[25];
|
|
|
|
|
|
|
|
|
|
for(x=0; x<5; x++) for(y=0; y<5; y++)
|
|
|
|
|
tempA[index(x, y)] = A[index(x, y)];
|
|
|
|
|
for(x=0; x<5; x++) for(y=0; y<5; y++)
|
|
|
|
|
A[index(0*x+1*y, 2*x+3*y)] = tempA[index(x, y)];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void chi(UINT64 *A)
|
|
|
|
|
{
|
|
|
|
|
unsigned int x, y;
|
|
|
|
|
UINT64 C[5];
|
|
|
|
|
|
|
|
|
|
for(y=0; y<5; y++) {
|
|
|
|
|
for(x=0; x<5; x++)
|
|
|
|
|
C[x] = A[index(x, y)] ^ ((~A[index(x+1, y)]) & A[index(x+2, y)]);
|
|
|
|
|
for(x=0; x<5; x++)
|
|
|
|
|
A[index(x, y)] = C[x];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void iota(UINT64 *A, unsigned int indexRound)
|
|
|
|
|
{
|
|
|
|
|
A[index(0, 0)] ^= KeccakRoundConstants[indexRound];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int LFSR86540(UINT8 *LFSR)
|
|
|
|
|
{
|
|
|
|
|
int result = ((*LFSR) & 0x01) != 0;
|
|
|
|
|
if (((*LFSR) & 0x80) != 0)
|
|
|
|
|
// Primitive polynomial over GF(2): x^8+x^6+x^5+x^4+1
|
|
|
|
|
(*LFSR) = ((*LFSR) << 1) ^ 0x71;
|
|
|
|
|
else
|
|
|
|
|
(*LFSR) <<= 1;
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void KeccakPermutationOnWords(UINT64 *state)
|
|
|
|
|
{
|
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
|
|
for(i=0; i<nrRounds; i++) {
|
|
|
|
|
theta(state);
|
|
|
|
|
rho(state);
|
|
|
|
|
pi(state);
|
|
|
|
|
chi(state);
|
|
|
|
|
iota(state, i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void KeccakPermutation(unsigned char *state)
|
|
|
|
|
{
|
|
|
|
@@ -66,97 +160,7 @@ void KeccakPermutation(unsigned char *state)
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void KeccakPermutationAfterXor(unsigned char *state, const unsigned char *data, unsigned int dataLengthInBytes)
|
|
|
|
|
{
|
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
|
|
for(i=0; i<dataLengthInBytes; i++)
|
|
|
|
|
state[i] ^= data[i];
|
|
|
|
|
KeccakPermutation(state);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void KeccakPermutationOnWords(UINT64 *state)
|
|
|
|
|
{
|
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
|
|
for(i=0; i<nrRounds; i++) {
|
|
|
|
|
theta(state);
|
|
|
|
|
rho(state);
|
|
|
|
|
pi(state);
|
|
|
|
|
chi(state);
|
|
|
|
|
iota(state, i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define index(x, y) (((x)%5)+5*((y)%5))
|
|
|
|
|
#define ROL64(a, offset) ((offset != 0) ? ((((UINT64)a) << offset) ^ (((UINT64)a) >> (64-offset))) : a)
|
|
|
|
|
|
|
|
|
|
void theta(UINT64 *A)
|
|
|
|
|
{
|
|
|
|
|
unsigned int x, y;
|
|
|
|
|
UINT64 C[5], D[5];
|
|
|
|
|
|
|
|
|
|
for(x=0; x<5; x++) {
|
|
|
|
|
C[x] = 0;
|
|
|
|
|
for(y=0; y<5; y++)
|
|
|
|
|
C[x] ^= A[index(x, y)];
|
|
|
|
|
}
|
|
|
|
|
for(x=0; x<5; x++)
|
|
|
|
|
D[x] = ROL64(C[(x+1)%5], 1) ^ C[(x+4)%5];
|
|
|
|
|
for(x=0; x<5; x++)
|
|
|
|
|
for(y=0; y<5; y++)
|
|
|
|
|
A[index(x, y)] ^= D[x];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void rho(UINT64 *A)
|
|
|
|
|
{
|
|
|
|
|
unsigned int x, y;
|
|
|
|
|
|
|
|
|
|
for(x=0; x<5; x++) for(y=0; y<5; y++)
|
|
|
|
|
A[index(x, y)] = ROL64(A[index(x, y)], KeccakRhoOffsets[index(x, y)]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void pi(UINT64 *A)
|
|
|
|
|
{
|
|
|
|
|
unsigned int x, y;
|
|
|
|
|
UINT64 tempA[25];
|
|
|
|
|
|
|
|
|
|
for(x=0; x<5; x++) for(y=0; y<5; y++)
|
|
|
|
|
tempA[index(x, y)] = A[index(x, y)];
|
|
|
|
|
for(x=0; x<5; x++) for(y=0; y<5; y++)
|
|
|
|
|
A[index(0*x+1*y, 2*x+3*y)] = tempA[index(x, y)];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void chi(UINT64 *A)
|
|
|
|
|
{
|
|
|
|
|
unsigned int x, y;
|
|
|
|
|
UINT64 C[5];
|
|
|
|
|
|
|
|
|
|
for(y=0; y<5; y++) {
|
|
|
|
|
for(x=0; x<5; x++)
|
|
|
|
|
C[x] = A[index(x, y)] ^ ((~A[index(x+1, y)]) & A[index(x+2, y)]);
|
|
|
|
|
for(x=0; x<5; x++)
|
|
|
|
|
A[index(x, y)] = C[x];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void iota(UINT64 *A, unsigned int indexRound)
|
|
|
|
|
{
|
|
|
|
|
A[index(0, 0)] ^= KeccakRoundConstants[indexRound];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int LFSR86540(UINT8 *LFSR)
|
|
|
|
|
{
|
|
|
|
|
int result = ((*LFSR) & 0x01) != 0;
|
|
|
|
|
if (((*LFSR) & 0x80) != 0)
|
|
|
|
|
// Primitive polynomial over GF(2): x^8+x^6+x^5+x^4+1
|
|
|
|
|
(*LFSR) = ((*LFSR) << 1) ^ 0x71;
|
|
|
|
|
else
|
|
|
|
|
(*LFSR) <<= 1;
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void KeccakInitializeRoundConstants()
|
|
|
|
|
static void KeccakInitializeRoundConstants()
|
|
|
|
|
{
|
|
|
|
|
UINT8 LFSRstate = 0x01;
|
|
|
|
|
unsigned int i, j, bitPosition;
|
|
|
|
@@ -171,7 +175,7 @@ void KeccakInitializeRoundConstants()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void KeccakInitializeRhoOffsets()
|
|
|
|
|
static void KeccakInitializeRhoOffsets()
|
|
|
|
|
{
|
|
|
|
|
unsigned int x, y, t, newX, newY;
|
|
|
|
|
|
|
|
|
@@ -187,7 +191,7 @@ void KeccakInitializeRhoOffsets()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void KeccakInitialize()
|
|
|
|
|
void KeccakInitialize(void)
|
|
|
|
|
{
|
|
|
|
|
KeccakInitializeRoundConstants();
|
|
|
|
|
KeccakInitializeRhoOffsets();
|
|
|
|
|