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