blob: 90623582a161aae26397a3bcf0d2f10a25772d3d [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é-Gonnard2cf5a7c2015-04-08 12:49:31 +020029#if !defined(MBEDTLS_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
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020032#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020033#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000034
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020035#if defined(MBEDTLS_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
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020041#if defined(MBEDTLS_SELF_TEST)
42#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000043#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010044#else
Rich Evans00ab4702015-02-06 13:43:58 +000045#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020046#define mbedtls_printf printf
47#endif /* MBEDTLS_PLATFORM_C */
48#endif /* MBEDTLS_SELF_TEST */
Paul Bakker7dc4c442014-02-01 22:50:26 +010049
Paul Bakker34617722014-06-13 17:20:13 +020050/* Implementation that should never be optimized out by the compiler */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020051static void mbedtls_zeroize( void *v, size_t n ) {
Paul Bakker34617722014-06-13 17:20:13 +020052 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
53}
54
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020055#if !defined(MBEDTLS_MD4_ALT)
Paul Bakker90995b52013-06-24 19:20:35 +020056
Paul Bakker5121ce52009-01-03 21:22:43 +000057/*
58 * 32-bit integer manipulation macros (little endian)
59 */
Paul Bakker5c2364c2012-10-01 14:41:15 +000060#ifndef GET_UINT32_LE
61#define GET_UINT32_LE(n,b,i) \
Paul Bakker5121ce52009-01-03 21:22:43 +000062{ \
Paul Bakker5c2364c2012-10-01 14:41:15 +000063 (n) = ( (uint32_t) (b)[(i) ] ) \
64 | ( (uint32_t) (b)[(i) + 1] << 8 ) \
65 | ( (uint32_t) (b)[(i) + 2] << 16 ) \
66 | ( (uint32_t) (b)[(i) + 3] << 24 ); \
Paul Bakker5121ce52009-01-03 21:22:43 +000067}
68#endif
69
Paul Bakker5c2364c2012-10-01 14:41:15 +000070#ifndef PUT_UINT32_LE
Manuel Pégourié-Gonnardceedb822015-01-23 15:02:43 +000071#define PUT_UINT32_LE(n,b,i) \
72{ \
73 (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \
74 (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \
75 (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \
76 (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \
Paul Bakker5121ce52009-01-03 21:22:43 +000077}
78#endif
79
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020080void mbedtls_md4_init( mbedtls_md4_context *ctx )
Paul Bakker5b4af392014-06-26 12:09:34 +020081{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020082 memset( ctx, 0, sizeof( mbedtls_md4_context ) );
Paul Bakker5b4af392014-06-26 12:09:34 +020083}
84
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020085void mbedtls_md4_free( mbedtls_md4_context *ctx )
Paul Bakker5b4af392014-06-26 12:09:34 +020086{
87 if( ctx == NULL )
88 return;
89
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020090 mbedtls_zeroize( ctx, sizeof( mbedtls_md4_context ) );
Paul Bakker5b4af392014-06-26 12:09:34 +020091}
92
Paul Bakker5121ce52009-01-03 21:22:43 +000093/*
94 * MD4 context setup
95 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020096void mbedtls_md4_starts( mbedtls_md4_context *ctx )
Paul Bakker5121ce52009-01-03 21:22:43 +000097{
98 ctx->total[0] = 0;
99 ctx->total[1] = 0;
100
101 ctx->state[0] = 0x67452301;
102 ctx->state[1] = 0xEFCDAB89;
103 ctx->state[2] = 0x98BADCFE;
104 ctx->state[3] = 0x10325476;
105}
106
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200107#if !defined(MBEDTLS_MD4_PROCESS_ALT)
108void mbedtls_md4_process( mbedtls_md4_context *ctx, const unsigned char data[64] )
Paul Bakker5121ce52009-01-03 21:22:43 +0000109{
Paul Bakker5c2364c2012-10-01 14:41:15 +0000110 uint32_t X[16], A, B, C, D;
Paul Bakker5121ce52009-01-03 21:22:43 +0000111
Paul Bakker5c2364c2012-10-01 14:41:15 +0000112 GET_UINT32_LE( X[ 0], data, 0 );
113 GET_UINT32_LE( X[ 1], data, 4 );
114 GET_UINT32_LE( X[ 2], data, 8 );
115 GET_UINT32_LE( X[ 3], data, 12 );
116 GET_UINT32_LE( X[ 4], data, 16 );
117 GET_UINT32_LE( X[ 5], data, 20 );
118 GET_UINT32_LE( X[ 6], data, 24 );
119 GET_UINT32_LE( X[ 7], data, 28 );
120 GET_UINT32_LE( X[ 8], data, 32 );
121 GET_UINT32_LE( X[ 9], data, 36 );
122 GET_UINT32_LE( X[10], data, 40 );
123 GET_UINT32_LE( X[11], data, 44 );
124 GET_UINT32_LE( X[12], data, 48 );
125 GET_UINT32_LE( X[13], data, 52 );
126 GET_UINT32_LE( X[14], data, 56 );
127 GET_UINT32_LE( X[15], data, 60 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000128
129#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
130
131 A = ctx->state[0];
132 B = ctx->state[1];
133 C = ctx->state[2];
134 D = ctx->state[3];
135
136#define F(x, y, z) ((x & y) | ((~x) & z))
137#define P(a,b,c,d,x,s) { a += F(b,c,d) + x; a = S(a,s); }
138
139 P( A, B, C, D, X[ 0], 3 );
140 P( D, A, B, C, X[ 1], 7 );
141 P( C, D, A, B, X[ 2], 11 );
142 P( B, C, D, A, X[ 3], 19 );
143 P( A, B, C, D, X[ 4], 3 );
144 P( D, A, B, C, X[ 5], 7 );
145 P( C, D, A, B, X[ 6], 11 );
146 P( B, C, D, A, X[ 7], 19 );
147 P( A, B, C, D, X[ 8], 3 );
148 P( D, A, B, C, X[ 9], 7 );
149 P( C, D, A, B, X[10], 11 );
150 P( B, C, D, A, X[11], 19 );
151 P( A, B, C, D, X[12], 3 );
152 P( D, A, B, C, X[13], 7 );
153 P( C, D, A, B, X[14], 11 );
154 P( B, C, D, A, X[15], 19 );
155
156#undef P
157#undef F
158
159#define F(x,y,z) ((x & y) | (x & z) | (y & z))
160#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x5A827999; a = S(a,s); }
161
162 P( A, B, C, D, X[ 0], 3 );
163 P( D, A, B, C, X[ 4], 5 );
164 P( C, D, A, B, X[ 8], 9 );
165 P( B, C, D, A, X[12], 13 );
166 P( A, B, C, D, X[ 1], 3 );
167 P( D, A, B, C, X[ 5], 5 );
168 P( C, D, A, B, X[ 9], 9 );
169 P( B, C, D, A, X[13], 13 );
170 P( A, B, C, D, X[ 2], 3 );
171 P( D, A, B, C, X[ 6], 5 );
172 P( C, D, A, B, X[10], 9 );
173 P( B, C, D, A, X[14], 13 );
174 P( A, B, C, D, X[ 3], 3 );
175 P( D, A, B, C, X[ 7], 5 );
176 P( C, D, A, B, X[11], 9 );
177 P( B, C, D, A, X[15], 13 );
178
179#undef P
180#undef F
181
182#define F(x,y,z) (x ^ y ^ z)
183#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x6ED9EBA1; a = S(a,s); }
184
185 P( A, B, C, D, X[ 0], 3 );
186 P( D, A, B, C, X[ 8], 9 );
187 P( C, D, A, B, X[ 4], 11 );
188 P( B, C, D, A, X[12], 15 );
189 P( A, B, C, D, X[ 2], 3 );
190 P( D, A, B, C, X[10], 9 );
191 P( C, D, A, B, X[ 6], 11 );
192 P( B, C, D, A, X[14], 15 );
193 P( A, B, C, D, X[ 1], 3 );
194 P( D, A, B, C, X[ 9], 9 );
195 P( C, D, A, B, X[ 5], 11 );
196 P( B, C, D, A, X[13], 15 );
197 P( A, B, C, D, X[ 3], 3 );
198 P( D, A, B, C, X[11], 9 );
199 P( C, D, A, B, X[ 7], 11 );
200 P( B, C, D, A, X[15], 15 );
201
202#undef F
203#undef P
204
205 ctx->state[0] += A;
206 ctx->state[1] += B;
207 ctx->state[2] += C;
208 ctx->state[3] += D;
209}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200210#endif /* !MBEDTLS_MD4_PROCESS_ALT */
Paul Bakker5121ce52009-01-03 21:22:43 +0000211
212/*
213 * MD4 process buffer
214 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200215void mbedtls_md4_update( mbedtls_md4_context *ctx, const unsigned char *input, size_t ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000216{
Paul Bakker23986e52011-04-24 08:57:21 +0000217 size_t fill;
Paul Bakker5c2364c2012-10-01 14:41:15 +0000218 uint32_t left;
Paul Bakker5121ce52009-01-03 21:22:43 +0000219
Brian White12895d12014-04-11 11:29:42 -0400220 if( ilen == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000221 return;
222
223 left = ctx->total[0] & 0x3F;
224 fill = 64 - left;
225
Paul Bakker5c2364c2012-10-01 14:41:15 +0000226 ctx->total[0] += (uint32_t) ilen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000227 ctx->total[0] &= 0xFFFFFFFF;
228
Paul Bakker5c2364c2012-10-01 14:41:15 +0000229 if( ctx->total[0] < (uint32_t) ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000230 ctx->total[1]++;
231
232 if( left && ilen >= fill )
233 {
234 memcpy( (void *) (ctx->buffer + left),
235 (void *) input, fill );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200236 mbedtls_md4_process( ctx, ctx->buffer );
Paul Bakker5121ce52009-01-03 21:22:43 +0000237 input += fill;
238 ilen -= fill;
239 left = 0;
240 }
241
242 while( ilen >= 64 )
243 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200244 mbedtls_md4_process( ctx, input );
Paul Bakker5121ce52009-01-03 21:22:43 +0000245 input += 64;
246 ilen -= 64;
247 }
248
249 if( ilen > 0 )
250 {
251 memcpy( (void *) (ctx->buffer + left),
252 (void *) input, ilen );
253 }
254}
255
256static const unsigned char md4_padding[64] =
257{
258 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
259 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
260 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
261 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
262};
263
264/*
265 * MD4 final digest
266 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200267void mbedtls_md4_finish( mbedtls_md4_context *ctx, unsigned char output[16] )
Paul Bakker5121ce52009-01-03 21:22:43 +0000268{
Paul Bakker5c2364c2012-10-01 14:41:15 +0000269 uint32_t last, padn;
270 uint32_t high, low;
Paul Bakker5121ce52009-01-03 21:22:43 +0000271 unsigned char msglen[8];
272
273 high = ( ctx->total[0] >> 29 )
274 | ( ctx->total[1] << 3 );
275 low = ( ctx->total[0] << 3 );
276
Paul Bakker5c2364c2012-10-01 14:41:15 +0000277 PUT_UINT32_LE( low, msglen, 0 );
278 PUT_UINT32_LE( high, msglen, 4 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000279
280 last = ctx->total[0] & 0x3F;
281 padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
282
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200283 mbedtls_md4_update( ctx, (unsigned char *) md4_padding, padn );
284 mbedtls_md4_update( ctx, msglen, 8 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000285
Paul Bakker5c2364c2012-10-01 14:41:15 +0000286 PUT_UINT32_LE( ctx->state[0], output, 0 );
287 PUT_UINT32_LE( ctx->state[1], output, 4 );
288 PUT_UINT32_LE( ctx->state[2], output, 8 );
289 PUT_UINT32_LE( ctx->state[3], output, 12 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000290}
291
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200292#endif /* !MBEDTLS_MD4_ALT */
Paul Bakker90995b52013-06-24 19:20:35 +0200293
Paul Bakker5121ce52009-01-03 21:22:43 +0000294/*
295 * output = MD4( input buffer )
296 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200297void mbedtls_md4( const unsigned char *input, size_t ilen, unsigned char output[16] )
Paul Bakker5121ce52009-01-03 21:22:43 +0000298{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200299 mbedtls_md4_context ctx;
Paul Bakker5121ce52009-01-03 21:22:43 +0000300
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200301 mbedtls_md4_init( &ctx );
302 mbedtls_md4_starts( &ctx );
303 mbedtls_md4_update( &ctx, input, ilen );
304 mbedtls_md4_finish( &ctx, output );
305 mbedtls_md4_free( &ctx );
Paul Bakker5121ce52009-01-03 21:22:43 +0000306}
307
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200308#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000309
310/*
311 * RFC 1320 test vectors
312 */
313static const char md4_test_str[7][81] =
314{
Paul Bakker9af723c2014-05-01 13:03:14 +0200315 { "" },
Paul Bakker5121ce52009-01-03 21:22:43 +0000316 { "a" },
317 { "abc" },
318 { "message digest" },
319 { "abcdefghijklmnopqrstuvwxyz" },
320 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
321 { "12345678901234567890123456789012345678901234567890123456789012" \
322 "345678901234567890" }
323};
324
325static const unsigned char md4_test_sum[7][16] =
326{
327 { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31,
328 0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 },
329 { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46,
330 0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 },
331 { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52,
332 0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D },
333 { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8,
334 0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B },
335 { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD,
336 0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 },
337 { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35,
338 0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 },
339 { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19,
340 0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 }
341};
342
343/*
344 * Checkup routine
345 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200346int mbedtls_md4_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +0000347{
348 int i;
349 unsigned char md4sum[16];
350
351 for( i = 0; i < 7; i++ )
352 {
353 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200354 mbedtls_printf( " MD4 test #%d: ", i + 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000355
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200356 mbedtls_md4( (unsigned char *) md4_test_str[i],
Paul Bakker5121ce52009-01-03 21:22:43 +0000357 strlen( md4_test_str[i] ), md4sum );
358
359 if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 )
360 {
361 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200362 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000363
364 return( 1 );
365 }
366
367 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200368 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000369 }
370
371 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200372 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000373
374 return( 0 );
375}
376
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200377#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +0000378
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200379#endif /* MBEDTLS_MD4_C */