2
* RFC 1186/1320 compliant MD4 implementation
4
* Copyright (C) 2006-2010, Paul Bakker <polarssl_maintainer at polarssl.org>
7
* This program is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation; either version 2 of the License, or
10
* (at your option) any later version.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
17
* You should have received a copy of the GNU General Public License along
18
* with this program; if not, write to the Free Software Foundation, Inc.,
19
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22
* The MD4 algorithm was designed by Ron Rivest in 1990.
24
* http://www.ietf.org/rfc/rfc1186.txt
25
* http://www.ietf.org/rfc/rfc1320.txt
28
#include "polarssl/config.h"
30
#if defined(POLARSSL_MD4_C)
32
#include "polarssl/md4.h"
38
* 32-bit integer manipulation macros (little endian)
41
#define GET_ULONG_LE(n,b,i) \
43
(n) = ( (unsigned long) (b)[(i) ] ) \
44
| ( (unsigned long) (b)[(i) + 1] << 8 ) \
45
| ( (unsigned long) (b)[(i) + 2] << 16 ) \
46
| ( (unsigned long) (b)[(i) + 3] << 24 ); \
51
#define PUT_ULONG_LE(n,b,i) \
53
(b)[(i) ] = (unsigned char) ( (n) ); \
54
(b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \
55
(b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \
56
(b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \
63
void md4_starts( md4_context *ctx )
68
ctx->state[0] = 0x67452301;
69
ctx->state[1] = 0xEFCDAB89;
70
ctx->state[2] = 0x98BADCFE;
71
ctx->state[3] = 0x10325476;
74
static void md4_process( md4_context *ctx, const unsigned char data[64] )
76
unsigned long X[16], A, B, C, D;
78
GET_ULONG_LE( X[ 0], data, 0 );
79
GET_ULONG_LE( X[ 1], data, 4 );
80
GET_ULONG_LE( X[ 2], data, 8 );
81
GET_ULONG_LE( X[ 3], data, 12 );
82
GET_ULONG_LE( X[ 4], data, 16 );
83
GET_ULONG_LE( X[ 5], data, 20 );
84
GET_ULONG_LE( X[ 6], data, 24 );
85
GET_ULONG_LE( X[ 7], data, 28 );
86
GET_ULONG_LE( X[ 8], data, 32 );
87
GET_ULONG_LE( X[ 9], data, 36 );
88
GET_ULONG_LE( X[10], data, 40 );
89
GET_ULONG_LE( X[11], data, 44 );
90
GET_ULONG_LE( X[12], data, 48 );
91
GET_ULONG_LE( X[13], data, 52 );
92
GET_ULONG_LE( X[14], data, 56 );
93
GET_ULONG_LE( X[15], data, 60 );
95
#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
102
#define F(x, y, z) ((x & y) | ((~x) & z))
103
#define P(a,b,c,d,x,s) { a += F(b,c,d) + x; a = S(a,s); }
105
P( A, B, C, D, X[ 0], 3 );
106
P( D, A, B, C, X[ 1], 7 );
107
P( C, D, A, B, X[ 2], 11 );
108
P( B, C, D, A, X[ 3], 19 );
109
P( A, B, C, D, X[ 4], 3 );
110
P( D, A, B, C, X[ 5], 7 );
111
P( C, D, A, B, X[ 6], 11 );
112
P( B, C, D, A, X[ 7], 19 );
113
P( A, B, C, D, X[ 8], 3 );
114
P( D, A, B, C, X[ 9], 7 );
115
P( C, D, A, B, X[10], 11 );
116
P( B, C, D, A, X[11], 19 );
117
P( A, B, C, D, X[12], 3 );
118
P( D, A, B, C, X[13], 7 );
119
P( C, D, A, B, X[14], 11 );
120
P( B, C, D, A, X[15], 19 );
125
#define F(x,y,z) ((x & y) | (x & z) | (y & z))
126
#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x5A827999; a = S(a,s); }
128
P( A, B, C, D, X[ 0], 3 );
129
P( D, A, B, C, X[ 4], 5 );
130
P( C, D, A, B, X[ 8], 9 );
131
P( B, C, D, A, X[12], 13 );
132
P( A, B, C, D, X[ 1], 3 );
133
P( D, A, B, C, X[ 5], 5 );
134
P( C, D, A, B, X[ 9], 9 );
135
P( B, C, D, A, X[13], 13 );
136
P( A, B, C, D, X[ 2], 3 );
137
P( D, A, B, C, X[ 6], 5 );
138
P( C, D, A, B, X[10], 9 );
139
P( B, C, D, A, X[14], 13 );
140
P( A, B, C, D, X[ 3], 3 );
141
P( D, A, B, C, X[ 7], 5 );
142
P( C, D, A, B, X[11], 9 );
143
P( B, C, D, A, X[15], 13 );
148
#define F(x,y,z) (x ^ y ^ z)
149
#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x6ED9EBA1; a = S(a,s); }
151
P( A, B, C, D, X[ 0], 3 );
152
P( D, A, B, C, X[ 8], 9 );
153
P( C, D, A, B, X[ 4], 11 );
154
P( B, C, D, A, X[12], 15 );
155
P( A, B, C, D, X[ 2], 3 );
156
P( D, A, B, C, X[10], 9 );
157
P( C, D, A, B, X[ 6], 11 );
158
P( B, C, D, A, X[14], 15 );
159
P( A, B, C, D, X[ 1], 3 );
160
P( D, A, B, C, X[ 9], 9 );
161
P( C, D, A, B, X[ 5], 11 );
162
P( B, C, D, A, X[13], 15 );
163
P( A, B, C, D, X[ 3], 3 );
164
P( D, A, B, C, X[11], 9 );
165
P( C, D, A, B, X[ 7], 11 );
166
P( B, C, D, A, X[15], 15 );
180
void md4_update( md4_context *ctx, const unsigned char *input, int ilen )
188
left = ctx->total[0] & 0x3F;
191
ctx->total[0] += ilen;
192
ctx->total[0] &= 0xFFFFFFFF;
194
if( ctx->total[0] < (unsigned long) ilen )
197
if( left && ilen >= fill )
199
memcpy( (void *) (ctx->buffer + left),
200
(void *) input, fill );
201
md4_process( ctx, ctx->buffer );
209
md4_process( ctx, input );
216
memcpy( (void *) (ctx->buffer + left),
217
(void *) input, ilen );
221
static const unsigned char md4_padding[64] =
223
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
224
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
225
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
226
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
232
void md4_finish( md4_context *ctx, unsigned char output[16] )
234
unsigned long last, padn;
235
unsigned long high, low;
236
unsigned char msglen[8];
238
high = ( ctx->total[0] >> 29 )
239
| ( ctx->total[1] << 3 );
240
low = ( ctx->total[0] << 3 );
242
PUT_ULONG_LE( low, msglen, 0 );
243
PUT_ULONG_LE( high, msglen, 4 );
245
last = ctx->total[0] & 0x3F;
246
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
248
md4_update( ctx, (unsigned char *) md4_padding, padn );
249
md4_update( ctx, msglen, 8 );
251
PUT_ULONG_LE( ctx->state[0], output, 0 );
252
PUT_ULONG_LE( ctx->state[1], output, 4 );
253
PUT_ULONG_LE( ctx->state[2], output, 8 );
254
PUT_ULONG_LE( ctx->state[3], output, 12 );
258
* output = MD4( input buffer )
260
void md4( const unsigned char *input, int ilen, unsigned char output[16] )
265
md4_update( &ctx, input, ilen );
266
md4_finish( &ctx, output );
268
memset( &ctx, 0, sizeof( md4_context ) );
272
* output = MD4( file contents )
274
int md4_file( const char *path, unsigned char output[16] )
279
unsigned char buf[1024];
281
if( ( f = fopen( path, "rb" ) ) == NULL )
286
while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
287
md4_update( &ctx, buf, (int) n );
289
md4_finish( &ctx, output );
291
memset( &ctx, 0, sizeof( md4_context ) );
293
if( ferror( f ) != 0 )
304
* MD4 HMAC context setup
306
void md4_hmac_starts( md4_context *ctx, const unsigned char *key, int keylen )
309
unsigned char sum[16];
313
md4( key, keylen, sum );
318
memset( ctx->ipad, 0x36, 64 );
319
memset( ctx->opad, 0x5C, 64 );
321
for( i = 0; i < keylen; i++ )
323
ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
324
ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
328
md4_update( ctx, ctx->ipad, 64 );
330
memset( sum, 0, sizeof( sum ) );
334
* MD4 HMAC process buffer
336
void md4_hmac_update( md4_context *ctx, const unsigned char *input, int ilen )
338
md4_update( ctx, input, ilen );
342
* MD4 HMAC final digest
344
void md4_hmac_finish( md4_context *ctx, unsigned char output[16] )
346
unsigned char tmpbuf[16];
348
md4_finish( ctx, tmpbuf );
350
md4_update( ctx, ctx->opad, 64 );
351
md4_update( ctx, tmpbuf, 16 );
352
md4_finish( ctx, output );
354
memset( tmpbuf, 0, sizeof( tmpbuf ) );
358
* MD4 HMAC context reset
360
void md4_hmac_reset( md4_context *ctx )
363
md4_update( ctx, ctx->ipad, 64 );
367
* output = HMAC-MD4( hmac key, input buffer )
369
void md4_hmac( const unsigned char *key, int keylen,
370
const unsigned char *input, int ilen,
371
unsigned char output[16] )
375
md4_hmac_starts( &ctx, key, keylen );
376
md4_hmac_update( &ctx, input, ilen );
377
md4_hmac_finish( &ctx, output );
379
memset( &ctx, 0, sizeof( md4_context ) );
382
#if defined(POLARSSL_SELF_TEST)
385
* RFC 1320 test vectors
387
static const char md4_test_str[7][81] =
392
{ "message digest" },
393
{ "abcdefghijklmnopqrstuvwxyz" },
394
{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
395
{ "12345678901234567890123456789012345678901234567890123456789012" \
396
"345678901234567890" }
399
static const unsigned char md4_test_sum[7][16] =
401
{ 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31,
402
0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 },
403
{ 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46,
404
0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 },
405
{ 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52,
406
0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D },
407
{ 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8,
408
0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B },
409
{ 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD,
410
0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 },
411
{ 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35,
412
0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 },
413
{ 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19,
414
0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 }
420
int md4_self_test( int verbose )
423
unsigned char md4sum[16];
425
for( i = 0; i < 7; i++ )
428
printf( " MD4 test #%d: ", i + 1 );
430
md4( (unsigned char *) md4_test_str[i],
431
strlen( md4_test_str[i] ), md4sum );
433
if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 )
436
printf( "failed\n" );
442
printf( "passed\n" );