blob: 4fd6bc3e459dbbc34364fa62f9eb1871b4e350de [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * RFC 1186/1320 compliant MD4 implementation
3 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02004 * Copyright The Mbed TLS Contributors
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * 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.
Paul Bakker5121ce52009-01-03 21:22:43 +000018 */
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
Gilles Peskinedb09ef62020-06-03 01:43:33 +020026#include "common.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000027
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020028#if defined(MBEDTLS_MD4_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000029
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000030#include "mbedtls/md4.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050031#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000032#include "mbedtls/error.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000033
Rich Evans00ab4702015-02-06 13:43:58 +000034#include <string.h>
35
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020036#if defined(MBEDTLS_SELF_TEST)
37#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000038#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010039#else
Rich Evans00ab4702015-02-06 13:43:58 +000040#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020041#define mbedtls_printf printf
42#endif /* MBEDTLS_PLATFORM_C */
43#endif /* MBEDTLS_SELF_TEST */
Paul Bakker7dc4c442014-02-01 22:50:26 +010044
Manuel Pégourié-Gonnard8b2641d2015-08-27 20:03:46 +020045#if !defined(MBEDTLS_MD4_ALT)
46
Paul Bakker5121ce52009-01-03 21:22:43 +000047/*
48 * 32-bit integer manipulation macros (little endian)
49 */
Paul Bakker5c2364c2012-10-01 14:41:15 +000050#ifndef GET_UINT32_LE
51#define GET_UINT32_LE(n,b,i) \
Paul Bakker5121ce52009-01-03 21:22:43 +000052{ \
Paul Bakker5c2364c2012-10-01 14:41:15 +000053 (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 ); \
Paul Bakker5121ce52009-01-03 21:22:43 +000057}
58#endif
59
Paul Bakker5c2364c2012-10-01 14:41:15 +000060#ifndef PUT_UINT32_LE
Manuel Pégourié-Gonnardceedb822015-01-23 15:02:43 +000061#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 ); \
Paul Bakker5121ce52009-01-03 21:22:43 +000067}
68#endif
69
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020070void mbedtls_md4_init( mbedtls_md4_context *ctx )
Paul Bakker5b4af392014-06-26 12:09:34 +020071{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020072 memset( ctx, 0, sizeof( mbedtls_md4_context ) );
Paul Bakker5b4af392014-06-26 12:09:34 +020073}
74
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020075void mbedtls_md4_free( mbedtls_md4_context *ctx )
Paul Bakker5b4af392014-06-26 12:09:34 +020076{
77 if( ctx == NULL )
78 return;
79
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050080 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md4_context ) );
Paul Bakker5b4af392014-06-26 12:09:34 +020081}
82
Manuel Pégourié-Gonnard16d412f2015-07-06 15:26:26 +020083void mbedtls_md4_clone( mbedtls_md4_context *dst,
84 const mbedtls_md4_context *src )
85{
86 *dst = *src;
87}
88
Paul Bakker5121ce52009-01-03 21:22:43 +000089/*
90 * MD4 context setup
91 */
Gilles Peskine9e4f77c2018-01-22 11:48:08 +010092int mbedtls_md4_starts_ret( mbedtls_md4_context *ctx )
Paul Bakker5121ce52009-01-03 21:22:43 +000093{
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;
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100101
102 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000103}
104
Manuel Pégourié-Gonnard93c08472021-04-15 12:23:55 +0200105#if !defined(MBEDTLS_DEPRECATED_REMOVED)
106void mbedtls_md4_starts( mbedtls_md4_context *ctx )
107{
108 mbedtls_md4_starts_ret( ctx );
109}
110#endif
111
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200112#if !defined(MBEDTLS_MD4_PROCESS_ALT)
Andres Amaya Garciacccfe082017-06-28 10:36:39 +0100113int mbedtls_internal_md4_process( mbedtls_md4_context *ctx,
114 const unsigned char data[64] )
Paul Bakker5121ce52009-01-03 21:22:43 +0000115{
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200116 struct
117 {
118 uint32_t X[16], A, B, C, D;
119 } local;
Paul Bakker5121ce52009-01-03 21:22:43 +0000120
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200121 GET_UINT32_LE( local.X[ 0], data, 0 );
122 GET_UINT32_LE( local.X[ 1], data, 4 );
123 GET_UINT32_LE( local.X[ 2], data, 8 );
124 GET_UINT32_LE( local.X[ 3], data, 12 );
125 GET_UINT32_LE( local.X[ 4], data, 16 );
126 GET_UINT32_LE( local.X[ 5], data, 20 );
127 GET_UINT32_LE( local.X[ 6], data, 24 );
128 GET_UINT32_LE( local.X[ 7], data, 28 );
129 GET_UINT32_LE( local.X[ 8], data, 32 );
130 GET_UINT32_LE( local.X[ 9], data, 36 );
131 GET_UINT32_LE( local.X[10], data, 40 );
132 GET_UINT32_LE( local.X[11], data, 44 );
133 GET_UINT32_LE( local.X[12], data, 48 );
134 GET_UINT32_LE( local.X[13], data, 52 );
135 GET_UINT32_LE( local.X[14], data, 56 );
136 GET_UINT32_LE( local.X[15], data, 60 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000137
Hanno Becker1eeca412018-10-15 12:01:35 +0100138#define S(x,n) (((x) << (n)) | (((x) & 0xFFFFFFFF) >> (32 - (n))))
Paul Bakker5121ce52009-01-03 21:22:43 +0000139
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200140 local.A = ctx->state[0];
141 local.B = ctx->state[1];
142 local.C = ctx->state[2];
143 local.D = ctx->state[3];
Paul Bakker5121ce52009-01-03 21:22:43 +0000144
Hanno Becker1eeca412018-10-15 12:01:35 +0100145#define F(x, y, z) (((x) & (y)) | ((~(x)) & (z)))
Hanno Becker26d02e12018-10-30 09:29:25 +0000146#define P(a,b,c,d,x,s) \
147 do \
148 { \
Hanno Becker818bac52018-10-26 09:13:26 +0100149 (a) += F((b),(c),(d)) + (x); \
150 (a) = S((a),(s)); \
Hanno Becker1eeca412018-10-15 12:01:35 +0100151 } while( 0 )
152
Paul Bakker5121ce52009-01-03 21:22:43 +0000153
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200154 P( local.A, local.B, local.C, local.D, local.X[ 0], 3 );
155 P( local.D, local.A, local.B, local.C, local.X[ 1], 7 );
156 P( local.C, local.D, local.A, local.B, local.X[ 2], 11 );
157 P( local.B, local.C, local.D, local.A, local.X[ 3], 19 );
158 P( local.A, local.B, local.C, local.D, local.X[ 4], 3 );
159 P( local.D, local.A, local.B, local.C, local.X[ 5], 7 );
160 P( local.C, local.D, local.A, local.B, local.X[ 6], 11 );
161 P( local.B, local.C, local.D, local.A, local.X[ 7], 19 );
162 P( local.A, local.B, local.C, local.D, local.X[ 8], 3 );
163 P( local.D, local.A, local.B, local.C, local.X[ 9], 7 );
164 P( local.C, local.D, local.A, local.B, local.X[10], 11 );
165 P( local.B, local.C, local.D, local.A, local.X[11], 19 );
166 P( local.A, local.B, local.C, local.D, local.X[12], 3 );
167 P( local.D, local.A, local.B, local.C, local.X[13], 7 );
168 P( local.C, local.D, local.A, local.B, local.X[14], 11 );
169 P( local.B, local.C, local.D, local.A, local.X[15], 19 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000170
171#undef P
172#undef F
173
Hanno Becker1eeca412018-10-15 12:01:35 +0100174#define F(x,y,z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
175#define P(a,b,c,d,x,s) \
176 do \
177 { \
Hanno Becker26d02e12018-10-30 09:29:25 +0000178 (a) += F((b),(c),(d)) + (x) + 0x5A827999; \
179 (a) = S((a),(s)); \
Hanno Becker1eeca412018-10-15 12:01:35 +0100180 } while( 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000181
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200182 P( local.A, local.B, local.C, local.D, local.X[ 0], 3 );
183 P( local.D, local.A, local.B, local.C, local.X[ 4], 5 );
184 P( local.C, local.D, local.A, local.B, local.X[ 8], 9 );
185 P( local.B, local.C, local.D, local.A, local.X[12], 13 );
186 P( local.A, local.B, local.C, local.D, local.X[ 1], 3 );
187 P( local.D, local.A, local.B, local.C, local.X[ 5], 5 );
188 P( local.C, local.D, local.A, local.B, local.X[ 9], 9 );
189 P( local.B, local.C, local.D, local.A, local.X[13], 13 );
190 P( local.A, local.B, local.C, local.D, local.X[ 2], 3 );
191 P( local.D, local.A, local.B, local.C, local.X[ 6], 5 );
192 P( local.C, local.D, local.A, local.B, local.X[10], 9 );
193 P( local.B, local.C, local.D, local.A, local.X[14], 13 );
194 P( local.A, local.B, local.C, local.D, local.X[ 3], 3 );
195 P( local.D, local.A, local.B, local.C, local.X[ 7], 5 );
196 P( local.C, local.D, local.A, local.B, local.X[11], 9 );
197 P( local.B, local.C, local.D, local.A, local.X[15], 13 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000198
199#undef P
200#undef F
201
Hanno Becker1eeca412018-10-15 12:01:35 +0100202#define F(x,y,z) ((x) ^ (y) ^ (z))
Hanno Becker26d02e12018-10-30 09:29:25 +0000203#define P(a,b,c,d,x,s) \
204 do \
205 { \
206 (a) += F((b),(c),(d)) + (x) + 0x6ED9EBA1; \
207 (a) = S((a),(s)); \
Hanno Becker1eeca412018-10-15 12:01:35 +0100208 } while( 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000209
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200210 P( local.A, local.B, local.C, local.D, local.X[ 0], 3 );
211 P( local.D, local.A, local.B, local.C, local.X[ 8], 9 );
212 P( local.C, local.D, local.A, local.B, local.X[ 4], 11 );
213 P( local.B, local.C, local.D, local.A, local.X[12], 15 );
214 P( local.A, local.B, local.C, local.D, local.X[ 2], 3 );
215 P( local.D, local.A, local.B, local.C, local.X[10], 9 );
216 P( local.C, local.D, local.A, local.B, local.X[ 6], 11 );
217 P( local.B, local.C, local.D, local.A, local.X[14], 15 );
218 P( local.A, local.B, local.C, local.D, local.X[ 1], 3 );
219 P( local.D, local.A, local.B, local.C, local.X[ 9], 9 );
220 P( local.C, local.D, local.A, local.B, local.X[ 5], 11 );
221 P( local.B, local.C, local.D, local.A, local.X[13], 15 );
222 P( local.A, local.B, local.C, local.D, local.X[ 3], 3 );
223 P( local.D, local.A, local.B, local.C, local.X[11], 9 );
224 P( local.C, local.D, local.A, local.B, local.X[ 7], 11 );
225 P( local.B, local.C, local.D, local.A, local.X[15], 15 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000226
227#undef F
228#undef P
229
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200230 ctx->state[0] += local.A;
231 ctx->state[1] += local.B;
232 ctx->state[2] += local.C;
233 ctx->state[3] += local.D;
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100234
gabor-mezei-armd1c98fc2020-08-19 14:03:06 +0200235 /* Zeroise variables to clear sensitive data from memory. */
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200236 mbedtls_platform_zeroize( &local, sizeof( local ) );
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100237
238 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000239}
Jaeden Amero041039f2018-02-19 15:28:08 +0000240
Manuel Pégourié-Gonnard93c08472021-04-15 12:23:55 +0200241#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
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200248#endif /* !MBEDTLS_MD4_PROCESS_ALT */
Paul Bakker5121ce52009-01-03 21:22:43 +0000249
250/*
251 * MD4 process buffer
252 */
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100253int mbedtls_md4_update_ret( mbedtls_md4_context *ctx,
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100254 const unsigned char *input,
255 size_t ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000256{
Janos Follath24eed8d2019-11-22 13:21:35 +0000257 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000258 size_t fill;
Paul Bakker5c2364c2012-10-01 14:41:15 +0000259 uint32_t left;
Paul Bakker5121ce52009-01-03 21:22:43 +0000260
Brian White12895d12014-04-11 11:29:42 -0400261 if( ilen == 0 )
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100262 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000263
264 left = ctx->total[0] & 0x3F;
265 fill = 64 - left;
266
Paul Bakker5c2364c2012-10-01 14:41:15 +0000267 ctx->total[0] += (uint32_t) ilen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000268 ctx->total[0] &= 0xFFFFFFFF;
269
Paul Bakker5c2364c2012-10-01 14:41:15 +0000270 if( ctx->total[0] < (uint32_t) ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000271 ctx->total[1]++;
272
273 if( left && ilen >= fill )
274 {
275 memcpy( (void *) (ctx->buffer + left),
276 (void *) input, fill );
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100277
Andres Amaya Garciacccfe082017-06-28 10:36:39 +0100278 if( ( ret = mbedtls_internal_md4_process( ctx, ctx->buffer ) ) != 0 )
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100279 return( ret );
280
Paul Bakker5121ce52009-01-03 21:22:43 +0000281 input += fill;
282 ilen -= fill;
283 left = 0;
284 }
285
286 while( ilen >= 64 )
287 {
Andres Amaya Garciacccfe082017-06-28 10:36:39 +0100288 if( ( ret = mbedtls_internal_md4_process( ctx, input ) ) != 0 )
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100289 return( ret );
290
Paul Bakker5121ce52009-01-03 21:22:43 +0000291 input += 64;
292 ilen -= 64;
293 }
294
295 if( ilen > 0 )
296 {
297 memcpy( (void *) (ctx->buffer + left),
298 (void *) input, ilen );
299 }
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100300
301 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000302}
303
Manuel Pégourié-Gonnard93c08472021-04-15 12:23:55 +0200304#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
Paul Bakker5121ce52009-01-03 21:22:43 +0000313static 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 */
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100324int mbedtls_md4_finish_ret( mbedtls_md4_context *ctx,
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100325 unsigned char output[16] )
Paul Bakker5121ce52009-01-03 21:22:43 +0000326{
Janos Follath24eed8d2019-11-22 13:21:35 +0000327 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker5c2364c2012-10-01 14:41:15 +0000328 uint32_t last, padn;
329 uint32_t high, low;
Paul Bakker5121ce52009-01-03 21:22:43 +0000330 unsigned char msglen[8];
331
332 high = ( ctx->total[0] >> 29 )
333 | ( ctx->total[1] << 3 );
334 low = ( ctx->total[0] << 3 );
335
Paul Bakker5c2364c2012-10-01 14:41:15 +0000336 PUT_UINT32_LE( low, msglen, 0 );
337 PUT_UINT32_LE( high, msglen, 4 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000338
339 last = ctx->total[0] & 0x3F;
340 padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
341
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100342 ret = mbedtls_md4_update_ret( ctx, (unsigned char *)md4_padding, padn );
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100343 if( ret != 0 )
344 return( ret );
345
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100346 if( ( ret = mbedtls_md4_update_ret( ctx, msglen, 8 ) ) != 0 )
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100347 return( ret );
348
Paul Bakker5121ce52009-01-03 21:22:43 +0000349
Paul Bakker5c2364c2012-10-01 14:41:15 +0000350 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 );
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100354
355 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000356}
357
Manuel Pégourié-Gonnard93c08472021-04-15 12:23:55 +0200358#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
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200366#endif /* !MBEDTLS_MD4_ALT */
Paul Bakker90995b52013-06-24 19:20:35 +0200367
Paul Bakker5121ce52009-01-03 21:22:43 +0000368/*
369 * output = MD4( input buffer )
370 */
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100371int mbedtls_md4_ret( const unsigned char *input,
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100372 size_t ilen,
373 unsigned char output[16] )
Paul Bakker5121ce52009-01-03 21:22:43 +0000374{
Janos Follath24eed8d2019-11-22 13:21:35 +0000375 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200376 mbedtls_md4_context ctx;
Paul Bakker5121ce52009-01-03 21:22:43 +0000377
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200378 mbedtls_md4_init( &ctx );
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100379
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100380 if( ( ret = mbedtls_md4_starts_ret( &ctx ) ) != 0 )
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100381 goto exit;
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100382
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100383 if( ( ret = mbedtls_md4_update_ret( &ctx, input, ilen ) ) != 0 )
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100384 goto exit;
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100385
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100386 if( ( ret = mbedtls_md4_finish_ret( &ctx, output ) ) != 0 )
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100387 goto exit;
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100388
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100389exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200390 mbedtls_md4_free( &ctx );
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100391
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100392 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000393}
394
Manuel Pégourié-Gonnard93c08472021-04-15 12:23:55 +0200395#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
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200404#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000405
406/*
407 * RFC 1320 test vectors
408 */
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100409static const unsigned char md4_test_str[7][81] =
Paul Bakker5121ce52009-01-03 21:22:43 +0000410{
Paul Bakker9af723c2014-05-01 13:03:14 +0200411 { "" },
Paul Bakker5121ce52009-01-03 21:22:43 +0000412 { "a" },
413 { "abc" },
414 { "message digest" },
415 { "abcdefghijklmnopqrstuvwxyz" },
416 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
Guido Vranken962e4ee2020-08-21 21:08:56 +0200417 { "12345678901234567890123456789012345678901234567890123456789012345678901234567890" }
Paul Bakker5121ce52009-01-03 21:22:43 +0000418};
419
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100420static const size_t md4_test_strlen[7] =
421{
422 0, 1, 3, 14, 26, 62, 80
423};
424
Paul Bakker5121ce52009-01-03 21:22:43 +0000425static 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 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200446int mbedtls_md4_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +0000447{
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100448 int i, ret = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000449 unsigned char md4sum[16];
450
451 for( i = 0; i < 7; i++ )
452 {
453 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200454 mbedtls_printf( " MD4 test #%d: ", i + 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000455
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100456 ret = mbedtls_md4_ret( md4_test_str[i], md4_test_strlen[i], md4sum );
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100457 if( ret != 0 )
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100458 goto fail;
Paul Bakker5121ce52009-01-03 21:22:43 +0000459
460 if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 )
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100461 {
462 ret = 1;
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100463 goto fail;
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100464 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000465
466 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200467 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000468 }
469
470 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200471 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000472
473 return( 0 );
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100474
475fail:
476 if( verbose != 0 )
477 mbedtls_printf( "failed\n" );
478
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100479 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000480}
481
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200482#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +0000483
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200484#endif /* MBEDTLS_MD4_C */