Annotation of embedaddon/php/ext/standard/md5.c, revision 1.1
1.1 ! misho 1: /*
! 2: +----------------------------------------------------------------------+
! 3: | PHP Version 5 |
! 4: +----------------------------------------------------------------------+
! 5: | Copyright (c) 1997-2012 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 321634 2012-01-01 13:15:04Z felipe $ */
! 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, "s|b", &arg, &arg_len, &raw_output) == FAILURE) {
! 89: return;
! 90: }
! 91:
! 92: stream = php_stream_open_wrapper(arg, "rb", REPORT_ERRORS | ENFORCE_SAFE_MODE, 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>