blob: 2259dc69dec785748fe0078db3359a6a40df0ac5 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * RFC 1321 compliant MD5 implementation
3 *
Paul Bakker530927b2015-02-13 14:24:10 +01004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Paul Bakkerb96f1542010-07-18 20:36:00 +00005 *
Manuel Pégourié-Gonnarde12abf92015-01-28 17:13:45 +00006 * This file is part of mbed TLS (https://polarssl.org)
Paul Bakkere0ccd0a2009-01-04 16:27:10 +00007 *
Paul Bakker5121ce52009-01-03 21:22:43 +00008 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22/*
23 * The MD5 algorithm was designed by Ron Rivest in 1991.
24 *
25 * http://www.ietf.org/rfc/rfc1321.txt
26 */
27
Paul Bakker40e46942009-01-03 21:51:57 +000028#include "polarssl/config.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000029
Paul Bakker40e46942009-01-03 21:51:57 +000030#if defined(POLARSSL_MD5_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000031
Paul Bakker40e46942009-01-03 21:51:57 +000032#include "polarssl/md5.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000033
Paul Bakker335db3f2011-04-25 15:28:35 +000034#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +000035#include <stdio.h>
Paul Bakker335db3f2011-04-25 15:28:35 +000036#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000037
Manuel Pégourié-Gonnardaa4e55b2015-08-31 11:22:01 +020038#if !defined(POLARSSL_MD5_ALT)
39
Paul Bakker312da332014-06-13 17:20:13 +020040/* Implementation that should never be optimized out by the compiler */
41static void polarssl_zeroize( void *v, size_t n ) {
42 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
43}
44
Paul Bakker5121ce52009-01-03 21:22:43 +000045/*
46 * 32-bit integer manipulation macros (little endian)
47 */
Paul Bakker5c2364c2012-10-01 14:41:15 +000048#ifndef GET_UINT32_LE
49#define GET_UINT32_LE(n,b,i) \
Paul Bakker5121ce52009-01-03 21:22:43 +000050{ \
Paul Bakker5c2364c2012-10-01 14:41:15 +000051 (n) = ( (uint32_t) (b)[(i) ] ) \
52 | ( (uint32_t) (b)[(i) + 1] << 8 ) \
53 | ( (uint32_t) (b)[(i) + 2] << 16 ) \
54 | ( (uint32_t) (b)[(i) + 3] << 24 ); \
Paul Bakker5121ce52009-01-03 21:22:43 +000055}
56#endif
57
Paul Bakker5c2364c2012-10-01 14:41:15 +000058#ifndef PUT_UINT32_LE
59#define PUT_UINT32_LE(n,b,i) \
Paul Bakker5121ce52009-01-03 21:22:43 +000060{ \
61 (b)[(i) ] = (unsigned char) ( (n) ); \
62 (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \
63 (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \
64 (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \
65}
66#endif
67
68/*
69 * MD5 context setup
70 */
71void md5_starts( md5_context *ctx )
72{
73 ctx->total[0] = 0;
74 ctx->total[1] = 0;
75
76 ctx->state[0] = 0x67452301;
77 ctx->state[1] = 0xEFCDAB89;
78 ctx->state[2] = 0x98BADCFE;
79 ctx->state[3] = 0x10325476;
80}
81
Paul Bakkere47b34b2013-02-27 14:48:00 +010082void md5_process( md5_context *ctx, const unsigned char data[64] )
Paul Bakker5121ce52009-01-03 21:22:43 +000083{
Paul Bakker5c2364c2012-10-01 14:41:15 +000084 uint32_t X[16], A, B, C, D;
Paul Bakker5121ce52009-01-03 21:22:43 +000085
Paul Bakker5c2364c2012-10-01 14:41:15 +000086 GET_UINT32_LE( X[ 0], data, 0 );
87 GET_UINT32_LE( X[ 1], data, 4 );
88 GET_UINT32_LE( X[ 2], data, 8 );
89 GET_UINT32_LE( X[ 3], data, 12 );
90 GET_UINT32_LE( X[ 4], data, 16 );
91 GET_UINT32_LE( X[ 5], data, 20 );
92 GET_UINT32_LE( X[ 6], data, 24 );
93 GET_UINT32_LE( X[ 7], data, 28 );
94 GET_UINT32_LE( X[ 8], data, 32 );
95 GET_UINT32_LE( X[ 9], data, 36 );
96 GET_UINT32_LE( X[10], data, 40 );
97 GET_UINT32_LE( X[11], data, 44 );
98 GET_UINT32_LE( X[12], data, 48 );
99 GET_UINT32_LE( X[13], data, 52 );
100 GET_UINT32_LE( X[14], data, 56 );
101 GET_UINT32_LE( X[15], data, 60 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000102
103#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
104
105#define P(a,b,c,d,k,s,t) \
106{ \
107 a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \
108}
109
110 A = ctx->state[0];
111 B = ctx->state[1];
112 C = ctx->state[2];
113 D = ctx->state[3];
114
115#define F(x,y,z) (z ^ (x & (y ^ z)))
116
117 P( A, B, C, D, 0, 7, 0xD76AA478 );
118 P( D, A, B, C, 1, 12, 0xE8C7B756 );
119 P( C, D, A, B, 2, 17, 0x242070DB );
120 P( B, C, D, A, 3, 22, 0xC1BDCEEE );
121 P( A, B, C, D, 4, 7, 0xF57C0FAF );
122 P( D, A, B, C, 5, 12, 0x4787C62A );
123 P( C, D, A, B, 6, 17, 0xA8304613 );
124 P( B, C, D, A, 7, 22, 0xFD469501 );
125 P( A, B, C, D, 8, 7, 0x698098D8 );
126 P( D, A, B, C, 9, 12, 0x8B44F7AF );
127 P( C, D, A, B, 10, 17, 0xFFFF5BB1 );
128 P( B, C, D, A, 11, 22, 0x895CD7BE );
129 P( A, B, C, D, 12, 7, 0x6B901122 );
130 P( D, A, B, C, 13, 12, 0xFD987193 );
131 P( C, D, A, B, 14, 17, 0xA679438E );
132 P( B, C, D, A, 15, 22, 0x49B40821 );
133
134#undef F
135
136#define F(x,y,z) (y ^ (z & (x ^ y)))
137
138 P( A, B, C, D, 1, 5, 0xF61E2562 );
139 P( D, A, B, C, 6, 9, 0xC040B340 );
140 P( C, D, A, B, 11, 14, 0x265E5A51 );
141 P( B, C, D, A, 0, 20, 0xE9B6C7AA );
142 P( A, B, C, D, 5, 5, 0xD62F105D );
143 P( D, A, B, C, 10, 9, 0x02441453 );
144 P( C, D, A, B, 15, 14, 0xD8A1E681 );
145 P( B, C, D, A, 4, 20, 0xE7D3FBC8 );
146 P( A, B, C, D, 9, 5, 0x21E1CDE6 );
147 P( D, A, B, C, 14, 9, 0xC33707D6 );
148 P( C, D, A, B, 3, 14, 0xF4D50D87 );
149 P( B, C, D, A, 8, 20, 0x455A14ED );
150 P( A, B, C, D, 13, 5, 0xA9E3E905 );
151 P( D, A, B, C, 2, 9, 0xFCEFA3F8 );
152 P( C, D, A, B, 7, 14, 0x676F02D9 );
153 P( B, C, D, A, 12, 20, 0x8D2A4C8A );
154
155#undef F
156
157#define F(x,y,z) (x ^ y ^ z)
158
159 P( A, B, C, D, 5, 4, 0xFFFA3942 );
160 P( D, A, B, C, 8, 11, 0x8771F681 );
161 P( C, D, A, B, 11, 16, 0x6D9D6122 );
162 P( B, C, D, A, 14, 23, 0xFDE5380C );
163 P( A, B, C, D, 1, 4, 0xA4BEEA44 );
164 P( D, A, B, C, 4, 11, 0x4BDECFA9 );
165 P( C, D, A, B, 7, 16, 0xF6BB4B60 );
166 P( B, C, D, A, 10, 23, 0xBEBFBC70 );
167 P( A, B, C, D, 13, 4, 0x289B7EC6 );
168 P( D, A, B, C, 0, 11, 0xEAA127FA );
169 P( C, D, A, B, 3, 16, 0xD4EF3085 );
170 P( B, C, D, A, 6, 23, 0x04881D05 );
171 P( A, B, C, D, 9, 4, 0xD9D4D039 );
172 P( D, A, B, C, 12, 11, 0xE6DB99E5 );
173 P( C, D, A, B, 15, 16, 0x1FA27CF8 );
174 P( B, C, D, A, 2, 23, 0xC4AC5665 );
175
176#undef F
177
178#define F(x,y,z) (y ^ (x | ~z))
179
180 P( A, B, C, D, 0, 6, 0xF4292244 );
181 P( D, A, B, C, 7, 10, 0x432AFF97 );
182 P( C, D, A, B, 14, 15, 0xAB9423A7 );
183 P( B, C, D, A, 5, 21, 0xFC93A039 );
184 P( A, B, C, D, 12, 6, 0x655B59C3 );
185 P( D, A, B, C, 3, 10, 0x8F0CCC92 );
186 P( C, D, A, B, 10, 15, 0xFFEFF47D );
187 P( B, C, D, A, 1, 21, 0x85845DD1 );
188 P( A, B, C, D, 8, 6, 0x6FA87E4F );
189 P( D, A, B, C, 15, 10, 0xFE2CE6E0 );
190 P( C, D, A, B, 6, 15, 0xA3014314 );
191 P( B, C, D, A, 13, 21, 0x4E0811A1 );
192 P( A, B, C, D, 4, 6, 0xF7537E82 );
193 P( D, A, B, C, 11, 10, 0xBD3AF235 );
194 P( C, D, A, B, 2, 15, 0x2AD7D2BB );
195 P( B, C, D, A, 9, 21, 0xEB86D391 );
196
197#undef F
198
199 ctx->state[0] += A;
200 ctx->state[1] += B;
201 ctx->state[2] += C;
202 ctx->state[3] += D;
203}
204
205/*
206 * MD5 process buffer
207 */
Paul Bakker23986e52011-04-24 08:57:21 +0000208void md5_update( md5_context *ctx, const unsigned char *input, size_t ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000209{
Paul Bakker23986e52011-04-24 08:57:21 +0000210 size_t fill;
Paul Bakker5c2364c2012-10-01 14:41:15 +0000211 uint32_t left;
Paul Bakker5121ce52009-01-03 21:22:43 +0000212
213 if( ilen <= 0 )
214 return;
215
216 left = ctx->total[0] & 0x3F;
217 fill = 64 - left;
218
Paul Bakker5c2364c2012-10-01 14:41:15 +0000219 ctx->total[0] += (uint32_t) ilen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000220 ctx->total[0] &= 0xFFFFFFFF;
221
Paul Bakker5c2364c2012-10-01 14:41:15 +0000222 if( ctx->total[0] < (uint32_t) ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000223 ctx->total[1]++;
224
225 if( left && ilen >= fill )
226 {
Paul Bakkereae09db2013-06-06 12:35:54 +0200227 memcpy( (void *) (ctx->buffer + left), input, fill );
Paul Bakker5121ce52009-01-03 21:22:43 +0000228 md5_process( ctx, ctx->buffer );
229 input += fill;
230 ilen -= fill;
231 left = 0;
232 }
233
234 while( ilen >= 64 )
235 {
236 md5_process( ctx, input );
237 input += 64;
238 ilen -= 64;
239 }
240
241 if( ilen > 0 )
242 {
Paul Bakkereae09db2013-06-06 12:35:54 +0200243 memcpy( (void *) (ctx->buffer + left), input, ilen );
Paul Bakker5121ce52009-01-03 21:22:43 +0000244 }
245}
246
247static const unsigned char md5_padding[64] =
248{
249 0x80, 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 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
252 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
253};
254
255/*
256 * MD5 final digest
257 */
258void md5_finish( md5_context *ctx, unsigned char output[16] )
259{
Paul Bakker5c2364c2012-10-01 14:41:15 +0000260 uint32_t last, padn;
261 uint32_t high, low;
Paul Bakker5121ce52009-01-03 21:22:43 +0000262 unsigned char msglen[8];
263
264 high = ( ctx->total[0] >> 29 )
265 | ( ctx->total[1] << 3 );
266 low = ( ctx->total[0] << 3 );
267
Paul Bakker5c2364c2012-10-01 14:41:15 +0000268 PUT_UINT32_LE( low, msglen, 0 );
269 PUT_UINT32_LE( high, msglen, 4 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000270
271 last = ctx->total[0] & 0x3F;
272 padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
273
Paul Bakkereae09db2013-06-06 12:35:54 +0200274 md5_update( ctx, md5_padding, padn );
Paul Bakker5121ce52009-01-03 21:22:43 +0000275 md5_update( ctx, msglen, 8 );
276
Paul Bakker5c2364c2012-10-01 14:41:15 +0000277 PUT_UINT32_LE( ctx->state[0], output, 0 );
278 PUT_UINT32_LE( ctx->state[1], output, 4 );
279 PUT_UINT32_LE( ctx->state[2], output, 8 );
280 PUT_UINT32_LE( ctx->state[3], output, 12 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000281}
282
Paul Bakker4087c472013-06-12 16:49:10 +0200283#endif /* !POLARSSL_MD5_ALT */
284
Paul Bakker5121ce52009-01-03 21:22:43 +0000285/*
286 * output = MD5( input buffer )
287 */
Paul Bakker23986e52011-04-24 08:57:21 +0000288void md5( const unsigned char *input, size_t ilen, unsigned char output[16] )
Paul Bakker5121ce52009-01-03 21:22:43 +0000289{
290 md5_context ctx;
291
292 md5_starts( &ctx );
293 md5_update( &ctx, input, ilen );
294 md5_finish( &ctx, output );
295
Paul Bakker312da332014-06-13 17:20:13 +0200296 polarssl_zeroize( &ctx, sizeof( md5_context ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000297}
298
Paul Bakker335db3f2011-04-25 15:28:35 +0000299#if defined(POLARSSL_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000300/*
301 * output = MD5( file contents )
302 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000303int md5_file( const char *path, unsigned char output[16] )
Paul Bakker5121ce52009-01-03 21:22:43 +0000304{
305 FILE *f;
306 size_t n;
307 md5_context ctx;
308 unsigned char buf[1024];
309
310 if( ( f = fopen( path, "rb" ) ) == NULL )
Paul Bakker69e095c2011-12-10 21:55:01 +0000311 return( POLARSSL_ERR_MD5_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000312
313 md5_starts( &ctx );
314
315 while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
Paul Bakker27fdf462011-06-09 13:55:13 +0000316 md5_update( &ctx, buf, n );
Paul Bakker5121ce52009-01-03 21:22:43 +0000317
318 md5_finish( &ctx, output );
319
Paul Bakker312da332014-06-13 17:20:13 +0200320 polarssl_zeroize( &ctx, sizeof( md5_context ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000321
322 if( ferror( f ) != 0 )
323 {
324 fclose( f );
Paul Bakker69e095c2011-12-10 21:55:01 +0000325 return( POLARSSL_ERR_MD5_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000326 }
327
328 fclose( f );
329 return( 0 );
330}
Paul Bakker335db3f2011-04-25 15:28:35 +0000331#endif /* POLARSSL_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000332
333/*
334 * MD5 HMAC context setup
335 */
Paul Bakker23986e52011-04-24 08:57:21 +0000336void md5_hmac_starts( md5_context *ctx, const unsigned char *key, size_t keylen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000337{
Paul Bakker23986e52011-04-24 08:57:21 +0000338 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000339 unsigned char sum[16];
340
341 if( keylen > 64 )
342 {
343 md5( key, keylen, sum );
344 keylen = 16;
345 key = sum;
346 }
347
348 memset( ctx->ipad, 0x36, 64 );
349 memset( ctx->opad, 0x5C, 64 );
350
351 for( i = 0; i < keylen; i++ )
352 {
353 ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
354 ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
355 }
356
357 md5_starts( ctx );
358 md5_update( ctx, ctx->ipad, 64 );
359
Paul Bakker312da332014-06-13 17:20:13 +0200360 polarssl_zeroize( sum, sizeof( sum ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000361}
362
363/*
364 * MD5 HMAC process buffer
365 */
Paul Bakker23986e52011-04-24 08:57:21 +0000366void md5_hmac_update( md5_context *ctx, const unsigned char *input, size_t ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000367{
368 md5_update( ctx, input, ilen );
369}
370
371/*
372 * MD5 HMAC final digest
373 */
374void md5_hmac_finish( md5_context *ctx, unsigned char output[16] )
375{
376 unsigned char tmpbuf[16];
377
378 md5_finish( ctx, tmpbuf );
379 md5_starts( ctx );
380 md5_update( ctx, ctx->opad, 64 );
381 md5_update( ctx, tmpbuf, 16 );
382 md5_finish( ctx, output );
383
Paul Bakker312da332014-06-13 17:20:13 +0200384 polarssl_zeroize( tmpbuf, sizeof( tmpbuf ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000385}
386
387/*
Paul Bakker7d3b6612010-03-21 16:23:13 +0000388 * MD5 HMAC context reset
389 */
390void md5_hmac_reset( md5_context *ctx )
391{
392 md5_starts( ctx );
393 md5_update( ctx, ctx->ipad, 64 );
394}
395
396/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000397 * output = HMAC-MD5( hmac key, input buffer )
398 */
Paul Bakker23986e52011-04-24 08:57:21 +0000399void md5_hmac( const unsigned char *key, size_t keylen,
400 const unsigned char *input, size_t ilen,
Paul Bakker5121ce52009-01-03 21:22:43 +0000401 unsigned char output[16] )
402{
403 md5_context ctx;
404
405 md5_hmac_starts( &ctx, key, keylen );
406 md5_hmac_update( &ctx, input, ilen );
407 md5_hmac_finish( &ctx, output );
408
Paul Bakker312da332014-06-13 17:20:13 +0200409 polarssl_zeroize( &ctx, sizeof( md5_context ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000410}
411
Paul Bakker40e46942009-01-03 21:51:57 +0000412#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000413/*
414 * RFC 1321 test vectors
415 */
416static unsigned char md5_test_buf[7][81] =
417{
418 { "" },
419 { "a" },
420 { "abc" },
421 { "message digest" },
422 { "abcdefghijklmnopqrstuvwxyz" },
423 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
424 { "12345678901234567890123456789012345678901234567890123456789012" \
425 "345678901234567890" }
426};
427
428static const int md5_test_buflen[7] =
429{
430 0, 1, 3, 14, 26, 62, 80
431};
432
433static const unsigned char md5_test_sum[7][16] =
434{
435 { 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04,
436 0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E },
437 { 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8,
438 0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 },
439 { 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0,
440 0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 },
441 { 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D,
442 0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 },
443 { 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00,
444 0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B },
445 { 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5,
446 0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F },
447 { 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55,
448 0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A }
449};
450
451/*
452 * RFC 2202 test vectors
453 */
454static unsigned char md5_hmac_test_key[7][26] =
455{
456 { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B" },
457 { "Jefe" },
458 { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" },
459 { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
460 "\x11\x12\x13\x14\x15\x16\x17\x18\x19" },
461 { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C" },
462 { "" }, /* 0xAA 80 times */
463 { "" }
464};
465
466static const int md5_hmac_test_keylen[7] =
467{
468 16, 4, 16, 25, 16, 80, 80
469};
470
471static unsigned char md5_hmac_test_buf[7][74] =
472{
473 { "Hi There" },
474 { "what do ya want for nothing?" },
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 "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
479 "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" },
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 "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
484 "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" },
485 { "Test With Truncation" },
486 { "Test Using Larger Than Block-Size Key - Hash Key First" },
487 { "Test Using Larger Than Block-Size Key and Larger"
488 " Than One Block-Size Data" }
489};
490
491static const int md5_hmac_test_buflen[7] =
492{
493 8, 28, 50, 50, 20, 54, 73
494};
495
496static const unsigned char md5_hmac_test_sum[7][16] =
497{
498 { 0x92, 0x94, 0x72, 0x7A, 0x36, 0x38, 0xBB, 0x1C,
499 0x13, 0xF4, 0x8E, 0xF8, 0x15, 0x8B, 0xFC, 0x9D },
500 { 0x75, 0x0C, 0x78, 0x3E, 0x6A, 0xB0, 0xB5, 0x03,
501 0xEA, 0xA8, 0x6E, 0x31, 0x0A, 0x5D, 0xB7, 0x38 },
502 { 0x56, 0xBE, 0x34, 0x52, 0x1D, 0x14, 0x4C, 0x88,
503 0xDB, 0xB8, 0xC7, 0x33, 0xF0, 0xE8, 0xB3, 0xF6 },
504 { 0x69, 0x7E, 0xAF, 0x0A, 0xCA, 0x3A, 0x3A, 0xEA,
505 0x3A, 0x75, 0x16, 0x47, 0x46, 0xFF, 0xAA, 0x79 },
506 { 0x56, 0x46, 0x1E, 0xF2, 0x34, 0x2E, 0xDC, 0x00,
507 0xF9, 0xBA, 0xB9, 0x95 },
508 { 0x6B, 0x1A, 0xB7, 0xFE, 0x4B, 0xD7, 0xBF, 0x8F,
509 0x0B, 0x62, 0xE6, 0xCE, 0x61, 0xB9, 0xD0, 0xCD },
510 { 0x6F, 0x63, 0x0F, 0xAD, 0x67, 0xCD, 0xA0, 0xEE,
511 0x1F, 0xB1, 0xF5, 0x62, 0xDB, 0x3A, 0xA5, 0x3E }
512};
513
514/*
515 * Checkup routine
516 */
517int md5_self_test( int verbose )
518{
519 int i, buflen;
520 unsigned char buf[1024];
521 unsigned char md5sum[16];
522 md5_context ctx;
523
524 for( i = 0; i < 7; i++ )
525 {
526 if( verbose != 0 )
527 printf( " MD5 test #%d: ", i + 1 );
528
529 md5( md5_test_buf[i], md5_test_buflen[i], md5sum );
530
531 if( memcmp( md5sum, md5_test_sum[i], 16 ) != 0 )
532 {
533 if( verbose != 0 )
534 printf( "failed\n" );
535
536 return( 1 );
537 }
538
539 if( verbose != 0 )
540 printf( "passed\n" );
541 }
542
543 if( verbose != 0 )
544 printf( "\n" );
545
546 for( i = 0; i < 7; i++ )
547 {
548 if( verbose != 0 )
549 printf( " HMAC-MD5 test #%d: ", i + 1 );
550
551 if( i == 5 || i == 6 )
552 {
553 memset( buf, '\xAA', buflen = 80 );
554 md5_hmac_starts( &ctx, buf, buflen );
555 }
556 else
557 md5_hmac_starts( &ctx, md5_hmac_test_key[i],
558 md5_hmac_test_keylen[i] );
559
560 md5_hmac_update( &ctx, md5_hmac_test_buf[i],
561 md5_hmac_test_buflen[i] );
562
563 md5_hmac_finish( &ctx, md5sum );
564
565 buflen = ( i == 4 ) ? 12 : 16;
566
567 if( memcmp( md5sum, md5_hmac_test_sum[i], buflen ) != 0 )
568 {
569 if( verbose != 0 )
570 printf( "failed\n" );
571
572 return( 1 );
573 }
574
575 if( verbose != 0 )
576 printf( "passed\n" );
577 }
578
579 if( verbose != 0 )
580 printf( "\n" );
581
582 return( 0 );
583}
584
585#endif
586
587#endif