blob: 2de259d98503802334d45464f32bff43e535fc72 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * RFC 1186/1320 compliant MD4 implementation
3 *
Manuel Pégourié-Gonnarda658a402015-01-23 09:45:19 +00004 * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
Paul Bakkerb96f1542010-07-18 20:36:00 +00005 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +00006 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakkerb96f1542010-07-18 20:36:00 +00007 *
Paul Bakker5121ce52009-01-03 21:22:43 +00008 * 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.
12 *
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.
17 *
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.
21 */
22/*
23 * The MD4 algorithm was designed by Ron Rivest in 1990.
24 *
25 * http://www.ietf.org/rfc/rfc1186.txt
26 * http://www.ietf.org/rfc/rfc1320.txt
27 */
28
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020029#if !defined(POLARSSL_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000030#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020031#else
32#include POLARSSL_CONFIG_FILE
33#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000034
Paul Bakker40e46942009-01-03 21:51:57 +000035#if defined(POLARSSL_MD4_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000036
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000037#include "mbedtls/md4.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000038
Rich Evans00ab4702015-02-06 13:43:58 +000039#include <string.h>
40
41#if defined(POLARSSL_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +000042#include <stdio.h>
Paul Bakker335db3f2011-04-25 15:28:35 +000043#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000044
Rich Evans00ab4702015-02-06 13:43:58 +000045#if defined(POLARSSL_SELF_TEST)
Paul Bakker7dc4c442014-02-01 22:50:26 +010046#if defined(POLARSSL_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000047#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010048#else
Rich Evans00ab4702015-02-06 13:43:58 +000049#include <stdio.h>
Paul Bakker7dc4c442014-02-01 22:50:26 +010050#define polarssl_printf printf
Rich Evans00ab4702015-02-06 13:43:58 +000051#endif /* POLARSSL_PLATFORM_C */
52#endif /* POLARSSL_SELF_TEST */
Paul Bakker7dc4c442014-02-01 22:50:26 +010053
Paul Bakker34617722014-06-13 17:20:13 +020054/* Implementation that should never be optimized out by the compiler */
55static void polarssl_zeroize( void *v, size_t n ) {
56 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
57}
58
Paul Bakker90995b52013-06-24 19:20:35 +020059#if !defined(POLARSSL_MD4_ALT)
60
Paul Bakker5121ce52009-01-03 21:22:43 +000061/*
62 * 32-bit integer manipulation macros (little endian)
63 */
Paul Bakker5c2364c2012-10-01 14:41:15 +000064#ifndef GET_UINT32_LE
65#define GET_UINT32_LE(n,b,i) \
Paul Bakker5121ce52009-01-03 21:22:43 +000066{ \
Paul Bakker5c2364c2012-10-01 14:41:15 +000067 (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 ); \
Paul Bakker5121ce52009-01-03 21:22:43 +000071}
72#endif
73
Paul Bakker5c2364c2012-10-01 14:41:15 +000074#ifndef PUT_UINT32_LE
Manuel Pégourié-Gonnardceedb822015-01-23 15:02:43 +000075#define PUT_UINT32_LE(n,b,i) \
76{ \
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 ); \
Paul Bakker5121ce52009-01-03 21:22:43 +000081}
82#endif
83
Paul Bakker5b4af392014-06-26 12:09:34 +020084void md4_init( md4_context *ctx )
85{
86 memset( ctx, 0, sizeof( md4_context ) );
87}
88
89void md4_free( md4_context *ctx )
90{
91 if( ctx == NULL )
92 return;
93
94 polarssl_zeroize( ctx, sizeof( md4_context ) );
95}
96
Paul Bakker5121ce52009-01-03 21:22:43 +000097/*
98 * MD4 context setup
99 */
100void md4_starts( md4_context *ctx )
101{
102 ctx->total[0] = 0;
103 ctx->total[1] = 0;
104
105 ctx->state[0] = 0x67452301;
106 ctx->state[1] = 0xEFCDAB89;
107 ctx->state[2] = 0x98BADCFE;
108 ctx->state[3] = 0x10325476;
109}
110
Manuel Pégourié-Gonnard427b6722015-03-31 18:32:50 +0200111#if !defined(POLARSSL_MD4_PROCESS_ALT)
Paul Bakker1bd3ae82013-03-13 10:26:44 +0100112void md4_process( md4_context *ctx, const unsigned char data[64] )
Paul Bakker5121ce52009-01-03 21:22:43 +0000113{
Paul Bakker5c2364c2012-10-01 14:41:15 +0000114 uint32_t X[16], A, B, C, D;
Paul Bakker5121ce52009-01-03 21:22:43 +0000115
Paul Bakker5c2364c2012-10-01 14:41:15 +0000116 GET_UINT32_LE( X[ 0], data, 0 );
117 GET_UINT32_LE( X[ 1], data, 4 );
118 GET_UINT32_LE( X[ 2], data, 8 );
119 GET_UINT32_LE( X[ 3], data, 12 );
120 GET_UINT32_LE( X[ 4], data, 16 );
121 GET_UINT32_LE( X[ 5], data, 20 );
122 GET_UINT32_LE( X[ 6], data, 24 );
123 GET_UINT32_LE( X[ 7], data, 28 );
124 GET_UINT32_LE( X[ 8], data, 32 );
125 GET_UINT32_LE( X[ 9], data, 36 );
126 GET_UINT32_LE( X[10], data, 40 );
127 GET_UINT32_LE( X[11], data, 44 );
128 GET_UINT32_LE( X[12], data, 48 );
129 GET_UINT32_LE( X[13], data, 52 );
130 GET_UINT32_LE( X[14], data, 56 );
131 GET_UINT32_LE( X[15], data, 60 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000132
133#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
134
135 A = ctx->state[0];
136 B = ctx->state[1];
137 C = ctx->state[2];
138 D = ctx->state[3];
139
140#define F(x, y, z) ((x & y) | ((~x) & z))
141#define P(a,b,c,d,x,s) { a += F(b,c,d) + x; a = S(a,s); }
142
143 P( A, B, C, D, X[ 0], 3 );
144 P( D, A, B, C, X[ 1], 7 );
145 P( C, D, A, B, X[ 2], 11 );
146 P( B, C, D, A, X[ 3], 19 );
147 P( A, B, C, D, X[ 4], 3 );
148 P( D, A, B, C, X[ 5], 7 );
149 P( C, D, A, B, X[ 6], 11 );
150 P( B, C, D, A, X[ 7], 19 );
151 P( A, B, C, D, X[ 8], 3 );
152 P( D, A, B, C, X[ 9], 7 );
153 P( C, D, A, B, X[10], 11 );
154 P( B, C, D, A, X[11], 19 );
155 P( A, B, C, D, X[12], 3 );
156 P( D, A, B, C, X[13], 7 );
157 P( C, D, A, B, X[14], 11 );
158 P( B, C, D, A, X[15], 19 );
159
160#undef P
161#undef F
162
163#define F(x,y,z) ((x & y) | (x & z) | (y & z))
164#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x5A827999; a = S(a,s); }
165
166 P( A, B, C, D, X[ 0], 3 );
167 P( D, A, B, C, X[ 4], 5 );
168 P( C, D, A, B, X[ 8], 9 );
169 P( B, C, D, A, X[12], 13 );
170 P( A, B, C, D, X[ 1], 3 );
171 P( D, A, B, C, X[ 5], 5 );
172 P( C, D, A, B, X[ 9], 9 );
173 P( B, C, D, A, X[13], 13 );
174 P( A, B, C, D, X[ 2], 3 );
175 P( D, A, B, C, X[ 6], 5 );
176 P( C, D, A, B, X[10], 9 );
177 P( B, C, D, A, X[14], 13 );
178 P( A, B, C, D, X[ 3], 3 );
179 P( D, A, B, C, X[ 7], 5 );
180 P( C, D, A, B, X[11], 9 );
181 P( B, C, D, A, X[15], 13 );
182
183#undef P
184#undef F
185
186#define F(x,y,z) (x ^ y ^ z)
187#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x6ED9EBA1; a = S(a,s); }
188
189 P( A, B, C, D, X[ 0], 3 );
190 P( D, A, B, C, X[ 8], 9 );
191 P( C, D, A, B, X[ 4], 11 );
192 P( B, C, D, A, X[12], 15 );
193 P( A, B, C, D, X[ 2], 3 );
194 P( D, A, B, C, X[10], 9 );
195 P( C, D, A, B, X[ 6], 11 );
196 P( B, C, D, A, X[14], 15 );
197 P( A, B, C, D, X[ 1], 3 );
198 P( D, A, B, C, X[ 9], 9 );
199 P( C, D, A, B, X[ 5], 11 );
200 P( B, C, D, A, X[13], 15 );
201 P( A, B, C, D, X[ 3], 3 );
202 P( D, A, B, C, X[11], 9 );
203 P( C, D, A, B, X[ 7], 11 );
204 P( B, C, D, A, X[15], 15 );
205
206#undef F
207#undef P
208
209 ctx->state[0] += A;
210 ctx->state[1] += B;
211 ctx->state[2] += C;
212 ctx->state[3] += D;
213}
Manuel Pégourié-Gonnard427b6722015-03-31 18:32:50 +0200214#endif /* !POLARSSL_MD4_PROCESS_ALT */
Paul Bakker5121ce52009-01-03 21:22:43 +0000215
216/*
217 * MD4 process buffer
218 */
Paul Bakker23986e52011-04-24 08:57:21 +0000219void md4_update( md4_context *ctx, const unsigned char *input, size_t ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000220{
Paul Bakker23986e52011-04-24 08:57:21 +0000221 size_t fill;
Paul Bakker5c2364c2012-10-01 14:41:15 +0000222 uint32_t left;
Paul Bakker5121ce52009-01-03 21:22:43 +0000223
Brian White12895d12014-04-11 11:29:42 -0400224 if( ilen == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000225 return;
226
227 left = ctx->total[0] & 0x3F;
228 fill = 64 - left;
229
Paul Bakker5c2364c2012-10-01 14:41:15 +0000230 ctx->total[0] += (uint32_t) ilen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000231 ctx->total[0] &= 0xFFFFFFFF;
232
Paul Bakker5c2364c2012-10-01 14:41:15 +0000233 if( ctx->total[0] < (uint32_t) ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000234 ctx->total[1]++;
235
236 if( left && ilen >= fill )
237 {
238 memcpy( (void *) (ctx->buffer + left),
239 (void *) input, fill );
240 md4_process( ctx, ctx->buffer );
241 input += fill;
242 ilen -= fill;
243 left = 0;
244 }
245
246 while( ilen >= 64 )
247 {
248 md4_process( ctx, input );
249 input += 64;
250 ilen -= 64;
251 }
252
253 if( ilen > 0 )
254 {
255 memcpy( (void *) (ctx->buffer + left),
256 (void *) input, ilen );
257 }
258}
259
260static const unsigned char md4_padding[64] =
261{
262 0x80, 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,
264 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
265 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
266};
267
268/*
269 * MD4 final digest
270 */
271void md4_finish( md4_context *ctx, unsigned char output[16] )
272{
Paul Bakker5c2364c2012-10-01 14:41:15 +0000273 uint32_t last, padn;
274 uint32_t high, low;
Paul Bakker5121ce52009-01-03 21:22:43 +0000275 unsigned char msglen[8];
276
277 high = ( ctx->total[0] >> 29 )
278 | ( ctx->total[1] << 3 );
279 low = ( ctx->total[0] << 3 );
280
Paul Bakker5c2364c2012-10-01 14:41:15 +0000281 PUT_UINT32_LE( low, msglen, 0 );
282 PUT_UINT32_LE( high, msglen, 4 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000283
284 last = ctx->total[0] & 0x3F;
285 padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
286
287 md4_update( ctx, (unsigned char *) md4_padding, padn );
288 md4_update( ctx, msglen, 8 );
289
Paul Bakker5c2364c2012-10-01 14:41:15 +0000290 PUT_UINT32_LE( ctx->state[0], output, 0 );
291 PUT_UINT32_LE( ctx->state[1], output, 4 );
292 PUT_UINT32_LE( ctx->state[2], output, 8 );
293 PUT_UINT32_LE( ctx->state[3], output, 12 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000294}
295
Paul Bakker90995b52013-06-24 19:20:35 +0200296#endif /* !POLARSSL_MD4_ALT */
297
Paul Bakker5121ce52009-01-03 21:22:43 +0000298/*
299 * output = MD4( input buffer )
300 */
Paul Bakker23986e52011-04-24 08:57:21 +0000301void md4( const unsigned char *input, size_t ilen, unsigned char output[16] )
Paul Bakker5121ce52009-01-03 21:22:43 +0000302{
303 md4_context ctx;
304
Paul Bakker5b4af392014-06-26 12:09:34 +0200305 md4_init( &ctx );
Paul Bakker5121ce52009-01-03 21:22:43 +0000306 md4_starts( &ctx );
307 md4_update( &ctx, input, ilen );
308 md4_finish( &ctx, output );
Paul Bakker5b4af392014-06-26 12:09:34 +0200309 md4_free( &ctx );
Paul Bakker5121ce52009-01-03 21:22:43 +0000310}
311
Paul Bakker335db3f2011-04-25 15:28:35 +0000312#if defined(POLARSSL_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000313/*
314 * output = MD4( file contents )
315 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000316int md4_file( const char *path, unsigned char output[16] )
Paul Bakker5121ce52009-01-03 21:22:43 +0000317{
318 FILE *f;
319 size_t n;
320 md4_context ctx;
321 unsigned char buf[1024];
322
323 if( ( f = fopen( path, "rb" ) ) == NULL )
Paul Bakker69e095c2011-12-10 21:55:01 +0000324 return( POLARSSL_ERR_MD4_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000325
Paul Bakker5b4af392014-06-26 12:09:34 +0200326 md4_init( &ctx );
Paul Bakker5121ce52009-01-03 21:22:43 +0000327 md4_starts( &ctx );
328
329 while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
Paul Bakker27fdf462011-06-09 13:55:13 +0000330 md4_update( &ctx, buf, n );
Paul Bakker5121ce52009-01-03 21:22:43 +0000331
332 md4_finish( &ctx, output );
Paul Bakker5b4af392014-06-26 12:09:34 +0200333 md4_free( &ctx );
Paul Bakker5121ce52009-01-03 21:22:43 +0000334
335 if( ferror( f ) != 0 )
336 {
337 fclose( f );
Paul Bakker69e095c2011-12-10 21:55:01 +0000338 return( POLARSSL_ERR_MD4_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000339 }
340
341 fclose( f );
342 return( 0 );
343}
Paul Bakker335db3f2011-04-25 15:28:35 +0000344#endif /* POLARSSL_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000345
Paul Bakker40e46942009-01-03 21:51:57 +0000346#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000347
348/*
349 * RFC 1320 test vectors
350 */
351static const char md4_test_str[7][81] =
352{
Paul Bakker9af723c2014-05-01 13:03:14 +0200353 { "" },
Paul Bakker5121ce52009-01-03 21:22:43 +0000354 { "a" },
355 { "abc" },
356 { "message digest" },
357 { "abcdefghijklmnopqrstuvwxyz" },
358 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
359 { "12345678901234567890123456789012345678901234567890123456789012" \
360 "345678901234567890" }
361};
362
363static const unsigned char md4_test_sum[7][16] =
364{
365 { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31,
366 0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 },
367 { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46,
368 0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 },
369 { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52,
370 0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D },
371 { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8,
372 0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B },
373 { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD,
374 0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 },
375 { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35,
376 0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 },
377 { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19,
378 0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 }
379};
380
381/*
382 * Checkup routine
383 */
384int md4_self_test( int verbose )
385{
386 int i;
387 unsigned char md4sum[16];
388
389 for( i = 0; i < 7; i++ )
390 {
391 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100392 polarssl_printf( " MD4 test #%d: ", i + 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000393
394 md4( (unsigned char *) md4_test_str[i],
395 strlen( md4_test_str[i] ), md4sum );
396
397 if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 )
398 {
399 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100400 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000401
402 return( 1 );
403 }
404
405 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100406 polarssl_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000407 }
408
409 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100410 polarssl_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000411
412 return( 0 );
413}
414
Paul Bakker9af723c2014-05-01 13:03:14 +0200415#endif /* POLARSSL_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +0000416
Paul Bakker9af723c2014-05-01 13:03:14 +0200417#endif /* POLARSSL_MD4_C */