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 #include "polarssl/config.h"
00031
00032 #if defined(POLARSSL_MD4_C)
00033
00034 #include "polarssl/md4.h"
00035
00036 #include <string.h>
00037 #include <stdio.h>
00038
00039
00040
00041
00042 #ifndef GET_ULONG_LE
00043 #define GET_ULONG_LE(n,b,i) \
00044 { \
00045 (n) = ( (unsigned long) (b)[(i) ] ) \
00046 | ( (unsigned long) (b)[(i) + 1] << 8 ) \
00047 | ( (unsigned long) (b)[(i) + 2] << 16 ) \
00048 | ( (unsigned long) (b)[(i) + 3] << 24 ); \
00049 }
00050 #endif
00051
00052 #ifndef PUT_ULONG_LE
00053 #define PUT_ULONG_LE(n,b,i) \
00054 { \
00055 (b)[(i) ] = (unsigned char) ( (n) ); \
00056 (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \
00057 (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \
00058 (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \
00059 }
00060 #endif
00061
00062
00063
00064
00065 void md4_starts( md4_context *ctx )
00066 {
00067 ctx->total[0] = 0;
00068 ctx->total[1] = 0;
00069
00070 ctx->state[0] = 0x67452301;
00071 ctx->state[1] = 0xEFCDAB89;
00072 ctx->state[2] = 0x98BADCFE;
00073 ctx->state[3] = 0x10325476;
00074 }
00075
00076 static void md4_process( md4_context *ctx, unsigned char data[64] )
00077 {
00078 unsigned long X[16], A, B, C, D;
00079
00080 GET_ULONG_LE( X[ 0], data, 0 );
00081 GET_ULONG_LE( X[ 1], data, 4 );
00082 GET_ULONG_LE( X[ 2], data, 8 );
00083 GET_ULONG_LE( X[ 3], data, 12 );
00084 GET_ULONG_LE( X[ 4], data, 16 );
00085 GET_ULONG_LE( X[ 5], data, 20 );
00086 GET_ULONG_LE( X[ 6], data, 24 );
00087 GET_ULONG_LE( X[ 7], data, 28 );
00088 GET_ULONG_LE( X[ 8], data, 32 );
00089 GET_ULONG_LE( X[ 9], data, 36 );
00090 GET_ULONG_LE( X[10], data, 40 );
00091 GET_ULONG_LE( X[11], data, 44 );
00092 GET_ULONG_LE( X[12], data, 48 );
00093 GET_ULONG_LE( X[13], data, 52 );
00094 GET_ULONG_LE( X[14], data, 56 );
00095 GET_ULONG_LE( X[15], data, 60 );
00096
00097 #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
00098
00099 A = ctx->state[0];
00100 B = ctx->state[1];
00101 C = ctx->state[2];
00102 D = ctx->state[3];
00103
00104 #define F(x, y, z) ((x & y) | ((~x) & z))
00105 #define P(a,b,c,d,x,s) { a += F(b,c,d) + x; a = S(a,s); }
00106
00107 P( A, B, C, D, X[ 0], 3 );
00108 P( D, A, B, C, X[ 1], 7 );
00109 P( C, D, A, B, X[ 2], 11 );
00110 P( B, C, D, A, X[ 3], 19 );
00111 P( A, B, C, D, X[ 4], 3 );
00112 P( D, A, B, C, X[ 5], 7 );
00113 P( C, D, A, B, X[ 6], 11 );
00114 P( B, C, D, A, X[ 7], 19 );
00115 P( A, B, C, D, X[ 8], 3 );
00116 P( D, A, B, C, X[ 9], 7 );
00117 P( C, D, A, B, X[10], 11 );
00118 P( B, C, D, A, X[11], 19 );
00119 P( A, B, C, D, X[12], 3 );
00120 P( D, A, B, C, X[13], 7 );
00121 P( C, D, A, B, X[14], 11 );
00122 P( B, C, D, A, X[15], 19 );
00123
00124 #undef P
00125 #undef F
00126
00127 #define F(x,y,z) ((x & y) | (x & z) | (y & z))
00128 #define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x5A827999; a = S(a,s); }
00129
00130 P( A, B, C, D, X[ 0], 3 );
00131 P( D, A, B, C, X[ 4], 5 );
00132 P( C, D, A, B, X[ 8], 9 );
00133 P( B, C, D, A, X[12], 13 );
00134 P( A, B, C, D, X[ 1], 3 );
00135 P( D, A, B, C, X[ 5], 5 );
00136 P( C, D, A, B, X[ 9], 9 );
00137 P( B, C, D, A, X[13], 13 );
00138 P( A, B, C, D, X[ 2], 3 );
00139 P( D, A, B, C, X[ 6], 5 );
00140 P( C, D, A, B, X[10], 9 );
00141 P( B, C, D, A, X[14], 13 );
00142 P( A, B, C, D, X[ 3], 3 );
00143 P( D, A, B, C, X[ 7], 5 );
00144 P( C, D, A, B, X[11], 9 );
00145 P( B, C, D, A, X[15], 13 );
00146
00147 #undef P
00148 #undef F
00149
00150 #define F(x,y,z) (x ^ y ^ z)
00151 #define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x6ED9EBA1; a = S(a,s); }
00152
00153 P( A, B, C, D, X[ 0], 3 );
00154 P( D, A, B, C, X[ 8], 9 );
00155 P( C, D, A, B, X[ 4], 11 );
00156 P( B, C, D, A, X[12], 15 );
00157 P( A, B, C, D, X[ 2], 3 );
00158 P( D, A, B, C, X[10], 9 );
00159 P( C, D, A, B, X[ 6], 11 );
00160 P( B, C, D, A, X[14], 15 );
00161 P( A, B, C, D, X[ 1], 3 );
00162 P( D, A, B, C, X[ 9], 9 );
00163 P( C, D, A, B, X[ 5], 11 );
00164 P( B, C, D, A, X[13], 15 );
00165 P( A, B, C, D, X[ 3], 3 );
00166 P( D, A, B, C, X[11], 9 );
00167 P( C, D, A, B, X[ 7], 11 );
00168 P( B, C, D, A, X[15], 15 );
00169
00170 #undef F
00171 #undef P
00172
00173 ctx->state[0] += A;
00174 ctx->state[1] += B;
00175 ctx->state[2] += C;
00176 ctx->state[3] += D;
00177 }
00178
00179
00180
00181
00182 void md4_update( md4_context *ctx, unsigned char *input, int ilen )
00183 {
00184 int fill;
00185 unsigned long left;
00186
00187 if( ilen <= 0 )
00188 return;
00189
00190 left = ctx->total[0] & 0x3F;
00191 fill = 64 - left;
00192
00193 ctx->total[0] += ilen;
00194 ctx->total[0] &= 0xFFFFFFFF;
00195
00196 if( ctx->total[0] < (unsigned long) ilen )
00197 ctx->total[1]++;
00198
00199 if( left && ilen >= fill )
00200 {
00201 memcpy( (void *) (ctx->buffer + left),
00202 (void *) input, fill );
00203 md4_process( ctx, ctx->buffer );
00204 input += fill;
00205 ilen -= fill;
00206 left = 0;
00207 }
00208
00209 while( ilen >= 64 )
00210 {
00211 md4_process( ctx, input );
00212 input += 64;
00213 ilen -= 64;
00214 }
00215
00216 if( ilen > 0 )
00217 {
00218 memcpy( (void *) (ctx->buffer + left),
00219 (void *) input, ilen );
00220 }
00221 }
00222
00223 static const unsigned char md4_padding[64] =
00224 {
00225 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00226 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00227 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00228 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00229 };
00230
00231
00232
00233
00234 void md4_finish( md4_context *ctx, unsigned char output[16] )
00235 {
00236 unsigned long last, padn;
00237 unsigned long high, low;
00238 unsigned char msglen[8];
00239
00240 high = ( ctx->total[0] >> 29 )
00241 | ( ctx->total[1] << 3 );
00242 low = ( ctx->total[0] << 3 );
00243
00244 PUT_ULONG_LE( low, msglen, 0 );
00245 PUT_ULONG_LE( high, msglen, 4 );
00246
00247 last = ctx->total[0] & 0x3F;
00248 padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
00249
00250 md4_update( ctx, (unsigned char *) md4_padding, padn );
00251 md4_update( ctx, msglen, 8 );
00252
00253 PUT_ULONG_LE( ctx->state[0], output, 0 );
00254 PUT_ULONG_LE( ctx->state[1], output, 4 );
00255 PUT_ULONG_LE( ctx->state[2], output, 8 );
00256 PUT_ULONG_LE( ctx->state[3], output, 12 );
00257 }
00258
00259
00260
00261
00262 void md4( unsigned char *input, int ilen, unsigned char output[16] )
00263 {
00264 md4_context ctx;
00265
00266 md4_starts( &ctx );
00267 md4_update( &ctx, input, ilen );
00268 md4_finish( &ctx, output );
00269
00270 memset( &ctx, 0, sizeof( md4_context ) );
00271 }
00272
00273
00274
00275
00276 int md4_file( char *path, unsigned char output[16] )
00277 {
00278 FILE *f;
00279 size_t n;
00280 md4_context ctx;
00281 unsigned char buf[1024];
00282
00283 if( ( f = fopen( path, "rb" ) ) == NULL )
00284 return( 1 );
00285
00286 md4_starts( &ctx );
00287
00288 while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
00289 md4_update( &ctx, buf, (int) n );
00290
00291 md4_finish( &ctx, output );
00292
00293 memset( &ctx, 0, sizeof( md4_context ) );
00294
00295 if( ferror( f ) != 0 )
00296 {
00297 fclose( f );
00298 return( 2 );
00299 }
00300
00301 fclose( f );
00302 return( 0 );
00303 }
00304
00305
00306
00307
00308 void md4_hmac_starts( md4_context *ctx, unsigned char *key, int keylen )
00309 {
00310 int i;
00311 unsigned char sum[16];
00312
00313 if( keylen > 64 )
00314 {
00315 md4( key, keylen, sum );
00316 keylen = 16;
00317 key = sum;
00318 }
00319
00320 memset( ctx->ipad, 0x36, 64 );
00321 memset( ctx->opad, 0x5C, 64 );
00322
00323 for( i = 0; i < keylen; i++ )
00324 {
00325 ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
00326 ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
00327 }
00328
00329 md4_starts( ctx );
00330 md4_update( ctx, ctx->ipad, 64 );
00331
00332 memset( sum, 0, sizeof( sum ) );
00333 }
00334
00335
00336
00337
00338 void md4_hmac_update( md4_context *ctx, unsigned char *input, int ilen )
00339 {
00340 md4_update( ctx, input, ilen );
00341 }
00342
00343
00344
00345
00346 void md4_hmac_finish( md4_context *ctx, unsigned char output[16] )
00347 {
00348 unsigned char tmpbuf[16];
00349
00350 md4_finish( ctx, tmpbuf );
00351 md4_starts( ctx );
00352 md4_update( ctx, ctx->opad, 64 );
00353 md4_update( ctx, tmpbuf, 16 );
00354 md4_finish( ctx, output );
00355
00356 memset( tmpbuf, 0, sizeof( tmpbuf ) );
00357 }
00358
00359
00360
00361
00362 void md4_hmac( unsigned char *key, int keylen, unsigned char *input, int ilen,
00363 unsigned char output[16] )
00364 {
00365 md4_context ctx;
00366
00367 md4_hmac_starts( &ctx, key, keylen );
00368 md4_hmac_update( &ctx, input, ilen );
00369 md4_hmac_finish( &ctx, output );
00370
00371 memset( &ctx, 0, sizeof( md4_context ) );
00372 }
00373
00374 #if defined(POLARSSL_SELF_TEST)
00375
00376
00377
00378
00379 static const char md4_test_str[7][81] =
00380 {
00381 { "" },
00382 { "a" },
00383 { "abc" },
00384 { "message digest" },
00385 { "abcdefghijklmnopqrstuvwxyz" },
00386 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
00387 { "12345678901234567890123456789012345678901234567890123456789012" \
00388 "345678901234567890" }
00389 };
00390
00391 static const unsigned char md4_test_sum[7][16] =
00392 {
00393 { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31,
00394 0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 },
00395 { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46,
00396 0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 },
00397 { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52,
00398 0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D },
00399 { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8,
00400 0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B },
00401 { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD,
00402 0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 },
00403 { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35,
00404 0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 },
00405 { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19,
00406 0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 }
00407 };
00408
00409
00410
00411
00412 int md4_self_test( int verbose )
00413 {
00414 int i;
00415 unsigned char md4sum[16];
00416
00417 for( i = 0; i < 7; i++ )
00418 {
00419 if( verbose != 0 )
00420 printf( " MD4 test #%d: ", i + 1 );
00421
00422 md4( (unsigned char *) md4_test_str[i],
00423 strlen( md4_test_str[i] ), md4sum );
00424
00425 if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 )
00426 {
00427 if( verbose != 0 )
00428 printf( "failed\n" );
00429
00430 return( 1 );
00431 }
00432
00433 if( verbose != 0 )
00434 printf( "passed\n" );
00435 }
00436
00437 if( verbose != 0 )
00438 printf( "\n" );
00439
00440 return( 0 );
00441 }
00442
00443 #endif
00444
00445 #endif