11a77e3ae4d0e87e2c0006fd3d1bfb0ff97ead30
2 * RFC 1186/1320 compliant MD4 implementation
4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5 * SPDX-License-Identifier: Apache-2.0
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
19 * This file is part of mbed TLS (https://tls.mbed.org)
22 * The MD4 algorithm was designed by Ron Rivest in 1990.
24 * http://www.ietf.org/rfc/rfc1186.txt
25 * http://www.ietf.org/rfc/rfc1320.txt
28 #if !defined(MBEDTLS_CONFIG_FILE)
29 #include "mbedtls/config.h"
31 #include MBEDTLS_CONFIG_FILE
34 #if defined(MBEDTLS_MD4_C)
36 #include "mbedtls/md4.h"
40 #if defined(MBEDTLS_SELF_TEST)
41 #if defined(MBEDTLS_PLATFORM_C)
42 #include "mbedtls/platform.h"
45 #define mbedtls_printf printf
46 #endif /* MBEDTLS_PLATFORM_C */
47 #endif /* MBEDTLS_SELF_TEST */
49 #if !defined(MBEDTLS_MD4_ALT)
51 /* Implementation that should never be optimized out by the compiler */
52 static void mbedtls_zeroize( void *v
, size_t n
) {
53 volatile unsigned char *p
= v
; while( n
-- ) *p
++ = 0;
57 * 32-bit integer manipulation macros (little endian)
60 #define GET_UINT32_LE(n,b,i) \
62 (n) = ( (uint32_t) (b)[(i) ] ) \
63 | ( (uint32_t) (b)[(i) + 1] << 8 ) \
64 | ( (uint32_t) (b)[(i) + 2] << 16 ) \
65 | ( (uint32_t) (b)[(i) + 3] << 24 ); \
70 #define PUT_UINT32_LE(n,b,i) \
72 (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \
73 (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \
74 (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \
75 (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \
79 void mbedtls_md4_init( mbedtls_md4_context
*ctx
)
81 memset( ctx
, 0, sizeof( mbedtls_md4_context
) );
84 void mbedtls_md4_free( mbedtls_md4_context
*ctx
)
89 mbedtls_zeroize( ctx
, sizeof( mbedtls_md4_context
) );
92 void mbedtls_md4_clone( mbedtls_md4_context
*dst
,
93 const mbedtls_md4_context
*src
)
101 void mbedtls_md4_starts( mbedtls_md4_context
*ctx
)
106 ctx
->state
[0] = 0x67452301;
107 ctx
->state
[1] = 0xEFCDAB89;
108 ctx
->state
[2] = 0x98BADCFE;
109 ctx
->state
[3] = 0x10325476;
112 #if !defined(MBEDTLS_MD4_PROCESS_ALT)
113 void mbedtls_md4_process( mbedtls_md4_context
*ctx
, const unsigned char data
[64] )
115 uint32_t X
[16], A
, B
, C
, D
;
117 GET_UINT32_LE( X
[ 0], data
, 0 );
118 GET_UINT32_LE( X
[ 1], data
, 4 );
119 GET_UINT32_LE( X
[ 2], data
, 8 );
120 GET_UINT32_LE( X
[ 3], data
, 12 );
121 GET_UINT32_LE( X
[ 4], data
, 16 );
122 GET_UINT32_LE( X
[ 5], data
, 20 );
123 GET_UINT32_LE( X
[ 6], data
, 24 );
124 GET_UINT32_LE( X
[ 7], data
, 28 );
125 GET_UINT32_LE( X
[ 8], data
, 32 );
126 GET_UINT32_LE( X
[ 9], data
, 36 );
127 GET_UINT32_LE( X
[10], data
, 40 );
128 GET_UINT32_LE( X
[11], data
, 44 );
129 GET_UINT32_LE( X
[12], data
, 48 );
130 GET_UINT32_LE( X
[13], data
, 52 );
131 GET_UINT32_LE( X
[14], data
, 56 );
132 GET_UINT32_LE( X
[15], data
, 60 );
134 #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
141 #define F(x, y, z) ((x & y) | ((~x) & z))
142 #define P(a,b,c,d,x,s) { a += F(b,c,d) + x; a = S(a,s); }
144 P( A
, B
, C
, D
, X
[ 0], 3 );
145 P( D
, A
, B
, C
, X
[ 1], 7 );
146 P( C
, D
, A
, B
, X
[ 2], 11 );
147 P( B
, C
, D
, A
, X
[ 3], 19 );
148 P( A
, B
, C
, D
, X
[ 4], 3 );
149 P( D
, A
, B
, C
, X
[ 5], 7 );
150 P( C
, D
, A
, B
, X
[ 6], 11 );
151 P( B
, C
, D
, A
, X
[ 7], 19 );
152 P( A
, B
, C
, D
, X
[ 8], 3 );
153 P( D
, A
, B
, C
, X
[ 9], 7 );
154 P( C
, D
, A
, B
, X
[10], 11 );
155 P( B
, C
, D
, A
, X
[11], 19 );
156 P( A
, B
, C
, D
, X
[12], 3 );
157 P( D
, A
, B
, C
, X
[13], 7 );
158 P( C
, D
, A
, B
, X
[14], 11 );
159 P( B
, C
, D
, A
, X
[15], 19 );
164 #define F(x,y,z) ((x & y) | (x & z) | (y & z))
165 #define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x5A827999; a = S(a,s); }
167 P( A
, B
, C
, D
, X
[ 0], 3 );
168 P( D
, A
, B
, C
, X
[ 4], 5 );
169 P( C
, D
, A
, B
, X
[ 8], 9 );
170 P( B
, C
, D
, A
, X
[12], 13 );
171 P( A
, B
, C
, D
, X
[ 1], 3 );
172 P( D
, A
, B
, C
, X
[ 5], 5 );
173 P( C
, D
, A
, B
, X
[ 9], 9 );
174 P( B
, C
, D
, A
, X
[13], 13 );
175 P( A
, B
, C
, D
, X
[ 2], 3 );
176 P( D
, A
, B
, C
, X
[ 6], 5 );
177 P( C
, D
, A
, B
, X
[10], 9 );
178 P( B
, C
, D
, A
, X
[14], 13 );
179 P( A
, B
, C
, D
, X
[ 3], 3 );
180 P( D
, A
, B
, C
, X
[ 7], 5 );
181 P( C
, D
, A
, B
, X
[11], 9 );
182 P( B
, C
, D
, A
, X
[15], 13 );
187 #define F(x,y,z) (x ^ y ^ z)
188 #define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x6ED9EBA1; a = S(a,s); }
190 P( A
, B
, C
, D
, X
[ 0], 3 );
191 P( D
, A
, B
, C
, X
[ 8], 9 );
192 P( C
, D
, A
, B
, X
[ 4], 11 );
193 P( B
, C
, D
, A
, X
[12], 15 );
194 P( A
, B
, C
, D
, X
[ 2], 3 );
195 P( D
, A
, B
, C
, X
[10], 9 );
196 P( C
, D
, A
, B
, X
[ 6], 11 );
197 P( B
, C
, D
, A
, X
[14], 15 );
198 P( A
, B
, C
, D
, X
[ 1], 3 );
199 P( D
, A
, B
, C
, X
[ 9], 9 );
200 P( C
, D
, A
, B
, X
[ 5], 11 );
201 P( B
, C
, D
, A
, X
[13], 15 );
202 P( A
, B
, C
, D
, X
[ 3], 3 );
203 P( D
, A
, B
, C
, X
[11], 9 );
204 P( C
, D
, A
, B
, X
[ 7], 11 );
205 P( B
, C
, D
, A
, X
[15], 15 );
215 #endif /* !MBEDTLS_MD4_PROCESS_ALT */
220 void mbedtls_md4_update( mbedtls_md4_context
*ctx
, const unsigned char *input
, size_t ilen
)
228 left
= ctx
->total
[0] & 0x3F;
231 ctx
->total
[0] += (uint32_t) ilen
;
232 ctx
->total
[0] &= 0xFFFFFFFF;
234 if( ctx
->total
[0] < (uint32_t) ilen
)
237 if( left
&& ilen
>= fill
)
239 memcpy( (void *) (ctx
->buffer
+ left
),
240 (void *) input
, fill
);
241 mbedtls_md4_process( ctx
, ctx
->buffer
);
249 mbedtls_md4_process( ctx
, input
);
256 memcpy( (void *) (ctx
->buffer
+ left
),
257 (void *) input
, ilen
);
261 static const unsigned char md4_padding
[64] =
263 0x80, 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 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
272 void mbedtls_md4_finish( mbedtls_md4_context
*ctx
, unsigned char output
[16] )
276 unsigned char msglen
[8];
278 high
= ( ctx
->total
[0] >> 29 )
279 | ( ctx
->total
[1] << 3 );
280 low
= ( ctx
->total
[0] << 3 );
282 PUT_UINT32_LE( low
, msglen
, 0 );
283 PUT_UINT32_LE( high
, msglen
, 4 );
285 last
= ctx
->total
[0] & 0x3F;
286 padn
= ( last
< 56 ) ? ( 56 - last
) : ( 120 - last
);
288 mbedtls_md4_update( ctx
, (unsigned char *) md4_padding
, padn
);
289 mbedtls_md4_update( ctx
, msglen
, 8 );
291 PUT_UINT32_LE( ctx
->state
[0], output
, 0 );
292 PUT_UINT32_LE( ctx
->state
[1], output
, 4 );
293 PUT_UINT32_LE( ctx
->state
[2], output
, 8 );
294 PUT_UINT32_LE( ctx
->state
[3], output
, 12 );
297 #endif /* !MBEDTLS_MD4_ALT */
300 * output = MD4( input buffer )
302 void mbedtls_md4( const unsigned char *input
, size_t ilen
, unsigned char output
[16] )
304 mbedtls_md4_context ctx
;
306 mbedtls_md4_init( &ctx
);
307 mbedtls_md4_starts( &ctx
);
308 mbedtls_md4_update( &ctx
, input
, ilen
);
309 mbedtls_md4_finish( &ctx
, output
);
310 mbedtls_md4_free( &ctx
);
313 #if defined(MBEDTLS_SELF_TEST)
316 * RFC 1320 test vectors
318 static const char md4_test_str
[7][81] =
323 { "message digest" },
324 { "abcdefghijklmnopqrstuvwxyz" },
325 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
326 { "12345678901234567890123456789012345678901234567890123456789012" \
327 "345678901234567890" }
330 static const unsigned char md4_test_sum
[7][16] =
332 { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31,
333 0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 },
334 { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46,
335 0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 },
336 { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52,
337 0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D },
338 { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8,
339 0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B },
340 { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD,
341 0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 },
342 { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35,
343 0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 },
344 { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19,
345 0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 }
351 int mbedtls_md4_self_test( int verbose
)
354 unsigned char md4sum
[16];
356 for( i
= 0; i
< 7; i
++ )
359 mbedtls_printf( " MD4 test #%d: ", i
+ 1 );
361 mbedtls_md4( (unsigned char *) md4_test_str
[i
],
362 strlen( md4_test_str
[i
] ), md4sum
);
364 if( memcmp( md4sum
, md4_test_sum
[i
], 16 ) != 0 )
367 mbedtls_printf( "failed\n" );
373 mbedtls_printf( "passed\n" );
377 mbedtls_printf( "\n" );
382 #endif /* MBEDTLS_SELF_TEST */
384 #endif /* MBEDTLS_MD4_C */