blob: 160a814970716832d74823c9a84d2b677bb1d2a2 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * RFC 1186/1320 compliant MD4 implementation
3 *
Bence Szépkúti44bfbe32020-08-19 16:54:51 +02004 * Copyright The Mbed TLS Contributors
Bence Szépkúti4e9f7122020-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úti4e9f7122020-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"
Paul Bakker5121ce52009-01-03 21:22:43 +000062
Rich Evans00ab4702015-02-06 13:43:58 +000063#include <string.h>
64
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020065#if defined(MBEDTLS_SELF_TEST)
66#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000067#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010068#else
Rich Evans00ab4702015-02-06 13:43:58 +000069#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020070#define mbedtls_printf printf
71#endif /* MBEDTLS_PLATFORM_C */
72#endif /* MBEDTLS_SELF_TEST */
Paul Bakker7dc4c442014-02-01 22:50:26 +010073
Manuel Pégourié-Gonnard8b2641d2015-08-27 20:03:46 +020074#if !defined(MBEDTLS_MD4_ALT)
75
Paul Bakker34617722014-06-13 17:20:13 +020076/* Implementation that should never be optimized out by the compiler */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020077static void mbedtls_zeroize( void *v, size_t n ) {
Paul Bakker34617722014-06-13 17:20:13 +020078 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
79}
80
Paul Bakker5121ce52009-01-03 21:22:43 +000081/*
82 * 32-bit integer manipulation macros (little endian)
83 */
Paul Bakker5c2364c2012-10-01 14:41:15 +000084#ifndef GET_UINT32_LE
85#define GET_UINT32_LE(n,b,i) \
Paul Bakker5121ce52009-01-03 21:22:43 +000086{ \
Paul Bakker5c2364c2012-10-01 14:41:15 +000087 (n) = ( (uint32_t) (b)[(i) ] ) \
88 | ( (uint32_t) (b)[(i) + 1] << 8 ) \
89 | ( (uint32_t) (b)[(i) + 2] << 16 ) \
90 | ( (uint32_t) (b)[(i) + 3] << 24 ); \
Paul Bakker5121ce52009-01-03 21:22:43 +000091}
92#endif
93
Paul Bakker5c2364c2012-10-01 14:41:15 +000094#ifndef PUT_UINT32_LE
Manuel Pégourié-Gonnardceedb822015-01-23 15:02:43 +000095#define PUT_UINT32_LE(n,b,i) \
96{ \
97 (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \
98 (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \
99 (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \
100 (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \
Paul Bakker5121ce52009-01-03 21:22:43 +0000101}
102#endif
103
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200104void mbedtls_md4_init( mbedtls_md4_context *ctx )
Paul Bakker5b4af392014-06-26 12:09:34 +0200105{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200106 memset( ctx, 0, sizeof( mbedtls_md4_context ) );
Paul Bakker5b4af392014-06-26 12:09:34 +0200107}
108
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200109void mbedtls_md4_free( mbedtls_md4_context *ctx )
Paul Bakker5b4af392014-06-26 12:09:34 +0200110{
111 if( ctx == NULL )
112 return;
113
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200114 mbedtls_zeroize( ctx, sizeof( mbedtls_md4_context ) );
Paul Bakker5b4af392014-06-26 12:09:34 +0200115}
116
Manuel Pégourié-Gonnard16d412f2015-07-06 15:26:26 +0200117void mbedtls_md4_clone( mbedtls_md4_context *dst,
118 const mbedtls_md4_context *src )
119{
120 *dst = *src;
121}
122
Paul Bakker5121ce52009-01-03 21:22:43 +0000123/*
124 * MD4 context setup
125 */
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100126int mbedtls_md4_starts_ret( mbedtls_md4_context *ctx )
Paul Bakker5121ce52009-01-03 21:22:43 +0000127{
128 ctx->total[0] = 0;
129 ctx->total[1] = 0;
130
131 ctx->state[0] = 0x67452301;
132 ctx->state[1] = 0xEFCDAB89;
133 ctx->state[2] = 0x98BADCFE;
134 ctx->state[3] = 0x10325476;
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100135
136 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000137}
138
Jaeden Ameroa53ff8d2018-02-19 15:28:08 +0000139#if !defined(MBEDTLS_DEPRECATED_REMOVED)
140void mbedtls_md4_starts( mbedtls_md4_context *ctx )
141{
142 mbedtls_md4_starts_ret( ctx );
143}
144#endif
145
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200146#if !defined(MBEDTLS_MD4_PROCESS_ALT)
Andres Amaya Garciacccfe082017-06-28 10:36:39 +0100147int mbedtls_internal_md4_process( mbedtls_md4_context *ctx,
148 const unsigned char data[64] )
Paul Bakker5121ce52009-01-03 21:22:43 +0000149{
gabor-mezei-armbfdbd432020-08-25 19:12:01 +0200150 struct
151 {
152 uint32_t X[16], A, B, C, D;
153 } local;
Paul Bakker5121ce52009-01-03 21:22:43 +0000154
gabor-mezei-armbfdbd432020-08-25 19:12:01 +0200155 GET_UINT32_LE( local.X[ 0], data, 0 );
156 GET_UINT32_LE( local.X[ 1], data, 4 );
157 GET_UINT32_LE( local.X[ 2], data, 8 );
158 GET_UINT32_LE( local.X[ 3], data, 12 );
159 GET_UINT32_LE( local.X[ 4], data, 16 );
160 GET_UINT32_LE( local.X[ 5], data, 20 );
161 GET_UINT32_LE( local.X[ 6], data, 24 );
162 GET_UINT32_LE( local.X[ 7], data, 28 );
163 GET_UINT32_LE( local.X[ 8], data, 32 );
164 GET_UINT32_LE( local.X[ 9], data, 36 );
165 GET_UINT32_LE( local.X[10], data, 40 );
166 GET_UINT32_LE( local.X[11], data, 44 );
167 GET_UINT32_LE( local.X[12], data, 48 );
168 GET_UINT32_LE( local.X[13], data, 52 );
169 GET_UINT32_LE( local.X[14], data, 56 );
170 GET_UINT32_LE( local.X[15], data, 60 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000171
172#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
173
gabor-mezei-armbfdbd432020-08-25 19:12:01 +0200174 local.A = ctx->state[0];
175 local.B = ctx->state[1];
176 local.C = ctx->state[2];
177 local.D = ctx->state[3];
Paul Bakker5121ce52009-01-03 21:22:43 +0000178
179#define F(x, y, z) ((x & y) | ((~x) & z))
180#define P(a,b,c,d,x,s) { a += F(b,c,d) + x; a = S(a,s); }
181
gabor-mezei-armbfdbd432020-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[ 1], 7 );
184 P( local.C, local.D, local.A, local.B, local.X[ 2], 11 );
185 P( local.B, local.C, local.D, local.A, local.X[ 3], 19 );
186 P( local.A, local.B, local.C, local.D, local.X[ 4], 3 );
187 P( local.D, local.A, local.B, local.C, local.X[ 5], 7 );
188 P( local.C, local.D, local.A, local.B, local.X[ 6], 11 );
189 P( local.B, local.C, local.D, local.A, local.X[ 7], 19 );
190 P( local.A, local.B, local.C, local.D, local.X[ 8], 3 );
191 P( local.D, local.A, local.B, local.C, local.X[ 9], 7 );
192 P( local.C, local.D, local.A, local.B, local.X[10], 11 );
193 P( local.B, local.C, local.D, local.A, local.X[11], 19 );
194 P( local.A, local.B, local.C, local.D, local.X[12], 3 );
195 P( local.D, local.A, local.B, local.C, local.X[13], 7 );
196 P( local.C, local.D, local.A, local.B, local.X[14], 11 );
197 P( local.B, local.C, local.D, local.A, local.X[15], 19 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000198
199#undef P
200#undef F
201
202#define F(x,y,z) ((x & y) | (x & z) | (y & z))
203#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x5A827999; a = S(a,s); }
204
gabor-mezei-armbfdbd432020-08-25 19:12:01 +0200205 P( local.A, local.B, local.C, local.D, local.X[ 0], 3 );
206 P( local.D, local.A, local.B, local.C, local.X[ 4], 5 );
207 P( local.C, local.D, local.A, local.B, local.X[ 8], 9 );
208 P( local.B, local.C, local.D, local.A, local.X[12], 13 );
209 P( local.A, local.B, local.C, local.D, local.X[ 1], 3 );
210 P( local.D, local.A, local.B, local.C, local.X[ 5], 5 );
211 P( local.C, local.D, local.A, local.B, local.X[ 9], 9 );
212 P( local.B, local.C, local.D, local.A, local.X[13], 13 );
213 P( local.A, local.B, local.C, local.D, local.X[ 2], 3 );
214 P( local.D, local.A, local.B, local.C, local.X[ 6], 5 );
215 P( local.C, local.D, local.A, local.B, local.X[10], 9 );
216 P( local.B, local.C, local.D, local.A, local.X[14], 13 );
217 P( local.A, local.B, local.C, local.D, local.X[ 3], 3 );
218 P( local.D, local.A, local.B, local.C, local.X[ 7], 5 );
219 P( local.C, local.D, local.A, local.B, local.X[11], 9 );
220 P( local.B, local.C, local.D, local.A, local.X[15], 13 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000221
222#undef P
223#undef F
224
225#define F(x,y,z) (x ^ y ^ z)
226#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x6ED9EBA1; a = S(a,s); }
227
gabor-mezei-armbfdbd432020-08-25 19:12:01 +0200228 P( local.A, local.B, local.C, local.D, local.X[ 0], 3 );
229 P( local.D, local.A, local.B, local.C, local.X[ 8], 9 );
230 P( local.C, local.D, local.A, local.B, local.X[ 4], 11 );
231 P( local.B, local.C, local.D, local.A, local.X[12], 15 );
232 P( local.A, local.B, local.C, local.D, local.X[ 2], 3 );
233 P( local.D, local.A, local.B, local.C, local.X[10], 9 );
234 P( local.C, local.D, local.A, local.B, local.X[ 6], 11 );
235 P( local.B, local.C, local.D, local.A, local.X[14], 15 );
236 P( local.A, local.B, local.C, local.D, local.X[ 1], 3 );
237 P( local.D, local.A, local.B, local.C, local.X[ 9], 9 );
238 P( local.C, local.D, local.A, local.B, local.X[ 5], 11 );
239 P( local.B, local.C, local.D, local.A, local.X[13], 15 );
240 P( local.A, local.B, local.C, local.D, local.X[ 3], 3 );
241 P( local.D, local.A, local.B, local.C, local.X[11], 9 );
242 P( local.C, local.D, local.A, local.B, local.X[ 7], 11 );
243 P( local.B, local.C, local.D, local.A, local.X[15], 15 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000244
245#undef F
246#undef P
247
gabor-mezei-armbfdbd432020-08-25 19:12:01 +0200248 ctx->state[0] += local.A;
249 ctx->state[1] += local.B;
250 ctx->state[2] += local.C;
251 ctx->state[3] += local.D;
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100252
gabor-mezei-armcb3a7422020-08-19 14:03:06 +0200253 /* Zeroise variables to clear sensitive data from memory. */
gabor-mezei-armbfdbd432020-08-25 19:12:01 +0200254 mbedtls_zeroize( &local, sizeof( local ) );
gabor-mezei-armcb3a7422020-08-19 14:03:06 +0200255
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100256 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000257}
Jaeden Ameroa53ff8d2018-02-19 15:28:08 +0000258
259#if !defined(MBEDTLS_DEPRECATED_REMOVED)
260void mbedtls_md4_process( mbedtls_md4_context *ctx,
261 const unsigned char data[64] )
262{
263 mbedtls_internal_md4_process( ctx, data );
264}
265#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200266#endif /* !MBEDTLS_MD4_PROCESS_ALT */
Paul Bakker5121ce52009-01-03 21:22:43 +0000267
268/*
269 * MD4 process buffer
270 */
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100271int mbedtls_md4_update_ret( mbedtls_md4_context *ctx,
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100272 const unsigned char *input,
273 size_t ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000274{
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100275 int ret;
Paul Bakker23986e52011-04-24 08:57:21 +0000276 size_t fill;
Paul Bakker5c2364c2012-10-01 14:41:15 +0000277 uint32_t left;
Paul Bakker5121ce52009-01-03 21:22:43 +0000278
Brian White12895d12014-04-11 11:29:42 -0400279 if( ilen == 0 )
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100280 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000281
282 left = ctx->total[0] & 0x3F;
283 fill = 64 - left;
284
Paul Bakker5c2364c2012-10-01 14:41:15 +0000285 ctx->total[0] += (uint32_t) ilen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000286 ctx->total[0] &= 0xFFFFFFFF;
287
Paul Bakker5c2364c2012-10-01 14:41:15 +0000288 if( ctx->total[0] < (uint32_t) ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000289 ctx->total[1]++;
290
291 if( left && ilen >= fill )
292 {
293 memcpy( (void *) (ctx->buffer + left),
294 (void *) input, fill );
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100295
Andres Amaya Garciacccfe082017-06-28 10:36:39 +0100296 if( ( ret = mbedtls_internal_md4_process( ctx, ctx->buffer ) ) != 0 )
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100297 return( ret );
298
Paul Bakker5121ce52009-01-03 21:22:43 +0000299 input += fill;
300 ilen -= fill;
301 left = 0;
302 }
303
304 while( ilen >= 64 )
305 {
Andres Amaya Garciacccfe082017-06-28 10:36:39 +0100306 if( ( ret = mbedtls_internal_md4_process( ctx, input ) ) != 0 )
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100307 return( ret );
308
Paul Bakker5121ce52009-01-03 21:22:43 +0000309 input += 64;
310 ilen -= 64;
311 }
312
313 if( ilen > 0 )
314 {
315 memcpy( (void *) (ctx->buffer + left),
316 (void *) input, ilen );
317 }
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100318
319 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000320}
321
Jaeden Ameroa53ff8d2018-02-19 15:28:08 +0000322#if !defined(MBEDTLS_DEPRECATED_REMOVED)
323void mbedtls_md4_update( mbedtls_md4_context *ctx,
324 const unsigned char *input,
325 size_t ilen )
326{
327 mbedtls_md4_update_ret( ctx, input, ilen );
328}
329#endif
330
Paul Bakker5121ce52009-01-03 21:22:43 +0000331static const unsigned char md4_padding[64] =
332{
333 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
334 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
335 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
336 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
337};
338
339/*
340 * MD4 final digest
341 */
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100342int mbedtls_md4_finish_ret( mbedtls_md4_context *ctx,
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100343 unsigned char output[16] )
Paul Bakker5121ce52009-01-03 21:22:43 +0000344{
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100345 int ret;
Paul Bakker5c2364c2012-10-01 14:41:15 +0000346 uint32_t last, padn;
347 uint32_t high, low;
Paul Bakker5121ce52009-01-03 21:22:43 +0000348 unsigned char msglen[8];
349
350 high = ( ctx->total[0] >> 29 )
351 | ( ctx->total[1] << 3 );
352 low = ( ctx->total[0] << 3 );
353
Paul Bakker5c2364c2012-10-01 14:41:15 +0000354 PUT_UINT32_LE( low, msglen, 0 );
355 PUT_UINT32_LE( high, msglen, 4 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000356
357 last = ctx->total[0] & 0x3F;
358 padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
359
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100360 ret = mbedtls_md4_update_ret( ctx, (unsigned char *)md4_padding, padn );
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100361 if( ret != 0 )
362 return( ret );
363
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100364 if( ( ret = mbedtls_md4_update_ret( ctx, msglen, 8 ) ) != 0 )
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100365 return( ret );
366
Paul Bakker5121ce52009-01-03 21:22:43 +0000367
Paul Bakker5c2364c2012-10-01 14:41:15 +0000368 PUT_UINT32_LE( ctx->state[0], output, 0 );
369 PUT_UINT32_LE( ctx->state[1], output, 4 );
370 PUT_UINT32_LE( ctx->state[2], output, 8 );
371 PUT_UINT32_LE( ctx->state[3], output, 12 );
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100372
373 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000374}
375
Jaeden Ameroa53ff8d2018-02-19 15:28:08 +0000376#if !defined(MBEDTLS_DEPRECATED_REMOVED)
377void mbedtls_md4_finish( mbedtls_md4_context *ctx,
378 unsigned char output[16] )
379{
380 mbedtls_md4_finish_ret( ctx, output );
381}
382#endif
383
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200384#endif /* !MBEDTLS_MD4_ALT */
Paul Bakker90995b52013-06-24 19:20:35 +0200385
Paul Bakker5121ce52009-01-03 21:22:43 +0000386/*
387 * output = MD4( input buffer )
388 */
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100389int mbedtls_md4_ret( const unsigned char *input,
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100390 size_t ilen,
391 unsigned char output[16] )
Paul Bakker5121ce52009-01-03 21:22:43 +0000392{
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100393 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200394 mbedtls_md4_context ctx;
Paul Bakker5121ce52009-01-03 21:22:43 +0000395
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200396 mbedtls_md4_init( &ctx );
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100397
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100398 if( ( ret = mbedtls_md4_starts_ret( &ctx ) ) != 0 )
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100399 goto exit;
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100400
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100401 if( ( ret = mbedtls_md4_update_ret( &ctx, input, ilen ) ) != 0 )
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100402 goto exit;
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100403
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100404 if( ( ret = mbedtls_md4_finish_ret( &ctx, output ) ) != 0 )
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100405 goto exit;
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100406
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100407exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200408 mbedtls_md4_free( &ctx );
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100409
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100410 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000411}
412
Jaeden Ameroa53ff8d2018-02-19 15:28:08 +0000413#if !defined(MBEDTLS_DEPRECATED_REMOVED)
414void mbedtls_md4( const unsigned char *input,
415 size_t ilen,
416 unsigned char output[16] )
417{
418 mbedtls_md4_ret( input, ilen, output );
419}
420#endif
421
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200422#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000423
424/*
425 * RFC 1320 test vectors
426 */
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100427static const unsigned char md4_test_str[7][81] =
Paul Bakker5121ce52009-01-03 21:22:43 +0000428{
Paul Bakker9af723c2014-05-01 13:03:14 +0200429 { "" },
Paul Bakker5121ce52009-01-03 21:22:43 +0000430 { "a" },
431 { "abc" },
432 { "message digest" },
433 { "abcdefghijklmnopqrstuvwxyz" },
434 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100435 { "12345678901234567890123456789012345678901234567890123456789012"
Paul Bakker5121ce52009-01-03 21:22:43 +0000436 "345678901234567890" }
437};
438
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100439static const size_t md4_test_strlen[7] =
440{
441 0, 1, 3, 14, 26, 62, 80
442};
443
Paul Bakker5121ce52009-01-03 21:22:43 +0000444static const unsigned char md4_test_sum[7][16] =
445{
446 { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31,
447 0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 },
448 { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46,
449 0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 },
450 { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52,
451 0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D },
452 { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8,
453 0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B },
454 { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD,
455 0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 },
456 { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35,
457 0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 },
458 { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19,
459 0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 }
460};
461
462/*
463 * Checkup routine
464 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200465int mbedtls_md4_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +0000466{
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100467 int i, ret = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000468 unsigned char md4sum[16];
469
470 for( i = 0; i < 7; i++ )
471 {
472 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200473 mbedtls_printf( " MD4 test #%d: ", i + 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000474
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100475 ret = mbedtls_md4_ret( md4_test_str[i], md4_test_strlen[i], md4sum );
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100476 if( ret != 0 )
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100477 goto fail;
Paul Bakker5121ce52009-01-03 21:22:43 +0000478
479 if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 )
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100480 {
481 ret = 1;
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100482 goto fail;
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100483 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000484
485 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200486 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000487 }
488
489 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200490 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000491
492 return( 0 );
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100493
494fail:
495 if( verbose != 0 )
496 mbedtls_printf( "failed\n" );
497
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100498 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000499}
500
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200501#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +0000502
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200503#endif /* MBEDTLS_MD4_C */