blob: 73cfbf87a6177f682c13bb2900e00aa90491abcf [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * RFC 1186/1320 compliant MD4 implementation
3 *
Paul Bakker84f12b72010-07-18 10:13:04 +00004 * Copyright (C) 2006-2010, 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
38#include <string.h>
39#include <stdio.h>
40
41/*
42 * 32-bit integer manipulation macros (little endian)
43 */
44#ifndef GET_ULONG_LE
45#define GET_ULONG_LE(n,b,i) \
46{ \
47 (n) = ( (unsigned long) (b)[(i) ] ) \
48 | ( (unsigned long) (b)[(i) + 1] << 8 ) \
49 | ( (unsigned long) (b)[(i) + 2] << 16 ) \
50 | ( (unsigned long) (b)[(i) + 3] << 24 ); \
51}
52#endif
53
54#ifndef PUT_ULONG_LE
55#define PUT_ULONG_LE(n,b,i) \
56{ \
57 (b)[(i) ] = (unsigned char) ( (n) ); \
58 (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \
59 (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \
60 (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \
61}
62#endif
63
64/*
65 * MD4 context setup
66 */
67void md4_starts( md4_context *ctx )
68{
69 ctx->total[0] = 0;
70 ctx->total[1] = 0;
71
72 ctx->state[0] = 0x67452301;
73 ctx->state[1] = 0xEFCDAB89;
74 ctx->state[2] = 0x98BADCFE;
75 ctx->state[3] = 0x10325476;
76}
77
Paul Bakkerff60ee62010-03-16 21:09:09 +000078static void md4_process( md4_context *ctx, const unsigned char data[64] )
Paul Bakker5121ce52009-01-03 21:22:43 +000079{
80 unsigned long X[16], A, B, C, D;
81
82 GET_ULONG_LE( X[ 0], data, 0 );
83 GET_ULONG_LE( X[ 1], data, 4 );
84 GET_ULONG_LE( X[ 2], data, 8 );
85 GET_ULONG_LE( X[ 3], data, 12 );
86 GET_ULONG_LE( X[ 4], data, 16 );
87 GET_ULONG_LE( X[ 5], data, 20 );
88 GET_ULONG_LE( X[ 6], data, 24 );
89 GET_ULONG_LE( X[ 7], data, 28 );
90 GET_ULONG_LE( X[ 8], data, 32 );
91 GET_ULONG_LE( X[ 9], data, 36 );
92 GET_ULONG_LE( X[10], data, 40 );
93 GET_ULONG_LE( X[11], data, 44 );
94 GET_ULONG_LE( X[12], data, 48 );
95 GET_ULONG_LE( X[13], data, 52 );
96 GET_ULONG_LE( X[14], data, 56 );
97 GET_ULONG_LE( X[15], data, 60 );
98
99#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
100
101 A = ctx->state[0];
102 B = ctx->state[1];
103 C = ctx->state[2];
104 D = ctx->state[3];
105
106#define F(x, y, z) ((x & y) | ((~x) & z))
107#define P(a,b,c,d,x,s) { a += F(b,c,d) + x; a = S(a,s); }
108
109 P( A, B, C, D, X[ 0], 3 );
110 P( D, A, B, C, X[ 1], 7 );
111 P( C, D, A, B, X[ 2], 11 );
112 P( B, C, D, A, X[ 3], 19 );
113 P( A, B, C, D, X[ 4], 3 );
114 P( D, A, B, C, X[ 5], 7 );
115 P( C, D, A, B, X[ 6], 11 );
116 P( B, C, D, A, X[ 7], 19 );
117 P( A, B, C, D, X[ 8], 3 );
118 P( D, A, B, C, X[ 9], 7 );
119 P( C, D, A, B, X[10], 11 );
120 P( B, C, D, A, X[11], 19 );
121 P( A, B, C, D, X[12], 3 );
122 P( D, A, B, C, X[13], 7 );
123 P( C, D, A, B, X[14], 11 );
124 P( B, C, D, A, X[15], 19 );
125
126#undef P
127#undef F
128
129#define F(x,y,z) ((x & y) | (x & z) | (y & z))
130#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x5A827999; a = S(a,s); }
131
132 P( A, B, C, D, X[ 0], 3 );
133 P( D, A, B, C, X[ 4], 5 );
134 P( C, D, A, B, X[ 8], 9 );
135 P( B, C, D, A, X[12], 13 );
136 P( A, B, C, D, X[ 1], 3 );
137 P( D, A, B, C, X[ 5], 5 );
138 P( C, D, A, B, X[ 9], 9 );
139 P( B, C, D, A, X[13], 13 );
140 P( A, B, C, D, X[ 2], 3 );
141 P( D, A, B, C, X[ 6], 5 );
142 P( C, D, A, B, X[10], 9 );
143 P( B, C, D, A, X[14], 13 );
144 P( A, B, C, D, X[ 3], 3 );
145 P( D, A, B, C, X[ 7], 5 );
146 P( C, D, A, B, X[11], 9 );
147 P( B, C, D, A, X[15], 13 );
148
149#undef P
150#undef F
151
152#define F(x,y,z) (x ^ y ^ z)
153#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x6ED9EBA1; a = S(a,s); }
154
155 P( A, B, C, D, X[ 0], 3 );
156 P( D, A, B, C, X[ 8], 9 );
157 P( C, D, A, B, X[ 4], 11 );
158 P( B, C, D, A, X[12], 15 );
159 P( A, B, C, D, X[ 2], 3 );
160 P( D, A, B, C, X[10], 9 );
161 P( C, D, A, B, X[ 6], 11 );
162 P( B, C, D, A, X[14], 15 );
163 P( A, B, C, D, X[ 1], 3 );
164 P( D, A, B, C, X[ 9], 9 );
165 P( C, D, A, B, X[ 5], 11 );
166 P( B, C, D, A, X[13], 15 );
167 P( A, B, C, D, X[ 3], 3 );
168 P( D, A, B, C, X[11], 9 );
169 P( C, D, A, B, X[ 7], 11 );
170 P( B, C, D, A, X[15], 15 );
171
172#undef F
173#undef P
174
175 ctx->state[0] += A;
176 ctx->state[1] += B;
177 ctx->state[2] += C;
178 ctx->state[3] += D;
179}
180
181/*
182 * MD4 process buffer
183 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000184void md4_update( md4_context *ctx, const unsigned char *input, int ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000185{
186 int fill;
187 unsigned long left;
188
189 if( ilen <= 0 )
190 return;
191
192 left = ctx->total[0] & 0x3F;
193 fill = 64 - left;
194
195 ctx->total[0] += ilen;
196 ctx->total[0] &= 0xFFFFFFFF;
197
198 if( ctx->total[0] < (unsigned long) ilen )
199 ctx->total[1]++;
200
201 if( left && ilen >= fill )
202 {
203 memcpy( (void *) (ctx->buffer + left),
204 (void *) input, fill );
205 md4_process( ctx, ctx->buffer );
206 input += fill;
207 ilen -= fill;
208 left = 0;
209 }
210
211 while( ilen >= 64 )
212 {
213 md4_process( ctx, input );
214 input += 64;
215 ilen -= 64;
216 }
217
218 if( ilen > 0 )
219 {
220 memcpy( (void *) (ctx->buffer + left),
221 (void *) input, ilen );
222 }
223}
224
225static const unsigned char md4_padding[64] =
226{
227 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
228 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
229 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
230 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
231};
232
233/*
234 * MD4 final digest
235 */
236void md4_finish( md4_context *ctx, unsigned char output[16] )
237{
238 unsigned long last, padn;
239 unsigned long high, low;
240 unsigned char msglen[8];
241
242 high = ( ctx->total[0] >> 29 )
243 | ( ctx->total[1] << 3 );
244 low = ( ctx->total[0] << 3 );
245
246 PUT_ULONG_LE( low, msglen, 0 );
247 PUT_ULONG_LE( high, msglen, 4 );
248
249 last = ctx->total[0] & 0x3F;
250 padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
251
252 md4_update( ctx, (unsigned char *) md4_padding, padn );
253 md4_update( ctx, msglen, 8 );
254
255 PUT_ULONG_LE( ctx->state[0], output, 0 );
256 PUT_ULONG_LE( ctx->state[1], output, 4 );
257 PUT_ULONG_LE( ctx->state[2], output, 8 );
258 PUT_ULONG_LE( ctx->state[3], output, 12 );
259}
260
261/*
262 * output = MD4( input buffer )
263 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000264void md4( const unsigned char *input, int ilen, unsigned char output[16] )
Paul Bakker5121ce52009-01-03 21:22:43 +0000265{
266 md4_context ctx;
267
268 md4_starts( &ctx );
269 md4_update( &ctx, input, ilen );
270 md4_finish( &ctx, output );
271
272 memset( &ctx, 0, sizeof( md4_context ) );
273}
274
275/*
276 * output = MD4( file contents )
277 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000278int md4_file( const char *path, unsigned char output[16] )
Paul Bakker5121ce52009-01-03 21:22:43 +0000279{
280 FILE *f;
281 size_t n;
282 md4_context ctx;
283 unsigned char buf[1024];
284
285 if( ( f = fopen( path, "rb" ) ) == NULL )
286 return( 1 );
287
288 md4_starts( &ctx );
289
290 while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
291 md4_update( &ctx, buf, (int) n );
292
293 md4_finish( &ctx, output );
294
295 memset( &ctx, 0, sizeof( md4_context ) );
296
297 if( ferror( f ) != 0 )
298 {
299 fclose( f );
300 return( 2 );
301 }
302
303 fclose( f );
304 return( 0 );
305}
306
307/*
308 * MD4 HMAC context setup
309 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000310void md4_hmac_starts( md4_context *ctx, const unsigned char *key, int keylen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000311{
312 int i;
313 unsigned char sum[16];
314
315 if( keylen > 64 )
316 {
317 md4( key, keylen, sum );
318 keylen = 16;
319 key = sum;
320 }
321
322 memset( ctx->ipad, 0x36, 64 );
323 memset( ctx->opad, 0x5C, 64 );
324
325 for( i = 0; i < keylen; i++ )
326 {
327 ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
328 ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
329 }
330
331 md4_starts( ctx );
332 md4_update( ctx, ctx->ipad, 64 );
333
334 memset( sum, 0, sizeof( sum ) );
335}
336
337/*
338 * MD4 HMAC process buffer
339 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000340void md4_hmac_update( md4_context *ctx, const unsigned char *input, int ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000341{
342 md4_update( ctx, input, ilen );
343}
344
345/*
346 * MD4 HMAC final digest
347 */
348void md4_hmac_finish( md4_context *ctx, unsigned char output[16] )
349{
350 unsigned char tmpbuf[16];
351
352 md4_finish( ctx, tmpbuf );
353 md4_starts( ctx );
354 md4_update( ctx, ctx->opad, 64 );
355 md4_update( ctx, tmpbuf, 16 );
356 md4_finish( ctx, output );
357
358 memset( tmpbuf, 0, sizeof( tmpbuf ) );
359}
360
361/*
Paul Bakker7d3b6612010-03-21 16:23:13 +0000362 * MD4 HMAC context reset
363 */
364void md4_hmac_reset( md4_context *ctx )
365{
366 md4_starts( ctx );
367 md4_update( ctx, ctx->ipad, 64 );
368}
369
370/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000371 * output = HMAC-MD4( hmac key, input buffer )
372 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000373void md4_hmac( const unsigned char *key, int keylen,
374 const unsigned char *input, int ilen,
Paul Bakker5121ce52009-01-03 21:22:43 +0000375 unsigned char output[16] )
376{
377 md4_context ctx;
378
379 md4_hmac_starts( &ctx, key, keylen );
380 md4_hmac_update( &ctx, input, ilen );
381 md4_hmac_finish( &ctx, output );
382
383 memset( &ctx, 0, sizeof( md4_context ) );
384}
385
Paul Bakker40e46942009-01-03 21:51:57 +0000386#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000387
388/*
389 * RFC 1320 test vectors
390 */
391static const char md4_test_str[7][81] =
392{
393 { "" },
394 { "a" },
395 { "abc" },
396 { "message digest" },
397 { "abcdefghijklmnopqrstuvwxyz" },
398 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
399 { "12345678901234567890123456789012345678901234567890123456789012" \
400 "345678901234567890" }
401};
402
403static const unsigned char md4_test_sum[7][16] =
404{
405 { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31,
406 0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 },
407 { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46,
408 0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 },
409 { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52,
410 0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D },
411 { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8,
412 0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B },
413 { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD,
414 0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 },
415 { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35,
416 0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 },
417 { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19,
418 0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 }
419};
420
421/*
422 * Checkup routine
423 */
424int md4_self_test( int verbose )
425{
426 int i;
427 unsigned char md4sum[16];
428
429 for( i = 0; i < 7; i++ )
430 {
431 if( verbose != 0 )
432 printf( " MD4 test #%d: ", i + 1 );
433
434 md4( (unsigned char *) md4_test_str[i],
435 strlen( md4_test_str[i] ), md4sum );
436
437 if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 )
438 {
439 if( verbose != 0 )
440 printf( "failed\n" );
441
442 return( 1 );
443 }
444
445 if( verbose != 0 )
446 printf( "passed\n" );
447 }
448
449 if( verbose != 0 )
450 printf( "\n" );
451
452 return( 0 );
453}
454
455#endif
456
457#endif