xref: /reactos/dll/3rdparty/mbedtls/md4.c (revision cbda039f)
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