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