blob: f3d80d0787cf920c38a485a2d3873e36e2525c49 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * RFC 1186/1320 compliant MD4 implementation
3 *
Paul Bakker83ded912010-03-21 17:46:26 +00004 * Copyright (C) 2006-2010, Paul Bakker <polarssl_maintainer at polarssl.org>
Paul Bakker77b385e2009-07-28 17:23:11 +00005 * All rights reserved.
Paul Bakkere0ccd0a2009-01-04 16:27:10 +00006 *
Paul Bakker5121ce52009-01-03 21:22:43 +00007 * 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.
11 *
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.
16 *
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.
20 */
21/*
22 * The MD4 algorithm was designed by Ron Rivest in 1990.
23 *
24 * http://www.ietf.org/rfc/rfc1186.txt
25 * http://www.ietf.org/rfc/rfc1320.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_MD4_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000031
Paul Bakker40e46942009-01-03 21:51:57 +000032#include "polarssl/md4.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000033
34#include <string.h>
35#include <stdio.h>
36
37/*
38 * 32-bit integer manipulation macros (little endian)
39 */
40#ifndef GET_ULONG_LE
41#define GET_ULONG_LE(n,b,i) \
42{ \
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 ); \
47}
48#endif
49
50#ifndef PUT_ULONG_LE
51#define PUT_ULONG_LE(n,b,i) \
52{ \
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 ); \
57}
58#endif
59
60/*
61 * MD4 context setup
62 */
63void md4_starts( md4_context *ctx )
64{
65 ctx->total[0] = 0;
66 ctx->total[1] = 0;
67
68 ctx->state[0] = 0x67452301;
69 ctx->state[1] = 0xEFCDAB89;
70 ctx->state[2] = 0x98BADCFE;
71 ctx->state[3] = 0x10325476;
72}
73
Paul Bakkerff60ee62010-03-16 21:09:09 +000074static void md4_process( md4_context *ctx, const unsigned char data[64] )
Paul Bakker5121ce52009-01-03 21:22:43 +000075{
76 unsigned long X[16], A, B, C, D;
77
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 );
94
95#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
96
97 A = ctx->state[0];
98 B = ctx->state[1];
99 C = ctx->state[2];
100 D = ctx->state[3];
101
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); }
104
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 );
121
122#undef P
123#undef F
124
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); }
127
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 );
144
145#undef P
146#undef F
147
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); }
150
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 );
167
168#undef F
169#undef P
170
171 ctx->state[0] += A;
172 ctx->state[1] += B;
173 ctx->state[2] += C;
174 ctx->state[3] += D;
175}
176
177/*
178 * MD4 process buffer
179 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000180void md4_update( md4_context *ctx, const unsigned char *input, int ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000181{
182 int fill;
183 unsigned long left;
184
185 if( ilen <= 0 )
186 return;
187
188 left = ctx->total[0] & 0x3F;
189 fill = 64 - left;
190
191 ctx->total[0] += ilen;
192 ctx->total[0] &= 0xFFFFFFFF;
193
194 if( ctx->total[0] < (unsigned long) ilen )
195 ctx->total[1]++;
196
197 if( left && ilen >= fill )
198 {
199 memcpy( (void *) (ctx->buffer + left),
200 (void *) input, fill );
201 md4_process( ctx, ctx->buffer );
202 input += fill;
203 ilen -= fill;
204 left = 0;
205 }
206
207 while( ilen >= 64 )
208 {
209 md4_process( ctx, input );
210 input += 64;
211 ilen -= 64;
212 }
213
214 if( ilen > 0 )
215 {
216 memcpy( (void *) (ctx->buffer + left),
217 (void *) input, ilen );
218 }
219}
220
221static const unsigned char md4_padding[64] =
222{
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
227};
228
229/*
230 * MD4 final digest
231 */
232void md4_finish( md4_context *ctx, unsigned char output[16] )
233{
234 unsigned long last, padn;
235 unsigned long high, low;
236 unsigned char msglen[8];
237
238 high = ( ctx->total[0] >> 29 )
239 | ( ctx->total[1] << 3 );
240 low = ( ctx->total[0] << 3 );
241
242 PUT_ULONG_LE( low, msglen, 0 );
243 PUT_ULONG_LE( high, msglen, 4 );
244
245 last = ctx->total[0] & 0x3F;
246 padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
247
248 md4_update( ctx, (unsigned char *) md4_padding, padn );
249 md4_update( ctx, msglen, 8 );
250
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 );
255}
256
257/*
258 * output = MD4( input buffer )
259 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000260void md4( const unsigned char *input, int ilen, unsigned char output[16] )
Paul Bakker5121ce52009-01-03 21:22:43 +0000261{
262 md4_context ctx;
263
264 md4_starts( &ctx );
265 md4_update( &ctx, input, ilen );
266 md4_finish( &ctx, output );
267
268 memset( &ctx, 0, sizeof( md4_context ) );
269}
270
271/*
272 * output = MD4( file contents )
273 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000274int md4_file( const char *path, unsigned char output[16] )
Paul Bakker5121ce52009-01-03 21:22:43 +0000275{
276 FILE *f;
277 size_t n;
278 md4_context ctx;
279 unsigned char buf[1024];
280
281 if( ( f = fopen( path, "rb" ) ) == NULL )
282 return( 1 );
283
284 md4_starts( &ctx );
285
286 while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
287 md4_update( &ctx, buf, (int) n );
288
289 md4_finish( &ctx, output );
290
291 memset( &ctx, 0, sizeof( md4_context ) );
292
293 if( ferror( f ) != 0 )
294 {
295 fclose( f );
296 return( 2 );
297 }
298
299 fclose( f );
300 return( 0 );
301}
302
303/*
304 * MD4 HMAC context setup
305 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000306void md4_hmac_starts( md4_context *ctx, const unsigned char *key, int keylen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000307{
308 int i;
309 unsigned char sum[16];
310
311 if( keylen > 64 )
312 {
313 md4( key, keylen, sum );
314 keylen = 16;
315 key = sum;
316 }
317
318 memset( ctx->ipad, 0x36, 64 );
319 memset( ctx->opad, 0x5C, 64 );
320
321 for( i = 0; i < keylen; i++ )
322 {
323 ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
324 ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
325 }
326
327 md4_starts( ctx );
328 md4_update( ctx, ctx->ipad, 64 );
329
330 memset( sum, 0, sizeof( sum ) );
331}
332
333/*
334 * MD4 HMAC process buffer
335 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000336void md4_hmac_update( md4_context *ctx, const unsigned char *input, int ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000337{
338 md4_update( ctx, input, ilen );
339}
340
341/*
342 * MD4 HMAC final digest
343 */
344void md4_hmac_finish( md4_context *ctx, unsigned char output[16] )
345{
346 unsigned char tmpbuf[16];
347
348 md4_finish( ctx, tmpbuf );
349 md4_starts( ctx );
350 md4_update( ctx, ctx->opad, 64 );
351 md4_update( ctx, tmpbuf, 16 );
352 md4_finish( ctx, output );
353
354 memset( tmpbuf, 0, sizeof( tmpbuf ) );
355}
356
357/*
Paul Bakker7d3b6612010-03-21 16:23:13 +0000358 * MD4 HMAC context reset
359 */
360void md4_hmac_reset( md4_context *ctx )
361{
362 md4_starts( ctx );
363 md4_update( ctx, ctx->ipad, 64 );
364}
365
366/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000367 * output = HMAC-MD4( hmac key, input buffer )
368 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000369void md4_hmac( const unsigned char *key, int keylen,
370 const unsigned char *input, int ilen,
Paul Bakker5121ce52009-01-03 21:22:43 +0000371 unsigned char output[16] )
372{
373 md4_context ctx;
374
375 md4_hmac_starts( &ctx, key, keylen );
376 md4_hmac_update( &ctx, input, ilen );
377 md4_hmac_finish( &ctx, output );
378
379 memset( &ctx, 0, sizeof( md4_context ) );
380}
381
Paul Bakker40e46942009-01-03 21:51:57 +0000382#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000383
384/*
385 * RFC 1320 test vectors
386 */
387static const char md4_test_str[7][81] =
388{
389 { "" },
390 { "a" },
391 { "abc" },
392 { "message digest" },
393 { "abcdefghijklmnopqrstuvwxyz" },
394 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
395 { "12345678901234567890123456789012345678901234567890123456789012" \
396 "345678901234567890" }
397};
398
399static const unsigned char md4_test_sum[7][16] =
400{
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 }
415};
416
417/*
418 * Checkup routine
419 */
420int md4_self_test( int verbose )
421{
422 int i;
423 unsigned char md4sum[16];
424
425 for( i = 0; i < 7; i++ )
426 {
427 if( verbose != 0 )
428 printf( " MD4 test #%d: ", i + 1 );
429
430 md4( (unsigned char *) md4_test_str[i],
431 strlen( md4_test_str[i] ), md4sum );
432
433 if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 )
434 {
435 if( verbose != 0 )
436 printf( "failed\n" );
437
438 return( 1 );
439 }
440
441 if( verbose != 0 )
442 printf( "passed\n" );
443 }
444
445 if( verbose != 0 )
446 printf( "\n" );
447
448 return( 0 );
449}
450
451#endif
452
453#endif