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