PolarSSL v1.1.4
md5.c
Go to the documentation of this file.
00001 /*
00002  *  RFC 1321 compliant MD5 implementation
00003  *
00004  *  Copyright (C) 2006-2010, Brainspark B.V.
00005  *
00006  *  This file is part of PolarSSL (http://www.polarssl.org)
00007  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
00008  *
00009  *  All rights reserved.
00010  *
00011  *  This program is free software; you can redistribute it and/or modify
00012  *  it under the terms of the GNU General Public License as published by
00013  *  the Free Software Foundation; either version 2 of the License, or
00014  *  (at your option) any later version.
00015  *
00016  *  This program is distributed in the hope that it will be useful,
00017  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  *  GNU General Public License for more details.
00020  *
00021  *  You should have received a copy of the GNU General Public License along
00022  *  with this program; if not, write to the Free Software Foundation, Inc.,
00023  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00024  */
00025 /*
00026  *  The MD5 algorithm was designed by Ron Rivest in 1991.
00027  *
00028  *  http://www.ietf.org/rfc/rfc1321.txt
00029  */
00030 
00031 #include "polarssl/config.h"
00032 
00033 #if defined(POLARSSL_MD5_C)
00034 
00035 #include "polarssl/md5.h"
00036 
00037 #if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST)
00038 #include <stdio.h>
00039 #endif
00040 
00041 /*
00042  * 32-bit integer manipulation macros (little endian)
00043  */
00044 #ifndef GET_ULONG_LE
00045 #define GET_ULONG_LE(n,b,i)                             \
00046 {                                                       \
00047     (n) = ( (unsigned long) (b)[(i)    ]       )        \
00048         | ( (unsigned long) (b)[(i) + 1] <<  8 )        \
00049         | ( (unsigned long) (b)[(i) + 2] << 16 )        \
00050         | ( (unsigned long) (b)[(i) + 3] << 24 );       \
00051 }
00052 #endif
00053 
00054 #ifndef PUT_ULONG_LE
00055 #define PUT_ULONG_LE(n,b,i)                             \
00056 {                                                       \
00057     (b)[(i)    ] = (unsigned char) ( (n)       );       \
00058     (b)[(i) + 1] = (unsigned char) ( (n) >>  8 );       \
00059     (b)[(i) + 2] = (unsigned char) ( (n) >> 16 );       \
00060     (b)[(i) + 3] = (unsigned char) ( (n) >> 24 );       \
00061 }
00062 #endif
00063 
00064 /*
00065  * MD5 context setup
00066  */
00067 void md5_starts( md5_context *ctx )
00068 {
00069     ctx->total[0] = 0;
00070     ctx->total[1] = 0;
00071 
00072     ctx->state[0] = 0x67452301;
00073     ctx->state[1] = 0xEFCDAB89;
00074     ctx->state[2] = 0x98BADCFE;
00075     ctx->state[3] = 0x10325476;
00076 }
00077 
00078 static void md5_process( md5_context *ctx, const unsigned char data[64] )
00079 {
00080     unsigned long X[16], A, B, C, D;
00081 
00082     GET_ULONG_LE( X[ 0], data,  0 );
00083     GET_ULONG_LE( X[ 1], data,  4 );
00084     GET_ULONG_LE( X[ 2], data,  8 );
00085     GET_ULONG_LE( X[ 3], data, 12 );
00086     GET_ULONG_LE( X[ 4], data, 16 );
00087     GET_ULONG_LE( X[ 5], data, 20 );
00088     GET_ULONG_LE( X[ 6], data, 24 );
00089     GET_ULONG_LE( X[ 7], data, 28 );
00090     GET_ULONG_LE( X[ 8], data, 32 );
00091     GET_ULONG_LE( X[ 9], data, 36 );
00092     GET_ULONG_LE( X[10], data, 40 );
00093     GET_ULONG_LE( X[11], data, 44 );
00094     GET_ULONG_LE( X[12], data, 48 );
00095     GET_ULONG_LE( X[13], data, 52 );
00096     GET_ULONG_LE( X[14], data, 56 );
00097     GET_ULONG_LE( X[15], data, 60 );
00098 
00099 #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
00100 
00101 #define P(a,b,c,d,k,s,t)                                \
00102 {                                                       \
00103     a += F(b,c,d) + X[k] + t; a = S(a,s) + b;           \
00104 }
00105 
00106     A = ctx->state[0];
00107     B = ctx->state[1];
00108     C = ctx->state[2];
00109     D = ctx->state[3];
00110 
00111 #define F(x,y,z) (z ^ (x & (y ^ z)))
00112 
00113     P( A, B, C, D,  0,  7, 0xD76AA478 );
00114     P( D, A, B, C,  1, 12, 0xE8C7B756 );
00115     P( C, D, A, B,  2, 17, 0x242070DB );
00116     P( B, C, D, A,  3, 22, 0xC1BDCEEE );
00117     P( A, B, C, D,  4,  7, 0xF57C0FAF );
00118     P( D, A, B, C,  5, 12, 0x4787C62A );
00119     P( C, D, A, B,  6, 17, 0xA8304613 );
00120     P( B, C, D, A,  7, 22, 0xFD469501 );
00121     P( A, B, C, D,  8,  7, 0x698098D8 );
00122     P( D, A, B, C,  9, 12, 0x8B44F7AF );
00123     P( C, D, A, B, 10, 17, 0xFFFF5BB1 );
00124     P( B, C, D, A, 11, 22, 0x895CD7BE );
00125     P( A, B, C, D, 12,  7, 0x6B901122 );
00126     P( D, A, B, C, 13, 12, 0xFD987193 );
00127     P( C, D, A, B, 14, 17, 0xA679438E );
00128     P( B, C, D, A, 15, 22, 0x49B40821 );
00129 
00130 #undef F
00131 
00132 #define F(x,y,z) (y ^ (z & (x ^ y)))
00133 
00134     P( A, B, C, D,  1,  5, 0xF61E2562 );
00135     P( D, A, B, C,  6,  9, 0xC040B340 );
00136     P( C, D, A, B, 11, 14, 0x265E5A51 );
00137     P( B, C, D, A,  0, 20, 0xE9B6C7AA );
00138     P( A, B, C, D,  5,  5, 0xD62F105D );
00139     P( D, A, B, C, 10,  9, 0x02441453 );
00140     P( C, D, A, B, 15, 14, 0xD8A1E681 );
00141     P( B, C, D, A,  4, 20, 0xE7D3FBC8 );
00142     P( A, B, C, D,  9,  5, 0x21E1CDE6 );
00143     P( D, A, B, C, 14,  9, 0xC33707D6 );
00144     P( C, D, A, B,  3, 14, 0xF4D50D87 );
00145     P( B, C, D, A,  8, 20, 0x455A14ED );
00146     P( A, B, C, D, 13,  5, 0xA9E3E905 );
00147     P( D, A, B, C,  2,  9, 0xFCEFA3F8 );
00148     P( C, D, A, B,  7, 14, 0x676F02D9 );
00149     P( B, C, D, A, 12, 20, 0x8D2A4C8A );
00150 
00151 #undef F
00152     
00153 #define F(x,y,z) (x ^ y ^ z)
00154 
00155     P( A, B, C, D,  5,  4, 0xFFFA3942 );
00156     P( D, A, B, C,  8, 11, 0x8771F681 );
00157     P( C, D, A, B, 11, 16, 0x6D9D6122 );
00158     P( B, C, D, A, 14, 23, 0xFDE5380C );
00159     P( A, B, C, D,  1,  4, 0xA4BEEA44 );
00160     P( D, A, B, C,  4, 11, 0x4BDECFA9 );
00161     P( C, D, A, B,  7, 16, 0xF6BB4B60 );
00162     P( B, C, D, A, 10, 23, 0xBEBFBC70 );
00163     P( A, B, C, D, 13,  4, 0x289B7EC6 );
00164     P( D, A, B, C,  0, 11, 0xEAA127FA );
00165     P( C, D, A, B,  3, 16, 0xD4EF3085 );
00166     P( B, C, D, A,  6, 23, 0x04881D05 );
00167     P( A, B, C, D,  9,  4, 0xD9D4D039 );
00168     P( D, A, B, C, 12, 11, 0xE6DB99E5 );
00169     P( C, D, A, B, 15, 16, 0x1FA27CF8 );
00170     P( B, C, D, A,  2, 23, 0xC4AC5665 );
00171 
00172 #undef F
00173 
00174 #define F(x,y,z) (y ^ (x | ~z))
00175 
00176     P( A, B, C, D,  0,  6, 0xF4292244 );
00177     P( D, A, B, C,  7, 10, 0x432AFF97 );
00178     P( C, D, A, B, 14, 15, 0xAB9423A7 );
00179     P( B, C, D, A,  5, 21, 0xFC93A039 );
00180     P( A, B, C, D, 12,  6, 0x655B59C3 );
00181     P( D, A, B, C,  3, 10, 0x8F0CCC92 );
00182     P( C, D, A, B, 10, 15, 0xFFEFF47D );
00183     P( B, C, D, A,  1, 21, 0x85845DD1 );
00184     P( A, B, C, D,  8,  6, 0x6FA87E4F );
00185     P( D, A, B, C, 15, 10, 0xFE2CE6E0 );
00186     P( C, D, A, B,  6, 15, 0xA3014314 );
00187     P( B, C, D, A, 13, 21, 0x4E0811A1 );
00188     P( A, B, C, D,  4,  6, 0xF7537E82 );
00189     P( D, A, B, C, 11, 10, 0xBD3AF235 );
00190     P( C, D, A, B,  2, 15, 0x2AD7D2BB );
00191     P( B, C, D, A,  9, 21, 0xEB86D391 );
00192 
00193 #undef F
00194 
00195     ctx->state[0] += A;
00196     ctx->state[1] += B;
00197     ctx->state[2] += C;
00198     ctx->state[3] += D;
00199 }
00200 
00201 /*
00202  * MD5 process buffer
00203  */
00204 void md5_update( md5_context *ctx, const unsigned char *input, size_t ilen )
00205 {
00206     size_t fill;
00207     unsigned long left;
00208 
00209     if( ilen <= 0 )
00210         return;
00211 
00212     left = ctx->total[0] & 0x3F;
00213     fill = 64 - left;
00214 
00215     ctx->total[0] += (unsigned long) ilen;
00216     ctx->total[0] &= 0xFFFFFFFF;
00217 
00218     if( ctx->total[0] < (unsigned long) ilen )
00219         ctx->total[1]++;
00220 
00221     if( left && ilen >= fill )
00222     {
00223         memcpy( (void *) (ctx->buffer + left),
00224                 (void *) input, fill );
00225         md5_process( ctx, ctx->buffer );
00226         input += fill;
00227         ilen  -= fill;
00228         left = 0;
00229     }
00230 
00231     while( ilen >= 64 )
00232     {
00233         md5_process( ctx, input );
00234         input += 64;
00235         ilen  -= 64;
00236     }
00237 
00238     if( ilen > 0 )
00239     {
00240         memcpy( (void *) (ctx->buffer + left),
00241                 (void *) input, ilen );
00242     }
00243 }
00244 
00245 static const unsigned char md5_padding[64] =
00246 {
00247  0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00248     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00249     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00250     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00251 };
00252 
00253 /*
00254  * MD5 final digest
00255  */
00256 void md5_finish( md5_context *ctx, unsigned char output[16] )
00257 {
00258     unsigned long last, padn;
00259     unsigned long high, low;
00260     unsigned char msglen[8];
00261 
00262     high = ( ctx->total[0] >> 29 )
00263          | ( ctx->total[1] <<  3 );
00264     low  = ( ctx->total[0] <<  3 );
00265 
00266     PUT_ULONG_LE( low,  msglen, 0 );
00267     PUT_ULONG_LE( high, msglen, 4 );
00268 
00269     last = ctx->total[0] & 0x3F;
00270     padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
00271 
00272     md5_update( ctx, (unsigned char *) md5_padding, padn );
00273     md5_update( ctx, msglen, 8 );
00274 
00275     PUT_ULONG_LE( ctx->state[0], output,  0 );
00276     PUT_ULONG_LE( ctx->state[1], output,  4 );
00277     PUT_ULONG_LE( ctx->state[2], output,  8 );
00278     PUT_ULONG_LE( ctx->state[3], output, 12 );
00279 }
00280 
00281 /*
00282  * output = MD5( input buffer )
00283  */
00284 void md5( const unsigned char *input, size_t ilen, unsigned char output[16] )
00285 {
00286     md5_context ctx;
00287 
00288     md5_starts( &ctx );
00289     md5_update( &ctx, input, ilen );
00290     md5_finish( &ctx, output );
00291 
00292     memset( &ctx, 0, sizeof( md5_context ) );
00293 }
00294 
00295 #if defined(POLARSSL_FS_IO)
00296 /*
00297  * output = MD5( file contents )
00298  */
00299 int md5_file( const char *path, unsigned char output[16] )
00300 {
00301     FILE *f;
00302     size_t n;
00303     md5_context ctx;
00304     unsigned char buf[1024];
00305 
00306     if( ( f = fopen( path, "rb" ) ) == NULL )
00307         return( POLARSSL_ERR_MD5_FILE_IO_ERROR );
00308 
00309     md5_starts( &ctx );
00310 
00311     while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
00312         md5_update( &ctx, buf, n );
00313 
00314     md5_finish( &ctx, output );
00315 
00316     memset( &ctx, 0, sizeof( md5_context ) );
00317 
00318     if( ferror( f ) != 0 )
00319     {
00320         fclose( f );
00321         return( POLARSSL_ERR_MD5_FILE_IO_ERROR );
00322     }
00323 
00324     fclose( f );
00325     return( 0 );
00326 }
00327 #endif /* POLARSSL_FS_IO */
00328 
00329 /*
00330  * MD5 HMAC context setup
00331  */
00332 void md5_hmac_starts( md5_context *ctx, const unsigned char *key, size_t keylen )
00333 {
00334     size_t i;
00335     unsigned char sum[16];
00336 
00337     if( keylen > 64 )
00338     {
00339         md5( key, keylen, sum );
00340         keylen = 16;
00341         key = sum;
00342     }
00343 
00344     memset( ctx->ipad, 0x36, 64 );
00345     memset( ctx->opad, 0x5C, 64 );
00346 
00347     for( i = 0; i < keylen; i++ )
00348     {
00349         ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
00350         ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
00351     }
00352 
00353     md5_starts( ctx );
00354     md5_update( ctx, ctx->ipad, 64 );
00355 
00356     memset( sum, 0, sizeof( sum ) );
00357 }
00358 
00359 /*
00360  * MD5 HMAC process buffer
00361  */
00362 void md5_hmac_update( md5_context *ctx, const unsigned char *input, size_t ilen )
00363 {
00364     md5_update( ctx, input, ilen );
00365 }
00366 
00367 /*
00368  * MD5 HMAC final digest
00369  */
00370 void md5_hmac_finish( md5_context *ctx, unsigned char output[16] )
00371 {
00372     unsigned char tmpbuf[16];
00373 
00374     md5_finish( ctx, tmpbuf );
00375     md5_starts( ctx );
00376     md5_update( ctx, ctx->opad, 64 );
00377     md5_update( ctx, tmpbuf, 16 );
00378     md5_finish( ctx, output );
00379 
00380     memset( tmpbuf, 0, sizeof( tmpbuf ) );
00381 }
00382 
00383 /*
00384  * MD5 HMAC context reset
00385  */
00386 void md5_hmac_reset( md5_context *ctx )
00387 {
00388     md5_starts( ctx );
00389     md5_update( ctx, ctx->ipad, 64 );
00390 }
00391 
00392 /*
00393  * output = HMAC-MD5( hmac key, input buffer )
00394  */
00395 void md5_hmac( const unsigned char *key, size_t keylen,
00396                const unsigned char *input, size_t ilen,
00397                unsigned char output[16] )
00398 {
00399     md5_context ctx;
00400 
00401     md5_hmac_starts( &ctx, key, keylen );
00402     md5_hmac_update( &ctx, input, ilen );
00403     md5_hmac_finish( &ctx, output );
00404 
00405     memset( &ctx, 0, sizeof( md5_context ) );
00406 }
00407 
00408 #if defined(POLARSSL_SELF_TEST)
00409 /*
00410  * RFC 1321 test vectors
00411  */
00412 static unsigned char md5_test_buf[7][81] =
00413 {
00414     { "" }, 
00415     { "a" },
00416     { "abc" },
00417     { "message digest" },
00418     { "abcdefghijklmnopqrstuvwxyz" },
00419     { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
00420     { "12345678901234567890123456789012345678901234567890123456789012" \
00421       "345678901234567890" }
00422 };
00423 
00424 static const int md5_test_buflen[7] =
00425 {
00426     0, 1, 3, 14, 26, 62, 80
00427 };
00428 
00429 static const unsigned char md5_test_sum[7][16] =
00430 {
00431     { 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04,
00432       0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E },
00433     { 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8,
00434       0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 },
00435     { 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0,
00436       0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 },
00437     { 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D,
00438       0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 },
00439     { 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00,
00440       0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B },
00441     { 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5,
00442       0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F },
00443     { 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55,
00444       0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A }
00445 };
00446 
00447 /*
00448  * RFC 2202 test vectors
00449  */
00450 static unsigned char md5_hmac_test_key[7][26] =
00451 {
00452     { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B" },
00453     { "Jefe" },
00454     { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" },
00455     { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
00456       "\x11\x12\x13\x14\x15\x16\x17\x18\x19" },
00457     { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C" },
00458     { "" }, /* 0xAA 80 times */
00459     { "" }
00460 };
00461 
00462 static const int md5_hmac_test_keylen[7] =
00463 {
00464     16, 4, 16, 25, 16, 80, 80
00465 };
00466 
00467 static unsigned char md5_hmac_test_buf[7][74] =
00468 {
00469     { "Hi There" },
00470     { "what do ya want for nothing?" },
00471     { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
00472       "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
00473       "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
00474       "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
00475       "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" },
00476     { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
00477       "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
00478       "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
00479       "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
00480       "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" },
00481     { "Test With Truncation" },
00482     { "Test Using Larger Than Block-Size Key - Hash Key First" },
00483     { "Test Using Larger Than Block-Size Key and Larger"
00484       " Than One Block-Size Data" }
00485 };
00486 
00487 static const int md5_hmac_test_buflen[7] =
00488 {
00489     8, 28, 50, 50, 20, 54, 73
00490 };
00491 
00492 static const unsigned char md5_hmac_test_sum[7][16] =
00493 {
00494     { 0x92, 0x94, 0x72, 0x7A, 0x36, 0x38, 0xBB, 0x1C,
00495       0x13, 0xF4, 0x8E, 0xF8, 0x15, 0x8B, 0xFC, 0x9D },
00496     { 0x75, 0x0C, 0x78, 0x3E, 0x6A, 0xB0, 0xB5, 0x03,
00497       0xEA, 0xA8, 0x6E, 0x31, 0x0A, 0x5D, 0xB7, 0x38 },
00498     { 0x56, 0xBE, 0x34, 0x52, 0x1D, 0x14, 0x4C, 0x88,
00499       0xDB, 0xB8, 0xC7, 0x33, 0xF0, 0xE8, 0xB3, 0xF6 },
00500     { 0x69, 0x7E, 0xAF, 0x0A, 0xCA, 0x3A, 0x3A, 0xEA,
00501       0x3A, 0x75, 0x16, 0x47, 0x46, 0xFF, 0xAA, 0x79 },
00502     { 0x56, 0x46, 0x1E, 0xF2, 0x34, 0x2E, 0xDC, 0x00,
00503       0xF9, 0xBA, 0xB9, 0x95 },
00504     { 0x6B, 0x1A, 0xB7, 0xFE, 0x4B, 0xD7, 0xBF, 0x8F,
00505       0x0B, 0x62, 0xE6, 0xCE, 0x61, 0xB9, 0xD0, 0xCD },
00506     { 0x6F, 0x63, 0x0F, 0xAD, 0x67, 0xCD, 0xA0, 0xEE,
00507       0x1F, 0xB1, 0xF5, 0x62, 0xDB, 0x3A, 0xA5, 0x3E }
00508 };
00509 
00510 /*
00511  * Checkup routine
00512  */
00513 int md5_self_test( int verbose )
00514 {
00515     int i, buflen;
00516     unsigned char buf[1024];
00517     unsigned char md5sum[16];
00518     md5_context ctx;
00519 
00520     for( i = 0; i < 7; i++ )
00521     {
00522         if( verbose != 0 )
00523             printf( "  MD5 test #%d: ", i + 1 );
00524 
00525         md5( md5_test_buf[i], md5_test_buflen[i], md5sum );
00526 
00527         if( memcmp( md5sum, md5_test_sum[i], 16 ) != 0 )
00528         {
00529             if( verbose != 0 )
00530                 printf( "failed\n" );
00531 
00532             return( 1 );
00533         }
00534 
00535         if( verbose != 0 )
00536             printf( "passed\n" );
00537     }
00538 
00539     if( verbose != 0 )
00540         printf( "\n" );
00541 
00542     for( i = 0; i < 7; i++ )
00543     {
00544         if( verbose != 0 )
00545             printf( "  HMAC-MD5 test #%d: ", i + 1 );
00546 
00547         if( i == 5 || i == 6 )
00548         {
00549             memset( buf, '\xAA', buflen = 80 );
00550             md5_hmac_starts( &ctx, buf, buflen );
00551         }
00552         else
00553             md5_hmac_starts( &ctx, md5_hmac_test_key[i],
00554                                    md5_hmac_test_keylen[i] );
00555 
00556         md5_hmac_update( &ctx, md5_hmac_test_buf[i],
00557                                md5_hmac_test_buflen[i] );
00558 
00559         md5_hmac_finish( &ctx, md5sum );
00560 
00561         buflen = ( i == 4 ) ? 12 : 16;
00562 
00563         if( memcmp( md5sum, md5_hmac_test_sum[i], buflen ) != 0 )
00564         {
00565             if( verbose != 0 )
00566                 printf( "failed\n" );
00567 
00568             return( 1 );
00569         }
00570 
00571         if( verbose != 0 )
00572             printf( "passed\n" );
00573     }
00574 
00575     if( verbose != 0 )
00576         printf( "\n" );
00577 
00578     return( 0 );
00579 }
00580 
00581 #endif
00582 
00583 #endif