blob: 9a825327f4bb633c5fad89af66483c5d65c04394 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * RFC 1186/1320 compliant MD4 implementation
3 *
Bence Szépkútia2947ac2020-08-19 16:37:36 +02004 * Copyright The Mbed TLS Contributors
Bence Szépkútif744bd72020-06-05 13:02:18 +02005 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6 *
7 * This file is provided under the Apache License 2.0, or the
8 * GNU General Public License v2.0 or later.
9 *
10 * **********
11 * Apache License 2.0:
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +020012 *
13 * Licensed under the Apache License, Version 2.0 (the "License"); you may
14 * not use this file except in compliance with the License.
15 * You may obtain a copy of the License at
16 *
17 * http://www.apache.org/licenses/LICENSE-2.0
18 *
19 * Unless required by applicable law or agreed to in writing, software
20 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
21 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 * See the License for the specific language governing permissions and
23 * limitations under the License.
Paul Bakkerb96f1542010-07-18 20:36:00 +000024 *
Bence Szépkútif744bd72020-06-05 13:02:18 +020025 * **********
26 *
27 * **********
28 * GNU General Public License v2.0 or later:
29 *
30 * This program is free software; you can redistribute it and/or modify
31 * it under the terms of the GNU General Public License as published by
32 * the Free Software Foundation; either version 2 of the License, or
33 * (at your option) any later version.
34 *
35 * This program is distributed in the hope that it will be useful,
36 * but WITHOUT ANY WARRANTY; without even the implied warranty of
37 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38 * GNU General Public License for more details.
39 *
40 * You should have received a copy of the GNU General Public License along
41 * with this program; if not, write to the Free Software Foundation, Inc.,
42 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
43 *
44 * **********
Paul Bakker5121ce52009-01-03 21:22:43 +000045 */
46/*
47 * The MD4 algorithm was designed by Ron Rivest in 1990.
48 *
49 * http://www.ietf.org/rfc/rfc1186.txt
50 * http://www.ietf.org/rfc/rfc1320.txt
51 */
52
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020053#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000054#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020055#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020056#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020057#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000058
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020059#if defined(MBEDTLS_MD4_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000060
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000061#include "mbedtls/md4.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050062#include "mbedtls/platform_util.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000063
Rich Evans00ab4702015-02-06 13:43:58 +000064#include <string.h>
65
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020066#if defined(MBEDTLS_SELF_TEST)
67#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000068#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010069#else
Rich Evans00ab4702015-02-06 13:43:58 +000070#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020071#define mbedtls_printf printf
72#endif /* MBEDTLS_PLATFORM_C */
73#endif /* MBEDTLS_SELF_TEST */
Paul Bakker7dc4c442014-02-01 22:50:26 +010074
Manuel Pégourié-Gonnard8b2641d2015-08-27 20:03:46 +020075#if !defined(MBEDTLS_MD4_ALT)
76
Paul Bakker5121ce52009-01-03 21:22:43 +000077/*
78 * 32-bit integer manipulation macros (little endian)
79 */
Paul Bakker5c2364c2012-10-01 14:41:15 +000080#ifndef GET_UINT32_LE
81#define GET_UINT32_LE(n,b,i) \
Paul Bakker5121ce52009-01-03 21:22:43 +000082{ \
Paul Bakker5c2364c2012-10-01 14:41:15 +000083 (n) = ( (uint32_t) (b)[(i) ] ) \
84 | ( (uint32_t) (b)[(i) + 1] << 8 ) \
85 | ( (uint32_t) (b)[(i) + 2] << 16 ) \
86 | ( (uint32_t) (b)[(i) + 3] << 24 ); \
Paul Bakker5121ce52009-01-03 21:22:43 +000087}
88#endif
89
Paul Bakker5c2364c2012-10-01 14:41:15 +000090#ifndef PUT_UINT32_LE
Manuel Pégourié-Gonnardceedb822015-01-23 15:02:43 +000091#define PUT_UINT32_LE(n,b,i) \
92{ \
93 (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \
94 (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \
95 (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \
96 (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \
Paul Bakker5121ce52009-01-03 21:22:43 +000097}
98#endif
99
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200100void mbedtls_md4_init( mbedtls_md4_context *ctx )
Paul Bakker5b4af392014-06-26 12:09:34 +0200101{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200102 memset( ctx, 0, sizeof( mbedtls_md4_context ) );
Paul Bakker5b4af392014-06-26 12:09:34 +0200103}
104
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200105void mbedtls_md4_free( mbedtls_md4_context *ctx )
Paul Bakker5b4af392014-06-26 12:09:34 +0200106{
107 if( ctx == NULL )
108 return;
109
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500110 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md4_context ) );
Paul Bakker5b4af392014-06-26 12:09:34 +0200111}
112
Manuel Pégourié-Gonnard16d412f2015-07-06 15:26:26 +0200113void mbedtls_md4_clone( mbedtls_md4_context *dst,
114 const mbedtls_md4_context *src )
115{
116 *dst = *src;
117}
118
Paul Bakker5121ce52009-01-03 21:22:43 +0000119/*
120 * MD4 context setup
121 */
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100122int mbedtls_md4_starts_ret( mbedtls_md4_context *ctx )
Paul Bakker5121ce52009-01-03 21:22:43 +0000123{
124 ctx->total[0] = 0;
125 ctx->total[1] = 0;
126
127 ctx->state[0] = 0x67452301;
128 ctx->state[1] = 0xEFCDAB89;
129 ctx->state[2] = 0x98BADCFE;
130 ctx->state[3] = 0x10325476;
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100131
132 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000133}
134
Jaeden Amero041039f2018-02-19 15:28:08 +0000135#if !defined(MBEDTLS_DEPRECATED_REMOVED)
136void mbedtls_md4_starts( mbedtls_md4_context *ctx )
137{
138 mbedtls_md4_starts_ret( ctx );
139}
140#endif
141
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200142#if !defined(MBEDTLS_MD4_PROCESS_ALT)
Andres Amaya Garciacccfe082017-06-28 10:36:39 +0100143int mbedtls_internal_md4_process( mbedtls_md4_context *ctx,
144 const unsigned char data[64] )
Paul Bakker5121ce52009-01-03 21:22:43 +0000145{
gabor-mezei-arm70f7f672020-08-25 19:12:01 +0200146 struct
147 {
148 uint32_t X[16], A, B, C, D;
149 } local;
Paul Bakker5121ce52009-01-03 21:22:43 +0000150
gabor-mezei-arm70f7f672020-08-25 19:12:01 +0200151 GET_UINT32_LE( local.X[ 0], data, 0 );
152 GET_UINT32_LE( local.X[ 1], data, 4 );
153 GET_UINT32_LE( local.X[ 2], data, 8 );
154 GET_UINT32_LE( local.X[ 3], data, 12 );
155 GET_UINT32_LE( local.X[ 4], data, 16 );
156 GET_UINT32_LE( local.X[ 5], data, 20 );
157 GET_UINT32_LE( local.X[ 6], data, 24 );
158 GET_UINT32_LE( local.X[ 7], data, 28 );
159 GET_UINT32_LE( local.X[ 8], data, 32 );
160 GET_UINT32_LE( local.X[ 9], data, 36 );
161 GET_UINT32_LE( local.X[10], data, 40 );
162 GET_UINT32_LE( local.X[11], data, 44 );
163 GET_UINT32_LE( local.X[12], data, 48 );
164 GET_UINT32_LE( local.X[13], data, 52 );
165 GET_UINT32_LE( local.X[14], data, 56 );
166 GET_UINT32_LE( local.X[15], data, 60 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000167
Hanno Beckerd6028a12018-10-15 12:01:35 +0100168#define S(x,n) (((x) << (n)) | (((x) & 0xFFFFFFFF) >> (32 - (n))))
Paul Bakker5121ce52009-01-03 21:22:43 +0000169
gabor-mezei-arm70f7f672020-08-25 19:12:01 +0200170 local.A = ctx->state[0];
171 local.B = ctx->state[1];
172 local.C = ctx->state[2];
173 local.D = ctx->state[3];
Paul Bakker5121ce52009-01-03 21:22:43 +0000174
Hanno Beckerd6028a12018-10-15 12:01:35 +0100175#define F(x, y, z) (((x) & (y)) | ((~(x)) & (z)))
Hanno Becker9306f1c2018-10-30 09:29:25 +0000176#define P(a,b,c,d,x,s) \
177 do \
178 { \
Hanno Becker3ac21ac2018-10-26 09:13:26 +0100179 (a) += F((b),(c),(d)) + (x); \
180 (a) = S((a),(s)); \
Hanno Beckerd6028a12018-10-15 12:01:35 +0100181 } while( 0 )
182
Paul Bakker5121ce52009-01-03 21:22:43 +0000183
gabor-mezei-arm70f7f672020-08-25 19:12:01 +0200184 P( local.A, local.B, local.C, local.D, local.X[ 0], 3 );
185 P( local.D, local.A, local.B, local.C, local.X[ 1], 7 );
186 P( local.C, local.D, local.A, local.B, local.X[ 2], 11 );
187 P( local.B, local.C, local.D, local.A, local.X[ 3], 19 );
188 P( local.A, local.B, local.C, local.D, local.X[ 4], 3 );
189 P( local.D, local.A, local.B, local.C, local.X[ 5], 7 );
190 P( local.C, local.D, local.A, local.B, local.X[ 6], 11 );
191 P( local.B, local.C, local.D, local.A, local.X[ 7], 19 );
192 P( local.A, local.B, local.C, local.D, local.X[ 8], 3 );
193 P( local.D, local.A, local.B, local.C, local.X[ 9], 7 );
194 P( local.C, local.D, local.A, local.B, local.X[10], 11 );
195 P( local.B, local.C, local.D, local.A, local.X[11], 19 );
196 P( local.A, local.B, local.C, local.D, local.X[12], 3 );
197 P( local.D, local.A, local.B, local.C, local.X[13], 7 );
198 P( local.C, local.D, local.A, local.B, local.X[14], 11 );
199 P( local.B, local.C, local.D, local.A, local.X[15], 19 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000200
201#undef P
202#undef F
203
Hanno Beckerd6028a12018-10-15 12:01:35 +0100204#define F(x,y,z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
205#define P(a,b,c,d,x,s) \
206 do \
207 { \
Hanno Becker9306f1c2018-10-30 09:29:25 +0000208 (a) += F((b),(c),(d)) + (x) + 0x5A827999; \
209 (a) = S((a),(s)); \
Hanno Beckerd6028a12018-10-15 12:01:35 +0100210 } while( 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000211
gabor-mezei-arm70f7f672020-08-25 19:12:01 +0200212 P( local.A, local.B, local.C, local.D, local.X[ 0], 3 );
213 P( local.D, local.A, local.B, local.C, local.X[ 4], 5 );
214 P( local.C, local.D, local.A, local.B, local.X[ 8], 9 );
215 P( local.B, local.C, local.D, local.A, local.X[12], 13 );
216 P( local.A, local.B, local.C, local.D, local.X[ 1], 3 );
217 P( local.D, local.A, local.B, local.C, local.X[ 5], 5 );
218 P( local.C, local.D, local.A, local.B, local.X[ 9], 9 );
219 P( local.B, local.C, local.D, local.A, local.X[13], 13 );
220 P( local.A, local.B, local.C, local.D, local.X[ 2], 3 );
221 P( local.D, local.A, local.B, local.C, local.X[ 6], 5 );
222 P( local.C, local.D, local.A, local.B, local.X[10], 9 );
223 P( local.B, local.C, local.D, local.A, local.X[14], 13 );
224 P( local.A, local.B, local.C, local.D, local.X[ 3], 3 );
225 P( local.D, local.A, local.B, local.C, local.X[ 7], 5 );
226 P( local.C, local.D, local.A, local.B, local.X[11], 9 );
227 P( local.B, local.C, local.D, local.A, local.X[15], 13 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000228
229#undef P
230#undef F
231
Hanno Beckerd6028a12018-10-15 12:01:35 +0100232#define F(x,y,z) ((x) ^ (y) ^ (z))
Hanno Becker9306f1c2018-10-30 09:29:25 +0000233#define P(a,b,c,d,x,s) \
234 do \
235 { \
236 (a) += F((b),(c),(d)) + (x) + 0x6ED9EBA1; \
237 (a) = S((a),(s)); \
Hanno Beckerd6028a12018-10-15 12:01:35 +0100238 } while( 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000239
gabor-mezei-arm70f7f672020-08-25 19:12:01 +0200240 P( local.A, local.B, local.C, local.D, local.X[ 0], 3 );
241 P( local.D, local.A, local.B, local.C, local.X[ 8], 9 );
242 P( local.C, local.D, local.A, local.B, local.X[ 4], 11 );
243 P( local.B, local.C, local.D, local.A, local.X[12], 15 );
244 P( local.A, local.B, local.C, local.D, local.X[ 2], 3 );
245 P( local.D, local.A, local.B, local.C, local.X[10], 9 );
246 P( local.C, local.D, local.A, local.B, local.X[ 6], 11 );
247 P( local.B, local.C, local.D, local.A, local.X[14], 15 );
248 P( local.A, local.B, local.C, local.D, local.X[ 1], 3 );
249 P( local.D, local.A, local.B, local.C, local.X[ 9], 9 );
250 P( local.C, local.D, local.A, local.B, local.X[ 5], 11 );
251 P( local.B, local.C, local.D, local.A, local.X[13], 15 );
252 P( local.A, local.B, local.C, local.D, local.X[ 3], 3 );
253 P( local.D, local.A, local.B, local.C, local.X[11], 9 );
254 P( local.C, local.D, local.A, local.B, local.X[ 7], 11 );
255 P( local.B, local.C, local.D, local.A, local.X[15], 15 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000256
257#undef F
258#undef P
259
gabor-mezei-arm70f7f672020-08-25 19:12:01 +0200260 ctx->state[0] += local.A;
261 ctx->state[1] += local.B;
262 ctx->state[2] += local.C;
263 ctx->state[3] += local.D;
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100264
gabor-mezei-armf21639f2020-08-19 14:03:06 +0200265 /* Zeroise variables to clear sensitive data from memory. */
gabor-mezei-arm70f7f672020-08-25 19:12:01 +0200266 mbedtls_platform_zeroize( &local, sizeof( local ) );
gabor-mezei-armf21639f2020-08-19 14:03:06 +0200267
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100268 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000269}
Jaeden Amero041039f2018-02-19 15:28:08 +0000270
271#if !defined(MBEDTLS_DEPRECATED_REMOVED)
272void mbedtls_md4_process( mbedtls_md4_context *ctx,
273 const unsigned char data[64] )
274{
275 mbedtls_internal_md4_process( ctx, data );
276}
277#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200278#endif /* !MBEDTLS_MD4_PROCESS_ALT */
Paul Bakker5121ce52009-01-03 21:22:43 +0000279
280/*
281 * MD4 process buffer
282 */
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100283int mbedtls_md4_update_ret( mbedtls_md4_context *ctx,
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100284 const unsigned char *input,
285 size_t ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000286{
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100287 int ret;
Paul Bakker23986e52011-04-24 08:57:21 +0000288 size_t fill;
Paul Bakker5c2364c2012-10-01 14:41:15 +0000289 uint32_t left;
Paul Bakker5121ce52009-01-03 21:22:43 +0000290
Brian White12895d12014-04-11 11:29:42 -0400291 if( ilen == 0 )
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100292 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000293
294 left = ctx->total[0] & 0x3F;
295 fill = 64 - left;
296
Paul Bakker5c2364c2012-10-01 14:41:15 +0000297 ctx->total[0] += (uint32_t) ilen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000298 ctx->total[0] &= 0xFFFFFFFF;
299
Paul Bakker5c2364c2012-10-01 14:41:15 +0000300 if( ctx->total[0] < (uint32_t) ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000301 ctx->total[1]++;
302
303 if( left && ilen >= fill )
304 {
305 memcpy( (void *) (ctx->buffer + left),
306 (void *) input, fill );
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100307
Andres Amaya Garciacccfe082017-06-28 10:36:39 +0100308 if( ( ret = mbedtls_internal_md4_process( ctx, ctx->buffer ) ) != 0 )
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100309 return( ret );
310
Paul Bakker5121ce52009-01-03 21:22:43 +0000311 input += fill;
312 ilen -= fill;
313 left = 0;
314 }
315
316 while( ilen >= 64 )
317 {
Andres Amaya Garciacccfe082017-06-28 10:36:39 +0100318 if( ( ret = mbedtls_internal_md4_process( ctx, input ) ) != 0 )
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100319 return( ret );
320
Paul Bakker5121ce52009-01-03 21:22:43 +0000321 input += 64;
322 ilen -= 64;
323 }
324
325 if( ilen > 0 )
326 {
327 memcpy( (void *) (ctx->buffer + left),
328 (void *) input, ilen );
329 }
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100330
331 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000332}
333
Jaeden Amero041039f2018-02-19 15:28:08 +0000334#if !defined(MBEDTLS_DEPRECATED_REMOVED)
335void mbedtls_md4_update( mbedtls_md4_context *ctx,
336 const unsigned char *input,
337 size_t ilen )
338{
339 mbedtls_md4_update_ret( ctx, input, ilen );
340}
341#endif
342
Paul Bakker5121ce52009-01-03 21:22:43 +0000343static const unsigned char md4_padding[64] =
344{
345 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
346 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
347 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
348 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
349};
350
351/*
352 * MD4 final digest
353 */
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100354int mbedtls_md4_finish_ret( mbedtls_md4_context *ctx,
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100355 unsigned char output[16] )
Paul Bakker5121ce52009-01-03 21:22:43 +0000356{
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100357 int ret;
Paul Bakker5c2364c2012-10-01 14:41:15 +0000358 uint32_t last, padn;
359 uint32_t high, low;
Paul Bakker5121ce52009-01-03 21:22:43 +0000360 unsigned char msglen[8];
361
362 high = ( ctx->total[0] >> 29 )
363 | ( ctx->total[1] << 3 );
364 low = ( ctx->total[0] << 3 );
365
Paul Bakker5c2364c2012-10-01 14:41:15 +0000366 PUT_UINT32_LE( low, msglen, 0 );
367 PUT_UINT32_LE( high, msglen, 4 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000368
369 last = ctx->total[0] & 0x3F;
370 padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
371
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100372 ret = mbedtls_md4_update_ret( ctx, (unsigned char *)md4_padding, padn );
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100373 if( ret != 0 )
374 return( ret );
375
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100376 if( ( ret = mbedtls_md4_update_ret( ctx, msglen, 8 ) ) != 0 )
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100377 return( ret );
378
Paul Bakker5121ce52009-01-03 21:22:43 +0000379
Paul Bakker5c2364c2012-10-01 14:41:15 +0000380 PUT_UINT32_LE( ctx->state[0], output, 0 );
381 PUT_UINT32_LE( ctx->state[1], output, 4 );
382 PUT_UINT32_LE( ctx->state[2], output, 8 );
383 PUT_UINT32_LE( ctx->state[3], output, 12 );
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100384
385 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000386}
387
Jaeden Amero041039f2018-02-19 15:28:08 +0000388#if !defined(MBEDTLS_DEPRECATED_REMOVED)
389void mbedtls_md4_finish( mbedtls_md4_context *ctx,
390 unsigned char output[16] )
391{
392 mbedtls_md4_finish_ret( ctx, output );
393}
394#endif
395
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200396#endif /* !MBEDTLS_MD4_ALT */
Paul Bakker90995b52013-06-24 19:20:35 +0200397
Paul Bakker5121ce52009-01-03 21:22:43 +0000398/*
399 * output = MD4( input buffer )
400 */
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100401int mbedtls_md4_ret( const unsigned char *input,
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100402 size_t ilen,
403 unsigned char output[16] )
Paul Bakker5121ce52009-01-03 21:22:43 +0000404{
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100405 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200406 mbedtls_md4_context ctx;
Paul Bakker5121ce52009-01-03 21:22:43 +0000407
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200408 mbedtls_md4_init( &ctx );
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100409
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100410 if( ( ret = mbedtls_md4_starts_ret( &ctx ) ) != 0 )
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100411 goto exit;
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100412
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100413 if( ( ret = mbedtls_md4_update_ret( &ctx, input, ilen ) ) != 0 )
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100414 goto exit;
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100415
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100416 if( ( ret = mbedtls_md4_finish_ret( &ctx, output ) ) != 0 )
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100417 goto exit;
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100418
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100419exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200420 mbedtls_md4_free( &ctx );
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100421
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100422 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000423}
424
Jaeden Amero041039f2018-02-19 15:28:08 +0000425#if !defined(MBEDTLS_DEPRECATED_REMOVED)
426void mbedtls_md4( const unsigned char *input,
427 size_t ilen,
428 unsigned char output[16] )
429{
430 mbedtls_md4_ret( input, ilen, output );
431}
432#endif
433
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200434#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000435
436/*
437 * RFC 1320 test vectors
438 */
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100439static const unsigned char md4_test_str[7][81] =
Paul Bakker5121ce52009-01-03 21:22:43 +0000440{
Paul Bakker9af723c2014-05-01 13:03:14 +0200441 { "" },
Paul Bakker5121ce52009-01-03 21:22:43 +0000442 { "a" },
443 { "abc" },
444 { "message digest" },
445 { "abcdefghijklmnopqrstuvwxyz" },
446 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
Guido Vranken70bdf8d2020-08-21 21:08:56 +0200447 { "12345678901234567890123456789012345678901234567890123456789012345678901234567890" }
Paul Bakker5121ce52009-01-03 21:22:43 +0000448};
449
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100450static const size_t md4_test_strlen[7] =
451{
452 0, 1, 3, 14, 26, 62, 80
453};
454
Paul Bakker5121ce52009-01-03 21:22:43 +0000455static const unsigned char md4_test_sum[7][16] =
456{
457 { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31,
458 0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 },
459 { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46,
460 0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 },
461 { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52,
462 0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D },
463 { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8,
464 0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B },
465 { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD,
466 0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 },
467 { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35,
468 0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 },
469 { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19,
470 0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 }
471};
472
473/*
474 * Checkup routine
475 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200476int mbedtls_md4_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +0000477{
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100478 int i, ret = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000479 unsigned char md4sum[16];
480
481 for( i = 0; i < 7; i++ )
482 {
483 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200484 mbedtls_printf( " MD4 test #%d: ", i + 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000485
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100486 ret = mbedtls_md4_ret( md4_test_str[i], md4_test_strlen[i], md4sum );
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100487 if( ret != 0 )
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100488 goto fail;
Paul Bakker5121ce52009-01-03 21:22:43 +0000489
490 if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 )
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100491 {
492 ret = 1;
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100493 goto fail;
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100494 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000495
496 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200497 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000498 }
499
500 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200501 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000502
503 return( 0 );
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100504
505fail:
506 if( verbose != 0 )
507 mbedtls_printf( "failed\n" );
508
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100509 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000510}
511
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200512#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +0000513
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200514#endif /* MBEDTLS_MD4_C */