|
/* |
|
The Keccak sponge function, designed by Guido Bertoni, Joan Daemen, |
|
Michaël Peeters and Gilles Van Assche. For more information, feedback or |
|
questions, please refer to our website: http://keccak.noekeon.org/ |
|
|
|
Implementation by Ronny Van Keer, |
|
hereby denoted as "the implementer". |
|
|
|
To the extent possible under law, the implementer has waived all copyright |
|
and related or neighboring rights to the source code in this file. |
|
http://creativecommons.org/publicdomain/zero/1.0/ |
|
*/ |
|
|
|
// WARNING: This implementation assumes a little-endian platform. Support for big-endinanness is not yet implemented. |
|
|
|
#include <string.h> |
|
#include "Keccak-simple-settings.h" |
|
#define cKeccakR_SizeInBytes (cKeccakR / 8) |
|
#include "crypto_hash.h" |
|
#ifndef crypto_hash_BYTES |
|
#ifdef cKeccakFixedOutputLengthInBytes |
|
#define crypto_hash_BYTES cKeccakFixedOutputLengthInBytes |
|
#else |
|
#define crypto_hash_BYTES cKeccakR_SizeInBytes |
|
#endif |
|
#endif |
|
#if (crypto_hash_BYTES > cKeccakR_SizeInBytes) |
|
#error "Full squeezing not yet implemented" |
|
#endif |
|
|
|
#if (cKeccakB == 1600) |
|
typedef unsigned long long UINT64; |
|
typedef UINT64 tKeccakLane; |
|
#define cKeccakNumberOfRounds 24 |
|
#elif (cKeccakB == 800) |
|
typedef unsigned int UINT32; |
|
// WARNING: on 8-bit and 16-bit platforms, this should be replaced by: |
|
//typedef unsigned long UINT32; |
|
typedef UINT32 tKeccakLane; |
|
#define cKeccakNumberOfRounds 22 |
|
#elif (cKeccakB == 400) |
|
typedef unsigned short UINT16; |
|
typedef UINT16 tKeccakLane; |
|
#define cKeccakNumberOfRounds 20 |
|
#elif (cKeccakB == 200) |
|
typedef unsigned char UINT8; |
|
typedef UINT8 tKeccakLane; |
|
#define cKeccakNumberOfRounds 18 |
|
#else |
|
#error "Unsupported Keccak-f width" |
|
#endif |
|
|
|
#define cKeccakLaneSizeInBits (sizeof(tKeccakLane) * 8) |
|
|
|
#define ROL(a, offset) ((((tKeccakLane)a) << ((offset) % cKeccakLaneSizeInBits)) ^ (((tKeccakLane)a) >> (cKeccakLaneSizeInBits-((offset) % cKeccakLaneSizeInBits)))) |
|
#if ((cKeccakB/25) == 8) |
|
#define ROL_mult8(a, offset) ((tKeccakLane)a) |
|
#else |
|
#define ROL_mult8(a, offset) ROL(a, offset) |
|
#endif |
|
void KeccakF( tKeccakLane * state, const tKeccakLane *in, int laneCount ); |
|
|
|
int crypto_hash( unsigned char *out, const unsigned char *in, unsigned long long inlen ) |
|
{ |
|
tKeccakLane state[5 * 5]; |
|
#if (crypto_hash_BYTES >= cKeccakR_SizeInBytes) |
|
#define temp out |
|
#else |
|
unsigned char temp[cKeccakR_SizeInBytes]; |
|
#endif |
|
|
|
memset( state, 0, sizeof(state) ); |
|
|
|
for ( /* empty */; inlen >= cKeccakR_SizeInBytes; inlen -= cKeccakR_SizeInBytes, in += cKeccakR_SizeInBytes ) |
|
{ |
|
KeccakF( state, (const tKeccakLane*)in, cKeccakR_SizeInBytes / sizeof(tKeccakLane) ); |
|
} |
|
|
|
// padding |
|
memcpy( temp, in, (size_t)inlen ); |
|
temp[inlen++] = 1; |
|
memset( temp+inlen, 0, cKeccakR_SizeInBytes - (size_t)inlen ); |
|
temp[cKeccakR_SizeInBytes-1] |= 0x80; |
|
KeccakF( state, (const tKeccakLane*)temp, cKeccakR_SizeInBytes / sizeof(tKeccakLane) ); |
|
memcpy( out, state, crypto_hash_BYTES ); |
|
#if (crypto_hash_BYTES >= cKeccakR_SizeInBytes) |
|
#undef temp |
|
#endif |
|
|
|
return ( 0 ); |
|
} |
|
|
|
|
|
const tKeccakLane KeccakF_RoundConstants[cKeccakNumberOfRounds] = |
|
{ |
|
(tKeccakLane)0x0000000000000001ULL, |
|
(tKeccakLane)0x0000000000008082ULL, |
|
(tKeccakLane)0x800000000000808aULL, |
|
(tKeccakLane)0x8000000080008000ULL, |
|
(tKeccakLane)0x000000000000808bULL, |
|
(tKeccakLane)0x0000000080000001ULL, |
|
(tKeccakLane)0x8000000080008081ULL, |
|
(tKeccakLane)0x8000000000008009ULL, |
|
(tKeccakLane)0x000000000000008aULL, |
|
(tKeccakLane)0x0000000000000088ULL, |
|
(tKeccakLane)0x0000000080008009ULL, |
|
(tKeccakLane)0x000000008000000aULL, |
|
(tKeccakLane)0x000000008000808bULL, |
|
(tKeccakLane)0x800000000000008bULL, |
|
(tKeccakLane)0x8000000000008089ULL, |
|
(tKeccakLane)0x8000000000008003ULL, |
|
(tKeccakLane)0x8000000000008002ULL, |
|
(tKeccakLane)0x8000000000000080ULL |
|
#if (cKeccakB >= 400) |
|
, (tKeccakLane)0x000000000000800aULL, |
|
(tKeccakLane)0x800000008000000aULL |
|
#if (cKeccakB >= 800) |
|
, (tKeccakLane)0x8000000080008081ULL, |
|
(tKeccakLane)0x8000000000008080ULL |
|
#if (cKeccakB == 1600) |
|
, (tKeccakLane)0x0000000080000001ULL, |
|
(tKeccakLane)0x8000000080008008ULL |
|
#endif |
|
#endif |
|
#endif |
|
}; |
|
|
|
void KeccakF( tKeccakLane * state, const tKeccakLane *in, int laneCount ) |
|
{ |
|
|
|
{ |
|
while ( --laneCount >= 0 ) |
|
{ |
|
state[laneCount] ^= in[laneCount]; |
|
} |
|
} |
|
|
|
{ |
|
tKeccakLane Aba, Abe, Abi, Abo, Abu; |
|
tKeccakLane Aga, Age, Agi, Ago, Agu; |
|
tKeccakLane Aka, Ake, Aki, Ako, Aku; |
|
tKeccakLane Ama, Ame, Ami, Amo, Amu; |
|
tKeccakLane Asa, Ase, Asi, Aso, Asu; |
|
tKeccakLane BCa, BCe, BCi, BCo, BCu; |
|
tKeccakLane Da, De, Di, Do, Du; |
|
tKeccakLane Eba, Ebe, Ebi, Ebo, Ebu; |
|
tKeccakLane Ega, Ege, Egi, Ego, Egu; |
|
tKeccakLane Eka, Eke, Eki, Eko, Eku; |
|
tKeccakLane Ema, Eme, Emi, Emo, Emu; |
|
tKeccakLane Esa, Ese, Esi, Eso, Esu; |
|
#define round laneCount |
|
|
|
//copyFromState(A, state) |
|
Aba = state[ 0]; |
|
Abe = state[ 1]; |
|
Abi = state[ 2]; |
|
Abo = state[ 3]; |
|
Abu = state[ 4]; |
|
Aga = state[ 5]; |
|
Age = state[ 6]; |
|
Agi = state[ 7]; |
|
Ago = state[ 8]; |
|
Agu = state[ 9]; |
|
Aka = state[10]; |
|
Ake = state[11]; |
|
Aki = state[12]; |
|
Ako = state[13]; |
|
Aku = state[14]; |
|
Ama = state[15]; |
|
Ame = state[16]; |
|
Ami = state[17]; |
|
Amo = state[18]; |
|
Amu = state[19]; |
|
Asa = state[20]; |
|
Ase = state[21]; |
|
Asi = state[22]; |
|
Aso = state[23]; |
|
Asu = state[24]; |
|
|
|
for( round = 0; round < cKeccakNumberOfRounds; round += 2 ) |
|
{ |
|
// prepareTheta |
|
BCa = Aba^Aga^Aka^Ama^Asa; |
|
BCe = Abe^Age^Ake^Ame^Ase; |
|
BCi = Abi^Agi^Aki^Ami^Asi; |
|
BCo = Abo^Ago^Ako^Amo^Aso; |
|
BCu = Abu^Agu^Aku^Amu^Asu; |
|
|
|
//thetaRhoPiChiIotaPrepareTheta(round , A, E) |
|
Da = BCu^ROL(BCe, 1); |
|
De = BCa^ROL(BCi, 1); |
|
Di = BCe^ROL(BCo, 1); |
|
Do = BCi^ROL(BCu, 1); |
|
Du = BCo^ROL(BCa, 1); |
|
|
|
Aba ^= Da; |
|
BCa = Aba; |
|
Age ^= De; |
|
BCe = ROL(Age, 44); |
|
Aki ^= Di; |
|
BCi = ROL(Aki, 43); |
|
Amo ^= Do; |
|
BCo = ROL(Amo, 21); |
|
Asu ^= Du; |
|
BCu = ROL(Asu, 14); |
|
Eba = BCa ^((~BCe)& BCi ); |
|
Eba ^= (tKeccakLane)KeccakF_RoundConstants[round]; |
|
Ebe = BCe ^((~BCi)& BCo ); |
|
Ebi = BCi ^((~BCo)& BCu ); |
|
Ebo = BCo ^((~BCu)& BCa ); |
|
Ebu = BCu ^((~BCa)& BCe ); |
|
|
|
Abo ^= Do; |
|
BCa = ROL(Abo, 28); |
|
Agu ^= Du; |
|
BCe = ROL(Agu, 20); |
|
Aka ^= Da; |
|
BCi = ROL(Aka, 3); |
|
Ame ^= De; |
|
BCo = ROL(Ame, 45); |
|
Asi ^= Di; |
|
BCu = ROL(Asi, 61); |
|
Ega = BCa ^((~BCe)& BCi ); |
|
Ege = BCe ^((~BCi)& BCo ); |
|
Egi = BCi ^((~BCo)& BCu ); |
|
Ego = BCo ^((~BCu)& BCa ); |
|
Egu = BCu ^((~BCa)& BCe ); |
|
|
|
Abe ^= De; |
|
BCa = ROL(Abe, 1); |
|
Agi ^= Di; |
|
BCe = ROL(Agi, 6); |
|
Ako ^= Do; |
|
BCi = ROL(Ako, 25); |
|
Amu ^= Du; |
|
BCo = ROL_mult8(Amu, 8); |
|
Asa ^= Da; |
|
BCu = ROL(Asa, 18); |
|
Eka = BCa ^((~BCe)& BCi ); |
|
Eke = BCe ^((~BCi)& BCo ); |
|
Eki = BCi ^((~BCo)& BCu ); |
|
Eko = BCo ^((~BCu)& BCa ); |
|
Eku = BCu ^((~BCa)& BCe ); |
|
|
|
Abu ^= Du; |
|
BCa = ROL(Abu, 27); |
|
Aga ^= Da; |
|
BCe = ROL(Aga, 36); |
|
Ake ^= De; |
|
BCi = ROL(Ake, 10); |
|
Ami ^= Di; |
|
BCo = ROL(Ami, 15); |
|
Aso ^= Do; |
|
BCu = ROL_mult8(Aso, 56); |
|
Ema = BCa ^((~BCe)& BCi ); |
|
Eme = BCe ^((~BCi)& BCo ); |
|
Emi = BCi ^((~BCo)& BCu ); |
|
Emo = BCo ^((~BCu)& BCa ); |
|
Emu = BCu ^((~BCa)& BCe ); |
|
|
|
Abi ^= Di; |
|
BCa = ROL(Abi, 62); |
|
Ago ^= Do; |
|
BCe = ROL(Ago, 55); |
|
Aku ^= Du; |
|
BCi = ROL(Aku, 39); |
|
Ama ^= Da; |
|
BCo = ROL(Ama, 41); |
|
Ase ^= De; |
|
BCu = ROL(Ase, 2); |
|
Esa = BCa ^((~BCe)& BCi ); |
|
Ese = BCe ^((~BCi)& BCo ); |
|
Esi = BCi ^((~BCo)& BCu ); |
|
Eso = BCo ^((~BCu)& BCa ); |
|
Esu = BCu ^((~BCa)& BCe ); |
|
|
|
// prepareTheta |
|
BCa = Eba^Ega^Eka^Ema^Esa; |
|
BCe = Ebe^Ege^Eke^Eme^Ese; |
|
BCi = Ebi^Egi^Eki^Emi^Esi; |
|
BCo = Ebo^Ego^Eko^Emo^Eso; |
|
BCu = Ebu^Egu^Eku^Emu^Esu; |
|
|
|
//thetaRhoPiChiIotaPrepareTheta(round+1, E, A) |
|
Da = BCu^ROL(BCe, 1); |
|
De = BCa^ROL(BCi, 1); |
|
Di = BCe^ROL(BCo, 1); |
|
Do = BCi^ROL(BCu, 1); |
|
Du = BCo^ROL(BCa, 1); |
|
|
|
Eba ^= Da; |
|
BCa = Eba; |
|
Ege ^= De; |
|
BCe = ROL(Ege, 44); |
|
Eki ^= Di; |
|
BCi = ROL(Eki, 43); |
|
Emo ^= Do; |
|
BCo = ROL(Emo, 21); |
|
Esu ^= Du; |
|
BCu = ROL(Esu, 14); |
|
Aba = BCa ^((~BCe)& BCi ); |
|
Aba ^= (tKeccakLane)KeccakF_RoundConstants[round+1]; |
|
Abe = BCe ^((~BCi)& BCo ); |
|
Abi = BCi ^((~BCo)& BCu ); |
|
Abo = BCo ^((~BCu)& BCa ); |
|
Abu = BCu ^((~BCa)& BCe ); |
|
|
|
Ebo ^= Do; |
|
BCa = ROL(Ebo, 28); |
|
Egu ^= Du; |
|
BCe = ROL(Egu, 20); |
|
Eka ^= Da; |
|
BCi = ROL(Eka, 3); |
|
Eme ^= De; |
|
BCo = ROL(Eme, 45); |
|
Esi ^= Di; |
|
BCu = ROL(Esi, 61); |
|
Aga = BCa ^((~BCe)& BCi ); |
|
Age = BCe ^((~BCi)& BCo ); |
|
Agi = BCi ^((~BCo)& BCu ); |
|
Ago = BCo ^((~BCu)& BCa ); |
|
Agu = BCu ^((~BCa)& BCe ); |
|
|
|
Ebe ^= De; |
|
BCa = ROL(Ebe, 1); |
|
Egi ^= Di; |
|
BCe = ROL(Egi, 6); |
|
Eko ^= Do; |
|
BCi = ROL(Eko, 25); |
|
Emu ^= Du; |
|
BCo = ROL_mult8(Emu, 8); |
|
Esa ^= Da; |
|
BCu = ROL(Esa, 18); |
|
Aka = BCa ^((~BCe)& BCi ); |
|
Ake = BCe ^((~BCi)& BCo ); |
|
Aki = BCi ^((~BCo)& BCu ); |
|
Ako = BCo ^((~BCu)& BCa ); |
|
Aku = BCu ^((~BCa)& BCe ); |
|
|
|
Ebu ^= Du; |
|
BCa = ROL(Ebu, 27); |
|
Ega ^= Da; |
|
BCe = ROL(Ega, 36); |
|
Eke ^= De; |
|
BCi = ROL(Eke, 10); |
|
Emi ^= Di; |
|
BCo = ROL(Emi, 15); |
|
Eso ^= Do; |
|
BCu = ROL_mult8(Eso, 56); |
|
Ama = BCa ^((~BCe)& BCi ); |
|
Ame = BCe ^((~BCi)& BCo ); |
|
Ami = BCi ^((~BCo)& BCu ); |
|
Amo = BCo ^((~BCu)& BCa ); |
|
Amu = BCu ^((~BCa)& BCe ); |
|
|
|
Ebi ^= Di; |
|
BCa = ROL(Ebi, 62); |
|
Ego ^= Do; |
|
BCe = ROL(Ego, 55); |
|
Eku ^= Du; |
|
BCi = ROL(Eku, 39); |
|
Ema ^= Da; |
|
BCo = ROL(Ema, 41); |
|
Ese ^= De; |
|
BCu = ROL(Ese, 2); |
|
Asa = BCa ^((~BCe)& BCi ); |
|
Ase = BCe ^((~BCi)& BCo ); |
|
Asi = BCi ^((~BCo)& BCu ); |
|
Aso = BCo ^((~BCu)& BCa ); |
|
Asu = BCu ^((~BCa)& BCe ); |
|
} |
|
|
|
//copyToState(state, A) |
|
state[ 0] = Aba; |
|
state[ 1] = Abe; |
|
state[ 2] = Abi; |
|
state[ 3] = Abo; |
|
state[ 4] = Abu; |
|
state[ 5] = Aga; |
|
state[ 6] = Age; |
|
state[ 7] = Agi; |
|
state[ 8] = Ago; |
|
state[ 9] = Agu; |
|
state[10] = Aka; |
|
state[11] = Ake; |
|
state[12] = Aki; |
|
state[13] = Ako; |
|
state[14] = Aku; |
|
state[15] = Ama; |
|
state[16] = Ame; |
|
state[17] = Ami; |
|
state[18] = Amo; |
|
state[19] = Amu; |
|
state[20] = Asa; |
|
state[21] = Ase; |
|
state[22] = Asi; |
|
state[23] = Aso; |
|
state[24] = Asu; |
|
|
|
#undef round |
|
} |
|
|
|
} |