2 * RFC 1186/1320 compliant MD4 implementation
\r
4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
\r
5 * SPDX-License-Identifier: Apache-2.0
\r
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
\r
8 * not use this file except in compliance with the License.
\r
9 * You may obtain a copy of the License at
\r
11 * http://www.apache.org/licenses/LICENSE-2.0
\r
13 * Unless required by applicable law or agreed to in writing, software
\r
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
\r
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
16 * See the License for the specific language governing permissions and
\r
17 * limitations under the License.
\r
19 * This file is part of mbed TLS (https://tls.mbed.org)
\r
22 * The MD4 algorithm was designed by Ron Rivest in 1990.
\r
24 * http://www.ietf.org/rfc/rfc1186.txt
\r
25 * http://www.ietf.org/rfc/rfc1320.txt
\r
28 #if !defined(MBEDTLS_CONFIG_FILE)
\r
29 #include "mbedtls/config.h"
\r
31 #include MBEDTLS_CONFIG_FILE
\r
34 #if defined(MBEDTLS_MD4_C)
\r
36 #include "mbedtls/md4.h"
\r
37 #include "mbedtls/platform_util.h"
\r
41 #if defined(MBEDTLS_SELF_TEST)
\r
42 #if defined(MBEDTLS_PLATFORM_C)
\r
43 #include "mbedtls/platform.h"
\r
46 #define mbedtls_printf printf
\r
47 #endif /* MBEDTLS_PLATFORM_C */
\r
48 #endif /* MBEDTLS_SELF_TEST */
\r
50 #if !defined(MBEDTLS_MD4_ALT)
\r
53 * 32-bit integer manipulation macros (little endian)
\r
55 #ifndef GET_UINT32_LE
\r
56 #define GET_UINT32_LE(n,b,i) \
\r
58 (n) = ( (uint32_t) (b)[(i) ] ) \
\r
59 | ( (uint32_t) (b)[(i) + 1] << 8 ) \
\r
60 | ( (uint32_t) (b)[(i) + 2] << 16 ) \
\r
61 | ( (uint32_t) (b)[(i) + 3] << 24 ); \
\r
65 #ifndef PUT_UINT32_LE
\r
66 #define PUT_UINT32_LE(n,b,i) \
\r
68 (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \
\r
69 (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \
\r
70 (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \
\r
71 (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \
\r
75 void mbedtls_md4_init( mbedtls_md4_context *ctx )
\r
77 memset( ctx, 0, sizeof( mbedtls_md4_context ) );
\r
80 void mbedtls_md4_free( mbedtls_md4_context *ctx )
\r
85 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md4_context ) );
\r
88 void mbedtls_md4_clone( mbedtls_md4_context *dst,
\r
89 const mbedtls_md4_context *src )
\r
97 int mbedtls_md4_starts_ret( mbedtls_md4_context *ctx )
\r
102 ctx->state[0] = 0x67452301;
\r
103 ctx->state[1] = 0xEFCDAB89;
\r
104 ctx->state[2] = 0x98BADCFE;
\r
105 ctx->state[3] = 0x10325476;
\r
110 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
\r
111 void mbedtls_md4_starts( mbedtls_md4_context *ctx )
\r
113 mbedtls_md4_starts_ret( ctx );
\r
117 #if !defined(MBEDTLS_MD4_PROCESS_ALT)
\r
118 int mbedtls_internal_md4_process( mbedtls_md4_context *ctx,
\r
119 const unsigned char data[64] )
\r
121 uint32_t X[16], A, B, C, D;
\r
123 GET_UINT32_LE( X[ 0], data, 0 );
\r
124 GET_UINT32_LE( X[ 1], data, 4 );
\r
125 GET_UINT32_LE( X[ 2], data, 8 );
\r
126 GET_UINT32_LE( X[ 3], data, 12 );
\r
127 GET_UINT32_LE( X[ 4], data, 16 );
\r
128 GET_UINT32_LE( X[ 5], data, 20 );
\r
129 GET_UINT32_LE( X[ 6], data, 24 );
\r
130 GET_UINT32_LE( X[ 7], data, 28 );
\r
131 GET_UINT32_LE( X[ 8], data, 32 );
\r
132 GET_UINT32_LE( X[ 9], data, 36 );
\r
133 GET_UINT32_LE( X[10], data, 40 );
\r
134 GET_UINT32_LE( X[11], data, 44 );
\r
135 GET_UINT32_LE( X[12], data, 48 );
\r
136 GET_UINT32_LE( X[13], data, 52 );
\r
137 GET_UINT32_LE( X[14], data, 56 );
\r
138 GET_UINT32_LE( X[15], data, 60 );
\r
140 #define S(x,n) (((x) << (n)) | (((x) & 0xFFFFFFFF) >> (32 - (n))))
\r
147 #define F(x, y, z) (((x) & (y)) | ((~(x)) & (z)))
\r
148 #define P(a,b,c,d,x,s) \
\r
151 (a) += F((b),(c),(d)) + (x); \
\r
152 (a) = S((a),(s)); \
\r
156 P( A, B, C, D, X[ 0], 3 );
\r
157 P( D, A, B, C, X[ 1], 7 );
\r
158 P( C, D, A, B, X[ 2], 11 );
\r
159 P( B, C, D, A, X[ 3], 19 );
\r
160 P( A, B, C, D, X[ 4], 3 );
\r
161 P( D, A, B, C, X[ 5], 7 );
\r
162 P( C, D, A, B, X[ 6], 11 );
\r
163 P( B, C, D, A, X[ 7], 19 );
\r
164 P( A, B, C, D, X[ 8], 3 );
\r
165 P( D, A, B, C, X[ 9], 7 );
\r
166 P( C, D, A, B, X[10], 11 );
\r
167 P( B, C, D, A, X[11], 19 );
\r
168 P( A, B, C, D, X[12], 3 );
\r
169 P( D, A, B, C, X[13], 7 );
\r
170 P( C, D, A, B, X[14], 11 );
\r
171 P( B, C, D, A, X[15], 19 );
\r
176 #define F(x,y,z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
\r
177 #define P(a,b,c,d,x,s) \
\r
180 (a) += F((b),(c),(d)) + (x) + 0x5A827999; \
\r
181 (a) = S((a),(s)); \
\r
184 P( A, B, C, D, X[ 0], 3 );
\r
185 P( D, A, B, C, X[ 4], 5 );
\r
186 P( C, D, A, B, X[ 8], 9 );
\r
187 P( B, C, D, A, X[12], 13 );
\r
188 P( A, B, C, D, X[ 1], 3 );
\r
189 P( D, A, B, C, X[ 5], 5 );
\r
190 P( C, D, A, B, X[ 9], 9 );
\r
191 P( B, C, D, A, X[13], 13 );
\r
192 P( A, B, C, D, X[ 2], 3 );
\r
193 P( D, A, B, C, X[ 6], 5 );
\r
194 P( C, D, A, B, X[10], 9 );
\r
195 P( B, C, D, A, X[14], 13 );
\r
196 P( A, B, C, D, X[ 3], 3 );
\r
197 P( D, A, B, C, X[ 7], 5 );
\r
198 P( C, D, A, B, X[11], 9 );
\r
199 P( B, C, D, A, X[15], 13 );
\r
204 #define F(x,y,z) ((x) ^ (y) ^ (z))
\r
205 #define P(a,b,c,d,x,s) \
\r
208 (a) += F((b),(c),(d)) + (x) + 0x6ED9EBA1; \
\r
209 (a) = S((a),(s)); \
\r
212 P( A, B, C, D, X[ 0], 3 );
\r
213 P( D, A, B, C, X[ 8], 9 );
\r
214 P( C, D, A, B, X[ 4], 11 );
\r
215 P( B, C, D, A, X[12], 15 );
\r
216 P( A, B, C, D, X[ 2], 3 );
\r
217 P( D, A, B, C, X[10], 9 );
\r
218 P( C, D, A, B, X[ 6], 11 );
\r
219 P( B, C, D, A, X[14], 15 );
\r
220 P( A, B, C, D, X[ 1], 3 );
\r
221 P( D, A, B, C, X[ 9], 9 );
\r
222 P( C, D, A, B, X[ 5], 11 );
\r
223 P( B, C, D, A, X[13], 15 );
\r
224 P( A, B, C, D, X[ 3], 3 );
\r
225 P( D, A, B, C, X[11], 9 );
\r
226 P( C, D, A, B, X[ 7], 11 );
\r
227 P( B, C, D, A, X[15], 15 );
\r
232 ctx->state[0] += A;
\r
233 ctx->state[1] += B;
\r
234 ctx->state[2] += C;
\r
235 ctx->state[3] += D;
\r
240 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
\r
241 void mbedtls_md4_process( mbedtls_md4_context *ctx,
\r
242 const unsigned char data[64] )
\r
244 mbedtls_internal_md4_process( ctx, data );
\r
247 #endif /* !MBEDTLS_MD4_PROCESS_ALT */
\r
250 * MD4 process buffer
\r
252 int mbedtls_md4_update_ret( mbedtls_md4_context *ctx,
\r
253 const unsigned char *input,
\r
263 left = ctx->total[0] & 0x3F;
\r
266 ctx->total[0] += (uint32_t) ilen;
\r
267 ctx->total[0] &= 0xFFFFFFFF;
\r
269 if( ctx->total[0] < (uint32_t) ilen )
\r
272 if( left && ilen >= fill )
\r
274 memcpy( (void *) (ctx->buffer + left),
\r
275 (void *) input, fill );
\r
277 if( ( ret = mbedtls_internal_md4_process( ctx, ctx->buffer ) ) != 0 )
\r
285 while( ilen >= 64 )
\r
287 if( ( ret = mbedtls_internal_md4_process( ctx, input ) ) != 0 )
\r
296 memcpy( (void *) (ctx->buffer + left),
\r
297 (void *) input, ilen );
\r
303 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
\r
304 void mbedtls_md4_update( mbedtls_md4_context *ctx,
\r
305 const unsigned char *input,
\r
308 mbedtls_md4_update_ret( ctx, input, ilen );
\r
312 static const unsigned char md4_padding[64] =
\r
314 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
\r
315 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
\r
316 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
\r
317 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
\r
323 int mbedtls_md4_finish_ret( mbedtls_md4_context *ctx,
\r
324 unsigned char output[16] )
\r
327 uint32_t last, padn;
\r
328 uint32_t high, low;
\r
329 unsigned char msglen[8];
\r
331 high = ( ctx->total[0] >> 29 )
\r
332 | ( ctx->total[1] << 3 );
\r
333 low = ( ctx->total[0] << 3 );
\r
335 PUT_UINT32_LE( low, msglen, 0 );
\r
336 PUT_UINT32_LE( high, msglen, 4 );
\r
338 last = ctx->total[0] & 0x3F;
\r
339 padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
\r
341 ret = mbedtls_md4_update_ret( ctx, (unsigned char *)md4_padding, padn );
\r
345 if( ( ret = mbedtls_md4_update_ret( ctx, msglen, 8 ) ) != 0 )
\r
349 PUT_UINT32_LE( ctx->state[0], output, 0 );
\r
350 PUT_UINT32_LE( ctx->state[1], output, 4 );
\r
351 PUT_UINT32_LE( ctx->state[2], output, 8 );
\r
352 PUT_UINT32_LE( ctx->state[3], output, 12 );
\r
357 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
\r
358 void mbedtls_md4_finish( mbedtls_md4_context *ctx,
\r
359 unsigned char output[16] )
\r
361 mbedtls_md4_finish_ret( ctx, output );
\r
365 #endif /* !MBEDTLS_MD4_ALT */
\r
368 * output = MD4( input buffer )
\r
370 int mbedtls_md4_ret( const unsigned char *input,
\r
372 unsigned char output[16] )
\r
375 mbedtls_md4_context ctx;
\r
377 mbedtls_md4_init( &ctx );
\r
379 if( ( ret = mbedtls_md4_starts_ret( &ctx ) ) != 0 )
\r
382 if( ( ret = mbedtls_md4_update_ret( &ctx, input, ilen ) ) != 0 )
\r
385 if( ( ret = mbedtls_md4_finish_ret( &ctx, output ) ) != 0 )
\r
389 mbedtls_md4_free( &ctx );
\r
394 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
\r
395 void mbedtls_md4( const unsigned char *input,
\r
397 unsigned char output[16] )
\r
399 mbedtls_md4_ret( input, ilen, output );
\r
403 #if defined(MBEDTLS_SELF_TEST)
\r
406 * RFC 1320 test vectors
\r
408 static const unsigned char md4_test_str[7][81] =
\r
413 { "message digest" },
\r
414 { "abcdefghijklmnopqrstuvwxyz" },
\r
415 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
\r
416 { "12345678901234567890123456789012345678901234567890123456789012"
\r
417 "345678901234567890" }
\r
420 static const size_t md4_test_strlen[7] =
\r
422 0, 1, 3, 14, 26, 62, 80
\r
425 static const unsigned char md4_test_sum[7][16] =
\r
427 { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31,
\r
428 0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 },
\r
429 { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46,
\r
430 0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 },
\r
431 { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52,
\r
432 0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D },
\r
433 { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8,
\r
434 0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B },
\r
435 { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD,
\r
436 0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 },
\r
437 { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35,
\r
438 0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 },
\r
439 { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19,
\r
440 0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 }
\r
446 int mbedtls_md4_self_test( int verbose )
\r
449 unsigned char md4sum[16];
\r
451 for( i = 0; i < 7; i++ )
\r
454 mbedtls_printf( " MD4 test #%d: ", i + 1 );
\r
456 ret = mbedtls_md4_ret( md4_test_str[i], md4_test_strlen[i], md4sum );
\r
460 if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 )
\r
467 mbedtls_printf( "passed\n" );
\r
471 mbedtls_printf( "\n" );
\r
477 mbedtls_printf( "failed\n" );
\r
482 #endif /* MBEDTLS_SELF_TEST */
\r
484 #endif /* MBEDTLS_MD4_C */
\r