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