This Keccak implementation by Ronny Van Keer comes from the obsolete software package "Reference and optimized code in C", version 3.2 from the Keccak Team archives.
This implementation is the base of ethash's Keccak implementation.
This Keccak implementation by Ronny Van Keer comes from the obsolete software package "Reference and optimized code in C", version 3.2 from the Keccak Team archives.
This implementation is the base of ethash's Keccak implementation.
/* | |
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 | |
} | |
} |