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