Ditch libuuid. Switch to using a md5 sum of each frame in the segment for the UID.
[libmkv.git] / src / md5.c
blobf8c30b4b3a27cc048c592713f6aed11b1ec06c75
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 )
213 memcpy( (void *) (ctx->buffer + left),
214 (void *) input, fill );
215 md5_process( ctx, ctx->buffer );
216 input += fill;
217 ilen -= fill;
218 left = 0;
221 while( ilen >= 64 )
223 md5_process( ctx, input );
224 input += 64;
225 ilen -= 64;
228 if( ilen > 0 )
230 memcpy( (void *) (ctx->buffer + left),
231 (void *) input, ilen );
235 static const unsigned char md5_padding[64] =
237 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
238 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
239 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
240 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
244 * MD5 final digest
246 void md5_finish( md5_context *ctx, unsigned char output[16] )
248 unsigned long last, padn;
249 unsigned long high, low;
250 unsigned char msglen[8];
252 high = ( ctx->total[0] >> 29 )
253 | ( ctx->total[1] << 3 );
254 low = ( ctx->total[0] << 3 );
256 PUT_ULONG_LE( low, msglen, 0 );
257 PUT_ULONG_LE( high, msglen, 4 );
259 last = ctx->total[0] & 0x3F;
260 padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
262 md5_update( ctx, (unsigned char *) md5_padding, padn );
263 md5_update( ctx, msglen, 8 );
265 PUT_ULONG_LE( ctx->state[0], output, 0 );
266 PUT_ULONG_LE( ctx->state[1], output, 4 );
267 PUT_ULONG_LE( ctx->state[2], output, 8 );
268 PUT_ULONG_LE( ctx->state[3], output, 12 );
272 * output = MD5( input buffer )
274 void md5( unsigned char *input, int ilen, unsigned char output[16] )
276 md5_context ctx;
278 md5_starts( &ctx );
279 md5_update( &ctx, input, ilen );
280 md5_finish( &ctx, output );
282 memset( &ctx, 0, sizeof( md5_context ) );
286 * output = MD5( file contents )
288 int md5_file( char *path, unsigned char output[16] )
290 FILE *f;
291 size_t n;
292 md5_context ctx;
293 unsigned char buf[1024];
295 if( ( f = fopen( path, "rb" ) ) == NULL )
296 return( 1 );
298 md5_starts( &ctx );
300 while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
301 md5_update( &ctx, buf, (int) n );
303 md5_finish( &ctx, output );
305 memset( &ctx, 0, sizeof( md5_context ) );
307 if( ferror( f ) != 0 )
309 fclose( f );
310 return( 2 );
313 fclose( f );
314 return( 0 );
318 * MD5 HMAC context setup
320 void md5_hmac_starts( md5_context *ctx, unsigned char *key, int keylen )
322 int i;
323 unsigned char sum[16];
325 if( keylen > 64 )
327 md5( key, keylen, sum );
328 keylen = 16;
329 key = sum;
332 memset( ctx->ipad, 0x36, 64 );
333 memset( ctx->opad, 0x5C, 64 );
335 for( i = 0; i < keylen; i++ )
337 ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
338 ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
341 md5_starts( ctx );
342 md5_update( ctx, ctx->ipad, 64 );
344 memset( sum, 0, sizeof( sum ) );
348 * MD5 HMAC process buffer
350 void md5_hmac_update( md5_context *ctx, unsigned char *input, int ilen )
352 md5_update( ctx, input, ilen );
356 * MD5 HMAC final digest
358 void md5_hmac_finish( md5_context *ctx, unsigned char output[16] )
360 unsigned char tmpbuf[16];
362 md5_finish( ctx, tmpbuf );
363 md5_starts( ctx );
364 md5_update( ctx, ctx->opad, 64 );
365 md5_update( ctx, tmpbuf, 16 );
366 md5_finish( ctx, output );
368 memset( tmpbuf, 0, sizeof( tmpbuf ) );
372 * output = HMAC-MD5( hmac key, input buffer )
374 void md5_hmac( unsigned char *key, int keylen, unsigned char *input, int ilen,
375 unsigned char output[16] )
377 md5_context ctx;
379 md5_hmac_starts( &ctx, key, keylen );
380 md5_hmac_update( &ctx, input, ilen );
381 md5_hmac_finish( &ctx, output );
383 memset( &ctx, 0, sizeof( md5_context ) );
386 #if defined(XYSSL_SELF_TEST)
389 * RFC 1321 test vectors
391 static const char md5_test_str[7][81] =
393 { "" },
394 { "a" },
395 { "abc" },
396 { "message digest" },
397 { "abcdefghijklmnopqrstuvwxyz" },
398 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
399 { "12345678901234567890123456789012345678901234567890123456789012" \
400 "345678901234567890" }
403 static const unsigned char md5_test_sum[7][16] =
405 { 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04,
406 0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E },
407 { 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8,
408 0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 },
409 { 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0,
410 0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 },
411 { 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D,
412 0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 },
413 { 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00,
414 0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B },
415 { 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5,
416 0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F },
417 { 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55,
418 0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A }
422 * Checkup routine
424 int md5_self_test( int verbose )
426 int i;
427 unsigned char md5sum[16];
429 for( i = 0; i < 7; i++ )
431 if( verbose != 0 )
432 printf( " MD5 test #%d: ", i + 1 );
434 md5( (unsigned char *) md5_test_str[i],
435 strlen( md5_test_str[i] ), md5sum );
437 if( memcmp( md5sum, md5_test_sum[i], 16 ) != 0 )
439 if( verbose != 0 )
440 printf( "failed\n" );
442 return( 1 );
445 if( verbose != 0 )
446 printf( "passed\n" );
449 if( verbose != 0 )
450 printf( "\n" );
452 return( 0 );
455 #endif