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