Back to index

php5  5.3.10
hash_md.c
Go to the documentation of this file.
00001 /*
00002   +----------------------------------------------------------------------+
00003   | PHP Version 5                                                        |
00004   +----------------------------------------------------------------------+
00005   | Copyright (c) 1997-2012 The PHP Group                                |
00006   +----------------------------------------------------------------------+
00007   | This source file is subject to version 3.01 of the PHP license,      |
00008   | that is bundled with this package in the file LICENSE, and is        |
00009   | available through the world-wide-web at the following url:           |
00010   | http://www.php.net/license/3_01.txt                                  |
00011   | If you did not receive a copy of the PHP license and are unable to   |
00012   | obtain it through the world-wide-web, please send a note to          |
00013   | license@php.net so we can mail you a copy immediately.               |
00014   +----------------------------------------------------------------------+
00015   | Taken from: ext/standard/md5.c                                       |
00016   +----------------------------------------------------------------------+
00017 */
00018 
00019 /* $Id: hash_md.c 321634 2012-01-01 13:15:04Z felipe $ */
00020 
00021 #include "php_hash.h"
00022 #include "php_hash_md.h"
00023 
00024 const php_hash_ops php_hash_md5_ops = {
00025        (php_hash_init_func_t) PHP_MD5Init,
00026        (php_hash_update_func_t) PHP_MD5Update,
00027        (php_hash_final_func_t) PHP_MD5Final,
00028        (php_hash_copy_func_t) php_hash_copy,
00029        16,
00030        64,
00031        sizeof(PHP_MD5_CTX)
00032 };
00033 
00034 const php_hash_ops php_hash_md4_ops = {
00035        (php_hash_init_func_t) PHP_MD4Init,
00036        (php_hash_update_func_t) PHP_MD4Update,
00037        (php_hash_final_func_t) PHP_MD4Final,
00038        (php_hash_copy_func_t) php_hash_copy,
00039        16,
00040        64,
00041        sizeof(PHP_MD4_CTX)
00042 };
00043 
00044 const php_hash_ops php_hash_md2_ops = {
00045        (php_hash_init_func_t) PHP_MD2Init,
00046        (php_hash_update_func_t) PHP_MD2Update,
00047        (php_hash_final_func_t) PHP_MD2Final,
00048        (php_hash_copy_func_t) php_hash_copy,
00049        16,
00050        16,
00051        sizeof(PHP_MD2_CTX)
00052 };
00053 
00054 /* MD common stuff */
00055 
00056 static const unsigned char PADDING[64] =
00057 {
00058        0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00059        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00060        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00061 };
00062 
00063 /* {{{ Encode
00064    Encodes input (php_hash_uint32) into output (unsigned char). Assumes len is
00065    a multiple of 4.
00066  */
00067 static void Encode(unsigned char *output, php_hash_uint32 *input, unsigned int len)
00068 {
00069        unsigned int i, j;
00070 
00071        for (i = 0, j = 0; j < len; i++, j += 4) {
00072               output[j] = (unsigned char) (input[i] & 0xff);
00073               output[j + 1] = (unsigned char) ((input[i] >> 8) & 0xff);
00074               output[j + 2] = (unsigned char) ((input[i] >> 16) & 0xff);
00075               output[j + 3] = (unsigned char) ((input[i] >> 24) & 0xff);
00076        }
00077 }
00078 /* }}} */
00079 
00080 /* {{{ Decode
00081    Decodes input (unsigned char) into output (php_hash_uint32). Assumes len is
00082    a multiple of 4.
00083  */
00084 static void Decode(php_hash_uint32 *output, const unsigned char *input, unsigned int len)
00085 {
00086        unsigned int i, j;
00087 
00088        for (i = 0, j = 0; j < len; i++, j += 4)
00089               output[i] = ((php_hash_uint32) input[j]) | (((php_hash_uint32) input[j + 1]) << 8) |
00090                      (((php_hash_uint32) input[j + 2]) << 16) | (((php_hash_uint32) input[j + 3]) << 24);
00091 }
00092 /* }}} */
00093 
00094 #ifdef PHP_HASH_MD5_NOT_IN_CORE
00095 
00096 /* MD5 */
00097 
00098 PHP_HASH_API void make_digest(char *md5str, unsigned char *digest)
00099 {
00100        php_hash_bin2hex(md5str, digest, 16);
00101        md5str[32] = '\0';
00102 }
00103 
00104 /* {{{ proto string md5(string str, [ bool raw_output])
00105    Calculate the md5 hash of a string */
00106 PHP_NAMED_FUNCTION(php_if_md5)
00107 {
00108        char *arg;
00109        int arg_len;
00110        zend_bool raw_output = 0;
00111        char md5str[33];
00112        PHP_MD5_CTX context;
00113        unsigned char digest[16];
00114        
00115        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &arg, &arg_len, &raw_output) == FAILURE) {
00116               return;
00117        }
00118        
00119        md5str[0] = '\0';
00120        PHP_MD5Init(&context);
00121        PHP_MD5Update(&context, arg, arg_len);
00122        PHP_MD5Final(digest, &context);
00123        if (raw_output) {
00124               RETURN_STRINGL(digest, 16, 1);
00125        } else {
00126               make_digest(md5str, digest);
00127               RETVAL_STRING(md5str, 1);
00128        }
00129 
00130 }
00131 /* }}} */
00132 
00133 /* {{{ proto string md5_file(string filename [, bool raw_output])
00134    Calculate the md5 hash of given filename */
00135 PHP_NAMED_FUNCTION(php_if_md5_file)
00136 {
00137        char          *arg;
00138        int           arg_len;
00139        zend_bool raw_output = 0;
00140        char          md5str[33];
00141        unsigned char buf[1024];
00142        unsigned char digest[16];
00143        PHP_MD5_CTX   context;
00144        int           n;
00145        php_stream    *stream;
00146 
00147        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &arg, &arg_len, &raw_output) == FAILURE) {
00148               return;
00149        }
00150        
00151        stream = php_stream_open_wrapper(arg, "rb", REPORT_ERRORS | ENFORCE_SAFE_MODE, NULL);
00152        if (!stream) {
00153               RETURN_FALSE;
00154        }
00155 
00156        PHP_MD5Init(&context);
00157 
00158        while ((n = php_stream_read(stream, buf, sizeof(buf))) > 0) {
00159               PHP_MD5Update(&context, buf, n);
00160        }
00161 
00162        PHP_MD5Final(digest, &context);
00163 
00164        php_stream_close(stream);
00165 
00166        if (n<0) {
00167               RETURN_FALSE;
00168        }
00169 
00170        if (raw_output) {
00171               RETURN_STRINGL(digest, 16, 1);
00172        } else {
00173               make_digest(md5str, digest);
00174               RETVAL_STRING(md5str, 1);
00175        }
00176 }
00177 /* }}} */
00178 
00179 /*
00180  * The remaining code is the reference MD5 code (md5c.c) from rfc1321
00181  */
00182 /* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
00183  */
00184 
00185 /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
00186    rights reserved.
00187 
00188    License to copy and use this software is granted provided that it
00189    is identified as the "RSA Data Security, Inc. MD5 Message-Digest
00190    Algorithm" in all material mentioning or referencing this software
00191    or this function.
00192 
00193    License is also granted to make and use derivative works provided
00194    that such works are identified as "derived from the RSA Data
00195    Security, Inc. MD5 Message-Digest Algorithm" in all material
00196    mentioning or referencing the derived work.
00197 
00198    RSA Data Security, Inc. makes no representations concerning either
00199    the merchantability of this software or the suitability of this
00200    software for any particular purpose. It is provided "as is"
00201    without express or implied warranty of any kind.
00202 
00203    These notices must be retained in any copies of any part of this
00204    documentation and/or software.
00205  */
00206 
00207 /* Constants for MD5Transform routine.
00208  */
00209 
00210 #define S11 7
00211 #define S12 12
00212 #define S13 17
00213 #define S14 22
00214 #define S21 5
00215 #define S22 9
00216 #define S23 14
00217 #define S24 20
00218 #define S31 4
00219 #define S32 11
00220 #define S33 16
00221 #define S34 23
00222 #define S41 6
00223 #define S42 10
00224 #define S43 15
00225 #define S44 21
00226 
00227 static void MD5Transform(php_hash_uint32[4], const unsigned char[64]);
00228 
00229 /* F, G, H and I are basic MD5 functions.
00230  */
00231 #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
00232 #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
00233 #define H(x, y, z) ((x) ^ (y) ^ (z))
00234 #define I(x, y, z) ((y) ^ ((x) | (~z)))
00235 
00236 /* ROTATE_LEFT rotates x left n bits.
00237  */
00238 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
00239 
00240 /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
00241    Rotation is separate from addition to prevent recomputation.
00242  */
00243 #define FF(a, b, c, d, x, s, ac) { \
00244  (a) += F ((b), (c), (d)) + (x) + (php_hash_uint32)(ac); \
00245  (a) = ROTATE_LEFT ((a), (s)); \
00246  (a) += (b); \
00247   }
00248 #define GG(a, b, c, d, x, s, ac) { \
00249  (a) += G ((b), (c), (d)) + (x) + (php_hash_uint32)(ac); \
00250  (a) = ROTATE_LEFT ((a), (s)); \
00251  (a) += (b); \
00252   }
00253 #define HH(a, b, c, d, x, s, ac) { \
00254  (a) += H ((b), (c), (d)) + (x) + (php_hash_uint32)(ac); \
00255  (a) = ROTATE_LEFT ((a), (s)); \
00256  (a) += (b); \
00257   }
00258 #define II(a, b, c, d, x, s, ac) { \
00259  (a) += I ((b), (c), (d)) + (x) + (php_hash_uint32)(ac); \
00260  (a) = ROTATE_LEFT ((a), (s)); \
00261  (a) += (b); \
00262   }
00263 
00264 /* {{{ PHP_MD5Init
00265  * MD5 initialization. Begins an MD5 operation, writing a new context.
00266  */
00267 PHP_HASH_API void PHP_MD5Init(PHP_MD5_CTX * context)
00268 {
00269        context->count[0] = context->count[1] = 0;
00270        /* Load magic initialization constants.
00271         */
00272        context->state[0] = 0x67452301;
00273        context->state[1] = 0xefcdab89;
00274        context->state[2] = 0x98badcfe;
00275        context->state[3] = 0x10325476;
00276 }
00277 /* }}} */
00278 
00279 /* {{{ PHP_MD5Update
00280    MD5 block update operation. Continues an MD5 message-digest
00281    operation, processing another message block, and updating the
00282    context.
00283  */
00284 PHP_HASH_API void PHP_MD5Update(PHP_MD5_CTX * context, const unsigned char *input,
00285                         unsigned int inputLen)
00286 {
00287        unsigned int i, index, partLen;
00288 
00289        /* Compute number of bytes mod 64 */
00290        index = (unsigned int) ((context->count[0] >> 3) & 0x3F);
00291 
00292        /* Update number of bits */
00293        if ((context->count[0] += ((php_hash_uint32) inputLen << 3))
00294               < ((php_hash_uint32) inputLen << 3))
00295               context->count[1]++;
00296        context->count[1] += ((php_hash_uint32) inputLen >> 29);
00297 
00298        partLen = 64 - index;
00299 
00300        /* Transform as many times as possible.
00301         */
00302        if (inputLen >= partLen) {
00303               memcpy
00304                      ((unsigned char*) & context->buffer[index], (unsigned char*) input, partLen);
00305               MD5Transform(context->state, context->buffer);
00306 
00307               for (i = partLen; i + 63 < inputLen; i += 64)
00308                      MD5Transform(context->state, &input[i]);
00309 
00310               index = 0;
00311        } else
00312               i = 0;
00313 
00314        /* Buffer remaining input */
00315        memcpy
00316               ((unsigned char*) & context->buffer[index], (unsigned char*) & input[i],
00317                inputLen - i);
00318 }
00319 /* }}} */
00320 
00321 /* {{{ PHP_MD5Final
00322    MD5 finalization. Ends an MD5 message-digest operation, writing the
00323    the message digest and zeroizing the context.
00324  */
00325 PHP_HASH_API void PHP_MD5Final(unsigned char digest[16], PHP_MD5_CTX * context)
00326 {
00327        unsigned char bits[8];
00328        unsigned int index, padLen;
00329 
00330        /* Save number of bits */
00331        Encode(bits, context->count, 8);
00332 
00333        /* Pad out to 56 mod 64.
00334         */
00335        index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
00336        padLen = (index < 56) ? (56 - index) : (120 - index);
00337        PHP_MD5Update(context, PADDING, padLen);
00338 
00339        /* Append length (before padding) */
00340        PHP_MD5Update(context, bits, 8);
00341 
00342        /* Store state in digest */
00343        Encode(digest, context->state, 16);
00344 
00345        /* Zeroize sensitive information.
00346         */
00347        memset((unsigned char*) context, 0, sizeof(*context));
00348 }
00349 /* }}} */
00350 
00351 /* {{{ MD5Transform
00352  * MD5 basic transformation. Transforms state based on block.
00353  */
00354 static void MD5Transform(state, block)
00355 php_hash_uint32 state[4];
00356 const unsigned char block[64];
00357 {
00358        php_hash_uint32 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
00359 
00360        Decode(x, block, 64);
00361 
00362        /* Round 1 */
00363        FF(a, b, c, d, x[0], S11, 0xd76aa478);    /* 1 */
00364        FF(d, a, b, c, x[1], S12, 0xe8c7b756);    /* 2 */
00365        FF(c, d, a, b, x[2], S13, 0x242070db);    /* 3 */
00366        FF(b, c, d, a, x[3], S14, 0xc1bdceee);    /* 4 */
00367        FF(a, b, c, d, x[4], S11, 0xf57c0faf);    /* 5 */
00368        FF(d, a, b, c, x[5], S12, 0x4787c62a);    /* 6 */
00369        FF(c, d, a, b, x[6], S13, 0xa8304613);    /* 7 */
00370        FF(b, c, d, a, x[7], S14, 0xfd469501);    /* 8 */
00371        FF(a, b, c, d, x[8], S11, 0x698098d8);    /* 9 */
00372        FF(d, a, b, c, x[9], S12, 0x8b44f7af);    /* 10 */
00373        FF(c, d, a, b, x[10], S13, 0xffff5bb1);          /* 11 */
00374        FF(b, c, d, a, x[11], S14, 0x895cd7be);          /* 12 */
00375        FF(a, b, c, d, x[12], S11, 0x6b901122);          /* 13 */
00376        FF(d, a, b, c, x[13], S12, 0xfd987193);          /* 14 */
00377        FF(c, d, a, b, x[14], S13, 0xa679438e);          /* 15 */
00378        FF(b, c, d, a, x[15], S14, 0x49b40821);          /* 16 */
00379 
00380        /* Round 2 */
00381        GG(a, b, c, d, x[1], S21, 0xf61e2562);    /* 17 */
00382        GG(d, a, b, c, x[6], S22, 0xc040b340);    /* 18 */
00383        GG(c, d, a, b, x[11], S23, 0x265e5a51);          /* 19 */
00384        GG(b, c, d, a, x[0], S24, 0xe9b6c7aa);    /* 20 */
00385        GG(a, b, c, d, x[5], S21, 0xd62f105d);    /* 21 */
00386        GG(d, a, b, c, x[10], S22, 0x2441453);    /* 22 */
00387        GG(c, d, a, b, x[15], S23, 0xd8a1e681);          /* 23 */
00388        GG(b, c, d, a, x[4], S24, 0xe7d3fbc8);    /* 24 */
00389        GG(a, b, c, d, x[9], S21, 0x21e1cde6);    /* 25 */
00390        GG(d, a, b, c, x[14], S22, 0xc33707d6);          /* 26 */
00391        GG(c, d, a, b, x[3], S23, 0xf4d50d87);    /* 27 */
00392        GG(b, c, d, a, x[8], S24, 0x455a14ed);    /* 28 */
00393        GG(a, b, c, d, x[13], S21, 0xa9e3e905);          /* 29 */
00394        GG(d, a, b, c, x[2], S22, 0xfcefa3f8);    /* 30 */
00395        GG(c, d, a, b, x[7], S23, 0x676f02d9);    /* 31 */
00396        GG(b, c, d, a, x[12], S24, 0x8d2a4c8a);          /* 32 */
00397 
00398        /* Round 3 */
00399        HH(a, b, c, d, x[5], S31, 0xfffa3942);    /* 33 */
00400        HH(d, a, b, c, x[8], S32, 0x8771f681);    /* 34 */
00401        HH(c, d, a, b, x[11], S33, 0x6d9d6122);          /* 35 */
00402        HH(b, c, d, a, x[14], S34, 0xfde5380c);          /* 36 */
00403        HH(a, b, c, d, x[1], S31, 0xa4beea44);    /* 37 */
00404        HH(d, a, b, c, x[4], S32, 0x4bdecfa9);    /* 38 */
00405        HH(c, d, a, b, x[7], S33, 0xf6bb4b60);    /* 39 */
00406        HH(b, c, d, a, x[10], S34, 0xbebfbc70);          /* 40 */
00407        HH(a, b, c, d, x[13], S31, 0x289b7ec6);          /* 41 */
00408        HH(d, a, b, c, x[0], S32, 0xeaa127fa);    /* 42 */
00409        HH(c, d, a, b, x[3], S33, 0xd4ef3085);    /* 43 */
00410        HH(b, c, d, a, x[6], S34, 0x4881d05);     /* 44 */
00411        HH(a, b, c, d, x[9], S31, 0xd9d4d039);    /* 45 */
00412        HH(d, a, b, c, x[12], S32, 0xe6db99e5);          /* 46 */
00413        HH(c, d, a, b, x[15], S33, 0x1fa27cf8);          /* 47 */
00414        HH(b, c, d, a, x[2], S34, 0xc4ac5665);    /* 48 */
00415 
00416        /* Round 4 */
00417        II(a, b, c, d, x[0], S41, 0xf4292244);    /* 49 */
00418        II(d, a, b, c, x[7], S42, 0x432aff97);    /* 50 */
00419        II(c, d, a, b, x[14], S43, 0xab9423a7);          /* 51 */
00420        II(b, c, d, a, x[5], S44, 0xfc93a039);    /* 52 */
00421        II(a, b, c, d, x[12], S41, 0x655b59c3);          /* 53 */
00422        II(d, a, b, c, x[3], S42, 0x8f0ccc92);    /* 54 */
00423        II(c, d, a, b, x[10], S43, 0xffeff47d);          /* 55 */
00424        II(b, c, d, a, x[1], S44, 0x85845dd1);    /* 56 */
00425        II(a, b, c, d, x[8], S41, 0x6fa87e4f);    /* 57 */
00426        II(d, a, b, c, x[15], S42, 0xfe2ce6e0);          /* 58 */
00427        II(c, d, a, b, x[6], S43, 0xa3014314);    /* 59 */
00428        II(b, c, d, a, x[13], S44, 0x4e0811a1);          /* 60 */
00429        II(a, b, c, d, x[4], S41, 0xf7537e82);    /* 61 */
00430        II(d, a, b, c, x[11], S42, 0xbd3af235);          /* 62 */
00431        II(c, d, a, b, x[2], S43, 0x2ad7d2bb);    /* 63 */
00432        II(b, c, d, a, x[9], S44, 0xeb86d391);    /* 64 */
00433 
00434        state[0] += a;
00435        state[1] += b;
00436        state[2] += c;
00437        state[3] += d;
00438 
00439        /* Zeroize sensitive information. */
00440        memset((unsigned char*) x, 0, sizeof(x));
00441 }
00442 /* }}} */
00443 
00444 #endif /* PHP_HASH_MD5_NOT_IN_CORE */
00445 
00446 /* MD4 */
00447 
00448 #define MD4_F(x,y,z)               ((z) ^ ((x) & ((y) ^ (z))))
00449 #define MD4_G(x,y,z)               (((x) & ((y) | (z))) | ((y) & (z)))
00450 #define MD4_H(x,y,z)               ((x) ^ (y) ^ (z))
00451 
00452 #define ROTL32(s,v)                       (((v) << (s)) | ((v) >> (32 - (s))))
00453 
00454 #define MD4_R1(a,b,c,d,k,s)        a = ROTL32(s, a + MD4_F(b,c,d) + x[k])
00455 #define MD4_R2(a,b,c,d,k,s)        a = ROTL32(s, a + MD4_G(b,c,d) + x[k] + 0x5A827999)
00456 #define MD4_R3(a,b,c,d,k,s)        a = ROTL32(s, a + MD4_H(b,c,d) + x[k] + 0x6ED9EBA1)
00457 
00458 static void MD4Transform(php_hash_uint32 state[4], const unsigned char block[64])
00459 {
00460        php_hash_uint32 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
00461 
00462        Decode(x, block, 64);
00463 
00464        /* Round 1 */
00465        MD4_R1(a,b,c,d, 0, 3);
00466        MD4_R1(d,a,b,c, 1, 7);
00467        MD4_R1(c,d,a,b, 2,11);
00468        MD4_R1(b,c,d,a, 3,19);
00469        MD4_R1(a,b,c,d, 4, 3);
00470        MD4_R1(d,a,b,c, 5, 7);
00471        MD4_R1(c,d,a,b, 6,11);
00472        MD4_R1(b,c,d,a, 7,19);
00473        MD4_R1(a,b,c,d, 8, 3);
00474        MD4_R1(d,a,b,c, 9, 7);
00475        MD4_R1(c,d,a,b,10,11);
00476        MD4_R1(b,c,d,a,11,19);
00477        MD4_R1(a,b,c,d,12, 3);
00478        MD4_R1(d,a,b,c,13, 7);
00479        MD4_R1(c,d,a,b,14,11);
00480        MD4_R1(b,c,d,a,15,19);
00481 
00482        /* Round 2 */
00483        MD4_R2(a,b,c,d, 0, 3);
00484        MD4_R2(d,a,b,c, 4, 5);
00485        MD4_R2(c,d,a,b, 8, 9);
00486        MD4_R2(b,c,d,a,12,13);
00487        MD4_R2(a,b,c,d, 1, 3);
00488        MD4_R2(d,a,b,c, 5, 5);
00489        MD4_R2(c,d,a,b, 9, 9);
00490        MD4_R2(b,c,d,a,13,13);
00491        MD4_R2(a,b,c,d, 2, 3);
00492        MD4_R2(d,a,b,c, 6, 5);
00493        MD4_R2(c,d,a,b,10, 9);
00494        MD4_R2(b,c,d,a,14,13);
00495        MD4_R2(a,b,c,d, 3, 3);
00496        MD4_R2(d,a,b,c, 7, 5);
00497        MD4_R2(c,d,a,b,11, 9);
00498        MD4_R2(b,c,d,a,15,13);
00499 
00500        /* Round 3 */
00501        MD4_R3(a,b,c,d, 0, 3);
00502        MD4_R3(d,a,b,c, 8, 9);
00503        MD4_R3(c,d,a,b, 4,11);
00504        MD4_R3(b,c,d,a,12,15);
00505        MD4_R3(a,b,c,d, 2, 3);
00506        MD4_R3(d,a,b,c,10, 9);
00507        MD4_R3(c,d,a,b, 6,11);
00508        MD4_R3(b,c,d,a,14,15);
00509        MD4_R3(a,b,c,d, 1, 3);
00510        MD4_R3(d,a,b,c, 9, 9);
00511        MD4_R3(c,d,a,b, 5,11);
00512        MD4_R3(b,c,d,a,13,15);
00513        MD4_R3(a,b,c,d, 3, 3);
00514        MD4_R3(d,a,b,c,11, 9);
00515        MD4_R3(c,d,a,b, 7,11);
00516        MD4_R3(b,c,d,a,15,15);
00517 
00518        state[0] += a;
00519        state[1] += b;
00520        state[2] += c;
00521        state[3] += d;
00522 }
00523 
00524 /* {{{ PHP_MD4Init
00525  * MD4 initialization. Begins an MD4 operation, writing a new context.
00526  */
00527 PHP_HASH_API void PHP_MD4Init(PHP_MD4_CTX * context)
00528 {
00529        context->count[0] = context->count[1] = 0;
00530        /* Load magic initialization constants.
00531         */
00532        context->state[0] = 0x67452301;
00533        context->state[1] = 0xefcdab89;
00534        context->state[2] = 0x98badcfe;
00535        context->state[3] = 0x10325476;
00536 }
00537 /* }}} */
00538 
00539 /* {{{ PHP_MD4Update
00540    MD4 block update operation. Continues an MD4 message-digest
00541    operation, processing another message block, and updating the
00542    context.
00543  */
00544 PHP_HASH_API void PHP_MD4Update(PHP_MD4_CTX * context, const unsigned char *input, unsigned int inputLen)
00545 {
00546        unsigned int i, index, partLen;
00547 
00548        /* Compute number of bytes mod 64 */
00549        index = (unsigned int) ((context->count[0] >> 3) & 0x3F);
00550 
00551        /* Update number of bits */
00552        if ((context->count[0] += ((php_hash_uint32) inputLen << 3))
00553               < ((php_hash_uint32) inputLen << 3))
00554               context->count[1]++;
00555        context->count[1] += ((php_hash_uint32) inputLen >> 29);
00556 
00557        partLen = 64 - index;
00558 
00559        /* Transform as many times as possible.
00560         */
00561        if (inputLen >= partLen) {
00562               memcpy((unsigned char*) & context->buffer[index], (unsigned char*) input, partLen);
00563               MD4Transform(context->state, context->buffer);
00564 
00565               for (i = partLen; i + 63 < inputLen; i += 64) {
00566                      MD4Transform(context->state, &input[i]);
00567               }
00568 
00569               index = 0;
00570        } else {
00571               i = 0;
00572        }
00573 
00574        /* Buffer remaining input */
00575        memcpy((unsigned char*) & context->buffer[index], (unsigned char*) & input[i], inputLen - i);
00576 }
00577 /* }}} */
00578 
00579 /* {{{ PHP_MD4Final
00580    MD4 finalization. Ends an MD4 message-digest operation, writing the
00581    the message digest and zeroizing the context.
00582  */
00583 PHP_HASH_API void PHP_MD4Final(unsigned char digest[16], PHP_MD4_CTX * context)
00584 {
00585        unsigned char bits[8];
00586        unsigned int index, padLen;
00587 
00588        /* Save number of bits */
00589        Encode(bits, context->count, 8);
00590 
00591        /* Pad out to 56 mod 64.
00592         */
00593        index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
00594        padLen = (index < 56) ? (56 - index) : (120 - index);
00595        PHP_MD4Update(context, PADDING, padLen);
00596 
00597        /* Append length (before padding) */
00598        PHP_MD4Update(context, bits, 8);
00599 
00600        /* Store state in digest */
00601        Encode(digest, context->state, 16);
00602 
00603        /* Zeroize sensitive information.
00604         */
00605        memset((unsigned char*) context, 0, sizeof(*context));
00606 }
00607 /* }}} */
00608 
00609 /* MD2 */
00610 
00611 static const unsigned char MD2_S[256] = {
00612         41,  46,  67, 201, 162, 216, 124,   1,  61,  54,  84, 161, 236, 240,   6,  19,
00613         98, 167,   5, 243, 192, 199, 115, 140, 152, 147,  43, 217, 188,  76, 130, 202,
00614         30, 155,  87,  60, 253, 212, 224,  22, 103,  66, 111,  24, 138,  23, 229,  18,
00615        190,  78, 196, 214, 218, 158, 222,  73, 160, 251, 245, 142, 187,  47, 238, 122,
00616        169, 104, 121, 145,  21, 178,   7,  63, 148, 194,  16, 137,  11,  34,  95,  33,
00617        128, 127,  93, 154,  90, 144,  50,  39,  53,  62, 204, 231, 191, 247, 151,   3,
00618        255,  25,  48, 179,  72, 165, 181, 209, 215,  94, 146,  42, 172,  86, 170, 198,
00619         79, 184,  56, 210, 150, 164, 125, 182, 118, 252, 107, 226, 156, 116,   4, 241,
00620         69, 157, 112,  89, 100, 113, 135,  32, 134,  91, 207, 101, 230,  45, 168,   2,
00621         27,  96,  37, 173, 174, 176, 185, 246,  28,  70,  97, 105,  52,  64, 126,  15,
00622         85,  71, 163,  35, 221,  81, 175,  58, 195,  92, 249, 206, 186, 197, 234,  38,
00623         44,  83,  13, 110, 133,  40, 132,   9, 211, 223, 205, 244,  65, 129,  77,  82,
00624        106, 220,  55, 200, 108, 193, 171, 250,  36, 225, 123,   8,  12, 189, 177,  74,
00625        120, 136, 149, 139, 227,  99, 232, 109, 233, 203, 213, 254,  59,   0,  29,  57,
00626        242, 239, 183,  14, 102,  88, 208, 228, 166, 119, 114, 248, 235, 117,  75,  10,
00627         49,  68,  80, 180, 143, 237,  31,  26, 219, 153, 141,  51, 159,  17, 131,  20 };
00628 
00629 PHP_HASH_API void PHP_MD2Init(PHP_MD2_CTX *context)
00630 {
00631        memset(context, 0, sizeof(PHP_MD2_CTX));
00632 }
00633 
00634 static void MD2_Transform(PHP_MD2_CTX *context, const unsigned char *block)
00635 {
00636        unsigned char i,j,t = 0;
00637 
00638        for(i = 0; i < 16; i++) {
00639               context->state[16+i] = block[i];
00640               context->state[32+i] = (context->state[16+i] ^ context->state[i]);
00641        }
00642 
00643        for(i = 0; i < 18; i++) {
00644               for(j = 0; j < 48; j++) {
00645                      t = context->state[j] = context->state[j] ^ MD2_S[t];
00646               }
00647               t += i;
00648        }
00649 
00650        /* Update checksum -- must be after transform to avoid fouling up last message block */
00651        t = context->checksum[15];
00652        for(i = 0; i < 16; i++) {
00653               t = context->checksum[i] ^= MD2_S[block[i] ^ t];
00654        }
00655 }
00656 
00657 PHP_HASH_API void PHP_MD2Update(PHP_MD2_CTX *context, const unsigned char *buf, unsigned int len)
00658 {
00659        const unsigned char *p = buf, *e = buf + len;
00660 
00661        if (context->in_buffer) {
00662               if (context->in_buffer + len < 16) {
00663                      /* Not enough for block, just pass into buffer */
00664                      memcpy(context->buffer + context->in_buffer, p, len);
00665                      context->in_buffer += len;
00666                      return;
00667               }
00668               /* Put buffered data together with inbound for a single block */
00669               memcpy(context->buffer + context->in_buffer, p, 16 - context->in_buffer);
00670               MD2_Transform(context, context->buffer);
00671               p += 16 - context->in_buffer;
00672               context->in_buffer = 0;
00673        }
00674 
00675        /* Process as many whole blocks as remain */
00676        while ((p + 16) <= e) {
00677               MD2_Transform(context, p);
00678               p += 16;
00679        }
00680 
00681        /* Copy remaining data to buffer */
00682        if (p < e) {
00683               memcpy(context->buffer, p, e - p);
00684               context->in_buffer = e - p;
00685        }
00686 }
00687 
00688 PHP_HASH_API void PHP_MD2Final(unsigned char output[16], PHP_MD2_CTX *context)
00689 {
00690        memset(context->buffer + context->in_buffer, 16 - context->in_buffer, 16 - context->in_buffer);
00691        MD2_Transform(context, context->buffer);
00692        MD2_Transform(context, context->checksum);
00693 
00694        memcpy(output, context->state, 16);
00695 }
00696 
00697 /*
00698  * Local variables:
00699  * tab-width: 4
00700  * c-basic-offset: 4
00701  * End:
00702  * vim600: sw=4 ts=4 fdm=marker
00703  * vim<600: sw=4 ts=4
00704  */