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