2 * RFC 1186/1320 compliant MD4 implementation
4 * Copyright The Mbed TLS Contributors
5 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
7 * This file is provided under the Apache License 2.0, or the
8 * GNU General Public License v2.0 or later.
13 * Licensed under the Apache License, Version 2.0 (the "License"); you may
14 * not use this file except in compliance with the License.
15 * You may obtain a copy of the License at
17 * http://www.apache.org/licenses/LICENSE-2.0
19 * Unless required by applicable law or agreed to in writing, software
20 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
21 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 * See the License for the specific language governing permissions and
23 * limitations under the License.
28 * GNU General Public License v2.0 or later:
30 * This program is free software; you can redistribute it and/or modify
31 * it under the terms of the GNU General Public License as published by
32 * the Free Software Foundation; either version 2 of the License, or
33 * (at your option) any later version.
35 * This program is distributed in the hope that it will be useful,
36 * but WITHOUT ANY WARRANTY; without even the implied warranty of
37 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38 * GNU General Public License for more details.
40 * You should have received a copy of the GNU General Public License along
41 * with this program; if not, write to the Free Software Foundation, Inc.,
42 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
47 * The MD4 algorithm was designed by Ron Rivest in 1990.
49 * http://www.ietf.org/rfc/rfc1186.txt
50 * http://www.ietf.org/rfc/rfc1320.txt
53 #if !defined(MBEDTLS_CONFIG_FILE)
54 #include "mbedtls/config.h"
56 #include MBEDTLS_CONFIG_FILE
59 #if defined(MBEDTLS_MD4_C)
61 #include "mbedtls/md4.h"
62 #include "mbedtls/platform_util.h"
66 #if defined(MBEDTLS_SELF_TEST)
67 #if defined(MBEDTLS_PLATFORM_C)
68 #include "mbedtls/platform.h"
71 #define mbedtls_printf printf
72 #endif /* MBEDTLS_PLATFORM_C */
73 #endif /* MBEDTLS_SELF_TEST */
75 #if !defined(MBEDTLS_MD4_ALT)
78 * 32-bit integer manipulation macros (little endian)
81 #define GET_UINT32_LE(n,b,i) \
83 (n) = ( (uint32_t) (b)[(i) ] ) \
84 | ( (uint32_t) (b)[(i) + 1] << 8 ) \
85 | ( (uint32_t) (b)[(i) + 2] << 16 ) \
86 | ( (uint32_t) (b)[(i) + 3] << 24 ); \
91 #define PUT_UINT32_LE(n,b,i) \
93 (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \
94 (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \
95 (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \
96 (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \
100 void mbedtls_md4_init( mbedtls_md4_context
*ctx
)
102 memset( ctx
, 0, sizeof( mbedtls_md4_context
) );
105 void mbedtls_md4_free( mbedtls_md4_context
*ctx
)
110 mbedtls_platform_zeroize( ctx
, sizeof( mbedtls_md4_context
) );
113 void mbedtls_md4_clone( mbedtls_md4_context
*dst
,
114 const mbedtls_md4_context
*src
)
122 int mbedtls_md4_starts_ret( mbedtls_md4_context
*ctx
)
127 ctx
->state
[0] = 0x67452301;
128 ctx
->state
[1] = 0xEFCDAB89;
129 ctx
->state
[2] = 0x98BADCFE;
130 ctx
->state
[3] = 0x10325476;
135 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
136 void mbedtls_md4_starts( mbedtls_md4_context
*ctx
)
138 mbedtls_md4_starts_ret( ctx
);
142 #if !defined(MBEDTLS_MD4_PROCESS_ALT)
143 int mbedtls_internal_md4_process( mbedtls_md4_context
*ctx
,
144 const unsigned char data
[64] )
148 uint32_t X
[16], A
, B
, C
, D
;
151 GET_UINT32_LE( local
.X
[ 0], data
, 0 );
152 GET_UINT32_LE( local
.X
[ 1], data
, 4 );
153 GET_UINT32_LE( local
.X
[ 2], data
, 8 );
154 GET_UINT32_LE( local
.X
[ 3], data
, 12 );
155 GET_UINT32_LE( local
.X
[ 4], data
, 16 );
156 GET_UINT32_LE( local
.X
[ 5], data
, 20 );
157 GET_UINT32_LE( local
.X
[ 6], data
, 24 );
158 GET_UINT32_LE( local
.X
[ 7], data
, 28 );
159 GET_UINT32_LE( local
.X
[ 8], data
, 32 );
160 GET_UINT32_LE( local
.X
[ 9], data
, 36 );
161 GET_UINT32_LE( local
.X
[10], data
, 40 );
162 GET_UINT32_LE( local
.X
[11], data
, 44 );
163 GET_UINT32_LE( local
.X
[12], data
, 48 );
164 GET_UINT32_LE( local
.X
[13], data
, 52 );
165 GET_UINT32_LE( local
.X
[14], data
, 56 );
166 GET_UINT32_LE( local
.X
[15], data
, 60 );
168 #define S(x,n) (((x) << (n)) | (((x) & 0xFFFFFFFF) >> (32 - (n))))
170 local
.A
= ctx
->state
[0];
171 local
.B
= ctx
->state
[1];
172 local
.C
= ctx
->state
[2];
173 local
.D
= ctx
->state
[3];
175 #define F(x, y, z) (((x) & (y)) | ((~(x)) & (z)))
176 #define P(a,b,c,d,x,s) \
179 (a) += F((b),(c),(d)) + (x); \
184 P( local
.A
, local
.B
, local
.C
, local
.D
, local
.X
[ 0], 3 );
185 P( local
.D
, local
.A
, local
.B
, local
.C
, local
.X
[ 1], 7 );
186 P( local
.C
, local
.D
, local
.A
, local
.B
, local
.X
[ 2], 11 );
187 P( local
.B
, local
.C
, local
.D
, local
.A
, local
.X
[ 3], 19 );
188 P( local
.A
, local
.B
, local
.C
, local
.D
, local
.X
[ 4], 3 );
189 P( local
.D
, local
.A
, local
.B
, local
.C
, local
.X
[ 5], 7 );
190 P( local
.C
, local
.D
, local
.A
, local
.B
, local
.X
[ 6], 11 );
191 P( local
.B
, local
.C
, local
.D
, local
.A
, local
.X
[ 7], 19 );
192 P( local
.A
, local
.B
, local
.C
, local
.D
, local
.X
[ 8], 3 );
193 P( local
.D
, local
.A
, local
.B
, local
.C
, local
.X
[ 9], 7 );
194 P( local
.C
, local
.D
, local
.A
, local
.B
, local
.X
[10], 11 );
195 P( local
.B
, local
.C
, local
.D
, local
.A
, local
.X
[11], 19 );
196 P( local
.A
, local
.B
, local
.C
, local
.D
, local
.X
[12], 3 );
197 P( local
.D
, local
.A
, local
.B
, local
.C
, local
.X
[13], 7 );
198 P( local
.C
, local
.D
, local
.A
, local
.B
, local
.X
[14], 11 );
199 P( local
.B
, local
.C
, local
.D
, local
.A
, local
.X
[15], 19 );
204 #define F(x,y,z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
205 #define P(a,b,c,d,x,s) \
208 (a) += F((b),(c),(d)) + (x) + 0x5A827999; \
212 P( local
.A
, local
.B
, local
.C
, local
.D
, local
.X
[ 0], 3 );
213 P( local
.D
, local
.A
, local
.B
, local
.C
, local
.X
[ 4], 5 );
214 P( local
.C
, local
.D
, local
.A
, local
.B
, local
.X
[ 8], 9 );
215 P( local
.B
, local
.C
, local
.D
, local
.A
, local
.X
[12], 13 );
216 P( local
.A
, local
.B
, local
.C
, local
.D
, local
.X
[ 1], 3 );
217 P( local
.D
, local
.A
, local
.B
, local
.C
, local
.X
[ 5], 5 );
218 P( local
.C
, local
.D
, local
.A
, local
.B
, local
.X
[ 9], 9 );
219 P( local
.B
, local
.C
, local
.D
, local
.A
, local
.X
[13], 13 );
220 P( local
.A
, local
.B
, local
.C
, local
.D
, local
.X
[ 2], 3 );
221 P( local
.D
, local
.A
, local
.B
, local
.C
, local
.X
[ 6], 5 );
222 P( local
.C
, local
.D
, local
.A
, local
.B
, local
.X
[10], 9 );
223 P( local
.B
, local
.C
, local
.D
, local
.A
, local
.X
[14], 13 );
224 P( local
.A
, local
.B
, local
.C
, local
.D
, local
.X
[ 3], 3 );
225 P( local
.D
, local
.A
, local
.B
, local
.C
, local
.X
[ 7], 5 );
226 P( local
.C
, local
.D
, local
.A
, local
.B
, local
.X
[11], 9 );
227 P( local
.B
, local
.C
, local
.D
, local
.A
, local
.X
[15], 13 );
232 #define F(x,y,z) ((x) ^ (y) ^ (z))
233 #define P(a,b,c,d,x,s) \
236 (a) += F((b),(c),(d)) + (x) + 0x6ED9EBA1; \
240 P( local
.A
, local
.B
, local
.C
, local
.D
, local
.X
[ 0], 3 );
241 P( local
.D
, local
.A
, local
.B
, local
.C
, local
.X
[ 8], 9 );
242 P( local
.C
, local
.D
, local
.A
, local
.B
, local
.X
[ 4], 11 );
243 P( local
.B
, local
.C
, local
.D
, local
.A
, local
.X
[12], 15 );
244 P( local
.A
, local
.B
, local
.C
, local
.D
, local
.X
[ 2], 3 );
245 P( local
.D
, local
.A
, local
.B
, local
.C
, local
.X
[10], 9 );
246 P( local
.C
, local
.D
, local
.A
, local
.B
, local
.X
[ 6], 11 );
247 P( local
.B
, local
.C
, local
.D
, local
.A
, local
.X
[14], 15 );
248 P( local
.A
, local
.B
, local
.C
, local
.D
, local
.X
[ 1], 3 );
249 P( local
.D
, local
.A
, local
.B
, local
.C
, local
.X
[ 9], 9 );
250 P( local
.C
, local
.D
, local
.A
, local
.B
, local
.X
[ 5], 11 );
251 P( local
.B
, local
.C
, local
.D
, local
.A
, local
.X
[13], 15 );
252 P( local
.A
, local
.B
, local
.C
, local
.D
, local
.X
[ 3], 3 );
253 P( local
.D
, local
.A
, local
.B
, local
.C
, local
.X
[11], 9 );
254 P( local
.C
, local
.D
, local
.A
, local
.B
, local
.X
[ 7], 11 );
255 P( local
.B
, local
.C
, local
.D
, local
.A
, local
.X
[15], 15 );
260 ctx
->state
[0] += local
.A
;
261 ctx
->state
[1] += local
.B
;
262 ctx
->state
[2] += local
.C
;
263 ctx
->state
[3] += local
.D
;
265 /* Zeroise variables to clear sensitive data from memory. */
266 mbedtls_platform_zeroize( &local
, sizeof( local
) );
271 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
272 void mbedtls_md4_process( mbedtls_md4_context
*ctx
,
273 const unsigned char data
[64] )
275 mbedtls_internal_md4_process( ctx
, data
);
278 #endif /* !MBEDTLS_MD4_PROCESS_ALT */
283 int mbedtls_md4_update_ret( mbedtls_md4_context
*ctx
,
284 const unsigned char *input
,
294 left
= ctx
->total
[0] & 0x3F;
297 ctx
->total
[0] += (uint32_t) ilen
;
298 ctx
->total
[0] &= 0xFFFFFFFF;
300 if( ctx
->total
[0] < (uint32_t) ilen
)
303 if( left
&& ilen
>= fill
)
305 memcpy( (void *) (ctx
->buffer
+ left
),
306 (void *) input
, fill
);
308 if( ( ret
= mbedtls_internal_md4_process( ctx
, ctx
->buffer
) ) != 0 )
318 if( ( ret
= mbedtls_internal_md4_process( ctx
, input
) ) != 0 )
327 memcpy( (void *) (ctx
->buffer
+ left
),
328 (void *) input
, ilen
);
334 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
335 void mbedtls_md4_update( mbedtls_md4_context
*ctx
,
336 const unsigned char *input
,
339 mbedtls_md4_update_ret( ctx
, input
, ilen
);
343 static const unsigned char md4_padding
[64] =
345 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
346 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
347 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
348 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
354 int mbedtls_md4_finish_ret( mbedtls_md4_context
*ctx
,
355 unsigned char output
[16] )
360 unsigned char msglen
[8];
362 high
= ( ctx
->total
[0] >> 29 )
363 | ( ctx
->total
[1] << 3 );
364 low
= ( ctx
->total
[0] << 3 );
366 PUT_UINT32_LE( low
, msglen
, 0 );
367 PUT_UINT32_LE( high
, msglen
, 4 );
369 last
= ctx
->total
[0] & 0x3F;
370 padn
= ( last
< 56 ) ? ( 56 - last
) : ( 120 - last
);
372 ret
= mbedtls_md4_update_ret( ctx
, (unsigned char *)md4_padding
, padn
);
376 if( ( ret
= mbedtls_md4_update_ret( ctx
, msglen
, 8 ) ) != 0 )
380 PUT_UINT32_LE( ctx
->state
[0], output
, 0 );
381 PUT_UINT32_LE( ctx
->state
[1], output
, 4 );
382 PUT_UINT32_LE( ctx
->state
[2], output
, 8 );
383 PUT_UINT32_LE( ctx
->state
[3], output
, 12 );
388 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
389 void mbedtls_md4_finish( mbedtls_md4_context
*ctx
,
390 unsigned char output
[16] )
392 mbedtls_md4_finish_ret( ctx
, output
);
396 #endif /* !MBEDTLS_MD4_ALT */
399 * output = MD4( input buffer )
401 int mbedtls_md4_ret( const unsigned char *input
,
403 unsigned char output
[16] )
406 mbedtls_md4_context ctx
;
408 mbedtls_md4_init( &ctx
);
410 if( ( ret
= mbedtls_md4_starts_ret( &ctx
) ) != 0 )
413 if( ( ret
= mbedtls_md4_update_ret( &ctx
, input
, ilen
) ) != 0 )
416 if( ( ret
= mbedtls_md4_finish_ret( &ctx
, output
) ) != 0 )
420 mbedtls_md4_free( &ctx
);
425 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
426 void mbedtls_md4( const unsigned char *input
,
428 unsigned char output
[16] )
430 mbedtls_md4_ret( input
, ilen
, output
);
434 #if defined(MBEDTLS_SELF_TEST)
437 * RFC 1320 test vectors
439 static const unsigned char md4_test_str
[7][81] =
444 { "message digest" },
445 { "abcdefghijklmnopqrstuvwxyz" },
446 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
447 { "12345678901234567890123456789012345678901234567890123456789012"
448 "345678901234567890" }
451 static const size_t md4_test_strlen
[7] =
453 0, 1, 3, 14, 26, 62, 80
456 static const unsigned char md4_test_sum
[7][16] =
458 { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31,
459 0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 },
460 { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46,
461 0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 },
462 { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52,
463 0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D },
464 { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8,
465 0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B },
466 { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD,
467 0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 },
468 { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35,
469 0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 },
470 { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19,
471 0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 }
477 int mbedtls_md4_self_test( int verbose
)
480 unsigned char md4sum
[16];
482 for( i
= 0; i
< 7; i
++ )
485 mbedtls_printf( " MD4 test #%d: ", i
+ 1 );
487 ret
= mbedtls_md4_ret( md4_test_str
[i
], md4_test_strlen
[i
], md4sum
);
491 if( memcmp( md4sum
, md4_test_sum
[i
], 16 ) != 0 )
498 mbedtls_printf( "passed\n" );
502 mbedtls_printf( "\n" );
508 mbedtls_printf( "failed\n" );
513 #endif /* MBEDTLS_SELF_TEST */
515 #endif /* MBEDTLS_MD4_C */