blob: d540e68a914189f5399eb71b8b9f75beaff5d7e3 [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.
5 * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
Paul Bakker77b385e2009-07-28 17:23:11 +00006 * All rights reserved.
Paul Bakkere0ccd0a2009-01-04 16:27:10 +00007 *
Paul Bakker5121ce52009-01-03 21:22:43 +00008 * 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
Paul Bakkerff60ee62010-03-16 21:09:09 +000074static void md5_process( md5_context *ctx, const unsigned char data[64] )
Paul Bakker5121ce52009-01-03 21:22:43 +000075{
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 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000200void md5_update( md5_context *ctx, const unsigned char *input, int ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000201{
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 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000280void md5( const unsigned char *input, int ilen, unsigned char output[16] )
Paul Bakker5121ce52009-01-03 21:22:43 +0000281{
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 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000294int md5_file( const char *path, unsigned char output[16] )
Paul Bakker5121ce52009-01-03 21:22:43 +0000295{
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 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000326void md5_hmac_starts( md5_context *ctx, const unsigned char *key, int keylen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000327{
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 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000356void md5_hmac_update( md5_context *ctx, const unsigned char *input, int ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000357{
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/*
Paul Bakker7d3b6612010-03-21 16:23:13 +0000378 * MD5 HMAC context reset
379 */
380void md5_hmac_reset( md5_context *ctx )
381{
382 md5_starts( ctx );
383 md5_update( ctx, ctx->ipad, 64 );
384}
385
386/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000387 * output = HMAC-MD5( hmac key, input buffer )
388 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000389void md5_hmac( const unsigned char *key, int keylen,
390 const unsigned char *input, int ilen,
Paul Bakker5121ce52009-01-03 21:22:43 +0000391 unsigned char output[16] )
392{
393 md5_context ctx;
394
395 md5_hmac_starts( &ctx, key, keylen );
396 md5_hmac_update( &ctx, input, ilen );
397 md5_hmac_finish( &ctx, output );
398
399 memset( &ctx, 0, sizeof( md5_context ) );
400}
401
Paul Bakker40e46942009-01-03 21:51:57 +0000402#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000403/*
404 * RFC 1321 test vectors
405 */
406static unsigned char md5_test_buf[7][81] =
407{
408 { "" },
409 { "a" },
410 { "abc" },
411 { "message digest" },
412 { "abcdefghijklmnopqrstuvwxyz" },
413 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
414 { "12345678901234567890123456789012345678901234567890123456789012" \
415 "345678901234567890" }
416};
417
418static const int md5_test_buflen[7] =
419{
420 0, 1, 3, 14, 26, 62, 80
421};
422
423static const unsigned char md5_test_sum[7][16] =
424{
425 { 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04,
426 0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E },
427 { 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8,
428 0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 },
429 { 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0,
430 0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 },
431 { 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D,
432 0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 },
433 { 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00,
434 0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B },
435 { 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5,
436 0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F },
437 { 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55,
438 0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A }
439};
440
441/*
442 * RFC 2202 test vectors
443 */
444static unsigned char md5_hmac_test_key[7][26] =
445{
446 { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B" },
447 { "Jefe" },
448 { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" },
449 { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
450 "\x11\x12\x13\x14\x15\x16\x17\x18\x19" },
451 { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C" },
452 { "" }, /* 0xAA 80 times */
453 { "" }
454};
455
456static const int md5_hmac_test_keylen[7] =
457{
458 16, 4, 16, 25, 16, 80, 80
459};
460
461static unsigned char md5_hmac_test_buf[7][74] =
462{
463 { "Hi There" },
464 { "what do ya want for nothing?" },
465 { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
466 "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
467 "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
468 "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
469 "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" },
470 { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
471 "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
472 "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
473 "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
474 "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" },
475 { "Test With Truncation" },
476 { "Test Using Larger Than Block-Size Key - Hash Key First" },
477 { "Test Using Larger Than Block-Size Key and Larger"
478 " Than One Block-Size Data" }
479};
480
481static const int md5_hmac_test_buflen[7] =
482{
483 8, 28, 50, 50, 20, 54, 73
484};
485
486static const unsigned char md5_hmac_test_sum[7][16] =
487{
488 { 0x92, 0x94, 0x72, 0x7A, 0x36, 0x38, 0xBB, 0x1C,
489 0x13, 0xF4, 0x8E, 0xF8, 0x15, 0x8B, 0xFC, 0x9D },
490 { 0x75, 0x0C, 0x78, 0x3E, 0x6A, 0xB0, 0xB5, 0x03,
491 0xEA, 0xA8, 0x6E, 0x31, 0x0A, 0x5D, 0xB7, 0x38 },
492 { 0x56, 0xBE, 0x34, 0x52, 0x1D, 0x14, 0x4C, 0x88,
493 0xDB, 0xB8, 0xC7, 0x33, 0xF0, 0xE8, 0xB3, 0xF6 },
494 { 0x69, 0x7E, 0xAF, 0x0A, 0xCA, 0x3A, 0x3A, 0xEA,
495 0x3A, 0x75, 0x16, 0x47, 0x46, 0xFF, 0xAA, 0x79 },
496 { 0x56, 0x46, 0x1E, 0xF2, 0x34, 0x2E, 0xDC, 0x00,
497 0xF9, 0xBA, 0xB9, 0x95 },
498 { 0x6B, 0x1A, 0xB7, 0xFE, 0x4B, 0xD7, 0xBF, 0x8F,
499 0x0B, 0x62, 0xE6, 0xCE, 0x61, 0xB9, 0xD0, 0xCD },
500 { 0x6F, 0x63, 0x0F, 0xAD, 0x67, 0xCD, 0xA0, 0xEE,
501 0x1F, 0xB1, 0xF5, 0x62, 0xDB, 0x3A, 0xA5, 0x3E }
502};
503
504/*
505 * Checkup routine
506 */
507int md5_self_test( int verbose )
508{
509 int i, buflen;
510 unsigned char buf[1024];
511 unsigned char md5sum[16];
512 md5_context ctx;
513
514 for( i = 0; i < 7; i++ )
515 {
516 if( verbose != 0 )
517 printf( " MD5 test #%d: ", i + 1 );
518
519 md5( md5_test_buf[i], md5_test_buflen[i], md5sum );
520
521 if( memcmp( md5sum, md5_test_sum[i], 16 ) != 0 )
522 {
523 if( verbose != 0 )
524 printf( "failed\n" );
525
526 return( 1 );
527 }
528
529 if( verbose != 0 )
530 printf( "passed\n" );
531 }
532
533 if( verbose != 0 )
534 printf( "\n" );
535
536 for( i = 0; i < 7; i++ )
537 {
538 if( verbose != 0 )
539 printf( " HMAC-MD5 test #%d: ", i + 1 );
540
541 if( i == 5 || i == 6 )
542 {
543 memset( buf, '\xAA', buflen = 80 );
544 md5_hmac_starts( &ctx, buf, buflen );
545 }
546 else
547 md5_hmac_starts( &ctx, md5_hmac_test_key[i],
548 md5_hmac_test_keylen[i] );
549
550 md5_hmac_update( &ctx, md5_hmac_test_buf[i],
551 md5_hmac_test_buflen[i] );
552
553 md5_hmac_finish( &ctx, md5sum );
554
555 buflen = ( i == 4 ) ? 12 : 16;
556
557 if( memcmp( md5sum, md5_hmac_test_sum[i], buflen ) != 0 )
558 {
559 if( verbose != 0 )
560 printf( "failed\n" );
561
562 return( 1 );
563 }
564
565 if( verbose != 0 )
566 printf( "passed\n" );
567 }
568
569 if( verbose != 0 )
570 printf( "\n" );
571
572 return( 0 );
573}
574
575#endif
576
577#endif