blob: 63bdcecf08328eb696cc147d9bc09a3cf068739d [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{
Paul Bakker5c2364c2012-10-01 14:41:15 +0000146 uint32_t X[16], A, B, C, D;
Paul Bakker5121ce52009-01-03 21:22:43 +0000147
Paul Bakker5c2364c2012-10-01 14:41:15 +0000148 GET_UINT32_LE( X[ 0], data, 0 );
149 GET_UINT32_LE( X[ 1], data, 4 );
150 GET_UINT32_LE( X[ 2], data, 8 );
151 GET_UINT32_LE( X[ 3], data, 12 );
152 GET_UINT32_LE( X[ 4], data, 16 );
153 GET_UINT32_LE( X[ 5], data, 20 );
154 GET_UINT32_LE( X[ 6], data, 24 );
155 GET_UINT32_LE( X[ 7], data, 28 );
156 GET_UINT32_LE( X[ 8], data, 32 );
157 GET_UINT32_LE( X[ 9], data, 36 );
158 GET_UINT32_LE( X[10], data, 40 );
159 GET_UINT32_LE( X[11], data, 44 );
160 GET_UINT32_LE( X[12], data, 48 );
161 GET_UINT32_LE( X[13], data, 52 );
162 GET_UINT32_LE( X[14], data, 56 );
163 GET_UINT32_LE( X[15], data, 60 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000164
Hanno Beckerd6028a12018-10-15 12:01:35 +0100165#define S(x,n) (((x) << (n)) | (((x) & 0xFFFFFFFF) >> (32 - (n))))
Paul Bakker5121ce52009-01-03 21:22:43 +0000166
167 A = ctx->state[0];
168 B = ctx->state[1];
169 C = ctx->state[2];
170 D = ctx->state[3];
171
Hanno Beckerd6028a12018-10-15 12:01:35 +0100172#define F(x, y, z) (((x) & (y)) | ((~(x)) & (z)))
Hanno Becker9306f1c2018-10-30 09:29:25 +0000173#define P(a,b,c,d,x,s) \
174 do \
175 { \
Hanno Becker3ac21ac2018-10-26 09:13:26 +0100176 (a) += F((b),(c),(d)) + (x); \
177 (a) = S((a),(s)); \
Hanno Beckerd6028a12018-10-15 12:01:35 +0100178 } while( 0 )
179
Paul Bakker5121ce52009-01-03 21:22:43 +0000180
181 P( A, B, C, D, X[ 0], 3 );
182 P( D, A, B, C, X[ 1], 7 );
183 P( C, D, A, B, X[ 2], 11 );
184 P( B, C, D, A, X[ 3], 19 );
185 P( A, B, C, D, X[ 4], 3 );
186 P( D, A, B, C, X[ 5], 7 );
187 P( C, D, A, B, X[ 6], 11 );
188 P( B, C, D, A, X[ 7], 19 );
189 P( A, B, C, D, X[ 8], 3 );
190 P( D, A, B, C, X[ 9], 7 );
191 P( C, D, A, B, X[10], 11 );
192 P( B, C, D, A, X[11], 19 );
193 P( A, B, C, D, X[12], 3 );
194 P( D, A, B, C, X[13], 7 );
195 P( C, D, A, B, X[14], 11 );
196 P( B, C, D, A, X[15], 19 );
197
198#undef P
199#undef F
200
Hanno Beckerd6028a12018-10-15 12:01:35 +0100201#define F(x,y,z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
202#define P(a,b,c,d,x,s) \
203 do \
204 { \
Hanno Becker9306f1c2018-10-30 09:29:25 +0000205 (a) += F((b),(c),(d)) + (x) + 0x5A827999; \
206 (a) = S((a),(s)); \
Hanno Beckerd6028a12018-10-15 12:01:35 +0100207 } while( 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000208
209 P( A, B, C, D, X[ 0], 3 );
210 P( D, A, B, C, X[ 4], 5 );
211 P( C, D, A, B, X[ 8], 9 );
212 P( B, C, D, A, X[12], 13 );
213 P( A, B, C, D, X[ 1], 3 );
214 P( D, A, B, C, X[ 5], 5 );
215 P( C, D, A, B, X[ 9], 9 );
216 P( B, C, D, A, X[13], 13 );
217 P( A, B, C, D, X[ 2], 3 );
218 P( D, A, B, C, X[ 6], 5 );
219 P( C, D, A, B, X[10], 9 );
220 P( B, C, D, A, X[14], 13 );
221 P( A, B, C, D, X[ 3], 3 );
222 P( D, A, B, C, X[ 7], 5 );
223 P( C, D, A, B, X[11], 9 );
224 P( B, C, D, A, X[15], 13 );
225
226#undef P
227#undef F
228
Hanno Beckerd6028a12018-10-15 12:01:35 +0100229#define F(x,y,z) ((x) ^ (y) ^ (z))
Hanno Becker9306f1c2018-10-30 09:29:25 +0000230#define P(a,b,c,d,x,s) \
231 do \
232 { \
233 (a) += F((b),(c),(d)) + (x) + 0x6ED9EBA1; \
234 (a) = S((a),(s)); \
Hanno Beckerd6028a12018-10-15 12:01:35 +0100235 } while( 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000236
237 P( A, B, C, D, X[ 0], 3 );
238 P( D, A, B, C, X[ 8], 9 );
239 P( C, D, A, B, X[ 4], 11 );
240 P( B, C, D, A, X[12], 15 );
241 P( A, B, C, D, X[ 2], 3 );
242 P( D, A, B, C, X[10], 9 );
243 P( C, D, A, B, X[ 6], 11 );
244 P( B, C, D, A, X[14], 15 );
245 P( A, B, C, D, X[ 1], 3 );
246 P( D, A, B, C, X[ 9], 9 );
247 P( C, D, A, B, X[ 5], 11 );
248 P( B, C, D, A, X[13], 15 );
249 P( A, B, C, D, X[ 3], 3 );
250 P( D, A, B, C, X[11], 9 );
251 P( C, D, A, B, X[ 7], 11 );
252 P( B, C, D, A, X[15], 15 );
253
254#undef F
255#undef P
256
257 ctx->state[0] += A;
258 ctx->state[1] += B;
259 ctx->state[2] += C;
260 ctx->state[3] += D;
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100261
gabor-mezei-armf21639f2020-08-19 14:03:06 +0200262 /* Zeroise variables to clear sensitive data from memory. */
263 mbedtls_platform_zeroize( &X, sizeof( X ) );
264 mbedtls_platform_zeroize( &A, sizeof( A ) );
265 mbedtls_platform_zeroize( &B, sizeof( B ) );
266 mbedtls_platform_zeroize( &C, sizeof( C ) );
267 mbedtls_platform_zeroize( &D, sizeof( D ) );
268
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100269 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000270}
Jaeden Amero041039f2018-02-19 15:28:08 +0000271
272#if !defined(MBEDTLS_DEPRECATED_REMOVED)
273void mbedtls_md4_process( mbedtls_md4_context *ctx,
274 const unsigned char data[64] )
275{
276 mbedtls_internal_md4_process( ctx, data );
277}
278#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200279#endif /* !MBEDTLS_MD4_PROCESS_ALT */
Paul Bakker5121ce52009-01-03 21:22:43 +0000280
281/*
282 * MD4 process buffer
283 */
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100284int mbedtls_md4_update_ret( mbedtls_md4_context *ctx,
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100285 const unsigned char *input,
286 size_t ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000287{
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100288 int ret;
Paul Bakker23986e52011-04-24 08:57:21 +0000289 size_t fill;
Paul Bakker5c2364c2012-10-01 14:41:15 +0000290 uint32_t left;
Paul Bakker5121ce52009-01-03 21:22:43 +0000291
Brian White12895d12014-04-11 11:29:42 -0400292 if( ilen == 0 )
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100293 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000294
295 left = ctx->total[0] & 0x3F;
296 fill = 64 - left;
297
Paul Bakker5c2364c2012-10-01 14:41:15 +0000298 ctx->total[0] += (uint32_t) ilen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000299 ctx->total[0] &= 0xFFFFFFFF;
300
Paul Bakker5c2364c2012-10-01 14:41:15 +0000301 if( ctx->total[0] < (uint32_t) ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000302 ctx->total[1]++;
303
304 if( left && ilen >= fill )
305 {
306 memcpy( (void *) (ctx->buffer + left),
307 (void *) input, fill );
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100308
Andres Amaya Garciacccfe082017-06-28 10:36:39 +0100309 if( ( ret = mbedtls_internal_md4_process( ctx, ctx->buffer ) ) != 0 )
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100310 return( ret );
311
Paul Bakker5121ce52009-01-03 21:22:43 +0000312 input += fill;
313 ilen -= fill;
314 left = 0;
315 }
316
317 while( ilen >= 64 )
318 {
Andres Amaya Garciacccfe082017-06-28 10:36:39 +0100319 if( ( ret = mbedtls_internal_md4_process( ctx, input ) ) != 0 )
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100320 return( ret );
321
Paul Bakker5121ce52009-01-03 21:22:43 +0000322 input += 64;
323 ilen -= 64;
324 }
325
326 if( ilen > 0 )
327 {
328 memcpy( (void *) (ctx->buffer + left),
329 (void *) input, ilen );
330 }
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100331
332 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000333}
334
Jaeden Amero041039f2018-02-19 15:28:08 +0000335#if !defined(MBEDTLS_DEPRECATED_REMOVED)
336void mbedtls_md4_update( mbedtls_md4_context *ctx,
337 const unsigned char *input,
338 size_t ilen )
339{
340 mbedtls_md4_update_ret( ctx, input, ilen );
341}
342#endif
343
Paul Bakker5121ce52009-01-03 21:22:43 +0000344static const unsigned char md4_padding[64] =
345{
346 0x80, 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 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
350};
351
352/*
353 * MD4 final digest
354 */
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100355int mbedtls_md4_finish_ret( mbedtls_md4_context *ctx,
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100356 unsigned char output[16] )
Paul Bakker5121ce52009-01-03 21:22:43 +0000357{
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100358 int ret;
Paul Bakker5c2364c2012-10-01 14:41:15 +0000359 uint32_t last, padn;
360 uint32_t high, low;
Paul Bakker5121ce52009-01-03 21:22:43 +0000361 unsigned char msglen[8];
362
363 high = ( ctx->total[0] >> 29 )
364 | ( ctx->total[1] << 3 );
365 low = ( ctx->total[0] << 3 );
366
Paul Bakker5c2364c2012-10-01 14:41:15 +0000367 PUT_UINT32_LE( low, msglen, 0 );
368 PUT_UINT32_LE( high, msglen, 4 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000369
370 last = ctx->total[0] & 0x3F;
371 padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
372
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100373 ret = mbedtls_md4_update_ret( ctx, (unsigned char *)md4_padding, padn );
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100374 if( ret != 0 )
375 return( ret );
376
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100377 if( ( ret = mbedtls_md4_update_ret( ctx, msglen, 8 ) ) != 0 )
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100378 return( ret );
379
Paul Bakker5121ce52009-01-03 21:22:43 +0000380
Paul Bakker5c2364c2012-10-01 14:41:15 +0000381 PUT_UINT32_LE( ctx->state[0], output, 0 );
382 PUT_UINT32_LE( ctx->state[1], output, 4 );
383 PUT_UINT32_LE( ctx->state[2], output, 8 );
384 PUT_UINT32_LE( ctx->state[3], output, 12 );
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100385
386 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000387}
388
Jaeden Amero041039f2018-02-19 15:28:08 +0000389#if !defined(MBEDTLS_DEPRECATED_REMOVED)
390void mbedtls_md4_finish( mbedtls_md4_context *ctx,
391 unsigned char output[16] )
392{
393 mbedtls_md4_finish_ret( ctx, output );
394}
395#endif
396
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200397#endif /* !MBEDTLS_MD4_ALT */
Paul Bakker90995b52013-06-24 19:20:35 +0200398
Paul Bakker5121ce52009-01-03 21:22:43 +0000399/*
400 * output = MD4( input buffer )
401 */
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100402int mbedtls_md4_ret( const unsigned char *input,
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100403 size_t ilen,
404 unsigned char output[16] )
Paul Bakker5121ce52009-01-03 21:22:43 +0000405{
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100406 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200407 mbedtls_md4_context ctx;
Paul Bakker5121ce52009-01-03 21:22:43 +0000408
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200409 mbedtls_md4_init( &ctx );
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100410
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100411 if( ( ret = mbedtls_md4_starts_ret( &ctx ) ) != 0 )
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100412 goto exit;
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100413
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100414 if( ( ret = mbedtls_md4_update_ret( &ctx, input, ilen ) ) != 0 )
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100415 goto exit;
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100416
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100417 if( ( ret = mbedtls_md4_finish_ret( &ctx, output ) ) != 0 )
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100418 goto exit;
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100419
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100420exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200421 mbedtls_md4_free( &ctx );
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100422
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100423 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000424}
425
Jaeden Amero041039f2018-02-19 15:28:08 +0000426#if !defined(MBEDTLS_DEPRECATED_REMOVED)
427void mbedtls_md4( const unsigned char *input,
428 size_t ilen,
429 unsigned char output[16] )
430{
431 mbedtls_md4_ret( input, ilen, output );
432}
433#endif
434
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200435#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000436
437/*
438 * RFC 1320 test vectors
439 */
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100440static const unsigned char md4_test_str[7][81] =
Paul Bakker5121ce52009-01-03 21:22:43 +0000441{
Paul Bakker9af723c2014-05-01 13:03:14 +0200442 { "" },
Paul Bakker5121ce52009-01-03 21:22:43 +0000443 { "a" },
444 { "abc" },
445 { "message digest" },
446 { "abcdefghijklmnopqrstuvwxyz" },
447 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100448 { "12345678901234567890123456789012345678901234567890123456789012"
Paul Bakker5121ce52009-01-03 21:22:43 +0000449 "345678901234567890" }
450};
451
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100452static const size_t md4_test_strlen[7] =
453{
454 0, 1, 3, 14, 26, 62, 80
455};
456
Paul Bakker5121ce52009-01-03 21:22:43 +0000457static const unsigned char md4_test_sum[7][16] =
458{
459 { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31,
460 0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 },
461 { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46,
462 0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 },
463 { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52,
464 0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D },
465 { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8,
466 0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B },
467 { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD,
468 0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 },
469 { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35,
470 0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 },
471 { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19,
472 0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 }
473};
474
475/*
476 * Checkup routine
477 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200478int mbedtls_md4_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +0000479{
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100480 int i, ret = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000481 unsigned char md4sum[16];
482
483 for( i = 0; i < 7; i++ )
484 {
485 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200486 mbedtls_printf( " MD4 test #%d: ", i + 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000487
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100488 ret = mbedtls_md4_ret( md4_test_str[i], md4_test_strlen[i], md4sum );
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100489 if( ret != 0 )
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100490 goto fail;
Paul Bakker5121ce52009-01-03 21:22:43 +0000491
492 if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 )
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100493 {
494 ret = 1;
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100495 goto fail;
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100496 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000497
498 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200499 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000500 }
501
502 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200503 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000504
505 return( 0 );
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100506
507fail:
508 if( verbose != 0 )
509 mbedtls_printf( "failed\n" );
510
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100511 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000512}
513
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200514#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +0000515
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200516#endif /* MBEDTLS_MD4_C */