lib/md5.c

Go to the documentation of this file.
00001 /*
00002  * RFC 1321 compliant MD5 implementation,
00003  * by Christophe Devine <devine@cr0.net>;
00004  * this program is licensed under the GPL.
00005  */
00006 
00007 #include "common.h"
00008 #include "md5.h"
00009 
00010 static char const rcsid[] = "$Id: md5.c,v 1.4 2003/05/06 07:33:43 kate Exp $";
00011 
00012 #define GET_UINT32(n,b,i)                                       \
00013 {                                                               \
00014     (n) = (uint32) ((uint8 *) b)[(i)]                           \
00015       | (((uint32) ((uint8 *) b)[(i)+1]) <<  8)                 \
00016       | (((uint32) ((uint8 *) b)[(i)+2]) << 16)                 \
00017       | (((uint32) ((uint8 *) b)[(i)+3]) << 24);                \
00018 }
00019 
00020 #define PUT_UINT32(n,b,i)                                       \
00021 {                                                               \
00022     (((uint8 *) b)[(i)]  ) = (uint8) (((n)      ) & 0xFF);      \
00023     (((uint8 *) b)[(i)+1]) = (uint8) (((n) >>  8) & 0xFF);      \
00024     (((uint8 *) b)[(i)+2]) = (uint8) (((n) >> 16) & 0xFF);      \
00025     (((uint8 *) b)[(i)+3]) = (uint8) (((n) >> 24) & 0xFF);      \
00026 }
00027 
00028 void md5_starts( struct md5_context *ctx )
00029 {
00030     ctx->total = 0;
00031     ctx->state[0] = 0x67452301;
00032     ctx->state[1] = 0xEFCDAB89;
00033     ctx->state[2] = 0x98BADCFE;
00034     ctx->state[3] = 0x10325476;
00035 }
00036 
00037 void md5_process( struct md5_context *ctx, uint8 data[64] )
00038 {
00039     uint32 A, B, C, D, X[16];
00040 
00041     GET_UINT32( X[0],  data,  0 );
00042     GET_UINT32( X[1],  data,  4 );
00043     GET_UINT32( X[2],  data,  8 );
00044     GET_UINT32( X[3],  data, 12 );
00045     GET_UINT32( X[4],  data, 16 );
00046     GET_UINT32( X[5],  data, 20 );
00047     GET_UINT32( X[6],  data, 24 );
00048     GET_UINT32( X[7],  data, 28 );
00049     GET_UINT32( X[8],  data, 32 );
00050     GET_UINT32( X[9],  data, 36 );
00051     GET_UINT32( X[10], data, 40 );
00052     GET_UINT32( X[11], data, 44 );
00053     GET_UINT32( X[12], data, 48 );
00054     GET_UINT32( X[13], data, 52 );
00055     GET_UINT32( X[14], data, 56 );
00056     GET_UINT32( X[15], data, 60 );
00057 
00058 #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
00059 
00060 #define P(a,b,c,d,k,s,t)                                \
00061 {                                                       \
00062     a += F(b,c,d) + X[k] + t; a = S(a,s) + b;           \
00063 }
00064 
00065     A = ctx->state[0];
00066     B = ctx->state[1];
00067     C = ctx->state[2];
00068     D = ctx->state[3];
00069 
00070 #define F(x,y,z) (z ^ (x & (y ^ z)))
00071 
00072     P( A, B, C, D,  0,  7, 0xD76AA478 );
00073     P( D, A, B, C,  1, 12, 0xE8C7B756 );
00074     P( C, D, A, B,  2, 17, 0x242070DB );
00075     P( B, C, D, A,  3, 22, 0xC1BDCEEE );
00076     P( A, B, C, D,  4,  7, 0xF57C0FAF );
00077     P( D, A, B, C,  5, 12, 0x4787C62A );
00078     P( C, D, A, B,  6, 17, 0xA8304613 );
00079     P( B, C, D, A,  7, 22, 0xFD469501 );
00080     P( A, B, C, D,  8,  7, 0x698098D8 );
00081     P( D, A, B, C,  9, 12, 0x8B44F7AF );
00082     P( C, D, A, B, 10, 17, 0xFFFF5BB1 );
00083     P( B, C, D, A, 11, 22, 0x895CD7BE );
00084     P( A, B, C, D, 12,  7, 0x6B901122 );
00085     P( D, A, B, C, 13, 12, 0xFD987193 );
00086     P( C, D, A, B, 14, 17, 0xA679438E );
00087     P( B, C, D, A, 15, 22, 0x49B40821 );
00088 
00089 #undef F
00090 
00091 #define F(x,y,z) (y ^ (z & (x ^ y)))
00092 
00093     P( A, B, C, D,  1,  5, 0xF61E2562 );
00094     P( D, A, B, C,  6,  9, 0xC040B340 );
00095     P( C, D, A, B, 11, 14, 0x265E5A51 );
00096     P( B, C, D, A,  0, 20, 0xE9B6C7AA );
00097     P( A, B, C, D,  5,  5, 0xD62F105D );
00098     P( D, A, B, C, 10,  9, 0x02441453 );
00099     P( C, D, A, B, 15, 14, 0xD8A1E681 );
00100     P( B, C, D, A,  4, 20, 0xE7D3FBC8 );
00101     P( A, B, C, D,  9,  5, 0x21E1CDE6 );
00102     P( D, A, B, C, 14,  9, 0xC33707D6 );
00103     P( C, D, A, B,  3, 14, 0xF4D50D87 );
00104     P( B, C, D, A,  8, 20, 0x455A14ED );
00105     P( A, B, C, D, 13,  5, 0xA9E3E905 );
00106     P( D, A, B, C,  2,  9, 0xFCEFA3F8 );
00107     P( C, D, A, B,  7, 14, 0x676F02D9 );
00108     P( B, C, D, A, 12, 20, 0x8D2A4C8A );
00109 
00110 #undef F
00111     
00112 #define F(x,y,z) (x ^ y ^ z)
00113 
00114     P( A, B, C, D,  5,  4, 0xFFFA3942 );
00115     P( D, A, B, C,  8, 11, 0x8771F681 );
00116     P( C, D, A, B, 11, 16, 0x6D9D6122 );
00117     P( B, C, D, A, 14, 23, 0xFDE5380C );
00118     P( A, B, C, D,  1,  4, 0xA4BEEA44 );
00119     P( D, A, B, C,  4, 11, 0x4BDECFA9 );
00120     P( C, D, A, B,  7, 16, 0xF6BB4B60 );
00121     P( B, C, D, A, 10, 23, 0xBEBFBC70 );
00122     P( A, B, C, D, 13,  4, 0x289B7EC6 );
00123     P( D, A, B, C,  0, 11, 0xEAA127FA );
00124     P( C, D, A, B,  3, 16, 0xD4EF3085 );
00125     P( B, C, D, A,  6, 23, 0x04881D05 );
00126     P( A, B, C, D,  9,  4, 0xD9D4D039 );
00127     P( D, A, B, C, 12, 11, 0xE6DB99E5 );
00128     P( C, D, A, B, 15, 16, 0x1FA27CF8 );
00129     P( B, C, D, A,  2, 23, 0xC4AC5665 );
00130 
00131 #undef F
00132 
00133 #define F(x,y,z) (y ^ (x | ~z))
00134 
00135     P( A, B, C, D,  0,  6, 0xF4292244 );
00136     P( D, A, B, C,  7, 10, 0x432AFF97 );
00137     P( C, D, A, B, 14, 15, 0xAB9423A7 );
00138     P( B, C, D, A,  5, 21, 0xFC93A039 );
00139     P( A, B, C, D, 12,  6, 0x655B59C3 );
00140     P( D, A, B, C,  3, 10, 0x8F0CCC92 );
00141     P( C, D, A, B, 10, 15, 0xFFEFF47D );
00142     P( B, C, D, A,  1, 21, 0x85845DD1 );
00143     P( A, B, C, D,  8,  6, 0x6FA87E4F );
00144     P( D, A, B, C, 15, 10, 0xFE2CE6E0 );
00145     P( C, D, A, B,  6, 15, 0xA3014314 );
00146     P( B, C, D, A, 13, 21, 0x4E0811A1 );
00147     P( A, B, C, D,  4,  6, 0xF7537E82 );
00148     P( D, A, B, C, 11, 10, 0xBD3AF235 );
00149     P( C, D, A, B,  2, 15, 0x2AD7D2BB );
00150     P( B, C, D, A,  9, 21, 0xEB86D391 );
00151 
00152 #undef F
00153 
00154     ctx->state[0] += A;
00155     ctx->state[1] += B;
00156     ctx->state[2] += C;
00157     ctx->state[3] += D;
00158 }
00159 
00160 void md5_update( struct md5_context *ctx, uint8 *input, uint32 length )
00161 {
00162     uint32 left, fill;
00163 
00164     if( ! length ) return;
00165 
00166     left = (uint32) (ctx->total & 0x3F);
00167     fill = 64 - left;
00168 
00169     ctx->total += length;
00170 
00171     if( left && length >= fill )
00172     {
00173         memcpy( (void *) (ctx->buffer + left), (void *) input, fill );
00174         md5_process( ctx, ctx->buffer );
00175         length -= fill;
00176         input  += fill;
00177         left = 0;
00178     }
00179 
00180     while( length >= 64 )
00181     {
00182         md5_process( ctx, input );
00183         length -= 64;
00184         input  += 64;
00185     }
00186 
00187     if( length )
00188     {
00189         memcpy( (void *) (ctx->buffer + left), (void *) input, length );
00190     }
00191 }
00192 
00193 static uint8 md5_padding[64] =
00194 {
00195  0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00196     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00197     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00198     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00199 };
00200 
00201 void md5_finish( struct md5_context *ctx, uint8 digest[16] )
00202 {
00203     uint32 last, padn;
00204     uint8 msglen[8];
00205 
00206     PUT_UINT32( (uint32) ((ctx->total <<  3) & 0xFFFFFFFF), msglen, 0 );
00207     PUT_UINT32( (uint32) ((ctx->total >> 29) & 0xFFFFFFFF), msglen, 4 );
00208 
00209     last = (uint32) (ctx->total & 0x3F);
00210     padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
00211 
00212     md5_update( ctx, md5_padding, padn );
00213     md5_update( ctx, msglen, 8 );
00214 
00215     PUT_UINT32( ctx->state[0], digest,  0 );
00216     PUT_UINT32( ctx->state[1], digest,  4 );
00217     PUT_UINT32( ctx->state[2], digest,  8 );
00218     PUT_UINT32( ctx->state[3], digest, 12 );
00219 }
00220 
00221 #ifdef TEST
00222 
00223 #include <stdio.h>
00224 
00225 /*
00226  * those are the standard RFC 1321 test vectors
00227  */
00228 
00229 static char *msg[] =
00230 {
00231     "",
00232     "a",
00233     "abc",
00234     "message digest",
00235     "abcdefghijklmnopqrstuvwxyz",
00236     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
00237     "12345678901234567890123456789012345678901234567890123456789012" \
00238         "345678901234567890"
00239 };
00240 
00241 static char *val[] =
00242 {
00243     "d41d8cd98f00b204e9800998ecf8427e",
00244     "0cc175b9c0f1b6a831c399e269772661",
00245     "900150983cd24fb0d6963f7d28e17f72",
00246     "f96b697d7cb7938d525a2f31aaf161d0",
00247     "c3fcd3d76192e4007dfb496cca67e13b",
00248     "d174ab98d277d9f5a5611c2c9f419d9f",
00249     "57edf4a22be3c955ac49da2e2107b67a"
00250 };
00251 
00252 int main( void )
00253 {
00254     int i, j;
00255     char output[33];
00256     struct md5_context ctx;
00257     unsigned char md5sum[16];
00258 
00259     for( i = 0; i < 7; i++ )
00260     {
00261         md5_starts( &ctx );
00262         md5_update( &ctx, (uint8 *) msg[i], strlen( msg[i] ) );
00263         md5_finish( &ctx, md5sum );
00264 
00265         for( j = 0; j < 16; j++ )
00266         {
00267             sprintf( output + j * 2, "%02x", md5sum[j] );
00268         }
00269 
00270         printf( "test %d ", i + 1 );
00271 
00272         if( ! memcmp( output, val[i], 32 ) )
00273         {
00274             printf( "passed\n" );
00275         }
00276         else
00277         {
00278             printf( "failed\n" );
00279             return( 1 );
00280         }
00281     }
00282 
00283     return( 0 );
00284 }
00285 
00286 #endif
00287 
00288 

Generated on Tue Dec 25 18:39:31 2007 for blat by  doxygen 1.5.2