00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #ifndef _CRT_SECURE_NO_DEPRECATE
00030 #define _CRT_SECURE_NO_DEPRECATE 1
00031 #endif
00032
00033 #include <string.h>
00034 #include <stdio.h>
00035
00036 #include "xyssl/md5.h"
00037
00038
00039
00040
00041 #ifndef GET_UINT32_LE
00042 #define GET_UINT32_LE(n,b,i) \
00043 { \
00044 (n) = ( (unsigned long) (b)[(i) ] ) \
00045 | ( (unsigned long) (b)[(i) + 1] << 8 ) \
00046 | ( (unsigned long) (b)[(i) + 2] << 16 ) \
00047 | ( (unsigned long) (b)[(i) + 3] << 24 ); \
00048 }
00049 #endif
00050
00051 #ifndef PUT_UINT32_LE
00052 #define PUT_UINT32_LE(n,b,i) \
00053 { \
00054 (b)[(i) ] = (unsigned char) ( (n) ); \
00055 (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \
00056 (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \
00057 (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \
00058 }
00059 #endif
00060
00061
00062
00063
00064 void md5_starts( md5_context *ctx )
00065 {
00066 ctx->total[0] = 0;
00067 ctx->total[1] = 0;
00068
00069 ctx->state[0] = 0x67452301;
00070 ctx->state[1] = 0xEFCDAB89;
00071 ctx->state[2] = 0x98BADCFE;
00072 ctx->state[3] = 0x10325476;
00073 }
00074
00075 static void md5_process( md5_context *ctx, unsigned char data[64] )
00076 {
00077 unsigned long X[16], A, B, C, D;
00078
00079 GET_UINT32_LE( X[ 0], data, 0 );
00080 GET_UINT32_LE( X[ 1], data, 4 );
00081 GET_UINT32_LE( X[ 2], data, 8 );
00082 GET_UINT32_LE( X[ 3], data, 12 );
00083 GET_UINT32_LE( X[ 4], data, 16 );
00084 GET_UINT32_LE( X[ 5], data, 20 );
00085 GET_UINT32_LE( X[ 6], data, 24 );
00086 GET_UINT32_LE( X[ 7], data, 28 );
00087 GET_UINT32_LE( X[ 8], data, 32 );
00088 GET_UINT32_LE( X[ 9], data, 36 );
00089 GET_UINT32_LE( X[10], data, 40 );
00090 GET_UINT32_LE( X[11], data, 44 );
00091 GET_UINT32_LE( X[12], data, 48 );
00092 GET_UINT32_LE( X[13], data, 52 );
00093 GET_UINT32_LE( X[14], data, 56 );
00094 GET_UINT32_LE( X[15], data, 60 );
00095
00096 #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
00097
00098 #define P(a,b,c,d,k,s,t) \
00099 { \
00100 a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \
00101 }
00102
00103 A = ctx->state[0];
00104 B = ctx->state[1];
00105 C = ctx->state[2];
00106 D = ctx->state[3];
00107
00108 #define F(x,y,z) (z ^ (x & (y ^ z)))
00109
00110 P( A, B, C, D, 0, 7, 0xD76AA478 );
00111 P( D, A, B, C, 1, 12, 0xE8C7B756 );
00112 P( C, D, A, B, 2, 17, 0x242070DB );
00113 P( B, C, D, A, 3, 22, 0xC1BDCEEE );
00114 P( A, B, C, D, 4, 7, 0xF57C0FAF );
00115 P( D, A, B, C, 5, 12, 0x4787C62A );
00116 P( C, D, A, B, 6, 17, 0xA8304613 );
00117 P( B, C, D, A, 7, 22, 0xFD469501 );
00118 P( A, B, C, D, 8, 7, 0x698098D8 );
00119 P( D, A, B, C, 9, 12, 0x8B44F7AF );
00120 P( C, D, A, B, 10, 17, 0xFFFF5BB1 );
00121 P( B, C, D, A, 11, 22, 0x895CD7BE );
00122 P( A, B, C, D, 12, 7, 0x6B901122 );
00123 P( D, A, B, C, 13, 12, 0xFD987193 );
00124 P( C, D, A, B, 14, 17, 0xA679438E );
00125 P( B, C, D, A, 15, 22, 0x49B40821 );
00126
00127 #undef F
00128
00129 #define F(x,y,z) (y ^ (z & (x ^ y)))
00130
00131 P( A, B, C, D, 1, 5, 0xF61E2562 );
00132 P( D, A, B, C, 6, 9, 0xC040B340 );
00133 P( C, D, A, B, 11, 14, 0x265E5A51 );
00134 P( B, C, D, A, 0, 20, 0xE9B6C7AA );
00135 P( A, B, C, D, 5, 5, 0xD62F105D );
00136 P( D, A, B, C, 10, 9, 0x02441453 );
00137 P( C, D, A, B, 15, 14, 0xD8A1E681 );
00138 P( B, C, D, A, 4, 20, 0xE7D3FBC8 );
00139 P( A, B, C, D, 9, 5, 0x21E1CDE6 );
00140 P( D, A, B, C, 14, 9, 0xC33707D6 );
00141 P( C, D, A, B, 3, 14, 0xF4D50D87 );
00142 P( B, C, D, A, 8, 20, 0x455A14ED );
00143 P( A, B, C, D, 13, 5, 0xA9E3E905 );
00144 P( D, A, B, C, 2, 9, 0xFCEFA3F8 );
00145 P( C, D, A, B, 7, 14, 0x676F02D9 );
00146 P( B, C, D, A, 12, 20, 0x8D2A4C8A );
00147
00148 #undef F
00149
00150 #define F(x,y,z) (x ^ y ^ z)
00151
00152 P( A, B, C, D, 5, 4, 0xFFFA3942 );
00153 P( D, A, B, C, 8, 11, 0x8771F681 );
00154 P( C, D, A, B, 11, 16, 0x6D9D6122 );
00155 P( B, C, D, A, 14, 23, 0xFDE5380C );
00156 P( A, B, C, D, 1, 4, 0xA4BEEA44 );
00157 P( D, A, B, C, 4, 11, 0x4BDECFA9 );
00158 P( C, D, A, B, 7, 16, 0xF6BB4B60 );
00159 P( B, C, D, A, 10, 23, 0xBEBFBC70 );
00160 P( A, B, C, D, 13, 4, 0x289B7EC6 );
00161 P( D, A, B, C, 0, 11, 0xEAA127FA );
00162 P( C, D, A, B, 3, 16, 0xD4EF3085 );
00163 P( B, C, D, A, 6, 23, 0x04881D05 );
00164 P( A, B, C, D, 9, 4, 0xD9D4D039 );
00165 P( D, A, B, C, 12, 11, 0xE6DB99E5 );
00166 P( C, D, A, B, 15, 16, 0x1FA27CF8 );
00167 P( B, C, D, A, 2, 23, 0xC4AC5665 );
00168
00169 #undef F
00170
00171 #define F(x,y,z) (y ^ (x | ~z))
00172
00173 P( A, B, C, D, 0, 6, 0xF4292244 );
00174 P( D, A, B, C, 7, 10, 0x432AFF97 );
00175 P( C, D, A, B, 14, 15, 0xAB9423A7 );
00176 P( B, C, D, A, 5, 21, 0xFC93A039 );
00177 P( A, B, C, D, 12, 6, 0x655B59C3 );
00178 P( D, A, B, C, 3, 10, 0x8F0CCC92 );
00179 P( C, D, A, B, 10, 15, 0xFFEFF47D );
00180 P( B, C, D, A, 1, 21, 0x85845DD1 );
00181 P( A, B, C, D, 8, 6, 0x6FA87E4F );
00182 P( D, A, B, C, 15, 10, 0xFE2CE6E0 );
00183 P( C, D, A, B, 6, 15, 0xA3014314 );
00184 P( B, C, D, A, 13, 21, 0x4E0811A1 );
00185 P( A, B, C, D, 4, 6, 0xF7537E82 );
00186 P( D, A, B, C, 11, 10, 0xBD3AF235 );
00187 P( C, D, A, B, 2, 15, 0x2AD7D2BB );
00188 P( B, C, D, A, 9, 21, 0xEB86D391 );
00189
00190 #undef F
00191
00192 ctx->state[0] += A;
00193 ctx->state[1] += B;
00194 ctx->state[2] += C;
00195 ctx->state[3] += D;
00196 }
00197
00198
00199
00200
00201 void md5_update( md5_context *ctx, unsigned char *input, int ilen )
00202 {
00203 int fill;
00204 unsigned long left;
00205
00206 if( ilen <= 0 )
00207 return;
00208
00209 left = ctx->total[0] & 0x3F;
00210 fill = 64 - left;
00211
00212 ctx->total[0] += ilen;
00213 ctx->total[0] &= 0xFFFFFFFF;
00214
00215 if( ctx->total[0] < (unsigned long) ilen )
00216 ctx->total[1]++;
00217
00218 if( left && ilen >= fill )
00219 {
00220 memcpy( (void *) (ctx->buffer + left),
00221 (void *) input, fill );
00222 md5_process( ctx, ctx->buffer );
00223 input += fill;
00224 ilen -= fill;
00225 left = 0;
00226 }
00227
00228 while( ilen >= 64 )
00229 {
00230 md5_process( ctx, input );
00231 input += 64;
00232 ilen -= 64;
00233 }
00234
00235 if( ilen > 0 )
00236 {
00237 memcpy( (void *) (ctx->buffer + left),
00238 (void *) input, ilen );
00239 }
00240 }
00241
00242 static const unsigned char md5_padding[64] =
00243 {
00244 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00245 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00246 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00247 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00248 };
00249
00250
00251
00252
00253 void md5_finish( md5_context *ctx, unsigned char *output )
00254 {
00255 unsigned long last, padn;
00256 unsigned long high, low;
00257 unsigned char msglen[8];
00258
00259 high = ( ctx->total[0] >> 29 )
00260 | ( ctx->total[1] << 3 );
00261 low = ( ctx->total[0] << 3 );
00262
00263 PUT_UINT32_LE( low, msglen, 0 );
00264 PUT_UINT32_LE( high, msglen, 4 );
00265
00266 last = ctx->total[0] & 0x3F;
00267 padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
00268
00269 md5_update( ctx, (unsigned char *) md5_padding, padn );
00270 md5_update( ctx, msglen, 8 );
00271
00272 PUT_UINT32_LE( ctx->state[0], output, 0 );
00273 PUT_UINT32_LE( ctx->state[1], output, 4 );
00274 PUT_UINT32_LE( ctx->state[2], output, 8 );
00275 PUT_UINT32_LE( ctx->state[3], output, 12 );
00276 }
00277
00278
00279
00280
00281 void md5( unsigned char *input, int ilen,
00282 unsigned char *output )
00283 {
00284 md5_context ctx;
00285
00286 md5_starts( &ctx );
00287 md5_update( &ctx, input, ilen );
00288 md5_finish( &ctx, output );
00289
00290 memset( &ctx, 0, sizeof( md5_context ) );
00291 }
00292
00293
00294
00295
00296 int md5_file( char *path, unsigned char *output )
00297 {
00298 FILE *f;
00299 size_t n;
00300 md5_context ctx;
00301 unsigned char buf[1024];
00302
00303 if( ( f = fopen( path, "rb" ) ) == NULL )
00304 return( 1 );
00305
00306 md5_starts( &ctx );
00307
00308 while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
00309 md5_update( &ctx, buf, (int) n );
00310
00311 md5_finish( &ctx, output );
00312
00313 memset( &ctx, 0, sizeof( md5_context ) );
00314
00315 if( ferror( f ) != 0 )
00316 {
00317 fclose( f );
00318 return( 2 );
00319 }
00320
00321 fclose( f );
00322 return( 0 );
00323 }
00324
00325
00326
00327
00328 void md5_hmac_starts( md5_context *ctx,
00329 unsigned char *key, int keylen )
00330 {
00331 int i;
00332
00333 memset( ctx->ipad, 0x36, 64 );
00334 memset( ctx->opad, 0x5C, 64 );
00335
00336 for( i = 0; i < keylen; i++ )
00337 {
00338 if( i >= 64 ) break;
00339
00340 ctx->ipad[i] ^= key[i];
00341 ctx->opad[i] ^= key[i];
00342 }
00343
00344 md5_starts( ctx );
00345 md5_update( ctx, ctx->ipad, 64 );
00346 }
00347
00348
00349
00350
00351 void md5_hmac_update( md5_context *ctx,
00352 unsigned char *input, int ilen )
00353 {
00354 md5_update( ctx, input, ilen );
00355 }
00356
00357
00358
00359
00360 void md5_hmac_finish( md5_context *ctx, unsigned char *output )
00361 {
00362 unsigned char tmpbuf[16];
00363
00364 md5_finish( ctx, tmpbuf );
00365 md5_starts( ctx );
00366 md5_update( ctx, ctx->opad, 64 );
00367 md5_update( ctx, tmpbuf, 16 );
00368 md5_finish( ctx, output );
00369
00370 memset( tmpbuf, 0, sizeof( tmpbuf ) );
00371 }
00372
00373
00374
00375
00376 void md5_hmac( unsigned char *key, int keylen,
00377 unsigned char *input, int ilen,
00378 unsigned char *output )
00379 {
00380 md5_context ctx;
00381
00382 md5_hmac_starts( &ctx, key, keylen );
00383 md5_hmac_update( &ctx, input, ilen );
00384 md5_hmac_finish( &ctx, output );
00385
00386 memset( &ctx, 0, sizeof( md5_context ) );
00387 }
00388
00389 static const char _md5_src[] = "_md5_src";
00390
00391 #if defined(SELF_TEST)
00392
00393
00394
00395 static const char md5_test_str[7][81] =
00396 {
00397 { "" },
00398 { "a" },
00399 { "abc" },
00400 { "message digest" },
00401 { "abcdefghijklmnopqrstuvwxyz" },
00402 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
00403 { "12345678901234567890123456789012345678901234567890123456789012" \
00404 "345678901234567890" }
00405 };
00406
00407 static const unsigned char md5_test_sum[7][16] =
00408 {
00409 { 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04,
00410 0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E },
00411 { 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8,
00412 0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 },
00413 { 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0,
00414 0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 },
00415 { 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D,
00416 0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 },
00417 { 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00,
00418 0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B },
00419 { 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5,
00420 0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F },
00421 { 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55,
00422 0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A }
00423 };
00424
00425
00426
00427
00428 int md5_self_test( int verbose )
00429 {
00430 int i;
00431 unsigned char md5sum[16];
00432
00433 for( i = 0; i < 7; i++ )
00434 {
00435 if( verbose != 0 )
00436 printf( " MD5 test #%d: ", i + 1 );
00437
00438 md5( (unsigned char *) md5_test_str[i],
00439 strlen( md5_test_str[i] ), md5sum );
00440
00441 if( memcmp( md5sum, md5_test_sum[i], 16 ) != 0 )
00442 {
00443 if( verbose != 0 )
00444 printf( "failed\n" );
00445
00446 return( 1 );
00447 }
00448
00449 if( verbose != 0 )
00450 printf( "passed\n" );
00451 }
00452
00453 if( verbose != 0 )
00454 printf( "\n" );
00455
00456 return( 0 );
00457 }
00458 #else
00459 int md5_self_test( int verbose )
00460 {
00461 return( 0 );
00462 }
00463 #endif