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