/src/php-src/ext/hash/sha3/generic64lc/KeccakSponge.inc
Line | Count | Source (jump to first uncovered line) |
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 | 537 | #define JOIN0(a, b) a ## b |
17 | 537 | #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 | 147 | #define SnP_Initialize JOIN(SnP, _Initialize) |
30 | 186 | #define SnP_AddByte JOIN(SnP, _AddByte) |
31 | 111 | #define SnP_AddBytes JOIN(SnP, _AddBytes) |
32 | 93 | #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 | 147 | { |
135 | 147 | if (rate+capacity != SnP_width) |
136 | 0 | return 1; |
137 | 147 | if ((rate <= 0) || (rate > SnP_width) || ((rate % 8) != 0)) |
138 | 0 | return 1; |
139 | 147 | SnP_StaticInitialize(); |
140 | 147 | SnP_Initialize(instance->state); |
141 | 147 | instance->rate = rate; |
142 | 147 | instance->byteIOIndex = 0; |
143 | 147 | instance->squeezing = 0; |
144 | | |
145 | 147 | return 0; |
146 | 147 | } KeccakWidth1600_SpongeInitialize Line | Count | Source | 134 | 147 | { | 135 | 147 | if (rate+capacity != SnP_width) | 136 | 0 | return 1; | 137 | 147 | if ((rate <= 0) || (rate > SnP_width) || ((rate % 8) != 0)) | 138 | 0 | return 1; | 139 | 147 | SnP_StaticInitialize(); | 140 | 147 | SnP_Initialize(instance->state); | 141 | 147 | instance->rate = rate; | 142 | 147 | instance->byteIOIndex = 0; | 143 | 147 | instance->squeezing = 0; | 144 | | | 145 | 147 | return 0; | 146 | 147 | } |
Unexecuted instantiation: KeccakWidth1600_12rounds_SpongeInitialize |
147 | | |
148 | | /* ---------------------------------------------------------------- */ |
149 | | |
150 | | int SpongeAbsorb(SpongeInstance *instance, const unsigned char *data, size_t dataByteLen) |
151 | 93 | { |
152 | 93 | size_t i, j; |
153 | 93 | unsigned int partialBlock; |
154 | 93 | const unsigned char *curData; |
155 | 93 | unsigned int rateInBytes = instance->rate/8; |
156 | | |
157 | 93 | if (instance->squeezing) |
158 | 0 | return 1; /* Too late for additional input */ |
159 | | |
160 | 93 | i = 0; |
161 | 93 | curData = data; |
162 | 270 | while(i < dataByteLen) { |
163 | 177 | if ((instance->byteIOIndex == 0) && (dataByteLen-i >= rateInBytes)) { |
164 | | #ifdef SnP_FastLoop_Absorb |
165 | | /* processing full blocks first */ |
166 | 66 | if ((rateInBytes % (SnP_width/200)) == 0) { |
167 | | /* fast lane: whole lane rate */ |
168 | 66 | j = SnP_FastLoop_Absorb(instance->state, rateInBytes/(SnP_width/200), curData, dataByteLen - i); |
169 | 66 | i += j; |
170 | 66 | curData += j; |
171 | 66 | } |
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 | 66 | } |
187 | 111 | else { |
188 | | /* normal lane: using the message queue */ |
189 | 111 | if (dataByteLen-i > rateInBytes-instance->byteIOIndex) |
190 | 52 | partialBlock = rateInBytes-instance->byteIOIndex; |
191 | 59 | else |
192 | 59 | partialBlock = (unsigned int)(dataByteLen - i); |
193 | | #ifdef KeccakReference |
194 | | displayBytes(1, "Block to be absorbed (part)", curData, partialBlock); |
195 | | #endif |
196 | 111 | i += partialBlock; |
197 | | |
198 | 111 | SnP_AddBytes(instance->state, curData, instance->byteIOIndex, partialBlock); |
199 | 111 | curData += partialBlock; |
200 | 111 | instance->byteIOIndex += partialBlock; |
201 | 111 | if (instance->byteIOIndex == rateInBytes) { |
202 | 52 | SnP_Permute(instance->state); |
203 | 52 | instance->byteIOIndex = 0; |
204 | 52 | } |
205 | 111 | } |
206 | 177 | } |
207 | 93 | return 0; |
208 | 93 | } KeccakWidth1600_SpongeAbsorb Line | Count | Source | 151 | 93 | { | 152 | 93 | size_t i, j; | 153 | 93 | unsigned int partialBlock; | 154 | 93 | const unsigned char *curData; | 155 | 93 | unsigned int rateInBytes = instance->rate/8; | 156 | | | 157 | 93 | if (instance->squeezing) | 158 | 0 | return 1; /* Too late for additional input */ | 159 | | | 160 | 93 | i = 0; | 161 | 93 | curData = data; | 162 | 270 | while(i < dataByteLen) { | 163 | 177 | if ((instance->byteIOIndex == 0) && (dataByteLen-i >= rateInBytes)) { | 164 | 66 | #ifdef SnP_FastLoop_Absorb | 165 | | /* processing full blocks first */ | 166 | 66 | if ((rateInBytes % (SnP_width/200)) == 0) { | 167 | | /* fast lane: whole lane rate */ | 168 | 66 | j = SnP_FastLoop_Absorb(instance->state, rateInBytes/(SnP_width/200), curData, dataByteLen - i); | 169 | 66 | i += j; | 170 | 66 | curData += j; | 171 | 66 | } | 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 | 0 | #ifdef SnP_FastLoop_Absorb | 184 | 0 | } | 185 | 66 | #endif | 186 | 66 | } | 187 | 111 | else { | 188 | | /* normal lane: using the message queue */ | 189 | 111 | if (dataByteLen-i > rateInBytes-instance->byteIOIndex) | 190 | 52 | partialBlock = rateInBytes-instance->byteIOIndex; | 191 | 59 | else | 192 | 59 | partialBlock = (unsigned int)(dataByteLen - i); | 193 | | #ifdef KeccakReference | 194 | | displayBytes(1, "Block to be absorbed (part)", curData, partialBlock); | 195 | | #endif | 196 | 111 | i += partialBlock; | 197 | | | 198 | 111 | SnP_AddBytes(instance->state, curData, instance->byteIOIndex, partialBlock); | 199 | 111 | curData += partialBlock; | 200 | 111 | instance->byteIOIndex += partialBlock; | 201 | 111 | if (instance->byteIOIndex == rateInBytes) { | 202 | 52 | SnP_Permute(instance->state); | 203 | 52 | instance->byteIOIndex = 0; | 204 | 52 | } | 205 | 111 | } | 206 | 177 | } | 207 | 93 | return 0; | 208 | 93 | } |
Unexecuted instantiation: KeccakWidth1600_12rounds_SpongeAbsorb |
209 | | |
210 | | /* ---------------------------------------------------------------- */ |
211 | | |
212 | | int SpongeAbsorbLastFewBits(SpongeInstance *instance, unsigned char delimitedData) |
213 | 93 | { |
214 | 93 | unsigned int rateInBytes = instance->rate/8; |
215 | | |
216 | 93 | if (delimitedData == 0) |
217 | 0 | return 1; |
218 | 93 | 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 | 93 | 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 | 93 | if ((delimitedData >= 0x80) && (instance->byteIOIndex == (rateInBytes-1))) |
232 | 0 | SnP_Permute(instance->state); |
233 | | /* Second bit of padding */ |
234 | 93 | 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 | 93 | SnP_Permute(instance->state); |
244 | 93 | instance->byteIOIndex = 0; |
245 | 93 | instance->squeezing = 1; |
246 | | #ifdef KeccakReference |
247 | | displayText(1, "--- Switching to squeezing phase ---"); |
248 | | #endif |
249 | 93 | return 0; |
250 | 93 | } KeccakWidth1600_SpongeAbsorbLastFewBits Line | Count | Source | 213 | 93 | { | 214 | 93 | unsigned int rateInBytes = instance->rate/8; | 215 | | | 216 | 93 | if (delimitedData == 0) | 217 | 0 | return 1; | 218 | 93 | 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 | 93 | 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 | 93 | if ((delimitedData >= 0x80) && (instance->byteIOIndex == (rateInBytes-1))) | 232 | 0 | SnP_Permute(instance->state); | 233 | | /* Second bit of padding */ | 234 | 93 | 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 | 93 | SnP_Permute(instance->state); | 244 | 93 | instance->byteIOIndex = 0; | 245 | 93 | instance->squeezing = 1; | 246 | | #ifdef KeccakReference | 247 | | displayText(1, "--- Switching to squeezing phase ---"); | 248 | | #endif | 249 | 93 | return 0; | 250 | 93 | } |
Unexecuted instantiation: KeccakWidth1600_12rounds_SpongeAbsorbLastFewBits |
251 | | |
252 | | /* ---------------------------------------------------------------- */ |
253 | | |
254 | | int SpongeSqueeze(SpongeInstance *instance, unsigned char *data, size_t dataByteLen) |
255 | 93 | { |
256 | 93 | size_t i, j; |
257 | 93 | unsigned int partialBlock; |
258 | 93 | unsigned int rateInBytes = instance->rate/8; |
259 | 93 | unsigned char *curData; |
260 | | |
261 | 93 | if (!instance->squeezing) |
262 | 0 | SpongeAbsorbLastFewBits(instance, 0x01); |
263 | | |
264 | 93 | i = 0; |
265 | 93 | curData = data; |
266 | 186 | while(i < dataByteLen) { |
267 | 93 | 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 | 93 | else { |
279 | | /* normal lane: using the message queue */ |
280 | 93 | if (instance->byteIOIndex == rateInBytes) { |
281 | 0 | SnP_Permute(instance->state); |
282 | 0 | instance->byteIOIndex = 0; |
283 | 0 | } |
284 | 93 | if (dataByteLen-i > rateInBytes-instance->byteIOIndex) |
285 | 0 | partialBlock = rateInBytes-instance->byteIOIndex; |
286 | 93 | else |
287 | 93 | partialBlock = (unsigned int)(dataByteLen - i); |
288 | 93 | i += partialBlock; |
289 | | |
290 | 93 | SnP_ExtractBytes(instance->state, curData, instance->byteIOIndex, partialBlock); |
291 | | #ifdef KeccakReference |
292 | | displayBytes(1, "Squeezed block (part)", curData, partialBlock); |
293 | | #endif |
294 | 93 | curData += partialBlock; |
295 | 93 | instance->byteIOIndex += partialBlock; |
296 | 93 | } |
297 | 93 | } |
298 | 93 | return 0; |
299 | 93 | } KeccakWidth1600_SpongeSqueeze Line | Count | Source | 255 | 93 | { | 256 | 93 | size_t i, j; | 257 | 93 | unsigned int partialBlock; | 258 | 93 | unsigned int rateInBytes = instance->rate/8; | 259 | 93 | unsigned char *curData; | 260 | | | 261 | 93 | if (!instance->squeezing) | 262 | 0 | SpongeAbsorbLastFewBits(instance, 0x01); | 263 | | | 264 | 93 | i = 0; | 265 | 93 | curData = data; | 266 | 186 | while(i < dataByteLen) { | 267 | 93 | 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 | 93 | else { | 279 | | /* normal lane: using the message queue */ | 280 | 93 | if (instance->byteIOIndex == rateInBytes) { | 281 | 0 | SnP_Permute(instance->state); | 282 | 0 | instance->byteIOIndex = 0; | 283 | 0 | } | 284 | 93 | if (dataByteLen-i > rateInBytes-instance->byteIOIndex) | 285 | 0 | partialBlock = rateInBytes-instance->byteIOIndex; | 286 | 93 | else | 287 | 93 | partialBlock = (unsigned int)(dataByteLen - i); | 288 | 93 | i += partialBlock; | 289 | | | 290 | 93 | SnP_ExtractBytes(instance->state, curData, instance->byteIOIndex, partialBlock); | 291 | | #ifdef KeccakReference | 292 | | displayBytes(1, "Squeezed block (part)", curData, partialBlock); | 293 | | #endif | 294 | 93 | curData += partialBlock; | 295 | 93 | instance->byteIOIndex += partialBlock; | 296 | 93 | } | 297 | 93 | } | 298 | 93 | return 0; | 299 | 93 | } |
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 |