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