/src/php-src/ext/hash/hash_whirlpool.c
Line | Count | Source |
1 | | /* |
2 | | +----------------------------------------------------------------------+ |
3 | | | Copyright (c) The PHP Group | |
4 | | +----------------------------------------------------------------------+ |
5 | | | This source file is subject to version 3.01 of the PHP license, | |
6 | | | that is bundled with this package in the file LICENSE, and is | |
7 | | | available through the world-wide-web at the following url: | |
8 | | | https://www.php.net/license/3_01.txt | |
9 | | | If you did not receive a copy of the PHP license and are unable to | |
10 | | | obtain it through the world-wide-web, please send a note to | |
11 | | | license@php.net so we can mail you a copy immediately. | |
12 | | +----------------------------------------------------------------------+ |
13 | | | Authors: Michael Wallner <mike@php.net> | |
14 | | | Sara Golemon <pollita@php.net> | |
15 | | +----------------------------------------------------------------------+ |
16 | | */ |
17 | | |
18 | | #include "php_hash.h" |
19 | | |
20 | | /* |
21 | | * TODO: simplify Update and Final, those look ridiculously complex |
22 | | * Mike, 2005-11-23 |
23 | | */ |
24 | | |
25 | | #include "php_hash_whirlpool.h" |
26 | | #include "php_hash_whirlpool_tables.h" |
27 | | |
28 | 87.0k | #define DIGESTBYTES 64 |
29 | 86.6k | #define DIGESTBITS (8*DIGESTBYTES) /* 512 */ |
30 | | |
31 | 283 | #define WBLOCKBYTES 64 |
32 | | #define WBLOCKBITS (8*WBLOCKBYTES) /* 512 */ |
33 | | |
34 | 287 | #define LENGTHBYTES 32 |
35 | | #define LENGTHBITS (8*LENGTHBYTES) /* 256 */ |
36 | | |
37 | | static void WhirlpoolTransform(PHP_WHIRLPOOL_CTX *context) |
38 | 1.44k | { |
39 | 1.44k | int i, r; |
40 | 1.44k | uint64_t K[8]; /* the round key */ |
41 | 1.44k | uint64_t block[8]; /* mu(buffer) */ |
42 | 1.44k | uint64_t state[8]; /* the cipher state */ |
43 | 1.44k | uint64_t L[8]; |
44 | 1.44k | unsigned char *buffer = context->buffer.data; |
45 | | |
46 | | /* |
47 | | * map the buffer to a block: |
48 | | */ |
49 | 12.9k | for (i = 0; i < 8; i++, buffer += 8) { |
50 | 11.5k | block[i] = |
51 | 11.5k | (((uint64_t)buffer[0] ) << 56) ^ |
52 | 11.5k | (((uint64_t)buffer[1] & 0xffL) << 48) ^ |
53 | 11.5k | (((uint64_t)buffer[2] & 0xffL) << 40) ^ |
54 | 11.5k | (((uint64_t)buffer[3] & 0xffL) << 32) ^ |
55 | 11.5k | (((uint64_t)buffer[4] & 0xffL) << 24) ^ |
56 | 11.5k | (((uint64_t)buffer[5] & 0xffL) << 16) ^ |
57 | 11.5k | (((uint64_t)buffer[6] & 0xffL) << 8) ^ |
58 | 11.5k | (((uint64_t)buffer[7] & 0xffL) ); |
59 | 11.5k | } |
60 | | /* |
61 | | * compute and apply K^0 to the cipher state: |
62 | | */ |
63 | 1.44k | state[0] = block[0] ^ (K[0] = context->state[0]); |
64 | 1.44k | state[1] = block[1] ^ (K[1] = context->state[1]); |
65 | 1.44k | state[2] = block[2] ^ (K[2] = context->state[2]); |
66 | 1.44k | state[3] = block[3] ^ (K[3] = context->state[3]); |
67 | 1.44k | state[4] = block[4] ^ (K[4] = context->state[4]); |
68 | 1.44k | state[5] = block[5] ^ (K[5] = context->state[5]); |
69 | 1.44k | state[6] = block[6] ^ (K[6] = context->state[6]); |
70 | 1.44k | state[7] = block[7] ^ (K[7] = context->state[7]); |
71 | | /* |
72 | | * iterate over all rounds: |
73 | | */ |
74 | 15.8k | for (r = 1; r <= R; r++) { |
75 | | /* |
76 | | * compute K^r from K^{r-1}: |
77 | | */ |
78 | 14.4k | L[0] = |
79 | 14.4k | C0[(int)(K[0] >> 56) ] ^ |
80 | 14.4k | C1[(int)(K[7] >> 48) & 0xff] ^ |
81 | 14.4k | C2[(int)(K[6] >> 40) & 0xff] ^ |
82 | 14.4k | C3[(int)(K[5] >> 32) & 0xff] ^ |
83 | 14.4k | C4[(int)(K[4] >> 24) & 0xff] ^ |
84 | 14.4k | C5[(int)(K[3] >> 16) & 0xff] ^ |
85 | 14.4k | C6[(int)(K[2] >> 8) & 0xff] ^ |
86 | 14.4k | C7[(int)(K[1] ) & 0xff] ^ |
87 | 14.4k | rc[r]; |
88 | 14.4k | L[1] = |
89 | 14.4k | C0[(int)(K[1] >> 56) ] ^ |
90 | 14.4k | C1[(int)(K[0] >> 48) & 0xff] ^ |
91 | 14.4k | C2[(int)(K[7] >> 40) & 0xff] ^ |
92 | 14.4k | C3[(int)(K[6] >> 32) & 0xff] ^ |
93 | 14.4k | C4[(int)(K[5] >> 24) & 0xff] ^ |
94 | 14.4k | C5[(int)(K[4] >> 16) & 0xff] ^ |
95 | 14.4k | C6[(int)(K[3] >> 8) & 0xff] ^ |
96 | 14.4k | C7[(int)(K[2] ) & 0xff]; |
97 | 14.4k | L[2] = |
98 | 14.4k | C0[(int)(K[2] >> 56) ] ^ |
99 | 14.4k | C1[(int)(K[1] >> 48) & 0xff] ^ |
100 | 14.4k | C2[(int)(K[0] >> 40) & 0xff] ^ |
101 | 14.4k | C3[(int)(K[7] >> 32) & 0xff] ^ |
102 | 14.4k | C4[(int)(K[6] >> 24) & 0xff] ^ |
103 | 14.4k | C5[(int)(K[5] >> 16) & 0xff] ^ |
104 | 14.4k | C6[(int)(K[4] >> 8) & 0xff] ^ |
105 | 14.4k | C7[(int)(K[3] ) & 0xff]; |
106 | 14.4k | L[3] = |
107 | 14.4k | C0[(int)(K[3] >> 56) ] ^ |
108 | 14.4k | C1[(int)(K[2] >> 48) & 0xff] ^ |
109 | 14.4k | C2[(int)(K[1] >> 40) & 0xff] ^ |
110 | 14.4k | C3[(int)(K[0] >> 32) & 0xff] ^ |
111 | 14.4k | C4[(int)(K[7] >> 24) & 0xff] ^ |
112 | 14.4k | C5[(int)(K[6] >> 16) & 0xff] ^ |
113 | 14.4k | C6[(int)(K[5] >> 8) & 0xff] ^ |
114 | 14.4k | C7[(int)(K[4] ) & 0xff]; |
115 | 14.4k | L[4] = |
116 | 14.4k | C0[(int)(K[4] >> 56) ] ^ |
117 | 14.4k | C1[(int)(K[3] >> 48) & 0xff] ^ |
118 | 14.4k | C2[(int)(K[2] >> 40) & 0xff] ^ |
119 | 14.4k | C3[(int)(K[1] >> 32) & 0xff] ^ |
120 | 14.4k | C4[(int)(K[0] >> 24) & 0xff] ^ |
121 | 14.4k | C5[(int)(K[7] >> 16) & 0xff] ^ |
122 | 14.4k | C6[(int)(K[6] >> 8) & 0xff] ^ |
123 | 14.4k | C7[(int)(K[5] ) & 0xff]; |
124 | 14.4k | L[5] = |
125 | 14.4k | C0[(int)(K[5] >> 56) ] ^ |
126 | 14.4k | C1[(int)(K[4] >> 48) & 0xff] ^ |
127 | 14.4k | C2[(int)(K[3] >> 40) & 0xff] ^ |
128 | 14.4k | C3[(int)(K[2] >> 32) & 0xff] ^ |
129 | 14.4k | C4[(int)(K[1] >> 24) & 0xff] ^ |
130 | 14.4k | C5[(int)(K[0] >> 16) & 0xff] ^ |
131 | 14.4k | C6[(int)(K[7] >> 8) & 0xff] ^ |
132 | 14.4k | C7[(int)(K[6] ) & 0xff]; |
133 | 14.4k | L[6] = |
134 | 14.4k | C0[(int)(K[6] >> 56) ] ^ |
135 | 14.4k | C1[(int)(K[5] >> 48) & 0xff] ^ |
136 | 14.4k | C2[(int)(K[4] >> 40) & 0xff] ^ |
137 | 14.4k | C3[(int)(K[3] >> 32) & 0xff] ^ |
138 | 14.4k | C4[(int)(K[2] >> 24) & 0xff] ^ |
139 | 14.4k | C5[(int)(K[1] >> 16) & 0xff] ^ |
140 | 14.4k | C6[(int)(K[0] >> 8) & 0xff] ^ |
141 | 14.4k | C7[(int)(K[7] ) & 0xff]; |
142 | 14.4k | L[7] = |
143 | 14.4k | C0[(int)(K[7] >> 56) ] ^ |
144 | 14.4k | C1[(int)(K[6] >> 48) & 0xff] ^ |
145 | 14.4k | C2[(int)(K[5] >> 40) & 0xff] ^ |
146 | 14.4k | C3[(int)(K[4] >> 32) & 0xff] ^ |
147 | 14.4k | C4[(int)(K[3] >> 24) & 0xff] ^ |
148 | 14.4k | C5[(int)(K[2] >> 16) & 0xff] ^ |
149 | 14.4k | C6[(int)(K[1] >> 8) & 0xff] ^ |
150 | 14.4k | C7[(int)(K[0] ) & 0xff]; |
151 | 14.4k | K[0] = L[0]; |
152 | 14.4k | K[1] = L[1]; |
153 | 14.4k | K[2] = L[2]; |
154 | 14.4k | K[3] = L[3]; |
155 | 14.4k | K[4] = L[4]; |
156 | 14.4k | K[5] = L[5]; |
157 | 14.4k | K[6] = L[6]; |
158 | 14.4k | K[7] = L[7]; |
159 | | /* |
160 | | * apply the r-th round transformation: |
161 | | */ |
162 | 14.4k | L[0] = |
163 | 14.4k | C0[(int)(state[0] >> 56) ] ^ |
164 | 14.4k | C1[(int)(state[7] >> 48) & 0xff] ^ |
165 | 14.4k | C2[(int)(state[6] >> 40) & 0xff] ^ |
166 | 14.4k | C3[(int)(state[5] >> 32) & 0xff] ^ |
167 | 14.4k | C4[(int)(state[4] >> 24) & 0xff] ^ |
168 | 14.4k | C5[(int)(state[3] >> 16) & 0xff] ^ |
169 | 14.4k | C6[(int)(state[2] >> 8) & 0xff] ^ |
170 | 14.4k | C7[(int)(state[1] ) & 0xff] ^ |
171 | 14.4k | K[0]; |
172 | 14.4k | L[1] = |
173 | 14.4k | C0[(int)(state[1] >> 56) ] ^ |
174 | 14.4k | C1[(int)(state[0] >> 48) & 0xff] ^ |
175 | 14.4k | C2[(int)(state[7] >> 40) & 0xff] ^ |
176 | 14.4k | C3[(int)(state[6] >> 32) & 0xff] ^ |
177 | 14.4k | C4[(int)(state[5] >> 24) & 0xff] ^ |
178 | 14.4k | C5[(int)(state[4] >> 16) & 0xff] ^ |
179 | 14.4k | C6[(int)(state[3] >> 8) & 0xff] ^ |
180 | 14.4k | C7[(int)(state[2] ) & 0xff] ^ |
181 | 14.4k | K[1]; |
182 | 14.4k | L[2] = |
183 | 14.4k | C0[(int)(state[2] >> 56) ] ^ |
184 | 14.4k | C1[(int)(state[1] >> 48) & 0xff] ^ |
185 | 14.4k | C2[(int)(state[0] >> 40) & 0xff] ^ |
186 | 14.4k | C3[(int)(state[7] >> 32) & 0xff] ^ |
187 | 14.4k | C4[(int)(state[6] >> 24) & 0xff] ^ |
188 | 14.4k | C5[(int)(state[5] >> 16) & 0xff] ^ |
189 | 14.4k | C6[(int)(state[4] >> 8) & 0xff] ^ |
190 | 14.4k | C7[(int)(state[3] ) & 0xff] ^ |
191 | 14.4k | K[2]; |
192 | 14.4k | L[3] = |
193 | 14.4k | C0[(int)(state[3] >> 56) ] ^ |
194 | 14.4k | C1[(int)(state[2] >> 48) & 0xff] ^ |
195 | 14.4k | C2[(int)(state[1] >> 40) & 0xff] ^ |
196 | 14.4k | C3[(int)(state[0] >> 32) & 0xff] ^ |
197 | 14.4k | C4[(int)(state[7] >> 24) & 0xff] ^ |
198 | 14.4k | C5[(int)(state[6] >> 16) & 0xff] ^ |
199 | 14.4k | C6[(int)(state[5] >> 8) & 0xff] ^ |
200 | 14.4k | C7[(int)(state[4] ) & 0xff] ^ |
201 | 14.4k | K[3]; |
202 | 14.4k | L[4] = |
203 | 14.4k | C0[(int)(state[4] >> 56) ] ^ |
204 | 14.4k | C1[(int)(state[3] >> 48) & 0xff] ^ |
205 | 14.4k | C2[(int)(state[2] >> 40) & 0xff] ^ |
206 | 14.4k | C3[(int)(state[1] >> 32) & 0xff] ^ |
207 | 14.4k | C4[(int)(state[0] >> 24) & 0xff] ^ |
208 | 14.4k | C5[(int)(state[7] >> 16) & 0xff] ^ |
209 | 14.4k | C6[(int)(state[6] >> 8) & 0xff] ^ |
210 | 14.4k | C7[(int)(state[5] ) & 0xff] ^ |
211 | 14.4k | K[4]; |
212 | 14.4k | L[5] = |
213 | 14.4k | C0[(int)(state[5] >> 56) ] ^ |
214 | 14.4k | C1[(int)(state[4] >> 48) & 0xff] ^ |
215 | 14.4k | C2[(int)(state[3] >> 40) & 0xff] ^ |
216 | 14.4k | C3[(int)(state[2] >> 32) & 0xff] ^ |
217 | 14.4k | C4[(int)(state[1] >> 24) & 0xff] ^ |
218 | 14.4k | C5[(int)(state[0] >> 16) & 0xff] ^ |
219 | 14.4k | C6[(int)(state[7] >> 8) & 0xff] ^ |
220 | 14.4k | C7[(int)(state[6] ) & 0xff] ^ |
221 | 14.4k | K[5]; |
222 | 14.4k | L[6] = |
223 | 14.4k | C0[(int)(state[6] >> 56) ] ^ |
224 | 14.4k | C1[(int)(state[5] >> 48) & 0xff] ^ |
225 | 14.4k | C2[(int)(state[4] >> 40) & 0xff] ^ |
226 | 14.4k | C3[(int)(state[3] >> 32) & 0xff] ^ |
227 | 14.4k | C4[(int)(state[2] >> 24) & 0xff] ^ |
228 | 14.4k | C5[(int)(state[1] >> 16) & 0xff] ^ |
229 | 14.4k | C6[(int)(state[0] >> 8) & 0xff] ^ |
230 | 14.4k | C7[(int)(state[7] ) & 0xff] ^ |
231 | 14.4k | K[6]; |
232 | 14.4k | L[7] = |
233 | 14.4k | C0[(int)(state[7] >> 56) ] ^ |
234 | 14.4k | C1[(int)(state[6] >> 48) & 0xff] ^ |
235 | 14.4k | C2[(int)(state[5] >> 40) & 0xff] ^ |
236 | 14.4k | C3[(int)(state[4] >> 32) & 0xff] ^ |
237 | 14.4k | C4[(int)(state[3] >> 24) & 0xff] ^ |
238 | 14.4k | C5[(int)(state[2] >> 16) & 0xff] ^ |
239 | 14.4k | C6[(int)(state[1] >> 8) & 0xff] ^ |
240 | 14.4k | C7[(int)(state[0] ) & 0xff] ^ |
241 | 14.4k | K[7]; |
242 | 14.4k | state[0] = L[0]; |
243 | 14.4k | state[1] = L[1]; |
244 | 14.4k | state[2] = L[2]; |
245 | 14.4k | state[3] = L[3]; |
246 | 14.4k | state[4] = L[4]; |
247 | 14.4k | state[5] = L[5]; |
248 | 14.4k | state[6] = L[6]; |
249 | 14.4k | state[7] = L[7]; |
250 | 14.4k | } |
251 | | /* |
252 | | * apply the Miyaguchi-Preneel compression function: |
253 | | */ |
254 | 1.44k | context->state[0] ^= state[0] ^ block[0]; |
255 | 1.44k | context->state[1] ^= state[1] ^ block[1]; |
256 | 1.44k | context->state[2] ^= state[2] ^ block[2]; |
257 | 1.44k | context->state[3] ^= state[3] ^ block[3]; |
258 | 1.44k | context->state[4] ^= state[4] ^ block[4]; |
259 | 1.44k | context->state[5] ^= state[5] ^ block[5]; |
260 | 1.44k | context->state[6] ^= state[6] ^ block[6]; |
261 | 1.44k | context->state[7] ^= state[7] ^ block[7]; |
262 | | |
263 | 1.44k | ZEND_SECURE_ZERO(state, sizeof(state)); |
264 | 1.44k | } |
265 | | |
266 | | PHP_HASH_API void PHP_WHIRLPOOLInit(PHP_WHIRLPOOL_CTX *context, ZEND_ATTRIBUTE_UNUSED HashTable *args) |
267 | 113 | { |
268 | 113 | memset(context, 0, sizeof(*context)); |
269 | 113 | } |
270 | | |
271 | | PHP_HASH_API void PHP_WHIRLPOOLUpdate(PHP_WHIRLPOOL_CTX *context, const unsigned char *input, size_t len) |
272 | 48 | { |
273 | 48 | uint64_t sourceBits = len * 8; |
274 | 48 | int sourcePos = 0; /* index of leftmost source unsigned char containing data (1 to 8 bits). */ |
275 | 48 | int sourceGap = (8 - ((int)sourceBits & 7)) & 7; /* space on source[sourcePos]. */ |
276 | 48 | int bufferRem = context->buffer.bits & 7; /* occupied bits on buffer[bufferPos]. */ |
277 | 48 | const unsigned char *source = input; |
278 | 48 | unsigned char *buffer = context->buffer.data; |
279 | 48 | unsigned char *bitLength = context->bitlength; |
280 | 48 | int bufferBits = context->buffer.bits; |
281 | 48 | int bufferPos = context->buffer.pos; |
282 | 48 | uint32_t b, carry; |
283 | 48 | int i; |
284 | | |
285 | | /* |
286 | | * tally the length of the added data: |
287 | | */ |
288 | 48 | uint64_t value = sourceBits; |
289 | 196 | for (i = 31, carry = 0; i >= 0 && (carry != 0 || value != L64(0)); i--) { |
290 | 148 | carry += bitLength[i] + ((uint32_t)value & 0xff); |
291 | 148 | bitLength[i] = (unsigned char)carry; |
292 | 148 | carry >>= 8; |
293 | 148 | value >>= 8; |
294 | 148 | } |
295 | | /* |
296 | | * process data in chunks of 8 bits (a more efficient approach would be to take whole-word chunks): |
297 | | */ |
298 | 86.6k | while (sourceBits > 8) { |
299 | | /* N.B. at least source[sourcePos] and source[sourcePos+1] contain data. */ |
300 | | /* |
301 | | * take a byte from the source: |
302 | | */ |
303 | 86.5k | b = ((source[sourcePos] << sourceGap) & 0xff) | |
304 | 86.5k | ((source[sourcePos + 1] & 0xff) >> (8 - sourceGap)); |
305 | | /* |
306 | | * process this byte: |
307 | | */ |
308 | 86.5k | buffer[bufferPos++] |= (unsigned char)(b >> bufferRem); |
309 | 86.5k | bufferBits += 8 - bufferRem; /* bufferBits = 8*bufferPos; */ |
310 | 86.5k | if (bufferBits == DIGESTBITS) { |
311 | | /* |
312 | | * process data block: |
313 | | */ |
314 | 1.37k | WhirlpoolTransform(context); |
315 | | /* |
316 | | * reset buffer: |
317 | | */ |
318 | 1.37k | bufferBits = bufferPos = 0; |
319 | 1.37k | } |
320 | 86.5k | buffer[bufferPos] = (unsigned char) (b << (8 - bufferRem)); |
321 | 86.5k | bufferBits += bufferRem; |
322 | | /* |
323 | | * proceed to remaining data: |
324 | | */ |
325 | 86.5k | sourceBits -= 8; |
326 | 86.5k | sourcePos++; |
327 | 86.5k | } |
328 | | /* now 0 <= sourceBits <= 8; |
329 | | * furthermore, all data (if any is left) is in source[sourcePos]. |
330 | | */ |
331 | 48 | if (sourceBits > 0) { |
332 | 46 | b = (source[sourcePos] << sourceGap) & 0xff; /* bits are left-justified on b. */ |
333 | | /* |
334 | | * process the remaining bits: |
335 | | */ |
336 | 46 | buffer[bufferPos] |= b >> bufferRem; |
337 | 46 | } else { |
338 | 2 | b = 0; |
339 | 2 | } |
340 | 48 | if (bufferRem + sourceBits < 8) { |
341 | | /* |
342 | | * all remaining data fits on buffer[bufferPos], |
343 | | * and there still remains some space. |
344 | | */ |
345 | 2 | bufferBits += (int) sourceBits; |
346 | 46 | } else { |
347 | | /* |
348 | | * buffer[bufferPos] is full: |
349 | | */ |
350 | 46 | bufferPos++; |
351 | 46 | bufferBits += 8 - bufferRem; /* bufferBits = 8*bufferPos; */ |
352 | 46 | sourceBits -= 8 - bufferRem; |
353 | | /* now 0 <= sourceBits < 8; |
354 | | * furthermore, all data (if any is left) is in source[sourcePos]. |
355 | | */ |
356 | 46 | if (bufferBits == DIGESTBITS) { |
357 | | /* |
358 | | * process data block: |
359 | | */ |
360 | 1 | WhirlpoolTransform(context); |
361 | | /* |
362 | | * reset buffer: |
363 | | */ |
364 | 1 | bufferBits = bufferPos = 0; |
365 | 1 | } |
366 | 46 | buffer[bufferPos] = (unsigned char) (b << (8 - bufferRem)); |
367 | 46 | bufferBits += (int)sourceBits; |
368 | 46 | } |
369 | 48 | context->buffer.bits = bufferBits; |
370 | 48 | context->buffer.pos = bufferPos; |
371 | 48 | } |
372 | | |
373 | | PHP_HASH_API void PHP_WHIRLPOOLFinal(unsigned char digest[64], PHP_WHIRLPOOL_CTX *context) |
374 | 48 | { |
375 | 48 | int i; |
376 | 48 | unsigned char *buffer = context->buffer.data; |
377 | 48 | unsigned char *bitLength = context->bitlength; |
378 | 48 | int bufferBits = context->buffer.bits; |
379 | 48 | int bufferPos = context->buffer.pos; |
380 | | |
381 | | /* |
382 | | * append a '1'-bit: |
383 | | */ |
384 | 48 | buffer[bufferPos] |= 0x80U >> (bufferBits & 7); |
385 | 48 | bufferPos++; /* all remaining bits on the current unsigned char are set to zero. */ |
386 | | /* |
387 | | * pad with zero bits to complete (N*WBLOCKBITS - LENGTHBITS) bits: |
388 | | */ |
389 | 48 | if (bufferPos > WBLOCKBYTES - LENGTHBYTES) { |
390 | 23 | if (bufferPos < WBLOCKBYTES) { |
391 | 21 | memset(&buffer[bufferPos], 0, WBLOCKBYTES - bufferPos); |
392 | 21 | } |
393 | | /* |
394 | | * process data block: |
395 | | */ |
396 | 23 | WhirlpoolTransform(context); |
397 | | /* |
398 | | * reset buffer: |
399 | | */ |
400 | 23 | bufferPos = 0; |
401 | 23 | } |
402 | 48 | if (bufferPos < WBLOCKBYTES - LENGTHBYTES) { |
403 | 47 | memset(&buffer[bufferPos], 0, (WBLOCKBYTES - LENGTHBYTES) - bufferPos); |
404 | 47 | } |
405 | 48 | bufferPos = WBLOCKBYTES - LENGTHBYTES; |
406 | | /* |
407 | | * append bit length of hashed data: |
408 | | */ |
409 | 48 | memcpy(&buffer[WBLOCKBYTES - LENGTHBYTES], bitLength, LENGTHBYTES); |
410 | | /* |
411 | | * process data block: |
412 | | */ |
413 | 48 | WhirlpoolTransform(context); |
414 | | /* |
415 | | * return the completed message digest: |
416 | | */ |
417 | 432 | for (i = 0; i < DIGESTBYTES/8; i++) { |
418 | 384 | digest[0] = (unsigned char)(context->state[i] >> 56); |
419 | 384 | digest[1] = (unsigned char)(context->state[i] >> 48); |
420 | 384 | digest[2] = (unsigned char)(context->state[i] >> 40); |
421 | 384 | digest[3] = (unsigned char)(context->state[i] >> 32); |
422 | 384 | digest[4] = (unsigned char)(context->state[i] >> 24); |
423 | 384 | digest[5] = (unsigned char)(context->state[i] >> 16); |
424 | 384 | digest[6] = (unsigned char)(context->state[i] >> 8); |
425 | 384 | digest[7] = (unsigned char)(context->state[i] ); |
426 | 384 | digest += 8; |
427 | 384 | } |
428 | | |
429 | 48 | ZEND_SECURE_ZERO(context, sizeof(*context)); |
430 | 48 | } |
431 | | |
432 | | static int php_whirlpool_unserialize(php_hashcontext_object *hash, zend_long magic, const zval *zv) |
433 | 113 | { |
434 | 113 | PHP_WHIRLPOOL_CTX *ctx = (PHP_WHIRLPOOL_CTX *) hash->context; |
435 | 113 | int r = FAILURE; |
436 | 113 | if (magic == PHP_HASH_SERIALIZE_MAGIC_SPEC |
437 | 113 | && (r = php_hash_unserialize_spec(hash, zv, PHP_WHIRLPOOL_SPEC)) == SUCCESS |
438 | 113 | && ctx->buffer.pos >= 0 |
439 | 113 | && ctx->buffer.pos < (int) sizeof(ctx->buffer.data) |
440 | 113 | && ctx->buffer.bits >= ctx->buffer.pos * 8 |
441 | 113 | && ctx->buffer.bits < ctx->buffer.pos * 8 + 8) { |
442 | 48 | return SUCCESS; |
443 | 65 | } else { |
444 | 65 | return r != SUCCESS ? r : -2000; |
445 | 65 | } |
446 | 113 | } |
447 | | |
448 | | const php_hash_ops php_hash_whirlpool_ops = { |
449 | | "whirlpool", |
450 | | (php_hash_init_func_t) PHP_WHIRLPOOLInit, |
451 | | (php_hash_update_func_t) PHP_WHIRLPOOLUpdate, |
452 | | (php_hash_final_func_t) PHP_WHIRLPOOLFinal, |
453 | | php_hash_copy, |
454 | | php_hash_serialize, |
455 | | php_whirlpool_unserialize, |
456 | | PHP_WHIRLPOOL_SPEC, |
457 | | 64, |
458 | | 64, |
459 | | sizeof(PHP_WHIRLPOOL_CTX), |
460 | | 1 |
461 | | }; |