/* The eXtended Keccak Code Package (XKCP) https://github.com/XKCP/XKCP The Keccak-p permutations, designed by Guido Bertoni, Joan Daemen, Michaƫl Peeters and Gilles Van Assche. Implementation by Ronny Van Keer, hereby denoted as "the implementer". For more information, feedback or questions, please refer to the Keccak Team website: https://keccak.team/ 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/ --- This file implements Keccak-p[1600] in a SnP-compatible way. Please refer to SnP-documentation.h for more details. This implementation comes with KeccakP-1600-SnP.h in the same folder. Please refer to LowLevel.build for the exact list of other files it must be combined with. */ #include #include #include #include "brg_endian.h" #include "KeccakP-1600-SnP.h" #include "SnP-Relaned.h" #define USE_MEMSET /* #define DIVISION_INSTRUCTION */ /* comment if no division instruction or more compact when not using division */ #define UNROLL_CHILOOP /* comment more compact using for loop */ typedef uint_fast8_t tSmallUInt; typedef uint64_t tKeccakLane; #if defined(_MSC_VER) #define ROL64(a, offset) _rotl64(a, offset) #elif defined(UseSHLD) #define ROL64(x,N) ({ \ register uint64_t __out; \ register uint64_t __in = x; \ __asm__ ("shld %2,%0,%0" : "=r"(__out) : "0"(__in), "i"(N)); \ __out; \ }) #else #define ROL64(a, offset) ((((uint64_t)a) << offset) ^ (((uint64_t)a) >> (64-offset))) #endif #define cKeccakNumberOfRounds 24 const uint8_t KeccakP1600_RotationConstants[25] = { 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44 }; const uint8_t KeccakP1600_PiLane[25] = { 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1 }; #if defined(DIVISION_INSTRUCTION) #define MOD5(argValue) ((argValue) % 5) #else const uint8_t KeccakP1600_Mod5[10] = { 0, 1, 2, 3, 4, 0, 1, 2, 3, 4 }; #define MOD5(argValue) KeccakP1600_Mod5[argValue] #endif /* ---------------------------------------------------------------- */ static tKeccakLane KeccakF1600_GetNextRoundConstant( uint8_t *LFSR ); static tKeccakLane KeccakF1600_GetNextRoundConstant( uint8_t *LFSR ) { tSmallUInt i; tKeccakLane roundConstant; tSmallUInt doXOR; tSmallUInt tempLSFR; roundConstant = 0; tempLSFR = *LFSR; for(i=1; i<128; i <<= 1) { doXOR = tempLSFR & 1; if ((tempLSFR & 0x80) != 0) /* Primitive polynomial over GF(2): x^8+x^6+x^5+x^4+1 */ tempLSFR = (tempLSFR << 1) ^ 0x71; else tempLSFR <<= 1; if ( doXOR != 0 ) roundConstant ^= (tKeccakLane)1ULL << (i - 1); } *LFSR = (uint8_t)tempLSFR; return ( roundConstant ); } /* ---------------------------------------------------------------- */ void KeccakP1600_Initialize(KeccakP1600_plain64_state *argState) { #if defined(USE_MEMSET) memset( argState, 0, 25 * 8 ); #else tSmallUInt i; tKeccakLane *state; state = argState; i = 25; do { *(state++) = 0; } while ( --i != 0 ); #endif } /* ---------------------------------------------------------------- */ void KeccakP1600_AddBytesInLane(KeccakP1600_plain64_state *argState, unsigned int lanePosition, const unsigned char *data, unsigned int offset, unsigned int length) { unsigned int i; #if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN) unsigned char * state = (unsigned char*)argState + lanePosition * sizeof(tKeccakLane) + offset; for(i=0; i>= offset*8; for(i=0; i>= 8; } #endif } /* ---------------------------------------------------------------- */ void KeccakP1600_ExtractLanes(const KeccakP1600_plain64_state *state, unsigned char *data, unsigned int laneCount) { #if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN) memcpy(data, state, laneCount*8); #else tSmallUInt i, j; for(i=0; i> (8*j)) & 0xFF; } } #endif } /* ---------------------------------------------------------------- */ void KeccakP1600_ExtractBytes(const KeccakP1600_plain64_state *state, unsigned char *data, unsigned int offset, unsigned int length) { SnP_ExtractBytes(state, data, offset, length, KeccakP1600_ExtractLanes, KeccakP1600_ExtractBytesInLane, 8); } /* ---------------------------------------------------------------- */ void KeccakP1600_ExtractAndAddBytesInLane(const KeccakP1600_plain64_state *state, unsigned int lanePosition, const unsigned char *input, unsigned char *output, unsigned int offset, unsigned int length) { tSmallUInt i; tKeccakLane lane = ((tKeccakLane*)state)[lanePosition]; lane >>= offset*8; for(i=0; i>= 8; } } /* ---------------------------------------------------------------- */ void KeccakP1600_ExtractAndAddLanes(const KeccakP1600_plain64_state *state, const unsigned char *input, unsigned char *output, unsigned int laneCount) { #if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN) tSmallUInt i; for(i=0; i> (8*j)) & 0xFF); } } #endif } /* ---------------------------------------------------------------- */ void KeccakP1600_ExtractAndAddBytes(const KeccakP1600_plain64_state *state, const unsigned char *input, unsigned char *output, unsigned int offset, unsigned int length) { SnP_ExtractAndAddBytes(state, input, output, offset, length, KeccakP1600_ExtractAndAddLanes, KeccakP1600_ExtractAndAddBytesInLane, 8); } /* ---------------------------------------------------------------- */