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