00001
00002
00003
00004
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
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