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