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 #include "polarssl/config.h"
00030
00031 #if defined(POLARSSL_MD5_C)
00032
00033 #include "polarssl/md5.h"
00034
00035 #include <string.h>
00036 #include <stdio.h>
00037
00038
00039
00040
00041 #ifndef GET_ULONG_LE
00042 #define GET_ULONG_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_ULONG_LE
00052 #define PUT_ULONG_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_ULONG_LE( X[ 0], data, 0 );
00080 GET_ULONG_LE( X[ 1], data, 4 );
00081 GET_ULONG_LE( X[ 2], data, 8 );
00082 GET_ULONG_LE( X[ 3], data, 12 );
00083 GET_ULONG_LE( X[ 4], data, 16 );
00084 GET_ULONG_LE( X[ 5], data, 20 );
00085 GET_ULONG_LE( X[ 6], data, 24 );
00086 GET_ULONG_LE( X[ 7], data, 28 );
00087 GET_ULONG_LE( X[ 8], data, 32 );
00088 GET_ULONG_LE( X[ 9], data, 36 );
00089 GET_ULONG_LE( X[10], data, 40 );
00090 GET_ULONG_LE( X[11], data, 44 );
00091 GET_ULONG_LE( X[12], data, 48 );
00092 GET_ULONG_LE( X[13], data, 52 );
00093 GET_ULONG_LE( X[14], data, 56 );
00094 GET_ULONG_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[16] )
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_ULONG_LE( low, msglen, 0 );
00264 PUT_ULONG_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_ULONG_LE( ctx->state[0], output, 0 );
00273 PUT_ULONG_LE( ctx->state[1], output, 4 );
00274 PUT_ULONG_LE( ctx->state[2], output, 8 );
00275 PUT_ULONG_LE( ctx->state[3], output, 12 );
00276 }
00277
00278
00279
00280
00281 void md5( unsigned char *input, int ilen, unsigned char output[16] )
00282 {
00283 md5_context ctx;
00284
00285 md5_starts( &ctx );
00286 md5_update( &ctx, input, ilen );
00287 md5_finish( &ctx, output );
00288
00289 memset( &ctx, 0, sizeof( md5_context ) );
00290 }
00291
00292
00293
00294
00295 int md5_file( char *path, unsigned char output[16] )
00296 {
00297 FILE *f;
00298 size_t n;
00299 md5_context ctx;
00300 unsigned char buf[1024];
00301
00302 if( ( f = fopen( path, "rb" ) ) == NULL )
00303 return( 1 );
00304
00305 md5_starts( &ctx );
00306
00307 while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
00308 md5_update( &ctx, buf, (int) n );
00309
00310 md5_finish( &ctx, output );
00311
00312 memset( &ctx, 0, sizeof( md5_context ) );
00313
00314 if( ferror( f ) != 0 )
00315 {
00316 fclose( f );
00317 return( 2 );
00318 }
00319
00320 fclose( f );
00321 return( 0 );
00322 }
00323
00324
00325
00326
00327 void md5_hmac_starts( md5_context *ctx, unsigned char *key, int keylen )
00328 {
00329 int i;
00330 unsigned char sum[16];
00331
00332 if( keylen > 64 )
00333 {
00334 md5( key, keylen, sum );
00335 keylen = 16;
00336 key = sum;
00337 }
00338
00339 memset( ctx->ipad, 0x36, 64 );
00340 memset( ctx->opad, 0x5C, 64 );
00341
00342 for( i = 0; i < keylen; i++ )
00343 {
00344 ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
00345 ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
00346 }
00347
00348 md5_starts( ctx );
00349 md5_update( ctx, ctx->ipad, 64 );
00350
00351 memset( sum, 0, sizeof( sum ) );
00352 }
00353
00354
00355
00356
00357 void md5_hmac_update( md5_context *ctx, unsigned char *input, int ilen )
00358 {
00359 md5_update( ctx, input, ilen );
00360 }
00361
00362
00363
00364
00365 void md5_hmac_finish( md5_context *ctx, unsigned char output[16] )
00366 {
00367 unsigned char tmpbuf[16];
00368
00369 md5_finish( ctx, tmpbuf );
00370 md5_starts( ctx );
00371 md5_update( ctx, ctx->opad, 64 );
00372 md5_update( ctx, tmpbuf, 16 );
00373 md5_finish( ctx, output );
00374
00375 memset( tmpbuf, 0, sizeof( tmpbuf ) );
00376 }
00377
00378
00379
00380
00381 void md5_hmac( unsigned char *key, int keylen, unsigned char *input, int ilen,
00382 unsigned char output[16] )
00383 {
00384 md5_context ctx;
00385
00386 md5_hmac_starts( &ctx, key, keylen );
00387 md5_hmac_update( &ctx, input, ilen );
00388 md5_hmac_finish( &ctx, output );
00389
00390 memset( &ctx, 0, sizeof( md5_context ) );
00391 }
00392
00393 #if defined(POLARSSL_SELF_TEST)
00394
00395
00396
00397 static unsigned char md5_test_buf[7][81] =
00398 {
00399 { "" },
00400 { "a" },
00401 { "abc" },
00402 { "message digest" },
00403 { "abcdefghijklmnopqrstuvwxyz" },
00404 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
00405 { "12345678901234567890123456789012345678901234567890123456789012" \
00406 "345678901234567890" }
00407 };
00408
00409 static const int md5_test_buflen[7] =
00410 {
00411 0, 1, 3, 14, 26, 62, 80
00412 };
00413
00414 static const unsigned char md5_test_sum[7][16] =
00415 {
00416 { 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04,
00417 0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E },
00418 { 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8,
00419 0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 },
00420 { 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0,
00421 0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 },
00422 { 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D,
00423 0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 },
00424 { 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00,
00425 0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B },
00426 { 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5,
00427 0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F },
00428 { 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55,
00429 0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A }
00430 };
00431
00432
00433
00434
00435 static unsigned char md5_hmac_test_key[7][26] =
00436 {
00437 { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B" },
00438 { "Jefe" },
00439 { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" },
00440 { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
00441 "\x11\x12\x13\x14\x15\x16\x17\x18\x19" },
00442 { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C" },
00443 { "" },
00444 { "" }
00445 };
00446
00447 static const int md5_hmac_test_keylen[7] =
00448 {
00449 16, 4, 16, 25, 16, 80, 80
00450 };
00451
00452 static unsigned char md5_hmac_test_buf[7][74] =
00453 {
00454 { "Hi There" },
00455 { "what do ya want for nothing?" },
00456 { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
00457 "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
00458 "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
00459 "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
00460 "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" },
00461 { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
00462 "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
00463 "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
00464 "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
00465 "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" },
00466 { "Test With Truncation" },
00467 { "Test Using Larger Than Block-Size Key - Hash Key First" },
00468 { "Test Using Larger Than Block-Size Key and Larger"
00469 " Than One Block-Size Data" }
00470 };
00471
00472 static const int md5_hmac_test_buflen[7] =
00473 {
00474 8, 28, 50, 50, 20, 54, 73
00475 };
00476
00477 static const unsigned char md5_hmac_test_sum[7][16] =
00478 {
00479 { 0x92, 0x94, 0x72, 0x7A, 0x36, 0x38, 0xBB, 0x1C,
00480 0x13, 0xF4, 0x8E, 0xF8, 0x15, 0x8B, 0xFC, 0x9D },
00481 { 0x75, 0x0C, 0x78, 0x3E, 0x6A, 0xB0, 0xB5, 0x03,
00482 0xEA, 0xA8, 0x6E, 0x31, 0x0A, 0x5D, 0xB7, 0x38 },
00483 { 0x56, 0xBE, 0x34, 0x52, 0x1D, 0x14, 0x4C, 0x88,
00484 0xDB, 0xB8, 0xC7, 0x33, 0xF0, 0xE8, 0xB3, 0xF6 },
00485 { 0x69, 0x7E, 0xAF, 0x0A, 0xCA, 0x3A, 0x3A, 0xEA,
00486 0x3A, 0x75, 0x16, 0x47, 0x46, 0xFF, 0xAA, 0x79 },
00487 { 0x56, 0x46, 0x1E, 0xF2, 0x34, 0x2E, 0xDC, 0x00,
00488 0xF9, 0xBA, 0xB9, 0x95 },
00489 { 0x6B, 0x1A, 0xB7, 0xFE, 0x4B, 0xD7, 0xBF, 0x8F,
00490 0x0B, 0x62, 0xE6, 0xCE, 0x61, 0xB9, 0xD0, 0xCD },
00491 { 0x6F, 0x63, 0x0F, 0xAD, 0x67, 0xCD, 0xA0, 0xEE,
00492 0x1F, 0xB1, 0xF5, 0x62, 0xDB, 0x3A, 0xA5, 0x3E }
00493 };
00494
00495
00496
00497
00498 int md5_self_test( int verbose )
00499 {
00500 int i, buflen;
00501 unsigned char buf[1024];
00502 unsigned char md5sum[16];
00503 md5_context ctx;
00504
00505 for( i = 0; i < 7; i++ )
00506 {
00507 if( verbose != 0 )
00508 printf( " MD5 test #%d: ", i + 1 );
00509
00510 md5( md5_test_buf[i], md5_test_buflen[i], md5sum );
00511
00512 if( memcmp( md5sum, md5_test_sum[i], 16 ) != 0 )
00513 {
00514 if( verbose != 0 )
00515 printf( "failed\n" );
00516
00517 return( 1 );
00518 }
00519
00520 if( verbose != 0 )
00521 printf( "passed\n" );
00522 }
00523
00524 if( verbose != 0 )
00525 printf( "\n" );
00526
00527 for( i = 0; i < 7; i++ )
00528 {
00529 if( verbose != 0 )
00530 printf( " HMAC-MD5 test #%d: ", i + 1 );
00531
00532 if( i == 5 || i == 6 )
00533 {
00534 memset( buf, '\xAA', buflen = 80 );
00535 md5_hmac_starts( &ctx, buf, buflen );
00536 }
00537 else
00538 md5_hmac_starts( &ctx, md5_hmac_test_key[i],
00539 md5_hmac_test_keylen[i] );
00540
00541 md5_hmac_update( &ctx, md5_hmac_test_buf[i],
00542 md5_hmac_test_buflen[i] );
00543
00544 md5_hmac_finish( &ctx, md5sum );
00545
00546 buflen = ( i == 4 ) ? 12 : 16;
00547
00548 if( memcmp( md5sum, md5_hmac_test_sum[i], buflen ) != 0 )
00549 {
00550 if( verbose != 0 )
00551 printf( "failed\n" );
00552
00553 return( 1 );
00554 }
00555
00556 if( verbose != 0 )
00557 printf( "passed\n" );
00558 }
00559
00560 if( verbose != 0 )
00561 printf( "\n" );
00562
00563 return( 0 );
00564 }
00565
00566 #endif
00567
00568 #endif