1 /*
2 * RFC 1321 compliant MD5 implementation,
3 * by Christophe Devine <devine@cr0.net>;
4 * this program is licensed under the GPL.
5 */
6
7 #include <string.h>
8 #include "md5.h"
9
10 #define GET_UINT32(n,b,i) \
11 { \
12 (n) = (uint32) ((uint8 *) b)[(i)] \
13 | (((uint32) ((uint8 *) b)[(i)+1]) << 8) \
14 | (((uint32) ((uint8 *) b)[(i)+2]) << 16) \
15 | (((uint32) ((uint8 *) b)[(i)+3]) << 24); \
16 }
17
18 #define PUT_UINT32(n,b,i) \
19 { \
20 (((uint8 *) b)[(i)] ) = (uint8) (((n) ) & 0xFF); \
21 (((uint8 *) b)[(i)+1]) = (uint8) (((n) >> 8) & 0xFF); \
22 (((uint8 *) b)[(i)+2]) = (uint8) (((n) >> 16) & 0xFF); \
23 (((uint8 *) b)[(i)+3]) = (uint8) (((n) >> 24) & 0xFF); \
24 }
25
26 void md5_starts( struct md5_context *ctx )
27 {
28 ctx->total[0] = 0;
29 ctx->total[1] = 0;
30 ctx->state[0] = 0x67452301;
31 ctx->state[1] = 0xEFCDAB89;
32 ctx->state[2] = 0x98BADCFE;
33 ctx->state[3] = 0x10325476;
34 }
35
36 void md5_process( struct md5_context *ctx, uint8 data[64] )
37 {
38 uint32 A, B, C, D, X[16];
39
40 GET_UINT32( X[0], data, 0 );
41 GET_UINT32( X[1], data, 4 );
42 GET_UINT32( X[2], data, 8 );
43 GET_UINT32( X[3], data, 12 );
44 GET_UINT32( X[4], data, 16 );
45 GET_UINT32( X[5], data, 20 );
46 GET_UINT32( X[6], data, 24 );
47 GET_UINT32( X[7], data, 28 );
48 GET_UINT32( X[8], data, 32 );
49 GET_UINT32( X[9], data, 36 );
50 GET_UINT32( X[10], data, 40 );
51 GET_UINT32( X[11], data, 44 );
52 GET_UINT32( X[12], data, 48 );
53 GET_UINT32( X[13], data, 52 );
54 GET_UINT32( X[14], data, 56 );
55 GET_UINT32( X[15], data, 60 );
56
57 #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
58
59 #define P(a,b,c,d,k,s,t) \
60 { \
61 a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \
62 }
63
64 A = ctx->state[0];
65 B = ctx->state[1];
66 C = ctx->state[2];
67 D = ctx->state[3];
68
69 #define F(x,y,z) (z ^ (x & (y ^ z)))
70
71 P( A, B, C, D, 0, 7, 0xD76AA478 );
72 P( D, A, B, C, 1, 12, 0xE8C7B756 );
73 P( C, D, A, B, 2, 17, 0x242070DB );
74 P( B, C, D, A, 3, 22, 0xC1BDCEEE );
75 P( A, B, C, D, 4, 7, 0xF57C0FAF );
76 P( D, A, B, C, 5, 12, 0x4787C62A );
77 P( C, D, A, B, 6, 17, 0xA8304613 );
78 P( B, C, D, A, 7, 22, 0xFD469501 );
79 P( A, B, C, D, 8, 7, 0x698098D8 );
80 P( D, A, B, C, 9, 12, 0x8B44F7AF );
81 P( C, D, A, B, 10, 17, 0xFFFF5BB1 );
82 P( B, C, D, A, 11, 22, 0x895CD7BE );
83 P( A, B, C, D, 12, 7, 0x6B901122 );
84 P( D, A, B, C, 13, 12, 0xFD987193 );
85 P( C, D, A, B, 14, 17, 0xA679438E );
86 P( B, C, D, A, 15, 22, 0x49B40821 );
87
88 #undef F
89
90 #define F(x,y,z) (y ^ (z & (x ^ y)))
91
92 P( A, B, C, D, 1, 5, 0xF61E2562 );
93 P( D, A, B, C, 6, 9, 0xC040B340 );
94 P( C, D, A, B, 11, 14, 0x265E5A51 );
95 P( B, C, D, A, 0, 20, 0xE9B6C7AA );
96 P( A, B, C, D, 5, 5, 0xD62F105D );
97 P( D, A, B, C, 10, 9, 0x02441453 );
98 P( C, D, A, B, 15, 14, 0xD8A1E681 );
99 P( B, C, D, A, 4, 20, 0xE7D3FBC8 );
100 P( A, B, C, D, 9, 5, 0x21E1CDE6 );
101 P( D, A, B, C, 14, 9, 0xC33707D6 );
102 P( C, D, A, B, 3, 14, 0xF4D50D87 );
103 P( B, C, D, A, 8, 20, 0x455A14ED );
104 P( A, B, C, D, 13, 5, 0xA9E3E905 );
105 P( D, A, B, C, 2, 9, 0xFCEFA3F8 );
106 P( C, D, A, B, 7, 14, 0x676F02D9 );
107 P( B, C, D, A, 12, 20, 0x8D2A4C8A );
108
109 #undef F
110
111 #define F(x,y,z) (x ^ y ^ z)
112
113 P( A, B, C, D, 5, 4, 0xFFFA3942 );
114 P( D, A, B, C, 8, 11, 0x8771F681 );
115 P( C, D, A, B, 11, 16, 0x6D9D6122 );
116 P( B, C, D, A, 14, 23, 0xFDE5380C );
117 P( A, B, C, D, 1, 4, 0xA4BEEA44 );
118 P( D, A, B, C, 4, 11, 0x4BDECFA9 );
119 P( C, D, A, B, 7, 16, 0xF6BB4B60 );
120 P( B, C, D, A, 10, 23, 0xBEBFBC70 );
121 P( A, B, C, D, 13, 4, 0x289B7EC6 );
122 P( D, A, B, C, 0, 11, 0xEAA127FA );
123 P( C, D, A, B, 3, 16, 0xD4EF3085 );
124 P( B, C, D, A, 6, 23, 0x04881D05 );
125 P( A, B, C, D, 9, 4, 0xD9D4D039 );
126 P( D, A, B, C, 12, 11, 0xE6DB99E5 );
127 P( C, D, A, B, 15, 16, 0x1FA27CF8 );
128 P( B, C, D, A, 2, 23, 0xC4AC5665 );
129
130 #undef F
131
132 #define F(x,y,z) (y ^ (x | ~z))
133
134 P( A, B, C, D, 0, 6, 0xF4292244 );
135 P( D, A, B, C, 7, 10, 0x432AFF97 );
136 P( C, D, A, B, 14, 15, 0xAB9423A7 );
137 P( B, C, D, A, 5, 21, 0xFC93A039 );
138 P( A, B, C, D, 12, 6, 0x655B59C3 );
139 P( D, A, B, C, 3, 10, 0x8F0CCC92 );
140 P( C, D, A, B, 10, 15, 0xFFEFF47D );
141 P( B, C, D, A, 1, 21, 0x85845DD1 );
142 P( A, B, C, D, 8, 6, 0x6FA87E4F );
143 P( D, A, B, C, 15, 10, 0xFE2CE6E0 );
144 P( C, D, A, B, 6, 15, 0xA3014314 );
145 P( B, C, D, A, 13, 21, 0x4E0811A1 );
146 P( A, B, C, D, 4, 6, 0xF7537E82 );
147 P( D, A, B, C, 11, 10, 0xBD3AF235 );
148 P( C, D, A, B, 2, 15, 0x2AD7D2BB );
149 P( B, C, D, A, 9, 21, 0xEB86D391 );
150
151 #undef F
152
153 ctx->state[0] += A;
154 ctx->state[1] += B;
155 ctx->state[2] += C;
156 ctx->state[3] += D;
157 }
158
159 void md5_update( struct md5_context *ctx, uint8 *input, uint32 length )
160 {
161 uint32 left, fill;
162
163 if( ! length ) return;
164
165 left = ( ctx->total[0] >> 3 ) & 0x3F;
166 fill = 64 - left;
167
168 ctx->total[0] += length << 3;
169 ctx->total[1] += length >> 29;
170
171 ctx->total[0] &= 0xFFFFFFFF;
172 ctx->total[1] += ctx->total[0] < ( length << 3 );
173
174 if( left && length >= fill )
175 {
176 memcpy( (void *) (ctx->buffer + left), (void *) input, fill );
177 md5_process( ctx, ctx->buffer );
178 length -= fill;
179 input += fill;
180 left = 0;
181 }
182
183 while( length >= 64 )
184 {
185 md5_process( ctx, input );
186 length -= 64;
187 input += 64;
188 }
189
190 if( length )
191 {
192 memcpy( (void *) (ctx->buffer + left), (void *) input, length );
193 }
194 }
195
196 static uint8 md5_padding[64] =
197 {
198 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
199 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
200 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
201 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
202 };
203
204 void md5_finish( struct md5_context *ctx, uint8 digest[16] )
205 {
206 uint32 last, padn;
207 uint8 msglen[8];
208
209 PUT_UINT32( ctx->total[0], msglen, 0 );
210 PUT_UINT32( ctx->total[1], msglen, 4 );
211
212 last = ( ctx->total[0] >> 3 ) & 0x3F;
213 padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
214
215 md5_update( ctx, md5_padding, padn );
216 md5_update( ctx, msglen, 8 );
217
218 PUT_UINT32( ctx->state[0], digest, 0 );
219 PUT_UINT32( ctx->state[1], digest, 4 );
220 PUT_UINT32( ctx->state[2], digest, 8 );
221 PUT_UINT32( ctx->state[3], digest, 12 );
222 }
223
224 #ifdef TEST
225
226 #include <stdio.h>
227
228 /*
229 * those are the standard RFC 1321 test vectors
230 */
231
232 static char *msg[] =
233 {
234 "",
235 "a",
236 "abc",
237 "message digest",
238 "abcdefghijklmnopqrstuvwxyz",
239 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
240 "12345678901234567890123456789012345678901234567890123456789012" \
241 "345678901234567890"
242 };
243
244 static char *val[] =
245 {
246 "d41d8cd98f00b204e9800998ecf8427e",
247 "0cc175b9c0f1b6a831c399e269772661",
248 "900150983cd24fb0d6963f7d28e17f72",
249 "f96b697d7cb7938d525a2f31aaf161d0",
250 "c3fcd3d76192e4007dfb496cca67e13b",
251 "d174ab98d277d9f5a5611c2c9f419d9f",
252 "57edf4a22be3c955ac49da2e2107b67a"
253 };
254
255 int main( int argc, char *argv[] )
256 {
257 FILE *f;
258 int i, j;
259 char output[33];
260 struct md5_context ctx;
261 unsigned char md5sum[16], buffer[1000];
262
263 if( argc < 2 )
264 {
265 for( i = 0; i < 7; i++ )
266 {
267 md5_starts( &ctx );
268 md5_update( &ctx, (uint8 *) msg[i], strlen( msg[i] ) );
269 md5_finish( &ctx, md5sum );
270
271 for( j = 0; j < 16; j++ )
272 {
273 sprintf( output + j * 2, "%02x", md5sum[j] );
274 }
275
276 printf( "test %d ", i + 1 );
277
278 if( ! memcmp( output, val[i], 32 ) )
279 {
280 printf( "passed\n" );
281 }
282 else
283 {
284 printf( "failed\n" );
285 return( 1 );
286 }
287 }
288 }
289 else
290 {
291 if( ! ( f = fopen( argv[1], "rb" ) ) )
292 {
293 perror( "fopen" );
294 return( 1 );
295 }
296
297 md5_starts( &ctx );
298
299 while( ( i = fread( buffer, 1, sizeof( buffer ), f ) ) > 0 )
300 {
301 md5_update( &ctx, buffer, i );
302 }
303
304 md5_finish( &ctx, md5sum );
305
306 for( j = 0; j < 16; j++ )
307 {
308 printf( "%02x", md5sum[j] );
309 }
310
311 printf( " %s\n", argv[1] );
312 }
313
314 return( 0 );
315 }
316
317 #endif
|