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