blob: 48b4ccd842bd148d421debdafdc395e2114ecc85 [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"
Jerome Forissier11fa71b2020-04-20 17:17:56 +020038#include "mbedtls/error.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020039
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
Jens Wiklander817466c2018-05-22 13:49:31 +020053/*
54 * 32-bit integer manipulation macros (little endian)
55 */
56#ifndef GET_UINT32_LE
57#define GET_UINT32_LE(n,b,i) \
58{ \
59 (n) = ( (uint32_t) (b)[(i) ] ) \
60 | ( (uint32_t) (b)[(i) + 1] << 8 ) \
61 | ( (uint32_t) (b)[(i) + 2] << 16 ) \
62 | ( (uint32_t) (b)[(i) + 3] << 24 ); \
63}
64#endif
65
66#ifndef PUT_UINT32_LE
67#define PUT_UINT32_LE(n,b,i) \
68{ \
69 (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \
70 (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \
71 (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \
72 (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \
73}
74#endif
75
76void mbedtls_md4_init( mbedtls_md4_context *ctx )
77{
78 memset( ctx, 0, sizeof( mbedtls_md4_context ) );
79}
80
81void mbedtls_md4_free( mbedtls_md4_context *ctx )
82{
83 if( ctx == NULL )
84 return;
85
Jens Wiklander3d3b0592019-03-20 15:30:29 +010086 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md4_context ) );
Jens Wiklander817466c2018-05-22 13:49:31 +020087}
88
89void mbedtls_md4_clone( mbedtls_md4_context *dst,
90 const mbedtls_md4_context *src )
91{
92 *dst = *src;
93}
94
95/*
96 * MD4 context setup
97 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +010098int mbedtls_md4_starts_ret( mbedtls_md4_context *ctx )
Jens Wiklander817466c2018-05-22 13:49:31 +020099{
100 ctx->total[0] = 0;
101 ctx->total[1] = 0;
102
103 ctx->state[0] = 0x67452301;
104 ctx->state[1] = 0xEFCDAB89;
105 ctx->state[2] = 0x98BADCFE;
106 ctx->state[3] = 0x10325476;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100107
108 return( 0 );
Jens Wiklander817466c2018-05-22 13:49:31 +0200109}
110
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100111#if !defined(MBEDTLS_DEPRECATED_REMOVED)
112void mbedtls_md4_starts( mbedtls_md4_context *ctx )
113{
114 mbedtls_md4_starts_ret( ctx );
115}
116#endif
117
Jens Wiklander817466c2018-05-22 13:49:31 +0200118#if !defined(MBEDTLS_MD4_PROCESS_ALT)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100119int mbedtls_internal_md4_process( mbedtls_md4_context *ctx,
120 const unsigned char data[64] )
Jens Wiklander817466c2018-05-22 13:49:31 +0200121{
122 uint32_t X[16], A, B, C, D;
123
124 GET_UINT32_LE( X[ 0], data, 0 );
125 GET_UINT32_LE( X[ 1], data, 4 );
126 GET_UINT32_LE( X[ 2], data, 8 );
127 GET_UINT32_LE( X[ 3], data, 12 );
128 GET_UINT32_LE( X[ 4], data, 16 );
129 GET_UINT32_LE( X[ 5], data, 20 );
130 GET_UINT32_LE( X[ 6], data, 24 );
131 GET_UINT32_LE( X[ 7], data, 28 );
132 GET_UINT32_LE( X[ 8], data, 32 );
133 GET_UINT32_LE( X[ 9], data, 36 );
134 GET_UINT32_LE( X[10], data, 40 );
135 GET_UINT32_LE( X[11], data, 44 );
136 GET_UINT32_LE( X[12], data, 48 );
137 GET_UINT32_LE( X[13], data, 52 );
138 GET_UINT32_LE( X[14], data, 56 );
139 GET_UINT32_LE( X[15], data, 60 );
140
Jerome Forissier5b25c762020-04-07 11:18:49 +0200141#define S(x,n) (((x) << (n)) | (((x) & 0xFFFFFFFF) >> (32 - (n))))
Jens Wiklander817466c2018-05-22 13:49:31 +0200142
143 A = ctx->state[0];
144 B = ctx->state[1];
145 C = ctx->state[2];
146 D = ctx->state[3];
147
Jerome Forissier5b25c762020-04-07 11:18:49 +0200148#define F(x, y, z) (((x) & (y)) | ((~(x)) & (z)))
149#define P(a,b,c,d,x,s) \
150 do \
151 { \
152 (a) += F((b),(c),(d)) + (x); \
153 (a) = S((a),(s)); \
154 } while( 0 )
155
Jens Wiklander817466c2018-05-22 13:49:31 +0200156
157 P( A, B, C, D, X[ 0], 3 );
158 P( D, A, B, C, X[ 1], 7 );
159 P( C, D, A, B, X[ 2], 11 );
160 P( B, C, D, A, X[ 3], 19 );
161 P( A, B, C, D, X[ 4], 3 );
162 P( D, A, B, C, X[ 5], 7 );
163 P( C, D, A, B, X[ 6], 11 );
164 P( B, C, D, A, X[ 7], 19 );
165 P( A, B, C, D, X[ 8], 3 );
166 P( D, A, B, C, X[ 9], 7 );
167 P( C, D, A, B, X[10], 11 );
168 P( B, C, D, A, X[11], 19 );
169 P( A, B, C, D, X[12], 3 );
170 P( D, A, B, C, X[13], 7 );
171 P( C, D, A, B, X[14], 11 );
172 P( B, C, D, A, X[15], 19 );
173
174#undef P
175#undef F
176
Jerome Forissier5b25c762020-04-07 11:18:49 +0200177#define F(x,y,z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
178#define P(a,b,c,d,x,s) \
179 do \
180 { \
181 (a) += F((b),(c),(d)) + (x) + 0x5A827999; \
182 (a) = S((a),(s)); \
183 } while( 0 )
Jens Wiklander817466c2018-05-22 13:49:31 +0200184
185 P( A, B, C, D, X[ 0], 3 );
186 P( D, A, B, C, X[ 4], 5 );
187 P( C, D, A, B, X[ 8], 9 );
188 P( B, C, D, A, X[12], 13 );
189 P( A, B, C, D, X[ 1], 3 );
190 P( D, A, B, C, X[ 5], 5 );
191 P( C, D, A, B, X[ 9], 9 );
192 P( B, C, D, A, X[13], 13 );
193 P( A, B, C, D, X[ 2], 3 );
194 P( D, A, B, C, X[ 6], 5 );
195 P( C, D, A, B, X[10], 9 );
196 P( B, C, D, A, X[14], 13 );
197 P( A, B, C, D, X[ 3], 3 );
198 P( D, A, B, C, X[ 7], 5 );
199 P( C, D, A, B, X[11], 9 );
200 P( B, C, D, A, X[15], 13 );
201
202#undef P
203#undef F
204
Jerome Forissier5b25c762020-04-07 11:18:49 +0200205#define F(x,y,z) ((x) ^ (y) ^ (z))
206#define P(a,b,c,d,x,s) \
207 do \
208 { \
209 (a) += F((b),(c),(d)) + (x) + 0x6ED9EBA1; \
210 (a) = S((a),(s)); \
211 } while( 0 )
Jens Wiklander817466c2018-05-22 13:49:31 +0200212
213 P( A, B, C, D, X[ 0], 3 );
214 P( D, A, B, C, X[ 8], 9 );
215 P( C, D, A, B, X[ 4], 11 );
216 P( B, C, D, A, X[12], 15 );
217 P( A, B, C, D, X[ 2], 3 );
218 P( D, A, B, C, X[10], 9 );
219 P( C, D, A, B, X[ 6], 11 );
220 P( B, C, D, A, X[14], 15 );
221 P( A, B, C, D, X[ 1], 3 );
222 P( D, A, B, C, X[ 9], 9 );
223 P( C, D, A, B, X[ 5], 11 );
224 P( B, C, D, A, X[13], 15 );
225 P( A, B, C, D, X[ 3], 3 );
226 P( D, A, B, C, X[11], 9 );
227 P( C, D, A, B, X[ 7], 11 );
228 P( B, C, D, A, X[15], 15 );
229
230#undef F
231#undef P
232
233 ctx->state[0] += A;
234 ctx->state[1] += B;
235 ctx->state[2] += C;
236 ctx->state[3] += D;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100237
238 return( 0 );
Jens Wiklander817466c2018-05-22 13:49:31 +0200239}
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100240
241#if !defined(MBEDTLS_DEPRECATED_REMOVED)
242void mbedtls_md4_process( mbedtls_md4_context *ctx,
243 const unsigned char data[64] )
244{
245 mbedtls_internal_md4_process( ctx, data );
246}
247#endif
Jens Wiklander817466c2018-05-22 13:49:31 +0200248#endif /* !MBEDTLS_MD4_PROCESS_ALT */
249
250/*
251 * MD4 process buffer
252 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100253int mbedtls_md4_update_ret( mbedtls_md4_context *ctx,
254 const unsigned char *input,
255 size_t ilen )
Jens Wiklander817466c2018-05-22 13:49:31 +0200256{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200257 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200258 size_t fill;
259 uint32_t left;
260
261 if( ilen == 0 )
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100262 return( 0 );
Jens Wiklander817466c2018-05-22 13:49:31 +0200263
264 left = ctx->total[0] & 0x3F;
265 fill = 64 - left;
266
267 ctx->total[0] += (uint32_t) ilen;
268 ctx->total[0] &= 0xFFFFFFFF;
269
270 if( ctx->total[0] < (uint32_t) ilen )
271 ctx->total[1]++;
272
273 if( left && ilen >= fill )
274 {
275 memcpy( (void *) (ctx->buffer + left),
276 (void *) input, fill );
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100277
278 if( ( ret = mbedtls_internal_md4_process( ctx, ctx->buffer ) ) != 0 )
279 return( ret );
280
Jens Wiklander817466c2018-05-22 13:49:31 +0200281 input += fill;
282 ilen -= fill;
283 left = 0;
284 }
285
286 while( ilen >= 64 )
287 {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100288 if( ( ret = mbedtls_internal_md4_process( ctx, input ) ) != 0 )
289 return( ret );
290
Jens Wiklander817466c2018-05-22 13:49:31 +0200291 input += 64;
292 ilen -= 64;
293 }
294
295 if( ilen > 0 )
296 {
297 memcpy( (void *) (ctx->buffer + left),
298 (void *) input, ilen );
299 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100300
301 return( 0 );
Jens Wiklander817466c2018-05-22 13:49:31 +0200302}
303
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100304#if !defined(MBEDTLS_DEPRECATED_REMOVED)
305void mbedtls_md4_update( mbedtls_md4_context *ctx,
306 const unsigned char *input,
307 size_t ilen )
308{
309 mbedtls_md4_update_ret( ctx, input, ilen );
310}
311#endif
312
Jens Wiklander817466c2018-05-22 13:49:31 +0200313static const unsigned char md4_padding[64] =
314{
315 0x80, 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 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
319};
320
321/*
322 * MD4 final digest
323 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100324int mbedtls_md4_finish_ret( mbedtls_md4_context *ctx,
325 unsigned char output[16] )
Jens Wiklander817466c2018-05-22 13:49:31 +0200326{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200327 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200328 uint32_t last, padn;
329 uint32_t high, low;
330 unsigned char msglen[8];
331
332 high = ( ctx->total[0] >> 29 )
333 | ( ctx->total[1] << 3 );
334 low = ( ctx->total[0] << 3 );
335
336 PUT_UINT32_LE( low, msglen, 0 );
337 PUT_UINT32_LE( high, msglen, 4 );
338
339 last = ctx->total[0] & 0x3F;
340 padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
341
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100342 ret = mbedtls_md4_update_ret( ctx, (unsigned char *)md4_padding, padn );
343 if( ret != 0 )
344 return( ret );
345
346 if( ( ret = mbedtls_md4_update_ret( ctx, msglen, 8 ) ) != 0 )
347 return( ret );
348
Jens Wiklander817466c2018-05-22 13:49:31 +0200349
350 PUT_UINT32_LE( ctx->state[0], output, 0 );
351 PUT_UINT32_LE( ctx->state[1], output, 4 );
352 PUT_UINT32_LE( ctx->state[2], output, 8 );
353 PUT_UINT32_LE( ctx->state[3], output, 12 );
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100354
355 return( 0 );
Jens Wiklander817466c2018-05-22 13:49:31 +0200356}
357
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100358#if !defined(MBEDTLS_DEPRECATED_REMOVED)
359void mbedtls_md4_finish( mbedtls_md4_context *ctx,
360 unsigned char output[16] )
361{
362 mbedtls_md4_finish_ret( ctx, output );
363}
364#endif
365
Jens Wiklander817466c2018-05-22 13:49:31 +0200366#endif /* !MBEDTLS_MD4_ALT */
367
368/*
369 * output = MD4( input buffer )
370 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100371int mbedtls_md4_ret( const unsigned char *input,
372 size_t ilen,
373 unsigned char output[16] )
Jens Wiklander817466c2018-05-22 13:49:31 +0200374{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200375 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200376 mbedtls_md4_context ctx;
377
378 mbedtls_md4_init( &ctx );
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100379
380 if( ( ret = mbedtls_md4_starts_ret( &ctx ) ) != 0 )
381 goto exit;
382
383 if( ( ret = mbedtls_md4_update_ret( &ctx, input, ilen ) ) != 0 )
384 goto exit;
385
386 if( ( ret = mbedtls_md4_finish_ret( &ctx, output ) ) != 0 )
387 goto exit;
388
389exit:
Jens Wiklander817466c2018-05-22 13:49:31 +0200390 mbedtls_md4_free( &ctx );
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100391
392 return( ret );
Jens Wiklander817466c2018-05-22 13:49:31 +0200393}
394
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100395#if !defined(MBEDTLS_DEPRECATED_REMOVED)
396void mbedtls_md4( const unsigned char *input,
397 size_t ilen,
398 unsigned char output[16] )
399{
400 mbedtls_md4_ret( input, ilen, output );
401}
402#endif
403
Jens Wiklander817466c2018-05-22 13:49:31 +0200404#if defined(MBEDTLS_SELF_TEST)
405
406/*
407 * RFC 1320 test vectors
408 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100409static const unsigned char md4_test_str[7][81] =
Jens Wiklander817466c2018-05-22 13:49:31 +0200410{
411 { "" },
412 { "a" },
413 { "abc" },
414 { "message digest" },
415 { "abcdefghijklmnopqrstuvwxyz" },
416 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
Guido Vranken36905f92021-04-22 14:47:51 +0200417 { "12345678901234567890123456789012345678901234567890123456789012345678901234567890" }
Jens Wiklander817466c2018-05-22 13:49:31 +0200418};
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 */