import C keccak implementation taken from NIST reference
authorkremlin <ian@kremlin.cc>
Sat, 20 Sep 2014 00:43:28 +0000 (20:43 -0400)
committerkremlin <ian@kremlin.cc>
Sat, 20 Sep 2014 00:43:28 +0000 (20:43 -0400)
DH-Keccak/assets/KremKeccak/KeccakF-1600-reference.c [new file with mode: 0755]
DH-Keccak/assets/KremKeccak/KeccakSponge.c [new file with mode: 0755]
DH-Keccak/assets/KremKeccak/Makefile [new file with mode: 0644]
DH-Keccak/assets/KremKeccak/displayIntermediateValues.c [new file with mode: 0755]
DH-Keccak/assets/KremKeccak/krem_keccak.c [new file with mode: 0644]

diff --git a/DH-Keccak/assets/KremKeccak/KeccakF-1600-reference.c b/DH-Keccak/assets/KremKeccak/KeccakF-1600-reference.c
new file mode 100755 (executable)
index 0000000..628f710
--- /dev/null
@@ -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 <stdio.h>
+#include <string.h>
+#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<dataLengthInBytes; i++)
+        state[i] ^= data[i];
+    KeccakPermutation(state);
+}
+
+void KeccakPermutationOnWords(UINT64 *state)
+{
+    unsigned int i;
+
+    displayStateAs64bitWords(3, "Same, with lanes as 64-bit words", state);
+
+    for(i=0; i<nrRounds; i++) {
+        displayRoundNumber(3, i);
+
+        theta(state);
+        displayStateAs64bitWords(3, "After theta", state);
+
+        rho(state);
+        displayStateAs64bitWords(3, "After rho", state);
+
+        pi(state);
+        displayStateAs64bitWords(3, "After pi", state);
+
+        chi(state);
+        displayStateAs64bitWords(3, "After chi", state);
+
+        iota(state, i);
+        displayStateAs64bitWords(3, "After iota", state);
+    }
+}
+
+#define index(x, y) (((x)%5)+5*((y)%5))
+#define ROL64(a, offset) ((offset != 0) ? ((((UINT64)a) << offset) ^ (((UINT64)a) >> (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<nrRounds; i++) {
+        KeccakRoundConstants[i] = 0;
+        for(j=0; j<7; j++) {
+            bitPosition = (1<<j)-1; //2^j-1
+            if (LFSR86540(&LFSRstate))
+                KeccakRoundConstants[i] ^= (UINT64)1<<bitPosition;
+        }
+    }
+}
+
+void KeccakInitializeRhoOffsets()
+{
+    unsigned int x, y, t, newX, newY;
+
+    KeccakRhoOffsets[index(0, 0)] = 0;
+    x = 1;
+    y = 0;
+    for(t=0; t<24; t++) {
+        KeccakRhoOffsets[index(x, y)] = ((t+1)*(t+2)/2) % 64;
+        newX = (0*x+1*y) % 5;
+        newY = (2*x+3*y) % 5;
+        x = newX;
+        y = newY;
+    }
+}
+
+void KeccakInitialize()
+{
+    KeccakInitializeRoundConstants();
+    KeccakInitializeRhoOffsets();
+}
+
+void displayRoundConstants(FILE *f)
+{
+    unsigned int i;
+
+    for(i=0; i<nrRounds; i++) {
+        fprintf(f, "RC[%02i][0][0] = ", i);
+        fprintf(f, "%08X", (unsigned int)(KeccakRoundConstants[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 (executable)
index 0000000..5939ba4
--- /dev/null
@@ -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 <string.h>
+#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; j<wholeBlocks; j++, curData+=576/8) {
+                    #ifdef KeccakReference
+                    displayBytes(1, "Block to be absorbed", curData, state->rate/8);
+                    #endif
+                    KeccakAbsorb576bits(state->state, curData);
+                }
+            }
+            else
+#endif
+#ifdef ProvideFast832
+            if (state->rate == 832) {
+                for(j=0; j<wholeBlocks; j++, curData+=832/8) {
+                    #ifdef KeccakReference
+                    displayBytes(1, "Block to be absorbed", curData, state->rate/8);
+                    #endif
+                    KeccakAbsorb832bits(state->state, curData);
+                }
+            }
+            else
+#endif
+#ifdef ProvideFast1024
+            if (state->rate == 1024) {
+                for(j=0; j<wholeBlocks; j++, curData+=1024/8) {
+                    #ifdef KeccakReference
+                    displayBytes(1, "Block to be absorbed", curData, state->rate/8);
+                    #endif
+                    KeccakAbsorb1024bits(state->state, curData);
+                }
+            }
+            else
+#endif
+#ifdef ProvideFast1088
+            if (state->rate == 1088) {
+                for(j=0; j<wholeBlocks; j++, curData+=1088/8) {
+                    #ifdef KeccakReference
+                    displayBytes(1, "Block to be absorbed", curData, state->rate/8);
+                    #endif
+                    KeccakAbsorb1088bits(state->state, curData);
+                }
+            }
+            else
+#endif
+#ifdef ProvideFast1152
+            if (state->rate == 1152) {
+                for(j=0; j<wholeBlocks; j++, curData+=1152/8) {
+                    #ifdef KeccakReference
+                    displayBytes(1, "Block to be absorbed", curData, state->rate/8);
+                    #endif
+                    KeccakAbsorb1152bits(state->state, curData);
+                }
+            }
+            else
+#endif
+#ifdef ProvideFast1344
+            if (state->rate == 1344) {
+                for(j=0; j<wholeBlocks; j++, curData+=1344/8) {
+                    #ifdef KeccakReference
+                    displayBytes(1, "Block to be absorbed", curData, state->rate/8);
+                    #endif
+                    KeccakAbsorb1344bits(state->state, curData);
+                }
+            }
+            else
+#endif
+            {
+                for(j=0; j<wholeBlocks; j++, curData+=state->rate/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 (file)
index 0000000..2832275
--- /dev/null
@@ -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 (executable)
index 0000000..f3bf9e2
--- /dev/null
@@ -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 <stdio.h>
+#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<size; i++)
+            fprintf(intermediateValueFile, "%02X ", bytes[i]);
+        fprintf(intermediateValueFile, "\n");
+        fprintf(intermediateValueFile, "\n");
+    }
+}
+
+void displayBits(int level, const char *text, const unsigned char *data, unsigned int size, int MSBfirst)
+{
+    unsigned int i, iByte, iBit;
+
+    if ((intermediateValueFile) && (level <= displayLevel)) {
+        fprintf(intermediateValueFile, "%s:\n", text);
+        for(i=0; i<size; i++) {
+            iByte = i/8;
+            iBit = i%8;
+            if (MSBfirst)
+                fprintf(intermediateValueFile, "%d ", ((data[iByte] << iBit) & 0x80) != 0);
+            else
+                fprintf(intermediateValueFile, "%d ", ((data[iByte] >> 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<KeccakPermutationSize/64; i++) {
+            fprintf(intermediateValueFile, "%08X:%08X", (unsigned int)state[2*i+0], (unsigned int)state[2*i+1]);
+            if ((i%5) == 4)
+                fprintf(intermediateValueFile, "\n");
+            else
+                fprintf(intermediateValueFile, " ");
+        }
+    }
+}
+
+void displayStateAs64bitWords(int level, const char *text, const unsigned long long int *state)
+{
+    unsigned int i;
+
+    if ((intermediateValueFile) && (level <= displayLevel)) {
+        fprintf(intermediateValueFile, "%s:\n", text);
+        for(i=0; i<KeccakPermutationSize/64; i++) {
+            fprintf(intermediateValueFile, "%08X", (unsigned int)(state[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 (file)
index 0000000..01fe486
--- /dev/null
@@ -0,0 +1,87 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#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 <file>\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;
+}