/*************************************************************************** ** ** ** Keccak (http://keccak.noekeon.org/) implementation file ** ** ** ** This file implements the Keccak hash algorithm as provided by the ** ** inventors, and submitted to the third round of the NIST SHA-3 ** ** competition. ** ** For the QKeccakHash wrapper, the originally multiple files were ** ** combined in this one. Slight modifications have been made to ** ** allow use in C++ as an independently included .cpp file. ** ** It is not meant to be compiled into an object, hence, there is no ** ** header. ** ** ** ** The code here is not part of the actual QKeccakHash implementation ** ** and thus not licensed under the GPLv3 but under its respecitve ** ** license given by the inventors. Typically, this means it is in the ** ** public domain, if not noted otherwise. ** ** ** ***************************************************************************/ namespace KeccakImpl { typedef unsigned char UINT8; typedef unsigned short UINT16; typedef unsigned int UINT32; typedef unsigned long long int UINT64; // ================================================================================ // =================== brg_endian.h // ================================================================================ /* --------------------------------------------------------------------------- Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved. LICENSE TERMS The redistribution and use of this software (with or without changes) is allowed without the payment of fees or royalties provided that: 1. source code distributions include the above copyright notice, this list of conditions and the following disclaimer; 2. binary distributions include the above copyright notice, this list of conditions and the following disclaimer in their documentation; 3. the name of the copyright holder is not used to endorse products built using this software without specific written permission. DISCLAIMER This software is provided 'as is' with no explicit or implied warranties in respect of its properties, including, but not limited to, correctness and/or fitness for purpose. --------------------------------------------------------------------------- Issue Date: 20/12/2007 Changes for ARM 9/9/2010 */ #ifndef _BRG_ENDIAN_H #define _BRG_ENDIAN_H #define IS_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */ #define IS_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */ #if 0 /* Include files where endian defines and byteswap functions may reside */ #if defined( __sun ) # include #elif defined( __FreeBSD__ ) || defined( __OpenBSD__ ) || defined( __NetBSD__ ) # include #elif defined( BSD ) && ( BSD >= 199103 ) || defined( __APPLE__ ) || \ defined( __CYGWIN32__ ) || defined( __DJGPP__ ) || defined( __osf__ ) # include #elif defined( __linux__ ) || defined( __GNUC__ ) || defined( __GNU_LIBRARY__ ) # if !defined( __MINGW32__ ) && !defined( _AIX ) # include # if !defined( __BEOS__ ) # include # endif # endif #endif #endif /* Now attempt to set the define for platform byte order using any */ /* of the four forms SYMBOL, _SYMBOL, __SYMBOL & __SYMBOL__, which */ /* seem to encompass most endian symbol definitions */ #if defined( BIG_ENDIAN ) && defined( LITTLE_ENDIAN ) # if defined( BYTE_ORDER ) && BYTE_ORDER == BIG_ENDIAN # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN # elif defined( BYTE_ORDER ) && BYTE_ORDER == LITTLE_ENDIAN # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN # endif #elif defined( BIG_ENDIAN ) # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN #elif defined( LITTLE_ENDIAN ) # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN #endif #if defined( _BIG_ENDIAN ) && defined( _LITTLE_ENDIAN ) # if defined( _BYTE_ORDER ) && _BYTE_ORDER == _BIG_ENDIAN # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN # elif defined( _BYTE_ORDER ) && _BYTE_ORDER == _LITTLE_ENDIAN # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN # endif #elif defined( _BIG_ENDIAN ) # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN #elif defined( _LITTLE_ENDIAN ) # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN #endif #if defined( __BIG_ENDIAN ) && defined( __LITTLE_ENDIAN ) # if defined( __BYTE_ORDER ) && __BYTE_ORDER == __BIG_ENDIAN # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN # elif defined( __BYTE_ORDER ) && __BYTE_ORDER == __LITTLE_ENDIAN # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN # endif #elif defined( __BIG_ENDIAN ) # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN #elif defined( __LITTLE_ENDIAN ) # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN #endif #if defined( __BIG_ENDIAN__ ) && defined( __LITTLE_ENDIAN__ ) # if defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __BIG_ENDIAN__ # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN # elif defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __LITTLE_ENDIAN__ # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN # endif #elif defined( __BIG_ENDIAN__ ) # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN #elif defined( __LITTLE_ENDIAN__ ) # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN #endif /* if the platform byte order could not be determined, then try to */ /* set this define using common machine defines */ #if !defined(PLATFORM_BYTE_ORDER) #if defined( __alpha__ ) || defined( __alpha ) || defined( i386 ) || \ defined( __i386__ ) || defined( _M_I86 ) || defined( _M_IX86 ) || \ defined( __OS2__ ) || defined( sun386 ) || defined( __TURBOC__ ) || \ defined( vax ) || defined( vms ) || defined( VMS ) || \ defined( __VMS ) || defined( _M_X64 ) # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN #elif defined( AMIGA ) || defined( applec ) || defined( __AS400__ ) || \ defined( _CRAY ) || defined( __hppa ) || defined( __hp9000 ) || \ defined( ibm370 ) || defined( mc68000 ) || defined( m68k ) || \ defined( __MRC__ ) || defined( __MVS__ ) || defined( __MWERKS__ ) || \ defined( sparc ) || defined( __sparc) || defined( SYMANTEC_C ) || \ defined( __VOS__ ) || defined( __TIGCC__ ) || defined( __TANDEM ) || \ defined( THINK_C ) || defined( __VMCMS__ ) || defined( _AIX ) # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN #elif defined(__arm__) # ifdef __BIG_ENDIAN # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN # else # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN # endif #elif 1 /* **** EDIT HERE IF NECESSARY **** */ # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN #elif 0 /* **** EDIT HERE IF NECESSARY **** */ # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN #else # error Please edit lines 132 or 134 in brg_endian.h to set the platform byte order #endif #endif #endif // ================================================================================ // =================== KeccakSponge.h // ================================================================================ /* 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 the designers, 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/ */ #ifndef _KeccakSponge_h_ #define _KeccakSponge_h_ /** * Function to initialize the state of the Keccak[r, c] sponge function. * The sponge function is set to the absorbing phase. * @param state Pointer to the state of the sponge function to be initialized. * @param rate The value of the rate r. * @param capacity The value of the capacity c. * @pre One must have r+c=1600 and the rate a multiple of 64 bits in this implementation. * @return Zero if successful, 1 otherwise. */ int InitSponge(spongeState *state, unsigned int rate, unsigned int capacity); /** * Function to give input data for the sponge function to absorb. * @param state Pointer to the state of the sponge function initialized by InitSponge(). * @param data Pointer to the input data. * When @a databitLen is not a multiple of 8, the last bits of data must be * in the least significant bits of the last byte. * @param databitLen The number of input bits provided in the input data. * @pre In the previous call to Absorb(), databitLen was a multiple of 8. * @pre The sponge function must be in the absorbing phase, * i.e., Squeeze() must not have been called before. * @return Zero if successful, 1 otherwise. */ int Absorb(spongeState *state, const unsigned char *data, unsigned long long databitlen); /** * Function to squeeze output data from the sponge function. * If the sponge function was in the absorbing phase, this function * switches it to the squeezing phase. * @param state Pointer to the state of the sponge function initialized by InitSponge(). * @param output Pointer to the buffer where to store the output data. * @param outputLength The number of output bits desired. * It must be a multiple of 8. * @return Zero if successful, 1 otherwise. */ int Squeeze(spongeState *state, unsigned char *output, unsigned long long outputLength); #endif // ================================================================================ // =================== KeccakF-1600-int-set.h // ================================================================================ #define ProvideFast576 #define ProvideFast832 #define ProvideFast1024 #define ProvideFast1088 #define ProvideFast1152 #define ProvideFast1344 // ================================================================================ // =================== KeccakF-1600-interface.h // ================================================================================ /* 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 the designers, 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/ */ #ifndef _KeccakPermutationInterface_h_ #define _KeccakPermutationInterface_h_ //#include "KeccakF-1600-int-set.h" void KeccakInitialize( void ); void KeccakInitializeState(unsigned char *state); void KeccakPermutation(unsigned char *state); #ifdef ProvideFast576 void KeccakAbsorb576bits(unsigned char *state, const unsigned char *data); #endif #ifdef ProvideFast832 void KeccakAbsorb832bits(unsigned char *state, const unsigned char *data); #endif #ifdef ProvideFast1024 void KeccakAbsorb1024bits(unsigned char *state, const unsigned char *data); #endif #ifdef ProvideFast1088 void KeccakAbsorb1088bits(unsigned char *state, const unsigned char *data); #endif #ifdef ProvideFast1152 void KeccakAbsorb1152bits(unsigned char *state, const unsigned char *data); #endif #ifdef ProvideFast1344 void KeccakAbsorb1344bits(unsigned char *state, const unsigned char *data); #endif void KeccakAbsorb(unsigned char *state, const unsigned char *data, unsigned int laneCount); #ifdef ProvideFast1024 void KeccakExtract1024bits(const unsigned char *state, unsigned char *data); #endif void KeccakExtract(const unsigned char *state, unsigned char *data, unsigned int laneCount); #endif // ================================================================================ // =================== KeccakF-1600-opt32-settings.h // ================================================================================ #define Unrolling 2 //#define UseBebigokimisa //#define UseInterleaveTables #define UseSchedule 3 // ================================================================================ // =================== KeccakF-1600-unrolling.macros // ================================================================================ /* 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 the designers, 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/ */ #if (Unrolling == 24) #define rounds \ prepareTheta \ thetaRhoPiChiIotaPrepareTheta( 0, A, E) \ thetaRhoPiChiIotaPrepareTheta( 1, E, A) \ thetaRhoPiChiIotaPrepareTheta( 2, A, E) \ thetaRhoPiChiIotaPrepareTheta( 3, E, A) \ thetaRhoPiChiIotaPrepareTheta( 4, A, E) \ thetaRhoPiChiIotaPrepareTheta( 5, E, A) \ thetaRhoPiChiIotaPrepareTheta( 6, A, E) \ thetaRhoPiChiIotaPrepareTheta( 7, E, A) \ thetaRhoPiChiIotaPrepareTheta( 8, A, E) \ thetaRhoPiChiIotaPrepareTheta( 9, E, A) \ thetaRhoPiChiIotaPrepareTheta(10, A, E) \ thetaRhoPiChiIotaPrepareTheta(11, E, A) \ thetaRhoPiChiIotaPrepareTheta(12, A, E) \ thetaRhoPiChiIotaPrepareTheta(13, E, A) \ thetaRhoPiChiIotaPrepareTheta(14, A, E) \ thetaRhoPiChiIotaPrepareTheta(15, E, A) \ thetaRhoPiChiIotaPrepareTheta(16, A, E) \ thetaRhoPiChiIotaPrepareTheta(17, E, A) \ thetaRhoPiChiIotaPrepareTheta(18, A, E) \ thetaRhoPiChiIotaPrepareTheta(19, E, A) \ thetaRhoPiChiIotaPrepareTheta(20, A, E) \ thetaRhoPiChiIotaPrepareTheta(21, E, A) \ thetaRhoPiChiIotaPrepareTheta(22, A, E) \ thetaRhoPiChiIota(23, E, A) \ copyToState(state, A) #elif (Unrolling == 12) #define rounds \ prepareTheta \ for(i=0; i<24; i+=12) { \ thetaRhoPiChiIotaPrepareTheta(i , A, E) \ thetaRhoPiChiIotaPrepareTheta(i+ 1, E, A) \ thetaRhoPiChiIotaPrepareTheta(i+ 2, A, E) \ thetaRhoPiChiIotaPrepareTheta(i+ 3, E, A) \ thetaRhoPiChiIotaPrepareTheta(i+ 4, A, E) \ thetaRhoPiChiIotaPrepareTheta(i+ 5, E, A) \ thetaRhoPiChiIotaPrepareTheta(i+ 6, A, E) \ thetaRhoPiChiIotaPrepareTheta(i+ 7, E, A) \ thetaRhoPiChiIotaPrepareTheta(i+ 8, A, E) \ thetaRhoPiChiIotaPrepareTheta(i+ 9, E, A) \ thetaRhoPiChiIotaPrepareTheta(i+10, A, E) \ thetaRhoPiChiIotaPrepareTheta(i+11, E, A) \ } \ copyToState(state, A) #elif (Unrolling == 8) #define rounds \ prepareTheta \ for(i=0; i<24; i+=8) { \ thetaRhoPiChiIotaPrepareTheta(i , A, E) \ thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \ thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \ thetaRhoPiChiIotaPrepareTheta(i+4, A, E) \ thetaRhoPiChiIotaPrepareTheta(i+5, E, A) \ thetaRhoPiChiIotaPrepareTheta(i+6, A, E) \ thetaRhoPiChiIotaPrepareTheta(i+7, E, A) \ } \ copyToState(state, A) #elif (Unrolling == 6) #define rounds \ prepareTheta \ for(i=0; i<24; i+=6) { \ thetaRhoPiChiIotaPrepareTheta(i , A, E) \ thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \ thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \ thetaRhoPiChiIotaPrepareTheta(i+4, A, E) \ thetaRhoPiChiIotaPrepareTheta(i+5, E, A) \ } \ copyToState(state, A) #elif (Unrolling == 4) #define rounds \ prepareTheta \ for(i=0; i<24; i+=4) { \ thetaRhoPiChiIotaPrepareTheta(i , A, E) \ thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \ thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \ } \ copyToState(state, A) #elif (Unrolling == 3) #define rounds \ prepareTheta \ for(i=0; i<24; i+=3) { \ thetaRhoPiChiIotaPrepareTheta(i , A, E) \ thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \ copyStateVariables(A, E) \ } \ copyToState(state, A) #elif (Unrolling == 2) #define rounds \ prepareTheta \ for(i=0; i<24; i+=2) { \ thetaRhoPiChiIotaPrepareTheta(i , A, E) \ thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ } \ copyToState(state, A) #elif (Unrolling == 1) #define rounds \ prepareTheta \ for(i=0; i<24; i++) { \ thetaRhoPiChiIotaPrepareTheta(i , A, E) \ copyStateVariables(A, E) \ } \ copyToState(state, A) #else #error "Unrolling is not correctly specified!" #endif // ================================================================================ // =================== KeccakF-1600-32-rvk.macros // ================================================================================ /* 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/ */ static const UINT32 KeccakF1600RoundConstants_int2[2*24] = { 0x00000001UL, 0x00000000UL, 0x00000000UL, 0x00000089UL, 0x00000000UL, 0x8000008bUL, 0x00000000UL, 0x80008080UL, 0x00000001UL, 0x0000008bUL, 0x00000001UL, 0x00008000UL, 0x00000001UL, 0x80008088UL, 0x00000001UL, 0x80000082UL, 0x00000000UL, 0x0000000bUL, 0x00000000UL, 0x0000000aUL, 0x00000001UL, 0x00008082UL, 0x00000000UL, 0x00008003UL, 0x00000001UL, 0x0000808bUL, 0x00000001UL, 0x8000000bUL, 0x00000001UL, 0x8000008aUL, 0x00000001UL, 0x80000081UL, 0x00000000UL, 0x80000081UL, 0x00000000UL, 0x80000008UL, 0x00000000UL, 0x00000083UL, 0x00000000UL, 0x80008003UL, 0x00000001UL, 0x80008088UL, 0x00000000UL, 0x80000088UL, 0x00000001UL, 0x00008000UL, 0x00000000UL, 0x80008082UL }; #undef rounds #define rounds \ { \ UINT32 Da0, De0, Di0, Do0, Du0; \ UINT32 Da1, De1, Di1, Do1, Du1; \ UINT32 Ba, Be, Bi, Bo, Bu; \ UINT32 Aba0, Abe0, Abi0, Abo0, Abu0; \ UINT32 Aba1, Abe1, Abi1, Abo1, Abu1; \ UINT32 Aga0, Age0, Agi0, Ago0, Agu0; \ UINT32 Aga1, Age1, Agi1, Ago1, Agu1; \ UINT32 Aka0, Ake0, Aki0, Ako0, Aku0; \ UINT32 Aka1, Ake1, Aki1, Ako1, Aku1; \ UINT32 Ama0, Ame0, Ami0, Amo0, Amu0; \ UINT32 Ama1, Ame1, Ami1, Amo1, Amu1; \ UINT32 Asa0, Ase0, Asi0, Aso0, Asu0; \ UINT32 Asa1, Ase1, Asi1, Aso1, Asu1; \ UINT32 Cw, Cx, Cy, Cz; \ UINT32 Eba0, Ebe0, Ebi0, Ebo0, Ebu0; \ UINT32 Eba1, Ebe1, Ebi1, Ebo1, Ebu1; \ UINT32 Ega0, Ege0, Egi0, Ego0, Egu0; \ UINT32 Ega1, Ege1, Egi1, Ego1, Egu1; \ UINT32 Eka0, Eke0, Eki0, Eko0, Eku0; \ UINT32 Eka1, Eke1, Eki1, Eko1, Eku1; \ UINT32 Ema0, Eme0, Emi0, Emo0, Emu0; \ UINT32 Ema1, Eme1, Emi1, Emo1, Emu1; \ UINT32 Esa0, Ese0, Esi0, Eso0, Esu0; \ UINT32 Esa1, Ese1, Esi1, Eso1, Esu1; \ const UINT32 * pRoundConstants = KeccakF1600RoundConstants_int2; \ UINT32 i; \ \ copyFromState(A, state) \ \ for( i = 12; i != 0; --i ) { \ Cx = Abu0^Agu0^Aku0^Amu0^Asu0; \ Du1 = Abe1^Age1^Ake1^Ame1^Ase1; \ Da0 = Cx^ROL32(Du1, 1); \ Cz = Abu1^Agu1^Aku1^Amu1^Asu1; \ Du0 = Abe0^Age0^Ake0^Ame0^Ase0; \ Da1 = Cz^Du0; \ \ Cw = Abi0^Agi0^Aki0^Ami0^Asi0; \ Do0 = Cw^ROL32(Cz, 1); \ Cy = Abi1^Agi1^Aki1^Ami1^Asi1; \ Do1 = Cy^Cx; \ \ Cx = Aba0^Aga0^Aka0^Ama0^Asa0; \ De0 = Cx^ROL32(Cy, 1); \ Cz = Aba1^Aga1^Aka1^Ama1^Asa1; \ De1 = Cz^Cw; \ \ Cy = Abo1^Ago1^Ako1^Amo1^Aso1; \ Di0 = Du0^ROL32(Cy, 1); \ Cw = Abo0^Ago0^Ako0^Amo0^Aso0; \ Di1 = Du1^Cw; \ \ Du0 = Cw^ROL32(Cz, 1); \ Du1 = Cy^Cx; \ \ Aba0 ^= Da0; \ Ba = Aba0; \ Age0 ^= De0; \ Be = ROL32(Age0, 22); \ Aki1 ^= Di1; \ Bi = ROL32(Aki1, 22); \ Amo1 ^= Do1; \ Bo = ROL32(Amo1, 11); \ Asu0 ^= Du0; \ Bu = ROL32(Asu0, 7); \ Eba0 = Ba ^((~Be)& Bi ) ^ *(pRoundConstants++); \ Ebe0 = Be ^((~Bi)& Bo ); \ Ebi0 = Bi ^((~Bo)& Bu ); \ Ebo0 = Bo ^((~Bu)& Ba ); \ Ebu0 = Bu ^((~Ba)& Be ); \ \ Abo0 ^= Do0; \ Ba = ROL32(Abo0, 14); \ Agu0 ^= Du0; \ Be = ROL32(Agu0, 10); \ Aka1 ^= Da1; \ Bi = ROL32(Aka1, 2); \ Ame1 ^= De1; \ Bo = ROL32(Ame1, 23); \ Asi1 ^= Di1; \ Bu = ROL32(Asi1, 31); \ Ega0 = Ba ^((~Be)& Bi ); \ Ege0 = Be ^((~Bi)& Bo ); \ Egi0 = Bi ^((~Bo)& Bu ); \ Ego0 = Bo ^((~Bu)& Ba ); \ Egu0 = Bu ^((~Ba)& Be ); \ \ Abe1 ^= De1; \ Ba = ROL32(Abe1, 1); \ Agi0 ^= Di0; \ Be = ROL32(Agi0, 3); \ Ako1 ^= Do1; \ Bi = ROL32(Ako1, 13); \ Amu0 ^= Du0; \ Bo = ROL32(Amu0, 4); \ Asa0 ^= Da0; \ Bu = ROL32(Asa0, 9); \ Eka0 = Ba ^((~Be)& Bi ); \ Eke0 = Be ^((~Bi)& Bo ); \ Eki0 = Bi ^((~Bo)& Bu ); \ Eko0 = Bo ^((~Bu)& Ba ); \ Eku0 = Bu ^((~Ba)& Be ); \ \ Abu1 ^= Du1; \ Ba = ROL32(Abu1, 14); \ Aga0 ^= Da0; \ Be = ROL32(Aga0, 18); \ Ake0 ^= De0; \ Bi = ROL32(Ake0, 5); \ Ami1 ^= Di1; \ Bo = ROL32(Ami1, 8); \ Aso0 ^= Do0; \ Bu = ROL32(Aso0, 28); \ Ema0 = Ba ^((~Be)& Bi ); \ Eme0 = Be ^((~Bi)& Bo ); \ Emi0 = Bi ^((~Bo)& Bu ); \ Emo0 = Bo ^((~Bu)& Ba ); \ Emu0 = Bu ^((~Ba)& Be ); \ \ Abi0 ^= Di0; \ Ba = ROL32(Abi0, 31); \ Ago1 ^= Do1; \ Be = ROL32(Ago1, 28); \ Aku1 ^= Du1; \ Bi = ROL32(Aku1, 20); \ Ama1 ^= Da1; \ Bo = ROL32(Ama1, 21); \ Ase0 ^= De0; \ Bu = ROL32(Ase0, 1); \ Esa0 = Ba ^((~Be)& Bi ); \ Ese0 = Be ^((~Bi)& Bo ); \ Esi0 = Bi ^((~Bo)& Bu ); \ Eso0 = Bo ^((~Bu)& Ba ); \ Esu0 = Bu ^((~Ba)& Be ); \ \ Aba1 ^= Da1; \ Ba = Aba1; \ Age1 ^= De1; \ Be = ROL32(Age1, 22); \ Aki0 ^= Di0; \ Bi = ROL32(Aki0, 21); \ Amo0 ^= Do0; \ Bo = ROL32(Amo0, 10); \ Asu1 ^= Du1; \ Bu = ROL32(Asu1, 7); \ Eba1 = Ba ^((~Be)& Bi ); \ Eba1 ^= *(pRoundConstants++); \ Ebe1 = Be ^((~Bi)& Bo ); \ Ebi1 = Bi ^((~Bo)& Bu ); \ Ebo1 = Bo ^((~Bu)& Ba ); \ Ebu1 = Bu ^((~Ba)& Be ); \ \ Abo1 ^= Do1; \ Ba = ROL32(Abo1, 14); \ Agu1 ^= Du1; \ Be = ROL32(Agu1, 10); \ Aka0 ^= Da0; \ Bi = ROL32(Aka0, 1); \ Ame0 ^= De0; \ Bo = ROL32(Ame0, 22); \ Asi0 ^= Di0; \ Bu = ROL32(Asi0, 30); \ Ega1 = Ba ^((~Be)& Bi ); \ Ege1 = Be ^((~Bi)& Bo ); \ Egi1 = Bi ^((~Bo)& Bu ); \ Ego1 = Bo ^((~Bu)& Ba ); \ Egu1 = Bu ^((~Ba)& Be ); \ \ Abe0 ^= De0; \ Ba = Abe0; \ Agi1 ^= Di1; \ Be = ROL32(Agi1, 3); \ Ako0 ^= Do0; \ Bi = ROL32(Ako0, 12); \ Amu1 ^= Du1; \ Bo = ROL32(Amu1, 4); \ Asa1 ^= Da1; \ Bu = ROL32(Asa1, 9); \ Eka1 = Ba ^((~Be)& Bi ); \ Eke1 = Be ^((~Bi)& Bo ); \ Eki1 = Bi ^((~Bo)& Bu ); \ Eko1 = Bo ^((~Bu)& Ba ); \ Eku1 = Bu ^((~Ba)& Be ); \ \ Abu0 ^= Du0; \ Ba = ROL32(Abu0, 13); \ Aga1 ^= Da1; \ Be = ROL32(Aga1, 18); \ Ake1 ^= De1; \ Bi = ROL32(Ake1, 5); \ Ami0 ^= Di0; \ Bo = ROL32(Ami0, 7); \ Aso1 ^= Do1; \ Bu = ROL32(Aso1, 28); \ Ema1 = Ba ^((~Be)& Bi ); \ Eme1 = Be ^((~Bi)& Bo ); \ Emi1 = Bi ^((~Bo)& Bu ); \ Emo1 = Bo ^((~Bu)& Ba ); \ Emu1 = Bu ^((~Ba)& Be ); \ \ Abi1 ^= Di1; \ Ba = ROL32(Abi1, 31); \ Ago0 ^= Do0; \ Be = ROL32(Ago0, 27); \ Aku0 ^= Du0; \ Bi = ROL32(Aku0, 19); \ Ama0 ^= Da0; \ Bo = ROL32(Ama0, 20); \ Ase1 ^= De1; \ Bu = ROL32(Ase1, 1); \ Esa1 = Ba ^((~Be)& Bi ); \ Ese1 = Be ^((~Bi)& Bo ); \ Esi1 = Bi ^((~Bo)& Bu ); \ Eso1 = Bo ^((~Bu)& Ba ); \ Esu1 = Bu ^((~Ba)& Be ); \ \ Cx = Ebu0^Egu0^Eku0^Emu0^Esu0; \ Du1 = Ebe1^Ege1^Eke1^Eme1^Ese1; \ Da0 = Cx^ROL32(Du1, 1); \ Cz = Ebu1^Egu1^Eku1^Emu1^Esu1; \ Du0 = Ebe0^Ege0^Eke0^Eme0^Ese0; \ Da1 = Cz^Du0; \ \ Cw = Ebi0^Egi0^Eki0^Emi0^Esi0; \ Do0 = Cw^ROL32(Cz, 1); \ Cy = Ebi1^Egi1^Eki1^Emi1^Esi1; \ Do1 = Cy^Cx; \ \ Cx = Eba0^Ega0^Eka0^Ema0^Esa0; \ De0 = Cx^ROL32(Cy, 1); \ Cz = Eba1^Ega1^Eka1^Ema1^Esa1; \ De1 = Cz^Cw; \ \ Cy = Ebo1^Ego1^Eko1^Emo1^Eso1; \ Di0 = Du0^ROL32(Cy, 1); \ Cw = Ebo0^Ego0^Eko0^Emo0^Eso0; \ Di1 = Du1^Cw; \ \ Du0 = Cw^ROL32(Cz, 1); \ Du1 = Cy^Cx; \ \ Eba0 ^= Da0; \ Ba = Eba0; \ Ege0 ^= De0; \ Be = ROL32(Ege0, 22); \ Eki1 ^= Di1; \ Bi = ROL32(Eki1, 22); \ Emo1 ^= Do1; \ Bo = ROL32(Emo1, 11); \ Esu0 ^= Du0; \ Bu = ROL32(Esu0, 7); \ Aba0 = Ba ^((~Be)& Bi ); \ Aba0 ^= *(pRoundConstants++); \ Abe0 = Be ^((~Bi)& Bo ); \ Abi0 = Bi ^((~Bo)& Bu ); \ Abo0 = Bo ^((~Bu)& Ba ); \ Abu0 = Bu ^((~Ba)& Be ); \ \ Ebo0 ^= Do0; \ Ba = ROL32(Ebo0, 14); \ Egu0 ^= Du0; \ Be = ROL32(Egu0, 10); \ Eka1 ^= Da1; \ Bi = ROL32(Eka1, 2); \ Eme1 ^= De1; \ Bo = ROL32(Eme1, 23); \ Esi1 ^= Di1; \ Bu = ROL32(Esi1, 31); \ Aga0 = Ba ^((~Be)& Bi ); \ Age0 = Be ^((~Bi)& Bo ); \ Agi0 = Bi ^((~Bo)& Bu ); \ Ago0 = Bo ^((~Bu)& Ba ); \ Agu0 = Bu ^((~Ba)& Be ); \ \ Ebe1 ^= De1; \ Ba = ROL32(Ebe1, 1); \ Egi0 ^= Di0; \ Be = ROL32(Egi0, 3); \ Eko1 ^= Do1; \ Bi = ROL32(Eko1, 13); \ Emu0 ^= Du0; \ Bo = ROL32(Emu0, 4); \ Esa0 ^= Da0; \ Bu = ROL32(Esa0, 9); \ Aka0 = Ba ^((~Be)& Bi ); \ Ake0 = Be ^((~Bi)& Bo ); \ Aki0 = Bi ^((~Bo)& Bu ); \ Ako0 = Bo ^((~Bu)& Ba ); \ Aku0 = Bu ^((~Ba)& Be ); \ \ Ebu1 ^= Du1; \ Ba = ROL32(Ebu1, 14); \ Ega0 ^= Da0; \ Be = ROL32(Ega0, 18); \ Eke0 ^= De0; \ Bi = ROL32(Eke0, 5); \ Emi1 ^= Di1; \ Bo = ROL32(Emi1, 8); \ Eso0 ^= Do0; \ Bu = ROL32(Eso0, 28); \ Ama0 = Ba ^((~Be)& Bi ); \ Ame0 = Be ^((~Bi)& Bo ); \ Ami0 = Bi ^((~Bo)& Bu ); \ Amo0 = Bo ^((~Bu)& Ba ); \ Amu0 = Bu ^((~Ba)& Be ); \ \ Ebi0 ^= Di0; \ Ba = ROL32(Ebi0, 31); \ Ego1 ^= Do1; \ Be = ROL32(Ego1, 28); \ Eku1 ^= Du1; \ Bi = ROL32(Eku1, 20); \ Ema1 ^= Da1; \ Bo = ROL32(Ema1, 21); \ Ese0 ^= De0; \ Bu = ROL32(Ese0, 1); \ Asa0 = Ba ^((~Be)& Bi ); \ Ase0 = Be ^((~Bi)& Bo ); \ Asi0 = Bi ^((~Bo)& Bu ); \ Aso0 = Bo ^((~Bu)& Ba ); \ Asu0 = Bu ^((~Ba)& Be ); \ \ Eba1 ^= Da1; \ Ba = Eba1; \ Ege1 ^= De1; \ Be = ROL32(Ege1, 22); \ Eki0 ^= Di0; \ Bi = ROL32(Eki0, 21); \ Emo0 ^= Do0; \ Bo = ROL32(Emo0, 10); \ Esu1 ^= Du1; \ Bu = ROL32(Esu1, 7); \ Aba1 = Ba ^((~Be)& Bi ); \ Aba1 ^= *(pRoundConstants++); \ Abe1 = Be ^((~Bi)& Bo ); \ Abi1 = Bi ^((~Bo)& Bu ); \ Abo1 = Bo ^((~Bu)& Ba ); \ Abu1 = Bu ^((~Ba)& Be ); \ \ Ebo1 ^= Do1; \ Ba = ROL32(Ebo1, 14); \ Egu1 ^= Du1; \ Be = ROL32(Egu1, 10); \ Eka0 ^= Da0; \ Bi = ROL32(Eka0, 1); \ Eme0 ^= De0; \ Bo = ROL32(Eme0, 22); \ Esi0 ^= Di0; \ Bu = ROL32(Esi0, 30); \ Aga1 = Ba ^((~Be)& Bi ); \ Age1 = Be ^((~Bi)& Bo ); \ Agi1 = Bi ^((~Bo)& Bu ); \ Ago1 = Bo ^((~Bu)& Ba ); \ Agu1 = Bu ^((~Ba)& Be ); \ \ Ebe0 ^= De0; \ Ba = Ebe0; \ Egi1 ^= Di1; \ Be = ROL32(Egi1, 3); \ Eko0 ^= Do0; \ Bi = ROL32(Eko0, 12); \ Emu1 ^= Du1; \ Bo = ROL32(Emu1, 4); \ Esa1 ^= Da1; \ Bu = ROL32(Esa1, 9); \ Aka1 = Ba ^((~Be)& Bi ); \ Ake1 = Be ^((~Bi)& Bo ); \ Aki1 = Bi ^((~Bo)& Bu ); \ Ako1 = Bo ^((~Bu)& Ba ); \ Aku1 = Bu ^((~Ba)& Be ); \ \ Ebu0 ^= Du0; \ Ba = ROL32(Ebu0, 13); \ Ega1 ^= Da1; \ Be = ROL32(Ega1, 18); \ Eke1 ^= De1; \ Bi = ROL32(Eke1, 5); \ Emi0 ^= Di0; \ Bo = ROL32(Emi0, 7); \ Eso1 ^= Do1; \ Bu = ROL32(Eso1, 28); \ Ama1 = Ba ^((~Be)& Bi ); \ Ame1 = Be ^((~Bi)& Bo ); \ Ami1 = Bi ^((~Bo)& Bu ); \ Amo1 = Bo ^((~Bu)& Ba ); \ Amu1 = Bu ^((~Ba)& Be ); \ \ Ebi1 ^= Di1; \ Ba = ROL32(Ebi1, 31); \ Ego0 ^= Do0; \ Be = ROL32(Ego0, 27); \ Eku0 ^= Du0; \ Bi = ROL32(Eku0, 19); \ Ema0 ^= Da0; \ Bo = ROL32(Ema0, 20); \ Ese1 ^= De1; \ Bu = ROL32(Ese1, 1); \ Asa1 = Ba ^((~Be)& Bi ); \ Ase1 = Be ^((~Bi)& Bo ); \ Asi1 = Bi ^((~Bo)& Bu ); \ Aso1 = Bo ^((~Bu)& Ba ); \ Asu1 = Bu ^((~Ba)& Be ); \ } \ copyToState(state, A) \ } #define copyFromState(X, state) \ X##ba0 = state[ 0]; \ X##ba1 = state[ 1]; \ X##be0 = state[ 2]; \ X##be1 = state[ 3]; \ X##bi0 = state[ 4]; \ X##bi1 = state[ 5]; \ X##bo0 = state[ 6]; \ X##bo1 = state[ 7]; \ X##bu0 = state[ 8]; \ X##bu1 = state[ 9]; \ X##ga0 = state[10]; \ X##ga1 = state[11]; \ X##ge0 = state[12]; \ X##ge1 = state[13]; \ X##gi0 = state[14]; \ X##gi1 = state[15]; \ X##go0 = state[16]; \ X##go1 = state[17]; \ X##gu0 = state[18]; \ X##gu1 = state[19]; \ X##ka0 = state[20]; \ X##ka1 = state[21]; \ X##ke0 = state[22]; \ X##ke1 = state[23]; \ X##ki0 = state[24]; \ X##ki1 = state[25]; \ X##ko0 = state[26]; \ X##ko1 = state[27]; \ X##ku0 = state[28]; \ X##ku1 = state[29]; \ X##ma0 = state[30]; \ X##ma1 = state[31]; \ X##me0 = state[32]; \ X##me1 = state[33]; \ X##mi0 = state[34]; \ X##mi1 = state[35]; \ X##mo0 = state[36]; \ X##mo1 = state[37]; \ X##mu0 = state[38]; \ X##mu1 = state[39]; \ X##sa0 = state[40]; \ X##sa1 = state[41]; \ X##se0 = state[42]; \ X##se1 = state[43]; \ X##si0 = state[44]; \ X##si1 = state[45]; \ X##so0 = state[46]; \ X##so1 = state[47]; \ X##su0 = state[48]; \ X##su1 = state[49]; \ #define copyToState(state, X) \ state[ 0] = X##ba0; \ state[ 1] = X##ba1; \ state[ 2] = X##be0; \ state[ 3] = X##be1; \ state[ 4] = X##bi0; \ state[ 5] = X##bi1; \ state[ 6] = X##bo0; \ state[ 7] = X##bo1; \ state[ 8] = X##bu0; \ state[ 9] = X##bu1; \ state[10] = X##ga0; \ state[11] = X##ga1; \ state[12] = X##ge0; \ state[13] = X##ge1; \ state[14] = X##gi0; \ state[15] = X##gi1; \ state[16] = X##go0; \ state[17] = X##go1; \ state[18] = X##gu0; \ state[19] = X##gu1; \ state[20] = X##ka0; \ state[21] = X##ka1; \ state[22] = X##ke0; \ state[23] = X##ke1; \ state[24] = X##ki0; \ state[25] = X##ki1; \ state[26] = X##ko0; \ state[27] = X##ko1; \ state[28] = X##ku0; \ state[29] = X##ku1; \ state[30] = X##ma0; \ state[31] = X##ma1; \ state[32] = X##me0; \ state[33] = X##me1; \ state[34] = X##mi0; \ state[35] = X##mi1; \ state[36] = X##mo0; \ state[37] = X##mo1; \ state[38] = X##mu0; \ state[39] = X##mu1; \ state[40] = X##sa0; \ state[41] = X##sa1; \ state[42] = X##se0; \ state[43] = X##se1; \ state[44] = X##si0; \ state[45] = X##si1; \ state[46] = X##so0; \ state[47] = X##so1; \ state[48] = X##su0; \ state[49] = X##su1; \ // ================================================================================ // =================== KeccakF-1600-32.macros // ================================================================================ /* 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 the designers, 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/ */ #ifdef UseSchedule #if (UseSchedule == 1) #include "KeccakF-1600-32-s1.macros" #elif (UseSchedule == 2) #include "KeccakF-1600-32-s2.macros" #elif (UseSchedule == 3) //#include "KeccakF-1600-32-rvk.macros" #else #error "This schedule is not supported." #endif #else #include "KeccakF-1600-32-s1.macros" #endif // ================================================================================ // =================== KeccakF-1600-opt32.c // ================================================================================ /* 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 the designers, 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/ */ #include //#include "brg_endian.h" //#include "KeccakF-1600-opt32-settings.h" //#include "KeccakF-1600-interface.h" #ifdef UseInterleaveTables int interleaveTablesBuilt = 0; UINT16 interleaveTable[65536]; UINT16 deinterleaveTable[65536]; void buildInterleaveTables() { UINT32 i, j; UINT16 x; if (!interleaveTablesBuilt) { for(i=0; i<65536; i++) { x = 0; for(j=0; j<16; j++) { if (i & (1 << j)) x |= (1 << (j/2 + 8*(j%2))); } interleaveTable[i] = x; deinterleaveTable[x] = (UINT16)i; } interleaveTablesBuilt = 1; } } #if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN) #define xor2bytesIntoInterleavedWords(even, odd, source, j) \ i##j = interleaveTable[((const UINT16*)source)[j]]; \ ((UINT8*)even)[j] ^= i##j & 0xFF; \ ((UINT8*)odd)[j] ^= i##j >> 8; #define setInterleavedWordsInto2bytes(dest, even, odd, j) \ d##j = deinterleaveTable[((even >> (j*8)) & 0xFF) ^ (((odd >> (j*8)) & 0xFF) << 8)]; \ ((UINT16*)dest)[j] = d##j; #else // (PLATFORM_BYTE_ORDER == IS_BIG_ENDIAN) #define xor2bytesIntoInterleavedWords(even, odd, source, j) \ i##j = interleaveTable[source[2*j] ^ ((UINT16)source[2*j+1] << 8)]; \ *even ^= (i##j & 0xFF) << (j*8); \ *odd ^= ((i##j >> 8) & 0xFF) << (j*8); #define setInterleavedWordsInto2bytes(dest, even, odd, j) \ d##j = deinterleaveTable[((even >> (j*8)) & 0xFF) ^ (((odd >> (j*8)) & 0xFF) << 8)]; \ dest[2*j] = d##j & 0xFF; \ dest[2*j+1] = d##j >> 8; #endif // Endianness void xor8bytesIntoInterleavedWords(UINT32 *even, UINT32 *odd, const UINT8* source) { UINT16 i0, i1, i2, i3; xor2bytesIntoInterleavedWords(even, odd, source, 0) xor2bytesIntoInterleavedWords(even, odd, source, 1) xor2bytesIntoInterleavedWords(even, odd, source, 2) xor2bytesIntoInterleavedWords(even, odd, source, 3) } #define xorLanesIntoState(laneCount, state, input) \ { \ int i; \ for(i=0; i<(laneCount); i++) \ xor8bytesIntoInterleavedWords(state+i*2, state+i*2+1, input+i*8); \ } void setInterleavedWordsInto8bytes(UINT8* dest, UINT32 even, UINT32 odd) { UINT16 d0, d1, d2, d3; setInterleavedWordsInto2bytes(dest, even, odd, 0) setInterleavedWordsInto2bytes(dest, even, odd, 1) setInterleavedWordsInto2bytes(dest, even, odd, 2) setInterleavedWordsInto2bytes(dest, even, odd, 3) } #define extractLanes(laneCount, state, data) \ { \ int i; \ for(i=0; i<(laneCount); i++) \ setInterleavedWordsInto8bytes(data+i*8, ((UINT32*)state)[i*2], ((UINT32*)state)[i*2+1]); \ } #else // No interleaving tables #if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN) // Credit: Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002 #define xorInterleavedLE(rateInLanes, state, input) \ { \ const UINT32 * pI = (const UINT32 *)input; \ UINT32 * pS = state; \ UINT32 t, x0, x1; \ int i; \ for (i = (rateInLanes)-1; i >= 0; --i) \ { \ x0 = *(pI++); \ t = (x0 ^ (x0 >> 1)) & 0x22222222UL; x0 = x0 ^ t ^ (t << 1); \ t = (x0 ^ (x0 >> 2)) & 0x0C0C0C0CUL; x0 = x0 ^ t ^ (t << 2); \ t = (x0 ^ (x0 >> 4)) & 0x00F000F0UL; x0 = x0 ^ t ^ (t << 4); \ t = (x0 ^ (x0 >> 8)) & 0x0000FF00UL; x0 = x0 ^ t ^ (t << 8); \ x1 = *(pI++); \ t = (x1 ^ (x1 >> 1)) & 0x22222222UL; x1 = x1 ^ t ^ (t << 1); \ t = (x1 ^ (x1 >> 2)) & 0x0C0C0C0CUL; x1 = x1 ^ t ^ (t << 2); \ t = (x1 ^ (x1 >> 4)) & 0x00F000F0UL; x1 = x1 ^ t ^ (t << 4); \ t = (x1 ^ (x1 >> 8)) & 0x0000FF00UL; x1 = x1 ^ t ^ (t << 8); \ *(pS++) ^= (UINT16)x0 | (x1 << 16); \ *(pS++) ^= (x0 >> 16) | (x1 & 0xFFFF0000); \ } \ } #define xorLanesIntoState(laneCount, state, input) \ xorInterleavedLE(laneCount, state, input) #else // (PLATFORM_BYTE_ORDER == IS_BIG_ENDIAN) // Credit: Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002 UINT64 toInterleaving(UINT64 x) { UINT64 t; t = (x ^ (x >> 1)) & 0x2222222222222222ULL; x = x ^ t ^ (t << 1); t = (x ^ (x >> 2)) & 0x0C0C0C0C0C0C0C0CULL; x = x ^ t ^ (t << 2); t = (x ^ (x >> 4)) & 0x00F000F000F000F0ULL; x = x ^ t ^ (t << 4); t = (x ^ (x >> 8)) & 0x0000FF000000FF00ULL; x = x ^ t ^ (t << 8); t = (x ^ (x >> 16)) & 0x00000000FFFF0000ULL; x = x ^ t ^ (t << 16); return x; } void xor8bytesIntoInterleavedWords(UINT32* evenAndOdd, const UINT8* source) { // This can be optimized UINT64 sourceWord = (UINT64)source[0] ^ (((UINT64)source[1]) << 8) ^ (((UINT64)source[2]) << 16) ^ (((UINT64)source[3]) << 24) ^ (((UINT64)source[4]) << 32) ^ (((UINT64)source[5]) << 40) ^ (((UINT64)source[6]) << 48) ^ (((UINT64)source[7]) << 56); UINT64 evenAndOddWord = toInterleaving(sourceWord); evenAndOdd[0] ^= (UINT32)evenAndOddWord; evenAndOdd[1] ^= (UINT32)(evenAndOddWord >> 32); } #define xorLanesIntoState(laneCount, state, input) \ { \ int i; \ for(i=0; i<(laneCount); i++) \ xor8bytesIntoInterleavedWords(state+i*2, input+i*8); \ } #endif // Endianness // Credit: Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002 UINT64 fromInterleaving(UINT64 x) { UINT64 t; t = (x ^ (x >> 16)) & 0x00000000FFFF0000ULL; x = x ^ t ^ (t << 16); t = (x ^ (x >> 8)) & 0x0000FF000000FF00ULL; x = x ^ t ^ (t << 8); t = (x ^ (x >> 4)) & 0x00F000F000F000F0ULL; x = x ^ t ^ (t << 4); t = (x ^ (x >> 2)) & 0x0C0C0C0C0C0C0C0CULL; x = x ^ t ^ (t << 2); t = (x ^ (x >> 1)) & 0x2222222222222222ULL; x = x ^ t ^ (t << 1); return x; } void setInterleavedWordsInto8bytes(UINT8* dest, UINT32* evenAndOdd) { #if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN) ((UINT64*)dest)[0] = fromInterleaving(*(UINT64*)evenAndOdd); #else // (PLATFORM_BYTE_ORDER == IS_BIG_ENDIAN) // This can be optimized UINT64 evenAndOddWord = (UINT64)evenAndOdd[0] ^ ((UINT64)evenAndOdd[1] << 32); UINT64 destWord = fromInterleaving(evenAndOddWord); dest[0] = destWord & 0xFF; dest[1] = (destWord >> 8) & 0xFF; dest[2] = (destWord >> 16) & 0xFF; dest[3] = (destWord >> 24) & 0xFF; dest[4] = (destWord >> 32) & 0xFF; dest[5] = (destWord >> 40) & 0xFF; dest[6] = (destWord >> 48) & 0xFF; dest[7] = (destWord >> 56) & 0xFF; #endif // Endianness } #define extractLanes(laneCount, state, data) \ { \ int i; \ for(i=0; i<(laneCount); i++) \ setInterleavedWordsInto8bytes(data+i*8, (UINT32*)state+i*2); \ } #endif // With or without interleaving tables #if defined(_MSC_VER) #define ROL32(a, offset) _rotl(a, offset) #elif (defined (__arm__) && defined(__ARMCC_VERSION)) #define ROL32(a, offset) __ror(a, 32-(offset)) #else #define ROL32(a, offset) ((((UINT32)a) << (offset)) ^ (((UINT32)a) >> (32-(offset)))) #endif //#include "KeccakF-1600-unrolling.macros" //#include "KeccakF-1600-32.macros" #if (UseSchedule == 3) #ifdef UseBebigokimisa #error "No lane complementing with schedule 3." #endif #if (Unrolling != 2) #error "Only unrolling 2 is supported by schedule 3." #endif void KeccakPermutationOnWords(UINT32 *state) { rounds } void KeccakPermutationOnWordsAfterXoring(UINT32 *state, const UINT8 *input, unsigned int laneCount) { xorLanesIntoState(laneCount, state, input) rounds } #ifdef ProvideFast576 void KeccakPermutationOnWordsAfterXoring576bits(UINT32 *state, const UINT8 *input) { xorLanesIntoState(9, state, input) rounds } #endif #ifdef ProvideFast832 void KeccakPermutationOnWordsAfterXoring832bits(UINT32 *state, const UINT8 *input) { xorLanesIntoState(13, state, input) rounds } #endif #ifdef ProvideFast1024 void KeccakPermutationOnWordsAfterXoring1024bits(UINT32 *state, const UINT8 *input) { xorLanesIntoState(16, state, input) rounds } #endif #ifdef ProvideFast1088 void KeccakPermutationOnWordsAfterXoring1088bits(UINT32 *state, const UINT8 *input) { xorLanesIntoState(17, state, input) rounds } #endif #ifdef ProvideFast1152 void KeccakPermutationOnWordsAfterXoring1152bits(UINT32 *state, const UINT8 *input) { xorLanesIntoState(18, state, input) rounds } #endif #ifdef ProvideFast1344 void KeccakPermutationOnWordsAfterXoring1344bits(UINT32 *state, const UINT8 *input) { xorLanesIntoState(21, state, input) rounds } #endif #else // (Schedule != 3) void KeccakPermutationOnWords(UINT32 *state) { declareABCDE #if (Unrolling != 24) unsigned int i; #endif copyFromState(A, state) rounds } void KeccakPermutationOnWordsAfterXoring(UINT32 *state, const UINT8 *input, unsigned int laneCount) { declareABCDE unsigned int i; xorLanesIntoState(laneCount, state, input) copyFromState(A, state) rounds } #ifdef ProvideFast576 void KeccakPermutationOnWordsAfterXoring576bits(UINT32 *state, const UINT8 *input) { declareABCDE unsigned int i; xorLanesIntoState(9, state, input) copyFromState(A, state) rounds } #endif #ifdef ProvideFast832 void KeccakPermutationOnWordsAfterXoring832bits(UINT32 *state, const UINT8 *input) { declareABCDE unsigned int i; xorLanesIntoState(13, state, input) copyFromState(A, state) rounds } #endif #ifdef ProvideFast1024 void KeccakPermutationOnWordsAfterXoring1024bits(UINT32 *state, const UINT8 *input) { declareABCDE unsigned int i; xorLanesIntoState(16, state, input) copyFromState(A, state) rounds } #endif #ifdef ProvideFast1088 void KeccakPermutationOnWordsAfterXoring1088bits(UINT32 *state, const UINT8 *input) { declareABCDE unsigned int i; xorLanesIntoState(17, state, input) copyFromState(A, state) rounds } #endif #ifdef ProvideFast1152 void KeccakPermutationOnWordsAfterXoring1152bits(UINT32 *state, const UINT8 *input) { declareABCDE unsigned int i; xorLanesIntoState(18, state, input) copyFromState(A, state) rounds } #endif #ifdef ProvideFast1344 void KeccakPermutationOnWordsAfterXoring1344bits(UINT32 *state, const UINT8 *input) { declareABCDE unsigned int i; xorLanesIntoState(21, state, input) copyFromState(A, state) rounds } #endif #endif void KeccakInitialize() { #ifdef UseInterleaveTables buildInterleaveTables(); #endif } void KeccakInitializeState(unsigned char *state) { memset(state, 0, 200); #ifdef UseBebigokimisa ((UINT32*)state)[ 2] = ~(UINT32)0; ((UINT32*)state)[ 3] = ~(UINT32)0; ((UINT32*)state)[ 4] = ~(UINT32)0; ((UINT32*)state)[ 5] = ~(UINT32)0; ((UINT32*)state)[16] = ~(UINT32)0; ((UINT32*)state)[17] = ~(UINT32)0; ((UINT32*)state)[24] = ~(UINT32)0; ((UINT32*)state)[25] = ~(UINT32)0; ((UINT32*)state)[34] = ~(UINT32)0; ((UINT32*)state)[35] = ~(UINT32)0; ((UINT32*)state)[40] = ~(UINT32)0; ((UINT32*)state)[41] = ~(UINT32)0; #endif } void KeccakPermutation(unsigned char *state) { // We assume the state is always stored as interleaved 32-bit words KeccakPermutationOnWords((UINT32*)state); } #ifdef ProvideFast576 void KeccakAbsorb576bits(unsigned char *state, const unsigned char *data) { KeccakPermutationOnWordsAfterXoring576bits((UINT32*)state, data); } #endif #ifdef ProvideFast832 void KeccakAbsorb832bits(unsigned char *state, const unsigned char *data) { KeccakPermutationOnWordsAfterXoring832bits((UINT32*)state, data); } #endif #ifdef ProvideFast1024 void KeccakAbsorb1024bits(unsigned char *state, const unsigned char *data) { KeccakPermutationOnWordsAfterXoring1024bits((UINT32*)state, data); } #endif #ifdef ProvideFast1088 void KeccakAbsorb1088bits(unsigned char *state, const unsigned char *data) { KeccakPermutationOnWordsAfterXoring1088bits((UINT32*)state, data); } #endif #ifdef ProvideFast1152 void KeccakAbsorb1152bits(unsigned char *state, const unsigned char *data) { KeccakPermutationOnWordsAfterXoring1152bits((UINT32*)state, data); } #endif #ifdef ProvideFast1344 void KeccakAbsorb1344bits(unsigned char *state, const unsigned char *data) { KeccakPermutationOnWordsAfterXoring1344bits((UINT32*)state, data); } #endif void KeccakAbsorb(unsigned char *state, const unsigned char *data, unsigned int laneCount) { KeccakPermutationOnWordsAfterXoring((UINT32*)state, data, laneCount); } #ifdef ProvideFast1024 void KeccakExtract1024bits(const unsigned char *state, unsigned char *data) { extractLanes(16, state, data) #ifdef UseBebigokimisa ((UINT32*)data)[ 2] = ~((UINT32*)data)[ 2]; ((UINT32*)data)[ 3] = ~((UINT32*)data)[ 3]; ((UINT32*)data)[ 4] = ~((UINT32*)data)[ 4]; ((UINT32*)data)[ 5] = ~((UINT32*)data)[ 5]; ((UINT32*)data)[16] = ~((UINT32*)data)[16]; ((UINT32*)data)[17] = ~((UINT32*)data)[17]; ((UINT32*)data)[24] = ~((UINT32*)data)[24]; ((UINT32*)data)[25] = ~((UINT32*)data)[25]; #endif } #endif void KeccakExtract(const unsigned char *state, unsigned char *data, unsigned int laneCount) { extractLanes((int)laneCount, state, data) #ifdef UseBebigokimisa if (laneCount > 1) { ((UINT32*)data)[ 2] = ~((UINT32*)data)[ 2]; ((UINT32*)data)[ 3] = ~((UINT32*)data)[ 3]; if (laneCount > 2) { ((UINT32*)data)[ 4] = ~((UINT32*)data)[ 4]; ((UINT32*)data)[ 5] = ~((UINT32*)data)[ 5]; if (laneCount > 8) { ((UINT32*)data)[16] = ~((UINT32*)data)[16]; ((UINT32*)data)[17] = ~((UINT32*)data)[17]; if (laneCount > 12) { ((UINT32*)data)[24] = ~((UINT32*)data)[24]; ((UINT32*)data)[25] = ~((UINT32*)data)[25]; if (laneCount > 17) { ((UINT32*)data)[34] = ~((UINT32*)data)[34]; ((UINT32*)data)[35] = ~((UINT32*)data)[35]; if (laneCount > 20) { ((UINT32*)data)[40] = ~((UINT32*)data)[40]; ((UINT32*)data)[41] = ~((UINT32*)data)[41]; } } } } } } #endif } // ================================================================================ // =================== KeccakSponge.c // ================================================================================ /* 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 the designers, 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/ */ #include //#include "KeccakSponge.h" //#include "KeccakF-1600-interface.h" #ifdef KeccakReference //#include "displayIntermediateValues.h" #endif int InitSponge(spongeState *state, unsigned int rate, unsigned int capacity) { if (rate+capacity != 1600) return 1; if ((rate <= 0) || (rate >= 1600) || ((rate % 64) != 0)) return 1; KeccakInitialize(); state->rate = rate; state->capacity = capacity; state->fixedOutputLength = 0; KeccakInitializeState(state->state); memset(state->dataQueue, 0, KeccakMaximumRateInBytes); state->bitsInQueue = 0; state->squeezing = 0; state->bitsAvailableForSqueezing = 0; return 0; } void AbsorbQueue(spongeState *state) { // state->bitsInQueue is assumed to be equal to state->rate #ifdef KeccakReference displayBytes(1, "Block to be absorbed", state->dataQueue, state->rate/8); #endif #ifdef ProvideFast576 if (state->rate == 576) KeccakAbsorb576bits(state->state, state->dataQueue); else #endif #ifdef ProvideFast832 if (state->rate == 832) KeccakAbsorb832bits(state->state, state->dataQueue); else #endif #ifdef ProvideFast1024 if (state->rate == 1024) KeccakAbsorb1024bits(state->state, state->dataQueue); else #endif #ifdef ProvideFast1088 if (state->rate == 1088) KeccakAbsorb1088bits(state->state, state->dataQueue); else #endif #ifdef ProvideFast1152 if (state->rate == 1152) KeccakAbsorb1152bits(state->state, state->dataQueue); else #endif #ifdef ProvideFast1344 if (state->rate == 1344) KeccakAbsorb1344bits(state->state, state->dataQueue); else #endif KeccakAbsorb(state->state, state->dataQueue, state->rate/64); state->bitsInQueue = 0; } int Absorb(spongeState *state, const unsigned char *data, unsigned long long databitlen) { unsigned long long i, j, wholeBlocks; unsigned int partialBlock, partialByte; const unsigned char *curData; if ((state->bitsInQueue % 8) != 0) return 1; // Only the last call may contain a partial byte if (state->squeezing) return 1; // Too late for additional input i = 0; while(i < databitlen) { if ((state->bitsInQueue == 0) && (databitlen >= state->rate) && (i <= (databitlen-state->rate))) { wholeBlocks = (databitlen-i)/state->rate; curData = data+i/8; #ifdef ProvideFast576 if (state->rate == 576) { for(j=0; jrate/8); #endif KeccakAbsorb576bits(state->state, curData); } } else #endif #ifdef ProvideFast832 if (state->rate == 832) { for(j=0; jrate/8); #endif KeccakAbsorb832bits(state->state, curData); } } else #endif #ifdef ProvideFast1024 if (state->rate == 1024) { for(j=0; jrate/8); #endif KeccakAbsorb1024bits(state->state, curData); } } else #endif #ifdef ProvideFast1088 if (state->rate == 1088) { for(j=0; jrate/8); #endif KeccakAbsorb1088bits(state->state, curData); } } else #endif #ifdef ProvideFast1152 if (state->rate == 1152) { for(j=0; jrate/8); #endif KeccakAbsorb1152bits(state->state, curData); } } else #endif #ifdef ProvideFast1344 if (state->rate == 1344) { for(j=0; jrate/8); #endif KeccakAbsorb1344bits(state->state, curData); } } else #endif { for(j=0; jrate/8) { #ifdef KeccakReference displayBytes(1, "Block to be absorbed", curData, state->rate/8); #endif KeccakAbsorb(state->state, curData, state->rate/64); } } i += wholeBlocks*state->rate; } else { partialBlock = (unsigned int)(databitlen - i); if (partialBlock+state->bitsInQueue > state->rate) partialBlock = state->rate-state->bitsInQueue; partialByte = partialBlock % 8; partialBlock -= partialByte; memcpy(state->dataQueue+state->bitsInQueue/8, data+i/8, partialBlock/8); state->bitsInQueue += partialBlock; i += partialBlock; if (state->bitsInQueue == state->rate) AbsorbQueue(state); if (partialByte > 0) { unsigned char mask = (1 << partialByte)-1; state->dataQueue[state->bitsInQueue/8] = data[i/8] & mask; state->bitsInQueue += partialByte; i += partialByte; } } } return 0; } void PadAndSwitchToSqueezingPhase(spongeState *state) { // Note: the bits are numbered from 0=LSB to 7=MSB if (state->bitsInQueue + 1 == state->rate) { state->dataQueue[state->bitsInQueue/8 ] |= 1 << (state->bitsInQueue % 8); AbsorbQueue(state); memset(state->dataQueue, 0, state->rate/8); } else { memset(state->dataQueue + (state->bitsInQueue+7)/8, 0, state->rate/8 - (state->bitsInQueue+7)/8); state->dataQueue[state->bitsInQueue/8 ] |= 1 << (state->bitsInQueue % 8); } state->dataQueue[(state->rate-1)/8] |= 1 << ((state->rate-1) % 8); AbsorbQueue(state); #ifdef KeccakReference displayText(1, "--- Switching to squeezing phase ---"); #endif #ifdef ProvideFast1024 if (state->rate == 1024) { KeccakExtract1024bits(state->state, state->dataQueue); state->bitsAvailableForSqueezing = 1024; } else #endif { KeccakExtract(state->state, state->dataQueue, state->rate/64); state->bitsAvailableForSqueezing = state->rate; } #ifdef KeccakReference displayBytes(1, "Block available for squeezing", state->dataQueue, state->bitsAvailableForSqueezing/8); #endif state->squeezing = 1; } int Squeeze(spongeState *state, unsigned char *output, unsigned long long outputLength) { unsigned long long i; unsigned int partialBlock; if (!state->squeezing) PadAndSwitchToSqueezingPhase(state); if ((outputLength % 8) != 0) return 1; // Only multiple of 8 bits are allowed, truncation can be done at user level i = 0; while(i < outputLength) { if (state->bitsAvailableForSqueezing == 0) { KeccakPermutation(state->state); #ifdef ProvideFast1024 if (state->rate == 1024) { KeccakExtract1024bits(state->state, state->dataQueue); state->bitsAvailableForSqueezing = 1024; } else #endif { KeccakExtract(state->state, state->dataQueue, state->rate/64); state->bitsAvailableForSqueezing = state->rate; } #ifdef KeccakReference displayBytes(1, "Block available for squeezing", state->dataQueue, state->bitsAvailableForSqueezing/8); #endif } partialBlock = state->bitsAvailableForSqueezing; if ((unsigned long long)partialBlock > outputLength - i) partialBlock = (unsigned int)(outputLength - i); memcpy(output+i/8, state->dataQueue+(state->rate-state->bitsAvailableForSqueezing)/8, partialBlock/8); state->bitsAvailableForSqueezing -= partialBlock; i += partialBlock; } return 0; } // ================================================================================ // =================== KeccakNISTInterface.h // ================================================================================ /* 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 the designers, 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/ */ #ifndef _KeccakNISTInterface_h_ #define _KeccakNISTInterface_h_ //#include "KeccakSponge.h" typedef unsigned char BitSequence; typedef unsigned long long DataLength; typedef enum { SUCCESS = 0, FAIL = 1, BAD_HASHLEN = 2 } HashReturn; typedef spongeState hashState; /** * Function to initialize the state of the Keccak[r, c] sponge function. * The rate r and capacity c values are determined from @a hashbitlen. * @param state Pointer to the state of the sponge function to be initialized. * @param hashbitlen The desired number of output bits, * or 0 for Keccak[] with default parameters * and arbitrarily-long output. * @pre The value of hashbitlen must be one of 0, 224, 256, 384 and 512. * @return SUCCESS if successful, BAD_HASHLEN if the value of hashbitlen is incorrect. */ HashReturn Init(hashState *state, int hashbitlen); /** * Function to give input data for the sponge function to absorb. * @param state Pointer to the state of the sponge function initialized by Init(). * @param data Pointer to the input data. * When @a databitLen is not a multiple of 8, the last bits of data must be * in the most significant bits of the last byte. * @param databitLen The number of input bits provided in the input data. * @pre In the previous call to Absorb(), databitLen was a multiple of 8. * @return SUCCESS if successful, FAIL otherwise. */ HashReturn Update(hashState *state, const BitSequence *data, DataLength databitlen); /** * Function to squeeze output data from the sponge function. * If @a hashbitlen was not 0 in the call to Init(), the number of output bits is equal to @a hashbitlen. * If @a hashbitlen was 0 in the call to Init(), the output bits must be extracted using the Squeeze() function. * @param state Pointer to the state of the sponge function initialized by Init(). * @param hashval Pointer to the buffer where to store the output data. * @return SUCCESS if successful, FAIL otherwise. */ HashReturn Final(hashState *state, BitSequence *hashval); /** * Function to compute a hash using the Keccak[r, c] sponge function. * The rate r and capacity c values are determined from @a hashbitlen. * @param hashbitlen The desired number of output bits. * @param data Pointer to the input data. * When @a databitLen is not a multiple of 8, the last bits of data must be * in the most significant bits of the last byte. * @param databitLen The number of input bits provided in the input data. * @param hashval Pointer to the buffer where to store the output data. * @pre The value of hashbitlen must be one of 224, 256, 384 and 512. * @return SUCCESS if successful, BAD_HASHLEN if the value of hashbitlen is incorrect. */ HashReturn Hash(int hashbitlen, const BitSequence *data, DataLength databitlen, BitSequence *hashval); #endif // ================================================================================ // =================== KeccakNISTInterface.c // ================================================================================ /* 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 the designers, 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/ */ #include //#include "KeccakNISTInterface.h" //#include "KeccakF-1600-interface.h" HashReturn Init(hashState *state, int hashbitlen) { switch(hashbitlen) { case 0: // Default parameters, arbitrary length output InitSponge((spongeState*)state, 1024, 576); break; case 224: InitSponge((spongeState*)state, 1152, 448); break; case 256: InitSponge((spongeState*)state, 1088, 512); break; case 384: InitSponge((spongeState*)state, 832, 768); break; case 512: InitSponge((spongeState*)state, 576, 1024); break; default: return BAD_HASHLEN; } state->fixedOutputLength = hashbitlen; return SUCCESS; } HashReturn Update(hashState *state, const BitSequence *data, DataLength databitlen) { if ((databitlen % 8) == 0) return (HashReturn)Absorb((spongeState*)state, data, databitlen); else { HashReturn ret = (HashReturn)Absorb((spongeState*)state, data, databitlen - (databitlen % 8)); if (ret == SUCCESS) { unsigned char lastByte; // Align the last partial byte to the least significant bits lastByte = data[databitlen/8] >> (8 - (databitlen % 8)); return (HashReturn)Absorb((spongeState*)state, &lastByte, databitlen % 8); } else return ret; } } HashReturn Final(hashState *state, BitSequence *hashval) { return (HashReturn)Squeeze(state, hashval, state->fixedOutputLength); } HashReturn Hash(int hashbitlen, const BitSequence *data, DataLength databitlen, BitSequence *hashval) { hashState state; HashReturn result; if ((hashbitlen != 224) && (hashbitlen != 256) && (hashbitlen != 384) && (hashbitlen != 512)) return BAD_HASHLEN; // Only the four fixed output lengths available through this API result = Init(&state, hashbitlen); if (result != SUCCESS) return result; result = Update(&state, data, databitlen); if (result != SUCCESS) return result; result = Final(&state, hashval); return result; } } // end of namespace KeccakImpl