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