blob: eaa679a0a6eee95d436ef2f979fd30d8cfd5ec81 [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
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020047void mbedtls_md4_init( mbedtls_md4_context *ctx )
Paul Bakker5b4af392014-06-26 12:09:34 +020048{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020049 memset( ctx, 0, sizeof( mbedtls_md4_context ) );
Paul Bakker5b4af392014-06-26 12:09:34 +020050}
51
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020052void mbedtls_md4_free( mbedtls_md4_context *ctx )
Paul Bakker5b4af392014-06-26 12:09:34 +020053{
54 if( ctx == NULL )
55 return;
56
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050057 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md4_context ) );
Paul Bakker5b4af392014-06-26 12:09:34 +020058}
59
Manuel Pégourié-Gonnard16d412f2015-07-06 15:26:26 +020060void mbedtls_md4_clone( mbedtls_md4_context *dst,
61 const mbedtls_md4_context *src )
62{
63 *dst = *src;
64}
65
Paul Bakker5121ce52009-01-03 21:22:43 +000066/*
67 * MD4 context setup
68 */
Gilles Peskine9e4f77c2018-01-22 11:48:08 +010069int mbedtls_md4_starts_ret( mbedtls_md4_context *ctx )
Paul Bakker5121ce52009-01-03 21:22:43 +000070{
71 ctx->total[0] = 0;
72 ctx->total[1] = 0;
73
74 ctx->state[0] = 0x67452301;
75 ctx->state[1] = 0xEFCDAB89;
76 ctx->state[2] = 0x98BADCFE;
77 ctx->state[3] = 0x10325476;
Andres Amaya Garciabee06352017-04-28 17:00:30 +010078
79 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +000080}
81
Manuel Pégourié-Gonnard93c08472021-04-15 12:23:55 +020082#if !defined(MBEDTLS_DEPRECATED_REMOVED)
83void mbedtls_md4_starts( mbedtls_md4_context *ctx )
84{
85 mbedtls_md4_starts_ret( ctx );
86}
87#endif
88
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020089#if !defined(MBEDTLS_MD4_PROCESS_ALT)
Andres Amaya Garciacccfe082017-06-28 10:36:39 +010090int mbedtls_internal_md4_process( mbedtls_md4_context *ctx,
91 const unsigned char data[64] )
Paul Bakker5121ce52009-01-03 21:22:43 +000092{
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +020093 struct
94 {
95 uint32_t X[16], A, B, C, D;
96 } local;
Paul Bakker5121ce52009-01-03 21:22:43 +000097
Joe Subbianica8a7cf2021-08-03 16:42:42 +010098 local.X[ 0] = MBEDTLS_GET_UINT32_LE( data, 0 );
99 local.X[ 1] = MBEDTLS_GET_UINT32_LE( data, 4 );
100 local.X[ 2] = MBEDTLS_GET_UINT32_LE( data, 8 );
101 local.X[ 3] = MBEDTLS_GET_UINT32_LE( data, 12 );
102 local.X[ 4] = MBEDTLS_GET_UINT32_LE( data, 16 );
103 local.X[ 5] = MBEDTLS_GET_UINT32_LE( data, 20 );
104 local.X[ 6] = MBEDTLS_GET_UINT32_LE( data, 24 );
105 local.X[ 7] = MBEDTLS_GET_UINT32_LE( data, 28 );
106 local.X[ 8] = MBEDTLS_GET_UINT32_LE( data, 32 );
107 local.X[ 9] = MBEDTLS_GET_UINT32_LE( data, 36 );
108 local.X[10] = MBEDTLS_GET_UINT32_LE( data, 40 );
109 local.X[11] = MBEDTLS_GET_UINT32_LE( data, 44 );
110 local.X[12] = MBEDTLS_GET_UINT32_LE( data, 48 );
111 local.X[13] = MBEDTLS_GET_UINT32_LE( data, 52 );
112 local.X[14] = MBEDTLS_GET_UINT32_LE( data, 56 );
113 local.X[15] = MBEDTLS_GET_UINT32_LE( data, 60 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000114
Hanno Becker1eeca412018-10-15 12:01:35 +0100115#define S(x,n) (((x) << (n)) | (((x) & 0xFFFFFFFF) >> (32 - (n))))
Paul Bakker5121ce52009-01-03 21:22:43 +0000116
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200117 local.A = ctx->state[0];
118 local.B = ctx->state[1];
119 local.C = ctx->state[2];
120 local.D = ctx->state[3];
Paul Bakker5121ce52009-01-03 21:22:43 +0000121
Hanno Becker1eeca412018-10-15 12:01:35 +0100122#define F(x, y, z) (((x) & (y)) | ((~(x)) & (z)))
Hanno Becker26d02e12018-10-30 09:29:25 +0000123#define P(a,b,c,d,x,s) \
124 do \
125 { \
Hanno Becker818bac52018-10-26 09:13:26 +0100126 (a) += F((b),(c),(d)) + (x); \
127 (a) = S((a),(s)); \
Hanno Becker1eeca412018-10-15 12:01:35 +0100128 } while( 0 )
129
Paul Bakker5121ce52009-01-03 21:22:43 +0000130
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200131 P( local.A, local.B, local.C, local.D, local.X[ 0], 3 );
132 P( local.D, local.A, local.B, local.C, local.X[ 1], 7 );
133 P( local.C, local.D, local.A, local.B, local.X[ 2], 11 );
134 P( local.B, local.C, local.D, local.A, local.X[ 3], 19 );
135 P( local.A, local.B, local.C, local.D, local.X[ 4], 3 );
136 P( local.D, local.A, local.B, local.C, local.X[ 5], 7 );
137 P( local.C, local.D, local.A, local.B, local.X[ 6], 11 );
138 P( local.B, local.C, local.D, local.A, local.X[ 7], 19 );
139 P( local.A, local.B, local.C, local.D, local.X[ 8], 3 );
140 P( local.D, local.A, local.B, local.C, local.X[ 9], 7 );
141 P( local.C, local.D, local.A, local.B, local.X[10], 11 );
142 P( local.B, local.C, local.D, local.A, local.X[11], 19 );
143 P( local.A, local.B, local.C, local.D, local.X[12], 3 );
144 P( local.D, local.A, local.B, local.C, local.X[13], 7 );
145 P( local.C, local.D, local.A, local.B, local.X[14], 11 );
146 P( local.B, local.C, local.D, local.A, local.X[15], 19 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000147
148#undef P
149#undef F
150
Hanno Becker1eeca412018-10-15 12:01:35 +0100151#define F(x,y,z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
152#define P(a,b,c,d,x,s) \
153 do \
154 { \
Hanno Becker26d02e12018-10-30 09:29:25 +0000155 (a) += F((b),(c),(d)) + (x) + 0x5A827999; \
156 (a) = S((a),(s)); \
Hanno Becker1eeca412018-10-15 12:01:35 +0100157 } while( 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000158
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200159 P( local.A, local.B, local.C, local.D, local.X[ 0], 3 );
160 P( local.D, local.A, local.B, local.C, local.X[ 4], 5 );
161 P( local.C, local.D, local.A, local.B, local.X[ 8], 9 );
162 P( local.B, local.C, local.D, local.A, local.X[12], 13 );
163 P( local.A, local.B, local.C, local.D, local.X[ 1], 3 );
164 P( local.D, local.A, local.B, local.C, local.X[ 5], 5 );
165 P( local.C, local.D, local.A, local.B, local.X[ 9], 9 );
166 P( local.B, local.C, local.D, local.A, local.X[13], 13 );
167 P( local.A, local.B, local.C, local.D, local.X[ 2], 3 );
168 P( local.D, local.A, local.B, local.C, local.X[ 6], 5 );
169 P( local.C, local.D, local.A, local.B, local.X[10], 9 );
170 P( local.B, local.C, local.D, local.A, local.X[14], 13 );
171 P( local.A, local.B, local.C, local.D, local.X[ 3], 3 );
172 P( local.D, local.A, local.B, local.C, local.X[ 7], 5 );
173 P( local.C, local.D, local.A, local.B, local.X[11], 9 );
174 P( local.B, local.C, local.D, local.A, local.X[15], 13 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000175
176#undef P
177#undef F
178
Hanno Becker1eeca412018-10-15 12:01:35 +0100179#define F(x,y,z) ((x) ^ (y) ^ (z))
Hanno Becker26d02e12018-10-30 09:29:25 +0000180#define P(a,b,c,d,x,s) \
181 do \
182 { \
183 (a) += F((b),(c),(d)) + (x) + 0x6ED9EBA1; \
184 (a) = S((a),(s)); \
Hanno Becker1eeca412018-10-15 12:01:35 +0100185 } while( 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000186
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200187 P( local.A, local.B, local.C, local.D, local.X[ 0], 3 );
188 P( local.D, local.A, local.B, local.C, local.X[ 8], 9 );
189 P( local.C, local.D, local.A, local.B, local.X[ 4], 11 );
190 P( local.B, local.C, local.D, local.A, local.X[12], 15 );
191 P( local.A, local.B, local.C, local.D, local.X[ 2], 3 );
192 P( local.D, local.A, local.B, local.C, local.X[10], 9 );
193 P( local.C, local.D, local.A, local.B, local.X[ 6], 11 );
194 P( local.B, local.C, local.D, local.A, local.X[14], 15 );
195 P( local.A, local.B, local.C, local.D, local.X[ 1], 3 );
196 P( local.D, local.A, local.B, local.C, local.X[ 9], 9 );
197 P( local.C, local.D, local.A, local.B, local.X[ 5], 11 );
198 P( local.B, local.C, local.D, local.A, local.X[13], 15 );
199 P( local.A, local.B, local.C, local.D, local.X[ 3], 3 );
200 P( local.D, local.A, local.B, local.C, local.X[11], 9 );
201 P( local.C, local.D, local.A, local.B, local.X[ 7], 11 );
202 P( local.B, local.C, local.D, local.A, local.X[15], 15 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000203
204#undef F
205#undef P
206
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200207 ctx->state[0] += local.A;
208 ctx->state[1] += local.B;
209 ctx->state[2] += local.C;
210 ctx->state[3] += local.D;
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100211
gabor-mezei-armd1c98fc2020-08-19 14:03:06 +0200212 /* Zeroise variables to clear sensitive data from memory. */
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200213 mbedtls_platform_zeroize( &local, sizeof( local ) );
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100214
215 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000216}
Jaeden Amero041039f2018-02-19 15:28:08 +0000217
Manuel Pégourié-Gonnard93c08472021-04-15 12:23:55 +0200218#if !defined(MBEDTLS_DEPRECATED_REMOVED)
219void mbedtls_md4_process( mbedtls_md4_context *ctx,
220 const unsigned char data[64] )
221{
222 mbedtls_internal_md4_process( ctx, data );
223}
224#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200225#endif /* !MBEDTLS_MD4_PROCESS_ALT */
Paul Bakker5121ce52009-01-03 21:22:43 +0000226
227/*
228 * MD4 process buffer
229 */
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100230int mbedtls_md4_update_ret( mbedtls_md4_context *ctx,
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100231 const unsigned char *input,
232 size_t ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000233{
Janos Follath24eed8d2019-11-22 13:21:35 +0000234 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000235 size_t fill;
Paul Bakker5c2364c2012-10-01 14:41:15 +0000236 uint32_t left;
Paul Bakker5121ce52009-01-03 21:22:43 +0000237
Brian White12895d12014-04-11 11:29:42 -0400238 if( ilen == 0 )
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100239 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000240
241 left = ctx->total[0] & 0x3F;
242 fill = 64 - left;
243
Paul Bakker5c2364c2012-10-01 14:41:15 +0000244 ctx->total[0] += (uint32_t) ilen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000245 ctx->total[0] &= 0xFFFFFFFF;
246
Paul Bakker5c2364c2012-10-01 14:41:15 +0000247 if( ctx->total[0] < (uint32_t) ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000248 ctx->total[1]++;
249
250 if( left && ilen >= fill )
251 {
252 memcpy( (void *) (ctx->buffer + left),
253 (void *) input, fill );
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100254
Andres Amaya Garciacccfe082017-06-28 10:36:39 +0100255 if( ( ret = mbedtls_internal_md4_process( ctx, ctx->buffer ) ) != 0 )
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100256 return( ret );
257
Paul Bakker5121ce52009-01-03 21:22:43 +0000258 input += fill;
259 ilen -= fill;
260 left = 0;
261 }
262
263 while( ilen >= 64 )
264 {
Andres Amaya Garciacccfe082017-06-28 10:36:39 +0100265 if( ( ret = mbedtls_internal_md4_process( ctx, input ) ) != 0 )
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100266 return( ret );
267
Paul Bakker5121ce52009-01-03 21:22:43 +0000268 input += 64;
269 ilen -= 64;
270 }
271
272 if( ilen > 0 )
273 {
274 memcpy( (void *) (ctx->buffer + left),
275 (void *) input, ilen );
276 }
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100277
278 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000279}
280
Manuel Pégourié-Gonnard93c08472021-04-15 12:23:55 +0200281#if !defined(MBEDTLS_DEPRECATED_REMOVED)
282void mbedtls_md4_update( mbedtls_md4_context *ctx,
283 const unsigned char *input,
284 size_t ilen )
285{
286 mbedtls_md4_update_ret( ctx, input, ilen );
287}
288#endif
289
Paul Bakker5121ce52009-01-03 21:22:43 +0000290static const unsigned char md4_padding[64] =
291{
292 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
293 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
294 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
295 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
296};
297
298/*
299 * MD4 final digest
300 */
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100301int mbedtls_md4_finish_ret( mbedtls_md4_context *ctx,
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100302 unsigned char output[16] )
Paul Bakker5121ce52009-01-03 21:22:43 +0000303{
Janos Follath24eed8d2019-11-22 13:21:35 +0000304 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker5c2364c2012-10-01 14:41:15 +0000305 uint32_t last, padn;
306 uint32_t high, low;
Paul Bakker5121ce52009-01-03 21:22:43 +0000307 unsigned char msglen[8];
308
309 high = ( ctx->total[0] >> 29 )
310 | ( ctx->total[1] << 3 );
311 low = ( ctx->total[0] << 3 );
312
Joe Subbianica8a7cf2021-08-03 16:42:42 +0100313 MBEDTLS_PUT_UINT32_LE( low, msglen, 0 );
314 MBEDTLS_PUT_UINT32_LE( high, msglen, 4 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000315
316 last = ctx->total[0] & 0x3F;
317 padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
318
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100319 ret = mbedtls_md4_update_ret( ctx, (unsigned char *)md4_padding, padn );
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100320 if( ret != 0 )
321 return( ret );
322
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100323 if( ( ret = mbedtls_md4_update_ret( ctx, msglen, 8 ) ) != 0 )
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100324 return( ret );
325
Paul Bakker5121ce52009-01-03 21:22:43 +0000326
Joe Subbianica8a7cf2021-08-03 16:42:42 +0100327 MBEDTLS_PUT_UINT32_LE( ctx->state[0], output, 0 );
328 MBEDTLS_PUT_UINT32_LE( ctx->state[1], output, 4 );
329 MBEDTLS_PUT_UINT32_LE( ctx->state[2], output, 8 );
330 MBEDTLS_PUT_UINT32_LE( ctx->state[3], output, 12 );
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100331
332 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000333}
334
Manuel Pégourié-Gonnard93c08472021-04-15 12:23:55 +0200335#if !defined(MBEDTLS_DEPRECATED_REMOVED)
336void mbedtls_md4_finish( mbedtls_md4_context *ctx,
337 unsigned char output[16] )
338{
339 mbedtls_md4_finish_ret( ctx, output );
340}
341#endif
342
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200343#endif /* !MBEDTLS_MD4_ALT */
Paul Bakker90995b52013-06-24 19:20:35 +0200344
Paul Bakker5121ce52009-01-03 21:22:43 +0000345/*
346 * output = MD4( input buffer )
347 */
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100348int mbedtls_md4_ret( const unsigned char *input,
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100349 size_t ilen,
350 unsigned char output[16] )
Paul Bakker5121ce52009-01-03 21:22:43 +0000351{
Janos Follath24eed8d2019-11-22 13:21:35 +0000352 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200353 mbedtls_md4_context ctx;
Paul Bakker5121ce52009-01-03 21:22:43 +0000354
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200355 mbedtls_md4_init( &ctx );
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100356
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100357 if( ( ret = mbedtls_md4_starts_ret( &ctx ) ) != 0 )
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100358 goto exit;
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100359
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100360 if( ( ret = mbedtls_md4_update_ret( &ctx, input, ilen ) ) != 0 )
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100361 goto exit;
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100362
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100363 if( ( ret = mbedtls_md4_finish_ret( &ctx, output ) ) != 0 )
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100364 goto exit;
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100365
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100366exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200367 mbedtls_md4_free( &ctx );
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100368
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100369 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000370}
371
Manuel Pégourié-Gonnard93c08472021-04-15 12:23:55 +0200372#if !defined(MBEDTLS_DEPRECATED_REMOVED)
373void mbedtls_md4( const unsigned char *input,
374 size_t ilen,
375 unsigned char output[16] )
376{
377 mbedtls_md4_ret( input, ilen, output );
378}
379#endif
380
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200381#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000382
383/*
384 * RFC 1320 test vectors
385 */
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100386static const unsigned char md4_test_str[7][81] =
Paul Bakker5121ce52009-01-03 21:22:43 +0000387{
Paul Bakker9af723c2014-05-01 13:03:14 +0200388 { "" },
Paul Bakker5121ce52009-01-03 21:22:43 +0000389 { "a" },
390 { "abc" },
391 { "message digest" },
392 { "abcdefghijklmnopqrstuvwxyz" },
393 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
Guido Vranken962e4ee2020-08-21 21:08:56 +0200394 { "12345678901234567890123456789012345678901234567890123456789012345678901234567890" }
Paul Bakker5121ce52009-01-03 21:22:43 +0000395};
396
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100397static const size_t md4_test_strlen[7] =
398{
399 0, 1, 3, 14, 26, 62, 80
400};
401
Paul Bakker5121ce52009-01-03 21:22:43 +0000402static const unsigned char md4_test_sum[7][16] =
403{
404 { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31,
405 0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 },
406 { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46,
407 0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 },
408 { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52,
409 0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D },
410 { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8,
411 0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B },
412 { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD,
413 0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 },
414 { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35,
415 0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 },
416 { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19,
417 0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 }
418};
419
420/*
421 * Checkup routine
422 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200423int mbedtls_md4_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +0000424{
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100425 int i, ret = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000426 unsigned char md4sum[16];
427
428 for( i = 0; i < 7; i++ )
429 {
430 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200431 mbedtls_printf( " MD4 test #%d: ", i + 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000432
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100433 ret = mbedtls_md4_ret( md4_test_str[i], md4_test_strlen[i], md4sum );
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100434 if( ret != 0 )
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100435 goto fail;
Paul Bakker5121ce52009-01-03 21:22:43 +0000436
437 if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 )
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100438 {
439 ret = 1;
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100440 goto fail;
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100441 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000442
443 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200444 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000445 }
446
447 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200448 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000449
450 return( 0 );
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100451
452fail:
453 if( verbose != 0 )
454 mbedtls_printf( "failed\n" );
455
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100456 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000457}
458
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200459#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +0000460
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200461#endif /* MBEDTLS_MD4_C */