blob: b3e8682ad43dc8346416450b028aa58f8831ac27 [file] [log] [blame]
Edison Ai7b079202018-02-28 15:01:47 +08001// SPDX-License-Identifier: Apache-2.0
Jens Wiklander817466c2018-05-22 13:49:31 +02002/*
3 * RFC 1186/1320 compliant MD4 implementation
4 *
5 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Jens Wiklander817466c2018-05-22 13:49:31 +02006 *
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 * This file is part of mbed TLS (https://tls.mbed.org)
20 */
21/*
22 * The MD4 algorithm was designed by Ron Rivest in 1990.
23 *
24 * http://www.ietf.org/rfc/rfc1186.txt
25 * http://www.ietf.org/rfc/rfc1320.txt
26 */
27
28#if !defined(MBEDTLS_CONFIG_FILE)
29#include "mbedtls/config.h"
30#else
31#include MBEDTLS_CONFIG_FILE
32#endif
33
34#if defined(MBEDTLS_MD4_C)
35
36#include "mbedtls/md4.h"
Jens Wiklander50a57cf2019-03-13 10:41:54 +010037#include "mbedtls/platform_util.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020038
39#include <string.h>
40
41#if defined(MBEDTLS_SELF_TEST)
42#if defined(MBEDTLS_PLATFORM_C)
43#include "mbedtls/platform.h"
44#else
45#include <stdio.h>
46#define mbedtls_printf printf
47#endif /* MBEDTLS_PLATFORM_C */
48#endif /* MBEDTLS_SELF_TEST */
49
50#if !defined(MBEDTLS_MD4_ALT)
51
Jens Wiklander817466c2018-05-22 13:49:31 +020052/*
53 * 32-bit integer manipulation macros (little endian)
54 */
55#ifndef GET_UINT32_LE
56#define GET_UINT32_LE(n,b,i) \
57{ \
58 (n) = ( (uint32_t) (b)[(i) ] ) \
59 | ( (uint32_t) (b)[(i) + 1] << 8 ) \
60 | ( (uint32_t) (b)[(i) + 2] << 16 ) \
61 | ( (uint32_t) (b)[(i) + 3] << 24 ); \
62}
63#endif
64
65#ifndef PUT_UINT32_LE
66#define PUT_UINT32_LE(n,b,i) \
67{ \
68 (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \
69 (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \
70 (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \
71 (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \
72}
73#endif
74
75void mbedtls_md4_init( mbedtls_md4_context *ctx )
76{
77 memset( ctx, 0, sizeof( mbedtls_md4_context ) );
78}
79
80void mbedtls_md4_free( mbedtls_md4_context *ctx )
81{
82 if( ctx == NULL )
83 return;
84
Jens Wiklander50a57cf2019-03-13 10:41:54 +010085 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md4_context ) );
Jens Wiklander817466c2018-05-22 13:49:31 +020086}
87
88void mbedtls_md4_clone( mbedtls_md4_context *dst,
89 const mbedtls_md4_context *src )
90{
91 *dst = *src;
92}
93
94/*
95 * MD4 context setup
96 */
Jens Wiklander50a57cf2019-03-13 10:41:54 +010097int mbedtls_md4_starts_ret( mbedtls_md4_context *ctx )
Jens Wiklander817466c2018-05-22 13:49:31 +020098{
99 ctx->total[0] = 0;
100 ctx->total[1] = 0;
101
102 ctx->state[0] = 0x67452301;
103 ctx->state[1] = 0xEFCDAB89;
104 ctx->state[2] = 0x98BADCFE;
105 ctx->state[3] = 0x10325476;
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100106
107 return( 0 );
Jens Wiklander817466c2018-05-22 13:49:31 +0200108}
109
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100110#if !defined(MBEDTLS_DEPRECATED_REMOVED)
111void mbedtls_md4_starts( mbedtls_md4_context *ctx )
112{
113 mbedtls_md4_starts_ret( ctx );
114}
115#endif
116
Jens Wiklander817466c2018-05-22 13:49:31 +0200117#if !defined(MBEDTLS_MD4_PROCESS_ALT)
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100118int mbedtls_internal_md4_process( mbedtls_md4_context *ctx,
119 const unsigned char data[64] )
Jens Wiklander817466c2018-05-22 13:49:31 +0200120{
121 uint32_t X[16], A, B, C, D;
122
123 GET_UINT32_LE( X[ 0], data, 0 );
124 GET_UINT32_LE( X[ 1], data, 4 );
125 GET_UINT32_LE( X[ 2], data, 8 );
126 GET_UINT32_LE( X[ 3], data, 12 );
127 GET_UINT32_LE( X[ 4], data, 16 );
128 GET_UINT32_LE( X[ 5], data, 20 );
129 GET_UINT32_LE( X[ 6], data, 24 );
130 GET_UINT32_LE( X[ 7], data, 28 );
131 GET_UINT32_LE( X[ 8], data, 32 );
132 GET_UINT32_LE( X[ 9], data, 36 );
133 GET_UINT32_LE( X[10], data, 40 );
134 GET_UINT32_LE( X[11], data, 44 );
135 GET_UINT32_LE( X[12], data, 48 );
136 GET_UINT32_LE( X[13], data, 52 );
137 GET_UINT32_LE( X[14], data, 56 );
138 GET_UINT32_LE( X[15], data, 60 );
139
140#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
141
142 A = ctx->state[0];
143 B = ctx->state[1];
144 C = ctx->state[2];
145 D = ctx->state[3];
146
147#define F(x, y, z) ((x & y) | ((~x) & z))
148#define P(a,b,c,d,x,s) { a += F(b,c,d) + x; a = S(a,s); }
149
150 P( A, B, C, D, X[ 0], 3 );
151 P( D, A, B, C, X[ 1], 7 );
152 P( C, D, A, B, X[ 2], 11 );
153 P( B, C, D, A, X[ 3], 19 );
154 P( A, B, C, D, X[ 4], 3 );
155 P( D, A, B, C, X[ 5], 7 );
156 P( C, D, A, B, X[ 6], 11 );
157 P( B, C, D, A, X[ 7], 19 );
158 P( A, B, C, D, X[ 8], 3 );
159 P( D, A, B, C, X[ 9], 7 );
160 P( C, D, A, B, X[10], 11 );
161 P( B, C, D, A, X[11], 19 );
162 P( A, B, C, D, X[12], 3 );
163 P( D, A, B, C, X[13], 7 );
164 P( C, D, A, B, X[14], 11 );
165 P( B, C, D, A, X[15], 19 );
166
167#undef P
168#undef F
169
170#define F(x,y,z) ((x & y) | (x & z) | (y & z))
171#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x5A827999; a = S(a,s); }
172
173 P( A, B, C, D, X[ 0], 3 );
174 P( D, A, B, C, X[ 4], 5 );
175 P( C, D, A, B, X[ 8], 9 );
176 P( B, C, D, A, X[12], 13 );
177 P( A, B, C, D, X[ 1], 3 );
178 P( D, A, B, C, X[ 5], 5 );
179 P( C, D, A, B, X[ 9], 9 );
180 P( B, C, D, A, X[13], 13 );
181 P( A, B, C, D, X[ 2], 3 );
182 P( D, A, B, C, X[ 6], 5 );
183 P( C, D, A, B, X[10], 9 );
184 P( B, C, D, A, X[14], 13 );
185 P( A, B, C, D, X[ 3], 3 );
186 P( D, A, B, C, X[ 7], 5 );
187 P( C, D, A, B, X[11], 9 );
188 P( B, C, D, A, X[15], 13 );
189
190#undef P
191#undef F
192
193#define F(x,y,z) (x ^ y ^ z)
194#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x6ED9EBA1; a = S(a,s); }
195
196 P( A, B, C, D, X[ 0], 3 );
197 P( D, A, B, C, X[ 8], 9 );
198 P( C, D, A, B, X[ 4], 11 );
199 P( B, C, D, A, X[12], 15 );
200 P( A, B, C, D, X[ 2], 3 );
201 P( D, A, B, C, X[10], 9 );
202 P( C, D, A, B, X[ 6], 11 );
203 P( B, C, D, A, X[14], 15 );
204 P( A, B, C, D, X[ 1], 3 );
205 P( D, A, B, C, X[ 9], 9 );
206 P( C, D, A, B, X[ 5], 11 );
207 P( B, C, D, A, X[13], 15 );
208 P( A, B, C, D, X[ 3], 3 );
209 P( D, A, B, C, X[11], 9 );
210 P( C, D, A, B, X[ 7], 11 );
211 P( B, C, D, A, X[15], 15 );
212
213#undef F
214#undef P
215
216 ctx->state[0] += A;
217 ctx->state[1] += B;
218 ctx->state[2] += C;
219 ctx->state[3] += D;
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100220
221 return( 0 );
Jens Wiklander817466c2018-05-22 13:49:31 +0200222}
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100223
224#if !defined(MBEDTLS_DEPRECATED_REMOVED)
225void mbedtls_md4_process( mbedtls_md4_context *ctx,
226 const unsigned char data[64] )
227{
228 mbedtls_internal_md4_process( ctx, data );
229}
230#endif
Jens Wiklander817466c2018-05-22 13:49:31 +0200231#endif /* !MBEDTLS_MD4_PROCESS_ALT */
232
233/*
234 * MD4 process buffer
235 */
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100236int mbedtls_md4_update_ret( mbedtls_md4_context *ctx,
237 const unsigned char *input,
238 size_t ilen )
Jens Wiklander817466c2018-05-22 13:49:31 +0200239{
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100240 int ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200241 size_t fill;
242 uint32_t left;
243
244 if( ilen == 0 )
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100245 return( 0 );
Jens Wiklander817466c2018-05-22 13:49:31 +0200246
247 left = ctx->total[0] & 0x3F;
248 fill = 64 - left;
249
250 ctx->total[0] += (uint32_t) ilen;
251 ctx->total[0] &= 0xFFFFFFFF;
252
253 if( ctx->total[0] < (uint32_t) ilen )
254 ctx->total[1]++;
255
256 if( left && ilen >= fill )
257 {
258 memcpy( (void *) (ctx->buffer + left),
259 (void *) input, fill );
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100260
261 if( ( ret = mbedtls_internal_md4_process( ctx, ctx->buffer ) ) != 0 )
262 return( ret );
263
Jens Wiklander817466c2018-05-22 13:49:31 +0200264 input += fill;
265 ilen -= fill;
266 left = 0;
267 }
268
269 while( ilen >= 64 )
270 {
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100271 if( ( ret = mbedtls_internal_md4_process( ctx, input ) ) != 0 )
272 return( ret );
273
Jens Wiklander817466c2018-05-22 13:49:31 +0200274 input += 64;
275 ilen -= 64;
276 }
277
278 if( ilen > 0 )
279 {
280 memcpy( (void *) (ctx->buffer + left),
281 (void *) input, ilen );
282 }
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100283
284 return( 0 );
Jens Wiklander817466c2018-05-22 13:49:31 +0200285}
286
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100287#if !defined(MBEDTLS_DEPRECATED_REMOVED)
288void mbedtls_md4_update( mbedtls_md4_context *ctx,
289 const unsigned char *input,
290 size_t ilen )
291{
292 mbedtls_md4_update_ret( ctx, input, ilen );
293}
294#endif
295
Jens Wiklander817466c2018-05-22 13:49:31 +0200296static const unsigned char md4_padding[64] =
297{
298 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
299 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
300 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
301 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
302};
303
304/*
305 * MD4 final digest
306 */
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100307int mbedtls_md4_finish_ret( mbedtls_md4_context *ctx,
308 unsigned char output[16] )
Jens Wiklander817466c2018-05-22 13:49:31 +0200309{
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100310 int ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200311 uint32_t last, padn;
312 uint32_t high, low;
313 unsigned char msglen[8];
314
315 high = ( ctx->total[0] >> 29 )
316 | ( ctx->total[1] << 3 );
317 low = ( ctx->total[0] << 3 );
318
319 PUT_UINT32_LE( low, msglen, 0 );
320 PUT_UINT32_LE( high, msglen, 4 );
321
322 last = ctx->total[0] & 0x3F;
323 padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
324
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100325 ret = mbedtls_md4_update_ret( ctx, (unsigned char *)md4_padding, padn );
326 if( ret != 0 )
327 return( ret );
328
329 if( ( ret = mbedtls_md4_update_ret( ctx, msglen, 8 ) ) != 0 )
330 return( ret );
331
Jens Wiklander817466c2018-05-22 13:49:31 +0200332
333 PUT_UINT32_LE( ctx->state[0], output, 0 );
334 PUT_UINT32_LE( ctx->state[1], output, 4 );
335 PUT_UINT32_LE( ctx->state[2], output, 8 );
336 PUT_UINT32_LE( ctx->state[3], output, 12 );
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100337
338 return( 0 );
Jens Wiklander817466c2018-05-22 13:49:31 +0200339}
340
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100341#if !defined(MBEDTLS_DEPRECATED_REMOVED)
342void mbedtls_md4_finish( mbedtls_md4_context *ctx,
343 unsigned char output[16] )
344{
345 mbedtls_md4_finish_ret( ctx, output );
346}
347#endif
348
Jens Wiklander817466c2018-05-22 13:49:31 +0200349#endif /* !MBEDTLS_MD4_ALT */
350
351/*
352 * output = MD4( input buffer )
353 */
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100354int mbedtls_md4_ret( const unsigned char *input,
355 size_t ilen,
356 unsigned char output[16] )
Jens Wiklander817466c2018-05-22 13:49:31 +0200357{
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100358 int ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200359 mbedtls_md4_context ctx;
360
361 mbedtls_md4_init( &ctx );
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100362
363 if( ( ret = mbedtls_md4_starts_ret( &ctx ) ) != 0 )
364 goto exit;
365
366 if( ( ret = mbedtls_md4_update_ret( &ctx, input, ilen ) ) != 0 )
367 goto exit;
368
369 if( ( ret = mbedtls_md4_finish_ret( &ctx, output ) ) != 0 )
370 goto exit;
371
372exit:
Jens Wiklander817466c2018-05-22 13:49:31 +0200373 mbedtls_md4_free( &ctx );
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100374
375 return( ret );
Jens Wiklander817466c2018-05-22 13:49:31 +0200376}
377
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100378#if !defined(MBEDTLS_DEPRECATED_REMOVED)
379void mbedtls_md4( const unsigned char *input,
380 size_t ilen,
381 unsigned char output[16] )
382{
383 mbedtls_md4_ret( input, ilen, output );
384}
385#endif
386
Jens Wiklander817466c2018-05-22 13:49:31 +0200387#if defined(MBEDTLS_SELF_TEST)
388
389/*
390 * RFC 1320 test vectors
391 */
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100392static const unsigned char md4_test_str[7][81] =
Jens Wiklander817466c2018-05-22 13:49:31 +0200393{
394 { "" },
395 { "a" },
396 { "abc" },
397 { "message digest" },
398 { "abcdefghijklmnopqrstuvwxyz" },
399 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100400 { "12345678901234567890123456789012345678901234567890123456789012"
Jens Wiklander817466c2018-05-22 13:49:31 +0200401 "345678901234567890" }
402};
403
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100404static const size_t md4_test_strlen[7] =
405{
406 0, 1, 3, 14, 26, 62, 80
407};
408
Jens Wiklander817466c2018-05-22 13:49:31 +0200409static const unsigned char md4_test_sum[7][16] =
410{
411 { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31,
412 0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 },
413 { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46,
414 0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 },
415 { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52,
416 0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D },
417 { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8,
418 0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B },
419 { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD,
420 0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 },
421 { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35,
422 0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 },
423 { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19,
424 0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 }
425};
426
427/*
428 * Checkup routine
429 */
430int mbedtls_md4_self_test( int verbose )
431{
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100432 int i, ret = 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200433 unsigned char md4sum[16];
434
435 for( i = 0; i < 7; i++ )
436 {
437 if( verbose != 0 )
438 mbedtls_printf( " MD4 test #%d: ", i + 1 );
439
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100440 ret = mbedtls_md4_ret( md4_test_str[i], md4_test_strlen[i], md4sum );
441 if( ret != 0 )
442 goto fail;
Jens Wiklander817466c2018-05-22 13:49:31 +0200443
444 if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 )
445 {
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100446 ret = 1;
447 goto fail;
Jens Wiklander817466c2018-05-22 13:49:31 +0200448 }
449
450 if( verbose != 0 )
451 mbedtls_printf( "passed\n" );
452 }
453
454 if( verbose != 0 )
455 mbedtls_printf( "\n" );
456
457 return( 0 );
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100458
459fail:
460 if( verbose != 0 )
461 mbedtls_printf( "failed\n" );
462
463 return( ret );
Jens Wiklander817466c2018-05-22 13:49:31 +0200464}
465
466#endif /* MBEDTLS_SELF_TEST */
467
468#endif /* MBEDTLS_MD4_C */