2 * RFC 1186/1320 compliant MD4 implementation
4 * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
6 * This file is part of mbed TLS (https://tls.mbed.org)
8 * 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.
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.
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.
23 * The MD4 algorithm was designed by Ron Rivest in 1990.
25 * http://www.ietf.org/rfc/rfc1186.txt
26 * http://www.ietf.org/rfc/rfc1320.txt
29 #if !defined(POLARSSL_CONFIG_FILE)
30 #include "polarssl/config.h"
32 #include POLARSSL_CONFIG_FILE
35 #if defined(POLARSSL_MD4_C)
37 #include "polarssl/md4.h"
41 #if defined(POLARSSL_FS_IO)
45 #if defined(POLARSSL_SELF_TEST)
46 #if defined(POLARSSL_PLATFORM_C)
47 #include "polarssl/platform.h"
50 #define polarssl_printf printf
51 #endif /* POLARSSL_PLATFORM_C */
52 #endif /* POLARSSL_SELF_TEST */
54 /* Implementation that should never be optimized out by the compiler */
55 static void polarssl_zeroize( void *v
, size_t n
) {
56 volatile unsigned char *p
= v
; while( n
-- ) *p
++ = 0;
59 #if !defined(POLARSSL_MD4_ALT)
62 * 32-bit integer manipulation macros (little endian)
65 #define GET_UINT32_LE(n,b,i) \
67 (n) = ( (uint32_t) (b)[(i) ] ) \
68 | ( (uint32_t) (b)[(i) + 1] << 8 ) \
69 | ( (uint32_t) (b)[(i) + 2] << 16 ) \
70 | ( (uint32_t) (b)[(i) + 3] << 24 ); \
75 #define PUT_UINT32_LE(n,b,i) \
77 (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \
78 (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \
79 (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \
80 (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \
84 void md4_init( md4_context
*ctx
)
86 memset( ctx
, 0, sizeof( md4_context
) );
89 void md4_free( md4_context
*ctx
)
94 polarssl_zeroize( ctx
, sizeof( md4_context
) );
100 void md4_starts( md4_context
*ctx
)
105 ctx
->state
[0] = 0x67452301;
106 ctx
->state
[1] = 0xEFCDAB89;
107 ctx
->state
[2] = 0x98BADCFE;
108 ctx
->state
[3] = 0x10325476;
111 void md4_process( md4_context
*ctx
, const unsigned char data
[64] )
113 uint32_t X
[16], A
, B
, C
, D
;
115 GET_UINT32_LE( X
[ 0], data
, 0 );
116 GET_UINT32_LE( X
[ 1], data
, 4 );
117 GET_UINT32_LE( X
[ 2], data
, 8 );
118 GET_UINT32_LE( X
[ 3], data
, 12 );
119 GET_UINT32_LE( X
[ 4], data
, 16 );
120 GET_UINT32_LE( X
[ 5], data
, 20 );
121 GET_UINT32_LE( X
[ 6], data
, 24 );
122 GET_UINT32_LE( X
[ 7], data
, 28 );
123 GET_UINT32_LE( X
[ 8], data
, 32 );
124 GET_UINT32_LE( X
[ 9], data
, 36 );
125 GET_UINT32_LE( X
[10], data
, 40 );
126 GET_UINT32_LE( X
[11], data
, 44 );
127 GET_UINT32_LE( X
[12], data
, 48 );
128 GET_UINT32_LE( X
[13], data
, 52 );
129 GET_UINT32_LE( X
[14], data
, 56 );
130 GET_UINT32_LE( X
[15], data
, 60 );
132 #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
139 #define F(x, y, z) ((x & y) | ((~x) & z))
140 #define P(a,b,c,d,x,s) { a += F(b,c,d) + x; a = S(a,s); }
142 P( A
, B
, C
, D
, X
[ 0], 3 );
143 P( D
, A
, B
, C
, X
[ 1], 7 );
144 P( C
, D
, A
, B
, X
[ 2], 11 );
145 P( B
, C
, D
, A
, X
[ 3], 19 );
146 P( A
, B
, C
, D
, X
[ 4], 3 );
147 P( D
, A
, B
, C
, X
[ 5], 7 );
148 P( C
, D
, A
, B
, X
[ 6], 11 );
149 P( B
, C
, D
, A
, X
[ 7], 19 );
150 P( A
, B
, C
, D
, X
[ 8], 3 );
151 P( D
, A
, B
, C
, X
[ 9], 7 );
152 P( C
, D
, A
, B
, X
[10], 11 );
153 P( B
, C
, D
, A
, X
[11], 19 );
154 P( A
, B
, C
, D
, X
[12], 3 );
155 P( D
, A
, B
, C
, X
[13], 7 );
156 P( C
, D
, A
, B
, X
[14], 11 );
157 P( B
, C
, D
, A
, X
[15], 19 );
162 #define F(x,y,z) ((x & y) | (x & z) | (y & z))
163 #define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x5A827999; a = S(a,s); }
165 P( A
, B
, C
, D
, X
[ 0], 3 );
166 P( D
, A
, B
, C
, X
[ 4], 5 );
167 P( C
, D
, A
, B
, X
[ 8], 9 );
168 P( B
, C
, D
, A
, X
[12], 13 );
169 P( A
, B
, C
, D
, X
[ 1], 3 );
170 P( D
, A
, B
, C
, X
[ 5], 5 );
171 P( C
, D
, A
, B
, X
[ 9], 9 );
172 P( B
, C
, D
, A
, X
[13], 13 );
173 P( A
, B
, C
, D
, X
[ 2], 3 );
174 P( D
, A
, B
, C
, X
[ 6], 5 );
175 P( C
, D
, A
, B
, X
[10], 9 );
176 P( B
, C
, D
, A
, X
[14], 13 );
177 P( A
, B
, C
, D
, X
[ 3], 3 );
178 P( D
, A
, B
, C
, X
[ 7], 5 );
179 P( C
, D
, A
, B
, X
[11], 9 );
180 P( B
, C
, D
, A
, X
[15], 13 );
185 #define F(x,y,z) (x ^ y ^ z)
186 #define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x6ED9EBA1; a = S(a,s); }
188 P( A
, B
, C
, D
, X
[ 0], 3 );
189 P( D
, A
, B
, C
, X
[ 8], 9 );
190 P( C
, D
, A
, B
, X
[ 4], 11 );
191 P( B
, C
, D
, A
, X
[12], 15 );
192 P( A
, B
, C
, D
, X
[ 2], 3 );
193 P( D
, A
, B
, C
, X
[10], 9 );
194 P( C
, D
, A
, B
, X
[ 6], 11 );
195 P( B
, C
, D
, A
, X
[14], 15 );
196 P( A
, B
, C
, D
, X
[ 1], 3 );
197 P( D
, A
, B
, C
, X
[ 9], 9 );
198 P( C
, D
, A
, B
, X
[ 5], 11 );
199 P( B
, C
, D
, A
, X
[13], 15 );
200 P( A
, B
, C
, D
, X
[ 3], 3 );
201 P( D
, A
, B
, C
, X
[11], 9 );
202 P( C
, D
, A
, B
, X
[ 7], 11 );
203 P( B
, C
, D
, A
, X
[15], 15 );
217 void md4_update( md4_context
*ctx
, const unsigned char *input
, size_t ilen
)
225 left
= ctx
->total
[0] & 0x3F;
228 ctx
->total
[0] += (uint32_t) ilen
;
229 ctx
->total
[0] &= 0xFFFFFFFF;
231 if( ctx
->total
[0] < (uint32_t) ilen
)
234 if( left
&& ilen
>= fill
)
236 memcpy( (void *) (ctx
->buffer
+ left
),
237 (void *) input
, fill
);
238 md4_process( ctx
, ctx
->buffer
);
246 md4_process( ctx
, input
);
253 memcpy( (void *) (ctx
->buffer
+ left
),
254 (void *) input
, ilen
);
258 static const unsigned char md4_padding
[64] =
260 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
261 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
262 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
263 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
269 void md4_finish( md4_context
*ctx
, unsigned char output
[16] )
273 unsigned char msglen
[8];
275 high
= ( ctx
->total
[0] >> 29 )
276 | ( ctx
->total
[1] << 3 );
277 low
= ( ctx
->total
[0] << 3 );
279 PUT_UINT32_LE( low
, msglen
, 0 );
280 PUT_UINT32_LE( high
, msglen
, 4 );
282 last
= ctx
->total
[0] & 0x3F;
283 padn
= ( last
< 56 ) ? ( 56 - last
) : ( 120 - last
);
285 md4_update( ctx
, (unsigned char *) md4_padding
, padn
);
286 md4_update( ctx
, msglen
, 8 );
288 PUT_UINT32_LE( ctx
->state
[0], output
, 0 );
289 PUT_UINT32_LE( ctx
->state
[1], output
, 4 );
290 PUT_UINT32_LE( ctx
->state
[2], output
, 8 );
291 PUT_UINT32_LE( ctx
->state
[3], output
, 12 );
294 #endif /* !POLARSSL_MD4_ALT */
297 * output = MD4( input buffer )
299 void md4( const unsigned char *input
, size_t ilen
, unsigned char output
[16] )
305 md4_update( &ctx
, input
, ilen
);
306 md4_finish( &ctx
, output
);
310 #if defined(POLARSSL_FS_IO)
312 * output = MD4( file contents )
314 int md4_file( const char *path
, unsigned char output
[16] )
319 unsigned char buf
[1024];
321 if( ( f
= fopen( path
, "rb" ) ) == NULL
)
322 return( POLARSSL_ERR_MD4_FILE_IO_ERROR
);
327 while( ( n
= fread( buf
, 1, sizeof( buf
), f
) ) > 0 )
328 md4_update( &ctx
, buf
, n
);
330 md4_finish( &ctx
, output
);
333 if( ferror( f
) != 0 )
336 return( POLARSSL_ERR_MD4_FILE_IO_ERROR
);
342 #endif /* POLARSSL_FS_IO */
345 * MD4 HMAC context setup
347 void md4_hmac_starts( md4_context
*ctx
, const unsigned char *key
,
351 unsigned char sum
[16];
355 md4( key
, keylen
, sum
);
360 memset( ctx
->ipad
, 0x36, 64 );
361 memset( ctx
->opad
, 0x5C, 64 );
363 for( i
= 0; i
< keylen
; i
++ )
365 ctx
->ipad
[i
] = (unsigned char)( ctx
->ipad
[i
] ^ key
[i
] );
366 ctx
->opad
[i
] = (unsigned char)( ctx
->opad
[i
] ^ key
[i
] );
370 md4_update( ctx
, ctx
->ipad
, 64 );
372 polarssl_zeroize( sum
, sizeof( sum
) );
376 * MD4 HMAC process buffer
378 void md4_hmac_update( md4_context
*ctx
, const unsigned char *input
,
381 md4_update( ctx
, input
, ilen
);
385 * MD4 HMAC final digest
387 void md4_hmac_finish( md4_context
*ctx
, unsigned char output
[16] )
389 unsigned char tmpbuf
[16];
391 md4_finish( ctx
, tmpbuf
);
393 md4_update( ctx
, ctx
->opad
, 64 );
394 md4_update( ctx
, tmpbuf
, 16 );
395 md4_finish( ctx
, output
);
397 polarssl_zeroize( tmpbuf
, sizeof( tmpbuf
) );
401 * MD4 HMAC context reset
403 void md4_hmac_reset( md4_context
*ctx
)
406 md4_update( ctx
, ctx
->ipad
, 64 );
410 * output = HMAC-MD4( hmac key, input buffer )
412 void md4_hmac( const unsigned char *key
, size_t keylen
,
413 const unsigned char *input
, size_t ilen
,
414 unsigned char output
[16] )
419 md4_hmac_starts( &ctx
, key
, keylen
);
420 md4_hmac_update( &ctx
, input
, ilen
);
421 md4_hmac_finish( &ctx
, output
);
425 #if defined(POLARSSL_SELF_TEST)
428 * RFC 1320 test vectors
430 static const char md4_test_str
[7][81] =
435 { "message digest" },
436 { "abcdefghijklmnopqrstuvwxyz" },
437 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
438 { "12345678901234567890123456789012345678901234567890123456789012" \
439 "345678901234567890" }
442 static const unsigned char md4_test_sum
[7][16] =
444 { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31,
445 0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 },
446 { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46,
447 0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 },
448 { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52,
449 0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D },
450 { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8,
451 0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B },
452 { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD,
453 0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 },
454 { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35,
455 0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 },
456 { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19,
457 0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 }
463 int md4_self_test( int verbose
)
466 unsigned char md4sum
[16];
468 for( i
= 0; i
< 7; i
++ )
471 polarssl_printf( " MD4 test #%d: ", i
+ 1 );
473 md4( (unsigned char *) md4_test_str
[i
],
474 strlen( md4_test_str
[i
] ), md4sum
);
476 if( memcmp( md4sum
, md4_test_sum
[i
], 16 ) != 0 )
479 polarssl_printf( "failed\n" );
485 polarssl_printf( "passed\n" );
489 polarssl_printf( "\n" );
494 #endif /* POLARSSL_SELF_TEST */
496 #endif /* POLARSSL_MD4_C */