blob: 563c6531731571db027f5ae2dd515663ccb203bd [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * RFC 1186/1320 compliant MD4 implementation
3 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, 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
Manuel Pégourié-Gonnard16d412f2015-07-06 15:26:26 +020093void mbedtls_md4_clone( mbedtls_md4_context *dst,
94 const mbedtls_md4_context *src )
95{
96 *dst = *src;
97}
98
Paul Bakker5121ce52009-01-03 21:22:43 +000099/*
100 * MD4 context setup
101 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200102void mbedtls_md4_starts( mbedtls_md4_context *ctx )
Paul Bakker5121ce52009-01-03 21:22:43 +0000103{
104 ctx->total[0] = 0;
105 ctx->total[1] = 0;
106
107 ctx->state[0] = 0x67452301;
108 ctx->state[1] = 0xEFCDAB89;
109 ctx->state[2] = 0x98BADCFE;
110 ctx->state[3] = 0x10325476;
111}
112
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200113#if !defined(MBEDTLS_MD4_PROCESS_ALT)
114void mbedtls_md4_process( mbedtls_md4_context *ctx, const unsigned char data[64] )
Paul Bakker5121ce52009-01-03 21:22:43 +0000115{
Paul Bakker5c2364c2012-10-01 14:41:15 +0000116 uint32_t X[16], A, B, C, D;
Paul Bakker5121ce52009-01-03 21:22:43 +0000117
Paul Bakker5c2364c2012-10-01 14:41:15 +0000118 GET_UINT32_LE( X[ 0], data, 0 );
119 GET_UINT32_LE( X[ 1], data, 4 );
120 GET_UINT32_LE( X[ 2], data, 8 );
121 GET_UINT32_LE( X[ 3], data, 12 );
122 GET_UINT32_LE( X[ 4], data, 16 );
123 GET_UINT32_LE( X[ 5], data, 20 );
124 GET_UINT32_LE( X[ 6], data, 24 );
125 GET_UINT32_LE( X[ 7], data, 28 );
126 GET_UINT32_LE( X[ 8], data, 32 );
127 GET_UINT32_LE( X[ 9], data, 36 );
128 GET_UINT32_LE( X[10], data, 40 );
129 GET_UINT32_LE( X[11], data, 44 );
130 GET_UINT32_LE( X[12], data, 48 );
131 GET_UINT32_LE( X[13], data, 52 );
132 GET_UINT32_LE( X[14], data, 56 );
133 GET_UINT32_LE( X[15], data, 60 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000134
135#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
136
137 A = ctx->state[0];
138 B = ctx->state[1];
139 C = ctx->state[2];
140 D = ctx->state[3];
141
142#define F(x, y, z) ((x & y) | ((~x) & z))
143#define P(a,b,c,d,x,s) { a += F(b,c,d) + x; a = S(a,s); }
144
145 P( A, B, C, D, X[ 0], 3 );
146 P( D, A, B, C, X[ 1], 7 );
147 P( C, D, A, B, X[ 2], 11 );
148 P( B, C, D, A, X[ 3], 19 );
149 P( A, B, C, D, X[ 4], 3 );
150 P( D, A, B, C, X[ 5], 7 );
151 P( C, D, A, B, X[ 6], 11 );
152 P( B, C, D, A, X[ 7], 19 );
153 P( A, B, C, D, X[ 8], 3 );
154 P( D, A, B, C, X[ 9], 7 );
155 P( C, D, A, B, X[10], 11 );
156 P( B, C, D, A, X[11], 19 );
157 P( A, B, C, D, X[12], 3 );
158 P( D, A, B, C, X[13], 7 );
159 P( C, D, A, B, X[14], 11 );
160 P( B, C, D, A, X[15], 19 );
161
162#undef P
163#undef F
164
165#define F(x,y,z) ((x & y) | (x & z) | (y & z))
166#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x5A827999; a = S(a,s); }
167
168 P( A, B, C, D, X[ 0], 3 );
169 P( D, A, B, C, X[ 4], 5 );
170 P( C, D, A, B, X[ 8], 9 );
171 P( B, C, D, A, X[12], 13 );
172 P( A, B, C, D, X[ 1], 3 );
173 P( D, A, B, C, X[ 5], 5 );
174 P( C, D, A, B, X[ 9], 9 );
175 P( B, C, D, A, X[13], 13 );
176 P( A, B, C, D, X[ 2], 3 );
177 P( D, A, B, C, X[ 6], 5 );
178 P( C, D, A, B, X[10], 9 );
179 P( B, C, D, A, X[14], 13 );
180 P( A, B, C, D, X[ 3], 3 );
181 P( D, A, B, C, X[ 7], 5 );
182 P( C, D, A, B, X[11], 9 );
183 P( B, C, D, A, X[15], 13 );
184
185#undef P
186#undef F
187
188#define F(x,y,z) (x ^ y ^ z)
189#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x6ED9EBA1; a = S(a,s); }
190
191 P( A, B, C, D, X[ 0], 3 );
192 P( D, A, B, C, X[ 8], 9 );
193 P( C, D, A, B, X[ 4], 11 );
194 P( B, C, D, A, X[12], 15 );
195 P( A, B, C, D, X[ 2], 3 );
196 P( D, A, B, C, X[10], 9 );
197 P( C, D, A, B, X[ 6], 11 );
198 P( B, C, D, A, X[14], 15 );
199 P( A, B, C, D, X[ 1], 3 );
200 P( D, A, B, C, X[ 9], 9 );
201 P( C, D, A, B, X[ 5], 11 );
202 P( B, C, D, A, X[13], 15 );
203 P( A, B, C, D, X[ 3], 3 );
204 P( D, A, B, C, X[11], 9 );
205 P( C, D, A, B, X[ 7], 11 );
206 P( B, C, D, A, X[15], 15 );
207
208#undef F
209#undef P
210
211 ctx->state[0] += A;
212 ctx->state[1] += B;
213 ctx->state[2] += C;
214 ctx->state[3] += D;
215}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200216#endif /* !MBEDTLS_MD4_PROCESS_ALT */
Paul Bakker5121ce52009-01-03 21:22:43 +0000217
218/*
219 * MD4 process buffer
220 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200221void mbedtls_md4_update( mbedtls_md4_context *ctx, const unsigned char *input, size_t ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000222{
Paul Bakker23986e52011-04-24 08:57:21 +0000223 size_t fill;
Paul Bakker5c2364c2012-10-01 14:41:15 +0000224 uint32_t left;
Paul Bakker5121ce52009-01-03 21:22:43 +0000225
Brian White12895d12014-04-11 11:29:42 -0400226 if( ilen == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000227 return;
228
229 left = ctx->total[0] & 0x3F;
230 fill = 64 - left;
231
Paul Bakker5c2364c2012-10-01 14:41:15 +0000232 ctx->total[0] += (uint32_t) ilen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000233 ctx->total[0] &= 0xFFFFFFFF;
234
Paul Bakker5c2364c2012-10-01 14:41:15 +0000235 if( ctx->total[0] < (uint32_t) ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000236 ctx->total[1]++;
237
238 if( left && ilen >= fill )
239 {
240 memcpy( (void *) (ctx->buffer + left),
241 (void *) input, fill );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200242 mbedtls_md4_process( ctx, ctx->buffer );
Paul Bakker5121ce52009-01-03 21:22:43 +0000243 input += fill;
244 ilen -= fill;
245 left = 0;
246 }
247
248 while( ilen >= 64 )
249 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200250 mbedtls_md4_process( ctx, input );
Paul Bakker5121ce52009-01-03 21:22:43 +0000251 input += 64;
252 ilen -= 64;
253 }
254
255 if( ilen > 0 )
256 {
257 memcpy( (void *) (ctx->buffer + left),
258 (void *) input, ilen );
259 }
260}
261
262static const unsigned char md4_padding[64] =
263{
264 0x80, 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 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
267 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
268};
269
270/*
271 * MD4 final digest
272 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200273void mbedtls_md4_finish( mbedtls_md4_context *ctx, unsigned char output[16] )
Paul Bakker5121ce52009-01-03 21:22:43 +0000274{
Paul Bakker5c2364c2012-10-01 14:41:15 +0000275 uint32_t last, padn;
276 uint32_t high, low;
Paul Bakker5121ce52009-01-03 21:22:43 +0000277 unsigned char msglen[8];
278
279 high = ( ctx->total[0] >> 29 )
280 | ( ctx->total[1] << 3 );
281 low = ( ctx->total[0] << 3 );
282
Paul Bakker5c2364c2012-10-01 14:41:15 +0000283 PUT_UINT32_LE( low, msglen, 0 );
284 PUT_UINT32_LE( high, msglen, 4 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000285
286 last = ctx->total[0] & 0x3F;
287 padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
288
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200289 mbedtls_md4_update( ctx, (unsigned char *) md4_padding, padn );
290 mbedtls_md4_update( ctx, msglen, 8 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000291
Paul Bakker5c2364c2012-10-01 14:41:15 +0000292 PUT_UINT32_LE( ctx->state[0], output, 0 );
293 PUT_UINT32_LE( ctx->state[1], output, 4 );
294 PUT_UINT32_LE( ctx->state[2], output, 8 );
295 PUT_UINT32_LE( ctx->state[3], output, 12 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000296}
297
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200298#endif /* !MBEDTLS_MD4_ALT */
Paul Bakker90995b52013-06-24 19:20:35 +0200299
Paul Bakker5121ce52009-01-03 21:22:43 +0000300/*
301 * output = MD4( input buffer )
302 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200303void mbedtls_md4( const unsigned char *input, size_t ilen, unsigned char output[16] )
Paul Bakker5121ce52009-01-03 21:22:43 +0000304{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200305 mbedtls_md4_context ctx;
Paul Bakker5121ce52009-01-03 21:22:43 +0000306
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200307 mbedtls_md4_init( &ctx );
308 mbedtls_md4_starts( &ctx );
309 mbedtls_md4_update( &ctx, input, ilen );
310 mbedtls_md4_finish( &ctx, output );
311 mbedtls_md4_free( &ctx );
Paul Bakker5121ce52009-01-03 21:22:43 +0000312}
313
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200314#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000315
316/*
317 * RFC 1320 test vectors
318 */
319static const char md4_test_str[7][81] =
320{
Paul Bakker9af723c2014-05-01 13:03:14 +0200321 { "" },
Paul Bakker5121ce52009-01-03 21:22:43 +0000322 { "a" },
323 { "abc" },
324 { "message digest" },
325 { "abcdefghijklmnopqrstuvwxyz" },
326 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
327 { "12345678901234567890123456789012345678901234567890123456789012" \
328 "345678901234567890" }
329};
330
331static const unsigned char md4_test_sum[7][16] =
332{
333 { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31,
334 0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 },
335 { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46,
336 0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 },
337 { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52,
338 0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D },
339 { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8,
340 0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B },
341 { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD,
342 0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 },
343 { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35,
344 0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 },
345 { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19,
346 0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 }
347};
348
349/*
350 * Checkup routine
351 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200352int mbedtls_md4_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +0000353{
354 int i;
355 unsigned char md4sum[16];
356
357 for( i = 0; i < 7; i++ )
358 {
359 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200360 mbedtls_printf( " MD4 test #%d: ", i + 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000361
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200362 mbedtls_md4( (unsigned char *) md4_test_str[i],
Paul Bakker5121ce52009-01-03 21:22:43 +0000363 strlen( md4_test_str[i] ), md4sum );
364
365 if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 )
366 {
367 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200368 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000369
370 return( 1 );
371 }
372
373 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200374 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000375 }
376
377 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200378 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000379
380 return( 0 );
381}
382
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200383#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +0000384
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200385#endif /* MBEDTLS_MD4_C */