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