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