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