blob: a9d8531569c55f48f5b91ed18fcab0293eceaa3a [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * RFC 1321 compliant MD5 implementation
3 *
4 * Copyright (C) 2006-2007 Christophe Devine
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, 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
Paul Bakker40e46942009-01-03 21:51:57 +000026#include "polarssl/config.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000027
Paul Bakker40e46942009-01-03 21:51:57 +000028#if defined(POLARSSL_MD5_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000029
Paul Bakker40e46942009-01-03 21:51:57 +000030#include "polarssl/md5.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000031
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
289/*
290 * output = MD5( file contents )
291 */
292int md5_file( char *path, unsigned char output[16] )
293{
294 FILE *f;
295 size_t n;
296 md5_context ctx;
297 unsigned char buf[1024];
298
299 if( ( f = fopen( path, "rb" ) ) == NULL )
300 return( 1 );
301
302 md5_starts( &ctx );
303
304 while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
305 md5_update( &ctx, buf, (int) n );
306
307 md5_finish( &ctx, output );
308
309 memset( &ctx, 0, sizeof( md5_context ) );
310
311 if( ferror( f ) != 0 )
312 {
313 fclose( f );
314 return( 2 );
315 }
316
317 fclose( f );
318 return( 0 );
319}
320
321/*
322 * MD5 HMAC context setup
323 */
324void md5_hmac_starts( md5_context *ctx, unsigned char *key, int keylen )
325{
326 int i;
327 unsigned char sum[16];
328
329 if( keylen > 64 )
330 {
331 md5( key, keylen, sum );
332 keylen = 16;
333 key = sum;
334 }
335
336 memset( ctx->ipad, 0x36, 64 );
337 memset( ctx->opad, 0x5C, 64 );
338
339 for( i = 0; i < keylen; i++ )
340 {
341 ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
342 ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
343 }
344
345 md5_starts( ctx );
346 md5_update( ctx, ctx->ipad, 64 );
347
348 memset( sum, 0, sizeof( sum ) );
349}
350
351/*
352 * MD5 HMAC process buffer
353 */
354void md5_hmac_update( md5_context *ctx, unsigned char *input, int ilen )
355{
356 md5_update( ctx, input, ilen );
357}
358
359/*
360 * MD5 HMAC final digest
361 */
362void md5_hmac_finish( md5_context *ctx, unsigned char output[16] )
363{
364 unsigned char tmpbuf[16];
365
366 md5_finish( ctx, tmpbuf );
367 md5_starts( ctx );
368 md5_update( ctx, ctx->opad, 64 );
369 md5_update( ctx, tmpbuf, 16 );
370 md5_finish( ctx, output );
371
372 memset( tmpbuf, 0, sizeof( tmpbuf ) );
373}
374
375/*
376 * output = HMAC-MD5( hmac key, input buffer )
377 */
378void md5_hmac( unsigned char *key, int keylen, unsigned char *input, int ilen,
379 unsigned char output[16] )
380{
381 md5_context ctx;
382
383 md5_hmac_starts( &ctx, key, keylen );
384 md5_hmac_update( &ctx, input, ilen );
385 md5_hmac_finish( &ctx, output );
386
387 memset( &ctx, 0, sizeof( md5_context ) );
388}
389
Paul Bakker40e46942009-01-03 21:51:57 +0000390#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000391/*
392 * RFC 1321 test vectors
393 */
394static unsigned char md5_test_buf[7][81] =
395{
396 { "" },
397 { "a" },
398 { "abc" },
399 { "message digest" },
400 { "abcdefghijklmnopqrstuvwxyz" },
401 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
402 { "12345678901234567890123456789012345678901234567890123456789012" \
403 "345678901234567890" }
404};
405
406static const int md5_test_buflen[7] =
407{
408 0, 1, 3, 14, 26, 62, 80
409};
410
411static const unsigned char md5_test_sum[7][16] =
412{
413 { 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04,
414 0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E },
415 { 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8,
416 0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 },
417 { 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0,
418 0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 },
419 { 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D,
420 0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 },
421 { 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00,
422 0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B },
423 { 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5,
424 0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F },
425 { 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55,
426 0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A }
427};
428
429/*
430 * RFC 2202 test vectors
431 */
432static unsigned char md5_hmac_test_key[7][26] =
433{
434 { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B" },
435 { "Jefe" },
436 { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" },
437 { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
438 "\x11\x12\x13\x14\x15\x16\x17\x18\x19" },
439 { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C" },
440 { "" }, /* 0xAA 80 times */
441 { "" }
442};
443
444static const int md5_hmac_test_keylen[7] =
445{
446 16, 4, 16, 25, 16, 80, 80
447};
448
449static unsigned char md5_hmac_test_buf[7][74] =
450{
451 { "Hi There" },
452 { "what do ya want for nothing?" },
453 { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
454 "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
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 { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
459 "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
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 { "Test With Truncation" },
464 { "Test Using Larger Than Block-Size Key - Hash Key First" },
465 { "Test Using Larger Than Block-Size Key and Larger"
466 " Than One Block-Size Data" }
467};
468
469static const int md5_hmac_test_buflen[7] =
470{
471 8, 28, 50, 50, 20, 54, 73
472};
473
474static const unsigned char md5_hmac_test_sum[7][16] =
475{
476 { 0x92, 0x94, 0x72, 0x7A, 0x36, 0x38, 0xBB, 0x1C,
477 0x13, 0xF4, 0x8E, 0xF8, 0x15, 0x8B, 0xFC, 0x9D },
478 { 0x75, 0x0C, 0x78, 0x3E, 0x6A, 0xB0, 0xB5, 0x03,
479 0xEA, 0xA8, 0x6E, 0x31, 0x0A, 0x5D, 0xB7, 0x38 },
480 { 0x56, 0xBE, 0x34, 0x52, 0x1D, 0x14, 0x4C, 0x88,
481 0xDB, 0xB8, 0xC7, 0x33, 0xF0, 0xE8, 0xB3, 0xF6 },
482 { 0x69, 0x7E, 0xAF, 0x0A, 0xCA, 0x3A, 0x3A, 0xEA,
483 0x3A, 0x75, 0x16, 0x47, 0x46, 0xFF, 0xAA, 0x79 },
484 { 0x56, 0x46, 0x1E, 0xF2, 0x34, 0x2E, 0xDC, 0x00,
485 0xF9, 0xBA, 0xB9, 0x95 },
486 { 0x6B, 0x1A, 0xB7, 0xFE, 0x4B, 0xD7, 0xBF, 0x8F,
487 0x0B, 0x62, 0xE6, 0xCE, 0x61, 0xB9, 0xD0, 0xCD },
488 { 0x6F, 0x63, 0x0F, 0xAD, 0x67, 0xCD, 0xA0, 0xEE,
489 0x1F, 0xB1, 0xF5, 0x62, 0xDB, 0x3A, 0xA5, 0x3E }
490};
491
492/*
493 * Checkup routine
494 */
495int md5_self_test( int verbose )
496{
497 int i, buflen;
498 unsigned char buf[1024];
499 unsigned char md5sum[16];
500 md5_context ctx;
501
502 for( i = 0; i < 7; i++ )
503 {
504 if( verbose != 0 )
505 printf( " MD5 test #%d: ", i + 1 );
506
507 md5( md5_test_buf[i], md5_test_buflen[i], md5sum );
508
509 if( memcmp( md5sum, md5_test_sum[i], 16 ) != 0 )
510 {
511 if( verbose != 0 )
512 printf( "failed\n" );
513
514 return( 1 );
515 }
516
517 if( verbose != 0 )
518 printf( "passed\n" );
519 }
520
521 if( verbose != 0 )
522 printf( "\n" );
523
524 for( i = 0; i < 7; i++ )
525 {
526 if( verbose != 0 )
527 printf( " HMAC-MD5 test #%d: ", i + 1 );
528
529 if( i == 5 || i == 6 )
530 {
531 memset( buf, '\xAA', buflen = 80 );
532 md5_hmac_starts( &ctx, buf, buflen );
533 }
534 else
535 md5_hmac_starts( &ctx, md5_hmac_test_key[i],
536 md5_hmac_test_keylen[i] );
537
538 md5_hmac_update( &ctx, md5_hmac_test_buf[i],
539 md5_hmac_test_buflen[i] );
540
541 md5_hmac_finish( &ctx, md5sum );
542
543 buflen = ( i == 4 ) ? 12 : 16;
544
545 if( memcmp( md5sum, md5_hmac_test_sum[i], buflen ) != 0 )
546 {
547 if( verbose != 0 )
548 printf( "failed\n" );
549
550 return( 1 );
551 }
552
553 if( verbose != 0 )
554 printf( "passed\n" );
555 }
556
557 if( verbose != 0 )
558 printf( "\n" );
559
560 return( 0 );
561}
562
563#endif
564
565#endif