[MBEDTLS]
[reactos.git] / reactos / dll / 3rdparty / mbedtls / md4.c
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 void mbedtls_md4_starts( 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
114 #if !defined(MBEDTLS_MD4_PROCESS_ALT)
115 void mbedtls_md4_process( mbedtls_md4_context *ctx, const unsigned char data[64] )
116 {
117 uint32_t X[16], A, B, C, D;
118
119 GET_UINT32_LE( X[ 0], data, 0 );
120 GET_UINT32_LE( X[ 1], data, 4 );
121 GET_UINT32_LE( X[ 2], data, 8 );
122 GET_UINT32_LE( X[ 3], data, 12 );
123 GET_UINT32_LE( X[ 4], data, 16 );
124 GET_UINT32_LE( X[ 5], data, 20 );
125 GET_UINT32_LE( X[ 6], data, 24 );
126 GET_UINT32_LE( X[ 7], data, 28 );
127 GET_UINT32_LE( X[ 8], data, 32 );
128 GET_UINT32_LE( X[ 9], data, 36 );
129 GET_UINT32_LE( X[10], data, 40 );
130 GET_UINT32_LE( X[11], data, 44 );
131 GET_UINT32_LE( X[12], data, 48 );
132 GET_UINT32_LE( X[13], data, 52 );
133 GET_UINT32_LE( X[14], data, 56 );
134 GET_UINT32_LE( X[15], data, 60 );
135
136 #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
137
138 A = ctx->state[0];
139 B = ctx->state[1];
140 C = ctx->state[2];
141 D = ctx->state[3];
142
143 #define F(x, y, z) ((x & y) | ((~x) & z))
144 #define P(a,b,c,d,x,s) { a += F(b,c,d) + x; a = S(a,s); }
145
146 P( A, B, C, D, X[ 0], 3 );
147 P( D, A, B, C, X[ 1], 7 );
148 P( C, D, A, B, X[ 2], 11 );
149 P( B, C, D, A, X[ 3], 19 );
150 P( A, B, C, D, X[ 4], 3 );
151 P( D, A, B, C, X[ 5], 7 );
152 P( C, D, A, B, X[ 6], 11 );
153 P( B, C, D, A, X[ 7], 19 );
154 P( A, B, C, D, X[ 8], 3 );
155 P( D, A, B, C, X[ 9], 7 );
156 P( C, D, A, B, X[10], 11 );
157 P( B, C, D, A, X[11], 19 );
158 P( A, B, C, D, X[12], 3 );
159 P( D, A, B, C, X[13], 7 );
160 P( C, D, A, B, X[14], 11 );
161 P( B, C, D, A, X[15], 19 );
162
163 #undef P
164 #undef F
165
166 #define F(x,y,z) ((x & y) | (x & z) | (y & z))
167 #define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x5A827999; a = S(a,s); }
168
169 P( A, B, C, D, X[ 0], 3 );
170 P( D, A, B, C, X[ 4], 5 );
171 P( C, D, A, B, X[ 8], 9 );
172 P( B, C, D, A, X[12], 13 );
173 P( A, B, C, D, X[ 1], 3 );
174 P( D, A, B, C, X[ 5], 5 );
175 P( C, D, A, B, X[ 9], 9 );
176 P( B, C, D, A, X[13], 13 );
177 P( A, B, C, D, X[ 2], 3 );
178 P( D, A, B, C, X[ 6], 5 );
179 P( C, D, A, B, X[10], 9 );
180 P( B, C, D, A, X[14], 13 );
181 P( A, B, C, D, X[ 3], 3 );
182 P( D, A, B, C, X[ 7], 5 );
183 P( C, D, A, B, X[11], 9 );
184 P( B, C, D, A, X[15], 13 );
185
186 #undef P
187 #undef F
188
189 #define F(x,y,z) (x ^ y ^ z)
190 #define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x6ED9EBA1; a = S(a,s); }
191
192 P( A, B, C, D, X[ 0], 3 );
193 P( D, A, B, C, X[ 8], 9 );
194 P( C, D, A, B, X[ 4], 11 );
195 P( B, C, D, A, X[12], 15 );
196 P( A, B, C, D, X[ 2], 3 );
197 P( D, A, B, C, X[10], 9 );
198 P( C, D, A, B, X[ 6], 11 );
199 P( B, C, D, A, X[14], 15 );
200 P( A, B, C, D, X[ 1], 3 );
201 P( D, A, B, C, X[ 9], 9 );
202 P( C, D, A, B, X[ 5], 11 );
203 P( B, C, D, A, X[13], 15 );
204 P( A, B, C, D, X[ 3], 3 );
205 P( D, A, B, C, X[11], 9 );
206 P( C, D, A, B, X[ 7], 11 );
207 P( B, C, D, A, X[15], 15 );
208
209 #undef F
210 #undef P
211
212 ctx->state[0] += A;
213 ctx->state[1] += B;
214 ctx->state[2] += C;
215 ctx->state[3] += D;
216 }
217 #endif /* !MBEDTLS_MD4_PROCESS_ALT */
218
219 /*
220 * MD4 process buffer
221 */
222 void mbedtls_md4_update( mbedtls_md4_context *ctx, const unsigned char *input, size_t ilen )
223 {
224 size_t fill;
225 uint32_t left;
226
227 if( ilen == 0 )
228 return;
229
230 left = ctx->total[0] & 0x3F;
231 fill = 64 - left;
232
233 ctx->total[0] += (uint32_t) ilen;
234 ctx->total[0] &= 0xFFFFFFFF;
235
236 if( ctx->total[0] < (uint32_t) ilen )
237 ctx->total[1]++;
238
239 if( left && ilen >= fill )
240 {
241 memcpy( (void *) (ctx->buffer + left),
242 (void *) input, fill );
243 mbedtls_md4_process( ctx, ctx->buffer );
244 input += fill;
245 ilen -= fill;
246 left = 0;
247 }
248
249 while( ilen >= 64 )
250 {
251 mbedtls_md4_process( ctx, input );
252 input += 64;
253 ilen -= 64;
254 }
255
256 if( ilen > 0 )
257 {
258 memcpy( (void *) (ctx->buffer + left),
259 (void *) input, ilen );
260 }
261 }
262
263 static const unsigned char md4_padding[64] =
264 {
265 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
266 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
267 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
268 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
269 };
270
271 /*
272 * MD4 final digest
273 */
274 void mbedtls_md4_finish( mbedtls_md4_context *ctx, unsigned char output[16] )
275 {
276 uint32_t last, padn;
277 uint32_t high, low;
278 unsigned char msglen[8];
279
280 high = ( ctx->total[0] >> 29 )
281 | ( ctx->total[1] << 3 );
282 low = ( ctx->total[0] << 3 );
283
284 PUT_UINT32_LE( low, msglen, 0 );
285 PUT_UINT32_LE( high, msglen, 4 );
286
287 last = ctx->total[0] & 0x3F;
288 padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
289
290 mbedtls_md4_update( ctx, (unsigned char *) md4_padding, padn );
291 mbedtls_md4_update( ctx, msglen, 8 );
292
293 PUT_UINT32_LE( ctx->state[0], output, 0 );
294 PUT_UINT32_LE( ctx->state[1], output, 4 );
295 PUT_UINT32_LE( ctx->state[2], output, 8 );
296 PUT_UINT32_LE( ctx->state[3], output, 12 );
297 }
298
299 #endif /* !MBEDTLS_MD4_ALT */
300
301 /*
302 * output = MD4( input buffer )
303 */
304 void mbedtls_md4( const unsigned char *input, size_t ilen, unsigned char output[16] )
305 {
306 mbedtls_md4_context ctx;
307
308 mbedtls_md4_init( &ctx );
309 mbedtls_md4_starts( &ctx );
310 mbedtls_md4_update( &ctx, input, ilen );
311 mbedtls_md4_finish( &ctx, output );
312 mbedtls_md4_free( &ctx );
313 }
314
315 #if defined(MBEDTLS_SELF_TEST)
316
317 /*
318 * RFC 1320 test vectors
319 */
320 static const char md4_test_str[7][81] =
321 {
322 { "" },
323 { "a" },
324 { "abc" },
325 { "message digest" },
326 { "abcdefghijklmnopqrstuvwxyz" },
327 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
328 { "12345678901234567890123456789012345678901234567890123456789012" \
329 "345678901234567890" }
330 };
331
332 static const unsigned char md4_test_sum[7][16] =
333 {
334 { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31,
335 0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 },
336 { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46,
337 0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 },
338 { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52,
339 0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D },
340 { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8,
341 0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B },
342 { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD,
343 0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 },
344 { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35,
345 0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 },
346 { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19,
347 0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 }
348 };
349
350 /*
351 * Checkup routine
352 */
353 int mbedtls_md4_self_test( int verbose )
354 {
355 int i;
356 unsigned char md4sum[16];
357
358 for( i = 0; i < 7; i++ )
359 {
360 if( verbose != 0 )
361 mbedtls_printf( " MD4 test #%d: ", i + 1 );
362
363 mbedtls_md4( (unsigned char *) md4_test_str[i],
364 strlen( md4_test_str[i] ), md4sum );
365
366 if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 )
367 {
368 if( verbose != 0 )
369 mbedtls_printf( "failed\n" );
370
371 return( 1 );
372 }
373
374 if( verbose != 0 )
375 mbedtls_printf( "passed\n" );
376 }
377
378 if( verbose != 0 )
379 mbedtls_printf( "\n" );
380
381 return( 0 );
382 }
383
384 #endif /* MBEDTLS_SELF_TEST */
385
386 #endif /* MBEDTLS_MD4_C */