Bump version to 0.6.4.1
[libmkv.git] / src / md5.c
blob320371cc0d8b0ca106861db3f576eff4d65df7f0
1 /*
2 * RFC 1321 compliant MD5 implementation
4 * Copyright (C) 2006-2007 Christophe Devine
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.
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.
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
21 * The MD5 algorithm was designed by Ron Rivest in 1991.
22 * From the XYSSL project.
24 * http://www.ietf.org/rfc/rfc1321.txt
26 #include "md5.h"
28 #include <string.h>
29 #include <stdio.h>
32 * 32-bit integer manipulation macros (little endian)
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 ); \
42 #endif
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 ); \
52 #endif
55 * MD5 context setup
57 void md5_starts(md5_context * ctx)
59 ctx->total[0] = 0;
60 ctx->total[1] = 0;
62 ctx->state[0] = 0x67452301;
63 ctx->state[1] = 0xEFCDAB89;
64 ctx->state[2] = 0x98BADCFE;
65 ctx->state[3] = 0x10325476;
68 static void md5_process(md5_context * ctx, unsigned char data[64])
70 unsigned long X[16], A, B, C, D;
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);
89 #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
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; \
96 A = ctx->state[0];
97 B = ctx->state[1];
98 C = ctx->state[2];
99 D = ctx->state[3];
101 #define F(x,y,z) (z ^ (x & (y ^ z)))
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);
120 #undef F
122 #define F(x,y,z) (y ^ (z & (x ^ y)))
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);
141 #undef F
143 #define F(x,y,z) (x ^ y ^ z)
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);
162 #undef F
164 #define F(x,y,z) (y ^ (x | ~z))
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);
183 #undef F
185 ctx->state[0] += A;
186 ctx->state[1] += B;
187 ctx->state[2] += C;
188 ctx->state[3] += D;
192 * MD5 process buffer
194 void md5_update(md5_context * ctx, unsigned char *input, int ilen)
196 int fill;
197 unsigned long left;
199 if (ilen <= 0)
200 return;
202 left = ctx->total[0] & 0x3F;
203 fill = 64 - left;
205 ctx->total[0] += ilen;
206 ctx->total[0] &= 0xFFFFFFFF;
208 if (ctx->total[0] < (unsigned long) ilen)
209 ctx->total[1]++;
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;
219 while (ilen >= 64) {
220 md5_process(ctx, input);
221 input += 64;
222 ilen -= 64;
225 if (ilen > 0) {
226 memcpy((void *) (ctx->buffer + left), (void *) input, ilen);
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
238 * MD5 final digest
240 void md5_finish(md5_context * ctx, unsigned char output[16])
242 unsigned long last, padn;
243 unsigned long high, low;
244 unsigned char msglen[8];
246 high = (ctx->total[0] >> 29)
247 | (ctx->total[1] << 3);
248 low = (ctx->total[0] << 3);
250 PUT_ULONG_LE(low, msglen, 0);
251 PUT_ULONG_LE(high, msglen, 4);
253 last = ctx->total[0] & 0x3F;
254 padn = (last < 56) ? (56 - last) : (120 - last);
256 md5_update(ctx, (unsigned char *) md5_padding, padn);
257 md5_update(ctx, msglen, 8);
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);
266 * output = MD5( input buffer )
268 void md5(unsigned char *input, int ilen, unsigned char output[16])
270 md5_context ctx;
272 md5_starts(&ctx);
273 md5_update(&ctx, input, ilen);
274 md5_finish(&ctx, output);
276 memset(&ctx, 0, sizeof(md5_context));
280 * output = MD5( file contents )
282 int md5_file(char *path, unsigned char output[16])
284 FILE *f;
285 size_t n;
286 md5_context ctx;
287 unsigned char buf[1024];
289 if ((f = fopen(path, "rb")) == NULL)
290 return (1);
292 md5_starts(&ctx);
294 while ((n = fread(buf, 1, sizeof(buf), f)) > 0)
295 md5_update(&ctx, buf, (int) n);
297 md5_finish(&ctx, output);
299 memset(&ctx, 0, sizeof(md5_context));
301 if (ferror(f) != 0) {
302 fclose(f);
303 return (2);
306 fclose(f);
307 return (0);
311 * MD5 HMAC context setup
313 void md5_hmac_starts(md5_context * ctx, unsigned char *key, int keylen)
315 int i;
316 unsigned char sum[16];
318 if (keylen > 64) {
319 md5(key, keylen, sum);
320 keylen = 16;
321 key = sum;
324 memset(ctx->ipad, 0x36, 64);
325 memset(ctx->opad, 0x5C, 64);
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]);
332 md5_starts(ctx);
333 md5_update(ctx, ctx->ipad, 64);
335 memset(sum, 0, sizeof(sum));
339 * MD5 HMAC process buffer
341 void md5_hmac_update(md5_context * ctx, unsigned char *input, int ilen)
343 md5_update(ctx, input, ilen);
347 * MD5 HMAC final digest
349 void md5_hmac_finish(md5_context * ctx, unsigned char output[16])
351 unsigned char tmpbuf[16];
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);
359 memset(tmpbuf, 0, sizeof(tmpbuf));
363 * output = HMAC-MD5( hmac key, input buffer )
365 void md5_hmac(unsigned char *key, int keylen, unsigned char *input,
366 int ilen, unsigned char output[16])
368 md5_context ctx;
370 md5_hmac_starts(&ctx, key, keylen);
371 md5_hmac_update(&ctx, input, ilen);
372 md5_hmac_finish(&ctx, output);
374 memset(&ctx, 0, sizeof(md5_context));
377 #if defined(XYSSL_SELF_TEST)
380 * RFC 1321 test vectors
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"}
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}
411 * Checkup routine
413 int md5_self_test(int verbose)
415 int i;
416 unsigned char md5sum[16];
418 for (i = 0; i < 7; i++) {
419 if (verbose != 0)
420 printf(" MD5 test #%d: ", i + 1);
422 md5((unsigned char *) md5_test_str[i],
423 strlen(md5_test_str[i]), md5sum);
425 if (memcmp(md5sum, md5_test_sum[i], 16) != 0) {
426 if (verbose != 0)
427 printf("failed\n");
429 return (1);
432 if (verbose != 0)
433 printf("passed\n");
436 if (verbose != 0)
437 printf("\n");
439 return (0);
442 #endif