From cc3956690d8b78b422203950e4f829e4821df190 Mon Sep 17 00:00:00 2001 From: kremlin Date: Fri, 19 Sep 2014 20:43:28 -0400 Subject: [PATCH] import C keccak implementation taken from NIST reference --- .../KremKeccak/KeccakF-1600-reference.c | 300 ++++++++++++++++++ DH-Keccak/assets/KremKeccak/KeccakSponge.c | 266 ++++++++++++++++ DH-Keccak/assets/KremKeccak/Makefile | 4 + .../KremKeccak/displayIntermediateValues.c | 117 +++++++ DH-Keccak/assets/KremKeccak/krem_keccak.c | 87 +++++ 5 files changed, 774 insertions(+) create mode 100755 DH-Keccak/assets/KremKeccak/KeccakF-1600-reference.c create mode 100755 DH-Keccak/assets/KremKeccak/KeccakSponge.c create mode 100644 DH-Keccak/assets/KremKeccak/Makefile create mode 100755 DH-Keccak/assets/KremKeccak/displayIntermediateValues.c create mode 100644 DH-Keccak/assets/KremKeccak/krem_keccak.c diff --git a/DH-Keccak/assets/KremKeccak/KeccakF-1600-reference.c b/DH-Keccak/assets/KremKeccak/KeccakF-1600-reference.c new file mode 100755 index 0000000..628f710 --- /dev/null +++ b/DH-Keccak/assets/KremKeccak/KeccakF-1600-reference.c @@ -0,0 +1,300 @@ +/* +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 +#include "brg_endian.h" +#include "displayIntermediateValues.h" +#include "KeccakNISTInterface.h" +#include "KeccakF-1600-interface.h" + +typedef unsigned char UINT8; +typedef unsigned long long int UINT64; + +#define nrRounds 24 +UINT64 KeccakRoundConstants[nrRounds]; +#define nrLanes 25 +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) +{ + unsigned int i, j; + + for(i=0; i<(KeccakPermutationSize/64); i++) { + stateAsWords[i] = 0; + for(j=0; j<(64/8); j++) + stateAsWords[i] |= (UINT64)(state[i*(64/8)+j]) << (8*j); + } +} + +void fromWordsToBytes(unsigned char *state, const UINT64 *stateAsWords) +{ + unsigned int i, j; + + for(i=0; i<(KeccakPermutationSize/64); i++) + for(j=0; j<(64/8); j++) + state[i*(64/8)+j] = (stateAsWords[i] >> (8*j)) & 0xFF; +} + +void KeccakPermutation(unsigned char *state) +{ +#if (PLATFORM_BYTE_ORDER != IS_LITTLE_ENDIAN) + UINT64 stateAsWords[KeccakPermutationSize/64]; +#endif + + displayStateAsBytes(1, "Input of permutation", state); +#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN) + KeccakPermutationOnWords((UINT64*)state); +#else + fromBytesToWords(stateAsWords, state); + KeccakPermutationOnWords(stateAsWords); + fromWordsToBytes(state, stateAsWords); +#endif + displayStateAsBytes(1, "State after permutation", state); +} + +void KeccakPermutationAfterXor(unsigned char *state, const unsigned char *data, unsigned int dataLengthInBytes) +{ + unsigned int i; + + for(i=0; i> (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() +{ + UINT8 LFSRstate = 0x01; + unsigned int i, j, bitPosition; + + for(i=0; i> 32)); + fprintf(f, "%08X", (unsigned int)(KeccakRoundConstants[i] & 0xFFFFFFFFULL)); + fprintf(f, "\n"); + } + fprintf(f, "\n"); +} + +void displayRhoOffsets(FILE *f) +{ + unsigned int x, y; + + for(y=0; y<5; y++) for(x=0; x<5; x++) { + fprintf(f, "RhoOffset[%i][%i] = ", x, y); + fprintf(f, "%2i", KeccakRhoOffsets[index(x, y)]); + fprintf(f, "\n"); + } + fprintf(f, "\n"); +} + +void KeccakInitializeState(unsigned char *state) +{ + memset(state, 0, KeccakPermutationSizeInBytes); +} + +#ifdef ProvideFast576 +void KeccakAbsorb576bits(unsigned char *state, const unsigned char *data) +{ + KeccakPermutationAfterXor(state, data, 72); +} +#endif + +#ifdef ProvideFast832 +void KeccakAbsorb832bits(unsigned char *state, const unsigned char *data) +{ + KeccakPermutationAfterXor(state, data, 104); +} +#endif + +#ifdef ProvideFast1024 +void KeccakAbsorb1024bits(unsigned char *state, const unsigned char *data) +{ + KeccakPermutationAfterXor(state, data, 128); +} +#endif + +#ifdef ProvideFast1088 +void KeccakAbsorb1088bits(unsigned char *state, const unsigned char *data) +{ + KeccakPermutationAfterXor(state, data, 136); +} +#endif + +#ifdef ProvideFast1152 +void KeccakAbsorb1152bits(unsigned char *state, const unsigned char *data) +{ + KeccakPermutationAfterXor(state, data, 144); +} +#endif + +#ifdef ProvideFast1344 +void KeccakAbsorb1344bits(unsigned char *state, const unsigned char *data) +{ + KeccakPermutationAfterXor(state, data, 168); +} +#endif + +void KeccakAbsorb(unsigned char *state, const unsigned char *data, unsigned int laneCount) +{ + KeccakPermutationAfterXor(state, data, laneCount*8); +} + +#ifdef ProvideFast1024 +void KeccakExtract1024bits(const unsigned char *state, unsigned char *data) +{ + memcpy(data, state, 128); +} +#endif + +void KeccakExtract(const unsigned char *state, unsigned char *data, unsigned int laneCount) +{ + memcpy(data, state, laneCount*8); +} diff --git a/DH-Keccak/assets/KremKeccak/KeccakSponge.c b/DH-Keccak/assets/KremKeccak/KeccakSponge.c new file mode 100755 index 0000000..5939ba4 --- /dev/null +++ b/DH-Keccak/assets/KremKeccak/KeccakSponge.c @@ -0,0 +1,266 @@ +/* +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; +} diff --git a/DH-Keccak/assets/KremKeccak/Makefile b/DH-Keccak/assets/KremKeccak/Makefile new file mode 100644 index 0000000..2832275 --- /dev/null +++ b/DH-Keccak/assets/KremKeccak/Makefile @@ -0,0 +1,4 @@ +.PHONY: all + +all: + gcc -o krem-keccak -Wall -Werror -g -std=c99 krem_keccak.c -Wno-unused diff --git a/DH-Keccak/assets/KremKeccak/displayIntermediateValues.c b/DH-Keccak/assets/KremKeccak/displayIntermediateValues.c new file mode 100755 index 0000000..f3bf9e2 --- /dev/null +++ b/DH-Keccak/assets/KremKeccak/displayIntermediateValues.c @@ -0,0 +1,117 @@ +/* +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 "displayIntermediateValues.h" +#include "KeccakNISTInterface.h" + +FILE *intermediateValueFile = 0; +int displayLevel = 0; + +void displaySetIntermediateValueFile(FILE *f) +{ + intermediateValueFile = f; +} + +void displaySetLevel(int level) +{ + displayLevel = level; +} + +void displayBytes(int level, const char *text, const unsigned char *bytes, unsigned int size) +{ + unsigned int i; + + if ((intermediateValueFile) && (level <= displayLevel)) { + fprintf(intermediateValueFile, "%s:\n", text); + for(i=0; i> iBit) & 0x01) != 0); + } + fprintf(intermediateValueFile, "\n"); + fprintf(intermediateValueFile, "\n"); + } +} + +void displayStateAsBytes(int level, const char *text, const unsigned char *state) +{ + displayBytes(level, text, state, KeccakPermutationSizeInBytes); +} + +void displayStateAs32bitWords(int level, const char *text, const unsigned int *state) +{ + unsigned int i; + + if ((intermediateValueFile) && (level <= displayLevel)) { + fprintf(intermediateValueFile, "%s:\n", text); + for(i=0; i> 32)); + fprintf(intermediateValueFile, "%08X", (unsigned int)(state[i] & 0xFFFFFFFFULL)); + if ((i%5) == 4) + fprintf(intermediateValueFile, "\n"); + else + fprintf(intermediateValueFile, " "); + } + } +} + +void displayRoundNumber(int level, unsigned int i) +{ + if ((intermediateValueFile) && (level <= displayLevel)) { + fprintf(intermediateValueFile, "\n"); + fprintf(intermediateValueFile, "--- Round %d ---\n", i); + fprintf(intermediateValueFile, "\n"); + } +} + +void displayText(int level, const char *text) +{ + if ((intermediateValueFile) && (level <= displayLevel)) { + fprintf(intermediateValueFile, text); + fprintf(intermediateValueFile, "\n"); + fprintf(intermediateValueFile, "\n"); + } +} diff --git a/DH-Keccak/assets/KremKeccak/krem_keccak.c b/DH-Keccak/assets/KremKeccak/krem_keccak.c new file mode 100644 index 0000000..01fe486 --- /dev/null +++ b/DH-Keccak/assets/KremKeccak/krem_keccak.c @@ -0,0 +1,87 @@ +#include +#include +#include + +#include +#include + +#include "../keccak-ref/Sources/KeccakSponge.c" +#include "../keccak-ref/Sources/KeccakF-1600-reference.c" +#include "../keccak-ref/Sources/displayIntermediateValues.c" + +#define HI_NIBBLE(b) (((b) >> 4) & 0x0F) +#define LO_NIBBLE(b) ((b) & 0x0F) + +int main(int argc, char *argv[]) { + + unsigned int r, c, i; + spongeState *state; + + FILE *input; + struct stat input_stat; + unsigned char *input_buf, *output_buf; + size_t input_bytes_read; + + if(argc != 2) { + + printf("no input file provided\nUSAGE: %s \n", argv[0]); + exit(1); + + } else if( ! (input = fopen(argv[1], "r"))) { + + printf("error opening file '%s'\n", argv[1]); + exit(1); + } + + /* significant values */ + r = 576; + c = 1024; + + state = (spongeState*) calloc(1, sizeof(spongeState)); + + if(stat(argv[1], &input_stat) || input_stat.st_size <= 0) { + + printf("failed to stat '%s'\n", argv[1]); + exit(1); + + } else if(InitSponge(state, r, c) || !state) { + + printf("error during sponge construction\n"); + exit(1); + + } else if(input_stat.st_size > SIZE_MAX) { + + printf("large files not supported yet\n"); + exit(1); + } + + input_buf = (unsigned char *) calloc(1, (size_t) input_stat.st_size); + output_buf = (unsigned char *) calloc(1, (size_t) 64); + + if( ! (input_bytes_read = fread(input_buf, 1, (size_t)input_stat.st_size, input))) { + + printf("error reading file\n"); + exit(1); + } + + fclose(input); + + if(Absorb(state, input_buf, (unsigned long long) (8 * input_stat.st_size))) { + + printf("encryption failure\n"); + exit(1); + + } else if(Squeeze(state, output_buf, (unsigned long long) (8 * input_stat.st_size))) { + + printf("decryption failure\n"); + exit(1); + } + + i = 0; + for(; i < 64; i++) + printf("%x%x", HI_NIBBLE(output_buf[i]), LO_NIBBLE(output_buf[i])); + + free(state); + + return 0; +} -- 2.41.0