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 #ifndef _CRT_SECURE_NO_DEPRECATE
00031 #define _CRT_SECURE_NO_DEPRECATE 1
00032 #endif
00033
00034 #include <string.h>
00035 #include <stdio.h>
00036
00037 #include "xyssl/md4.h"
00038
00039
00040
00041
00042 #ifndef GET_UINT32_LE
00043 #define GET_UINT32_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_UINT32_LE
00053 #define PUT_UINT32_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_UINT32_LE( X[ 0], data, 0 );
00081 GET_UINT32_LE( X[ 1], data, 4 );
00082 GET_UINT32_LE( X[ 2], data, 8 );
00083 GET_UINT32_LE( X[ 3], data, 12 );
00084 GET_UINT32_LE( X[ 4], data, 16 );
00085 GET_UINT32_LE( X[ 5], data, 20 );
00086 GET_UINT32_LE( X[ 6], data, 24 );
00087 GET_UINT32_LE( X[ 7], data, 28 );
00088 GET_UINT32_LE( X[ 8], data, 32 );
00089 GET_UINT32_LE( X[ 9], data, 36 );
00090 GET_UINT32_LE( X[10], data, 40 );
00091 GET_UINT32_LE( X[11], data, 44 );
00092 GET_UINT32_LE( X[12], data, 48 );
00093 GET_UINT32_LE( X[13], data, 52 );
00094 GET_UINT32_LE( X[14], data, 56 );
00095 GET_UINT32_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 )
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_UINT32_LE( low, msglen, 0 );
00245 PUT_UINT32_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_UINT32_LE( ctx->state[0], output, 0 );
00254 PUT_UINT32_LE( ctx->state[1], output, 4 );
00255 PUT_UINT32_LE( ctx->state[2], output, 8 );
00256 PUT_UINT32_LE( ctx->state[3], output, 12 );
00257 }
00258
00259
00260
00261
00262 void md4( unsigned char *input, int ilen,
00263 unsigned char *output )
00264 {
00265 md4_context ctx;
00266
00267 md4_starts( &ctx );
00268 md4_update( &ctx, input, ilen );
00269 md4_finish( &ctx, output );
00270
00271 memset( &ctx, 0, sizeof( md4_context ) );
00272 }
00273
00274
00275
00276
00277 int md4_file( char *path, unsigned char *output )
00278 {
00279 FILE *f;
00280 size_t n;
00281 md4_context ctx;
00282 unsigned char buf[1024];
00283
00284 if( ( f = fopen( path, "rb" ) ) == NULL )
00285 return( 1 );
00286
00287 md4_starts( &ctx );
00288
00289 while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
00290 md4_update( &ctx, buf, (int) n );
00291
00292 md4_finish( &ctx, output );
00293
00294 memset( &ctx, 0, sizeof( md4_context ) );
00295
00296 if( ferror( f ) != 0 )
00297 {
00298 fclose( f );
00299 return( 2 );
00300 }
00301
00302 fclose( f );
00303 return( 0 );
00304 }
00305
00306
00307
00308
00309 void md4_hmac_starts( md4_context *ctx,
00310 unsigned char *key, int keylen )
00311 {
00312 int i;
00313
00314 memset( ctx->ipad, 0x36, 64 );
00315 memset( ctx->opad, 0x5C, 64 );
00316
00317 for( i = 0; i < keylen; i++ )
00318 {
00319 if( i >= 64 ) break;
00320
00321 ctx->ipad[i] ^= key[i];
00322 ctx->opad[i] ^= key[i];
00323 }
00324
00325 md4_starts( ctx );
00326 md4_update( ctx, ctx->ipad, 64 );
00327 }
00328
00329
00330
00331
00332 void md4_hmac_update( md4_context *ctx,
00333 unsigned char *input, int ilen )
00334 {
00335 md4_update( ctx, input, ilen );
00336 }
00337
00338
00339
00340
00341 void md4_hmac_finish( md4_context *ctx, unsigned char *output )
00342 {
00343 unsigned char tmpbuf[16];
00344
00345 md4_finish( ctx, tmpbuf );
00346 md4_starts( ctx );
00347 md4_update( ctx, ctx->opad, 64 );
00348 md4_update( ctx, tmpbuf, 16 );
00349 md4_finish( ctx, output );
00350
00351 memset( tmpbuf, 0, sizeof( tmpbuf ) );
00352 }
00353
00354
00355
00356
00357 void md4_hmac( unsigned char *key, int keylen,
00358 unsigned char *input, int ilen,
00359 unsigned char *output )
00360 {
00361 md4_context ctx;
00362
00363 md4_hmac_starts( &ctx, key, keylen );
00364 md4_hmac_update( &ctx, input, ilen );
00365 md4_hmac_finish( &ctx, output );
00366
00367 memset( &ctx, 0, sizeof( md4_context ) );
00368 }
00369
00370 static const char _md4_src[] = "_md4_src";
00371
00372 #if defined(SELF_TEST)
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 #else
00440 int md4_self_test( int verbose )
00441 {
00442 return( 0 );
00443 }
00444 #endif