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