blob: e14c83dc2451e11e2f89103df8568d9ef36def57 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * RFC 1186/1320 compliant MD4 implementation
3 *
Paul Bakker90995b52013-06-24 19:20:35 +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 MD4 algorithm was designed by Ron Rivest in 1990.
27 *
28 * http://www.ietf.org/rfc/rfc1186.txt
29 * http://www.ietf.org/rfc/rfc1320.txt
30 */
31
Paul Bakker40e46942009-01-03 21:51:57 +000032#include "polarssl/config.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000033
Paul Bakker40e46942009-01-03 21:51:57 +000034#if defined(POLARSSL_MD4_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000035
Paul Bakker40e46942009-01-03 21:51:57 +000036#include "polarssl/md4.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000037
Paul Bakker335db3f2011-04-25 15:28:35 +000038#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +000039#include <stdio.h>
Paul Bakker335db3f2011-04-25 15:28:35 +000040#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000041
Paul Bakker90995b52013-06-24 19:20:35 +020042#if !defined(POLARSSL_MD4_ALT)
43
Paul Bakker5121ce52009-01-03 21:22:43 +000044/*
45 * 32-bit integer manipulation macros (little endian)
46 */
Paul Bakker5c2364c2012-10-01 14:41:15 +000047#ifndef GET_UINT32_LE
48#define GET_UINT32_LE(n,b,i) \
Paul Bakker5121ce52009-01-03 21:22:43 +000049{ \
Paul Bakker5c2364c2012-10-01 14:41:15 +000050 (n) = ( (uint32_t) (b)[(i) ] ) \
51 | ( (uint32_t) (b)[(i) + 1] << 8 ) \
52 | ( (uint32_t) (b)[(i) + 2] << 16 ) \
53 | ( (uint32_t) (b)[(i) + 3] << 24 ); \
Paul Bakker5121ce52009-01-03 21:22:43 +000054}
55#endif
56
Paul Bakker5c2364c2012-10-01 14:41:15 +000057#ifndef PUT_UINT32_LE
58#define PUT_UINT32_LE(n,b,i) \
Paul Bakker5121ce52009-01-03 21:22:43 +000059{ \
60 (b)[(i) ] = (unsigned char) ( (n) ); \
61 (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \
62 (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \
63 (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \
64}
65#endif
66
67/*
68 * MD4 context setup
69 */
70void md4_starts( md4_context *ctx )
71{
72 ctx->total[0] = 0;
73 ctx->total[1] = 0;
74
75 ctx->state[0] = 0x67452301;
76 ctx->state[1] = 0xEFCDAB89;
77 ctx->state[2] = 0x98BADCFE;
78 ctx->state[3] = 0x10325476;
79}
80
Paul Bakker1bd3ae82013-03-13 10:26:44 +010081void md4_process( md4_context *ctx, const unsigned char data[64] )
Paul Bakker5121ce52009-01-03 21:22:43 +000082{
Paul Bakker5c2364c2012-10-01 14:41:15 +000083 uint32_t X[16], A, B, C, D;
Paul Bakker5121ce52009-01-03 21:22:43 +000084
Paul Bakker5c2364c2012-10-01 14:41:15 +000085 GET_UINT32_LE( X[ 0], data, 0 );
86 GET_UINT32_LE( X[ 1], data, 4 );
87 GET_UINT32_LE( X[ 2], data, 8 );
88 GET_UINT32_LE( X[ 3], data, 12 );
89 GET_UINT32_LE( X[ 4], data, 16 );
90 GET_UINT32_LE( X[ 5], data, 20 );
91 GET_UINT32_LE( X[ 6], data, 24 );
92 GET_UINT32_LE( X[ 7], data, 28 );
93 GET_UINT32_LE( X[ 8], data, 32 );
94 GET_UINT32_LE( X[ 9], data, 36 );
95 GET_UINT32_LE( X[10], data, 40 );
96 GET_UINT32_LE( X[11], data, 44 );
97 GET_UINT32_LE( X[12], data, 48 );
98 GET_UINT32_LE( X[13], data, 52 );
99 GET_UINT32_LE( X[14], data, 56 );
100 GET_UINT32_LE( X[15], data, 60 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000101
102#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
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) ((x & y) | ((~x) & z))
110#define P(a,b,c,d,x,s) { a += F(b,c,d) + x; a = S(a,s); }
111
112 P( A, B, C, D, X[ 0], 3 );
113 P( D, A, B, C, X[ 1], 7 );
114 P( C, D, A, B, X[ 2], 11 );
115 P( B, C, D, A, X[ 3], 19 );
116 P( A, B, C, D, X[ 4], 3 );
117 P( D, A, B, C, X[ 5], 7 );
118 P( C, D, A, B, X[ 6], 11 );
119 P( B, C, D, A, X[ 7], 19 );
120 P( A, B, C, D, X[ 8], 3 );
121 P( D, A, B, C, X[ 9], 7 );
122 P( C, D, A, B, X[10], 11 );
123 P( B, C, D, A, X[11], 19 );
124 P( A, B, C, D, X[12], 3 );
125 P( D, A, B, C, X[13], 7 );
126 P( C, D, A, B, X[14], 11 );
127 P( B, C, D, A, X[15], 19 );
128
129#undef P
130#undef F
131
132#define F(x,y,z) ((x & y) | (x & z) | (y & z))
133#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x5A827999; a = S(a,s); }
134
135 P( A, B, C, D, X[ 0], 3 );
136 P( D, A, B, C, X[ 4], 5 );
137 P( C, D, A, B, X[ 8], 9 );
138 P( B, C, D, A, X[12], 13 );
139 P( A, B, C, D, X[ 1], 3 );
140 P( D, A, B, C, X[ 5], 5 );
141 P( C, D, A, B, X[ 9], 9 );
142 P( B, C, D, A, X[13], 13 );
143 P( A, B, C, D, X[ 2], 3 );
144 P( D, A, B, C, X[ 6], 5 );
145 P( C, D, A, B, X[10], 9 );
146 P( B, C, D, A, X[14], 13 );
147 P( A, B, C, D, X[ 3], 3 );
148 P( D, A, B, C, X[ 7], 5 );
149 P( C, D, A, B, X[11], 9 );
150 P( B, C, D, A, X[15], 13 );
151
152#undef P
153#undef F
154
155#define F(x,y,z) (x ^ y ^ z)
156#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x6ED9EBA1; a = S(a,s); }
157
158 P( A, B, C, D, X[ 0], 3 );
159 P( D, A, B, C, X[ 8], 9 );
160 P( C, D, A, B, X[ 4], 11 );
161 P( B, C, D, A, X[12], 15 );
162 P( A, B, C, D, X[ 2], 3 );
163 P( D, A, B, C, X[10], 9 );
164 P( C, D, A, B, X[ 6], 11 );
165 P( B, C, D, A, X[14], 15 );
166 P( A, B, C, D, X[ 1], 3 );
167 P( D, A, B, C, X[ 9], 9 );
168 P( C, D, A, B, X[ 5], 11 );
169 P( B, C, D, A, X[13], 15 );
170 P( A, B, C, D, X[ 3], 3 );
171 P( D, A, B, C, X[11], 9 );
172 P( C, D, A, B, X[ 7], 11 );
173 P( B, C, D, A, X[15], 15 );
174
175#undef F
176#undef P
177
178 ctx->state[0] += A;
179 ctx->state[1] += B;
180 ctx->state[2] += C;
181 ctx->state[3] += D;
182}
183
184/*
185 * MD4 process buffer
186 */
Paul Bakker23986e52011-04-24 08:57:21 +0000187void md4_update( md4_context *ctx, const unsigned char *input, size_t ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000188{
Paul Bakker23986e52011-04-24 08:57:21 +0000189 size_t fill;
Paul Bakker5c2364c2012-10-01 14:41:15 +0000190 uint32_t left;
Paul Bakker5121ce52009-01-03 21:22:43 +0000191
192 if( ilen <= 0 )
193 return;
194
195 left = ctx->total[0] & 0x3F;
196 fill = 64 - left;
197
Paul Bakker5c2364c2012-10-01 14:41:15 +0000198 ctx->total[0] += (uint32_t) ilen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000199 ctx->total[0] &= 0xFFFFFFFF;
200
Paul Bakker5c2364c2012-10-01 14:41:15 +0000201 if( ctx->total[0] < (uint32_t) ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000202 ctx->total[1]++;
203
204 if( left && ilen >= fill )
205 {
206 memcpy( (void *) (ctx->buffer + left),
207 (void *) input, fill );
208 md4_process( ctx, ctx->buffer );
209 input += fill;
210 ilen -= fill;
211 left = 0;
212 }
213
214 while( ilen >= 64 )
215 {
216 md4_process( ctx, input );
217 input += 64;
218 ilen -= 64;
219 }
220
221 if( ilen > 0 )
222 {
223 memcpy( (void *) (ctx->buffer + left),
224 (void *) input, ilen );
225 }
226}
227
228static const unsigned char md4_padding[64] =
229{
230 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
231 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
232 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
233 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
234};
235
236/*
237 * MD4 final digest
238 */
239void md4_finish( md4_context *ctx, unsigned char output[16] )
240{
Paul Bakker5c2364c2012-10-01 14:41:15 +0000241 uint32_t last, padn;
242 uint32_t high, low;
Paul Bakker5121ce52009-01-03 21:22:43 +0000243 unsigned char msglen[8];
244
245 high = ( ctx->total[0] >> 29 )
246 | ( ctx->total[1] << 3 );
247 low = ( ctx->total[0] << 3 );
248
Paul Bakker5c2364c2012-10-01 14:41:15 +0000249 PUT_UINT32_LE( low, msglen, 0 );
250 PUT_UINT32_LE( high, msglen, 4 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000251
252 last = ctx->total[0] & 0x3F;
253 padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
254
255 md4_update( ctx, (unsigned char *) md4_padding, padn );
256 md4_update( ctx, msglen, 8 );
257
Paul Bakker5c2364c2012-10-01 14:41:15 +0000258 PUT_UINT32_LE( ctx->state[0], output, 0 );
259 PUT_UINT32_LE( ctx->state[1], output, 4 );
260 PUT_UINT32_LE( ctx->state[2], output, 8 );
261 PUT_UINT32_LE( ctx->state[3], output, 12 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000262}
263
Paul Bakker90995b52013-06-24 19:20:35 +0200264#endif /* !POLARSSL_MD4_ALT */
265
Paul Bakker5121ce52009-01-03 21:22:43 +0000266/*
267 * output = MD4( input buffer )
268 */
Paul Bakker23986e52011-04-24 08:57:21 +0000269void md4( const unsigned char *input, size_t ilen, unsigned char output[16] )
Paul Bakker5121ce52009-01-03 21:22:43 +0000270{
271 md4_context ctx;
272
273 md4_starts( &ctx );
274 md4_update( &ctx, input, ilen );
275 md4_finish( &ctx, output );
276
277 memset( &ctx, 0, sizeof( md4_context ) );
278}
279
Paul Bakker335db3f2011-04-25 15:28:35 +0000280#if defined(POLARSSL_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000281/*
282 * output = MD4( file contents )
283 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000284int md4_file( const char *path, unsigned char output[16] )
Paul Bakker5121ce52009-01-03 21:22:43 +0000285{
286 FILE *f;
287 size_t n;
288 md4_context ctx;
289 unsigned char buf[1024];
290
291 if( ( f = fopen( path, "rb" ) ) == NULL )
Paul Bakker69e095c2011-12-10 21:55:01 +0000292 return( POLARSSL_ERR_MD4_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000293
294 md4_starts( &ctx );
295
296 while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
Paul Bakker27fdf462011-06-09 13:55:13 +0000297 md4_update( &ctx, buf, n );
Paul Bakker5121ce52009-01-03 21:22:43 +0000298
299 md4_finish( &ctx, output );
300
301 memset( &ctx, 0, sizeof( md4_context ) );
302
303 if( ferror( f ) != 0 )
304 {
305 fclose( f );
Paul Bakker69e095c2011-12-10 21:55:01 +0000306 return( POLARSSL_ERR_MD4_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000307 }
308
309 fclose( f );
310 return( 0 );
311}
Paul Bakker335db3f2011-04-25 15:28:35 +0000312#endif /* POLARSSL_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000313
314/*
315 * MD4 HMAC context setup
316 */
Paul Bakker23986e52011-04-24 08:57:21 +0000317void md4_hmac_starts( md4_context *ctx, const unsigned char *key, size_t keylen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000318{
Paul Bakker23986e52011-04-24 08:57:21 +0000319 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000320 unsigned char sum[16];
321
322 if( keylen > 64 )
323 {
324 md4( key, keylen, sum );
325 keylen = 16;
326 key = sum;
327 }
328
329 memset( ctx->ipad, 0x36, 64 );
330 memset( ctx->opad, 0x5C, 64 );
331
332 for( i = 0; i < keylen; i++ )
333 {
334 ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
335 ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
336 }
337
338 md4_starts( ctx );
339 md4_update( ctx, ctx->ipad, 64 );
340
341 memset( sum, 0, sizeof( sum ) );
342}
343
344/*
345 * MD4 HMAC process buffer
346 */
Paul Bakker23986e52011-04-24 08:57:21 +0000347void md4_hmac_update( md4_context *ctx, const unsigned char *input, size_t ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000348{
349 md4_update( ctx, input, ilen );
350}
351
352/*
353 * MD4 HMAC final digest
354 */
355void md4_hmac_finish( md4_context *ctx, unsigned char output[16] )
356{
357 unsigned char tmpbuf[16];
358
359 md4_finish( ctx, tmpbuf );
360 md4_starts( ctx );
361 md4_update( ctx, ctx->opad, 64 );
362 md4_update( ctx, tmpbuf, 16 );
363 md4_finish( ctx, output );
364
365 memset( tmpbuf, 0, sizeof( tmpbuf ) );
366}
367
368/*
Paul Bakker7d3b6612010-03-21 16:23:13 +0000369 * MD4 HMAC context reset
370 */
371void md4_hmac_reset( md4_context *ctx )
372{
373 md4_starts( ctx );
374 md4_update( ctx, ctx->ipad, 64 );
375}
376
377/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000378 * output = HMAC-MD4( hmac key, input buffer )
379 */
Paul Bakker23986e52011-04-24 08:57:21 +0000380void md4_hmac( const unsigned char *key, size_t keylen,
381 const unsigned char *input, size_t ilen,
Paul Bakker5121ce52009-01-03 21:22:43 +0000382 unsigned char output[16] )
383{
384 md4_context ctx;
385
386 md4_hmac_starts( &ctx, key, keylen );
387 md4_hmac_update( &ctx, input, ilen );
388 md4_hmac_finish( &ctx, output );
389
390 memset( &ctx, 0, sizeof( md4_context ) );
391}
392
Paul Bakker40e46942009-01-03 21:51:57 +0000393#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000394
395/*
396 * RFC 1320 test vectors
397 */
398static const char md4_test_str[7][81] =
399{
400 { "" },
401 { "a" },
402 { "abc" },
403 { "message digest" },
404 { "abcdefghijklmnopqrstuvwxyz" },
405 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
406 { "12345678901234567890123456789012345678901234567890123456789012" \
407 "345678901234567890" }
408};
409
410static const unsigned char md4_test_sum[7][16] =
411{
412 { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31,
413 0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 },
414 { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46,
415 0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 },
416 { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52,
417 0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D },
418 { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8,
419 0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B },
420 { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD,
421 0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 },
422 { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35,
423 0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 },
424 { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19,
425 0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 }
426};
427
428/*
429 * Checkup routine
430 */
431int md4_self_test( int verbose )
432{
433 int i;
434 unsigned char md4sum[16];
435
436 for( i = 0; i < 7; i++ )
437 {
438 if( verbose != 0 )
439 printf( " MD4 test #%d: ", i + 1 );
440
441 md4( (unsigned char *) md4_test_str[i],
442 strlen( md4_test_str[i] ), md4sum );
443
444 if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 )
445 {
446 if( verbose != 0 )
447 printf( "failed\n" );
448
449 return( 1 );
450 }
451
452 if( verbose != 0 )
453 printf( "passed\n" );
454 }
455
456 if( verbose != 0 )
457 printf( "\n" );
458
459 return( 0 );
460}
461
462#endif
463
464#endif