blob: 943c953ffd9105f742f838be003aca52d8041b69 [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" },
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100417 { "12345678901234567890123456789012345678901234567890123456789012"
Jens Wiklander817466c2018-05-22 13:49:31 +0200418 "345678901234567890" }
419};
420
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100421static const size_t md4_test_strlen[7] =
422{
423 0, 1, 3, 14, 26, 62, 80
424};
425
Jens Wiklander817466c2018-05-22 13:49:31 +0200426static const unsigned char md4_test_sum[7][16] =
427{
428 { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31,
429 0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 },
430 { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46,
431 0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 },
432 { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52,
433 0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D },
434 { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8,
435 0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B },
436 { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD,
437 0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 },
438 { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35,
439 0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 },
440 { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19,
441 0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 }
442};
443
444/*
445 * Checkup routine
446 */
447int mbedtls_md4_self_test( int verbose )
448{
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100449 int i, ret = 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200450 unsigned char md4sum[16];
451
452 for( i = 0; i < 7; i++ )
453 {
454 if( verbose != 0 )
455 mbedtls_printf( " MD4 test #%d: ", i + 1 );
456
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100457 ret = mbedtls_md4_ret( md4_test_str[i], md4_test_strlen[i], md4sum );
458 if( ret != 0 )
459 goto fail;
Jens Wiklander817466c2018-05-22 13:49:31 +0200460
461 if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 )
462 {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100463 ret = 1;
464 goto fail;
Jens Wiklander817466c2018-05-22 13:49:31 +0200465 }
466
467 if( verbose != 0 )
468 mbedtls_printf( "passed\n" );
469 }
470
471 if( verbose != 0 )
472 mbedtls_printf( "\n" );
473
474 return( 0 );
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100475
476fail:
477 if( verbose != 0 )
478 mbedtls_printf( "failed\n" );
479
480 return( ret );
Jens Wiklander817466c2018-05-22 13:49:31 +0200481}
482
483#endif /* MBEDTLS_SELF_TEST */
484
485#endif /* MBEDTLS_MD4_C */