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/
6 Implementation by the designers,
7 hereby denoted as "the implementer".
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/
15 #include "KeccakSponge.h"
16 #include "KeccakF-1600-interface.h"
17 #ifdef KeccakReference
18 #include "displayIntermediateValues.h"
21 int InitSponge(spongeState
*state
, unsigned int rate
, unsigned int capacity
)
23 if (rate
+capacity
!= 1600)
25 if ((rate
<= 0) || (rate
>= 1600) || ((rate
% 64) != 0))
29 state
->capacity
= capacity
;
30 state
->fixedOutputLength
= 0;
31 KeccakInitializeState(state
->state
);
32 memset(state
->dataQueue
, 0, KeccakMaximumRateInBytes
);
33 state
->bitsInQueue
= 0;
35 state
->bitsAvailableForSqueezing
= 0;
40 void AbsorbQueue(spongeState
*state
)
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);
47 if (state
->rate
== 576)
48 KeccakAbsorb576bits(state
->state
, state
->dataQueue
);
52 if (state
->rate
== 832)
53 KeccakAbsorb832bits(state
->state
, state
->dataQueue
);
56 #ifdef ProvideFast1024
57 if (state
->rate
== 1024)
58 KeccakAbsorb1024bits(state
->state
, state
->dataQueue
);
61 #ifdef ProvideFast1088
62 if (state
->rate
== 1088)
63 KeccakAbsorb1088bits(state
->state
, state
->dataQueue
);
66 #ifdef ProvideFast1152
67 if (state
->rate
== 1152)
68 KeccakAbsorb1152bits(state
->state
, state
->dataQueue
);
71 #ifdef ProvideFast1344
72 if (state
->rate
== 1344)
73 KeccakAbsorb1344bits(state
->state
, state
->dataQueue
);
76 KeccakAbsorb(state
->state
, state
->dataQueue
, state
->rate
/64);
77 state
->bitsInQueue
= 0;
80 int Absorb(spongeState
*state
, const unsigned char *data
, unsigned long long databitlen
)
82 unsigned long long i
, j
, wholeBlocks
;
83 unsigned int partialBlock
, partialByte
;
84 const unsigned char *curData
;
86 if ((state
->bitsInQueue
% 8) != 0)
87 return 1; // Only the last call may contain a partial byte
89 return 1; // Too late for additional input
92 while(i
< databitlen
) {
93 if ((state
->bitsInQueue
== 0) && (databitlen
>= state
->rate
) && (i
<= (databitlen
-state
->rate
))) {
94 wholeBlocks
= (databitlen
-i
)/state
->rate
;
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);
102 KeccakAbsorb576bits(state
->state
, curData
);
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);
113 KeccakAbsorb832bits(state
->state
, curData
);
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);
124 KeccakAbsorb1024bits(state
->state
, curData
);
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);
135 KeccakAbsorb1088bits(state
->state
, curData
);
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);
146 KeccakAbsorb1152bits(state
->state
, curData
);
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);
157 KeccakAbsorb1344bits(state
->state
, curData
);
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);
167 KeccakAbsorb(state
->state
, curData
, state
->rate
/64);
170 i
+= wholeBlocks
*state
->rate
;
173 partialBlock
= (unsigned int)(databitlen
- i
);
174 if (partialBlock
+state
->bitsInQueue
> state
->rate
)
175 partialBlock
= state
->rate
-state
->bitsInQueue
;
176 partialByte
= partialBlock
% 8;
177 partialBlock
-= partialByte
;
178 memcpy(state
->dataQueue
+state
->bitsInQueue
/8, data
+i
/8, partialBlock
/8);
179 state
->bitsInQueue
+= partialBlock
;
181 if (state
->bitsInQueue
== state
->rate
)
183 if (partialByte
> 0) {
184 unsigned char mask
= (1 << partialByte
)-1;
185 state
->dataQueue
[state
->bitsInQueue
/8] = data
[i
/8] & mask
;
186 state
->bitsInQueue
+= partialByte
;
194 void PadAndSwitchToSqueezingPhase(spongeState
*state
)
196 // Note: the bits are numbered from 0=LSB to 7=MSB
197 if (state
->bitsInQueue
+ 1 == state
->rate
) {
198 state
->dataQueue
[state
->bitsInQueue
/8 ] |= 1 << (state
->bitsInQueue
% 8);
200 memset(state
->dataQueue
, 0, state
->rate
/8);
203 memset(state
->dataQueue
+ (state
->bitsInQueue
+7)/8, 0, state
->rate
/8 - (state
->bitsInQueue
+7)/8);
204 state
->dataQueue
[state
->bitsInQueue
/8 ] |= 1 << (state
->bitsInQueue
% 8);
206 state
->dataQueue
[(state
->rate
-1)/8] |= 1 << ((state
->rate
-1) % 8);
209 #ifdef KeccakReference
210 displayText(1, "--- Switching to squeezing phase ---");
212 #ifdef ProvideFast1024
213 if (state
->rate
== 1024) {
214 KeccakExtract1024bits(state
->state
, state
->dataQueue
);
215 state
->bitsAvailableForSqueezing
= 1024;
220 KeccakExtract(state
->state
, state
->dataQueue
, state
->rate
/64);
221 state
->bitsAvailableForSqueezing
= state
->rate
;
223 #ifdef KeccakReference
224 displayBytes(1, "Block available for squeezing", state
->dataQueue
, state
->bitsAvailableForSqueezing
/8);
226 state
->squeezing
= 1;
229 int Squeeze(spongeState
*state
, unsigned char *output
, unsigned long long outputLength
)
231 unsigned long long i
;
232 unsigned int partialBlock
;
234 if (!state
->squeezing
)
235 PadAndSwitchToSqueezingPhase(state
);
236 if ((outputLength
% 8) != 0)
237 return 1; // Only multiple of 8 bits are allowed, truncation can be done at user level
240 while(i
< outputLength
) {
241 if (state
->bitsAvailableForSqueezing
== 0) {
242 KeccakPermutation(state
->state
);
243 #ifdef ProvideFast1024
244 if (state
->rate
== 1024) {
245 KeccakExtract1024bits(state
->state
, state
->dataQueue
);
246 state
->bitsAvailableForSqueezing
= 1024;
251 KeccakExtract(state
->state
, state
->dataQueue
, state
->rate
/64);
252 state
->bitsAvailableForSqueezing
= state
->rate
;
254 #ifdef KeccakReference
255 displayBytes(1, "Block available for squeezing", state
->dataQueue
, state
->bitsAvailableForSqueezing
/8);
258 partialBlock
= state
->bitsAvailableForSqueezing
;
259 if ((unsigned long long)partialBlock
> outputLength
- i
)
260 partialBlock
= (unsigned int)(outputLength
- i
);
261 memcpy(output
+i
/8, state
->dataQueue
+(state
->rate
-state
->bitsAvailableForSqueezing
)/8, partialBlock
/8);
262 state
->bitsAvailableForSqueezing
-= partialBlock
;