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