blob: a9646175209f43ea0b760fe1c28e535a09ca67e6 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * RFC 1321 compliant MD5 implementation
3 *
Paul Bakkere0ccd0a2009-01-04 16:27:10 +00004 * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine
5 *
Paul Bakker27db1f52009-01-25 15:27:00 +00006 * Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org>
Paul Bakker5121ce52009-01-03 21:22:43 +00007 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22/*
23 * The MD5 algorithm was designed by Ron Rivest in 1991.
24 *
25 * http://www.ietf.org/rfc/rfc1321.txt
26 */
27
Paul Bakker40e46942009-01-03 21:51:57 +000028#include "polarssl/config.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000029
Paul Bakker40e46942009-01-03 21:51:57 +000030#if defined(POLARSSL_MD5_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000031
Paul Bakker40e46942009-01-03 21:51:57 +000032#include "polarssl/md5.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000033
34#include <string.h>
35#include <stdio.h>
36
37/*
38 * 32-bit integer manipulation macros (little endian)
39 */
40#ifndef GET_ULONG_LE
41#define GET_ULONG_LE(n,b,i) \
42{ \
43 (n) = ( (unsigned long) (b)[(i) ] ) \
44 | ( (unsigned long) (b)[(i) + 1] << 8 ) \
45 | ( (unsigned long) (b)[(i) + 2] << 16 ) \
46 | ( (unsigned long) (b)[(i) + 3] << 24 ); \
47}
48#endif
49
50#ifndef PUT_ULONG_LE
51#define PUT_ULONG_LE(n,b,i) \
52{ \
53 (b)[(i) ] = (unsigned char) ( (n) ); \
54 (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \
55 (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \
56 (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \
57}
58#endif
59
60/*
61 * MD5 context setup
62 */
63void md5_starts( md5_context *ctx )
64{
65 ctx->total[0] = 0;
66 ctx->total[1] = 0;
67
68 ctx->state[0] = 0x67452301;
69 ctx->state[1] = 0xEFCDAB89;
70 ctx->state[2] = 0x98BADCFE;
71 ctx->state[3] = 0x10325476;
72}
73
74static void md5_process( md5_context *ctx, unsigned char data[64] )
75{
76 unsigned long X[16], A, B, C, D;
77
78 GET_ULONG_LE( X[ 0], data, 0 );
79 GET_ULONG_LE( X[ 1], data, 4 );
80 GET_ULONG_LE( X[ 2], data, 8 );
81 GET_ULONG_LE( X[ 3], data, 12 );
82 GET_ULONG_LE( X[ 4], data, 16 );
83 GET_ULONG_LE( X[ 5], data, 20 );
84 GET_ULONG_LE( X[ 6], data, 24 );
85 GET_ULONG_LE( X[ 7], data, 28 );
86 GET_ULONG_LE( X[ 8], data, 32 );
87 GET_ULONG_LE( X[ 9], data, 36 );
88 GET_ULONG_LE( X[10], data, 40 );
89 GET_ULONG_LE( X[11], data, 44 );
90 GET_ULONG_LE( X[12], data, 48 );
91 GET_ULONG_LE( X[13], data, 52 );
92 GET_ULONG_LE( X[14], data, 56 );
93 GET_ULONG_LE( X[15], data, 60 );
94
95#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
96
97#define P(a,b,c,d,k,s,t) \
98{ \
99 a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \
100}
101
102 A = ctx->state[0];
103 B = ctx->state[1];
104 C = ctx->state[2];
105 D = ctx->state[3];
106
107#define F(x,y,z) (z ^ (x & (y ^ z)))
108
109 P( A, B, C, D, 0, 7, 0xD76AA478 );
110 P( D, A, B, C, 1, 12, 0xE8C7B756 );
111 P( C, D, A, B, 2, 17, 0x242070DB );
112 P( B, C, D, A, 3, 22, 0xC1BDCEEE );
113 P( A, B, C, D, 4, 7, 0xF57C0FAF );
114 P( D, A, B, C, 5, 12, 0x4787C62A );
115 P( C, D, A, B, 6, 17, 0xA8304613 );
116 P( B, C, D, A, 7, 22, 0xFD469501 );
117 P( A, B, C, D, 8, 7, 0x698098D8 );
118 P( D, A, B, C, 9, 12, 0x8B44F7AF );
119 P( C, D, A, B, 10, 17, 0xFFFF5BB1 );
120 P( B, C, D, A, 11, 22, 0x895CD7BE );
121 P( A, B, C, D, 12, 7, 0x6B901122 );
122 P( D, A, B, C, 13, 12, 0xFD987193 );
123 P( C, D, A, B, 14, 17, 0xA679438E );
124 P( B, C, D, A, 15, 22, 0x49B40821 );
125
126#undef F
127
128#define F(x,y,z) (y ^ (z & (x ^ y)))
129
130 P( A, B, C, D, 1, 5, 0xF61E2562 );
131 P( D, A, B, C, 6, 9, 0xC040B340 );
132 P( C, D, A, B, 11, 14, 0x265E5A51 );
133 P( B, C, D, A, 0, 20, 0xE9B6C7AA );
134 P( A, B, C, D, 5, 5, 0xD62F105D );
135 P( D, A, B, C, 10, 9, 0x02441453 );
136 P( C, D, A, B, 15, 14, 0xD8A1E681 );
137 P( B, C, D, A, 4, 20, 0xE7D3FBC8 );
138 P( A, B, C, D, 9, 5, 0x21E1CDE6 );
139 P( D, A, B, C, 14, 9, 0xC33707D6 );
140 P( C, D, A, B, 3, 14, 0xF4D50D87 );
141 P( B, C, D, A, 8, 20, 0x455A14ED );
142 P( A, B, C, D, 13, 5, 0xA9E3E905 );
143 P( D, A, B, C, 2, 9, 0xFCEFA3F8 );
144 P( C, D, A, B, 7, 14, 0x676F02D9 );
145 P( B, C, D, A, 12, 20, 0x8D2A4C8A );
146
147#undef F
148
149#define F(x,y,z) (x ^ y ^ z)
150
151 P( A, B, C, D, 5, 4, 0xFFFA3942 );
152 P( D, A, B, C, 8, 11, 0x8771F681 );
153 P( C, D, A, B, 11, 16, 0x6D9D6122 );
154 P( B, C, D, A, 14, 23, 0xFDE5380C );
155 P( A, B, C, D, 1, 4, 0xA4BEEA44 );
156 P( D, A, B, C, 4, 11, 0x4BDECFA9 );
157 P( C, D, A, B, 7, 16, 0xF6BB4B60 );
158 P( B, C, D, A, 10, 23, 0xBEBFBC70 );
159 P( A, B, C, D, 13, 4, 0x289B7EC6 );
160 P( D, A, B, C, 0, 11, 0xEAA127FA );
161 P( C, D, A, B, 3, 16, 0xD4EF3085 );
162 P( B, C, D, A, 6, 23, 0x04881D05 );
163 P( A, B, C, D, 9, 4, 0xD9D4D039 );
164 P( D, A, B, C, 12, 11, 0xE6DB99E5 );
165 P( C, D, A, B, 15, 16, 0x1FA27CF8 );
166 P( B, C, D, A, 2, 23, 0xC4AC5665 );
167
168#undef F
169
170#define F(x,y,z) (y ^ (x | ~z))
171
172 P( A, B, C, D, 0, 6, 0xF4292244 );
173 P( D, A, B, C, 7, 10, 0x432AFF97 );
174 P( C, D, A, B, 14, 15, 0xAB9423A7 );
175 P( B, C, D, A, 5, 21, 0xFC93A039 );
176 P( A, B, C, D, 12, 6, 0x655B59C3 );
177 P( D, A, B, C, 3, 10, 0x8F0CCC92 );
178 P( C, D, A, B, 10, 15, 0xFFEFF47D );
179 P( B, C, D, A, 1, 21, 0x85845DD1 );
180 P( A, B, C, D, 8, 6, 0x6FA87E4F );
181 P( D, A, B, C, 15, 10, 0xFE2CE6E0 );
182 P( C, D, A, B, 6, 15, 0xA3014314 );
183 P( B, C, D, A, 13, 21, 0x4E0811A1 );
184 P( A, B, C, D, 4, 6, 0xF7537E82 );
185 P( D, A, B, C, 11, 10, 0xBD3AF235 );
186 P( C, D, A, B, 2, 15, 0x2AD7D2BB );
187 P( B, C, D, A, 9, 21, 0xEB86D391 );
188
189#undef F
190
191 ctx->state[0] += A;
192 ctx->state[1] += B;
193 ctx->state[2] += C;
194 ctx->state[3] += D;
195}
196
197/*
198 * MD5 process buffer
199 */
200void md5_update( md5_context *ctx, unsigned char *input, int ilen )
201{
202 int fill;
203 unsigned long left;
204
205 if( ilen <= 0 )
206 return;
207
208 left = ctx->total[0] & 0x3F;
209 fill = 64 - left;
210
211 ctx->total[0] += ilen;
212 ctx->total[0] &= 0xFFFFFFFF;
213
214 if( ctx->total[0] < (unsigned long) ilen )
215 ctx->total[1]++;
216
217 if( left && ilen >= fill )
218 {
219 memcpy( (void *) (ctx->buffer + left),
220 (void *) input, fill );
221 md5_process( ctx, ctx->buffer );
222 input += fill;
223 ilen -= fill;
224 left = 0;
225 }
226
227 while( ilen >= 64 )
228 {
229 md5_process( ctx, input );
230 input += 64;
231 ilen -= 64;
232 }
233
234 if( ilen > 0 )
235 {
236 memcpy( (void *) (ctx->buffer + left),
237 (void *) input, ilen );
238 }
239}
240
241static const unsigned char md5_padding[64] =
242{
243 0x80, 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 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
246 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
247};
248
249/*
250 * MD5 final digest
251 */
252void md5_finish( md5_context *ctx, unsigned char output[16] )
253{
254 unsigned long last, padn;
255 unsigned long high, low;
256 unsigned char msglen[8];
257
258 high = ( ctx->total[0] >> 29 )
259 | ( ctx->total[1] << 3 );
260 low = ( ctx->total[0] << 3 );
261
262 PUT_ULONG_LE( low, msglen, 0 );
263 PUT_ULONG_LE( high, msglen, 4 );
264
265 last = ctx->total[0] & 0x3F;
266 padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
267
268 md5_update( ctx, (unsigned char *) md5_padding, padn );
269 md5_update( ctx, msglen, 8 );
270
271 PUT_ULONG_LE( ctx->state[0], output, 0 );
272 PUT_ULONG_LE( ctx->state[1], output, 4 );
273 PUT_ULONG_LE( ctx->state[2], output, 8 );
274 PUT_ULONG_LE( ctx->state[3], output, 12 );
275}
276
277/*
278 * output = MD5( input buffer )
279 */
280void md5( unsigned char *input, int ilen, unsigned char output[16] )
281{
282 md5_context ctx;
283
284 md5_starts( &ctx );
285 md5_update( &ctx, input, ilen );
286 md5_finish( &ctx, output );
287
288 memset( &ctx, 0, sizeof( md5_context ) );
289}
290
291/*
292 * output = MD5( file contents )
293 */
294int md5_file( char *path, unsigned char output[16] )
295{
296 FILE *f;
297 size_t n;
298 md5_context ctx;
299 unsigned char buf[1024];
300
301 if( ( f = fopen( path, "rb" ) ) == NULL )
302 return( 1 );
303
304 md5_starts( &ctx );
305
306 while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
307 md5_update( &ctx, buf, (int) n );
308
309 md5_finish( &ctx, output );
310
311 memset( &ctx, 0, sizeof( md5_context ) );
312
313 if( ferror( f ) != 0 )
314 {
315 fclose( f );
316 return( 2 );
317 }
318
319 fclose( f );
320 return( 0 );
321}
322
323/*
324 * MD5 HMAC context setup
325 */
326void md5_hmac_starts( md5_context *ctx, unsigned char *key, int keylen )
327{
328 int i;
329 unsigned char sum[16];
330
331 if( keylen > 64 )
332 {
333 md5( key, keylen, sum );
334 keylen = 16;
335 key = sum;
336 }
337
338 memset( ctx->ipad, 0x36, 64 );
339 memset( ctx->opad, 0x5C, 64 );
340
341 for( i = 0; i < keylen; i++ )
342 {
343 ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
344 ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
345 }
346
347 md5_starts( ctx );
348 md5_update( ctx, ctx->ipad, 64 );
349
350 memset( sum, 0, sizeof( sum ) );
351}
352
353/*
354 * MD5 HMAC process buffer
355 */
356void md5_hmac_update( md5_context *ctx, unsigned char *input, int ilen )
357{
358 md5_update( ctx, input, ilen );
359}
360
361/*
362 * MD5 HMAC final digest
363 */
364void md5_hmac_finish( md5_context *ctx, unsigned char output[16] )
365{
366 unsigned char tmpbuf[16];
367
368 md5_finish( ctx, tmpbuf );
369 md5_starts( ctx );
370 md5_update( ctx, ctx->opad, 64 );
371 md5_update( ctx, tmpbuf, 16 );
372 md5_finish( ctx, output );
373
374 memset( tmpbuf, 0, sizeof( tmpbuf ) );
375}
376
377/*
378 * output = HMAC-MD5( hmac key, input buffer )
379 */
380void md5_hmac( unsigned char *key, int keylen, unsigned char *input, int ilen,
381 unsigned char output[16] )
382{
383 md5_context ctx;
384
385 md5_hmac_starts( &ctx, key, keylen );
386 md5_hmac_update( &ctx, input, ilen );
387 md5_hmac_finish( &ctx, output );
388
389 memset( &ctx, 0, sizeof( md5_context ) );
390}
391
Paul Bakker40e46942009-01-03 21:51:57 +0000392#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000393/*
394 * RFC 1321 test vectors
395 */
396static unsigned char md5_test_buf[7][81] =
397{
398 { "" },
399 { "a" },
400 { "abc" },
401 { "message digest" },
402 { "abcdefghijklmnopqrstuvwxyz" },
403 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
404 { "12345678901234567890123456789012345678901234567890123456789012" \
405 "345678901234567890" }
406};
407
408static const int md5_test_buflen[7] =
409{
410 0, 1, 3, 14, 26, 62, 80
411};
412
413static const unsigned char md5_test_sum[7][16] =
414{
415 { 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04,
416 0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E },
417 { 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8,
418 0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 },
419 { 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0,
420 0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 },
421 { 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D,
422 0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 },
423 { 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00,
424 0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B },
425 { 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5,
426 0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F },
427 { 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55,
428 0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A }
429};
430
431/*
432 * RFC 2202 test vectors
433 */
434static unsigned char md5_hmac_test_key[7][26] =
435{
436 { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B" },
437 { "Jefe" },
438 { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" },
439 { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
440 "\x11\x12\x13\x14\x15\x16\x17\x18\x19" },
441 { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C" },
442 { "" }, /* 0xAA 80 times */
443 { "" }
444};
445
446static const int md5_hmac_test_keylen[7] =
447{
448 16, 4, 16, 25, 16, 80, 80
449};
450
451static unsigned char md5_hmac_test_buf[7][74] =
452{
453 { "Hi There" },
454 { "what do ya want for nothing?" },
455 { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
456 "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
457 "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
458 "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
459 "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" },
460 { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
461 "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
462 "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
463 "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
464 "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" },
465 { "Test With Truncation" },
466 { "Test Using Larger Than Block-Size Key - Hash Key First" },
467 { "Test Using Larger Than Block-Size Key and Larger"
468 " Than One Block-Size Data" }
469};
470
471static const int md5_hmac_test_buflen[7] =
472{
473 8, 28, 50, 50, 20, 54, 73
474};
475
476static const unsigned char md5_hmac_test_sum[7][16] =
477{
478 { 0x92, 0x94, 0x72, 0x7A, 0x36, 0x38, 0xBB, 0x1C,
479 0x13, 0xF4, 0x8E, 0xF8, 0x15, 0x8B, 0xFC, 0x9D },
480 { 0x75, 0x0C, 0x78, 0x3E, 0x6A, 0xB0, 0xB5, 0x03,
481 0xEA, 0xA8, 0x6E, 0x31, 0x0A, 0x5D, 0xB7, 0x38 },
482 { 0x56, 0xBE, 0x34, 0x52, 0x1D, 0x14, 0x4C, 0x88,
483 0xDB, 0xB8, 0xC7, 0x33, 0xF0, 0xE8, 0xB3, 0xF6 },
484 { 0x69, 0x7E, 0xAF, 0x0A, 0xCA, 0x3A, 0x3A, 0xEA,
485 0x3A, 0x75, 0x16, 0x47, 0x46, 0xFF, 0xAA, 0x79 },
486 { 0x56, 0x46, 0x1E, 0xF2, 0x34, 0x2E, 0xDC, 0x00,
487 0xF9, 0xBA, 0xB9, 0x95 },
488 { 0x6B, 0x1A, 0xB7, 0xFE, 0x4B, 0xD7, 0xBF, 0x8F,
489 0x0B, 0x62, 0xE6, 0xCE, 0x61, 0xB9, 0xD0, 0xCD },
490 { 0x6F, 0x63, 0x0F, 0xAD, 0x67, 0xCD, 0xA0, 0xEE,
491 0x1F, 0xB1, 0xF5, 0x62, 0xDB, 0x3A, 0xA5, 0x3E }
492};
493
494/*
495 * Checkup routine
496 */
497int md5_self_test( int verbose )
498{
499 int i, buflen;
500 unsigned char buf[1024];
501 unsigned char md5sum[16];
502 md5_context ctx;
503
504 for( i = 0; i < 7; i++ )
505 {
506 if( verbose != 0 )
507 printf( " MD5 test #%d: ", i + 1 );
508
509 md5( md5_test_buf[i], md5_test_buflen[i], md5sum );
510
511 if( memcmp( md5sum, md5_test_sum[i], 16 ) != 0 )
512 {
513 if( verbose != 0 )
514 printf( "failed\n" );
515
516 return( 1 );
517 }
518
519 if( verbose != 0 )
520 printf( "passed\n" );
521 }
522
523 if( verbose != 0 )
524 printf( "\n" );
525
526 for( i = 0; i < 7; i++ )
527 {
528 if( verbose != 0 )
529 printf( " HMAC-MD5 test #%d: ", i + 1 );
530
531 if( i == 5 || i == 6 )
532 {
533 memset( buf, '\xAA', buflen = 80 );
534 md5_hmac_starts( &ctx, buf, buflen );
535 }
536 else
537 md5_hmac_starts( &ctx, md5_hmac_test_key[i],
538 md5_hmac_test_keylen[i] );
539
540 md5_hmac_update( &ctx, md5_hmac_test_buf[i],
541 md5_hmac_test_buflen[i] );
542
543 md5_hmac_finish( &ctx, md5sum );
544
545 buflen = ( i == 4 ) ? 12 : 16;
546
547 if( memcmp( md5sum, md5_hmac_test_sum[i], buflen ) != 0 )
548 {
549 if( verbose != 0 )
550 printf( "failed\n" );
551
552 return( 1 );
553 }
554
555 if( verbose != 0 )
556 printf( "passed\n" );
557 }
558
559 if( verbose != 0 )
560 printf( "\n" );
561
562 return( 0 );
563}
564
565#endif
566
567#endif