1 /*
2 * RFC 1321 compliant MD5 implementation
3 *
4 * Copyright (C) 2006-2007 Christophe Devine
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License, version 2.1 as published by the Free Software Foundation.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 * MA 02110-1301 USA
19 */
20 /*
21 * The MD5 algorithm was designed by Ron Rivest in 1991.
22 * From the XYSSL project.
23 *
24 * http://www.ietf.org/rfc/rfc1321.txt
25 */
26 #include "md5.h"
27
28 #include <string.h>
29 #include <stdio.h>
30
31 /*
32 * 32-bit integer manipulation macros (little endian)
33 */
34 #ifndef GET_ULONG_LE
35 #define GET_ULONG_LE(n,b,i) \
36 { \
37 (n) = ( (unsigned long) (b)[(i) ] ) \
38 | ( (unsigned long) (b)[(i) + 1] << 8 ) \
39 | ( (unsigned long) (b)[(i) + 2] << 16 ) \
40 | ( (unsigned long) (b)[(i) + 3] << 24 ); \
41 }
42 #endif
43
44 #ifndef PUT_ULONG_LE
45 #define PUT_ULONG_LE(n,b,i) \
46 { \
47 (b)[(i) ] = (unsigned char) ( (n) ); \
48 (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \
49 (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \
50 (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \
51 }
52 #endif
53
54 /*
55 * MD5 context setup
56 */
md5_starts(md5_context * ctx)57 void md5_starts(md5_context * ctx)
58 {
59 ctx->total[0] = 0;
60 ctx->total[1] = 0;
61
62 ctx->state[0] = 0x67452301;
63 ctx->state[1] = 0xEFCDAB89;
64 ctx->state[2] = 0x98BADCFE;
65 ctx->state[3] = 0x10325476;
66 }
67
md5_process(md5_context * ctx,unsigned char data[64])68 static void md5_process(md5_context * ctx, unsigned char data[64])
69 {
70 unsigned long X[16], A, B, C, D;
71
72 GET_ULONG_LE(X[0], data, 0);
73 GET_ULONG_LE(X[1], data, 4);
74 GET_ULONG_LE(X[2], data, 8);
75 GET_ULONG_LE(X[3], data, 12);
76 GET_ULONG_LE(X[4], data, 16);
77 GET_ULONG_LE(X[5], data, 20);
78 GET_ULONG_LE(X[6], data, 24);
79 GET_ULONG_LE(X[7], data, 28);
80 GET_ULONG_LE(X[8], data, 32);
81 GET_ULONG_LE(X[9], data, 36);
82 GET_ULONG_LE(X[10], data, 40);
83 GET_ULONG_LE(X[11], data, 44);
84 GET_ULONG_LE(X[12], data, 48);
85 GET_ULONG_LE(X[13], data, 52);
86 GET_ULONG_LE(X[14], data, 56);
87 GET_ULONG_LE(X[15], data, 60);
88
89 #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
90
91 #define P(a,b,c,d,k,s,t) \
92 { \
93 a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \
94 }
95
96 A = ctx->state[0];
97 B = ctx->state[1];
98 C = ctx->state[2];
99 D = ctx->state[3];
100
101 #define F(x,y,z) (z ^ (x & (y ^ z)))
102
103 P(A, B, C, D, 0, 7, 0xD76AA478);
104 P(D, A, B, C, 1, 12, 0xE8C7B756);
105 P(C, D, A, B, 2, 17, 0x242070DB);
106 P(B, C, D, A, 3, 22, 0xC1BDCEEE);
107 P(A, B, C, D, 4, 7, 0xF57C0FAF);
108 P(D, A, B, C, 5, 12, 0x4787C62A);
109 P(C, D, A, B, 6, 17, 0xA8304613);
110 P(B, C, D, A, 7, 22, 0xFD469501);
111 P(A, B, C, D, 8, 7, 0x698098D8);
112 P(D, A, B, C, 9, 12, 0x8B44F7AF);
113 P(C, D, A, B, 10, 17, 0xFFFF5BB1);
114 P(B, C, D, A, 11, 22, 0x895CD7BE);
115 P(A, B, C, D, 12, 7, 0x6B901122);
116 P(D, A, B, C, 13, 12, 0xFD987193);
117 P(C, D, A, B, 14, 17, 0xA679438E);
118 P(B, C, D, A, 15, 22, 0x49B40821);
119
120 #undef F
121
122 #define F(x,y,z) (y ^ (z & (x ^ y)))
123
124 P(A, B, C, D, 1, 5, 0xF61E2562);
125 P(D, A, B, C, 6, 9, 0xC040B340);
126 P(C, D, A, B, 11, 14, 0x265E5A51);
127 P(B, C, D, A, 0, 20, 0xE9B6C7AA);
128 P(A, B, C, D, 5, 5, 0xD62F105D);
129 P(D, A, B, C, 10, 9, 0x02441453);
130 P(C, D, A, B, 15, 14, 0xD8A1E681);
131 P(B, C, D, A, 4, 20, 0xE7D3FBC8);
132 P(A, B, C, D, 9, 5, 0x21E1CDE6);
133 P(D, A, B, C, 14, 9, 0xC33707D6);
134 P(C, D, A, B, 3, 14, 0xF4D50D87);
135 P(B, C, D, A, 8, 20, 0x455A14ED);
136 P(A, B, C, D, 13, 5, 0xA9E3E905);
137 P(D, A, B, C, 2, 9, 0xFCEFA3F8);
138 P(C, D, A, B, 7, 14, 0x676F02D9);
139 P(B, C, D, A, 12, 20, 0x8D2A4C8A);
140
141 #undef F
142
143 #define F(x,y,z) (x ^ y ^ z)
144
145 P(A, B, C, D, 5, 4, 0xFFFA3942);
146 P(D, A, B, C, 8, 11, 0x8771F681);
147 P(C, D, A, B, 11, 16, 0x6D9D6122);
148 P(B, C, D, A, 14, 23, 0xFDE5380C);
149 P(A, B, C, D, 1, 4, 0xA4BEEA44);
150 P(D, A, B, C, 4, 11, 0x4BDECFA9);
151 P(C, D, A, B, 7, 16, 0xF6BB4B60);
152 P(B, C, D, A, 10, 23, 0xBEBFBC70);
153 P(A, B, C, D, 13, 4, 0x289B7EC6);
154 P(D, A, B, C, 0, 11, 0xEAA127FA);
155 P(C, D, A, B, 3, 16, 0xD4EF3085);
156 P(B, C, D, A, 6, 23, 0x04881D05);
157 P(A, B, C, D, 9, 4, 0xD9D4D039);
158 P(D, A, B, C, 12, 11, 0xE6DB99E5);
159 P(C, D, A, B, 15, 16, 0x1FA27CF8);
160 P(B, C, D, A, 2, 23, 0xC4AC5665);
161
162 #undef F
163
164 #define F(x,y,z) (y ^ (x | ~z))
165
166 P(A, B, C, D, 0, 6, 0xF4292244);
167 P(D, A, B, C, 7, 10, 0x432AFF97);
168 P(C, D, A, B, 14, 15, 0xAB9423A7);
169 P(B, C, D, A, 5, 21, 0xFC93A039);
170 P(A, B, C, D, 12, 6, 0x655B59C3);
171 P(D, A, B, C, 3, 10, 0x8F0CCC92);
172 P(C, D, A, B, 10, 15, 0xFFEFF47D);
173 P(B, C, D, A, 1, 21, 0x85845DD1);
174 P(A, B, C, D, 8, 6, 0x6FA87E4F);
175 P(D, A, B, C, 15, 10, 0xFE2CE6E0);
176 P(C, D, A, B, 6, 15, 0xA3014314);
177 P(B, C, D, A, 13, 21, 0x4E0811A1);
178 P(A, B, C, D, 4, 6, 0xF7537E82);
179 P(D, A, B, C, 11, 10, 0xBD3AF235);
180 P(C, D, A, B, 2, 15, 0x2AD7D2BB);
181 P(B, C, D, A, 9, 21, 0xEB86D391);
182
183 #undef F
184
185 ctx->state[0] += A;
186 ctx->state[1] += B;
187 ctx->state[2] += C;
188 ctx->state[3] += D;
189 }
190
191 /*
192 * MD5 process buffer
193 */
md5_update(md5_context * ctx,unsigned char * input,int ilen)194 void md5_update(md5_context * ctx, unsigned char *input, int ilen)
195 {
196 int fill;
197 unsigned long left;
198
199 if (ilen <= 0)
200 return;
201
202 left = ctx->total[0] & 0x3F;
203 fill = 64 - left;
204
205 ctx->total[0] += ilen;
206 ctx->total[0] &= 0xFFFFFFFF;
207
208 if (ctx->total[0] < (unsigned long) ilen)
209 ctx->total[1]++;
210
211 if (left && ilen >= fill) {
212 memcpy((void *) (ctx->buffer + left), (void *) input, fill);
213 md5_process(ctx, ctx->buffer);
214 input += fill;
215 ilen -= fill;
216 left = 0;
217 }
218
219 while (ilen >= 64) {
220 md5_process(ctx, input);
221 input += 64;
222 ilen -= 64;
223 }
224
225 if (ilen > 0) {
226 memcpy((void *) (ctx->buffer + left), (void *) input, ilen);
227 }
228 }
229
230 static const unsigned char md5_padding[64] = {
231 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
232 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
233 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
234 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
235 };
236
237 /*
238 * MD5 final digest
239 */
md5_finish(md5_context * ctx,unsigned char output[16])240 void md5_finish(md5_context * ctx, unsigned char output[16])
241 {
242 unsigned long last, padn;
243 unsigned long high, low;
244 unsigned char msglen[8];
245
246 high = (ctx->total[0] >> 29)
247 | (ctx->total[1] << 3);
248 low = (ctx->total[0] << 3);
249
250 PUT_ULONG_LE(low, msglen, 0);
251 PUT_ULONG_LE(high, msglen, 4);
252
253 last = ctx->total[0] & 0x3F;
254 padn = (last < 56) ? (56 - last) : (120 - last);
255
256 md5_update(ctx, (unsigned char *) md5_padding, padn);
257 md5_update(ctx, msglen, 8);
258
259 PUT_ULONG_LE(ctx->state[0], output, 0);
260 PUT_ULONG_LE(ctx->state[1], output, 4);
261 PUT_ULONG_LE(ctx->state[2], output, 8);
262 PUT_ULONG_LE(ctx->state[3], output, 12);
263 }
264
265 /*
266 * output = MD5( input buffer )
267 */
md5(unsigned char * input,int ilen,unsigned char output[16])268 void md5(unsigned char *input, int ilen, unsigned char output[16])
269 {
270 md5_context ctx;
271
272 md5_starts(&ctx);
273 md5_update(&ctx, input, ilen);
274 md5_finish(&ctx, output);
275
276 memset(&ctx, 0, sizeof(md5_context));
277 }
278
279 /*
280 * output = MD5( file contents )
281 */
md5_file(char * path,unsigned char output[16])282 int md5_file(char *path, unsigned char output[16])
283 {
284 FILE *f;
285 size_t n;
286 md5_context ctx;
287 unsigned char buf[1024];
288
289 if ((f = fopen(path, "rb")) == NULL)
290 return (1);
291
292 md5_starts(&ctx);
293
294 while ((n = fread(buf, 1, sizeof(buf), f)) > 0)
295 md5_update(&ctx, buf, (int) n);
296
297 md5_finish(&ctx, output);
298
299 memset(&ctx, 0, sizeof(md5_context));
300
301 if (ferror(f) != 0) {
302 fclose(f);
303 return (2);
304 }
305
306 fclose(f);
307 return (0);
308 }
309
310 /*
311 * MD5 HMAC context setup
312 */
md5_hmac_starts(md5_context * ctx,unsigned char * key,int keylen)313 void md5_hmac_starts(md5_context * ctx, unsigned char *key, int keylen)
314 {
315 int i;
316 unsigned char sum[16];
317
318 if (keylen > 64) {
319 md5(key, keylen, sum);
320 keylen = 16;
321 key = sum;
322 }
323
324 memset(ctx->ipad, 0x36, 64);
325 memset(ctx->opad, 0x5C, 64);
326
327 for (i = 0; i < keylen; i++) {
328 ctx->ipad[i] = (unsigned char) (ctx->ipad[i] ^ key[i]);
329 ctx->opad[i] = (unsigned char) (ctx->opad[i] ^ key[i]);
330 }
331
332 md5_starts(ctx);
333 md5_update(ctx, ctx->ipad, 64);
334
335 memset(sum, 0, sizeof(sum));
336 }
337
338 /*
339 * MD5 HMAC process buffer
340 */
md5_hmac_update(md5_context * ctx,unsigned char * input,int ilen)341 void md5_hmac_update(md5_context * ctx, unsigned char *input, int ilen)
342 {
343 md5_update(ctx, input, ilen);
344 }
345
346 /*
347 * MD5 HMAC final digest
348 */
md5_hmac_finish(md5_context * ctx,unsigned char output[16])349 void md5_hmac_finish(md5_context * ctx, unsigned char output[16])
350 {
351 unsigned char tmpbuf[16];
352
353 md5_finish(ctx, tmpbuf);
354 md5_starts(ctx);
355 md5_update(ctx, ctx->opad, 64);
356 md5_update(ctx, tmpbuf, 16);
357 md5_finish(ctx, output);
358
359 memset(tmpbuf, 0, sizeof(tmpbuf));
360 }
361
362 /*
363 * output = HMAC-MD5( hmac key, input buffer )
364 */
md5_hmac(unsigned char * key,int keylen,unsigned char * input,int ilen,unsigned char output[16])365 void md5_hmac(unsigned char *key, int keylen, unsigned char *input,
366 int ilen, unsigned char output[16])
367 {
368 md5_context ctx;
369
370 md5_hmac_starts(&ctx, key, keylen);
371 md5_hmac_update(&ctx, input, ilen);
372 md5_hmac_finish(&ctx, output);
373
374 memset(&ctx, 0, sizeof(md5_context));
375 }
376
377 #if defined(XYSSL_SELF_TEST)
378
379 /*
380 * RFC 1321 test vectors
381 */
382 static const char md5_test_str[7][81] = {
383 {""},
384 {"a"},
385 {"abc"},
386 {"message digest"},
387 {"abcdefghijklmnopqrstuvwxyz"},
388 {"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"},
389 {"12345678901234567890123456789012345678901234567890123456789012"
390 "345678901234567890"}
391 };
392
393 static const unsigned char md5_test_sum[7][16] = {
394 {0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04,
395 0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E},
396 {0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8,
397 0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61},
398 {0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0,
399 0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72},
400 {0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D,
401 0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0},
402 {0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00,
403 0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B},
404 {0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5,
405 0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F},
406 {0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55,
407 0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A}
408 };
409
410 /*
411 * Checkup routine
412 */
md5_self_test(int verbose)413 int md5_self_test(int verbose)
414 {
415 int i;
416 unsigned char md5sum[16];
417
418 for (i = 0; i < 7; i++) {
419 if (verbose != 0)
420 printf(" MD5 test #%d: ", i + 1);
421
422 md5((unsigned char *) md5_test_str[i],
423 strlen(md5_test_str[i]), md5sum);
424
425 if (memcmp(md5sum, md5_test_sum[i], 16) != 0) {
426 if (verbose != 0)
427 printf("failed\n");
428
429 return (1);
430 }
431
432 if (verbose != 0)
433 printf("passed\n");
434 }
435
436 if (verbose != 0)
437 printf("\n");
438
439 return (0);
440 }
441
442 #endif
443