| 1 | /* | 
| 2 | The Keccak sponge function, designed by Guido Bertoni, Joan Daemen, | 
| 3 | Michaƫl Peeters and Gilles Van Assche. For more information, feedback or | 
| 4 | questions, please refer to our website: http://keccak.noekeon.org/ | 
| 5 |  | 
| 6 | Implementation by the designers, | 
| 7 | hereby denoted as "the implementer". | 
| 8 |  | 
| 9 | To the extent possible under law, the implementer has waived all copyright | 
| 10 | and related or neighboring rights to the source code in this file. | 
| 11 | http://creativecommons.org/publicdomain/zero/1.0/ | 
| 12 | */ | 
| 13 |  | 
| 14 | #include <string.h> | 
| 15 | #include "KeccakSponge.h" | 
| 16 | #include "KeccakF-1600-interface.h" | 
| 17 | #ifdef KeccakReference | 
| 18 | #include "displayIntermediateValues.h" | 
| 19 | #endif | 
| 20 |  | 
| 21 | static int InitSponge(spongeState *state, unsigned int rate, unsigned int capacity) | 
| 22 | { | 
| 23 |     if (rate+capacity != 1600) | 
| 24 |         return 1; | 
| 25 |     if ((rate <= 0) || (rate >= 1600) || ((rate % 64) != 0)) | 
| 26 |         return 1; | 
| 27 |     KeccakInitialize(); | 
| 28 |     state->rate = rate; | 
| 29 |     state->capacity = capacity; | 
| 30 |     state->fixedOutputLength = 0; | 
| 31 |     KeccakInitializeState(state: state->state); | 
| 32 |     memset(s: state->dataQueue, c: 0, KeccakMaximumRateInBytes); | 
| 33 |     state->bitsInQueue = 0; | 
| 34 |     state->squeezing = 0; | 
| 35 |     state->bitsAvailableForSqueezing = 0; | 
| 36 |  | 
| 37 |     return 0; | 
| 38 | } | 
| 39 |  | 
| 40 | static void AbsorbQueue(spongeState *state) | 
| 41 | { | 
| 42 |     // state->bitsInQueue is assumed to be equal to state->rate | 
| 43 |     #ifdef KeccakReference | 
| 44 |     displayBytes(1, "Block to be absorbed" , state->dataQueue, state->rate/8); | 
| 45 |     #endif | 
| 46 | #ifdef ProvideFast576 | 
| 47 |     if (state->rate == 576) | 
| 48 |         KeccakAbsorb576bits(state: state->state, data: state->dataQueue); | 
| 49 |     else  | 
| 50 | #endif | 
| 51 | #ifdef ProvideFast832 | 
| 52 |     if (state->rate == 832) | 
| 53 |         KeccakAbsorb832bits(state: state->state, data: state->dataQueue); | 
| 54 |     else  | 
| 55 | #endif | 
| 56 | #ifdef ProvideFast1024 | 
| 57 |     if (state->rate == 1024) | 
| 58 |         KeccakAbsorb1024bits(state: state->state, data: state->dataQueue); | 
| 59 |     else  | 
| 60 | #endif | 
| 61 | #ifdef ProvideFast1088 | 
| 62 |     if (state->rate == 1088) | 
| 63 |         KeccakAbsorb1088bits(state: state->state, data: state->dataQueue); | 
| 64 |     else | 
| 65 | #endif | 
| 66 | #ifdef ProvideFast1152 | 
| 67 |     if (state->rate == 1152) | 
| 68 |         KeccakAbsorb1152bits(state: state->state, data: state->dataQueue); | 
| 69 |     else  | 
| 70 | #endif | 
| 71 | #ifdef ProvideFast1344 | 
| 72 |     if (state->rate == 1344) | 
| 73 |         KeccakAbsorb1344bits(state: state->state, data: state->dataQueue); | 
| 74 |     else  | 
| 75 | #endif | 
| 76 |         KeccakAbsorb(state: state->state, data: state->dataQueue, laneCount: state->rate/64); | 
| 77 |     state->bitsInQueue = 0; | 
| 78 | } | 
| 79 |  | 
| 80 | static int Absorb(spongeState *state, const unsigned char *data, unsigned long long databitlen) | 
| 81 | { | 
| 82 |     unsigned long long i, j, wholeBlocks; | 
| 83 |     unsigned int partialBlock, partialByte; | 
| 84 |     const unsigned char *curData; | 
| 85 |  | 
| 86 |     if ((state->bitsInQueue % 8) != 0) | 
| 87 |         return 1; // Only the last call may contain a partial byte | 
| 88 |     if (state->squeezing) | 
| 89 |         return 1; // Too late for additional input | 
| 90 |  | 
| 91 |     i = 0; | 
| 92 |     while(i < databitlen) { | 
| 93 |         if ((state->bitsInQueue == 0) && (databitlen >= state->rate) && (i <= (databitlen-state->rate))) { | 
| 94 |             wholeBlocks = (databitlen-i)/state->rate; | 
| 95 |             curData = data+i/8; | 
| 96 | #ifdef ProvideFast576 | 
| 97 |             if (state->rate == 576) { | 
| 98 |                 for(j=0; j<wholeBlocks; j++, curData+=576/8) { | 
| 99 |                     #ifdef KeccakReference | 
| 100 |                     displayBytes(1, "Block to be absorbed" , curData, state->rate/8); | 
| 101 |                     #endif | 
| 102 |                     KeccakAbsorb576bits(state: state->state, data: curData); | 
| 103 |                 } | 
| 104 |             } | 
| 105 |             else | 
| 106 | #endif | 
| 107 | #ifdef ProvideFast832 | 
| 108 |             if (state->rate == 832) { | 
| 109 |                 for(j=0; j<wholeBlocks; j++, curData+=832/8) { | 
| 110 |                     #ifdef KeccakReference | 
| 111 |                     displayBytes(1, "Block to be absorbed" , curData, state->rate/8); | 
| 112 |                     #endif | 
| 113 |                     KeccakAbsorb832bits(state: state->state, data: curData); | 
| 114 |                 } | 
| 115 |             } | 
| 116 |             else | 
| 117 | #endif | 
| 118 | #ifdef ProvideFast1024 | 
| 119 |             if (state->rate == 1024) { | 
| 120 |                 for(j=0; j<wholeBlocks; j++, curData+=1024/8) { | 
| 121 |                     #ifdef KeccakReference | 
| 122 |                     displayBytes(1, "Block to be absorbed" , curData, state->rate/8); | 
| 123 |                     #endif | 
| 124 |                     KeccakAbsorb1024bits(state: state->state, data: curData); | 
| 125 |                 } | 
| 126 |             } | 
| 127 |             else | 
| 128 | #endif | 
| 129 | #ifdef ProvideFast1088 | 
| 130 |             if (state->rate == 1088) { | 
| 131 |                 for(j=0; j<wholeBlocks; j++, curData+=1088/8) { | 
| 132 |                     #ifdef KeccakReference | 
| 133 |                     displayBytes(1, "Block to be absorbed" , curData, state->rate/8); | 
| 134 |                     #endif | 
| 135 |                     KeccakAbsorb1088bits(state: state->state, data: curData); | 
| 136 |                 } | 
| 137 |             } | 
| 138 |             else | 
| 139 | #endif | 
| 140 | #ifdef ProvideFast1152 | 
| 141 |             if (state->rate == 1152) { | 
| 142 |                 for(j=0; j<wholeBlocks; j++, curData+=1152/8) { | 
| 143 |                     #ifdef KeccakReference | 
| 144 |                     displayBytes(1, "Block to be absorbed" , curData, state->rate/8); | 
| 145 |                     #endif | 
| 146 |                     KeccakAbsorb1152bits(state: state->state, data: curData); | 
| 147 |                 } | 
| 148 |             } | 
| 149 |             else | 
| 150 | #endif | 
| 151 | #ifdef ProvideFast1344 | 
| 152 |             if (state->rate == 1344) { | 
| 153 |                 for(j=0; j<wholeBlocks; j++, curData+=1344/8) { | 
| 154 |                     #ifdef KeccakReference | 
| 155 |                     displayBytes(1, "Block to be absorbed" , curData, state->rate/8); | 
| 156 |                     #endif | 
| 157 |                     KeccakAbsorb1344bits(state: state->state, data: curData); | 
| 158 |                 } | 
| 159 |             } | 
| 160 |             else | 
| 161 | #endif | 
| 162 |             { | 
| 163 |                 for(j=0; j<wholeBlocks; j++, curData+=state->rate/8) { | 
| 164 |                     #ifdef KeccakReference | 
| 165 |                     displayBytes(1, "Block to be absorbed" , curData, state->rate/8); | 
| 166 |                     #endif | 
| 167 |                     KeccakAbsorb(state: state->state, data: curData, laneCount: state->rate/64); | 
| 168 |                 } | 
| 169 |             } | 
| 170 |             i += wholeBlocks*state->rate; | 
| 171 |         } | 
| 172 |         else { | 
| 173 |             if (databitlen-i > state->rate - state->bitsInQueue) | 
| 174 |                 partialBlock = state->rate-state->bitsInQueue; | 
| 175 |             else | 
| 176 |                 partialBlock = (unsigned int)(databitlen - i); | 
| 177 |             partialByte = partialBlock % 8; | 
| 178 |             partialBlock -= partialByte; | 
| 179 |             memcpy(dest: state->dataQueue+state->bitsInQueue/8, src: data+i/8, n: partialBlock/8); | 
| 180 |             state->bitsInQueue += partialBlock; | 
| 181 |             i += partialBlock; | 
| 182 |             if (state->bitsInQueue == state->rate) | 
| 183 |                 AbsorbQueue(state); | 
| 184 |             if (partialByte > 0) { | 
| 185 |                 unsigned char mask = (1 << partialByte)-1; | 
| 186 |                 state->dataQueue[state->bitsInQueue/8] = data[i/8] & mask; | 
| 187 |                 state->bitsInQueue += partialByte; | 
| 188 |                 i += partialByte; | 
| 189 |             } | 
| 190 |         } | 
| 191 |     } | 
| 192 |     return 0; | 
| 193 | } | 
| 194 |  | 
| 195 | static void PadAndSwitchToSqueezingPhase(spongeState *state) | 
| 196 | { | 
| 197 |     // Note: the bits are numbered from 0=LSB to 7=MSB | 
| 198 |     if (state->bitsInQueue + 1 == state->rate) { | 
| 199 |         state->dataQueue[state->bitsInQueue/8 ] |= 1 << (state->bitsInQueue % 8); | 
| 200 |         AbsorbQueue(state); | 
| 201 |         memset(s: state->dataQueue, c: 0, n: state->rate/8); | 
| 202 |     } | 
| 203 |     else { | 
| 204 |         memset(s: state->dataQueue + (state->bitsInQueue+7)/8, c: 0, n: state->rate/8 - (state->bitsInQueue+7)/8); | 
| 205 |         state->dataQueue[state->bitsInQueue/8 ] |= 1 << (state->bitsInQueue % 8); | 
| 206 |     } | 
| 207 |     state->dataQueue[(state->rate-1)/8] |= 1 << ((state->rate-1) % 8); | 
| 208 |     AbsorbQueue(state); | 
| 209 |  | 
| 210 |     #ifdef KeccakReference | 
| 211 |     displayText(1, "--- Switching to squeezing phase ---" ); | 
| 212 |     #endif | 
| 213 | #ifdef ProvideFast1024 | 
| 214 |     if (state->rate == 1024) { | 
| 215 |         KeccakExtract1024bits(state: state->state, data: state->dataQueue); | 
| 216 |         state->bitsAvailableForSqueezing = 1024; | 
| 217 |     } | 
| 218 |     else | 
| 219 | #endif | 
| 220 |     { | 
| 221 |         KeccakExtract(state: state->state, data: state->dataQueue, laneCount: state->rate/64); | 
| 222 |         state->bitsAvailableForSqueezing = state->rate; | 
| 223 |     } | 
| 224 |     #ifdef KeccakReference | 
| 225 |     displayBytes(1, "Block available for squeezing" , state->dataQueue, state->bitsAvailableForSqueezing/8); | 
| 226 |     #endif | 
| 227 |     state->squeezing = 1; | 
| 228 | } | 
| 229 |  | 
| 230 | static int Squeeze(spongeState *state, unsigned char *output, unsigned long long outputLength) | 
| 231 | { | 
| 232 |     unsigned long long i; | 
| 233 |     unsigned int partialBlock; | 
| 234 |  | 
| 235 |     if (!state->squeezing) | 
| 236 |         PadAndSwitchToSqueezingPhase(state); | 
| 237 |     if ((outputLength % 8) != 0) | 
| 238 |         return 1; // Only multiple of 8 bits are allowed, truncation can be done at user level | 
| 239 |  | 
| 240 |     i = 0; | 
| 241 |     while(i < outputLength) { | 
| 242 |         if (state->bitsAvailableForSqueezing == 0) { | 
| 243 |             KeccakPermutation(state: state->state); | 
| 244 | #ifdef ProvideFast1024 | 
| 245 |             if (state->rate == 1024) { | 
| 246 |                 KeccakExtract1024bits(state: state->state, data: state->dataQueue); | 
| 247 |                 state->bitsAvailableForSqueezing = 1024; | 
| 248 |             } | 
| 249 |             else | 
| 250 | #endif | 
| 251 |             { | 
| 252 |                 KeccakExtract(state: state->state, data: state->dataQueue, laneCount: state->rate/64); | 
| 253 |                 state->bitsAvailableForSqueezing = state->rate; | 
| 254 |             } | 
| 255 |             #ifdef KeccakReference | 
| 256 |             displayBytes(1, "Block available for squeezing" , state->dataQueue, state->bitsAvailableForSqueezing/8); | 
| 257 |             #endif | 
| 258 |         } | 
| 259 |         partialBlock = state->bitsAvailableForSqueezing; | 
| 260 |         if ((unsigned long long)partialBlock > outputLength - i) | 
| 261 |             partialBlock = (unsigned int)(outputLength - i); | 
| 262 |         memcpy(dest: output+i/8, src: state->dataQueue+(state->rate-state->bitsAvailableForSqueezing)/8, n: partialBlock/8); | 
| 263 |         state->bitsAvailableForSqueezing -= partialBlock; | 
| 264 |         i += partialBlock; | 
| 265 |     } | 
| 266 |     return 0; | 
| 267 | } | 
| 268 |  |