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