/src/php-src/ext/hash/sha3/generic64lc/KeccakSponge.inc
Line | Count | Source |
1 | | /* |
2 | | Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni, |
3 | | Joan Daemen, Michaƫl Peeters, Gilles Van Assche and Ronny Van Keer, hereby |
4 | | denoted as "the implementer". |
5 | | |
6 | | For more information, feedback or questions, please refer to our websites: |
7 | | http://keccak.noekeon.org/ |
8 | | http://keyak.noekeon.org/ |
9 | | http://ketje.noekeon.org/ |
10 | | |
11 | | To the extent possible under law, the implementer has waived all copyright |
12 | | and related or neighboring rights to the source code in this file. |
13 | | http://creativecommons.org/publicdomain/zero/1.0/ |
14 | | */ |
15 | | |
16 | 0 | #define JOIN0(a, b) a ## b |
17 | 0 | #define JOIN(a, b) JOIN0(a, b) |
18 | | |
19 | | #define Sponge JOIN(prefix, _Sponge) |
20 | | #define SpongeInstance JOIN(prefix, _SpongeInstance) |
21 | | #define SpongeInitialize JOIN(prefix, _SpongeInitialize) |
22 | | #define SpongeAbsorb JOIN(prefix, _SpongeAbsorb) |
23 | 0 | #define SpongeAbsorbLastFewBits JOIN(prefix, _SpongeAbsorbLastFewBits) |
24 | | #define SpongeSqueeze JOIN(prefix, _SpongeSqueeze) |
25 | | |
26 | | #define SnP_stateSizeInBytes JOIN(SnP, _stateSizeInBytes) |
27 | | #define SnP_stateAlignment JOIN(SnP, _stateAlignment) |
28 | | #define SnP_StaticInitialize JOIN(SnP, _StaticInitialize) |
29 | 0 | #define SnP_Initialize JOIN(SnP, _Initialize) |
30 | 0 | #define SnP_AddByte JOIN(SnP, _AddByte) |
31 | 0 | #define SnP_AddBytes JOIN(SnP, _AddBytes) |
32 | 0 | #define SnP_ExtractBytes JOIN(SnP, _ExtractBytes) |
33 | | |
34 | | int Sponge(unsigned int rate, unsigned int capacity, const unsigned char *input, size_t inputByteLen, unsigned char suffix, unsigned char *output, size_t outputByteLen) |
35 | 0 | { |
36 | 0 | ALIGN(SnP_stateAlignment) unsigned char state[SnP_stateSizeInBytes]; |
37 | 0 | unsigned int partialBlock; |
38 | 0 | const unsigned char *curInput = input; |
39 | 0 | unsigned char *curOutput = output; |
40 | 0 | unsigned int rateInBytes = rate/8; |
41 | |
|
42 | 0 | if (rate+capacity != SnP_width) |
43 | 0 | return 1; |
44 | 0 | if ((rate <= 0) || (rate > SnP_width) || ((rate % 8) != 0)) |
45 | 0 | return 1; |
46 | 0 | if (suffix == 0) |
47 | 0 | return 1; |
48 | | |
49 | | /* Initialize the state */ |
50 | 0 | SnP_StaticInitialize(); |
51 | 0 | SnP_Initialize(state); |
52 | | |
53 | | /* First, absorb whole blocks */ |
54 | | #ifdef SnP_FastLoop_Absorb |
55 | 0 | if (((rateInBytes % (SnP_width/200)) == 0) && (inputByteLen >= rateInBytes)) { |
56 | | /* fast lane: whole lane rate */ |
57 | 0 | size_t j; |
58 | 0 | j = SnP_FastLoop_Absorb(state, rateInBytes/(SnP_width/200), curInput, inputByteLen); |
59 | 0 | curInput += j; |
60 | 0 | inputByteLen -= j; |
61 | 0 | } |
62 | | #endif |
63 | 0 | while(inputByteLen >= (size_t)rateInBytes) { |
64 | | #ifdef KeccakReference |
65 | | displayBytes(1, "Block to be absorbed", curInput, rateInBytes); |
66 | | #endif |
67 | 0 | SnP_AddBytes(state, curInput, 0, rateInBytes); |
68 | 0 | SnP_Permute(state); |
69 | 0 | curInput += rateInBytes; |
70 | 0 | inputByteLen -= rateInBytes; |
71 | 0 | } |
72 | | |
73 | | /* Then, absorb what remains */ |
74 | 0 | partialBlock = (unsigned int)inputByteLen; |
75 | | #ifdef KeccakReference |
76 | | displayBytes(1, "Block to be absorbed (part)", curInput, partialBlock); |
77 | | #endif |
78 | 0 | SnP_AddBytes(state, curInput, 0, partialBlock); |
79 | | |
80 | | /* Finally, absorb the suffix */ |
81 | | #ifdef KeccakReference |
82 | | { |
83 | | unsigned char delimitedData1[1]; |
84 | | delimitedData1[0] = suffix; |
85 | | displayBytes(1, "Block to be absorbed (last few bits + first bit of padding)", delimitedData1, 1); |
86 | | } |
87 | | #endif |
88 | | /* Last few bits, whose delimiter coincides with first bit of padding */ |
89 | 0 | SnP_AddByte(state, suffix, partialBlock); |
90 | | /* If the first bit of padding is at position rate-1, we need a whole new block for the second bit of padding */ |
91 | 0 | if ((suffix >= 0x80) && (partialBlock == (rateInBytes-1))) |
92 | 0 | SnP_Permute(state); |
93 | | /* Second bit of padding */ |
94 | 0 | SnP_AddByte(state, 0x80, rateInBytes-1); |
95 | | #ifdef KeccakReference |
96 | | { |
97 | | unsigned char block[SnP_width/8]; |
98 | | memset(block, 0, SnP_width/8); |
99 | | block[rateInBytes-1] = 0x80; |
100 | | displayBytes(1, "Second bit of padding", block, rateInBytes); |
101 | | } |
102 | | #endif |
103 | 0 | SnP_Permute(state); |
104 | | #ifdef KeccakReference |
105 | | displayText(1, "--- Switching to squeezing phase ---"); |
106 | | #endif |
107 | | |
108 | | /* First, output whole blocks */ |
109 | 0 | while(outputByteLen > (size_t)rateInBytes) { |
110 | 0 | SnP_ExtractBytes(state, curOutput, 0, rateInBytes); |
111 | 0 | SnP_Permute(state); |
112 | | #ifdef KeccakReference |
113 | | displayBytes(1, "Squeezed block", curOutput, rateInBytes); |
114 | | #endif |
115 | 0 | curOutput += rateInBytes; |
116 | 0 | outputByteLen -= rateInBytes; |
117 | 0 | } |
118 | | |
119 | | /* Finally, output what remains */ |
120 | 0 | partialBlock = (unsigned int)outputByteLen; |
121 | 0 | SnP_ExtractBytes(state, curOutput, 0, partialBlock); |
122 | | #ifdef KeccakReference |
123 | | displayBytes(1, "Squeezed block (part)", curOutput, partialBlock); |
124 | | #endif |
125 | |
|
126 | 0 | return 0; |
127 | 0 | } Unexecuted instantiation: KeccakWidth1600_Sponge Unexecuted instantiation: KeccakWidth1600_12rounds_Sponge |
128 | | |
129 | | /* ---------------------------------------------------------------- */ |
130 | | /* ---------------------------------------------------------------- */ |
131 | | /* ---------------------------------------------------------------- */ |
132 | | |
133 | | int SpongeInitialize(SpongeInstance *instance, unsigned int rate, unsigned int capacity) |
134 | 0 | { |
135 | 0 | if (rate+capacity != SnP_width) |
136 | 0 | return 1; |
137 | 0 | if ((rate <= 0) || (rate > SnP_width) || ((rate % 8) != 0)) |
138 | 0 | return 1; |
139 | 0 | SnP_StaticInitialize(); |
140 | 0 | SnP_Initialize(instance->state); |
141 | 0 | instance->rate = rate; |
142 | 0 | instance->byteIOIndex = 0; |
143 | 0 | instance->squeezing = 0; |
144 | |
|
145 | 0 | return 0; |
146 | 0 | } Unexecuted instantiation: KeccakWidth1600_SpongeInitialize Unexecuted instantiation: KeccakWidth1600_12rounds_SpongeInitialize |
147 | | |
148 | | /* ---------------------------------------------------------------- */ |
149 | | |
150 | | int SpongeAbsorb(SpongeInstance *instance, const unsigned char *data, size_t dataByteLen) |
151 | 0 | { |
152 | 0 | size_t i, j; |
153 | 0 | unsigned int partialBlock; |
154 | 0 | const unsigned char *curData; |
155 | 0 | unsigned int rateInBytes = instance->rate/8; |
156 | |
|
157 | 0 | if (instance->squeezing) |
158 | 0 | return 1; /* Too late for additional input */ |
159 | | |
160 | 0 | i = 0; |
161 | 0 | curData = data; |
162 | 0 | while(i < dataByteLen) { |
163 | 0 | if ((instance->byteIOIndex == 0) && (dataByteLen-i >= rateInBytes)) { |
164 | | #ifdef SnP_FastLoop_Absorb |
165 | | /* processing full blocks first */ |
166 | 0 | if ((rateInBytes % (SnP_width/200)) == 0) { |
167 | | /* fast lane: whole lane rate */ |
168 | 0 | j = SnP_FastLoop_Absorb(instance->state, rateInBytes/(SnP_width/200), curData, dataByteLen - i); |
169 | 0 | i += j; |
170 | 0 | curData += j; |
171 | 0 | } |
172 | 0 | else { |
173 | 0 | #endif |
174 | 0 | for(j=dataByteLen-i; j>=rateInBytes; j-=rateInBytes) { |
175 | | #ifdef KeccakReference |
176 | | displayBytes(1, "Block to be absorbed", curData, rateInBytes); |
177 | | #endif |
178 | 0 | SnP_AddBytes(instance->state, curData, 0, rateInBytes); |
179 | 0 | SnP_Permute(instance->state); |
180 | 0 | curData+=rateInBytes; |
181 | 0 | } |
182 | 0 | i = dataByteLen - j; |
183 | | #ifdef SnP_FastLoop_Absorb |
184 | | } |
185 | | #endif |
186 | 0 | } |
187 | 0 | else { |
188 | | /* normal lane: using the message queue */ |
189 | 0 | if (dataByteLen-i > rateInBytes-instance->byteIOIndex) |
190 | 0 | partialBlock = rateInBytes-instance->byteIOIndex; |
191 | 0 | else |
192 | 0 | partialBlock = (unsigned int)(dataByteLen - i); |
193 | | #ifdef KeccakReference |
194 | | displayBytes(1, "Block to be absorbed (part)", curData, partialBlock); |
195 | | #endif |
196 | 0 | i += partialBlock; |
197 | |
|
198 | 0 | SnP_AddBytes(instance->state, curData, instance->byteIOIndex, partialBlock); |
199 | 0 | curData += partialBlock; |
200 | 0 | instance->byteIOIndex += partialBlock; |
201 | 0 | if (instance->byteIOIndex == rateInBytes) { |
202 | 0 | SnP_Permute(instance->state); |
203 | 0 | instance->byteIOIndex = 0; |
204 | 0 | } |
205 | 0 | } |
206 | 0 | } |
207 | 0 | return 0; |
208 | 0 | } Unexecuted instantiation: KeccakWidth1600_SpongeAbsorb Unexecuted instantiation: KeccakWidth1600_12rounds_SpongeAbsorb |
209 | | |
210 | | /* ---------------------------------------------------------------- */ |
211 | | |
212 | | int SpongeAbsorbLastFewBits(SpongeInstance *instance, unsigned char delimitedData) |
213 | 0 | { |
214 | 0 | unsigned int rateInBytes = instance->rate/8; |
215 | |
|
216 | 0 | if (delimitedData == 0) |
217 | 0 | return 1; |
218 | 0 | if (instance->squeezing) |
219 | 0 | return 1; /* Too late for additional input */ |
220 | | |
221 | | #ifdef KeccakReference |
222 | | { |
223 | | unsigned char delimitedData1[1]; |
224 | | delimitedData1[0] = delimitedData; |
225 | | displayBytes(1, "Block to be absorbed (last few bits + first bit of padding)", delimitedData1, 1); |
226 | | } |
227 | | #endif |
228 | | /* Last few bits, whose delimiter coincides with first bit of padding */ |
229 | 0 | SnP_AddByte(instance->state, delimitedData, instance->byteIOIndex); |
230 | | /* If the first bit of padding is at position rate-1, we need a whole new block for the second bit of padding */ |
231 | 0 | if ((delimitedData >= 0x80) && (instance->byteIOIndex == (rateInBytes-1))) |
232 | 0 | SnP_Permute(instance->state); |
233 | | /* Second bit of padding */ |
234 | 0 | SnP_AddByte(instance->state, 0x80, rateInBytes-1); |
235 | | #ifdef KeccakReference |
236 | | { |
237 | | unsigned char block[SnP_width/8]; |
238 | | memset(block, 0, SnP_width/8); |
239 | | block[rateInBytes-1] = 0x80; |
240 | | displayBytes(1, "Second bit of padding", block, rateInBytes); |
241 | | } |
242 | | #endif |
243 | 0 | SnP_Permute(instance->state); |
244 | 0 | instance->byteIOIndex = 0; |
245 | 0 | instance->squeezing = 1; |
246 | | #ifdef KeccakReference |
247 | | displayText(1, "--- Switching to squeezing phase ---"); |
248 | | #endif |
249 | 0 | return 0; |
250 | 0 | } Unexecuted instantiation: KeccakWidth1600_SpongeAbsorbLastFewBits Unexecuted instantiation: KeccakWidth1600_12rounds_SpongeAbsorbLastFewBits |
251 | | |
252 | | /* ---------------------------------------------------------------- */ |
253 | | |
254 | | int SpongeSqueeze(SpongeInstance *instance, unsigned char *data, size_t dataByteLen) |
255 | 0 | { |
256 | 0 | size_t i, j; |
257 | 0 | unsigned int partialBlock; |
258 | 0 | unsigned int rateInBytes = instance->rate/8; |
259 | 0 | unsigned char *curData; |
260 | |
|
261 | 0 | if (!instance->squeezing) |
262 | 0 | SpongeAbsorbLastFewBits(instance, 0x01); |
263 | |
|
264 | 0 | i = 0; |
265 | 0 | curData = data; |
266 | 0 | while(i < dataByteLen) { |
267 | 0 | if ((instance->byteIOIndex == rateInBytes) && (dataByteLen-i >= rateInBytes)) { |
268 | 0 | for(j=dataByteLen-i; j>=rateInBytes; j-=rateInBytes) { |
269 | 0 | SnP_Permute(instance->state); |
270 | 0 | SnP_ExtractBytes(instance->state, curData, 0, rateInBytes); |
271 | | #ifdef KeccakReference |
272 | | displayBytes(1, "Squeezed block", curData, rateInBytes); |
273 | | #endif |
274 | 0 | curData+=rateInBytes; |
275 | 0 | } |
276 | 0 | i = dataByteLen - j; |
277 | 0 | } |
278 | 0 | else { |
279 | | /* normal lane: using the message queue */ |
280 | 0 | if (instance->byteIOIndex == rateInBytes) { |
281 | 0 | SnP_Permute(instance->state); |
282 | 0 | instance->byteIOIndex = 0; |
283 | 0 | } |
284 | 0 | if (dataByteLen-i > rateInBytes-instance->byteIOIndex) |
285 | 0 | partialBlock = rateInBytes-instance->byteIOIndex; |
286 | 0 | else |
287 | 0 | partialBlock = (unsigned int)(dataByteLen - i); |
288 | 0 | i += partialBlock; |
289 | |
|
290 | 0 | SnP_ExtractBytes(instance->state, curData, instance->byteIOIndex, partialBlock); |
291 | | #ifdef KeccakReference |
292 | | displayBytes(1, "Squeezed block (part)", curData, partialBlock); |
293 | | #endif |
294 | 0 | curData += partialBlock; |
295 | 0 | instance->byteIOIndex += partialBlock; |
296 | 0 | } |
297 | 0 | } |
298 | 0 | return 0; |
299 | 0 | } Unexecuted instantiation: KeccakWidth1600_SpongeSqueeze Unexecuted instantiation: KeccakWidth1600_12rounds_SpongeSqueeze |
300 | | |
301 | | /* ---------------------------------------------------------------- */ |
302 | | |
303 | | #undef Sponge |
304 | | #undef SpongeInstance |
305 | | #undef SpongeInitialize |
306 | | #undef SpongeAbsorb |
307 | | #undef SpongeAbsorbLastFewBits |
308 | | #undef SpongeSqueeze |
309 | | #undef SnP_stateSizeInBytes |
310 | | #undef SnP_stateAlignment |
311 | | #undef SnP_StaticInitialize |
312 | | #undef SnP_Initialize |
313 | | #undef SnP_AddByte |
314 | | #undef SnP_AddBytes |
315 | | #undef SnP_ExtractBytes |