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
00030
00031 #include "polarssl/config.h"
00032
00033 #if defined(POLARSSL_MD5_C)
00034
00035 #include "polarssl/md5.h"
00036
00037 #if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST)
00038 #include <stdio.h>
00039 #endif
00040
00041 #if !defined(POLARSSL_MD5_ALT)
00042
00043
00044
00045
00046 #ifndef GET_UINT32_LE
00047 #define GET_UINT32_LE(n,b,i) \
00048 { \
00049 (n) = ( (uint32_t) (b)[(i) ] ) \
00050 | ( (uint32_t) (b)[(i) + 1] << 8 ) \
00051 | ( (uint32_t) (b)[(i) + 2] << 16 ) \
00052 | ( (uint32_t) (b)[(i) + 3] << 24 ); \
00053 }
00054 #endif
00055
00056 #ifndef PUT_UINT32_LE
00057 #define PUT_UINT32_LE(n,b,i) \
00058 { \
00059 (b)[(i) ] = (unsigned char) ( (n) ); \
00060 (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \
00061 (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \
00062 (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \
00063 }
00064 #endif
00065
00066
00067
00068
00069 void md5_starts( md5_context *ctx )
00070 {
00071 ctx->total[0] = 0;
00072 ctx->total[1] = 0;
00073
00074 ctx->state[0] = 0x67452301;
00075 ctx->state[1] = 0xEFCDAB89;
00076 ctx->state[2] = 0x98BADCFE;
00077 ctx->state[3] = 0x10325476;
00078 }
00079
00080 void md5_process( md5_context *ctx, const unsigned char data[64] )
00081 {
00082 uint32_t X[16], A, B, C, D;
00083
00084 GET_UINT32_LE( X[ 0], data, 0 );
00085 GET_UINT32_LE( X[ 1], data, 4 );
00086 GET_UINT32_LE( X[ 2], data, 8 );
00087 GET_UINT32_LE( X[ 3], data, 12 );
00088 GET_UINT32_LE( X[ 4], data, 16 );
00089 GET_UINT32_LE( X[ 5], data, 20 );
00090 GET_UINT32_LE( X[ 6], data, 24 );
00091 GET_UINT32_LE( X[ 7], data, 28 );
00092 GET_UINT32_LE( X[ 8], data, 32 );
00093 GET_UINT32_LE( X[ 9], data, 36 );
00094 GET_UINT32_LE( X[10], data, 40 );
00095 GET_UINT32_LE( X[11], data, 44 );
00096 GET_UINT32_LE( X[12], data, 48 );
00097 GET_UINT32_LE( X[13], data, 52 );
00098 GET_UINT32_LE( X[14], data, 56 );
00099 GET_UINT32_LE( X[15], data, 60 );
00100
00101 #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
00102
00103 #define P(a,b,c,d,k,s,t) \
00104 { \
00105 a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \
00106 }
00107
00108 A = ctx->state[0];
00109 B = ctx->state[1];
00110 C = ctx->state[2];
00111 D = ctx->state[3];
00112
00113 #define F(x,y,z) (z ^ (x & (y ^ z)))
00114
00115 P( A, B, C, D, 0, 7, 0xD76AA478 );
00116 P( D, A, B, C, 1, 12, 0xE8C7B756 );
00117 P( C, D, A, B, 2, 17, 0x242070DB );
00118 P( B, C, D, A, 3, 22, 0xC1BDCEEE );
00119 P( A, B, C, D, 4, 7, 0xF57C0FAF );
00120 P( D, A, B, C, 5, 12, 0x4787C62A );
00121 P( C, D, A, B, 6, 17, 0xA8304613 );
00122 P( B, C, D, A, 7, 22, 0xFD469501 );
00123 P( A, B, C, D, 8, 7, 0x698098D8 );
00124 P( D, A, B, C, 9, 12, 0x8B44F7AF );
00125 P( C, D, A, B, 10, 17, 0xFFFF5BB1 );
00126 P( B, C, D, A, 11, 22, 0x895CD7BE );
00127 P( A, B, C, D, 12, 7, 0x6B901122 );
00128 P( D, A, B, C, 13, 12, 0xFD987193 );
00129 P( C, D, A, B, 14, 17, 0xA679438E );
00130 P( B, C, D, A, 15, 22, 0x49B40821 );
00131
00132 #undef F
00133
00134 #define F(x,y,z) (y ^ (z & (x ^ y)))
00135
00136 P( A, B, C, D, 1, 5, 0xF61E2562 );
00137 P( D, A, B, C, 6, 9, 0xC040B340 );
00138 P( C, D, A, B, 11, 14, 0x265E5A51 );
00139 P( B, C, D, A, 0, 20, 0xE9B6C7AA );
00140 P( A, B, C, D, 5, 5, 0xD62F105D );
00141 P( D, A, B, C, 10, 9, 0x02441453 );
00142 P( C, D, A, B, 15, 14, 0xD8A1E681 );
00143 P( B, C, D, A, 4, 20, 0xE7D3FBC8 );
00144 P( A, B, C, D, 9, 5, 0x21E1CDE6 );
00145 P( D, A, B, C, 14, 9, 0xC33707D6 );
00146 P( C, D, A, B, 3, 14, 0xF4D50D87 );
00147 P( B, C, D, A, 8, 20, 0x455A14ED );
00148 P( A, B, C, D, 13, 5, 0xA9E3E905 );
00149 P( D, A, B, C, 2, 9, 0xFCEFA3F8 );
00150 P( C, D, A, B, 7, 14, 0x676F02D9 );
00151 P( B, C, D, A, 12, 20, 0x8D2A4C8A );
00152
00153 #undef F
00154
00155 #define F(x,y,z) (x ^ y ^ z)
00156
00157 P( A, B, C, D, 5, 4, 0xFFFA3942 );
00158 P( D, A, B, C, 8, 11, 0x8771F681 );
00159 P( C, D, A, B, 11, 16, 0x6D9D6122 );
00160 P( B, C, D, A, 14, 23, 0xFDE5380C );
00161 P( A, B, C, D, 1, 4, 0xA4BEEA44 );
00162 P( D, A, B, C, 4, 11, 0x4BDECFA9 );
00163 P( C, D, A, B, 7, 16, 0xF6BB4B60 );
00164 P( B, C, D, A, 10, 23, 0xBEBFBC70 );
00165 P( A, B, C, D, 13, 4, 0x289B7EC6 );
00166 P( D, A, B, C, 0, 11, 0xEAA127FA );
00167 P( C, D, A, B, 3, 16, 0xD4EF3085 );
00168 P( B, C, D, A, 6, 23, 0x04881D05 );
00169 P( A, B, C, D, 9, 4, 0xD9D4D039 );
00170 P( D, A, B, C, 12, 11, 0xE6DB99E5 );
00171 P( C, D, A, B, 15, 16, 0x1FA27CF8 );
00172 P( B, C, D, A, 2, 23, 0xC4AC5665 );
00173
00174 #undef F
00175
00176 #define F(x,y,z) (y ^ (x | ~z))
00177
00178 P( A, B, C, D, 0, 6, 0xF4292244 );
00179 P( D, A, B, C, 7, 10, 0x432AFF97 );
00180 P( C, D, A, B, 14, 15, 0xAB9423A7 );
00181 P( B, C, D, A, 5, 21, 0xFC93A039 );
00182 P( A, B, C, D, 12, 6, 0x655B59C3 );
00183 P( D, A, B, C, 3, 10, 0x8F0CCC92 );
00184 P( C, D, A, B, 10, 15, 0xFFEFF47D );
00185 P( B, C, D, A, 1, 21, 0x85845DD1 );
00186 P( A, B, C, D, 8, 6, 0x6FA87E4F );
00187 P( D, A, B, C, 15, 10, 0xFE2CE6E0 );
00188 P( C, D, A, B, 6, 15, 0xA3014314 );
00189 P( B, C, D, A, 13, 21, 0x4E0811A1 );
00190 P( A, B, C, D, 4, 6, 0xF7537E82 );
00191 P( D, A, B, C, 11, 10, 0xBD3AF235 );
00192 P( C, D, A, B, 2, 15, 0x2AD7D2BB );
00193 P( B, C, D, A, 9, 21, 0xEB86D391 );
00194
00195 #undef F
00196
00197 ctx->state[0] += A;
00198 ctx->state[1] += B;
00199 ctx->state[2] += C;
00200 ctx->state[3] += D;
00201 }
00202
00203
00204
00205
00206 void md5_update( md5_context *ctx, const unsigned char *input, size_t ilen )
00207 {
00208 size_t fill;
00209 uint32_t left;
00210
00211 if( ilen <= 0 )
00212 return;
00213
00214 left = ctx->total[0] & 0x3F;
00215 fill = 64 - left;
00216
00217 ctx->total[0] += (uint32_t) ilen;
00218 ctx->total[0] &= 0xFFFFFFFF;
00219
00220 if( ctx->total[0] < (uint32_t) ilen )
00221 ctx->total[1]++;
00222
00223 if( left && ilen >= fill )
00224 {
00225 memcpy( (void *) (ctx->buffer + left), input, fill );
00226 md5_process( ctx, ctx->buffer );
00227 input += fill;
00228 ilen -= fill;
00229 left = 0;
00230 }
00231
00232 while( ilen >= 64 )
00233 {
00234 md5_process( ctx, input );
00235 input += 64;
00236 ilen -= 64;
00237 }
00238
00239 if( ilen > 0 )
00240 {
00241 memcpy( (void *) (ctx->buffer + left), input, ilen );
00242 }
00243 }
00244
00245 static const unsigned char md5_padding[64] =
00246 {
00247 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00248 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00249 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00250 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00251 };
00252
00253
00254
00255
00256 void md5_finish( md5_context *ctx, unsigned char output[16] )
00257 {
00258 uint32_t last, padn;
00259 uint32_t high, low;
00260 unsigned char msglen[8];
00261
00262 high = ( ctx->total[0] >> 29 )
00263 | ( ctx->total[1] << 3 );
00264 low = ( ctx->total[0] << 3 );
00265
00266 PUT_UINT32_LE( low, msglen, 0 );
00267 PUT_UINT32_LE( high, msglen, 4 );
00268
00269 last = ctx->total[0] & 0x3F;
00270 padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
00271
00272 md5_update( ctx, md5_padding, padn );
00273 md5_update( ctx, msglen, 8 );
00274
00275 PUT_UINT32_LE( ctx->state[0], output, 0 );
00276 PUT_UINT32_LE( ctx->state[1], output, 4 );
00277 PUT_UINT32_LE( ctx->state[2], output, 8 );
00278 PUT_UINT32_LE( ctx->state[3], output, 12 );
00279 }
00280
00281 #endif
00282
00283
00284
00285
00286 void md5( const unsigned char *input, size_t ilen, unsigned char output[16] )
00287 {
00288 md5_context ctx;
00289
00290 md5_starts( &ctx );
00291 md5_update( &ctx, input, ilen );
00292 md5_finish( &ctx, output );
00293
00294 memset( &ctx, 0, sizeof( md5_context ) );
00295 }
00296
00297 #if defined(POLARSSL_FS_IO)
00298
00299
00300
00301 int md5_file( const char *path, unsigned char output[16] )
00302 {
00303 FILE *f;
00304 size_t n;
00305 md5_context ctx;
00306 unsigned char buf[1024];
00307
00308 if( ( f = fopen( path, "rb" ) ) == NULL )
00309 return( POLARSSL_ERR_MD5_FILE_IO_ERROR );
00310
00311 md5_starts( &ctx );
00312
00313 while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
00314 md5_update( &ctx, buf, n );
00315
00316 md5_finish( &ctx, output );
00317
00318 memset( &ctx, 0, sizeof( md5_context ) );
00319
00320 if( ferror( f ) != 0 )
00321 {
00322 fclose( f );
00323 return( POLARSSL_ERR_MD5_FILE_IO_ERROR );
00324 }
00325
00326 fclose( f );
00327 return( 0 );
00328 }
00329 #endif
00330
00331
00332
00333
00334 void md5_hmac_starts( md5_context *ctx, const unsigned char *key, size_t keylen )
00335 {
00336 size_t i;
00337 unsigned char sum[16];
00338
00339 if( keylen > 64 )
00340 {
00341 md5( key, keylen, sum );
00342 keylen = 16;
00343 key = sum;
00344 }
00345
00346 memset( ctx->ipad, 0x36, 64 );
00347 memset( ctx->opad, 0x5C, 64 );
00348
00349 for( i = 0; i < keylen; i++ )
00350 {
00351 ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
00352 ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
00353 }
00354
00355 md5_starts( ctx );
00356 md5_update( ctx, ctx->ipad, 64 );
00357
00358 memset( sum, 0, sizeof( sum ) );
00359 }
00360
00361
00362
00363
00364 void md5_hmac_update( md5_context *ctx, const unsigned char *input, size_t ilen )
00365 {
00366 md5_update( ctx, input, ilen );
00367 }
00368
00369
00370
00371
00372 void md5_hmac_finish( md5_context *ctx, unsigned char output[16] )
00373 {
00374 unsigned char tmpbuf[16];
00375
00376 md5_finish( ctx, tmpbuf );
00377 md5_starts( ctx );
00378 md5_update( ctx, ctx->opad, 64 );
00379 md5_update( ctx, tmpbuf, 16 );
00380 md5_finish( ctx, output );
00381
00382 memset( tmpbuf, 0, sizeof( tmpbuf ) );
00383 }
00384
00385
00386
00387
00388 void md5_hmac_reset( md5_context *ctx )
00389 {
00390 md5_starts( ctx );
00391 md5_update( ctx, ctx->ipad, 64 );
00392 }
00393
00394
00395
00396
00397 void md5_hmac( const unsigned char *key, size_t keylen,
00398 const unsigned char *input, size_t ilen,
00399 unsigned char output[16] )
00400 {
00401 md5_context ctx;
00402
00403 md5_hmac_starts( &ctx, key, keylen );
00404 md5_hmac_update( &ctx, input, ilen );
00405 md5_hmac_finish( &ctx, output );
00406
00407 memset( &ctx, 0, sizeof( md5_context ) );
00408 }
00409
00410 #if defined(POLARSSL_SELF_TEST)
00411
00412
00413
00414 static unsigned char md5_test_buf[7][81] =
00415 {
00416 { "" },
00417 { "a" },
00418 { "abc" },
00419 { "message digest" },
00420 { "abcdefghijklmnopqrstuvwxyz" },
00421 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
00422 { "12345678901234567890123456789012345678901234567890123456789012" \
00423 "345678901234567890" }
00424 };
00425
00426 static const int md5_test_buflen[7] =
00427 {
00428 0, 1, 3, 14, 26, 62, 80
00429 };
00430
00431 static const unsigned char md5_test_sum[7][16] =
00432 {
00433 { 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04,
00434 0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E },
00435 { 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8,
00436 0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 },
00437 { 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0,
00438 0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 },
00439 { 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D,
00440 0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 },
00441 { 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00,
00442 0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B },
00443 { 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5,
00444 0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F },
00445 { 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55,
00446 0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A }
00447 };
00448
00449
00450
00451
00452 static unsigned char md5_hmac_test_key[7][26] =
00453 {
00454 { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B" },
00455 { "Jefe" },
00456 { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" },
00457 { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
00458 "\x11\x12\x13\x14\x15\x16\x17\x18\x19" },
00459 { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C" },
00460 { "" },
00461 { "" }
00462 };
00463
00464 static const int md5_hmac_test_keylen[7] =
00465 {
00466 16, 4, 16, 25, 16, 80, 80
00467 };
00468
00469 static unsigned char md5_hmac_test_buf[7][74] =
00470 {
00471 { "Hi There" },
00472 { "what do ya want for nothing?" },
00473 { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
00474 "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
00475 "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
00476 "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
00477 "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" },
00478 { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
00479 "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
00480 "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
00481 "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
00482 "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" },
00483 { "Test With Truncation" },
00484 { "Test Using Larger Than Block-Size Key - Hash Key First" },
00485 { "Test Using Larger Than Block-Size Key and Larger"
00486 " Than One Block-Size Data" }
00487 };
00488
00489 static const int md5_hmac_test_buflen[7] =
00490 {
00491 8, 28, 50, 50, 20, 54, 73
00492 };
00493
00494 static const unsigned char md5_hmac_test_sum[7][16] =
00495 {
00496 { 0x92, 0x94, 0x72, 0x7A, 0x36, 0x38, 0xBB, 0x1C,
00497 0x13, 0xF4, 0x8E, 0xF8, 0x15, 0x8B, 0xFC, 0x9D },
00498 { 0x75, 0x0C, 0x78, 0x3E, 0x6A, 0xB0, 0xB5, 0x03,
00499 0xEA, 0xA8, 0x6E, 0x31, 0x0A, 0x5D, 0xB7, 0x38 },
00500 { 0x56, 0xBE, 0x34, 0x52, 0x1D, 0x14, 0x4C, 0x88,
00501 0xDB, 0xB8, 0xC7, 0x33, 0xF0, 0xE8, 0xB3, 0xF6 },
00502 { 0x69, 0x7E, 0xAF, 0x0A, 0xCA, 0x3A, 0x3A, 0xEA,
00503 0x3A, 0x75, 0x16, 0x47, 0x46, 0xFF, 0xAA, 0x79 },
00504 { 0x56, 0x46, 0x1E, 0xF2, 0x34, 0x2E, 0xDC, 0x00,
00505 0xF9, 0xBA, 0xB9, 0x95 },
00506 { 0x6B, 0x1A, 0xB7, 0xFE, 0x4B, 0xD7, 0xBF, 0x8F,
00507 0x0B, 0x62, 0xE6, 0xCE, 0x61, 0xB9, 0xD0, 0xCD },
00508 { 0x6F, 0x63, 0x0F, 0xAD, 0x67, 0xCD, 0xA0, 0xEE,
00509 0x1F, 0xB1, 0xF5, 0x62, 0xDB, 0x3A, 0xA5, 0x3E }
00510 };
00511
00512
00513
00514
00515 int md5_self_test( int verbose )
00516 {
00517 int i, buflen;
00518 unsigned char buf[1024];
00519 unsigned char md5sum[16];
00520 md5_context ctx;
00521
00522 for( i = 0; i < 7; i++ )
00523 {
00524 if( verbose != 0 )
00525 printf( " MD5 test #%d: ", i + 1 );
00526
00527 md5( md5_test_buf[i], md5_test_buflen[i], md5sum );
00528
00529 if( memcmp( md5sum, md5_test_sum[i], 16 ) != 0 )
00530 {
00531 if( verbose != 0 )
00532 printf( "failed\n" );
00533
00534 return( 1 );
00535 }
00536
00537 if( verbose != 0 )
00538 printf( "passed\n" );
00539 }
00540
00541 if( verbose != 0 )
00542 printf( "\n" );
00543
00544 for( i = 0; i < 7; i++ )
00545 {
00546 if( verbose != 0 )
00547 printf( " HMAC-MD5 test #%d: ", i + 1 );
00548
00549 if( i == 5 || i == 6 )
00550 {
00551 memset( buf, '\xAA', buflen = 80 );
00552 md5_hmac_starts( &ctx, buf, buflen );
00553 }
00554 else
00555 md5_hmac_starts( &ctx, md5_hmac_test_key[i],
00556 md5_hmac_test_keylen[i] );
00557
00558 md5_hmac_update( &ctx, md5_hmac_test_buf[i],
00559 md5_hmac_test_buflen[i] );
00560
00561 md5_hmac_finish( &ctx, md5sum );
00562
00563 buflen = ( i == 4 ) ? 12 : 16;
00564
00565 if( memcmp( md5sum, md5_hmac_test_sum[i], buflen ) != 0 )
00566 {
00567 if( verbose != 0 )
00568 printf( "failed\n" );
00569
00570 return( 1 );
00571 }
00572
00573 if( verbose != 0 )
00574 printf( "passed\n" );
00575 }
00576
00577 if( verbose != 0 )
00578 printf( "\n" );
00579
00580 return( 0 );
00581 }
00582
00583 #endif
00584
00585 #endif