File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / ext / standard / md5.c
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jun 15 20:03:57 2014 UTC (10 years, 1 month ago) by misho
Branches: php, MAIN
CVS tags: v5_4_29, HEAD
php 5.4.29

    1: /*
    2:    +----------------------------------------------------------------------+
    3:    | PHP Version 5                                                        |
    4:    +----------------------------------------------------------------------+
    5:    | Copyright (c) 1997-2014 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: md5.c,v 1.1.1.4 2014/06/15 20:03:57 misho Exp $ */
   22: 
   23: #include "php.h"
   24: #include "md5.h"
   25: 
   26: PHPAPI void make_digest(char *md5str, const unsigned char *digest) /* {{{ */
   27: {
   28: 	make_digest_ex(md5str, digest, 16);
   29: }
   30: /* }}} */
   31: 
   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 */
   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 */
   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:  */
  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: 
  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: 
  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: 
  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: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>