xref: /PHP-7.4/ext/hash/hash_ripemd.c (revision 92ac598a)
1 /*
2   +----------------------------------------------------------------------+
3   | PHP Version 7                                                        |
4   +----------------------------------------------------------------------+
5   | Copyright (c) The PHP Group                                          |
6   +----------------------------------------------------------------------+
7   | This source file is subject to version 3.01 of the PHP license,      |
8   | that is bundled with this package in the file LICENSE, and is        |
9   | available through the world-wide-web at the following url:           |
10   | http://www.php.net/license/3_01.txt                                  |
11   | If you did not receive a copy of the PHP license and are unable to   |
12   | obtain it through the world-wide-web, please send a note to          |
13   | license@php.net so we can mail you a copy immediately.               |
14   +----------------------------------------------------------------------+
15   | Author: Sara Golemon <pollita@php.net>                               |
16   +----------------------------------------------------------------------+
17 */
18 
19 /* Heavily borrowed from md5.c & sha1.c of PHP archival fame
20    Note that ripemd laughs in the face of logic and uses
21    little endian byte ordering */
22 
23 #include "php_hash.h"
24 #include "php_hash_ripemd.h"
25 
26 const php_hash_ops php_hash_ripemd128_ops = {
27 	(php_hash_init_func_t) PHP_RIPEMD128Init,
28 	(php_hash_update_func_t) PHP_RIPEMD128Update,
29 	(php_hash_final_func_t) PHP_RIPEMD128Final,
30 	(php_hash_copy_func_t) php_hash_copy,
31 	16,
32 	64,
33 	sizeof(PHP_RIPEMD128_CTX),
34 	1
35 };
36 
37 const php_hash_ops php_hash_ripemd160_ops = {
38 	(php_hash_init_func_t) PHP_RIPEMD160Init,
39 	(php_hash_update_func_t) PHP_RIPEMD160Update,
40 	(php_hash_final_func_t) PHP_RIPEMD160Final,
41 	(php_hash_copy_func_t) php_hash_copy,
42 	20,
43 	64,
44 	sizeof(PHP_RIPEMD160_CTX),
45 	1
46 };
47 
48 const php_hash_ops php_hash_ripemd256_ops = {
49 	(php_hash_init_func_t) PHP_RIPEMD256Init,
50 	(php_hash_update_func_t) PHP_RIPEMD256Update,
51 	(php_hash_final_func_t) PHP_RIPEMD256Final,
52 	(php_hash_copy_func_t) php_hash_copy,
53 	32,
54 	64,
55 	sizeof(PHP_RIPEMD256_CTX),
56 	1
57 };
58 
59 const php_hash_ops php_hash_ripemd320_ops = {
60 	(php_hash_init_func_t) PHP_RIPEMD320Init,
61 	(php_hash_update_func_t) PHP_RIPEMD320Update,
62 	(php_hash_final_func_t) PHP_RIPEMD320Final,
63 	(php_hash_copy_func_t) php_hash_copy,
64 	40,
65 	64,
66 	sizeof(PHP_RIPEMD320_CTX),
67 	1
68 };
69 
70 /* {{{ PHP_RIPEMD128Init
71  * ripemd128 initialization. Begins a ripemd128 operation, writing a new context.
72  */
PHP_RIPEMD128Init(PHP_RIPEMD128_CTX * context)73 PHP_HASH_API void PHP_RIPEMD128Init(PHP_RIPEMD128_CTX * context)
74 {
75 	context->count[0] = context->count[1] = 0;
76 	/* Load magic initialization constants.
77 	 */
78 	context->state[0] = 0x67452301;
79 	context->state[1] = 0xEFCDAB89;
80 	context->state[2] = 0x98BADCFE;
81 	context->state[3] = 0x10325476;
82 }
83 /* }}} */
84 
85 /* {{{ PHP_RIPEMD256Init
86  * ripemd256 initialization. Begins a ripemd256 operation, writing a new context.
87  */
PHP_RIPEMD256Init(PHP_RIPEMD256_CTX * context)88 PHP_HASH_API void PHP_RIPEMD256Init(PHP_RIPEMD256_CTX * context)
89 {
90 	context->count[0] = context->count[1] = 0;
91 	/* Load magic initialization constants.
92 	 */
93 	context->state[0] = 0x67452301;
94 	context->state[1] = 0xEFCDAB89;
95 	context->state[2] = 0x98BADCFE;
96 	context->state[3] = 0x10325476;
97 	context->state[4] = 0x76543210;
98 	context->state[5] = 0xFEDCBA98;
99 	context->state[6] = 0x89ABCDEF;
100 	context->state[7] = 0x01234567;
101 }
102 /* }}} */
103 
104 /* {{{ PHP_RIPEMD160Init
105  * ripemd160 initialization. Begins a ripemd160 operation, writing a new context.
106  */
PHP_RIPEMD160Init(PHP_RIPEMD160_CTX * context)107 PHP_HASH_API void PHP_RIPEMD160Init(PHP_RIPEMD160_CTX * context)
108 {
109 	context->count[0] = context->count[1] = 0;
110 	/* Load magic initialization constants.
111 	 */
112 	context->state[0] = 0x67452301;
113 	context->state[1] = 0xEFCDAB89;
114 	context->state[2] = 0x98BADCFE;
115 	context->state[3] = 0x10325476;
116 	context->state[4] = 0xC3D2E1F0;
117 }
118 /* }}} */
119 
120 /* {{{ PHP_RIPEMD320Init
121  * ripemd320 initialization. Begins a ripemd320 operation, writing a new context.
122  */
PHP_RIPEMD320Init(PHP_RIPEMD320_CTX * context)123 PHP_HASH_API void PHP_RIPEMD320Init(PHP_RIPEMD320_CTX * context)
124 {
125 	context->count[0] = context->count[1] = 0;
126 	/* Load magic initialization constants.
127 	 */
128 	context->state[0] = 0x67452301;
129 	context->state[1] = 0xEFCDAB89;
130 	context->state[2] = 0x98BADCFE;
131 	context->state[3] = 0x10325476;
132 	context->state[4] = 0xC3D2E1F0;
133 	context->state[5] = 0x76543210;
134 	context->state[6] = 0xFEDCBA98;
135 	context->state[7] = 0x89ABCDEF;
136 	context->state[8] = 0x01234567;
137 	context->state[9] = 0x3C2D1E0F;
138 }
139 /* }}} */
140 
141 /* Basic ripemd function */
142 #define F0(x,y,z)		((x) ^ (y) ^ (z))
143 #define F1(x,y,z)		(((x) & (y)) | ((~(x)) & (z)))
144 #define F2(x,y,z)		(((x) | (~(y))) ^ (z))
145 #define F3(x,y,z)		(((x) & (z)) | ((y) & (~(z))))
146 #define F4(x,y,z)		((x) ^ ((y) | (~(z))))
147 
148 static const uint32_t K_values[5]  = { 0x00000000, 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xA953FD4E };    /* 128, 256, 160, 320 */
149 static const uint32_t KK_values[4] = { 0x50A28BE6, 0x5C4DD124, 0x6D703EF3, 0x00000000 };                /* 128 & 256 */
150 static const uint32_t KK160_values[5] = { 0x50A28BE6, 0x5C4DD124, 0x6D703EF3, 0x7A6D76E9, 0x00000000 }; /* 160 & 320 */
151 
152 #define K(n)  K_values[ (n) >> 4]
153 #define KK(n) KK_values[(n) >> 4]
154 #define KK160(n) KK160_values[(n) >> 4]
155 
156 static const unsigned char R[80] = {
157 	 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
158 	 7,  4, 13,  1, 10,  6, 15,  3, 12,  0,  9,  5,  2, 14, 11,  8,
159 	 3, 10, 14,  4,  9, 15,  8,  1,  2,  7,  0,  6, 13, 11,  5, 12,
160 	 1,  9, 11, 10,  0,  8, 12,  4, 13,  3,  7, 15, 14,  5,  6,  2,
161 	 4,  0,  5,  9,  7, 12,  2, 10, 14,  1,  3,  8, 11,  6, 15, 13 };
162 
163 static const unsigned char RR[80] = {
164 	 5, 14,  7,  0,  9,  2, 11,  4, 13,  6, 15,  8,  1, 10,  3, 12,
165 	 6, 11,  3,  7,  0, 13,  5, 10, 14, 15,  8, 12,  4,  9,  1,  2,
166 	15,  5,  1,  3,  7, 14,  6,  9, 11,  8, 12,  2, 10,  0,  4, 13,
167 	 8,  6,  4,  1,  3, 11, 15,  0,  5, 12,  2, 13,  9,  7, 10, 14,
168 	12, 15, 10,  4,  1,  5,  8,  7,  6,  2, 13, 14,  0,  3,  9, 11 };
169 
170 static const unsigned char S[80] = {
171 	11, 14, 15, 12,  5,  8,  7,  9, 11, 13, 14, 15,  6,  7,  9,  8,
172 	 7,  6,  8, 13, 11,  9,  7, 15,  7, 12, 15,  9, 11,  7, 13, 12,
173 	11, 13,  6,  7, 14,  9, 13, 15, 14,  8, 13,  6,  5, 12,  7,  5,
174 	11, 12, 14, 15, 14, 15,  9,  8,  9, 14,  5,  6,  8,  6,  5, 12,
175 	 9, 15,  5, 11,  6,  8, 13, 12,  5, 12, 13, 14, 11,  8,  5,  6 };
176 
177 static const unsigned char SS[80] = {
178 	 8,  9,  9, 11, 13, 15, 15,  5,  7,  7,  8, 11, 14, 14, 12,  6,
179 	 9, 13, 15,  7, 12,  8,  9, 11,  7,  7, 12,  7,  6, 15, 13, 11,
180 	 9,  7, 15, 11,  8,  6,  6, 14, 12, 13,  5, 14, 13, 13,  7,  5,
181 	15,  5,  8, 11, 14, 14,  6, 14,  6,  9, 12,  9, 12,  5, 15,  8,
182 	 8,  5, 12,  9, 12,  5, 14,  6,  8, 13,  6,  5, 15, 13, 11, 11 };
183 
184 #define ROLS(j, x)	(((x) << S[j])  | ((x) >> (32 - S[j])))
185 #define ROLSS(j, x)	(((x) << SS[j]) | ((x) >> (32 - SS[j])))
186 #define ROL(n, x)	(((x) << n) | ((x) >> (32 - n)))
187 
188 /* {{{ RIPEMDDecode
189    Decodes input (unsigned char) into output (uint32_t). Assumes len is
190    a multiple of 4.
191  */
RIPEMDDecode(uint32_t * output,const unsigned char * input,unsigned int len)192 static void RIPEMDDecode(uint32_t *output, const unsigned char *input, unsigned int len)
193 {
194 	unsigned int i, j;
195 
196 	for (i = 0, j = 0; j < len; i++, j += 4)
197 		output[i] = ((uint32_t) input[j + 0]) | (((uint32_t) input[j + 1]) << 8) |
198 			(((uint32_t) input[j + 2]) << 16) | (((uint32_t) input[j + 3]) << 24);
199 }
200 /* }}} */
201 
202 /* {{{ RIPEMD128Transform
203  * ripemd128 basic transformation. Transforms state based on block.
204  */
RIPEMD128Transform(uint32_t state[4],const unsigned char block[64])205 static void RIPEMD128Transform(uint32_t state[4], const unsigned char block[64])
206 {
207 	uint32_t a  = state[0], b  = state[1], c  = state[2], d  = state[3];
208 	uint32_t aa = state[0], bb = state[1], cc = state[2], dd = state[3];
209 	uint32_t tmp, x[16];
210 	int j;
211 
212 	RIPEMDDecode(x, block, 64);
213 
214 	for(j = 0; j < 16; j++) {
215 		tmp = ROLS( j, a  + F0(b,  c,  d)  + x[R[j]]  + K(j));
216 		a = d; d = c; c = b; b = tmp;
217 		tmp = ROLSS(j, aa + F3(bb, cc, dd) + x[RR[j]] + KK(j));
218 		aa = dd; dd = cc; cc = bb; bb = tmp;
219 	}
220 
221 	for(j = 16; j < 32; j++) {
222 		tmp = ROLS( j, a  + F1(b,  c,  d)  + x[R[j]]  + K(j));
223 		a = d; d = c; c = b; b = tmp;
224 		tmp = ROLSS(j, aa + F2(bb, cc, dd) + x[RR[j]] + KK(j));
225 		aa = dd; dd = cc; cc = bb; bb = tmp;
226 	}
227 
228 	for(j = 32; j < 48; j++) {
229 		tmp = ROLS( j, a  + F2(b,  c,  d)  + x[R[j]]  + K(j));
230 		a = d; d = c; c = b; b = tmp;
231 		tmp = ROLSS(j, aa + F1(bb, cc, dd) + x[RR[j]] + KK(j));
232 		aa = dd; dd = cc; cc = bb; bb = tmp;
233 	}
234 
235 	for(j = 48; j < 64; j++) {
236 		tmp = ROLS( j, a  + F3(b,  c,  d)  + x[R[j]]  + K(j));
237 		a = d; d = c; c = b; b = tmp;
238 		tmp = ROLSS(j, aa + F0(bb, cc, dd) + x[RR[j]] + KK(j));
239 		aa = dd; dd = cc; cc = bb; bb = tmp;
240 	}
241 
242 	tmp = state[1] + c + dd;
243 	state[1] = state[2] + d + aa;
244 	state[2] = state[3] + a + bb;
245 	state[3] = state[0] + b + cc;
246 	state[0] = tmp;
247 
248 	tmp = 0;
249 	ZEND_SECURE_ZERO(x, sizeof(x));
250 }
251 /* }}} */
252 
253 /* {{{ PHP_RIPEMD128Update
254    ripemd128 block update operation. Continues a ripemd128 message-digest
255    operation, processing another message block, and updating the
256    context.
257  */
PHP_RIPEMD128Update(PHP_RIPEMD128_CTX * context,const unsigned char * input,size_t inputLen)258 PHP_HASH_API void PHP_RIPEMD128Update(PHP_RIPEMD128_CTX * context, const unsigned char *input, size_t inputLen)
259 {
260 	unsigned int i, index, partLen;
261 
262 	/* Compute number of bytes mod 64 */
263 	index = (unsigned int) ((context->count[0] >> 3) & 0x3F);
264 
265 	/* Update number of bits */
266 	if ((context->count[0] += ((uint32_t) inputLen << 3)) < ((uint32_t) inputLen << 3)) {
267 		context->count[1]++;
268 	}
269 	context->count[1] += ((uint32_t) inputLen >> 29);
270 
271 	partLen = 64 - index;
272 
273 	/* Transform as many times as possible.
274 	 */
275 	if (inputLen >= partLen) {
276 		memcpy((unsigned char*) & context->buffer[index], (unsigned char*) input, partLen);
277 		RIPEMD128Transform(context->state, context->buffer);
278 
279 		for (i = partLen; i + 63 < inputLen; i += 64) {
280 			RIPEMD128Transform(context->state, &input[i]);
281 		}
282 
283 		index = 0;
284 	} else {
285 		i = 0;
286 	}
287 
288 	/* Buffer remaining input */
289 	memcpy((unsigned char*) & context->buffer[index], (unsigned char*) & input[i], inputLen - i);
290 }
291 /* }}} */
292 
293 /* {{{ RIPEMD256Transform
294  * ripemd256 basic transformation. Transforms state based on block.
295  */
RIPEMD256Transform(uint32_t state[8],const unsigned char block[64])296 static void RIPEMD256Transform(uint32_t state[8], const unsigned char block[64])
297 {
298 	uint32_t a  = state[0], b  = state[1], c  = state[2], d  = state[3];
299 	uint32_t aa = state[4], bb = state[5], cc = state[6], dd = state[7];
300 	uint32_t tmp, x[16];
301 	int j;
302 
303 	RIPEMDDecode(x, block, 64);
304 
305 	for(j = 0; j < 16; j++) {
306 		tmp = ROLS( j, a  + F0(b,  c,  d)  + x[R[j]]  + K(j));
307 		a = d; d = c; c = b; b = tmp;
308 		tmp = ROLSS(j, aa + F3(bb, cc, dd) + x[RR[j]] + KK(j));
309 		aa = dd; dd = cc; cc = bb; bb = tmp;
310 	}
311 	tmp = a; a = aa; aa = tmp;
312 
313 	for(j = 16; j < 32; j++) {
314 		tmp = ROLS( j, a  + F1(b,  c,  d)  + x[R[j]]  + K(j));
315 		a = d; d = c; c = b; b = tmp;
316 		tmp = ROLSS(j, aa + F2(bb, cc, dd) + x[RR[j]] + KK(j));
317 		aa = dd; dd = cc; cc = bb; bb = tmp;
318 	}
319 	tmp = b; b = bb; bb = tmp;
320 
321 	for(j = 32; j < 48; j++) {
322 		tmp = ROLS( j, a  + F2(b,  c,  d)  + x[R[j]]  + K(j));
323 		a = d; d = c; c = b; b = tmp;
324 		tmp = ROLSS(j, aa + F1(bb, cc, dd) + x[RR[j]] + KK(j));
325 		aa = dd; dd = cc; cc = bb; bb = tmp;
326 	}
327 	tmp = c; c = cc; cc = tmp;
328 
329 	for(j = 48; j < 64; j++) {
330 		tmp = ROLS( j, a  + F3(b,  c,  d)  + x[R[j]]  + K(j));
331 		a = d; d = c; c = b; b = tmp;
332 		tmp = ROLSS(j, aa + F0(bb, cc, dd) + x[RR[j]] + KK(j));
333 		aa = dd; dd = cc; cc = bb; bb = tmp;
334 	}
335 	tmp = d; d = dd; dd = tmp;
336 
337 	state[0] += a;
338 	state[1] += b;
339 	state[2] += c;
340 	state[3] += d;
341 	state[4] += aa;
342 	state[5] += bb;
343 	state[6] += cc;
344 	state[7] += dd;
345 
346 	tmp = 0;
347 	ZEND_SECURE_ZERO(x, sizeof(x));
348 }
349 /* }}} */
350 
351 /* {{{ PHP_RIPEMD256Update
352    ripemd256 block update operation. Continues a ripemd256 message-digest
353    operation, processing another message block, and updating the
354    context.
355  */
PHP_RIPEMD256Update(PHP_RIPEMD256_CTX * context,const unsigned char * input,size_t inputLen)356 PHP_HASH_API void PHP_RIPEMD256Update(PHP_RIPEMD256_CTX * context, const unsigned char *input, size_t inputLen)
357 {
358 	unsigned int i, index, partLen;
359 
360 	/* Compute number of bytes mod 64 */
361 	index = (unsigned int) ((context->count[0] >> 3) & 0x3F);
362 
363 	/* Update number of bits */
364 	if ((context->count[0] += ((uint32_t) inputLen << 3)) < ((uint32_t) inputLen << 3)) {
365 		context->count[1]++;
366 	}
367 	context->count[1] += ((uint32_t) inputLen >> 29);
368 
369 	partLen = 64 - index;
370 
371 	/* Transform as many times as possible.
372 	 */
373 	if (inputLen >= partLen) {
374 		memcpy((unsigned char*) & context->buffer[index], (unsigned char*) input, partLen);
375 		RIPEMD256Transform(context->state, context->buffer);
376 
377 		for (i = partLen; i + 63 < inputLen; i += 64) {
378 			RIPEMD256Transform(context->state, &input[i]);
379 		}
380 
381 		index = 0;
382 	} else {
383 		i = 0;
384 	}
385 
386 	/* Buffer remaining input */
387 	memcpy((unsigned char*) & context->buffer[index], (unsigned char*) & input[i], inputLen - i);
388 }
389 /* }}} */
390 
391 /* {{{ RIPEMD160Transform
392  * ripemd160 basic transformation. Transforms state based on block.
393  */
RIPEMD160Transform(uint32_t state[5],const unsigned char block[64])394 static void RIPEMD160Transform(uint32_t state[5], const unsigned char block[64])
395 {
396 	uint32_t a  = state[0], b  = state[1], c  = state[2], d  = state[3], e  = state[4];
397 	uint32_t aa = state[0], bb = state[1], cc = state[2], dd = state[3], ee = state[4];
398 	uint32_t tmp, x[16];
399 	int j;
400 
401 	RIPEMDDecode(x, block, 64);
402 
403 	for(j = 0; j < 16; j++) {
404 		tmp = ROLS( j, a  + F0(b,  c,  d)  + x[R[j]]  + K(j)) + e;
405 		a = e; e = d; d = ROL(10, c); c = b; b = tmp;
406 		tmp = ROLSS(j, aa + F4(bb, cc, dd) + x[RR[j]] + KK160(j)) + ee;
407 		aa = ee; ee = dd; dd = ROL(10, cc); cc = bb; bb = tmp;
408 	}
409 
410 	for(j = 16; j < 32; j++) {
411 		tmp = ROLS( j, a  + F1(b,  c,  d)  + x[R[j]]  + K(j)) + e;
412 		a = e; e = d; d = ROL(10, c); c = b; b = tmp;
413 		tmp = ROLSS(j, aa + F3(bb, cc, dd) + x[RR[j]] + KK160(j)) + ee;
414 		aa = ee; ee = dd; dd = ROL(10, cc); cc = bb; bb = tmp;
415 	}
416 
417 	for(j = 32; j < 48; j++) {
418 		tmp = ROLS( j, a  + F2(b,  c,  d)  + x[R[j]]  + K(j)) + e;
419 		a = e; e = d; d = ROL(10, c); c = b; b = tmp;
420 		tmp = ROLSS(j, aa + F2(bb, cc, dd) + x[RR[j]] + KK160(j)) + ee;
421 		aa = ee; ee = dd; dd = ROL(10, cc); cc = bb; bb = tmp;
422 	}
423 
424 	for(j = 48; j < 64; j++) {
425 		tmp = ROLS( j, a  + F3(b,  c,  d)  + x[R[j]]  + K(j)) + e;
426 		a = e; e = d; d = ROL(10, c); c = b; b = tmp;
427 		tmp = ROLSS(j, aa + F1(bb, cc, dd) + x[RR[j]] + KK160(j)) + ee;
428 		aa = ee; ee = dd; dd = ROL(10, cc); cc = bb; bb = tmp;
429 	}
430 
431 	for(j = 64; j < 80; j++) {
432 		tmp = ROLS( j, a  + F4(b,  c,  d)  + x[R[j]]  + K(j)) + e;
433 		a = e; e = d; d = ROL(10, c); c = b; b = tmp;
434 		tmp = ROLSS(j, aa + F0(bb, cc, dd) + x[RR[j]] + KK160(j)) + ee;
435 		aa = ee; ee = dd; dd = ROL(10, cc); cc = bb; bb = tmp;
436 	}
437 
438 	tmp = state[1] + c + dd;
439 	state[1] = state[2] + d + ee;
440 	state[2] = state[3] + e + aa;
441 	state[3] = state[4] + a + bb;
442 	state[4] = state[0] + b + cc;
443 	state[0] = tmp;
444 
445 	tmp = 0;
446 	ZEND_SECURE_ZERO(x, sizeof(x));
447 }
448 /* }}} */
449 
450 /* {{{ PHP_RIPEMD160Update
451    ripemd160 block update operation. Continues a ripemd160 message-digest
452    operation, processing another message block, and updating the
453    context.
454  */
PHP_RIPEMD160Update(PHP_RIPEMD160_CTX * context,const unsigned char * input,size_t inputLen)455 PHP_HASH_API void PHP_RIPEMD160Update(PHP_RIPEMD160_CTX * context, const unsigned char *input, size_t inputLen)
456 {
457 	unsigned int i, index, partLen;
458 
459 	/* Compute number of bytes mod 64 */
460 	index = (unsigned int) ((context->count[0] >> 3) & 0x3F);
461 
462 	/* Update number of bits */
463 	if ((context->count[0] += ((uint32_t) inputLen << 3)) < ((uint32_t) inputLen << 3)) {
464 		context->count[1]++;
465 	}
466 	context->count[1] += ((uint32_t) inputLen >> 29);
467 
468 	partLen = 64 - index;
469 
470 	/* Transform as many times as possible.
471 	 */
472 	if (inputLen >= partLen) {
473 		memcpy((unsigned char*) & context->buffer[index], (unsigned char*) input, partLen);
474 		RIPEMD160Transform(context->state, context->buffer);
475 
476 		for (i = partLen; i + 63 < inputLen; i += 64) {
477 			RIPEMD160Transform(context->state, &input[i]);
478 		}
479 
480 		index = 0;
481 	} else {
482 		i = 0;
483 	}
484 
485 	/* Buffer remaining input */
486 	memcpy((unsigned char*) & context->buffer[index], (unsigned char*) & input[i], inputLen - i);
487 }
488 /* }}} */
489 
490 /* {{{ RIPEMD320Transform
491  * ripemd320 basic transformation. Transforms state based on block.
492  */
RIPEMD320Transform(uint32_t state[10],const unsigned char block[64])493 static void RIPEMD320Transform(uint32_t state[10], const unsigned char block[64])
494 {
495 	uint32_t a  = state[0], b  = state[1], c  = state[2], d  = state[3], e  = state[4];
496 	uint32_t aa = state[5], bb = state[6], cc = state[7], dd = state[8], ee = state[9];
497 	uint32_t tmp, x[16];
498 	int j;
499 
500 	RIPEMDDecode(x, block, 64);
501 
502 	for(j = 0; j < 16; j++) {
503 		tmp = ROLS( j, a  + F0(b,  c,  d)  + x[R[j]]  + K(j)) + e;
504 		a = e; e = d; d = ROL(10, c); c = b; b = tmp;
505 		tmp = ROLSS(j, aa + F4(bb, cc, dd) + x[RR[j]] + KK160(j)) + ee;
506 		aa = ee; ee = dd; dd = ROL(10, cc); cc = bb; bb = tmp;
507 	}
508 	tmp = b; b = bb; bb = tmp;
509 
510 	for(j = 16; j < 32; j++) {
511 		tmp = ROLS( j, a  + F1(b,  c,  d)  + x[R[j]]  + K(j)) + e;
512 		a = e; e = d; d = ROL(10, c); c = b; b = tmp;
513 		tmp = ROLSS(j, aa + F3(bb, cc, dd) + x[RR[j]] + KK160(j)) + ee;
514 		aa = ee; ee = dd; dd = ROL(10, cc); cc = bb; bb = tmp;
515 	}
516 	tmp = d; d = dd; dd = tmp;
517 
518 	for(j = 32; j < 48; j++) {
519 		tmp = ROLS( j, a  + F2(b,  c,  d)  + x[R[j]]  + K(j)) + e;
520 		a = e; e = d; d = ROL(10, c); c = b; b = tmp;
521 		tmp = ROLSS(j, aa + F2(bb, cc, dd) + x[RR[j]] + KK160(j)) + ee;
522 		aa = ee; ee = dd; dd = ROL(10, cc); cc = bb; bb = tmp;
523 	}
524 	tmp = a; a = aa; aa = tmp;
525 
526 	for(j = 48; j < 64; j++) {
527 		tmp = ROLS( j, a  + F3(b,  c,  d)  + x[R[j]]  + K(j)) + e;
528 		a = e; e = d; d = ROL(10, c); c = b; b = tmp;
529 		tmp = ROLSS(j, aa + F1(bb, cc, dd) + x[RR[j]] + KK160(j)) + ee;
530 		aa = ee; ee = dd; dd = ROL(10, cc); cc = bb; bb = tmp;
531 	}
532 	tmp = c; c = cc; cc = tmp;
533 
534 	for(j = 64; j < 80; j++) {
535 		tmp = ROLS( j, a  + F4(b,  c,  d)  + x[R[j]]  + K(j)) + e;
536 		a = e; e = d; d = ROL(10, c); c = b; b = tmp;
537 		tmp = ROLSS(j, aa + F0(bb, cc, dd) + x[RR[j]] + KK160(j)) + ee;
538 		aa = ee; ee = dd; dd = ROL(10, cc); cc = bb; bb = tmp;
539 	}
540 	tmp = e; e = ee; ee = tmp;
541 
542 	state[0] += a;
543 	state[1] += b;
544 	state[2] += c;
545 	state[3] += d;
546 	state[4] += e;
547 	state[5] += aa;
548 	state[6] += bb;
549 	state[7] += cc;
550 	state[8] += dd;
551 	state[9] += ee;
552 
553 	tmp = 0;
554 	ZEND_SECURE_ZERO(x, sizeof(x));
555 }
556 /* }}} */
557 
558 /* {{{ PHP_RIPEMD320Update
559    ripemd320 block update operation. Continues a ripemd320 message-digest
560    operation, processing another message block, and updating the
561    context.
562  */
PHP_RIPEMD320Update(PHP_RIPEMD320_CTX * context,const unsigned char * input,size_t inputLen)563 PHP_HASH_API void PHP_RIPEMD320Update(PHP_RIPEMD320_CTX * context, const unsigned char *input, size_t inputLen)
564 {
565 	unsigned int i, index, partLen;
566 
567 	/* Compute number of bytes mod 64 */
568 	index = (unsigned int) ((context->count[0] >> 3) & 0x3F);
569 
570 	/* Update number of bits */
571 	if ((context->count[0] += ((uint32_t) inputLen << 3)) < ((uint32_t) inputLen << 3)) {
572 		context->count[1]++;
573 	}
574 	context->count[1] += ((uint32_t) inputLen >> 29);
575 
576 	partLen = 64 - index;
577 
578 	/* Transform as many times as possible.
579 	 */
580 	if (inputLen >= partLen) {
581 		memcpy((unsigned char*) & context->buffer[index], (unsigned char*) input, partLen);
582 		RIPEMD320Transform(context->state, context->buffer);
583 
584 		for (i = partLen; i + 63 < inputLen; i += 64) {
585 			RIPEMD320Transform(context->state, &input[i]);
586 		}
587 
588 		index = 0;
589 	} else {
590 		i = 0;
591 	}
592 
593 	/* Buffer remaining input */
594 	memcpy((unsigned char*) & context->buffer[index], (unsigned char*) & input[i], inputLen - i);
595 }
596 /* }}} */
597 
598 static const unsigned char PADDING[64] =
599 {
600 	0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
601 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
602 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
603 };
604 
605 /* {{{ RIPEMDEncode
606    Encodes input (uint32_t) into output (unsigned char). Assumes len is
607    a multiple of 4.
608  */
RIPEMDEncode(unsigned char * output,uint32_t * input,unsigned int len)609 static void RIPEMDEncode(unsigned char *output, uint32_t *input, unsigned int len)
610 {
611 	unsigned int i, j;
612 
613 	for (i = 0, j = 0; j < len; i++, j += 4) {
614 		output[j + 3] = (unsigned char) ((input[i] >> 24) & 0xff);
615 		output[j + 2] = (unsigned char) ((input[i] >> 16) & 0xff);
616 		output[j + 1] = (unsigned char) ((input[i] >> 8) & 0xff);
617 		output[j + 0] = (unsigned char) (input[i] & 0xff);
618 	}
619 }
620 /* }}} */
621 
622 /* {{{ PHP_RIPEMD128Final
623    ripemd128 finalization. Ends a ripemd128 message-digest operation, writing the
624    the message digest and zeroizing the context.
625  */
PHP_RIPEMD128Final(unsigned char digest[16],PHP_RIPEMD128_CTX * context)626 PHP_HASH_API void PHP_RIPEMD128Final(unsigned char digest[16], PHP_RIPEMD128_CTX * context)
627 {
628 	unsigned char bits[8];
629 	unsigned int index, padLen;
630 
631 	/* Save number of bits */
632 	bits[0] = (unsigned char) (context->count[0] & 0xFF);
633 	bits[1] = (unsigned char) ((context->count[0] >> 8) & 0xFF);
634 	bits[2] = (unsigned char) ((context->count[0] >> 16) & 0xFF);
635 	bits[3] = (unsigned char) ((context->count[0] >> 24) & 0xFF);
636 	bits[4] = (unsigned char) (context->count[1] & 0xFF);
637 	bits[5] = (unsigned char) ((context->count[1] >> 8) & 0xFF);
638 	bits[6] = (unsigned char) ((context->count[1] >> 16) & 0xFF);
639 	bits[7] = (unsigned char) ((context->count[1] >> 24) & 0xFF);
640 
641 	/* Pad out to 56 mod 64.
642 	 */
643 	index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
644 	padLen = (index < 56) ? (56 - index) : (120 - index);
645 	PHP_RIPEMD128Update(context, PADDING, padLen);
646 
647 	/* Append length (before padding) */
648 	PHP_RIPEMD128Update(context, bits, 8);
649 
650 	/* Store state in digest */
651 	RIPEMDEncode(digest, context->state, 16);
652 
653 	/* Zeroize sensitive information.
654 	 */
655 	ZEND_SECURE_ZERO((unsigned char*) context, sizeof(*context));
656 }
657 /* }}} */
658 
659 /* {{{ PHP_RIPEMD256Final
660    ripemd256 finalization. Ends a ripemd256 message-digest operation, writing the
661    the message digest and zeroizing the context.
662  */
PHP_RIPEMD256Final(unsigned char digest[32],PHP_RIPEMD256_CTX * context)663 PHP_HASH_API void PHP_RIPEMD256Final(unsigned char digest[32], PHP_RIPEMD256_CTX * context)
664 {
665 	unsigned char bits[8];
666 	unsigned int index, padLen;
667 
668 	/* Save number of bits */
669 	bits[0] = (unsigned char) (context->count[0] & 0xFF);
670 	bits[1] = (unsigned char) ((context->count[0] >> 8) & 0xFF);
671 	bits[2] = (unsigned char) ((context->count[0] >> 16) & 0xFF);
672 	bits[3] = (unsigned char) ((context->count[0] >> 24) & 0xFF);
673 	bits[4] = (unsigned char) (context->count[1] & 0xFF);
674 	bits[5] = (unsigned char) ((context->count[1] >> 8) & 0xFF);
675 	bits[6] = (unsigned char) ((context->count[1] >> 16) & 0xFF);
676 	bits[7] = (unsigned char) ((context->count[1] >> 24) & 0xFF);
677 
678 	/* Pad out to 56 mod 64.
679 	 */
680 	index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
681 	padLen = (index < 56) ? (56 - index) : (120 - index);
682 	PHP_RIPEMD256Update(context, PADDING, padLen);
683 
684 	/* Append length (before padding) */
685 	PHP_RIPEMD256Update(context, bits, 8);
686 
687 	/* Store state in digest */
688 	RIPEMDEncode(digest, context->state, 32);
689 
690 	/* Zeroize sensitive information.
691 	 */
692 	ZEND_SECURE_ZERO((unsigned char*) context, sizeof(*context));
693 }
694 /* }}} */
695 
696 /* {{{ PHP_RIPEMD160Final
697    ripemd160 finalization. Ends a ripemd160 message-digest operation, writing the
698    the message digest and zeroizing the context.
699  */
PHP_RIPEMD160Final(unsigned char digest[20],PHP_RIPEMD160_CTX * context)700 PHP_HASH_API void PHP_RIPEMD160Final(unsigned char digest[20], PHP_RIPEMD160_CTX * context)
701 {
702 	unsigned char bits[8];
703 	unsigned int index, padLen;
704 
705 	/* Save number of bits */
706 	bits[0] = (unsigned char) (context->count[0] & 0xFF);
707 	bits[1] = (unsigned char) ((context->count[0] >> 8) & 0xFF);
708 	bits[2] = (unsigned char) ((context->count[0] >> 16) & 0xFF);
709 	bits[3] = (unsigned char) ((context->count[0] >> 24) & 0xFF);
710 	bits[4] = (unsigned char) (context->count[1] & 0xFF);
711 	bits[5] = (unsigned char) ((context->count[1] >> 8) & 0xFF);
712 	bits[6] = (unsigned char) ((context->count[1] >> 16) & 0xFF);
713 	bits[7] = (unsigned char) ((context->count[1] >> 24) & 0xFF);
714 
715 	/* Pad out to 56 mod 64.
716 	 */
717 	index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
718 	padLen = (index < 56) ? (56 - index) : (120 - index);
719 	PHP_RIPEMD160Update(context, PADDING, padLen);
720 
721 	/* Append length (before padding) */
722 	PHP_RIPEMD160Update(context, bits, 8);
723 
724 	/* Store state in digest */
725 	RIPEMDEncode(digest, context->state, 20);
726 
727 	/* Zeroize sensitive information.
728 	 */
729 	ZEND_SECURE_ZERO((unsigned char*) context, sizeof(*context));
730 }
731 /* }}} */
732 
733 /* {{{ PHP_RIPEMD320Final
734    ripemd320 finalization. Ends a ripemd320 message-digest operation, writing the
735    the message digest and zeroizing the context.
736  */
PHP_RIPEMD320Final(unsigned char digest[40],PHP_RIPEMD320_CTX * context)737 PHP_HASH_API void PHP_RIPEMD320Final(unsigned char digest[40], PHP_RIPEMD320_CTX * context)
738 {
739 	unsigned char bits[8];
740 	unsigned int index, padLen;
741 
742 	/* Save number of bits */
743 	bits[0] = (unsigned char) (context->count[0] & 0xFF);
744 	bits[1] = (unsigned char) ((context->count[0] >> 8) & 0xFF);
745 	bits[2] = (unsigned char) ((context->count[0] >> 16) & 0xFF);
746 	bits[3] = (unsigned char) ((context->count[0] >> 24) & 0xFF);
747 	bits[4] = (unsigned char) (context->count[1] & 0xFF);
748 	bits[5] = (unsigned char) ((context->count[1] >> 8) & 0xFF);
749 	bits[6] = (unsigned char) ((context->count[1] >> 16) & 0xFF);
750 	bits[7] = (unsigned char) ((context->count[1] >> 24) & 0xFF);
751 
752 	/* Pad out to 56 mod 64.
753 	 */
754 	index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
755 	padLen = (index < 56) ? (56 - index) : (120 - index);
756 	PHP_RIPEMD320Update(context, PADDING, padLen);
757 
758 	/* Append length (before padding) */
759 	PHP_RIPEMD320Update(context, bits, 8);
760 
761 	/* Store state in digest */
762 	RIPEMDEncode(digest, context->state, 40);
763 
764 	/* Zeroize sensitive information.
765 	 */
766 	ZEND_SECURE_ZERO((unsigned char*) context, sizeof(*context));
767 }
768 /* }}} */
769