xref: /PHP-5.5/ext/hash/hash_md.c (revision 73c1be26)
1 /*
2   +----------------------------------------------------------------------+
3   | PHP Version 5                                                        |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 1997-2015 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   | Taken from: ext/standard/md5.c                                       |
16   +----------------------------------------------------------------------+
17 */
18 
19 /* $Id$ */
20 
21 #include "php_hash.h"
22 #include "php_hash_md.h"
23 
24 const php_hash_ops php_hash_md5_ops = {
25 	(php_hash_init_func_t) PHP_MD5Init,
26 	(php_hash_update_func_t) PHP_MD5Update,
27 	(php_hash_final_func_t) PHP_MD5Final,
28 	(php_hash_copy_func_t) php_hash_copy,
29 	16,
30 	64,
31 	sizeof(PHP_MD5_CTX)
32 };
33 
34 const php_hash_ops php_hash_md4_ops = {
35 	(php_hash_init_func_t) PHP_MD4Init,
36 	(php_hash_update_func_t) PHP_MD4Update,
37 	(php_hash_final_func_t) PHP_MD4Final,
38 	(php_hash_copy_func_t) php_hash_copy,
39 	16,
40 	64,
41 	sizeof(PHP_MD4_CTX)
42 };
43 
44 const php_hash_ops php_hash_md2_ops = {
45 	(php_hash_init_func_t) PHP_MD2Init,
46 	(php_hash_update_func_t) PHP_MD2Update,
47 	(php_hash_final_func_t) PHP_MD2Final,
48 	(php_hash_copy_func_t) php_hash_copy,
49 	16,
50 	16,
51 	sizeof(PHP_MD2_CTX)
52 };
53 
54 /* MD common stuff */
55 
56 static const unsigned char PADDING[64] =
57 {
58 	0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
59 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
60 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
61 };
62 
63 /* {{{ Encode
64    Encodes input (php_hash_uint32) into output (unsigned char). Assumes len is
65    a multiple of 4.
66  */
Encode(unsigned char * output,php_hash_uint32 * input,unsigned int len)67 static void Encode(unsigned char *output, php_hash_uint32 *input, unsigned int len)
68 {
69 	unsigned int i, j;
70 
71 	for (i = 0, j = 0; j < len; i++, j += 4) {
72 		output[j] = (unsigned char) (input[i] & 0xff);
73 		output[j + 1] = (unsigned char) ((input[i] >> 8) & 0xff);
74 		output[j + 2] = (unsigned char) ((input[i] >> 16) & 0xff);
75 		output[j + 3] = (unsigned char) ((input[i] >> 24) & 0xff);
76 	}
77 }
78 /* }}} */
79 
80 /* {{{ Decode
81    Decodes input (unsigned char) into output (php_hash_uint32). Assumes len is
82    a multiple of 4.
83  */
Decode(php_hash_uint32 * output,const unsigned char * input,unsigned int len)84 static void Decode(php_hash_uint32 *output, const unsigned char *input, unsigned int len)
85 {
86 	unsigned int i, j;
87 
88 	for (i = 0, j = 0; j < len; i++, j += 4)
89 		output[i] = ((php_hash_uint32) input[j]) | (((php_hash_uint32) input[j + 1]) << 8) |
90 			(((php_hash_uint32) input[j + 2]) << 16) | (((php_hash_uint32) input[j + 3]) << 24);
91 }
92 /* }}} */
93 
94 #ifdef PHP_HASH_MD5_NOT_IN_CORE
95 
96 /* MD5 */
97 
make_digest(char * md5str,unsigned char * digest)98 PHP_HASH_API void make_digest(char *md5str, unsigned char *digest)
99 {
100 	php_hash_bin2hex(md5str, digest, 16);
101 	md5str[32] = '\0';
102 }
103 
104 /* {{{ proto string md5(string str, [ bool raw_output])
105    Calculate the md5 hash of a string */
PHP_NAMED_FUNCTION(php_if_md5)106 PHP_NAMED_FUNCTION(php_if_md5)
107 {
108 	char *arg;
109 	int arg_len;
110 	zend_bool raw_output = 0;
111 	char md5str[33];
112 	PHP_MD5_CTX context;
113 	unsigned char digest[16];
114 
115 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &arg, &arg_len, &raw_output) == FAILURE) {
116 		return;
117 	}
118 
119 	md5str[0] = '\0';
120 	PHP_MD5Init(&context);
121 	PHP_MD5Update(&context, arg, arg_len);
122 	PHP_MD5Final(digest, &context);
123 	if (raw_output) {
124 		RETURN_STRINGL(digest, 16, 1);
125 	} else {
126 		make_digest(md5str, digest);
127 		RETVAL_STRING(md5str, 1);
128 	}
129 
130 }
131 /* }}} */
132 
133 /* {{{ proto string md5_file(string filename [, bool raw_output])
134    Calculate the md5 hash of given filename */
PHP_NAMED_FUNCTION(php_if_md5_file)135 PHP_NAMED_FUNCTION(php_if_md5_file)
136 {
137 	char          *arg;
138 	int           arg_len;
139 	zend_bool raw_output = 0;
140 	char          md5str[33];
141 	unsigned char buf[1024];
142 	unsigned char digest[16];
143 	PHP_MD5_CTX   context;
144 	int           n;
145 	php_stream    *stream;
146 
147 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|b", &arg, &arg_len, &raw_output) == FAILURE) {
148 		return;
149 	}
150 
151 	stream = php_stream_open_wrapper(arg, "rb", REPORT_ERRORS, NULL);
152 	if (!stream) {
153 		RETURN_FALSE;
154 	}
155 
156 	PHP_MD5Init(&context);
157 
158 	while ((n = php_stream_read(stream, buf, sizeof(buf))) > 0) {
159 		PHP_MD5Update(&context, buf, n);
160 	}
161 
162 	PHP_MD5Final(digest, &context);
163 
164 	php_stream_close(stream);
165 
166 	if (n<0) {
167 		RETURN_FALSE;
168 	}
169 
170 	if (raw_output) {
171 		RETURN_STRINGL(digest, 16, 1);
172 	} else {
173 		make_digest(md5str, digest);
174 		RETVAL_STRING(md5str, 1);
175 	}
176 }
177 /* }}} */
178 
179 /*
180  * The remaining code is the reference MD5 code (md5c.c) from rfc1321
181  */
182 /* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
183  */
184 
185 /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
186    rights reserved.
187 
188    License to copy and use this software is granted provided that it
189    is identified as the "RSA Data Security, Inc. MD5 Message-Digest
190    Algorithm" in all material mentioning or referencing this software
191    or this function.
192 
193    License is also granted to make and use derivative works provided
194    that such works are identified as "derived from the RSA Data
195    Security, Inc. MD5 Message-Digest Algorithm" in all material
196    mentioning or referencing the derived work.
197 
198    RSA Data Security, Inc. makes no representations concerning either
199    the merchantability of this software or the suitability of this
200    software for any particular purpose. It is provided "as is"
201    without express or implied warranty of any kind.
202 
203    These notices must be retained in any copies of any part of this
204    documentation and/or software.
205  */
206 
207 /* Constants for MD5Transform routine.
208  */
209 
210 #define S11 7
211 #define S12 12
212 #define S13 17
213 #define S14 22
214 #define S21 5
215 #define S22 9
216 #define S23 14
217 #define S24 20
218 #define S31 4
219 #define S32 11
220 #define S33 16
221 #define S34 23
222 #define S41 6
223 #define S42 10
224 #define S43 15
225 #define S44 21
226 
227 static void MD5Transform(php_hash_uint32[4], const unsigned char[64]);
228 
229 /* F, G, H and I are basic MD5 functions.
230  */
231 #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
232 #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
233 #define H(x, y, z) ((x) ^ (y) ^ (z))
234 #define I(x, y, z) ((y) ^ ((x) | (~z)))
235 
236 /* ROTATE_LEFT rotates x left n bits.
237  */
238 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
239 
240 /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
241    Rotation is separate from addition to prevent recomputation.
242  */
243 #define FF(a, b, c, d, x, s, ac) { \
244  (a) += F ((b), (c), (d)) + (x) + (php_hash_uint32)(ac); \
245  (a) = ROTATE_LEFT ((a), (s)); \
246  (a) += (b); \
247   }
248 #define GG(a, b, c, d, x, s, ac) { \
249  (a) += G ((b), (c), (d)) + (x) + (php_hash_uint32)(ac); \
250  (a) = ROTATE_LEFT ((a), (s)); \
251  (a) += (b); \
252   }
253 #define HH(a, b, c, d, x, s, ac) { \
254  (a) += H ((b), (c), (d)) + (x) + (php_hash_uint32)(ac); \
255  (a) = ROTATE_LEFT ((a), (s)); \
256  (a) += (b); \
257   }
258 #define II(a, b, c, d, x, s, ac) { \
259  (a) += I ((b), (c), (d)) + (x) + (php_hash_uint32)(ac); \
260  (a) = ROTATE_LEFT ((a), (s)); \
261  (a) += (b); \
262   }
263 
264 /* {{{ PHP_MD5Init
265  * MD5 initialization. Begins an MD5 operation, writing a new context.
266  */
PHP_MD5Init(PHP_MD5_CTX * context)267 PHP_HASH_API void PHP_MD5Init(PHP_MD5_CTX * context)
268 {
269 	context->count[0] = context->count[1] = 0;
270 	/* Load magic initialization constants.
271 	 */
272 	context->state[0] = 0x67452301;
273 	context->state[1] = 0xefcdab89;
274 	context->state[2] = 0x98badcfe;
275 	context->state[3] = 0x10325476;
276 }
277 /* }}} */
278 
279 /* {{{ PHP_MD5Update
280    MD5 block update operation. Continues an MD5 message-digest
281    operation, processing another message block, and updating the
282    context.
283  */
PHP_MD5Update(PHP_MD5_CTX * context,const unsigned char * input,unsigned int inputLen)284 PHP_HASH_API void PHP_MD5Update(PHP_MD5_CTX * context, const unsigned char *input,
285 			   unsigned int inputLen)
286 {
287 	unsigned int i, index, partLen;
288 
289 	/* Compute number of bytes mod 64 */
290 	index = (unsigned int) ((context->count[0] >> 3) & 0x3F);
291 
292 	/* Update number of bits */
293 	if ((context->count[0] += ((php_hash_uint32) inputLen << 3))
294 		< ((php_hash_uint32) inputLen << 3))
295 		context->count[1]++;
296 	context->count[1] += ((php_hash_uint32) inputLen >> 29);
297 
298 	partLen = 64 - index;
299 
300 	/* Transform as many times as possible.
301 	 */
302 	if (inputLen >= partLen) {
303 		memcpy
304 			((unsigned char*) & context->buffer[index], (unsigned char*) input, partLen);
305 		MD5Transform(context->state, context->buffer);
306 
307 		for (i = partLen; i + 63 < inputLen; i += 64)
308 			MD5Transform(context->state, &input[i]);
309 
310 		index = 0;
311 	} else
312 		i = 0;
313 
314 	/* Buffer remaining input */
315 	memcpy
316 		((unsigned char*) & context->buffer[index], (unsigned char*) & input[i],
317 		 inputLen - i);
318 }
319 /* }}} */
320 
321 /* {{{ PHP_MD5Final
322    MD5 finalization. Ends an MD5 message-digest operation, writing the
323    the message digest and zeroizing the context.
324  */
PHP_MD5Final(unsigned char digest[16],PHP_MD5_CTX * context)325 PHP_HASH_API void PHP_MD5Final(unsigned char digest[16], PHP_MD5_CTX * context)
326 {
327 	unsigned char bits[8];
328 	unsigned int index, padLen;
329 
330 	/* Save number of bits */
331 	Encode(bits, context->count, 8);
332 
333 	/* Pad out to 56 mod 64.
334 	 */
335 	index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
336 	padLen = (index < 56) ? (56 - index) : (120 - index);
337 	PHP_MD5Update(context, PADDING, padLen);
338 
339 	/* Append length (before padding) */
340 	PHP_MD5Update(context, bits, 8);
341 
342 	/* Store state in digest */
343 	Encode(digest, context->state, 16);
344 
345 	/* Zeroize sensitive information.
346 	 */
347 	memset((unsigned char*) context, 0, sizeof(*context));
348 }
349 /* }}} */
350 
351 /* {{{ MD5Transform
352  * MD5 basic transformation. Transforms state based on block.
353  */
MD5Transform(state,block)354 static void MD5Transform(state, block)
355 php_hash_uint32 state[4];
356 const unsigned char block[64];
357 {
358 	php_hash_uint32 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
359 
360 	Decode(x, block, 64);
361 
362 	/* Round 1 */
363 	FF(a, b, c, d, x[0], S11, 0xd76aa478);	/* 1 */
364 	FF(d, a, b, c, x[1], S12, 0xe8c7b756);	/* 2 */
365 	FF(c, d, a, b, x[2], S13, 0x242070db);	/* 3 */
366 	FF(b, c, d, a, x[3], S14, 0xc1bdceee);	/* 4 */
367 	FF(a, b, c, d, x[4], S11, 0xf57c0faf);	/* 5 */
368 	FF(d, a, b, c, x[5], S12, 0x4787c62a);	/* 6 */
369 	FF(c, d, a, b, x[6], S13, 0xa8304613);	/* 7 */
370 	FF(b, c, d, a, x[7], S14, 0xfd469501);	/* 8 */
371 	FF(a, b, c, d, x[8], S11, 0x698098d8);	/* 9 */
372 	FF(d, a, b, c, x[9], S12, 0x8b44f7af);	/* 10 */
373 	FF(c, d, a, b, x[10], S13, 0xffff5bb1);		/* 11 */
374 	FF(b, c, d, a, x[11], S14, 0x895cd7be);		/* 12 */
375 	FF(a, b, c, d, x[12], S11, 0x6b901122);		/* 13 */
376 	FF(d, a, b, c, x[13], S12, 0xfd987193);		/* 14 */
377 	FF(c, d, a, b, x[14], S13, 0xa679438e);		/* 15 */
378 	FF(b, c, d, a, x[15], S14, 0x49b40821);		/* 16 */
379 
380 	/* Round 2 */
381 	GG(a, b, c, d, x[1], S21, 0xf61e2562);	/* 17 */
382 	GG(d, a, b, c, x[6], S22, 0xc040b340);	/* 18 */
383 	GG(c, d, a, b, x[11], S23, 0x265e5a51);		/* 19 */
384 	GG(b, c, d, a, x[0], S24, 0xe9b6c7aa);	/* 20 */
385 	GG(a, b, c, d, x[5], S21, 0xd62f105d);	/* 21 */
386 	GG(d, a, b, c, x[10], S22, 0x2441453);	/* 22 */
387 	GG(c, d, a, b, x[15], S23, 0xd8a1e681);		/* 23 */
388 	GG(b, c, d, a, x[4], S24, 0xe7d3fbc8);	/* 24 */
389 	GG(a, b, c, d, x[9], S21, 0x21e1cde6);	/* 25 */
390 	GG(d, a, b, c, x[14], S22, 0xc33707d6);		/* 26 */
391 	GG(c, d, a, b, x[3], S23, 0xf4d50d87);	/* 27 */
392 	GG(b, c, d, a, x[8], S24, 0x455a14ed);	/* 28 */
393 	GG(a, b, c, d, x[13], S21, 0xa9e3e905);		/* 29 */
394 	GG(d, a, b, c, x[2], S22, 0xfcefa3f8);	/* 30 */
395 	GG(c, d, a, b, x[7], S23, 0x676f02d9);	/* 31 */
396 	GG(b, c, d, a, x[12], S24, 0x8d2a4c8a);		/* 32 */
397 
398 	/* Round 3 */
399 	HH(a, b, c, d, x[5], S31, 0xfffa3942);	/* 33 */
400 	HH(d, a, b, c, x[8], S32, 0x8771f681);	/* 34 */
401 	HH(c, d, a, b, x[11], S33, 0x6d9d6122);		/* 35 */
402 	HH(b, c, d, a, x[14], S34, 0xfde5380c);		/* 36 */
403 	HH(a, b, c, d, x[1], S31, 0xa4beea44);	/* 37 */
404 	HH(d, a, b, c, x[4], S32, 0x4bdecfa9);	/* 38 */
405 	HH(c, d, a, b, x[7], S33, 0xf6bb4b60);	/* 39 */
406 	HH(b, c, d, a, x[10], S34, 0xbebfbc70);		/* 40 */
407 	HH(a, b, c, d, x[13], S31, 0x289b7ec6);		/* 41 */
408 	HH(d, a, b, c, x[0], S32, 0xeaa127fa);	/* 42 */
409 	HH(c, d, a, b, x[3], S33, 0xd4ef3085);	/* 43 */
410 	HH(b, c, d, a, x[6], S34, 0x4881d05);	/* 44 */
411 	HH(a, b, c, d, x[9], S31, 0xd9d4d039);	/* 45 */
412 	HH(d, a, b, c, x[12], S32, 0xe6db99e5);		/* 46 */
413 	HH(c, d, a, b, x[15], S33, 0x1fa27cf8);		/* 47 */
414 	HH(b, c, d, a, x[2], S34, 0xc4ac5665);	/* 48 */
415 
416 	/* Round 4 */
417 	II(a, b, c, d, x[0], S41, 0xf4292244);	/* 49 */
418 	II(d, a, b, c, x[7], S42, 0x432aff97);	/* 50 */
419 	II(c, d, a, b, x[14], S43, 0xab9423a7);		/* 51 */
420 	II(b, c, d, a, x[5], S44, 0xfc93a039);	/* 52 */
421 	II(a, b, c, d, x[12], S41, 0x655b59c3);		/* 53 */
422 	II(d, a, b, c, x[3], S42, 0x8f0ccc92);	/* 54 */
423 	II(c, d, a, b, x[10], S43, 0xffeff47d);		/* 55 */
424 	II(b, c, d, a, x[1], S44, 0x85845dd1);	/* 56 */
425 	II(a, b, c, d, x[8], S41, 0x6fa87e4f);	/* 57 */
426 	II(d, a, b, c, x[15], S42, 0xfe2ce6e0);		/* 58 */
427 	II(c, d, a, b, x[6], S43, 0xa3014314);	/* 59 */
428 	II(b, c, d, a, x[13], S44, 0x4e0811a1);		/* 60 */
429 	II(a, b, c, d, x[4], S41, 0xf7537e82);	/* 61 */
430 	II(d, a, b, c, x[11], S42, 0xbd3af235);		/* 62 */
431 	II(c, d, a, b, x[2], S43, 0x2ad7d2bb);	/* 63 */
432 	II(b, c, d, a, x[9], S44, 0xeb86d391);	/* 64 */
433 
434 	state[0] += a;
435 	state[1] += b;
436 	state[2] += c;
437 	state[3] += d;
438 
439 	/* Zeroize sensitive information. */
440 	memset((unsigned char*) x, 0, sizeof(x));
441 }
442 /* }}} */
443 
444 #endif /* PHP_HASH_MD5_NOT_IN_CORE */
445 
446 /* MD4 */
447 
448 #define MD4_F(x,y,z)			((z) ^ ((x) & ((y) ^ (z))))
449 #define MD4_G(x,y,z)			(((x) & ((y) | (z))) | ((y) & (z)))
450 #define MD4_H(x,y,z)			((x) ^ (y) ^ (z))
451 
452 #define ROTL32(s,v)				(((v) << (s)) | ((v) >> (32 - (s))))
453 
454 #define MD4_R1(a,b,c,d,k,s)		a = ROTL32(s, a + MD4_F(b,c,d) + x[k])
455 #define MD4_R2(a,b,c,d,k,s)		a = ROTL32(s, a + MD4_G(b,c,d) + x[k] + 0x5A827999)
456 #define MD4_R3(a,b,c,d,k,s)		a = ROTL32(s, a + MD4_H(b,c,d) + x[k] + 0x6ED9EBA1)
457 
MD4Transform(php_hash_uint32 state[4],const unsigned char block[64])458 static void MD4Transform(php_hash_uint32 state[4], const unsigned char block[64])
459 {
460 	php_hash_uint32 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
461 
462 	Decode(x, block, 64);
463 
464 	/* Round 1 */
465 	MD4_R1(a,b,c,d, 0, 3);
466 	MD4_R1(d,a,b,c, 1, 7);
467 	MD4_R1(c,d,a,b, 2,11);
468 	MD4_R1(b,c,d,a, 3,19);
469 	MD4_R1(a,b,c,d, 4, 3);
470 	MD4_R1(d,a,b,c, 5, 7);
471 	MD4_R1(c,d,a,b, 6,11);
472 	MD4_R1(b,c,d,a, 7,19);
473 	MD4_R1(a,b,c,d, 8, 3);
474 	MD4_R1(d,a,b,c, 9, 7);
475 	MD4_R1(c,d,a,b,10,11);
476 	MD4_R1(b,c,d,a,11,19);
477 	MD4_R1(a,b,c,d,12, 3);
478 	MD4_R1(d,a,b,c,13, 7);
479 	MD4_R1(c,d,a,b,14,11);
480 	MD4_R1(b,c,d,a,15,19);
481 
482 	/* Round 2 */
483 	MD4_R2(a,b,c,d, 0, 3);
484 	MD4_R2(d,a,b,c, 4, 5);
485 	MD4_R2(c,d,a,b, 8, 9);
486 	MD4_R2(b,c,d,a,12,13);
487 	MD4_R2(a,b,c,d, 1, 3);
488 	MD4_R2(d,a,b,c, 5, 5);
489 	MD4_R2(c,d,a,b, 9, 9);
490 	MD4_R2(b,c,d,a,13,13);
491 	MD4_R2(a,b,c,d, 2, 3);
492 	MD4_R2(d,a,b,c, 6, 5);
493 	MD4_R2(c,d,a,b,10, 9);
494 	MD4_R2(b,c,d,a,14,13);
495 	MD4_R2(a,b,c,d, 3, 3);
496 	MD4_R2(d,a,b,c, 7, 5);
497 	MD4_R2(c,d,a,b,11, 9);
498 	MD4_R2(b,c,d,a,15,13);
499 
500 	/* Round 3 */
501 	MD4_R3(a,b,c,d, 0, 3);
502 	MD4_R3(d,a,b,c, 8, 9);
503 	MD4_R3(c,d,a,b, 4,11);
504 	MD4_R3(b,c,d,a,12,15);
505 	MD4_R3(a,b,c,d, 2, 3);
506 	MD4_R3(d,a,b,c,10, 9);
507 	MD4_R3(c,d,a,b, 6,11);
508 	MD4_R3(b,c,d,a,14,15);
509 	MD4_R3(a,b,c,d, 1, 3);
510 	MD4_R3(d,a,b,c, 9, 9);
511 	MD4_R3(c,d,a,b, 5,11);
512 	MD4_R3(b,c,d,a,13,15);
513 	MD4_R3(a,b,c,d, 3, 3);
514 	MD4_R3(d,a,b,c,11, 9);
515 	MD4_R3(c,d,a,b, 7,11);
516 	MD4_R3(b,c,d,a,15,15);
517 
518 	state[0] += a;
519 	state[1] += b;
520 	state[2] += c;
521 	state[3] += d;
522 }
523 
524 /* {{{ PHP_MD4Init
525  * MD4 initialization. Begins an MD4 operation, writing a new context.
526  */
PHP_MD4Init(PHP_MD4_CTX * context)527 PHP_HASH_API void PHP_MD4Init(PHP_MD4_CTX * context)
528 {
529 	context->count[0] = context->count[1] = 0;
530 	/* Load magic initialization constants.
531 	 */
532 	context->state[0] = 0x67452301;
533 	context->state[1] = 0xefcdab89;
534 	context->state[2] = 0x98badcfe;
535 	context->state[3] = 0x10325476;
536 }
537 /* }}} */
538 
539 /* {{{ PHP_MD4Update
540    MD4 block update operation. Continues an MD4 message-digest
541    operation, processing another message block, and updating the
542    context.
543  */
PHP_MD4Update(PHP_MD4_CTX * context,const unsigned char * input,unsigned int inputLen)544 PHP_HASH_API void PHP_MD4Update(PHP_MD4_CTX * context, const unsigned char *input, unsigned int inputLen)
545 {
546 	unsigned int i, index, partLen;
547 
548 	/* Compute number of bytes mod 64 */
549 	index = (unsigned int) ((context->count[0] >> 3) & 0x3F);
550 
551 	/* Update number of bits */
552 	if ((context->count[0] += ((php_hash_uint32) inputLen << 3))
553 		< ((php_hash_uint32) inputLen << 3))
554 		context->count[1]++;
555 	context->count[1] += ((php_hash_uint32) inputLen >> 29);
556 
557 	partLen = 64 - index;
558 
559 	/* Transform as many times as possible.
560 	 */
561 	if (inputLen >= partLen) {
562 		memcpy((unsigned char*) & context->buffer[index], (unsigned char*) input, partLen);
563 		MD4Transform(context->state, context->buffer);
564 
565 		for (i = partLen; i + 63 < inputLen; i += 64) {
566 			MD4Transform(context->state, &input[i]);
567 		}
568 
569 		index = 0;
570 	} else {
571 		i = 0;
572 	}
573 
574 	/* Buffer remaining input */
575 	memcpy((unsigned char*) & context->buffer[index], (unsigned char*) & input[i], inputLen - i);
576 }
577 /* }}} */
578 
579 /* {{{ PHP_MD4Final
580    MD4 finalization. Ends an MD4 message-digest operation, writing the
581    the message digest and zeroizing the context.
582  */
PHP_MD4Final(unsigned char digest[16],PHP_MD4_CTX * context)583 PHP_HASH_API void PHP_MD4Final(unsigned char digest[16], PHP_MD4_CTX * context)
584 {
585 	unsigned char bits[8];
586 	unsigned int index, padLen;
587 
588 	/* Save number of bits */
589 	Encode(bits, context->count, 8);
590 
591 	/* Pad out to 56 mod 64.
592 	 */
593 	index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
594 	padLen = (index < 56) ? (56 - index) : (120 - index);
595 	PHP_MD4Update(context, PADDING, padLen);
596 
597 	/* Append length (before padding) */
598 	PHP_MD4Update(context, bits, 8);
599 
600 	/* Store state in digest */
601 	Encode(digest, context->state, 16);
602 
603 	/* Zeroize sensitive information.
604 	 */
605 	memset((unsigned char*) context, 0, sizeof(*context));
606 }
607 /* }}} */
608 
609 /* MD2 */
610 
611 static const unsigned char MD2_S[256] = {
612 	 41,  46,  67, 201, 162, 216, 124,   1,  61,  54,  84, 161, 236, 240,   6,  19,
613 	 98, 167,   5, 243, 192, 199, 115, 140, 152, 147,  43, 217, 188,  76, 130, 202,
614 	 30, 155,  87,  60, 253, 212, 224,  22, 103,  66, 111,  24, 138,  23, 229,  18,
615 	190,  78, 196, 214, 218, 158, 222,  73, 160, 251, 245, 142, 187,  47, 238, 122,
616 	169, 104, 121, 145,  21, 178,   7,  63, 148, 194,  16, 137,  11,  34,  95,  33,
617 	128, 127,  93, 154,  90, 144,  50,  39,  53,  62, 204, 231, 191, 247, 151,   3,
618 	255,  25,  48, 179,  72, 165, 181, 209, 215,  94, 146,  42, 172,  86, 170, 198,
619 	 79, 184,  56, 210, 150, 164, 125, 182, 118, 252, 107, 226, 156, 116,   4, 241,
620 	 69, 157, 112,  89, 100, 113, 135,  32, 134,  91, 207, 101, 230,  45, 168,   2,
621 	 27,  96,  37, 173, 174, 176, 185, 246,  28,  70,  97, 105,  52,  64, 126,  15,
622 	 85,  71, 163,  35, 221,  81, 175,  58, 195,  92, 249, 206, 186, 197, 234,  38,
623 	 44,  83,  13, 110, 133,  40, 132,   9, 211, 223, 205, 244,  65, 129,  77,  82,
624 	106, 220,  55, 200, 108, 193, 171, 250,  36, 225, 123,   8,  12, 189, 177,  74,
625 	120, 136, 149, 139, 227,  99, 232, 109, 233, 203, 213, 254,  59,   0,  29,  57,
626 	242, 239, 183,  14, 102,  88, 208, 228, 166, 119, 114, 248, 235, 117,  75,  10,
627 	 49,  68,  80, 180, 143, 237,  31,  26, 219, 153, 141,  51, 159,  17, 131,  20 };
628 
PHP_MD2Init(PHP_MD2_CTX * context)629 PHP_HASH_API void PHP_MD2Init(PHP_MD2_CTX *context)
630 {
631 	memset(context, 0, sizeof(PHP_MD2_CTX));
632 }
633 
MD2_Transform(PHP_MD2_CTX * context,const unsigned char * block)634 static void MD2_Transform(PHP_MD2_CTX *context, const unsigned char *block)
635 {
636 	unsigned char i,j,t = 0;
637 
638 	for(i = 0; i < 16; i++) {
639 		context->state[16+i] = block[i];
640 		context->state[32+i] = (context->state[16+i] ^ context->state[i]);
641 	}
642 
643 	for(i = 0; i < 18; i++) {
644 		for(j = 0; j < 48; j++) {
645 			t = context->state[j] = context->state[j] ^ MD2_S[t];
646 		}
647 		t += i;
648 	}
649 
650 	/* Update checksum -- must be after transform to avoid fouling up last message block */
651 	t = context->checksum[15];
652 	for(i = 0; i < 16; i++) {
653 		t = context->checksum[i] ^= MD2_S[block[i] ^ t];
654 	}
655 }
656 
PHP_MD2Update(PHP_MD2_CTX * context,const unsigned char * buf,unsigned int len)657 PHP_HASH_API void PHP_MD2Update(PHP_MD2_CTX *context, const unsigned char *buf, unsigned int len)
658 {
659 	const unsigned char *p = buf, *e = buf + len;
660 
661 	if (context->in_buffer) {
662 		if (context->in_buffer + len < 16) {
663 			/* Not enough for block, just pass into buffer */
664 			memcpy(context->buffer + context->in_buffer, p, len);
665 			context->in_buffer += len;
666 			return;
667 		}
668 		/* Put buffered data together with inbound for a single block */
669 		memcpy(context->buffer + context->in_buffer, p, 16 - context->in_buffer);
670 		MD2_Transform(context, context->buffer);
671 		p += 16 - context->in_buffer;
672 		context->in_buffer = 0;
673 	}
674 
675 	/* Process as many whole blocks as remain */
676 	while ((p + 16) <= e) {
677 		MD2_Transform(context, p);
678 		p += 16;
679 	}
680 
681 	/* Copy remaining data to buffer */
682 	if (p < e) {
683 		memcpy(context->buffer, p, e - p);
684 		context->in_buffer = e - p;
685 	}
686 }
687 
PHP_MD2Final(unsigned char output[16],PHP_MD2_CTX * context)688 PHP_HASH_API void PHP_MD2Final(unsigned char output[16], PHP_MD2_CTX *context)
689 {
690 	memset(context->buffer + context->in_buffer, 16 - context->in_buffer, 16 - context->in_buffer);
691 	MD2_Transform(context, context->buffer);
692 	MD2_Transform(context, context->checksum);
693 
694 	memcpy(output, context->state, 16);
695 }
696 
697 /*
698  * Local variables:
699  * tab-width: 4
700  * c-basic-offset: 4
701  * End:
702  * vim600: sw=4 ts=4 fdm=marker
703  * vim<600: sw=4 ts=4
704  */
705