xref: /PHP-5.5/ext/standard/md5.c (revision 73c1be26)
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    | Author: Alexander Peslyak (Solar Designer) <solar at openwall.com>   |
16    |         Lachlan Roche                                                |
17    |         Alessandro Astarita <aleast@capri.it>                        |
18    +----------------------------------------------------------------------+
19 */
20 
21 /* $Id$ */
22 
23 #include "php.h"
24 #include "md5.h"
25 
make_digest(char * md5str,const unsigned char * digest)26 PHPAPI void make_digest(char *md5str, const unsigned char *digest) /* {{{ */
27 {
28 	make_digest_ex(md5str, digest, 16);
29 }
30 /* }}} */
31 
make_digest_ex(char * md5str,const unsigned char * digest,int len)32 PHPAPI void make_digest_ex(char *md5str, const unsigned char *digest, int len) /* {{{ */
33 {
34 	static const char hexits[17] = "0123456789abcdef";
35 	int i;
36 
37 	for (i = 0; i < len; i++) {
38 		md5str[i * 2]       = hexits[digest[i] >> 4];
39 		md5str[(i * 2) + 1] = hexits[digest[i] &  0x0F];
40 	}
41 	md5str[len * 2] = '\0';
42 }
43 /* }}} */
44 
45 /* {{{ proto string md5(string str, [ bool raw_output])
46    Calculate the md5 hash of a string */
PHP_NAMED_FUNCTION(php_if_md5)47 PHP_NAMED_FUNCTION(php_if_md5)
48 {
49 	char *arg;
50 	int arg_len;
51 	zend_bool raw_output = 0;
52 	char md5str[33];
53 	PHP_MD5_CTX context;
54 	unsigned char digest[16];
55 
56 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &arg, &arg_len, &raw_output) == FAILURE) {
57 		return;
58 	}
59 
60 	md5str[0] = '\0';
61 	PHP_MD5Init(&context);
62 	PHP_MD5Update(&context, arg, arg_len);
63 	PHP_MD5Final(digest, &context);
64 	if (raw_output) {
65 		RETURN_STRINGL(digest, 16, 1);
66 	} else {
67 		make_digest_ex(md5str, digest, 16);
68 		RETVAL_STRING(md5str, 1);
69 	}
70 
71 }
72 /* }}} */
73 
74 /* {{{ proto string md5_file(string filename [, bool raw_output])
75    Calculate the md5 hash of given filename */
PHP_NAMED_FUNCTION(php_if_md5_file)76 PHP_NAMED_FUNCTION(php_if_md5_file)
77 {
78 	char          *arg;
79 	int           arg_len;
80 	zend_bool raw_output = 0;
81 	char          md5str[33];
82 	unsigned char buf[1024];
83 	unsigned char digest[16];
84 	PHP_MD5_CTX   context;
85 	int           n;
86 	php_stream    *stream;
87 
88 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|b", &arg, &arg_len, &raw_output) == FAILURE) {
89 		return;
90 	}
91 
92 	stream = php_stream_open_wrapper(arg, "rb", REPORT_ERRORS, NULL);
93 	if (!stream) {
94 		RETURN_FALSE;
95 	}
96 
97 	PHP_MD5Init(&context);
98 
99 	while ((n = php_stream_read(stream, buf, sizeof(buf))) > 0) {
100 		PHP_MD5Update(&context, buf, n);
101 	}
102 
103 	PHP_MD5Final(digest, &context);
104 
105 	php_stream_close(stream);
106 
107 	if (n<0) {
108 		RETURN_FALSE;
109 	}
110 
111 	if (raw_output) {
112 		RETURN_STRINGL(digest, 16, 1);
113 	} else {
114 		make_digest_ex(md5str, digest, 16);
115 		RETVAL_STRING(md5str, 1);
116 	}
117 }
118 /* }}} */
119 
120 /*
121  * This is an OpenSSL-compatible implementation of the RSA Data Security,
122  * Inc. MD5 Message-Digest Algorithm (RFC 1321).
123  *
124  * Written by Solar Designer <solar at openwall.com> in 2001, and placed
125  * in the public domain.  There's absolutely no warranty.
126  *
127  * This differs from Colin Plumb's older public domain implementation in
128  * that no 32-bit integer data type is required, there's no compile-time
129  * endianness configuration, and the function prototypes match OpenSSL's.
130  * The primary goals are portability and ease of use.
131  *
132  * This implementation is meant to be fast, but not as fast as possible.
133  * Some known optimizations are not included to reduce source code size
134  * and avoid compile-time configuration.
135  */
136 
137 #include <string.h>
138 
139 /*
140  * The basic MD5 functions.
141  *
142  * F and G are optimized compared to their RFC 1321 definitions for
143  * architectures that lack an AND-NOT instruction, just like in Colin Plumb's
144  * implementation.
145  */
146 #define F(x, y, z)			((z) ^ ((x) & ((y) ^ (z))))
147 #define G(x, y, z)			((y) ^ ((z) & ((x) ^ (y))))
148 #define H(x, y, z)			((x) ^ (y) ^ (z))
149 #define I(x, y, z)			((y) ^ ((x) | ~(z)))
150 
151 /*
152  * The MD5 transformation for all four rounds.
153  */
154 #define STEP(f, a, b, c, d, x, t, s) \
155 	(a) += f((b), (c), (d)) + (x) + (t); \
156 	(a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
157 	(a) += (b);
158 
159 /*
160  * SET reads 4 input bytes in little-endian byte order and stores them
161  * in a properly aligned word in host byte order.
162  *
163  * The check for little-endian architectures that tolerate unaligned
164  * memory accesses is just an optimization.  Nothing will break if it
165  * doesn't work.
166  */
167 #if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
168 # define SET(n) \
169 	(*(php_uint32 *)&ptr[(n) * 4])
170 # define GET(n) \
171 	SET(n)
172 #else
173 # define SET(n) \
174 	(ctx->block[(n)] = \
175 	(php_uint32)ptr[(n) * 4] | \
176 	((php_uint32)ptr[(n) * 4 + 1] << 8) | \
177 	((php_uint32)ptr[(n) * 4 + 2] << 16) | \
178 	((php_uint32)ptr[(n) * 4 + 3] << 24))
179 # define GET(n) \
180 	(ctx->block[(n)])
181 #endif
182 
183 /*
184  * This processes one or more 64-byte data blocks, but does NOT update
185  * the bit counters.  There are no alignment requirements.
186  */
body(PHP_MD5_CTX * ctx,const void * data,size_t size)187 static const void *body(PHP_MD5_CTX *ctx, const void *data, size_t size)
188 {
189 	const unsigned char *ptr;
190 	php_uint32 a, b, c, d;
191 	php_uint32 saved_a, saved_b, saved_c, saved_d;
192 
193 	ptr = data;
194 
195 	a = ctx->a;
196 	b = ctx->b;
197 	c = ctx->c;
198 	d = ctx->d;
199 
200 	do {
201 		saved_a = a;
202 		saved_b = b;
203 		saved_c = c;
204 		saved_d = d;
205 
206 /* Round 1 */
207 		STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
208 		STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
209 		STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
210 		STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
211 		STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
212 		STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
213 		STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
214 		STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
215 		STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
216 		STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
217 		STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
218 		STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
219 		STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
220 		STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
221 		STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
222 		STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
223 
224 /* Round 2 */
225 		STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
226 		STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
227 		STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
228 		STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
229 		STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
230 		STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
231 		STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
232 		STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
233 		STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
234 		STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
235 		STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
236 		STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
237 		STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
238 		STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
239 		STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
240 		STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
241 
242 /* Round 3 */
243 		STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
244 		STEP(H, d, a, b, c, GET(8), 0x8771f681, 11)
245 		STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
246 		STEP(H, b, c, d, a, GET(14), 0xfde5380c, 23)
247 		STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
248 		STEP(H, d, a, b, c, GET(4), 0x4bdecfa9, 11)
249 		STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
250 		STEP(H, b, c, d, a, GET(10), 0xbebfbc70, 23)
251 		STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
252 		STEP(H, d, a, b, c, GET(0), 0xeaa127fa, 11)
253 		STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
254 		STEP(H, b, c, d, a, GET(6), 0x04881d05, 23)
255 		STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
256 		STEP(H, d, a, b, c, GET(12), 0xe6db99e5, 11)
257 		STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
258 		STEP(H, b, c, d, a, GET(2), 0xc4ac5665, 23)
259 
260 /* Round 4 */
261 		STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
262 		STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
263 		STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
264 		STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
265 		STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
266 		STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
267 		STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
268 		STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
269 		STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
270 		STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
271 		STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
272 		STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
273 		STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
274 		STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
275 		STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
276 		STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
277 
278 		a += saved_a;
279 		b += saved_b;
280 		c += saved_c;
281 		d += saved_d;
282 
283 		ptr += 64;
284 	} while (size -= 64);
285 
286 	ctx->a = a;
287 	ctx->b = b;
288 	ctx->c = c;
289 	ctx->d = d;
290 
291 	return ptr;
292 }
293 
PHP_MD5Init(PHP_MD5_CTX * ctx)294 PHPAPI void PHP_MD5Init(PHP_MD5_CTX *ctx)
295 {
296 	ctx->a = 0x67452301;
297 	ctx->b = 0xefcdab89;
298 	ctx->c = 0x98badcfe;
299 	ctx->d = 0x10325476;
300 
301 	ctx->lo = 0;
302 	ctx->hi = 0;
303 }
304 
PHP_MD5Update(PHP_MD5_CTX * ctx,const void * data,size_t size)305 PHPAPI void PHP_MD5Update(PHP_MD5_CTX *ctx, const void *data, size_t size)
306 {
307 	php_uint32 saved_lo;
308 	php_uint32 used, free;
309 
310 	saved_lo = ctx->lo;
311 	if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo) {
312 		ctx->hi++;
313 	}
314 	ctx->hi += size >> 29;
315 
316 	used = saved_lo & 0x3f;
317 
318 	if (used) {
319 		free = 64 - used;
320 
321 		if (size < free) {
322 			memcpy(&ctx->buffer[used], data, size);
323 			return;
324 		}
325 
326 		memcpy(&ctx->buffer[used], data, free);
327 		data = (unsigned char *)data + free;
328 		size -= free;
329 		body(ctx, ctx->buffer, 64);
330 	}
331 
332 	if (size >= 64) {
333 		data = body(ctx, data, size & ~(size_t)0x3f);
334 		size &= 0x3f;
335 	}
336 
337 	memcpy(ctx->buffer, data, size);
338 }
339 
PHP_MD5Final(unsigned char * result,PHP_MD5_CTX * ctx)340 PHPAPI void PHP_MD5Final(unsigned char *result, PHP_MD5_CTX *ctx)
341 {
342 	php_uint32 used, free;
343 
344 	used = ctx->lo & 0x3f;
345 
346 	ctx->buffer[used++] = 0x80;
347 
348 	free = 64 - used;
349 
350 	if (free < 8) {
351 		memset(&ctx->buffer[used], 0, free);
352 		body(ctx, ctx->buffer, 64);
353 		used = 0;
354 		free = 64;
355 	}
356 
357 	memset(&ctx->buffer[used], 0, free - 8);
358 
359 	ctx->lo <<= 3;
360 	ctx->buffer[56] = ctx->lo;
361 	ctx->buffer[57] = ctx->lo >> 8;
362 	ctx->buffer[58] = ctx->lo >> 16;
363 	ctx->buffer[59] = ctx->lo >> 24;
364 	ctx->buffer[60] = ctx->hi;
365 	ctx->buffer[61] = ctx->hi >> 8;
366 	ctx->buffer[62] = ctx->hi >> 16;
367 	ctx->buffer[63] = ctx->hi >> 24;
368 
369 	body(ctx, ctx->buffer, 64);
370 
371 	result[0] = ctx->a;
372 	result[1] = ctx->a >> 8;
373 	result[2] = ctx->a >> 16;
374 	result[3] = ctx->a >> 24;
375 	result[4] = ctx->b;
376 	result[5] = ctx->b >> 8;
377 	result[6] = ctx->b >> 16;
378 	result[7] = ctx->b >> 24;
379 	result[8] = ctx->c;
380 	result[9] = ctx->c >> 8;
381 	result[10] = ctx->c >> 16;
382 	result[11] = ctx->c >> 24;
383 	result[12] = ctx->d;
384 	result[13] = ctx->d >> 8;
385 	result[14] = ctx->d >> 16;
386 	result[15] = ctx->d >> 24;
387 
388 	memset(ctx, 0, sizeof(*ctx));
389 }
390