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