1 : /*
2 : +----------------------------------------------------------------------+
3 : | PHP Version 5 |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1997-2009 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 : | Author: Lachlan Roche |
16 : +----------------------------------------------------------------------+
17 : */
18 :
19 : /* $Id: md5.c 272374 2008-12-31 11:17:49Z sebastian $ */
20 :
21 : /*
22 : * md5.c - Copyright 1997 Lachlan Roche
23 : * md5_file() added by Alessandro Astarita <aleast@capri.it>
24 : */
25 :
26 : #include "php.h"
27 : #include "md5.h"
28 :
29 : PHPAPI void make_digest(char *md5str, unsigned char *digest)
30 8 : {
31 8 : make_digest_ex(md5str, digest, 16);
32 8 : }
33 :
34 : PHPAPI void make_digest_ex(char *md5str, unsigned char *digest, int len)
35 300477 : {
36 : static const char hexits[17] = "0123456789abcdef";
37 : int i;
38 :
39 5108349 : for (i = 0; i < len; i++) {
40 4807872 : md5str[i * 2] = hexits[digest[i] >> 4];
41 4807872 : md5str[(i * 2) + 1] = hexits[digest[i] & 0x0F];
42 : }
43 300477 : md5str[len * 2] = '\0';
44 300477 : }
45 :
46 : /* {{{ proto string md5(string str, [ bool raw_output])
47 : Calculate the md5 hash of a string */
48 : PHP_NAMED_FUNCTION(php_if_md5)
49 300403 : {
50 : char *arg;
51 : int arg_len;
52 300403 : zend_bool raw_output = 0;
53 : char md5str[33];
54 : PHP_MD5_CTX context;
55 : unsigned char digest[16];
56 :
57 300403 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &arg, &arg_len, &raw_output) == FAILURE) {
58 2 : return;
59 : }
60 :
61 300401 : md5str[0] = '\0';
62 300401 : PHP_MD5Init(&context);
63 300401 : PHP_MD5Update(&context, arg, arg_len);
64 300401 : PHP_MD5Final(digest, &context);
65 300401 : if (raw_output) {
66 8 : RETURN_STRINGL(digest, 16, 1);
67 : } else {
68 300393 : make_digest_ex(md5str, digest, 16);
69 300393 : RETVAL_STRING(md5str, 1);
70 : }
71 :
72 : }
73 : /* }}} */
74 :
75 : /* {{{ proto string md5_file(string filename [, bool raw_output])
76 : Calculate the md5 hash of given filename */
77 : PHP_NAMED_FUNCTION(php_if_md5_file)
78 24 : {
79 : char *arg;
80 : int arg_len;
81 24 : zend_bool raw_output = 0;
82 : char md5str[33];
83 : unsigned char buf[1024];
84 : unsigned char digest[16];
85 : PHP_MD5_CTX context;
86 : int n;
87 : php_stream *stream;
88 :
89 24 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &arg, &arg_len, &raw_output) == FAILURE) {
90 2 : return;
91 : }
92 :
93 22 : stream = php_stream_open_wrapper(arg, "rb", REPORT_ERRORS | ENFORCE_SAFE_MODE, NULL);
94 22 : if (!stream) {
95 4 : RETURN_FALSE;
96 : }
97 :
98 18 : PHP_MD5Init(&context);
99 :
100 52885 : while ((n = php_stream_read(stream, buf, sizeof(buf))) > 0) {
101 52849 : PHP_MD5Update(&context, buf, n);
102 : }
103 :
104 18 : PHP_MD5Final(digest, &context);
105 :
106 18 : php_stream_close(stream);
107 :
108 18 : if (n<0) {
109 0 : RETURN_FALSE;
110 : }
111 :
112 18 : if (raw_output) {
113 2 : RETURN_STRINGL(digest, 16, 1);
114 : } else {
115 16 : make_digest_ex(md5str, digest, 16);
116 16 : RETVAL_STRING(md5str, 1);
117 : }
118 : }
119 : /* }}} */
120 :
121 : /*
122 : * The remaining code is the reference MD5 code (md5c.c) from rfc1321
123 : */
124 : /* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
125 : */
126 :
127 : /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
128 : rights reserved.
129 :
130 : License to copy and use this software is granted provided that it
131 : is identified as the "RSA Data Security, Inc. MD5 Message-Digest
132 : Algorithm" in all material mentioning or referencing this software
133 : or this function.
134 :
135 : License is also granted to make and use derivative works provided
136 : that such works are identified as "derived from the RSA Data
137 : Security, Inc. MD5 Message-Digest Algorithm" in all material
138 : mentioning or referencing the derived work.
139 :
140 : RSA Data Security, Inc. makes no representations concerning either
141 : the merchantability of this software or the suitability of this
142 : software for any particular purpose. It is provided "as is"
143 : without express or implied warranty of any kind.
144 :
145 : These notices must be retained in any copies of any part of this
146 : documentation and/or software.
147 : */
148 :
149 : /* Constants for MD5Transform routine.
150 : */
151 :
152 :
153 : #define S11 7
154 : #define S12 12
155 : #define S13 17
156 : #define S14 22
157 : #define S21 5
158 : #define S22 9
159 : #define S23 14
160 : #define S24 20
161 : #define S31 4
162 : #define S32 11
163 : #define S33 16
164 : #define S34 23
165 : #define S41 6
166 : #define S42 10
167 : #define S43 15
168 : #define S44 21
169 :
170 : static void MD5Transform(php_uint32[4], const unsigned char[64]);
171 : static void Encode(unsigned char *, php_uint32 *, unsigned int);
172 : static void Decode(php_uint32 *, const unsigned char *, unsigned int);
173 :
174 : static unsigned char PADDING[64] =
175 : {
176 : 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
177 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
178 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
179 : };
180 :
181 : /* F, G, H and I are basic MD5 functions.
182 : */
183 : #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
184 : #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
185 : #define H(x, y, z) ((x) ^ (y) ^ (z))
186 : #define I(x, y, z) ((y) ^ ((x) | (~z)))
187 :
188 : /* ROTATE_LEFT rotates x left n bits.
189 : */
190 : #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
191 :
192 : /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
193 : Rotation is separate from addition to prevent recomputation.
194 : */
195 : #define FF(a, b, c, d, x, s, ac) { \
196 : (a) += F ((b), (c), (d)) + (x) + (php_uint32)(ac); \
197 : (a) = ROTATE_LEFT ((a), (s)); \
198 : (a) += (b); \
199 : }
200 : #define GG(a, b, c, d, x, s, ac) { \
201 : (a) += G ((b), (c), (d)) + (x) + (php_uint32)(ac); \
202 : (a) = ROTATE_LEFT ((a), (s)); \
203 : (a) += (b); \
204 : }
205 : #define HH(a, b, c, d, x, s, ac) { \
206 : (a) += H ((b), (c), (d)) + (x) + (php_uint32)(ac); \
207 : (a) = ROTATE_LEFT ((a), (s)); \
208 : (a) += (b); \
209 : }
210 : #define II(a, b, c, d, x, s, ac) { \
211 : (a) += I ((b), (c), (d)) + (x) + (php_uint32)(ac); \
212 : (a) = ROTATE_LEFT ((a), (s)); \
213 : (a) += (b); \
214 : }
215 :
216 : /* {{{ PHP_MD5Init
217 : * MD5 initialization. Begins an MD5 operation, writing a new context.
218 : */
219 : PHPAPI void PHP_MD5Init(PHP_MD5_CTX * context)
220 300690 : {
221 300690 : context->count[0] = context->count[1] = 0;
222 : /* Load magic initialization constants.
223 : */
224 300690 : context->state[0] = 0x67452301;
225 300690 : context->state[1] = 0xefcdab89;
226 300690 : context->state[2] = 0x98badcfe;
227 300690 : context->state[3] = 0x10325476;
228 300690 : }
229 : /* }}} */
230 :
231 : /* {{{ PHP_MD5Update
232 : MD5 block update operation. Continues an MD5 message-digest
233 : operation, processing another message block, and updating the
234 : context.
235 : */
236 : PHPAPI void PHP_MD5Update(PHP_MD5_CTX * context, const unsigned char *input,
237 : unsigned int inputLen)
238 954880 : {
239 : unsigned int i, index, partLen;
240 :
241 : /* Compute number of bytes mod 64 */
242 954880 : index = (unsigned int) ((context->count[0] >> 3) & 0x3F);
243 :
244 : /* Update number of bits */
245 954880 : if ((context->count[0] += ((php_uint32) inputLen << 3))
246 : < ((php_uint32) inputLen << 3))
247 0 : context->count[1]++;
248 954880 : context->count[1] += ((php_uint32) inputLen >> 29);
249 :
250 954880 : partLen = 64 - index;
251 :
252 : /* Transform as many times as possible.
253 : */
254 954880 : if (inputLen >= partLen) {
255 353917 : memcpy
256 : ((unsigned char*) & context->buffer[index], (unsigned char*) input, partLen);
257 353917 : MD5Transform(context->state, context->buffer);
258 :
259 1168772 : for (i = partLen; i + 63 < inputLen; i += 64)
260 814855 : MD5Transform(context->state, &input[i]);
261 :
262 353917 : index = 0;
263 : } else
264 600963 : i = 0;
265 :
266 : /* Buffer remaining input */
267 954880 : memcpy
268 : ((unsigned char*) & context->buffer[index], (unsigned char*) & input[i],
269 : inputLen - i);
270 954880 : }
271 : /* }}} */
272 :
273 : /* {{{ PHP_MD5Final
274 : MD5 finalization. Ends an MD5 message-digest operation, writing the
275 : the message digest and zeroizing the context.
276 : */
277 : PHPAPI void PHP_MD5Final(unsigned char digest[16], PHP_MD5_CTX * context)
278 300678 : {
279 : unsigned char bits[8];
280 : unsigned int index, padLen;
281 :
282 : /* Save number of bits */
283 300678 : Encode(bits, context->count, 8);
284 :
285 : /* Pad out to 56 mod 64.
286 : */
287 300678 : index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
288 300678 : padLen = (index < 56) ? (56 - index) : (120 - index);
289 300678 : PHP_MD5Update(context, PADDING, padLen);
290 :
291 : /* Append length (before padding) */
292 300678 : PHP_MD5Update(context, bits, 8);
293 :
294 : /* Store state in digest */
295 300678 : Encode(digest, context->state, 16);
296 :
297 : /* Zeroize sensitive information.
298 : */
299 300678 : memset((unsigned char*) context, 0, sizeof(*context));
300 300678 : }
301 : /* }}} */
302 :
303 : /* {{{ MD5Transform
304 : * MD5 basic transformation. Transforms state based on block.
305 : */
306 : static void MD5Transform(state, block)
307 : php_uint32 state[4];
308 : const unsigned char block[64];
309 1168772 : {
310 1168772 : php_uint32 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
311 :
312 1168772 : Decode(x, block, 64);
313 :
314 : /* Round 1 */
315 1168772 : FF(a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */
316 1168772 : FF(d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */
317 1168772 : FF(c, d, a, b, x[2], S13, 0x242070db); /* 3 */
318 1168772 : FF(b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */
319 1168772 : FF(a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */
320 1168772 : FF(d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */
321 1168772 : FF(c, d, a, b, x[6], S13, 0xa8304613); /* 7 */
322 1168772 : FF(b, c, d, a, x[7], S14, 0xfd469501); /* 8 */
323 1168772 : FF(a, b, c, d, x[8], S11, 0x698098d8); /* 9 */
324 1168772 : FF(d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */
325 1168772 : FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
326 1168772 : FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
327 1168772 : FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
328 1168772 : FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
329 1168772 : FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
330 1168772 : FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
331 :
332 : /* Round 2 */
333 1168772 : GG(a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */
334 1168772 : GG(d, a, b, c, x[6], S22, 0xc040b340); /* 18 */
335 1168772 : GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
336 1168772 : GG(b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */
337 1168772 : GG(a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */
338 1168772 : GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */
339 1168772 : GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
340 1168772 : GG(b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */
341 1168772 : GG(a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */
342 1168772 : GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
343 1168772 : GG(c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */
344 1168772 : GG(b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */
345 1168772 : GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
346 1168772 : GG(d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */
347 1168772 : GG(c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */
348 1168772 : GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
349 :
350 : /* Round 3 */
351 1168772 : HH(a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */
352 1168772 : HH(d, a, b, c, x[8], S32, 0x8771f681); /* 34 */
353 1168772 : HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
354 1168772 : HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
355 1168772 : HH(a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */
356 1168772 : HH(d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */
357 1168772 : HH(c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */
358 1168772 : HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
359 1168772 : HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
360 1168772 : HH(d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */
361 1168772 : HH(c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */
362 1168772 : HH(b, c, d, a, x[6], S34, 0x4881d05); /* 44 */
363 1168772 : HH(a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */
364 1168772 : HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
365 1168772 : HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
366 1168772 : HH(b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */
367 :
368 : /* Round 4 */
369 1168772 : II(a, b, c, d, x[0], S41, 0xf4292244); /* 49 */
370 1168772 : II(d, a, b, c, x[7], S42, 0x432aff97); /* 50 */
371 1168772 : II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
372 1168772 : II(b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */
373 1168772 : II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
374 1168772 : II(d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */
375 1168772 : II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
376 1168772 : II(b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */
377 1168772 : II(a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */
378 1168772 : II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
379 1168772 : II(c, d, a, b, x[6], S43, 0xa3014314); /* 59 */
380 1168772 : II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
381 1168772 : II(a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */
382 1168772 : II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
383 1168772 : II(c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */
384 1168772 : II(b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */
385 :
386 1168772 : state[0] += a;
387 1168772 : state[1] += b;
388 1168772 : state[2] += c;
389 1168772 : state[3] += d;
390 :
391 : /* Zeroize sensitive information. */
392 1168772 : memset((unsigned char*) x, 0, sizeof(x));
393 1168772 : }
394 : /* }}} */
395 :
396 : /* {{{ Encode
397 : Encodes input (php_uint32) into output (unsigned char). Assumes len is
398 : a multiple of 4.
399 : */
400 : static void Encode(output, input, len)
401 : unsigned char *output;
402 : php_uint32 *input;
403 : unsigned int len;
404 601356 : {
405 : unsigned int i, j;
406 :
407 2405424 : for (i = 0, j = 0; j < len; i++, j += 4) {
408 1804068 : output[j] = (unsigned char) (input[i] & 0xff);
409 1804068 : output[j + 1] = (unsigned char) ((input[i] >> 8) & 0xff);
410 1804068 : output[j + 2] = (unsigned char) ((input[i] >> 16) & 0xff);
411 1804068 : output[j + 3] = (unsigned char) ((input[i] >> 24) & 0xff);
412 : }
413 601356 : }
414 : /* }}} */
415 :
416 : /* {{{ Decode
417 : Decodes input (unsigned char) into output (php_uint32). Assumes len is
418 : a multiple of 4.
419 : */
420 : static void Decode(output, input, len)
421 : php_uint32 *output;
422 : const unsigned char *input;
423 : unsigned int len;
424 1168772 : {
425 : unsigned int i, j;
426 :
427 19869124 : for (i = 0, j = 0; j < len; i++, j += 4)
428 18700352 : output[i] = ((php_uint32) input[j]) | (((php_uint32) input[j + 1]) << 8) |
429 : (((php_uint32) input[j + 2]) << 16) | (((php_uint32) input[j + 3]) << 24);
430 1168772 : }
431 : /* }}} */
432 :
433 : /*
434 : * Local variables:
435 : * tab-width: 4
436 : * c-basic-offset: 4
437 : * End:
438 : * vim600: sw=4 ts=4 fdm=marker
439 : * vim<600: sw=4 ts=4
440 : */
|