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