blob: 163afb1ddb46b869dc3c8d612c1439df635f1743 [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é-Gonnard7f809972015-03-09 17:05:11 +000036#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010037
Manuel Pégourié-Gonnard8b2641d2015-08-27 20:03:46 +020038#if !defined(MBEDTLS_MD4_ALT)
39
David Horstmannceeaeb92023-01-05 15:44:23 +000040void mbedtls_md4_init(mbedtls_md4_context *ctx)
Paul Bakker5b4af392014-06-26 12:09:34 +020041{
David Horstmannceeaeb92023-01-05 15:44:23 +000042 memset(ctx, 0, sizeof(mbedtls_md4_context));
Paul Bakker5b4af392014-06-26 12:09:34 +020043}
44
David Horstmannceeaeb92023-01-05 15:44:23 +000045void mbedtls_md4_free(mbedtls_md4_context *ctx)
Paul Bakker5b4af392014-06-26 12:09:34 +020046{
David Horstmannceeaeb92023-01-05 15:44:23 +000047 if (ctx == NULL) {
Paul Bakker5b4af392014-06-26 12:09:34 +020048 return;
David Horstmannceeaeb92023-01-05 15:44:23 +000049 }
Paul Bakker5b4af392014-06-26 12:09:34 +020050
David Horstmannceeaeb92023-01-05 15:44:23 +000051 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_md4_context));
Paul Bakker5b4af392014-06-26 12:09:34 +020052}
53
David Horstmannceeaeb92023-01-05 15:44:23 +000054void mbedtls_md4_clone(mbedtls_md4_context *dst,
55 const mbedtls_md4_context *src)
Manuel Pégourié-Gonnard16d412f2015-07-06 15:26:26 +020056{
57 *dst = *src;
58}
59
Paul Bakker5121ce52009-01-03 21:22:43 +000060/*
61 * MD4 context setup
62 */
David Horstmannceeaeb92023-01-05 15:44:23 +000063int mbedtls_md4_starts_ret(mbedtls_md4_context *ctx)
Paul Bakker5121ce52009-01-03 21:22:43 +000064{
65 ctx->total[0] = 0;
66 ctx->total[1] = 0;
67
68 ctx->state[0] = 0x67452301;
69 ctx->state[1] = 0xEFCDAB89;
70 ctx->state[2] = 0x98BADCFE;
71 ctx->state[3] = 0x10325476;
Andres Amaya Garciabee06352017-04-28 17:00:30 +010072
David Horstmannceeaeb92023-01-05 15:44:23 +000073 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +000074}
75
Manuel Pégourié-Gonnard93c08472021-04-15 12:23:55 +020076#if !defined(MBEDTLS_DEPRECATED_REMOVED)
David Horstmannceeaeb92023-01-05 15:44:23 +000077void mbedtls_md4_starts(mbedtls_md4_context *ctx)
Manuel Pégourié-Gonnard93c08472021-04-15 12:23:55 +020078{
David Horstmannceeaeb92023-01-05 15:44:23 +000079 mbedtls_md4_starts_ret(ctx);
Manuel Pégourié-Gonnard93c08472021-04-15 12:23:55 +020080}
81#endif
82
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020083#if !defined(MBEDTLS_MD4_PROCESS_ALT)
David Horstmannceeaeb92023-01-05 15:44:23 +000084int mbedtls_internal_md4_process(mbedtls_md4_context *ctx,
85 const unsigned char data[64])
Paul Bakker5121ce52009-01-03 21:22:43 +000086{
David Horstmannceeaeb92023-01-05 15:44:23 +000087 struct {
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +020088 uint32_t X[16], A, B, C, D;
89 } local;
Paul Bakker5121ce52009-01-03 21:22:43 +000090
David Horstmannceeaeb92023-01-05 15:44:23 +000091 local.X[0] = MBEDTLS_GET_UINT32_LE(data, 0);
92 local.X[1] = MBEDTLS_GET_UINT32_LE(data, 4);
93 local.X[2] = MBEDTLS_GET_UINT32_LE(data, 8);
94 local.X[3] = MBEDTLS_GET_UINT32_LE(data, 12);
95 local.X[4] = MBEDTLS_GET_UINT32_LE(data, 16);
96 local.X[5] = MBEDTLS_GET_UINT32_LE(data, 20);
97 local.X[6] = MBEDTLS_GET_UINT32_LE(data, 24);
98 local.X[7] = MBEDTLS_GET_UINT32_LE(data, 28);
99 local.X[8] = MBEDTLS_GET_UINT32_LE(data, 32);
100 local.X[9] = MBEDTLS_GET_UINT32_LE(data, 36);
101 local.X[10] = MBEDTLS_GET_UINT32_LE(data, 40);
102 local.X[11] = MBEDTLS_GET_UINT32_LE(data, 44);
103 local.X[12] = MBEDTLS_GET_UINT32_LE(data, 48);
104 local.X[13] = MBEDTLS_GET_UINT32_LE(data, 52);
105 local.X[14] = MBEDTLS_GET_UINT32_LE(data, 56);
106 local.X[15] = MBEDTLS_GET_UINT32_LE(data, 60);
Paul Bakker5121ce52009-01-03 21:22:43 +0000107
David Horstmannceeaeb92023-01-05 15:44:23 +0000108#define S(x, n) (((x) << (n)) | (((x) & 0xFFFFFFFF) >> (32 - (n))))
Paul Bakker5121ce52009-01-03 21:22:43 +0000109
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200110 local.A = ctx->state[0];
111 local.B = ctx->state[1];
112 local.C = ctx->state[2];
113 local.D = ctx->state[3];
Paul Bakker5121ce52009-01-03 21:22:43 +0000114
Hanno Becker1eeca412018-10-15 12:01:35 +0100115#define F(x, y, z) (((x) & (y)) | ((~(x)) & (z)))
David Horstmannceeaeb92023-01-05 15:44:23 +0000116#define P(a, b, c, d, x, s) \
Hanno Becker26d02e12018-10-30 09:29:25 +0000117 do \
118 { \
David Horstmannceeaeb92023-01-05 15:44:23 +0000119 (a) += F((b), (c), (d)) + (x); \
120 (a) = S((a), (s)); \
121 } while (0)
Hanno Becker1eeca412018-10-15 12:01:35 +0100122
Paul Bakker5121ce52009-01-03 21:22:43 +0000123
David Horstmannceeaeb92023-01-05 15:44:23 +0000124 P(local.A, local.B, local.C, local.D, local.X[0], 3);
125 P(local.D, local.A, local.B, local.C, local.X[1], 7);
126 P(local.C, local.D, local.A, local.B, local.X[2], 11);
127 P(local.B, local.C, local.D, local.A, local.X[3], 19);
128 P(local.A, local.B, local.C, local.D, local.X[4], 3);
129 P(local.D, local.A, local.B, local.C, local.X[5], 7);
130 P(local.C, local.D, local.A, local.B, local.X[6], 11);
131 P(local.B, local.C, local.D, local.A, local.X[7], 19);
132 P(local.A, local.B, local.C, local.D, local.X[8], 3);
133 P(local.D, local.A, local.B, local.C, local.X[9], 7);
134 P(local.C, local.D, local.A, local.B, local.X[10], 11);
135 P(local.B, local.C, local.D, local.A, local.X[11], 19);
136 P(local.A, local.B, local.C, local.D, local.X[12], 3);
137 P(local.D, local.A, local.B, local.C, local.X[13], 7);
138 P(local.C, local.D, local.A, local.B, local.X[14], 11);
139 P(local.B, local.C, local.D, local.A, local.X[15], 19);
Paul Bakker5121ce52009-01-03 21:22:43 +0000140
141#undef P
142#undef F
143
David Horstmannceeaeb92023-01-05 15:44:23 +0000144#define F(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
145#define P(a, b, c, d, x, s) \
Hanno Becker1eeca412018-10-15 12:01:35 +0100146 do \
147 { \
David Horstmannceeaeb92023-01-05 15:44:23 +0000148 (a) += F((b), (c), (d)) + (x) + 0x5A827999; \
149 (a) = S((a), (s)); \
150 } while (0)
Paul Bakker5121ce52009-01-03 21:22:43 +0000151
David Horstmannceeaeb92023-01-05 15:44:23 +0000152 P(local.A, local.B, local.C, local.D, local.X[0], 3);
153 P(local.D, local.A, local.B, local.C, local.X[4], 5);
154 P(local.C, local.D, local.A, local.B, local.X[8], 9);
155 P(local.B, local.C, local.D, local.A, local.X[12], 13);
156 P(local.A, local.B, local.C, local.D, local.X[1], 3);
157 P(local.D, local.A, local.B, local.C, local.X[5], 5);
158 P(local.C, local.D, local.A, local.B, local.X[9], 9);
159 P(local.B, local.C, local.D, local.A, local.X[13], 13);
160 P(local.A, local.B, local.C, local.D, local.X[2], 3);
161 P(local.D, local.A, local.B, local.C, local.X[6], 5);
162 P(local.C, local.D, local.A, local.B, local.X[10], 9);
163 P(local.B, local.C, local.D, local.A, local.X[14], 13);
164 P(local.A, local.B, local.C, local.D, local.X[3], 3);
165 P(local.D, local.A, local.B, local.C, local.X[7], 5);
166 P(local.C, local.D, local.A, local.B, local.X[11], 9);
167 P(local.B, local.C, local.D, local.A, local.X[15], 13);
Paul Bakker5121ce52009-01-03 21:22:43 +0000168
169#undef P
170#undef F
171
David Horstmannceeaeb92023-01-05 15:44:23 +0000172#define F(x, y, z) ((x) ^ (y) ^ (z))
173#define P(a, b, c, d, x, s) \
Hanno Becker26d02e12018-10-30 09:29:25 +0000174 do \
175 { \
David Horstmannceeaeb92023-01-05 15:44:23 +0000176 (a) += F((b), (c), (d)) + (x) + 0x6ED9EBA1; \
177 (a) = S((a), (s)); \
178 } while (0)
Paul Bakker5121ce52009-01-03 21:22:43 +0000179
David Horstmannceeaeb92023-01-05 15:44:23 +0000180 P(local.A, local.B, local.C, local.D, local.X[0], 3);
181 P(local.D, local.A, local.B, local.C, local.X[8], 9);
182 P(local.C, local.D, local.A, local.B, local.X[4], 11);
183 P(local.B, local.C, local.D, local.A, local.X[12], 15);
184 P(local.A, local.B, local.C, local.D, local.X[2], 3);
185 P(local.D, local.A, local.B, local.C, local.X[10], 9);
186 P(local.C, local.D, local.A, local.B, local.X[6], 11);
187 P(local.B, local.C, local.D, local.A, local.X[14], 15);
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[9], 9);
190 P(local.C, local.D, local.A, local.B, local.X[5], 11);
191 P(local.B, local.C, local.D, local.A, local.X[13], 15);
192 P(local.A, local.B, local.C, local.D, local.X[3], 3);
193 P(local.D, local.A, local.B, local.C, local.X[11], 9);
194 P(local.C, local.D, local.A, local.B, local.X[7], 11);
195 P(local.B, local.C, local.D, local.A, local.X[15], 15);
Paul Bakker5121ce52009-01-03 21:22:43 +0000196
197#undef F
198#undef P
199
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200200 ctx->state[0] += local.A;
201 ctx->state[1] += local.B;
202 ctx->state[2] += local.C;
203 ctx->state[3] += local.D;
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100204
gabor-mezei-armd1c98fc2020-08-19 14:03:06 +0200205 /* Zeroise variables to clear sensitive data from memory. */
David Horstmannceeaeb92023-01-05 15:44:23 +0000206 mbedtls_platform_zeroize(&local, sizeof(local));
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100207
David Horstmannceeaeb92023-01-05 15:44:23 +0000208 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000209}
Jaeden Amero041039f2018-02-19 15:28:08 +0000210
Manuel Pégourié-Gonnard93c08472021-04-15 12:23:55 +0200211#if !defined(MBEDTLS_DEPRECATED_REMOVED)
David Horstmannceeaeb92023-01-05 15:44:23 +0000212void mbedtls_md4_process(mbedtls_md4_context *ctx,
213 const unsigned char data[64])
Manuel Pégourié-Gonnard93c08472021-04-15 12:23:55 +0200214{
David Horstmannceeaeb92023-01-05 15:44:23 +0000215 mbedtls_internal_md4_process(ctx, data);
Manuel Pégourié-Gonnard93c08472021-04-15 12:23:55 +0200216}
217#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200218#endif /* !MBEDTLS_MD4_PROCESS_ALT */
Paul Bakker5121ce52009-01-03 21:22:43 +0000219
220/*
221 * MD4 process buffer
222 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000223int mbedtls_md4_update_ret(mbedtls_md4_context *ctx,
224 const unsigned char *input,
225 size_t ilen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000226{
Janos Follath24eed8d2019-11-22 13:21:35 +0000227 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000228 size_t fill;
Paul Bakker5c2364c2012-10-01 14:41:15 +0000229 uint32_t left;
Paul Bakker5121ce52009-01-03 21:22:43 +0000230
David Horstmannceeaeb92023-01-05 15:44:23 +0000231 if (ilen == 0) {
232 return 0;
233 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000234
235 left = ctx->total[0] & 0x3F;
236 fill = 64 - left;
237
Paul Bakker5c2364c2012-10-01 14:41:15 +0000238 ctx->total[0] += (uint32_t) ilen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000239 ctx->total[0] &= 0xFFFFFFFF;
240
David Horstmannceeaeb92023-01-05 15:44:23 +0000241 if (ctx->total[0] < (uint32_t) ilen) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000242 ctx->total[1]++;
David Horstmannceeaeb92023-01-05 15:44:23 +0000243 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000244
David Horstmannceeaeb92023-01-05 15:44:23 +0000245 if (left && ilen >= fill) {
246 memcpy((void *) (ctx->buffer + left),
247 (void *) input, fill);
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100248
David Horstmannceeaeb92023-01-05 15:44:23 +0000249 if ((ret = mbedtls_internal_md4_process(ctx, ctx->buffer)) != 0) {
250 return ret;
251 }
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100252
Paul Bakker5121ce52009-01-03 21:22:43 +0000253 input += fill;
254 ilen -= fill;
255 left = 0;
256 }
257
David Horstmannceeaeb92023-01-05 15:44:23 +0000258 while (ilen >= 64) {
259 if ((ret = mbedtls_internal_md4_process(ctx, input)) != 0) {
260 return ret;
261 }
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100262
Paul Bakker5121ce52009-01-03 21:22:43 +0000263 input += 64;
264 ilen -= 64;
265 }
266
David Horstmannceeaeb92023-01-05 15:44:23 +0000267 if (ilen > 0) {
268 memcpy((void *) (ctx->buffer + left),
269 (void *) input, ilen);
Paul Bakker5121ce52009-01-03 21:22:43 +0000270 }
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100271
David Horstmannceeaeb92023-01-05 15:44:23 +0000272 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000273}
274
Manuel Pégourié-Gonnard93c08472021-04-15 12:23:55 +0200275#if !defined(MBEDTLS_DEPRECATED_REMOVED)
David Horstmannceeaeb92023-01-05 15:44:23 +0000276void mbedtls_md4_update(mbedtls_md4_context *ctx,
277 const unsigned char *input,
278 size_t ilen)
Manuel Pégourié-Gonnard93c08472021-04-15 12:23:55 +0200279{
David Horstmannceeaeb92023-01-05 15:44:23 +0000280 mbedtls_md4_update_ret(ctx, input, ilen);
Manuel Pégourié-Gonnard93c08472021-04-15 12:23:55 +0200281}
282#endif
283
Paul Bakker5121ce52009-01-03 21:22:43 +0000284static const unsigned char md4_padding[64] =
285{
David Horstmannceeaeb92023-01-05 15:44:23 +0000286 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Paul Bakker5121ce52009-01-03 21:22:43 +0000287 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
288 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
289 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
290};
291
292/*
293 * MD4 final digest
294 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000295int mbedtls_md4_finish_ret(mbedtls_md4_context *ctx,
296 unsigned char output[16])
Paul Bakker5121ce52009-01-03 21:22:43 +0000297{
Janos Follath24eed8d2019-11-22 13:21:35 +0000298 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker5c2364c2012-10-01 14:41:15 +0000299 uint32_t last, padn;
300 uint32_t high, low;
Paul Bakker5121ce52009-01-03 21:22:43 +0000301 unsigned char msglen[8];
302
David Horstmannceeaeb92023-01-05 15:44:23 +0000303 high = (ctx->total[0] >> 29)
304 | (ctx->total[1] << 3);
305 low = (ctx->total[0] << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000306
David Horstmannceeaeb92023-01-05 15:44:23 +0000307 MBEDTLS_PUT_UINT32_LE(low, msglen, 0);
308 MBEDTLS_PUT_UINT32_LE(high, msglen, 4);
Paul Bakker5121ce52009-01-03 21:22:43 +0000309
310 last = ctx->total[0] & 0x3F;
David Horstmannceeaeb92023-01-05 15:44:23 +0000311 padn = (last < 56) ? (56 - last) : (120 - last);
Paul Bakker5121ce52009-01-03 21:22:43 +0000312
David Horstmannceeaeb92023-01-05 15:44:23 +0000313 ret = mbedtls_md4_update_ret(ctx, (unsigned char *) md4_padding, padn);
314 if (ret != 0) {
315 return ret;
316 }
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100317
David Horstmannceeaeb92023-01-05 15:44:23 +0000318 if ((ret = mbedtls_md4_update_ret(ctx, msglen, 8)) != 0) {
319 return ret;
320 }
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100321
Paul Bakker5121ce52009-01-03 21:22:43 +0000322
David Horstmannceeaeb92023-01-05 15:44:23 +0000323 MBEDTLS_PUT_UINT32_LE(ctx->state[0], output, 0);
324 MBEDTLS_PUT_UINT32_LE(ctx->state[1], output, 4);
325 MBEDTLS_PUT_UINT32_LE(ctx->state[2], output, 8);
326 MBEDTLS_PUT_UINT32_LE(ctx->state[3], output, 12);
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100327
David Horstmannceeaeb92023-01-05 15:44:23 +0000328 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000329}
330
Manuel Pégourié-Gonnard93c08472021-04-15 12:23:55 +0200331#if !defined(MBEDTLS_DEPRECATED_REMOVED)
David Horstmannceeaeb92023-01-05 15:44:23 +0000332void mbedtls_md4_finish(mbedtls_md4_context *ctx,
333 unsigned char output[16])
Manuel Pégourié-Gonnard93c08472021-04-15 12:23:55 +0200334{
David Horstmannceeaeb92023-01-05 15:44:23 +0000335 mbedtls_md4_finish_ret(ctx, output);
Manuel Pégourié-Gonnard93c08472021-04-15 12:23:55 +0200336}
337#endif
338
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200339#endif /* !MBEDTLS_MD4_ALT */
Paul Bakker90995b52013-06-24 19:20:35 +0200340
Paul Bakker5121ce52009-01-03 21:22:43 +0000341/*
342 * output = MD4( input buffer )
343 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000344int mbedtls_md4_ret(const unsigned char *input,
345 size_t ilen,
346 unsigned char output[16])
Paul Bakker5121ce52009-01-03 21:22:43 +0000347{
Janos Follath24eed8d2019-11-22 13:21:35 +0000348 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200349 mbedtls_md4_context ctx;
Paul Bakker5121ce52009-01-03 21:22:43 +0000350
David Horstmannceeaeb92023-01-05 15:44:23 +0000351 mbedtls_md4_init(&ctx);
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100352
David Horstmannceeaeb92023-01-05 15:44:23 +0000353 if ((ret = mbedtls_md4_starts_ret(&ctx)) != 0) {
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100354 goto exit;
David Horstmannceeaeb92023-01-05 15:44:23 +0000355 }
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100356
David Horstmannceeaeb92023-01-05 15:44:23 +0000357 if ((ret = mbedtls_md4_update_ret(&ctx, input, ilen)) != 0) {
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100358 goto exit;
David Horstmannceeaeb92023-01-05 15:44:23 +0000359 }
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100360
David Horstmannceeaeb92023-01-05 15:44:23 +0000361 if ((ret = mbedtls_md4_finish_ret(&ctx, output)) != 0) {
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100362 goto exit;
David Horstmannceeaeb92023-01-05 15:44:23 +0000363 }
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100364
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100365exit:
David Horstmannceeaeb92023-01-05 15:44:23 +0000366 mbedtls_md4_free(&ctx);
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100367
David Horstmannceeaeb92023-01-05 15:44:23 +0000368 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000369}
370
Manuel Pégourié-Gonnard93c08472021-04-15 12:23:55 +0200371#if !defined(MBEDTLS_DEPRECATED_REMOVED)
David Horstmannceeaeb92023-01-05 15:44:23 +0000372void mbedtls_md4(const unsigned char *input,
373 size_t ilen,
374 unsigned char output[16])
Manuel Pégourié-Gonnard93c08472021-04-15 12:23:55 +0200375{
David Horstmannceeaeb92023-01-05 15:44:23 +0000376 mbedtls_md4_ret(input, ilen, output);
Manuel Pégourié-Gonnard93c08472021-04-15 12:23:55 +0200377}
378#endif
379
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200380#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000381
382/*
383 * RFC 1320 test vectors
384 */
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100385static const unsigned char md4_test_str[7][81] =
Paul Bakker5121ce52009-01-03 21:22:43 +0000386{
Paul Bakker9af723c2014-05-01 13:03:14 +0200387 { "" },
Paul Bakker5121ce52009-01-03 21:22:43 +0000388 { "a" },
389 { "abc" },
390 { "message digest" },
391 { "abcdefghijklmnopqrstuvwxyz" },
392 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
Guido Vranken962e4ee2020-08-21 21:08:56 +0200393 { "12345678901234567890123456789012345678901234567890123456789012345678901234567890" }
Paul Bakker5121ce52009-01-03 21:22:43 +0000394};
395
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100396static const size_t md4_test_strlen[7] =
397{
398 0, 1, 3, 14, 26, 62, 80
399};
400
Paul Bakker5121ce52009-01-03 21:22:43 +0000401static const unsigned char md4_test_sum[7][16] =
402{
403 { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31,
404 0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 },
405 { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46,
406 0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 },
407 { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52,
408 0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D },
409 { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8,
410 0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B },
411 { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD,
412 0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 },
413 { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35,
414 0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 },
415 { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19,
416 0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 }
417};
418
419/*
420 * Checkup routine
421 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000422int mbedtls_md4_self_test(int verbose)
Paul Bakker5121ce52009-01-03 21:22:43 +0000423{
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100424 int i, ret = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000425 unsigned char md4sum[16];
426
David Horstmannceeaeb92023-01-05 15:44:23 +0000427 for (i = 0; i < 7; i++) {
428 if (verbose != 0) {
429 mbedtls_printf(" MD4 test #%d: ", i + 1);
430 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000431
David Horstmannceeaeb92023-01-05 15:44:23 +0000432 ret = mbedtls_md4_ret(md4_test_str[i], md4_test_strlen[i], md4sum);
433 if (ret != 0) {
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100434 goto fail;
David Horstmannceeaeb92023-01-05 15:44:23 +0000435 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000436
David Horstmannceeaeb92023-01-05 15:44:23 +0000437 if (memcmp(md4sum, md4_test_sum[i], 16) != 0) {
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100438 ret = 1;
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100439 goto fail;
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100440 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000441
David Horstmannceeaeb92023-01-05 15:44:23 +0000442 if (verbose != 0) {
443 mbedtls_printf("passed\n");
444 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000445 }
446
David Horstmannceeaeb92023-01-05 15:44:23 +0000447 if (verbose != 0) {
448 mbedtls_printf("\n");
449 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000450
David Horstmannceeaeb92023-01-05 15:44:23 +0000451 return 0;
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100452
453fail:
David Horstmannceeaeb92023-01-05 15:44:23 +0000454 if (verbose != 0) {
455 mbedtls_printf("failed\n");
456 }
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100457
David Horstmannceeaeb92023-01-05 15:44:23 +0000458 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000459}
460
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200461#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +0000462
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200463#endif /* MBEDTLS_MD4_C */