1 /*
2 * RFC 1186/1320 compliant MD4 implementation
3 *
4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5 * SPDX-License-Identifier: Apache-2.0
6 *
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
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
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.
18 *
19 * This file is part of mbed TLS (https://tls.mbed.org)
20 */
21 /*
22 * The MD4 algorithm was designed by Ron Rivest in 1990.
23 *
24 * http://www.ietf.org/rfc/rfc1186.txt
25 * http://www.ietf.org/rfc/rfc1320.txt
26 */
27
28 #if !defined(MBEDTLS_CONFIG_FILE)
29 #include "mbedtls/config.h"
30 #else
31 #include MBEDTLS_CONFIG_FILE
32 #endif
33
34 #if defined(MBEDTLS_MD4_C)
35
36 #include "mbedtls/md4.h"
37
38 #include <string.h>
39
40 #if defined(MBEDTLS_SELF_TEST)
41 #if defined(MBEDTLS_PLATFORM_C)
42 #include "mbedtls/platform.h"
43 #else
44 #include <stdio.h>
45 #define mbedtls_printf printf
46 #endif /* MBEDTLS_PLATFORM_C */
47 #endif /* MBEDTLS_SELF_TEST */
48
49 #if !defined(MBEDTLS_MD4_ALT)
50
51 /* Implementation that should never be optimized out by the compiler */
mbedtls_zeroize(void * v,size_t n)52 static void mbedtls_zeroize( void *v, size_t n ) {
53 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
54 }
55
56 /*
57 * 32-bit integer manipulation macros (little endian)
58 */
59 #ifndef GET_UINT32_LE
60 #define GET_UINT32_LE(n,b,i) \
61 { \
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 ); \
66 }
67 #endif
68
69 #ifndef PUT_UINT32_LE
70 #define PUT_UINT32_LE(n,b,i) \
71 { \
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 ); \
76 }
77 #endif
78
mbedtls_md4_init(mbedtls_md4_context * ctx)79 void mbedtls_md4_init( mbedtls_md4_context *ctx )
80 {
81 memset( ctx, 0, sizeof( mbedtls_md4_context ) );
82 }
83
mbedtls_md4_free(mbedtls_md4_context * ctx)84 void mbedtls_md4_free( mbedtls_md4_context *ctx )
85 {
86 if( ctx == NULL )
87 return;
88
89 mbedtls_zeroize( ctx, sizeof( mbedtls_md4_context ) );
90 }
91
mbedtls_md4_clone(mbedtls_md4_context * dst,const mbedtls_md4_context * src)92 void mbedtls_md4_clone( mbedtls_md4_context *dst,
93 const mbedtls_md4_context *src )
94 {
95 *dst = *src;
96 }
97
98 /*
99 * MD4 context setup
100 */
mbedtls_md4_starts(mbedtls_md4_context * ctx)101 void mbedtls_md4_starts( mbedtls_md4_context *ctx )
102 {
103 ctx->total[0] = 0;
104 ctx->total[1] = 0;
105
106 ctx->state[0] = 0x67452301;
107 ctx->state[1] = 0xEFCDAB89;
108 ctx->state[2] = 0x98BADCFE;
109 ctx->state[3] = 0x10325476;
110 }
111
112 #if !defined(MBEDTLS_MD4_PROCESS_ALT)
mbedtls_md4_process(mbedtls_md4_context * ctx,const unsigned char data[64])113 void mbedtls_md4_process( mbedtls_md4_context *ctx, const unsigned char data[64] )
114 {
115 uint32_t X[16], A, B, C, D;
116
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 );
133
134 #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
135
136 A = ctx->state[0];
137 B = ctx->state[1];
138 C = ctx->state[2];
139 D = ctx->state[3];
140
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); }
143
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 );
160
161 #undef P
162 #undef F
163
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); }
166
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 );
183
184 #undef P
185 #undef F
186
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); }
189
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 );
206
207 #undef F
208 #undef P
209
210 ctx->state[0] += A;
211 ctx->state[1] += B;
212 ctx->state[2] += C;
213 ctx->state[3] += D;
214 }
215 #endif /* !MBEDTLS_MD4_PROCESS_ALT */
216
217 /*
218 * MD4 process buffer
219 */
mbedtls_md4_update(mbedtls_md4_context * ctx,const unsigned char * input,size_t ilen)220 void mbedtls_md4_update( mbedtls_md4_context *ctx, const unsigned char *input, size_t ilen )
221 {
222 size_t fill;
223 uint32_t left;
224
225 if( ilen == 0 )
226 return;
227
228 left = ctx->total[0] & 0x3F;
229 fill = 64 - left;
230
231 ctx->total[0] += (uint32_t) ilen;
232 ctx->total[0] &= 0xFFFFFFFF;
233
234 if( ctx->total[0] < (uint32_t) ilen )
235 ctx->total[1]++;
236
237 if( left && ilen >= fill )
238 {
239 memcpy( (void *) (ctx->buffer + left),
240 (void *) input, fill );
241 mbedtls_md4_process( ctx, ctx->buffer );
242 input += fill;
243 ilen -= fill;
244 left = 0;
245 }
246
247 while( ilen >= 64 )
248 {
249 mbedtls_md4_process( ctx, input );
250 input += 64;
251 ilen -= 64;
252 }
253
254 if( ilen > 0 )
255 {
256 memcpy( (void *) (ctx->buffer + left),
257 (void *) input, ilen );
258 }
259 }
260
261 static const unsigned char md4_padding[64] =
262 {
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
267 };
268
269 /*
270 * MD4 final digest
271 */
mbedtls_md4_finish(mbedtls_md4_context * ctx,unsigned char output[16])272 void mbedtls_md4_finish( mbedtls_md4_context *ctx, unsigned char output[16] )
273 {
274 uint32_t last, padn;
275 uint32_t high, low;
276 unsigned char msglen[8];
277
278 high = ( ctx->total[0] >> 29 )
279 | ( ctx->total[1] << 3 );
280 low = ( ctx->total[0] << 3 );
281
282 PUT_UINT32_LE( low, msglen, 0 );
283 PUT_UINT32_LE( high, msglen, 4 );
284
285 last = ctx->total[0] & 0x3F;
286 padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
287
288 mbedtls_md4_update( ctx, (unsigned char *) md4_padding, padn );
289 mbedtls_md4_update( ctx, msglen, 8 );
290
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 );
295 }
296
297 #endif /* !MBEDTLS_MD4_ALT */
298
299 /*
300 * output = MD4( input buffer )
301 */
mbedtls_md4(const unsigned char * input,size_t ilen,unsigned char output[16])302 void mbedtls_md4( const unsigned char *input, size_t ilen, unsigned char output[16] )
303 {
304 mbedtls_md4_context ctx;
305
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 );
311 }
312
313 #if defined(MBEDTLS_SELF_TEST)
314
315 /*
316 * RFC 1320 test vectors
317 */
318 static const char md4_test_str[7][81] =
319 {
320 { "" },
321 { "a" },
322 { "abc" },
323 { "message digest" },
324 { "abcdefghijklmnopqrstuvwxyz" },
325 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
326 { "12345678901234567890123456789012345678901234567890123456789012" \
327 "345678901234567890" }
328 };
329
330 static const unsigned char md4_test_sum[7][16] =
331 {
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 }
346 };
347
348 /*
349 * Checkup routine
350 */
mbedtls_md4_self_test(int verbose)351 int mbedtls_md4_self_test( int verbose )
352 {
353 int i;
354 unsigned char md4sum[16];
355
356 for( i = 0; i < 7; i++ )
357 {
358 if( verbose != 0 )
359 mbedtls_printf( " MD4 test #%d: ", i + 1 );
360
361 mbedtls_md4( (unsigned char *) md4_test_str[i],
362 strlen( md4_test_str[i] ), md4sum );
363
364 if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 )
365 {
366 if( verbose != 0 )
367 mbedtls_printf( "failed\n" );
368
369 return( 1 );
370 }
371
372 if( verbose != 0 )
373 mbedtls_printf( "passed\n" );
374 }
375
376 if( verbose != 0 )
377 mbedtls_printf( "\n" );
378
379 return( 0 );
380 }
381
382 #endif /* MBEDTLS_SELF_TEST */
383
384 #endif /* MBEDTLS_MD4_C */
385