blob: 4fd6bc3e459dbbc34364fa62f9eb1871b4e350de [file] [log] [blame]
Jens Wiklander817466c2018-05-22 13:49:31 +02001/*
2 * RFC 1186/1320 compliant MD4 implementation
3 *
Jerome Forissier79013242021-07-28 10:24:04 +02004 * Copyright The Mbed TLS Contributors
5 * SPDX-License-Identifier: Apache-2.0
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.
Jens Wiklander817466c2018-05-22 13:49:31 +020018 */
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
Jerome Forissier79013242021-07-28 10:24:04 +020026#include "common.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020027
28#if defined(MBEDTLS_MD4_C)
29
30#include "mbedtls/md4.h"
Jens Wiklander3d3b0592019-03-20 15:30:29 +010031#include "mbedtls/platform_util.h"
Jerome Forissier11fa71b2020-04-20 17:17:56 +020032#include "mbedtls/error.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020033
34#include <string.h>
35
36#if defined(MBEDTLS_SELF_TEST)
37#if defined(MBEDTLS_PLATFORM_C)
38#include "mbedtls/platform.h"
39#else
40#include <stdio.h>
41#define mbedtls_printf printf
42#endif /* MBEDTLS_PLATFORM_C */
43#endif /* MBEDTLS_SELF_TEST */
44
45#if !defined(MBEDTLS_MD4_ALT)
46
Jens Wiklander817466c2018-05-22 13:49:31 +020047/*
48 * 32-bit integer manipulation macros (little endian)
49 */
50#ifndef GET_UINT32_LE
51#define GET_UINT32_LE(n,b,i) \
52{ \
53 (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 ); \
57}
58#endif
59
60#ifndef PUT_UINT32_LE
61#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 ); \
67}
68#endif
69
70void mbedtls_md4_init( mbedtls_md4_context *ctx )
71{
72 memset( ctx, 0, sizeof( mbedtls_md4_context ) );
73}
74
75void mbedtls_md4_free( mbedtls_md4_context *ctx )
76{
77 if( ctx == NULL )
78 return;
79
Jens Wiklander3d3b0592019-03-20 15:30:29 +010080 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md4_context ) );
Jens Wiklander817466c2018-05-22 13:49:31 +020081}
82
83void mbedtls_md4_clone( mbedtls_md4_context *dst,
84 const mbedtls_md4_context *src )
85{
86 *dst = *src;
87}
88
89/*
90 * MD4 context setup
91 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +010092int mbedtls_md4_starts_ret( mbedtls_md4_context *ctx )
Jens Wiklander817466c2018-05-22 13:49:31 +020093{
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;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100101
102 return( 0 );
Jens Wiklander817466c2018-05-22 13:49:31 +0200103}
104
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100105#if !defined(MBEDTLS_DEPRECATED_REMOVED)
106void mbedtls_md4_starts( mbedtls_md4_context *ctx )
107{
108 mbedtls_md4_starts_ret( ctx );
109}
110#endif
111
Jens Wiklander817466c2018-05-22 13:49:31 +0200112#if !defined(MBEDTLS_MD4_PROCESS_ALT)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100113int mbedtls_internal_md4_process( mbedtls_md4_context *ctx,
114 const unsigned char data[64] )
Jens Wiklander817466c2018-05-22 13:49:31 +0200115{
Jerome Forissier79013242021-07-28 10:24:04 +0200116 struct
117 {
118 uint32_t X[16], A, B, C, D;
119 } local;
Jens Wiklander817466c2018-05-22 13:49:31 +0200120
Jerome Forissier79013242021-07-28 10:24:04 +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 );
Jens Wiklander817466c2018-05-22 13:49:31 +0200137
Jerome Forissier5b25c762020-04-07 11:18:49 +0200138#define S(x,n) (((x) << (n)) | (((x) & 0xFFFFFFFF) >> (32 - (n))))
Jens Wiklander817466c2018-05-22 13:49:31 +0200139
Jerome Forissier79013242021-07-28 10:24:04 +0200140 local.A = ctx->state[0];
141 local.B = ctx->state[1];
142 local.C = ctx->state[2];
143 local.D = ctx->state[3];
Jens Wiklander817466c2018-05-22 13:49:31 +0200144
Jerome Forissier5b25c762020-04-07 11:18:49 +0200145#define F(x, y, z) (((x) & (y)) | ((~(x)) & (z)))
146#define P(a,b,c,d,x,s) \
147 do \
148 { \
149 (a) += F((b),(c),(d)) + (x); \
150 (a) = S((a),(s)); \
151 } while( 0 )
152
Jens Wiklander817466c2018-05-22 13:49:31 +0200153
Jerome Forissier79013242021-07-28 10:24:04 +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 );
Jens Wiklander817466c2018-05-22 13:49:31 +0200170
171#undef P
172#undef F
173
Jerome Forissier5b25c762020-04-07 11:18:49 +0200174#define F(x,y,z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
175#define P(a,b,c,d,x,s) \
176 do \
177 { \
178 (a) += F((b),(c),(d)) + (x) + 0x5A827999; \
179 (a) = S((a),(s)); \
180 } while( 0 )
Jens Wiklander817466c2018-05-22 13:49:31 +0200181
Jerome Forissier79013242021-07-28 10:24:04 +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 );
Jens Wiklander817466c2018-05-22 13:49:31 +0200198
199#undef P
200#undef F
201
Jerome Forissier5b25c762020-04-07 11:18:49 +0200202#define F(x,y,z) ((x) ^ (y) ^ (z))
203#define P(a,b,c,d,x,s) \
204 do \
205 { \
206 (a) += F((b),(c),(d)) + (x) + 0x6ED9EBA1; \
207 (a) = S((a),(s)); \
208 } while( 0 )
Jens Wiklander817466c2018-05-22 13:49:31 +0200209
Jerome Forissier79013242021-07-28 10:24:04 +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 );
Jens Wiklander817466c2018-05-22 13:49:31 +0200226
227#undef F
228#undef P
229
Jerome Forissier79013242021-07-28 10:24:04 +0200230 ctx->state[0] += local.A;
231 ctx->state[1] += local.B;
232 ctx->state[2] += local.C;
233 ctx->state[3] += local.D;
234
235 /* Zeroise variables to clear sensitive data from memory. */
236 mbedtls_platform_zeroize( &local, sizeof( local ) );
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 */