/home/dko/projects/mobilec/trunk/src/security/xyssl-0.7/library/md4.c

Go to the documentation of this file.
00001 /* SVN FILE INFO
00002  * $Revision: 174 $ : Last Committed Revision
00003  * $Date: 2008-06-24 10:50:29 -0700 (Tue, 24 Jun 2008) $ : Last Committed Date */
00004 /*
00005  *  RFC 1186/1320 compliant MD4 implementation
00006  *
00007  *  Copyright (C) 2006-2007  Christophe Devine
00008  *
00009  *  This library is free software; you can redistribute it and/or
00010  *  modify it under the terms of the GNU Lesser General Public
00011  *  License, version 2.1 as published by the Free Software Foundation.
00012  *
00013  *  This library is distributed in the hope that it will be useful,
00014  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  *  Lesser General Public License for more details.
00017  *
00018  *  You should have received a copy of the GNU Lesser General Public
00019  *  License along with this library; if not, write to the Free Software
00020  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
00021  *  MA  02110-1301  USA
00022  */
00023 /*
00024  *  The MD4 algorithm was designed by Ron Rivest in 1990.
00025  *
00026  *  http://www.ietf.org/rfc/rfc1186.txt
00027  *  http://www.ietf.org/rfc/rfc1320.txt
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  * 32-bit integer manipulation macros (little endian)
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  * MD4 context setup
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  * MD4 process buffer
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  * MD4 final digest
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  * Output = MD4( input buffer )
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  * Output = MD4( file contents )
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  * MD4 HMAC context setup
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  * MD4 HMAC process buffer
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  * MD4 HMAC final digest
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  * Output = HMAC-MD4( hmac key, input buffer )
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  * RFC 1320 test vectors
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  * Checkup routine
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

Generated on Tue Jul 1 15:29:59 2008 for Mobile-C by  doxygen 1.5.4