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