/home/dko/projects/mobilec/trunk/src/security/xyssl-0.7/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 library is free software; you can redistribute it and/or
00007  *  modify it under the terms of the GNU Lesser General Public
00008  *  License, version 2.1 as published by the Free Software Foundation.
00009  *
00010  *  This library is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  *  Lesser General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU Lesser General Public
00016  *  License along with this library; if not, write to the Free Software
00017  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
00018  *  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 #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  * 32-bit integer manipulation macros (little endian)
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  * 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_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  * 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 )
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  * Output = MD4( input buffer )
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  * Output = MD4( file contents )
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  * MD4 HMAC context setup
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  * MD4 HMAC process buffer
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  * MD4 HMAC final digest
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  * Output = HMAC-MD4( hmac key, input buffer )
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  * RFC 1320 test vectors
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  * Checkup routine
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

Generated on Fri May 16 14:49:55 2008 for Mobile-C by  doxygen 1.5.4