/home/dko/projects/mobilec/tags/MobileC-v1.10.2/MobileC-v1.10.2/src/security/xyssl-0.9/library/md4.c

Go to the documentation of this file.
00001 /*
00002  *  RFC 1186/1320 compliant MD4 implementation
00003  *
00004  *  Copyright (C) 2006-2007  Christophe Devine
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; either version 2 of the License, or
00009  *  (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License along
00017  *  with this program; if not, write to the Free Software Foundation, Inc.,
00018  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00019  */
00020 /*
00021  *  The MD4 algorithm was designed by Ron Rivest in 1990.
00022  *
00023  *  http://www.ietf.org/rfc/rfc1186.txt
00024  *  http://www.ietf.org/rfc/rfc1320.txt
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  * 32-bit integer manipulation macros (little endian)
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  * MD4 context setup
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  * MD4 process buffer
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  * MD4 final digest
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  * output = MD4( input buffer )
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  * output = MD4( file contents )
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  * MD4 HMAC context setup
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  * MD4 HMAC process buffer
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  * MD4 HMAC final digest
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  * output = HMAC-MD4( hmac key, input buffer )
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  * 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 
00440 #endif
00441 
00442 #endif

Generated on Fri Jul 11 17:59:46 2008 for Mobile-C by  doxygen 1.5.4