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