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