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