blob: 5546202b53842c7210ead2cc72053fc1c9fdb9fb [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * RFC 1186/1320 compliant MD4 implementation
3 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
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 Bakkerb96f1542010-07-18 20:36:00 +000018 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker5121ce52009-01-03 21:22:43 +000020 */
21/*
22 * The MD4 algorithm was designed by Ron Rivest in 1990.
23 *
24 * http://www.ietf.org/rfc/rfc1186.txt
25 * http://www.ietf.org/rfc/rfc1320.txt
26 */
27
Gilles Peskinedb09ef62020-06-03 01:43:33 +020028#include "common.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000029
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020030#if defined(MBEDTLS_MD4_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000031
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000032#include "mbedtls/md4.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050033#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000034#include "mbedtls/error.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000035
Rich Evans00ab4702015-02-06 13:43:58 +000036#include <string.h>
37
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020038#if defined(MBEDTLS_SELF_TEST)
39#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000040#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010041#else
Rich Evans00ab4702015-02-06 13:43:58 +000042#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020043#define mbedtls_printf printf
44#endif /* MBEDTLS_PLATFORM_C */
45#endif /* MBEDTLS_SELF_TEST */
Paul Bakker7dc4c442014-02-01 22:50:26 +010046
Manuel Pégourié-Gonnard8b2641d2015-08-27 20:03:46 +020047#if !defined(MBEDTLS_MD4_ALT)
48
Paul Bakker5121ce52009-01-03 21:22:43 +000049/*
50 * 32-bit integer manipulation macros (little endian)
51 */
Paul Bakker5c2364c2012-10-01 14:41:15 +000052#ifndef GET_UINT32_LE
53#define GET_UINT32_LE(n,b,i) \
Paul Bakker5121ce52009-01-03 21:22:43 +000054{ \
Paul Bakker5c2364c2012-10-01 14:41:15 +000055 (n) = ( (uint32_t) (b)[(i) ] ) \
56 | ( (uint32_t) (b)[(i) + 1] << 8 ) \
57 | ( (uint32_t) (b)[(i) + 2] << 16 ) \
58 | ( (uint32_t) (b)[(i) + 3] << 24 ); \
Paul Bakker5121ce52009-01-03 21:22:43 +000059}
60#endif
61
Paul Bakker5c2364c2012-10-01 14:41:15 +000062#ifndef PUT_UINT32_LE
Manuel Pégourié-Gonnardceedb822015-01-23 15:02:43 +000063#define PUT_UINT32_LE(n,b,i) \
64{ \
65 (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \
66 (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \
67 (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \
68 (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \
Paul Bakker5121ce52009-01-03 21:22:43 +000069}
70#endif
71
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020072void mbedtls_md4_init( mbedtls_md4_context *ctx )
Paul Bakker5b4af392014-06-26 12:09:34 +020073{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020074 memset( ctx, 0, sizeof( mbedtls_md4_context ) );
Paul Bakker5b4af392014-06-26 12:09:34 +020075}
76
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020077void mbedtls_md4_free( mbedtls_md4_context *ctx )
Paul Bakker5b4af392014-06-26 12:09:34 +020078{
79 if( ctx == NULL )
80 return;
81
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050082 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md4_context ) );
Paul Bakker5b4af392014-06-26 12:09:34 +020083}
84
Manuel Pégourié-Gonnard16d412f2015-07-06 15:26:26 +020085void mbedtls_md4_clone( mbedtls_md4_context *dst,
86 const mbedtls_md4_context *src )
87{
88 *dst = *src;
89}
90
Paul Bakker5121ce52009-01-03 21:22:43 +000091/*
92 * MD4 context setup
93 */
Gilles Peskine9e4f77c2018-01-22 11:48:08 +010094int mbedtls_md4_starts_ret( mbedtls_md4_context *ctx )
Paul Bakker5121ce52009-01-03 21:22:43 +000095{
96 ctx->total[0] = 0;
97 ctx->total[1] = 0;
98
99 ctx->state[0] = 0x67452301;
100 ctx->state[1] = 0xEFCDAB89;
101 ctx->state[2] = 0x98BADCFE;
102 ctx->state[3] = 0x10325476;
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100103
104 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000105}
106
Jaeden Amero041039f2018-02-19 15:28:08 +0000107#if !defined(MBEDTLS_DEPRECATED_REMOVED)
108void mbedtls_md4_starts( mbedtls_md4_context *ctx )
109{
110 mbedtls_md4_starts_ret( ctx );
111}
112#endif
113
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200114#if !defined(MBEDTLS_MD4_PROCESS_ALT)
Andres Amaya Garciacccfe082017-06-28 10:36:39 +0100115int mbedtls_internal_md4_process( mbedtls_md4_context *ctx,
116 const unsigned char data[64] )
Paul Bakker5121ce52009-01-03 21:22:43 +0000117{
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200118 struct
119 {
120 uint32_t X[16], A, B, C, D;
121 } local;
Paul Bakker5121ce52009-01-03 21:22:43 +0000122
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200123 GET_UINT32_LE( local.X[ 0], data, 0 );
124 GET_UINT32_LE( local.X[ 1], data, 4 );
125 GET_UINT32_LE( local.X[ 2], data, 8 );
126 GET_UINT32_LE( local.X[ 3], data, 12 );
127 GET_UINT32_LE( local.X[ 4], data, 16 );
128 GET_UINT32_LE( local.X[ 5], data, 20 );
129 GET_UINT32_LE( local.X[ 6], data, 24 );
130 GET_UINT32_LE( local.X[ 7], data, 28 );
131 GET_UINT32_LE( local.X[ 8], data, 32 );
132 GET_UINT32_LE( local.X[ 9], data, 36 );
133 GET_UINT32_LE( local.X[10], data, 40 );
134 GET_UINT32_LE( local.X[11], data, 44 );
135 GET_UINT32_LE( local.X[12], data, 48 );
136 GET_UINT32_LE( local.X[13], data, 52 );
137 GET_UINT32_LE( local.X[14], data, 56 );
138 GET_UINT32_LE( local.X[15], data, 60 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000139
Hanno Becker1eeca412018-10-15 12:01:35 +0100140#define S(x,n) (((x) << (n)) | (((x) & 0xFFFFFFFF) >> (32 - (n))))
Paul Bakker5121ce52009-01-03 21:22:43 +0000141
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200142 local.A = ctx->state[0];
143 local.B = ctx->state[1];
144 local.C = ctx->state[2];
145 local.D = ctx->state[3];
Paul Bakker5121ce52009-01-03 21:22:43 +0000146
Hanno Becker1eeca412018-10-15 12:01:35 +0100147#define F(x, y, z) (((x) & (y)) | ((~(x)) & (z)))
Hanno Becker26d02e12018-10-30 09:29:25 +0000148#define P(a,b,c,d,x,s) \
149 do \
150 { \
Hanno Becker818bac52018-10-26 09:13:26 +0100151 (a) += F((b),(c),(d)) + (x); \
152 (a) = S((a),(s)); \
Hanno Becker1eeca412018-10-15 12:01:35 +0100153 } while( 0 )
154
Paul Bakker5121ce52009-01-03 21:22:43 +0000155
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200156 P( local.A, local.B, local.C, local.D, local.X[ 0], 3 );
157 P( local.D, local.A, local.B, local.C, local.X[ 1], 7 );
158 P( local.C, local.D, local.A, local.B, local.X[ 2], 11 );
159 P( local.B, local.C, local.D, local.A, local.X[ 3], 19 );
160 P( local.A, local.B, local.C, local.D, local.X[ 4], 3 );
161 P( local.D, local.A, local.B, local.C, local.X[ 5], 7 );
162 P( local.C, local.D, local.A, local.B, local.X[ 6], 11 );
163 P( local.B, local.C, local.D, local.A, local.X[ 7], 19 );
164 P( local.A, local.B, local.C, local.D, local.X[ 8], 3 );
165 P( local.D, local.A, local.B, local.C, local.X[ 9], 7 );
166 P( local.C, local.D, local.A, local.B, local.X[10], 11 );
167 P( local.B, local.C, local.D, local.A, local.X[11], 19 );
168 P( local.A, local.B, local.C, local.D, local.X[12], 3 );
169 P( local.D, local.A, local.B, local.C, local.X[13], 7 );
170 P( local.C, local.D, local.A, local.B, local.X[14], 11 );
171 P( local.B, local.C, local.D, local.A, local.X[15], 19 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000172
173#undef P
174#undef F
175
Hanno Becker1eeca412018-10-15 12:01:35 +0100176#define F(x,y,z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
177#define P(a,b,c,d,x,s) \
178 do \
179 { \
Hanno Becker26d02e12018-10-30 09:29:25 +0000180 (a) += F((b),(c),(d)) + (x) + 0x5A827999; \
181 (a) = S((a),(s)); \
Hanno Becker1eeca412018-10-15 12:01:35 +0100182 } while( 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000183
gabor-mezei-arm4cb56f82020-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[ 4], 5 );
186 P( local.C, local.D, local.A, local.B, local.X[ 8], 9 );
187 P( local.B, local.C, local.D, local.A, local.X[12], 13 );
188 P( local.A, local.B, local.C, local.D, local.X[ 1], 3 );
189 P( local.D, local.A, local.B, local.C, local.X[ 5], 5 );
190 P( local.C, local.D, local.A, local.B, local.X[ 9], 9 );
191 P( local.B, local.C, local.D, local.A, local.X[13], 13 );
192 P( local.A, local.B, local.C, local.D, local.X[ 2], 3 );
193 P( local.D, local.A, local.B, local.C, local.X[ 6], 5 );
194 P( local.C, local.D, local.A, local.B, local.X[10], 9 );
195 P( local.B, local.C, local.D, local.A, local.X[14], 13 );
196 P( local.A, local.B, local.C, local.D, local.X[ 3], 3 );
197 P( local.D, local.A, local.B, local.C, local.X[ 7], 5 );
198 P( local.C, local.D, local.A, local.B, local.X[11], 9 );
199 P( local.B, local.C, local.D, local.A, local.X[15], 13 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000200
201#undef P
202#undef F
203
Hanno Becker1eeca412018-10-15 12:01:35 +0100204#define F(x,y,z) ((x) ^ (y) ^ (z))
Hanno Becker26d02e12018-10-30 09:29:25 +0000205#define P(a,b,c,d,x,s) \
206 do \
207 { \
208 (a) += F((b),(c),(d)) + (x) + 0x6ED9EBA1; \
209 (a) = S((a),(s)); \
Hanno Becker1eeca412018-10-15 12:01:35 +0100210 } while( 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000211
gabor-mezei-arm4cb56f82020-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[ 8], 9 );
214 P( local.C, local.D, local.A, local.B, local.X[ 4], 11 );
215 P( local.B, local.C, local.D, local.A, local.X[12], 15 );
216 P( local.A, local.B, local.C, local.D, local.X[ 2], 3 );
217 P( local.D, local.A, local.B, local.C, local.X[10], 9 );
218 P( local.C, local.D, local.A, local.B, local.X[ 6], 11 );
219 P( local.B, local.C, local.D, local.A, local.X[14], 15 );
220 P( local.A, local.B, local.C, local.D, local.X[ 1], 3 );
221 P( local.D, local.A, local.B, local.C, local.X[ 9], 9 );
222 P( local.C, local.D, local.A, local.B, local.X[ 5], 11 );
223 P( local.B, local.C, local.D, local.A, local.X[13], 15 );
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[11], 9 );
226 P( local.C, local.D, local.A, local.B, local.X[ 7], 11 );
227 P( local.B, local.C, local.D, local.A, local.X[15], 15 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000228
229#undef F
230#undef P
231
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200232 ctx->state[0] += local.A;
233 ctx->state[1] += local.B;
234 ctx->state[2] += local.C;
235 ctx->state[3] += local.D;
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100236
gabor-mezei-armd1c98fc2020-08-19 14:03:06 +0200237 /* Zeroise variables to clear sensitive data from memory. */
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200238 mbedtls_platform_zeroize( &local, sizeof( local ) );
gabor-mezei-armd1c98fc2020-08-19 14:03:06 +0200239
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100240 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000241}
Jaeden Amero041039f2018-02-19 15:28:08 +0000242
243#if !defined(MBEDTLS_DEPRECATED_REMOVED)
244void mbedtls_md4_process( mbedtls_md4_context *ctx,
245 const unsigned char data[64] )
246{
247 mbedtls_internal_md4_process( ctx, data );
248}
249#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200250#endif /* !MBEDTLS_MD4_PROCESS_ALT */
Paul Bakker5121ce52009-01-03 21:22:43 +0000251
252/*
253 * MD4 process buffer
254 */
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100255int mbedtls_md4_update_ret( mbedtls_md4_context *ctx,
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100256 const unsigned char *input,
257 size_t ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000258{
Janos Follath24eed8d2019-11-22 13:21:35 +0000259 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000260 size_t fill;
Paul Bakker5c2364c2012-10-01 14:41:15 +0000261 uint32_t left;
Paul Bakker5121ce52009-01-03 21:22:43 +0000262
Brian White12895d12014-04-11 11:29:42 -0400263 if( ilen == 0 )
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100264 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000265
266 left = ctx->total[0] & 0x3F;
267 fill = 64 - left;
268
Paul Bakker5c2364c2012-10-01 14:41:15 +0000269 ctx->total[0] += (uint32_t) ilen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000270 ctx->total[0] &= 0xFFFFFFFF;
271
Paul Bakker5c2364c2012-10-01 14:41:15 +0000272 if( ctx->total[0] < (uint32_t) ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000273 ctx->total[1]++;
274
275 if( left && ilen >= fill )
276 {
277 memcpy( (void *) (ctx->buffer + left),
278 (void *) input, fill );
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100279
Andres Amaya Garciacccfe082017-06-28 10:36:39 +0100280 if( ( ret = mbedtls_internal_md4_process( ctx, ctx->buffer ) ) != 0 )
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100281 return( ret );
282
Paul Bakker5121ce52009-01-03 21:22:43 +0000283 input += fill;
284 ilen -= fill;
285 left = 0;
286 }
287
288 while( ilen >= 64 )
289 {
Andres Amaya Garciacccfe082017-06-28 10:36:39 +0100290 if( ( ret = mbedtls_internal_md4_process( ctx, input ) ) != 0 )
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100291 return( ret );
292
Paul Bakker5121ce52009-01-03 21:22:43 +0000293 input += 64;
294 ilen -= 64;
295 }
296
297 if( ilen > 0 )
298 {
299 memcpy( (void *) (ctx->buffer + left),
300 (void *) input, ilen );
301 }
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100302
303 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000304}
305
Jaeden Amero041039f2018-02-19 15:28:08 +0000306#if !defined(MBEDTLS_DEPRECATED_REMOVED)
307void mbedtls_md4_update( mbedtls_md4_context *ctx,
308 const unsigned char *input,
309 size_t ilen )
310{
311 mbedtls_md4_update_ret( ctx, input, ilen );
312}
313#endif
314
Paul Bakker5121ce52009-01-03 21:22:43 +0000315static const unsigned char md4_padding[64] =
316{
317 0x80, 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 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
320 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
321};
322
323/*
324 * MD4 final digest
325 */
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100326int mbedtls_md4_finish_ret( mbedtls_md4_context *ctx,
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100327 unsigned char output[16] )
Paul Bakker5121ce52009-01-03 21:22:43 +0000328{
Janos Follath24eed8d2019-11-22 13:21:35 +0000329 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker5c2364c2012-10-01 14:41:15 +0000330 uint32_t last, padn;
331 uint32_t high, low;
Paul Bakker5121ce52009-01-03 21:22:43 +0000332 unsigned char msglen[8];
333
334 high = ( ctx->total[0] >> 29 )
335 | ( ctx->total[1] << 3 );
336 low = ( ctx->total[0] << 3 );
337
Paul Bakker5c2364c2012-10-01 14:41:15 +0000338 PUT_UINT32_LE( low, msglen, 0 );
339 PUT_UINT32_LE( high, msglen, 4 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000340
341 last = ctx->total[0] & 0x3F;
342 padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
343
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100344 ret = mbedtls_md4_update_ret( ctx, (unsigned char *)md4_padding, padn );
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100345 if( ret != 0 )
346 return( ret );
347
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100348 if( ( ret = mbedtls_md4_update_ret( ctx, msglen, 8 ) ) != 0 )
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100349 return( ret );
350
Paul Bakker5121ce52009-01-03 21:22:43 +0000351
Paul Bakker5c2364c2012-10-01 14:41:15 +0000352 PUT_UINT32_LE( ctx->state[0], output, 0 );
353 PUT_UINT32_LE( ctx->state[1], output, 4 );
354 PUT_UINT32_LE( ctx->state[2], output, 8 );
355 PUT_UINT32_LE( ctx->state[3], output, 12 );
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100356
357 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000358}
359
Jaeden Amero041039f2018-02-19 15:28:08 +0000360#if !defined(MBEDTLS_DEPRECATED_REMOVED)
361void mbedtls_md4_finish( mbedtls_md4_context *ctx,
362 unsigned char output[16] )
363{
364 mbedtls_md4_finish_ret( ctx, output );
365}
366#endif
367
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200368#endif /* !MBEDTLS_MD4_ALT */
Paul Bakker90995b52013-06-24 19:20:35 +0200369
Paul Bakker5121ce52009-01-03 21:22:43 +0000370/*
371 * output = MD4( input buffer )
372 */
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100373int mbedtls_md4_ret( const unsigned char *input,
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100374 size_t ilen,
375 unsigned char output[16] )
Paul Bakker5121ce52009-01-03 21:22:43 +0000376{
Janos Follath24eed8d2019-11-22 13:21:35 +0000377 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200378 mbedtls_md4_context ctx;
Paul Bakker5121ce52009-01-03 21:22:43 +0000379
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200380 mbedtls_md4_init( &ctx );
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100381
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100382 if( ( ret = mbedtls_md4_starts_ret( &ctx ) ) != 0 )
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100383 goto exit;
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100384
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100385 if( ( ret = mbedtls_md4_update_ret( &ctx, input, ilen ) ) != 0 )
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100386 goto exit;
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100387
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100388 if( ( ret = mbedtls_md4_finish_ret( &ctx, output ) ) != 0 )
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100389 goto exit;
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100390
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100391exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200392 mbedtls_md4_free( &ctx );
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100393
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100394 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000395}
396
Jaeden Amero041039f2018-02-19 15:28:08 +0000397#if !defined(MBEDTLS_DEPRECATED_REMOVED)
398void mbedtls_md4( const unsigned char *input,
399 size_t ilen,
400 unsigned char output[16] )
401{
402 mbedtls_md4_ret( input, ilen, output );
403}
404#endif
405
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200406#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000407
408/*
409 * RFC 1320 test vectors
410 */
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100411static const unsigned char md4_test_str[7][81] =
Paul Bakker5121ce52009-01-03 21:22:43 +0000412{
Paul Bakker9af723c2014-05-01 13:03:14 +0200413 { "" },
Paul Bakker5121ce52009-01-03 21:22:43 +0000414 { "a" },
415 { "abc" },
416 { "message digest" },
417 { "abcdefghijklmnopqrstuvwxyz" },
418 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100419 { "12345678901234567890123456789012345678901234567890123456789012"
Paul Bakker5121ce52009-01-03 21:22:43 +0000420 "345678901234567890" }
421};
422
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100423static const size_t md4_test_strlen[7] =
424{
425 0, 1, 3, 14, 26, 62, 80
426};
427
Paul Bakker5121ce52009-01-03 21:22:43 +0000428static const unsigned char md4_test_sum[7][16] =
429{
430 { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31,
431 0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 },
432 { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46,
433 0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 },
434 { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52,
435 0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D },
436 { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8,
437 0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B },
438 { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD,
439 0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 },
440 { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35,
441 0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 },
442 { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19,
443 0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 }
444};
445
446/*
447 * Checkup routine
448 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200449int mbedtls_md4_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +0000450{
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100451 int i, ret = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000452 unsigned char md4sum[16];
453
454 for( i = 0; i < 7; i++ )
455 {
456 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200457 mbedtls_printf( " MD4 test #%d: ", i + 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000458
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100459 ret = mbedtls_md4_ret( md4_test_str[i], md4_test_strlen[i], md4sum );
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100460 if( ret != 0 )
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100461 goto fail;
Paul Bakker5121ce52009-01-03 21:22:43 +0000462
463 if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 )
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100464 {
465 ret = 1;
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100466 goto fail;
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100467 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000468
469 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200470 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000471 }
472
473 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200474 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000475
476 return( 0 );
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100477
478fail:
479 if( verbose != 0 )
480 mbedtls_printf( "failed\n" );
481
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100482 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000483}
484
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200485#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +0000486
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200487#endif /* MBEDTLS_MD4_C */