blob: 8156d0bc78ea36fe4a83e99983544c66e011693d [file] [log] [blame]
Edison Aic6672fd2018-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 Wiklander3d3b0592019-03-20 15:30:29 +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 Wiklander3d3b0592019-03-20 15:30:29 +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 Wiklander3d3b0592019-03-20 15:30:29 +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 Wiklander3d3b0592019-03-20 15:30:29 +0100106
107 return( 0 );
Jens Wiklander817466c2018-05-22 13:49:31 +0200108}
109
Jens Wiklander3d3b0592019-03-20 15:30:29 +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 Wiklander3d3b0592019-03-20 15:30:29 +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
Jerome Forissier5b25c762020-04-07 11:18:49 +0200140#define S(x,n) (((x) << (n)) | (((x) & 0xFFFFFFFF) >> (32 - (n))))
Jens Wiklander817466c2018-05-22 13:49:31 +0200141
142 A = ctx->state[0];
143 B = ctx->state[1];
144 C = ctx->state[2];
145 D = ctx->state[3];
146
Jerome Forissier5b25c762020-04-07 11:18:49 +0200147#define F(x, y, z) (((x) & (y)) | ((~(x)) & (z)))
148#define P(a,b,c,d,x,s) \
149 do \
150 { \
151 (a) += F((b),(c),(d)) + (x); \
152 (a) = S((a),(s)); \
153 } while( 0 )
154
Jens Wiklander817466c2018-05-22 13:49:31 +0200155
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
Jerome Forissier5b25c762020-04-07 11:18:49 +0200176#define F(x,y,z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
177#define P(a,b,c,d,x,s) \
178 do \
179 { \
180 (a) += F((b),(c),(d)) + (x) + 0x5A827999; \
181 (a) = S((a),(s)); \
182 } while( 0 )
Jens Wiklander817466c2018-05-22 13:49:31 +0200183
184 P( A, B, C, D, X[ 0], 3 );
185 P( D, A, B, C, X[ 4], 5 );
186 P( C, D, A, B, X[ 8], 9 );
187 P( B, C, D, A, X[12], 13 );
188 P( A, B, C, D, X[ 1], 3 );
189 P( D, A, B, C, X[ 5], 5 );
190 P( C, D, A, B, X[ 9], 9 );
191 P( B, C, D, A, X[13], 13 );
192 P( A, B, C, D, X[ 2], 3 );
193 P( D, A, B, C, X[ 6], 5 );
194 P( C, D, A, B, X[10], 9 );
195 P( B, C, D, A, X[14], 13 );
196 P( A, B, C, D, X[ 3], 3 );
197 P( D, A, B, C, X[ 7], 5 );
198 P( C, D, A, B, X[11], 9 );
199 P( B, C, D, A, X[15], 13 );
200
201#undef P
202#undef F
203
Jerome Forissier5b25c762020-04-07 11:18:49 +0200204#define F(x,y,z) ((x) ^ (y) ^ (z))
205#define P(a,b,c,d,x,s) \
206 do \
207 { \
208 (a) += F((b),(c),(d)) + (x) + 0x6ED9EBA1; \
209 (a) = S((a),(s)); \
210 } while( 0 )
Jens Wiklander817466c2018-05-22 13:49:31 +0200211
212 P( A, B, C, D, X[ 0], 3 );
213 P( D, A, B, C, X[ 8], 9 );
214 P( C, D, A, B, X[ 4], 11 );
215 P( B, C, D, A, X[12], 15 );
216 P( A, B, C, D, X[ 2], 3 );
217 P( D, A, B, C, X[10], 9 );
218 P( C, D, A, B, X[ 6], 11 );
219 P( B, C, D, A, X[14], 15 );
220 P( A, B, C, D, X[ 1], 3 );
221 P( D, A, B, C, X[ 9], 9 );
222 P( C, D, A, B, X[ 5], 11 );
223 P( B, C, D, A, X[13], 15 );
224 P( A, B, C, D, X[ 3], 3 );
225 P( D, A, B, C, X[11], 9 );
226 P( C, D, A, B, X[ 7], 11 );
227 P( B, C, D, A, X[15], 15 );
228
229#undef F
230#undef P
231
232 ctx->state[0] += A;
233 ctx->state[1] += B;
234 ctx->state[2] += C;
235 ctx->state[3] += D;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100236
237 return( 0 );
Jens Wiklander817466c2018-05-22 13:49:31 +0200238}
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100239
240#if !defined(MBEDTLS_DEPRECATED_REMOVED)
241void mbedtls_md4_process( mbedtls_md4_context *ctx,
242 const unsigned char data[64] )
243{
244 mbedtls_internal_md4_process( ctx, data );
245}
246#endif
Jens Wiklander817466c2018-05-22 13:49:31 +0200247#endif /* !MBEDTLS_MD4_PROCESS_ALT */
248
249/*
250 * MD4 process buffer
251 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100252int mbedtls_md4_update_ret( mbedtls_md4_context *ctx,
253 const unsigned char *input,
254 size_t ilen )
Jens Wiklander817466c2018-05-22 13:49:31 +0200255{
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100256 int ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200257 size_t fill;
258 uint32_t left;
259
260 if( ilen == 0 )
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100261 return( 0 );
Jens Wiklander817466c2018-05-22 13:49:31 +0200262
263 left = ctx->total[0] & 0x3F;
264 fill = 64 - left;
265
266 ctx->total[0] += (uint32_t) ilen;
267 ctx->total[0] &= 0xFFFFFFFF;
268
269 if( ctx->total[0] < (uint32_t) ilen )
270 ctx->total[1]++;
271
272 if( left && ilen >= fill )
273 {
274 memcpy( (void *) (ctx->buffer + left),
275 (void *) input, fill );
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100276
277 if( ( ret = mbedtls_internal_md4_process( ctx, ctx->buffer ) ) != 0 )
278 return( ret );
279
Jens Wiklander817466c2018-05-22 13:49:31 +0200280 input += fill;
281 ilen -= fill;
282 left = 0;
283 }
284
285 while( ilen >= 64 )
286 {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100287 if( ( ret = mbedtls_internal_md4_process( ctx, input ) ) != 0 )
288 return( ret );
289
Jens Wiklander817466c2018-05-22 13:49:31 +0200290 input += 64;
291 ilen -= 64;
292 }
293
294 if( ilen > 0 )
295 {
296 memcpy( (void *) (ctx->buffer + left),
297 (void *) input, ilen );
298 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100299
300 return( 0 );
Jens Wiklander817466c2018-05-22 13:49:31 +0200301}
302
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100303#if !defined(MBEDTLS_DEPRECATED_REMOVED)
304void mbedtls_md4_update( mbedtls_md4_context *ctx,
305 const unsigned char *input,
306 size_t ilen )
307{
308 mbedtls_md4_update_ret( ctx, input, ilen );
309}
310#endif
311
Jens Wiklander817466c2018-05-22 13:49:31 +0200312static const unsigned char md4_padding[64] =
313{
314 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
315 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
316 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
317 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
318};
319
320/*
321 * MD4 final digest
322 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100323int mbedtls_md4_finish_ret( mbedtls_md4_context *ctx,
324 unsigned char output[16] )
Jens Wiklander817466c2018-05-22 13:49:31 +0200325{
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100326 int ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200327 uint32_t last, padn;
328 uint32_t high, low;
329 unsigned char msglen[8];
330
331 high = ( ctx->total[0] >> 29 )
332 | ( ctx->total[1] << 3 );
333 low = ( ctx->total[0] << 3 );
334
335 PUT_UINT32_LE( low, msglen, 0 );
336 PUT_UINT32_LE( high, msglen, 4 );
337
338 last = ctx->total[0] & 0x3F;
339 padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
340
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100341 ret = mbedtls_md4_update_ret( ctx, (unsigned char *)md4_padding, padn );
342 if( ret != 0 )
343 return( ret );
344
345 if( ( ret = mbedtls_md4_update_ret( ctx, msglen, 8 ) ) != 0 )
346 return( ret );
347
Jens Wiklander817466c2018-05-22 13:49:31 +0200348
349 PUT_UINT32_LE( ctx->state[0], output, 0 );
350 PUT_UINT32_LE( ctx->state[1], output, 4 );
351 PUT_UINT32_LE( ctx->state[2], output, 8 );
352 PUT_UINT32_LE( ctx->state[3], output, 12 );
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100353
354 return( 0 );
Jens Wiklander817466c2018-05-22 13:49:31 +0200355}
356
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100357#if !defined(MBEDTLS_DEPRECATED_REMOVED)
358void mbedtls_md4_finish( mbedtls_md4_context *ctx,
359 unsigned char output[16] )
360{
361 mbedtls_md4_finish_ret( ctx, output );
362}
363#endif
364
Jens Wiklander817466c2018-05-22 13:49:31 +0200365#endif /* !MBEDTLS_MD4_ALT */
366
367/*
368 * output = MD4( input buffer )
369 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100370int mbedtls_md4_ret( const unsigned char *input,
371 size_t ilen,
372 unsigned char output[16] )
Jens Wiklander817466c2018-05-22 13:49:31 +0200373{
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100374 int ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200375 mbedtls_md4_context ctx;
376
377 mbedtls_md4_init( &ctx );
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100378
379 if( ( ret = mbedtls_md4_starts_ret( &ctx ) ) != 0 )
380 goto exit;
381
382 if( ( ret = mbedtls_md4_update_ret( &ctx, input, ilen ) ) != 0 )
383 goto exit;
384
385 if( ( ret = mbedtls_md4_finish_ret( &ctx, output ) ) != 0 )
386 goto exit;
387
388exit:
Jens Wiklander817466c2018-05-22 13:49:31 +0200389 mbedtls_md4_free( &ctx );
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100390
391 return( ret );
Jens Wiklander817466c2018-05-22 13:49:31 +0200392}
393
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100394#if !defined(MBEDTLS_DEPRECATED_REMOVED)
395void mbedtls_md4( const unsigned char *input,
396 size_t ilen,
397 unsigned char output[16] )
398{
399 mbedtls_md4_ret( input, ilen, output );
400}
401#endif
402
Jens Wiklander817466c2018-05-22 13:49:31 +0200403#if defined(MBEDTLS_SELF_TEST)
404
405/*
406 * RFC 1320 test vectors
407 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100408static const unsigned char md4_test_str[7][81] =
Jens Wiklander817466c2018-05-22 13:49:31 +0200409{
410 { "" },
411 { "a" },
412 { "abc" },
413 { "message digest" },
414 { "abcdefghijklmnopqrstuvwxyz" },
415 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100416 { "12345678901234567890123456789012345678901234567890123456789012"
Jens Wiklander817466c2018-05-22 13:49:31 +0200417 "345678901234567890" }
418};
419
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100420static const size_t md4_test_strlen[7] =
421{
422 0, 1, 3, 14, 26, 62, 80
423};
424
Jens Wiklander817466c2018-05-22 13:49:31 +0200425static const unsigned char md4_test_sum[7][16] =
426{
427 { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31,
428 0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 },
429 { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46,
430 0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 },
431 { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52,
432 0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D },
433 { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8,
434 0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B },
435 { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD,
436 0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 },
437 { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35,
438 0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 },
439 { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19,
440 0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 }
441};
442
443/*
444 * Checkup routine
445 */
446int mbedtls_md4_self_test( int verbose )
447{
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100448 int i, ret = 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200449 unsigned char md4sum[16];
450
451 for( i = 0; i < 7; i++ )
452 {
453 if( verbose != 0 )
454 mbedtls_printf( " MD4 test #%d: ", i + 1 );
455
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100456 ret = mbedtls_md4_ret( md4_test_str[i], md4_test_strlen[i], md4sum );
457 if( ret != 0 )
458 goto fail;
Jens Wiklander817466c2018-05-22 13:49:31 +0200459
460 if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 )
461 {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100462 ret = 1;
463 goto fail;
Jens Wiklander817466c2018-05-22 13:49:31 +0200464 }
465
466 if( verbose != 0 )
467 mbedtls_printf( "passed\n" );
468 }
469
470 if( verbose != 0 )
471 mbedtls_printf( "\n" );
472
473 return( 0 );
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100474
475fail:
476 if( verbose != 0 )
477 mbedtls_printf( "failed\n" );
478
479 return( ret );
Jens Wiklander817466c2018-05-22 13:49:31 +0200480}
481
482#endif /* MBEDTLS_SELF_TEST */
483
484#endif /* MBEDTLS_MD4_C */