2 * RFC 1186/1320 compliant MD4 implementation
4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5 * SPDX-License-Identifier: GPL-2.0
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 * This file is part of mbed TLS (https://tls.mbed.org)
24 * The MD4 algorithm was designed by Ron Rivest in 1990.
26 * http://www.ietf.org/rfc/rfc1186.txt
27 * http://www.ietf.org/rfc/rfc1320.txt
30 #if !defined(MBEDTLS_CONFIG_FILE)
31 #include "mbedtls/config.h"
33 #include MBEDTLS_CONFIG_FILE
36 #if defined(MBEDTLS_MD4_C)
38 #include "mbedtls/md4.h"
42 #if defined(MBEDTLS_SELF_TEST)
43 #if defined(MBEDTLS_PLATFORM_C)
44 #include "mbedtls/platform.h"
47 #define mbedtls_printf printf
48 #endif /* MBEDTLS_PLATFORM_C */
49 #endif /* MBEDTLS_SELF_TEST */
51 #if !defined(MBEDTLS_MD4_ALT)
53 /* Implementation that should never be optimized out by the compiler */
54 static void mbedtls_zeroize( void *v
, size_t n
) {
55 volatile unsigned char *p
= v
; while( n
-- ) *p
++ = 0;
59 * 32-bit integer manipulation macros (little endian)
62 #define GET_UINT32_LE(n,b,i) \
64 (n) = ( (uint32_t) (b)[(i) ] ) \
65 | ( (uint32_t) (b)[(i) + 1] << 8 ) \
66 | ( (uint32_t) (b)[(i) + 2] << 16 ) \
67 | ( (uint32_t) (b)[(i) + 3] << 24 ); \
72 #define PUT_UINT32_LE(n,b,i) \
74 (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \
75 (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \
76 (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \
77 (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \
81 void mbedtls_md4_init( mbedtls_md4_context
*ctx
)
83 memset( ctx
, 0, sizeof( mbedtls_md4_context
) );
86 void mbedtls_md4_free( mbedtls_md4_context
*ctx
)
91 mbedtls_zeroize( ctx
, sizeof( mbedtls_md4_context
) );
94 void mbedtls_md4_clone( mbedtls_md4_context
*dst
,
95 const mbedtls_md4_context
*src
)
103 void mbedtls_md4_starts( mbedtls_md4_context
*ctx
)
108 ctx
->state
[0] = 0x67452301;
109 ctx
->state
[1] = 0xEFCDAB89;
110 ctx
->state
[2] = 0x98BADCFE;
111 ctx
->state
[3] = 0x10325476;
114 #if !defined(MBEDTLS_MD4_PROCESS_ALT)
115 void mbedtls_md4_process( mbedtls_md4_context
*ctx
, const unsigned char data
[64] )
117 uint32_t X
[16], A
, B
, C
, D
;
119 GET_UINT32_LE( X
[ 0], data
, 0 );
120 GET_UINT32_LE( X
[ 1], data
, 4 );
121 GET_UINT32_LE( X
[ 2], data
, 8 );
122 GET_UINT32_LE( X
[ 3], data
, 12 );
123 GET_UINT32_LE( X
[ 4], data
, 16 );
124 GET_UINT32_LE( X
[ 5], data
, 20 );
125 GET_UINT32_LE( X
[ 6], data
, 24 );
126 GET_UINT32_LE( X
[ 7], data
, 28 );
127 GET_UINT32_LE( X
[ 8], data
, 32 );
128 GET_UINT32_LE( X
[ 9], data
, 36 );
129 GET_UINT32_LE( X
[10], data
, 40 );
130 GET_UINT32_LE( X
[11], data
, 44 );
131 GET_UINT32_LE( X
[12], data
, 48 );
132 GET_UINT32_LE( X
[13], data
, 52 );
133 GET_UINT32_LE( X
[14], data
, 56 );
134 GET_UINT32_LE( X
[15], data
, 60 );
136 #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
143 #define F(x, y, z) ((x & y) | ((~x) & z))
144 #define P(a,b,c,d,x,s) { a += F(b,c,d) + x; a = S(a,s); }
146 P( A
, B
, C
, D
, X
[ 0], 3 );
147 P( D
, A
, B
, C
, X
[ 1], 7 );
148 P( C
, D
, A
, B
, X
[ 2], 11 );
149 P( B
, C
, D
, A
, X
[ 3], 19 );
150 P( A
, B
, C
, D
, X
[ 4], 3 );
151 P( D
, A
, B
, C
, X
[ 5], 7 );
152 P( C
, D
, A
, B
, X
[ 6], 11 );
153 P( B
, C
, D
, A
, X
[ 7], 19 );
154 P( A
, B
, C
, D
, X
[ 8], 3 );
155 P( D
, A
, B
, C
, X
[ 9], 7 );
156 P( C
, D
, A
, B
, X
[10], 11 );
157 P( B
, C
, D
, A
, X
[11], 19 );
158 P( A
, B
, C
, D
, X
[12], 3 );
159 P( D
, A
, B
, C
, X
[13], 7 );
160 P( C
, D
, A
, B
, X
[14], 11 );
161 P( B
, C
, D
, A
, X
[15], 19 );
166 #define F(x,y,z) ((x & y) | (x & z) | (y & z))
167 #define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x5A827999; a = S(a,s); }
169 P( A
, B
, C
, D
, X
[ 0], 3 );
170 P( D
, A
, B
, C
, X
[ 4], 5 );
171 P( C
, D
, A
, B
, X
[ 8], 9 );
172 P( B
, C
, D
, A
, X
[12], 13 );
173 P( A
, B
, C
, D
, X
[ 1], 3 );
174 P( D
, A
, B
, C
, X
[ 5], 5 );
175 P( C
, D
, A
, B
, X
[ 9], 9 );
176 P( B
, C
, D
, A
, X
[13], 13 );
177 P( A
, B
, C
, D
, X
[ 2], 3 );
178 P( D
, A
, B
, C
, X
[ 6], 5 );
179 P( C
, D
, A
, B
, X
[10], 9 );
180 P( B
, C
, D
, A
, X
[14], 13 );
181 P( A
, B
, C
, D
, X
[ 3], 3 );
182 P( D
, A
, B
, C
, X
[ 7], 5 );
183 P( C
, D
, A
, B
, X
[11], 9 );
184 P( B
, C
, D
, A
, X
[15], 13 );
189 #define F(x,y,z) (x ^ y ^ z)
190 #define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x6ED9EBA1; a = S(a,s); }
192 P( A
, B
, C
, D
, X
[ 0], 3 );
193 P( D
, A
, B
, C
, X
[ 8], 9 );
194 P( C
, D
, A
, B
, X
[ 4], 11 );
195 P( B
, C
, D
, A
, X
[12], 15 );
196 P( A
, B
, C
, D
, X
[ 2], 3 );
197 P( D
, A
, B
, C
, X
[10], 9 );
198 P( C
, D
, A
, B
, X
[ 6], 11 );
199 P( B
, C
, D
, A
, X
[14], 15 );
200 P( A
, B
, C
, D
, X
[ 1], 3 );
201 P( D
, A
, B
, C
, X
[ 9], 9 );
202 P( C
, D
, A
, B
, X
[ 5], 11 );
203 P( B
, C
, D
, A
, X
[13], 15 );
204 P( A
, B
, C
, D
, X
[ 3], 3 );
205 P( D
, A
, B
, C
, X
[11], 9 );
206 P( C
, D
, A
, B
, X
[ 7], 11 );
207 P( B
, C
, D
, A
, X
[15], 15 );
217 #endif /* !MBEDTLS_MD4_PROCESS_ALT */
222 void mbedtls_md4_update( mbedtls_md4_context
*ctx
, const unsigned char *input
, size_t ilen
)
230 left
= ctx
->total
[0] & 0x3F;
233 ctx
->total
[0] += (uint32_t) ilen
;
234 ctx
->total
[0] &= 0xFFFFFFFF;
236 if( ctx
->total
[0] < (uint32_t) ilen
)
239 if( left
&& ilen
>= fill
)
241 memcpy( (void *) (ctx
->buffer
+ left
),
242 (void *) input
, fill
);
243 mbedtls_md4_process( ctx
, ctx
->buffer
);
251 mbedtls_md4_process( ctx
, input
);
258 memcpy( (void *) (ctx
->buffer
+ left
),
259 (void *) input
, ilen
);
263 static const unsigned char md4_padding
[64] =
265 0x80, 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 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
274 void mbedtls_md4_finish( mbedtls_md4_context
*ctx
, unsigned char output
[16] )
278 unsigned char msglen
[8];
280 high
= ( ctx
->total
[0] >> 29 )
281 | ( ctx
->total
[1] << 3 );
282 low
= ( ctx
->total
[0] << 3 );
284 PUT_UINT32_LE( low
, msglen
, 0 );
285 PUT_UINT32_LE( high
, msglen
, 4 );
287 last
= ctx
->total
[0] & 0x3F;
288 padn
= ( last
< 56 ) ? ( 56 - last
) : ( 120 - last
);
290 mbedtls_md4_update( ctx
, (unsigned char *) md4_padding
, padn
);
291 mbedtls_md4_update( ctx
, msglen
, 8 );
293 PUT_UINT32_LE( ctx
->state
[0], output
, 0 );
294 PUT_UINT32_LE( ctx
->state
[1], output
, 4 );
295 PUT_UINT32_LE( ctx
->state
[2], output
, 8 );
296 PUT_UINT32_LE( ctx
->state
[3], output
, 12 );
299 #endif /* !MBEDTLS_MD4_ALT */
302 * output = MD4( input buffer )
304 void mbedtls_md4( const unsigned char *input
, size_t ilen
, unsigned char output
[16] )
306 mbedtls_md4_context ctx
;
308 mbedtls_md4_init( &ctx
);
309 mbedtls_md4_starts( &ctx
);
310 mbedtls_md4_update( &ctx
, input
, ilen
);
311 mbedtls_md4_finish( &ctx
, output
);
312 mbedtls_md4_free( &ctx
);
315 #if defined(MBEDTLS_SELF_TEST)
318 * RFC 1320 test vectors
320 static const char md4_test_str
[7][81] =
325 { "message digest" },
326 { "abcdefghijklmnopqrstuvwxyz" },
327 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
328 { "12345678901234567890123456789012345678901234567890123456789012" \
329 "345678901234567890" }
332 static const unsigned char md4_test_sum
[7][16] =
334 { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31,
335 0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 },
336 { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46,
337 0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 },
338 { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52,
339 0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D },
340 { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8,
341 0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B },
342 { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD,
343 0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 },
344 { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35,
345 0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 },
346 { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19,
347 0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 }
353 int mbedtls_md4_self_test( int verbose
)
356 unsigned char md4sum
[16];
358 for( i
= 0; i
< 7; i
++ )
361 mbedtls_printf( " MD4 test #%d: ", i
+ 1 );
363 mbedtls_md4( (unsigned char *) md4_test_str
[i
],
364 strlen( md4_test_str
[i
] ), md4sum
);
366 if( memcmp( md4sum
, md4_test_sum
[i
], 16 ) != 0 )
369 mbedtls_printf( "failed\n" );
375 mbedtls_printf( "passed\n" );
379 mbedtls_printf( "\n" );
384 #endif /* MBEDTLS_SELF_TEST */
386 #endif /* MBEDTLS_MD4_C */