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 #ifndef _CRT_SECURE_NO_DEPRECATE
00028 #define _CRT_SECURE_NO_DEPRECATE 1
00029 #endif
00030
00031 #include <string.h>
00032 #include <stdio.h>
00033
00034 #include "xyssl/md4.h"
00035
00036
00037
00038
00039 #ifndef GET_UINT32_LE
00040 #define GET_UINT32_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_UINT32_LE
00050 #define PUT_UINT32_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_UINT32_LE( X[ 0], data, 0 );
00078 GET_UINT32_LE( X[ 1], data, 4 );
00079 GET_UINT32_LE( X[ 2], data, 8 );
00080 GET_UINT32_LE( X[ 3], data, 12 );
00081 GET_UINT32_LE( X[ 4], data, 16 );
00082 GET_UINT32_LE( X[ 5], data, 20 );
00083 GET_UINT32_LE( X[ 6], data, 24 );
00084 GET_UINT32_LE( X[ 7], data, 28 );
00085 GET_UINT32_LE( X[ 8], data, 32 );
00086 GET_UINT32_LE( X[ 9], data, 36 );
00087 GET_UINT32_LE( X[10], data, 40 );
00088 GET_UINT32_LE( X[11], data, 44 );
00089 GET_UINT32_LE( X[12], data, 48 );
00090 GET_UINT32_LE( X[13], data, 52 );
00091 GET_UINT32_LE( X[14], data, 56 );
00092 GET_UINT32_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 )
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_UINT32_LE( low, msglen, 0 );
00242 PUT_UINT32_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_UINT32_LE( ctx->state[0], output, 0 );
00251 PUT_UINT32_LE( ctx->state[1], output, 4 );
00252 PUT_UINT32_LE( ctx->state[2], output, 8 );
00253 PUT_UINT32_LE( ctx->state[3], output, 12 );
00254 }
00255
00256
00257
00258
00259 void md4( unsigned char *input, int ilen,
00260 unsigned char *output )
00261 {
00262 md4_context ctx;
00263
00264 md4_starts( &ctx );
00265 md4_update( &ctx, input, ilen );
00266 md4_finish( &ctx, output );
00267
00268 memset( &ctx, 0, sizeof( md4_context ) );
00269 }
00270
00271
00272
00273
00274 int md4_file( char *path, unsigned char *output )
00275 {
00276 FILE *f;
00277 size_t n;
00278 md4_context ctx;
00279 unsigned char buf[1024];
00280
00281 if( ( f = fopen( path, "rb" ) ) == NULL )
00282 return( 1 );
00283
00284 md4_starts( &ctx );
00285
00286 while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
00287 md4_update( &ctx, buf, (int) n );
00288
00289 md4_finish( &ctx, output );
00290
00291 memset( &ctx, 0, sizeof( md4_context ) );
00292
00293 if( ferror( f ) != 0 )
00294 {
00295 fclose( f );
00296 return( 2 );
00297 }
00298
00299 fclose( f );
00300 return( 0 );
00301 }
00302
00303
00304
00305
00306 void md4_hmac_starts( md4_context *ctx,
00307 unsigned char *key, int keylen )
00308 {
00309 int i;
00310
00311 memset( ctx->ipad, 0x36, 64 );
00312 memset( ctx->opad, 0x5C, 64 );
00313
00314 for( i = 0; i < keylen; i++ )
00315 {
00316 if( i >= 64 ) break;
00317
00318 ctx->ipad[i] ^= key[i];
00319 ctx->opad[i] ^= key[i];
00320 }
00321
00322 md4_starts( ctx );
00323 md4_update( ctx, ctx->ipad, 64 );
00324 }
00325
00326
00327
00328
00329 void md4_hmac_update( md4_context *ctx,
00330 unsigned char *input, int ilen )
00331 {
00332 md4_update( ctx, input, ilen );
00333 }
00334
00335
00336
00337
00338 void md4_hmac_finish( md4_context *ctx, unsigned char *output )
00339 {
00340 unsigned char tmpbuf[16];
00341
00342 md4_finish( ctx, tmpbuf );
00343 md4_starts( ctx );
00344 md4_update( ctx, ctx->opad, 64 );
00345 md4_update( ctx, tmpbuf, 16 );
00346 md4_finish( ctx, output );
00347
00348 memset( tmpbuf, 0, sizeof( tmpbuf ) );
00349 }
00350
00351
00352
00353
00354 void md4_hmac( unsigned char *key, int keylen,
00355 unsigned char *input, int ilen,
00356 unsigned char *output )
00357 {
00358 md4_context ctx;
00359
00360 md4_hmac_starts( &ctx, key, keylen );
00361 md4_hmac_update( &ctx, input, ilen );
00362 md4_hmac_finish( &ctx, output );
00363
00364 memset( &ctx, 0, sizeof( md4_context ) );
00365 }
00366
00367 static const char _md4_src[] = "_md4_src";
00368
00369 #if defined(SELF_TEST)
00370
00371
00372
00373 static const char md4_test_str[7][81] =
00374 {
00375 { "" },
00376 { "a" },
00377 { "abc" },
00378 { "message digest" },
00379 { "abcdefghijklmnopqrstuvwxyz" },
00380 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
00381 { "12345678901234567890123456789012345678901234567890123456789012" \
00382 "345678901234567890" }
00383 };
00384
00385 static const unsigned char md4_test_sum[7][16] =
00386 {
00387 { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31,
00388 0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 },
00389 { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46,
00390 0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 },
00391 { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52,
00392 0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D },
00393 { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8,
00394 0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B },
00395 { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD,
00396 0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 },
00397 { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35,
00398 0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 },
00399 { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19,
00400 0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 }
00401 };
00402
00403
00404
00405
00406 int md4_self_test( int verbose )
00407 {
00408 int i;
00409 unsigned char md4sum[16];
00410
00411 for( i = 0; i < 7; i++ )
00412 {
00413 if( verbose != 0 )
00414 printf( " MD4 test #%d: ", i + 1 );
00415
00416 md4( (unsigned char *) md4_test_str[i],
00417 strlen( md4_test_str[i] ), md4sum );
00418
00419 if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 )
00420 {
00421 if( verbose != 0 )
00422 printf( "failed\n" );
00423
00424 return( 1 );
00425 }
00426
00427 if( verbose != 0 )
00428 printf( "passed\n" );
00429 }
00430
00431 if( verbose != 0 )
00432 printf( "\n" );
00433
00434 return( 0 );
00435 }
00436 #else
00437 int md4_self_test( int verbose )
00438 {
00439 return( 0 );
00440 }
00441 #endif