1 /*
2 * RFC 1186/1320 compliant MD4 implementation
3 *
4 * Copyright The Mbed TLS Contributors
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 /*
20 * The MD4 algorithm was designed by Ron Rivest in 1990.
21 *
22 * http://www.ietf.org/rfc/rfc1186.txt
23 * http://www.ietf.org/rfc/rfc1320.txt
24 */
25
26 #include "common.h"
27
28 #if defined(MBEDTLS_MD4_C)
29
30 #include "mbedtls/md4.h"
31 #include "mbedtls/platform_util.h"
32 #include "mbedtls/error.h"
33
34 #include <string.h>
35
36 #if defined(MBEDTLS_SELF_TEST)
37 #if defined(MBEDTLS_PLATFORM_C)
38 #include "mbedtls/platform.h"
39 #else
40 #include <stdio.h>
41 #define mbedtls_printf printf
42 #endif /* MBEDTLS_PLATFORM_C */
43 #endif /* MBEDTLS_SELF_TEST */
44
45 #if !defined(MBEDTLS_MD4_ALT)
46
47 /*
48 * 32-bit integer manipulation macros (little endian)
49 */
50 #ifndef GET_UINT32_LE
51 #define GET_UINT32_LE(n,b,i) \
52 { \
53 (n) = ( (uint32_t) (b)[(i) ] ) \
54 | ( (uint32_t) (b)[(i) + 1] << 8 ) \
55 | ( (uint32_t) (b)[(i) + 2] << 16 ) \
56 | ( (uint32_t) (b)[(i) + 3] << 24 ); \
57 }
58 #endif
59
60 #ifndef PUT_UINT32_LE
61 #define PUT_UINT32_LE(n,b,i) \
62 { \
63 (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \
64 (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \
65 (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \
66 (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \
67 }
68 #endif
69
mbedtls_md4_init(mbedtls_md4_context * ctx)70 void mbedtls_md4_init( mbedtls_md4_context *ctx )
71 {
72 memset( ctx, 0, sizeof( mbedtls_md4_context ) );
73 }
74
mbedtls_md4_free(mbedtls_md4_context * ctx)75 void mbedtls_md4_free( mbedtls_md4_context *ctx )
76 {
77 if( ctx == NULL )
78 return;
79
80 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md4_context ) );
81 }
82
mbedtls_md4_clone(mbedtls_md4_context * dst,const mbedtls_md4_context * src)83 void mbedtls_md4_clone( mbedtls_md4_context *dst,
84 const mbedtls_md4_context *src )
85 {
86 *dst = *src;
87 }
88
89 /*
90 * MD4 context setup
91 */
mbedtls_md4_starts_ret(mbedtls_md4_context * ctx)92 int mbedtls_md4_starts_ret( mbedtls_md4_context *ctx )
93 {
94 ctx->total[0] = 0;
95 ctx->total[1] = 0;
96
97 ctx->state[0] = 0x67452301;
98 ctx->state[1] = 0xEFCDAB89;
99 ctx->state[2] = 0x98BADCFE;
100 ctx->state[3] = 0x10325476;
101
102 return( 0 );
103 }
104
105 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
mbedtls_md4_starts(mbedtls_md4_context * ctx)106 void mbedtls_md4_starts( mbedtls_md4_context *ctx )
107 {
108 mbedtls_md4_starts_ret( ctx );
109 }
110 #endif
111
112 #if !defined(MBEDTLS_MD4_PROCESS_ALT)
mbedtls_internal_md4_process(mbedtls_md4_context * ctx,const unsigned char data[64])113 int mbedtls_internal_md4_process( mbedtls_md4_context *ctx,
114 const unsigned char data[64] )
115 {
116 struct
117 {
118 uint32_t X[16], A, B, C, D;
119 } local;
120
121 GET_UINT32_LE( local.X[ 0], data, 0 );
122 GET_UINT32_LE( local.X[ 1], data, 4 );
123 GET_UINT32_LE( local.X[ 2], data, 8 );
124 GET_UINT32_LE( local.X[ 3], data, 12 );
125 GET_UINT32_LE( local.X[ 4], data, 16 );
126 GET_UINT32_LE( local.X[ 5], data, 20 );
127 GET_UINT32_LE( local.X[ 6], data, 24 );
128 GET_UINT32_LE( local.X[ 7], data, 28 );
129 GET_UINT32_LE( local.X[ 8], data, 32 );
130 GET_UINT32_LE( local.X[ 9], data, 36 );
131 GET_UINT32_LE( local.X[10], data, 40 );
132 GET_UINT32_LE( local.X[11], data, 44 );
133 GET_UINT32_LE( local.X[12], data, 48 );
134 GET_UINT32_LE( local.X[13], data, 52 );
135 GET_UINT32_LE( local.X[14], data, 56 );
136 GET_UINT32_LE( local.X[15], data, 60 );
137
138 #define S(x,n) (((x) << (n)) | (((x) & 0xFFFFFFFF) >> (32 - (n))))
139
140 local.A = ctx->state[0];
141 local.B = ctx->state[1];
142 local.C = ctx->state[2];
143 local.D = ctx->state[3];
144
145 #define F(x, y, z) (((x) & (y)) | ((~(x)) & (z)))
146 #define P(a,b,c,d,x,s) \
147 do \
148 { \
149 (a) += F((b),(c),(d)) + (x); \
150 (a) = S((a),(s)); \
151 } while( 0 )
152
153
154 P( local.A, local.B, local.C, local.D, local.X[ 0], 3 );
155 P( local.D, local.A, local.B, local.C, local.X[ 1], 7 );
156 P( local.C, local.D, local.A, local.B, local.X[ 2], 11 );
157 P( local.B, local.C, local.D, local.A, local.X[ 3], 19 );
158 P( local.A, local.B, local.C, local.D, local.X[ 4], 3 );
159 P( local.D, local.A, local.B, local.C, local.X[ 5], 7 );
160 P( local.C, local.D, local.A, local.B, local.X[ 6], 11 );
161 P( local.B, local.C, local.D, local.A, local.X[ 7], 19 );
162 P( local.A, local.B, local.C, local.D, local.X[ 8], 3 );
163 P( local.D, local.A, local.B, local.C, local.X[ 9], 7 );
164 P( local.C, local.D, local.A, local.B, local.X[10], 11 );
165 P( local.B, local.C, local.D, local.A, local.X[11], 19 );
166 P( local.A, local.B, local.C, local.D, local.X[12], 3 );
167 P( local.D, local.A, local.B, local.C, local.X[13], 7 );
168 P( local.C, local.D, local.A, local.B, local.X[14], 11 );
169 P( local.B, local.C, local.D, local.A, local.X[15], 19 );
170
171 #undef P
172 #undef F
173
174 #define F(x,y,z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
175 #define P(a,b,c,d,x,s) \
176 do \
177 { \
178 (a) += F((b),(c),(d)) + (x) + 0x5A827999; \
179 (a) = S((a),(s)); \
180 } while( 0 )
181
182 P( local.A, local.B, local.C, local.D, local.X[ 0], 3 );
183 P( local.D, local.A, local.B, local.C, local.X[ 4], 5 );
184 P( local.C, local.D, local.A, local.B, local.X[ 8], 9 );
185 P( local.B, local.C, local.D, local.A, local.X[12], 13 );
186 P( local.A, local.B, local.C, local.D, local.X[ 1], 3 );
187 P( local.D, local.A, local.B, local.C, local.X[ 5], 5 );
188 P( local.C, local.D, local.A, local.B, local.X[ 9], 9 );
189 P( local.B, local.C, local.D, local.A, local.X[13], 13 );
190 P( local.A, local.B, local.C, local.D, local.X[ 2], 3 );
191 P( local.D, local.A, local.B, local.C, local.X[ 6], 5 );
192 P( local.C, local.D, local.A, local.B, local.X[10], 9 );
193 P( local.B, local.C, local.D, local.A, local.X[14], 13 );
194 P( local.A, local.B, local.C, local.D, local.X[ 3], 3 );
195 P( local.D, local.A, local.B, local.C, local.X[ 7], 5 );
196 P( local.C, local.D, local.A, local.B, local.X[11], 9 );
197 P( local.B, local.C, local.D, local.A, local.X[15], 13 );
198
199 #undef P
200 #undef F
201
202 #define F(x,y,z) ((x) ^ (y) ^ (z))
203 #define P(a,b,c,d,x,s) \
204 do \
205 { \
206 (a) += F((b),(c),(d)) + (x) + 0x6ED9EBA1; \
207 (a) = S((a),(s)); \
208 } while( 0 )
209
210 P( local.A, local.B, local.C, local.D, local.X[ 0], 3 );
211 P( local.D, local.A, local.B, local.C, local.X[ 8], 9 );
212 P( local.C, local.D, local.A, local.B, local.X[ 4], 11 );
213 P( local.B, local.C, local.D, local.A, local.X[12], 15 );
214 P( local.A, local.B, local.C, local.D, local.X[ 2], 3 );
215 P( local.D, local.A, local.B, local.C, local.X[10], 9 );
216 P( local.C, local.D, local.A, local.B, local.X[ 6], 11 );
217 P( local.B, local.C, local.D, local.A, local.X[14], 15 );
218 P( local.A, local.B, local.C, local.D, local.X[ 1], 3 );
219 P( local.D, local.A, local.B, local.C, local.X[ 9], 9 );
220 P( local.C, local.D, local.A, local.B, local.X[ 5], 11 );
221 P( local.B, local.C, local.D, local.A, local.X[13], 15 );
222 P( local.A, local.B, local.C, local.D, local.X[ 3], 3 );
223 P( local.D, local.A, local.B, local.C, local.X[11], 9 );
224 P( local.C, local.D, local.A, local.B, local.X[ 7], 11 );
225 P( local.B, local.C, local.D, local.A, local.X[15], 15 );
226
227 #undef F
228 #undef P
229
230 ctx->state[0] += local.A;
231 ctx->state[1] += local.B;
232 ctx->state[2] += local.C;
233 ctx->state[3] += local.D;
234
235 /* Zeroise variables to clear sensitive data from memory. */
236 mbedtls_platform_zeroize( &local, sizeof( local ) );
237
238 return( 0 );
239 }
240
241 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
mbedtls_md4_process(mbedtls_md4_context * ctx,const unsigned char data[64])242 void mbedtls_md4_process( mbedtls_md4_context *ctx,
243 const unsigned char data[64] )
244 {
245 mbedtls_internal_md4_process( ctx, data );
246 }
247 #endif
248 #endif /* !MBEDTLS_MD4_PROCESS_ALT */
249
250 /*
251 * MD4 process buffer
252 */
mbedtls_md4_update_ret(mbedtls_md4_context * ctx,const unsigned char * input,size_t ilen)253 int mbedtls_md4_update_ret( mbedtls_md4_context *ctx,
254 const unsigned char *input,
255 size_t ilen )
256 {
257 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
258 size_t fill;
259 uint32_t left;
260
261 if( ilen == 0 )
262 return( 0 );
263
264 left = ctx->total[0] & 0x3F;
265 fill = 64 - left;
266
267 ctx->total[0] += (uint32_t) ilen;
268 ctx->total[0] &= 0xFFFFFFFF;
269
270 if( ctx->total[0] < (uint32_t) ilen )
271 ctx->total[1]++;
272
273 if( left && ilen >= fill )
274 {
275 memcpy( (void *) (ctx->buffer + left),
276 (void *) input, fill );
277
278 if( ( ret = mbedtls_internal_md4_process( ctx, ctx->buffer ) ) != 0 )
279 return( ret );
280
281 input += fill;
282 ilen -= fill;
283 left = 0;
284 }
285
286 while( ilen >= 64 )
287 {
288 if( ( ret = mbedtls_internal_md4_process( ctx, input ) ) != 0 )
289 return( ret );
290
291 input += 64;
292 ilen -= 64;
293 }
294
295 if( ilen > 0 )
296 {
297 memcpy( (void *) (ctx->buffer + left),
298 (void *) input, ilen );
299 }
300
301 return( 0 );
302 }
303
304 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
mbedtls_md4_update(mbedtls_md4_context * ctx,const unsigned char * input,size_t ilen)305 void mbedtls_md4_update( mbedtls_md4_context *ctx,
306 const unsigned char *input,
307 size_t ilen )
308 {
309 mbedtls_md4_update_ret( ctx, input, ilen );
310 }
311 #endif
312
313 static const unsigned char md4_padding[64] =
314 {
315 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
316 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
317 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
318 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
319 };
320
321 /*
322 * MD4 final digest
323 */
mbedtls_md4_finish_ret(mbedtls_md4_context * ctx,unsigned char output[16])324 int mbedtls_md4_finish_ret( mbedtls_md4_context *ctx,
325 unsigned char output[16] )
326 {
327 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
328 uint32_t last, padn;
329 uint32_t high, low;
330 unsigned char msglen[8];
331
332 high = ( ctx->total[0] >> 29 )
333 | ( ctx->total[1] << 3 );
334 low = ( ctx->total[0] << 3 );
335
336 PUT_UINT32_LE( low, msglen, 0 );
337 PUT_UINT32_LE( high, msglen, 4 );
338
339 last = ctx->total[0] & 0x3F;
340 padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
341
342 ret = mbedtls_md4_update_ret( ctx, (unsigned char *)md4_padding, padn );
343 if( ret != 0 )
344 return( ret );
345
346 if( ( ret = mbedtls_md4_update_ret( ctx, msglen, 8 ) ) != 0 )
347 return( ret );
348
349
350 PUT_UINT32_LE( ctx->state[0], output, 0 );
351 PUT_UINT32_LE( ctx->state[1], output, 4 );
352 PUT_UINT32_LE( ctx->state[2], output, 8 );
353 PUT_UINT32_LE( ctx->state[3], output, 12 );
354
355 return( 0 );
356 }
357
358 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
mbedtls_md4_finish(mbedtls_md4_context * ctx,unsigned char output[16])359 void mbedtls_md4_finish( mbedtls_md4_context *ctx,
360 unsigned char output[16] )
361 {
362 mbedtls_md4_finish_ret( ctx, output );
363 }
364 #endif
365
366 #endif /* !MBEDTLS_MD4_ALT */
367
368 /*
369 * output = MD4( input buffer )
370 */
mbedtls_md4_ret(const unsigned char * input,size_t ilen,unsigned char output[16])371 int mbedtls_md4_ret( const unsigned char *input,
372 size_t ilen,
373 unsigned char output[16] )
374 {
375 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
376 mbedtls_md4_context ctx;
377
378 mbedtls_md4_init( &ctx );
379
380 if( ( ret = mbedtls_md4_starts_ret( &ctx ) ) != 0 )
381 goto exit;
382
383 if( ( ret = mbedtls_md4_update_ret( &ctx, input, ilen ) ) != 0 )
384 goto exit;
385
386 if( ( ret = mbedtls_md4_finish_ret( &ctx, output ) ) != 0 )
387 goto exit;
388
389 exit:
390 mbedtls_md4_free( &ctx );
391
392 return( ret );
393 }
394
395 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
mbedtls_md4(const unsigned char * input,size_t ilen,unsigned char output[16])396 void mbedtls_md4( const unsigned char *input,
397 size_t ilen,
398 unsigned char output[16] )
399 {
400 mbedtls_md4_ret( input, ilen, output );
401 }
402 #endif
403
404 #if defined(MBEDTLS_SELF_TEST)
405
406 /*
407 * RFC 1320 test vectors
408 */
409 static const unsigned char md4_test_str[7][81] =
410 {
411 { "" },
412 { "a" },
413 { "abc" },
414 { "message digest" },
415 { "abcdefghijklmnopqrstuvwxyz" },
416 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
417 { "12345678901234567890123456789012345678901234567890123456789012345678901234567890" }
418 };
419
420 static const size_t md4_test_strlen[7] =
421 {
422 0, 1, 3, 14, 26, 62, 80
423 };
424
425 static const unsigned char md4_test_sum[7][16] =
426 {
427 { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31,
428 0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 },
429 { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46,
430 0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 },
431 { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52,
432 0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D },
433 { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8,
434 0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B },
435 { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD,
436 0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 },
437 { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35,
438 0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 },
439 { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19,
440 0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 }
441 };
442
443 /*
444 * Checkup routine
445 */
mbedtls_md4_self_test(int verbose)446 int mbedtls_md4_self_test( int verbose )
447 {
448 int i, ret = 0;
449 unsigned char md4sum[16];
450
451 for( i = 0; i < 7; i++ )
452 {
453 if( verbose != 0 )
454 mbedtls_printf( " MD4 test #%d: ", i + 1 );
455
456 ret = mbedtls_md4_ret( md4_test_str[i], md4_test_strlen[i], md4sum );
457 if( ret != 0 )
458 goto fail;
459
460 if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 )
461 {
462 ret = 1;
463 goto fail;
464 }
465
466 if( verbose != 0 )
467 mbedtls_printf( "passed\n" );
468 }
469
470 if( verbose != 0 )
471 mbedtls_printf( "\n" );
472
473 return( 0 );
474
475 fail:
476 if( verbose != 0 )
477 mbedtls_printf( "failed\n" );
478
479 return( ret );
480 }
481
482 #endif /* MBEDTLS_SELF_TEST */
483
484 #endif /* MBEDTLS_MD4_C */
485