blob: 8de85fba2e68da64e2cfd699ac863ba7ab1ca1e0 [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
Dave Rodgman7ff79652023-11-03 12:04:52 +00005 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
Paul Bakker5121ce52009-01-03 21:22:43 +00006 */
7/*
8 * The MD4 algorithm was designed by Ron Rivest in 1990.
9 *
10 * http://www.ietf.org/rfc/rfc1186.txt
11 * http://www.ietf.org/rfc/rfc1320.txt
12 */
13
Gilles Peskinedb09ef62020-06-03 01:43:33 +020014#include "common.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000015
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020016#if defined(MBEDTLS_MD4_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000017
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000018#include "mbedtls/md4.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050019#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000020#include "mbedtls/error.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000021
Rich Evans00ab4702015-02-06 13:43:58 +000022#include <string.h>
23
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000024#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010025
Manuel Pégourié-Gonnard8b2641d2015-08-27 20:03:46 +020026#if !defined(MBEDTLS_MD4_ALT)
27
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010028void mbedtls_md4_init(mbedtls_md4_context *ctx)
Paul Bakker5b4af392014-06-26 12:09:34 +020029{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010030 memset(ctx, 0, sizeof(mbedtls_md4_context));
Paul Bakker5b4af392014-06-26 12:09:34 +020031}
32
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010033void mbedtls_md4_free(mbedtls_md4_context *ctx)
Paul Bakker5b4af392014-06-26 12:09:34 +020034{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010035 if (ctx == NULL) {
Paul Bakker5b4af392014-06-26 12:09:34 +020036 return;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010037 }
Paul Bakker5b4af392014-06-26 12:09:34 +020038
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010039 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_md4_context));
Paul Bakker5b4af392014-06-26 12:09:34 +020040}
41
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010042void mbedtls_md4_clone(mbedtls_md4_context *dst,
43 const mbedtls_md4_context *src)
Manuel Pégourié-Gonnard16d412f2015-07-06 15:26:26 +020044{
45 *dst = *src;
46}
47
Paul Bakker5121ce52009-01-03 21:22:43 +000048/*
49 * MD4 context setup
50 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010051int mbedtls_md4_starts_ret(mbedtls_md4_context *ctx)
Paul Bakker5121ce52009-01-03 21:22:43 +000052{
53 ctx->total[0] = 0;
54 ctx->total[1] = 0;
55
56 ctx->state[0] = 0x67452301;
57 ctx->state[1] = 0xEFCDAB89;
58 ctx->state[2] = 0x98BADCFE;
59 ctx->state[3] = 0x10325476;
Andres Amaya Garciabee06352017-04-28 17:00:30 +010060
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010061 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +000062}
63
Manuel Pégourié-Gonnard93c08472021-04-15 12:23:55 +020064#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010065void mbedtls_md4_starts(mbedtls_md4_context *ctx)
Manuel Pégourié-Gonnard93c08472021-04-15 12:23:55 +020066{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010067 mbedtls_md4_starts_ret(ctx);
Manuel Pégourié-Gonnard93c08472021-04-15 12:23:55 +020068}
69#endif
70
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020071#if !defined(MBEDTLS_MD4_PROCESS_ALT)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010072int mbedtls_internal_md4_process(mbedtls_md4_context *ctx,
73 const unsigned char data[64])
Paul Bakker5121ce52009-01-03 21:22:43 +000074{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010075 struct {
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +020076 uint32_t X[16], A, B, C, D;
77 } local;
Paul Bakker5121ce52009-01-03 21:22:43 +000078
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010079 local.X[0] = MBEDTLS_GET_UINT32_LE(data, 0);
80 local.X[1] = MBEDTLS_GET_UINT32_LE(data, 4);
81 local.X[2] = MBEDTLS_GET_UINT32_LE(data, 8);
82 local.X[3] = MBEDTLS_GET_UINT32_LE(data, 12);
83 local.X[4] = MBEDTLS_GET_UINT32_LE(data, 16);
84 local.X[5] = MBEDTLS_GET_UINT32_LE(data, 20);
85 local.X[6] = MBEDTLS_GET_UINT32_LE(data, 24);
86 local.X[7] = MBEDTLS_GET_UINT32_LE(data, 28);
87 local.X[8] = MBEDTLS_GET_UINT32_LE(data, 32);
88 local.X[9] = MBEDTLS_GET_UINT32_LE(data, 36);
89 local.X[10] = MBEDTLS_GET_UINT32_LE(data, 40);
90 local.X[11] = MBEDTLS_GET_UINT32_LE(data, 44);
91 local.X[12] = MBEDTLS_GET_UINT32_LE(data, 48);
92 local.X[13] = MBEDTLS_GET_UINT32_LE(data, 52);
93 local.X[14] = MBEDTLS_GET_UINT32_LE(data, 56);
94 local.X[15] = MBEDTLS_GET_UINT32_LE(data, 60);
Paul Bakker5121ce52009-01-03 21:22:43 +000095
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010096#define S(x, n) (((x) << (n)) | (((x) & 0xFFFFFFFF) >> (32 - (n))))
Paul Bakker5121ce52009-01-03 21:22:43 +000097
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +020098 local.A = ctx->state[0];
99 local.B = ctx->state[1];
100 local.C = ctx->state[2];
101 local.D = ctx->state[3];
Paul Bakker5121ce52009-01-03 21:22:43 +0000102
Hanno Becker1eeca412018-10-15 12:01:35 +0100103#define F(x, y, z) (((x) & (y)) | ((~(x)) & (z)))
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100104#define P(a, b, c, d, x, s) \
Hanno Becker26d02e12018-10-30 09:29:25 +0000105 do \
106 { \
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100107 (a) += F((b), (c), (d)) + (x); \
108 (a) = S((a), (s)); \
109 } while (0)
Hanno Becker1eeca412018-10-15 12:01:35 +0100110
Paul Bakker5121ce52009-01-03 21:22:43 +0000111
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100112 P(local.A, local.B, local.C, local.D, local.X[0], 3);
113 P(local.D, local.A, local.B, local.C, local.X[1], 7);
114 P(local.C, local.D, local.A, local.B, local.X[2], 11);
115 P(local.B, local.C, local.D, local.A, local.X[3], 19);
116 P(local.A, local.B, local.C, local.D, local.X[4], 3);
117 P(local.D, local.A, local.B, local.C, local.X[5], 7);
118 P(local.C, local.D, local.A, local.B, local.X[6], 11);
119 P(local.B, local.C, local.D, local.A, local.X[7], 19);
120 P(local.A, local.B, local.C, local.D, local.X[8], 3);
121 P(local.D, local.A, local.B, local.C, local.X[9], 7);
122 P(local.C, local.D, local.A, local.B, local.X[10], 11);
123 P(local.B, local.C, local.D, local.A, local.X[11], 19);
124 P(local.A, local.B, local.C, local.D, local.X[12], 3);
125 P(local.D, local.A, local.B, local.C, local.X[13], 7);
126 P(local.C, local.D, local.A, local.B, local.X[14], 11);
127 P(local.B, local.C, local.D, local.A, local.X[15], 19);
Paul Bakker5121ce52009-01-03 21:22:43 +0000128
129#undef P
130#undef F
131
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100132#define F(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
133#define P(a, b, c, d, x, s) \
Hanno Becker1eeca412018-10-15 12:01:35 +0100134 do \
135 { \
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100136 (a) += F((b), (c), (d)) + (x) + 0x5A827999; \
137 (a) = S((a), (s)); \
138 } while (0)
Paul Bakker5121ce52009-01-03 21:22:43 +0000139
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100140 P(local.A, local.B, local.C, local.D, local.X[0], 3);
141 P(local.D, local.A, local.B, local.C, local.X[4], 5);
142 P(local.C, local.D, local.A, local.B, local.X[8], 9);
143 P(local.B, local.C, local.D, local.A, local.X[12], 13);
144 P(local.A, local.B, local.C, local.D, local.X[1], 3);
145 P(local.D, local.A, local.B, local.C, local.X[5], 5);
146 P(local.C, local.D, local.A, local.B, local.X[9], 9);
147 P(local.B, local.C, local.D, local.A, local.X[13], 13);
148 P(local.A, local.B, local.C, local.D, local.X[2], 3);
149 P(local.D, local.A, local.B, local.C, local.X[6], 5);
150 P(local.C, local.D, local.A, local.B, local.X[10], 9);
151 P(local.B, local.C, local.D, local.A, local.X[14], 13);
152 P(local.A, local.B, local.C, local.D, local.X[3], 3);
153 P(local.D, local.A, local.B, local.C, local.X[7], 5);
154 P(local.C, local.D, local.A, local.B, local.X[11], 9);
155 P(local.B, local.C, local.D, local.A, local.X[15], 13);
Paul Bakker5121ce52009-01-03 21:22:43 +0000156
157#undef P
158#undef F
159
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100160#define F(x, y, z) ((x) ^ (y) ^ (z))
161#define P(a, b, c, d, x, s) \
Hanno Becker26d02e12018-10-30 09:29:25 +0000162 do \
163 { \
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100164 (a) += F((b), (c), (d)) + (x) + 0x6ED9EBA1; \
165 (a) = S((a), (s)); \
166 } while (0)
Paul Bakker5121ce52009-01-03 21:22:43 +0000167
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100168 P(local.A, local.B, local.C, local.D, local.X[0], 3);
169 P(local.D, local.A, local.B, local.C, local.X[8], 9);
170 P(local.C, local.D, local.A, local.B, local.X[4], 11);
171 P(local.B, local.C, local.D, local.A, local.X[12], 15);
172 P(local.A, local.B, local.C, local.D, local.X[2], 3);
173 P(local.D, local.A, local.B, local.C, local.X[10], 9);
174 P(local.C, local.D, local.A, local.B, local.X[6], 11);
175 P(local.B, local.C, local.D, local.A, local.X[14], 15);
176 P(local.A, local.B, local.C, local.D, local.X[1], 3);
177 P(local.D, local.A, local.B, local.C, local.X[9], 9);
178 P(local.C, local.D, local.A, local.B, local.X[5], 11);
179 P(local.B, local.C, local.D, local.A, local.X[13], 15);
180 P(local.A, local.B, local.C, local.D, local.X[3], 3);
181 P(local.D, local.A, local.B, local.C, local.X[11], 9);
182 P(local.C, local.D, local.A, local.B, local.X[7], 11);
183 P(local.B, local.C, local.D, local.A, local.X[15], 15);
Paul Bakker5121ce52009-01-03 21:22:43 +0000184
185#undef F
186#undef P
187
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200188 ctx->state[0] += local.A;
189 ctx->state[1] += local.B;
190 ctx->state[2] += local.C;
191 ctx->state[3] += local.D;
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100192
gabor-mezei-armd1c98fc2020-08-19 14:03:06 +0200193 /* Zeroise variables to clear sensitive data from memory. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100194 mbedtls_platform_zeroize(&local, sizeof(local));
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100195
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100196 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000197}
Jaeden Amero041039f2018-02-19 15:28:08 +0000198
Manuel Pégourié-Gonnard93c08472021-04-15 12:23:55 +0200199#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100200void mbedtls_md4_process(mbedtls_md4_context *ctx,
201 const unsigned char data[64])
Manuel Pégourié-Gonnard93c08472021-04-15 12:23:55 +0200202{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100203 mbedtls_internal_md4_process(ctx, data);
Manuel Pégourié-Gonnard93c08472021-04-15 12:23:55 +0200204}
205#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200206#endif /* !MBEDTLS_MD4_PROCESS_ALT */
Paul Bakker5121ce52009-01-03 21:22:43 +0000207
208/*
209 * MD4 process buffer
210 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100211int mbedtls_md4_update_ret(mbedtls_md4_context *ctx,
212 const unsigned char *input,
213 size_t ilen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000214{
Janos Follath24eed8d2019-11-22 13:21:35 +0000215 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000216 size_t fill;
Paul Bakker5c2364c2012-10-01 14:41:15 +0000217 uint32_t left;
Paul Bakker5121ce52009-01-03 21:22:43 +0000218
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100219 if (ilen == 0) {
220 return 0;
221 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000222
223 left = ctx->total[0] & 0x3F;
224 fill = 64 - left;
225
Paul Bakker5c2364c2012-10-01 14:41:15 +0000226 ctx->total[0] += (uint32_t) ilen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000227 ctx->total[0] &= 0xFFFFFFFF;
228
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100229 if (ctx->total[0] < (uint32_t) ilen) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000230 ctx->total[1]++;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100231 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000232
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100233 if (left && ilen >= fill) {
234 memcpy((void *) (ctx->buffer + left),
235 (void *) input, fill);
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100236
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100237 if ((ret = mbedtls_internal_md4_process(ctx, ctx->buffer)) != 0) {
238 return ret;
239 }
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100240
Paul Bakker5121ce52009-01-03 21:22:43 +0000241 input += fill;
242 ilen -= fill;
243 left = 0;
244 }
245
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100246 while (ilen >= 64) {
247 if ((ret = mbedtls_internal_md4_process(ctx, input)) != 0) {
248 return ret;
249 }
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100250
Paul Bakker5121ce52009-01-03 21:22:43 +0000251 input += 64;
252 ilen -= 64;
253 }
254
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100255 if (ilen > 0) {
256 memcpy((void *) (ctx->buffer + left),
257 (void *) input, ilen);
Paul Bakker5121ce52009-01-03 21:22:43 +0000258 }
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100259
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100260 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000261}
262
Manuel Pégourié-Gonnard93c08472021-04-15 12:23:55 +0200263#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100264void mbedtls_md4_update(mbedtls_md4_context *ctx,
265 const unsigned char *input,
266 size_t ilen)
Manuel Pégourié-Gonnard93c08472021-04-15 12:23:55 +0200267{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100268 mbedtls_md4_update_ret(ctx, input, ilen);
Manuel Pégourié-Gonnard93c08472021-04-15 12:23:55 +0200269}
270#endif
271
Paul Bakker5121ce52009-01-03 21:22:43 +0000272static const unsigned char md4_padding[64] =
273{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100274 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Paul Bakker5121ce52009-01-03 21:22:43 +0000275 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
276 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
277 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
278};
279
280/*
281 * MD4 final digest
282 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100283int mbedtls_md4_finish_ret(mbedtls_md4_context *ctx,
284 unsigned char output[16])
Paul Bakker5121ce52009-01-03 21:22:43 +0000285{
Janos Follath24eed8d2019-11-22 13:21:35 +0000286 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker5c2364c2012-10-01 14:41:15 +0000287 uint32_t last, padn;
288 uint32_t high, low;
Paul Bakker5121ce52009-01-03 21:22:43 +0000289 unsigned char msglen[8];
290
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100291 high = (ctx->total[0] >> 29)
292 | (ctx->total[1] << 3);
293 low = (ctx->total[0] << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000294
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100295 MBEDTLS_PUT_UINT32_LE(low, msglen, 0);
296 MBEDTLS_PUT_UINT32_LE(high, msglen, 4);
Paul Bakker5121ce52009-01-03 21:22:43 +0000297
298 last = ctx->total[0] & 0x3F;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100299 padn = (last < 56) ? (56 - last) : (120 - last);
Paul Bakker5121ce52009-01-03 21:22:43 +0000300
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100301 ret = mbedtls_md4_update_ret(ctx, (unsigned char *) md4_padding, padn);
302 if (ret != 0) {
303 return ret;
304 }
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100305
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100306 if ((ret = mbedtls_md4_update_ret(ctx, msglen, 8)) != 0) {
307 return ret;
308 }
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100309
Paul Bakker5121ce52009-01-03 21:22:43 +0000310
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100311 MBEDTLS_PUT_UINT32_LE(ctx->state[0], output, 0);
312 MBEDTLS_PUT_UINT32_LE(ctx->state[1], output, 4);
313 MBEDTLS_PUT_UINT32_LE(ctx->state[2], output, 8);
314 MBEDTLS_PUT_UINT32_LE(ctx->state[3], output, 12);
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100315
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100316 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000317}
318
Manuel Pégourié-Gonnard93c08472021-04-15 12:23:55 +0200319#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100320void mbedtls_md4_finish(mbedtls_md4_context *ctx,
321 unsigned char output[16])
Manuel Pégourié-Gonnard93c08472021-04-15 12:23:55 +0200322{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100323 mbedtls_md4_finish_ret(ctx, output);
Manuel Pégourié-Gonnard93c08472021-04-15 12:23:55 +0200324}
325#endif
326
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200327#endif /* !MBEDTLS_MD4_ALT */
Paul Bakker90995b52013-06-24 19:20:35 +0200328
Paul Bakker5121ce52009-01-03 21:22:43 +0000329/*
330 * output = MD4( input buffer )
331 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100332int mbedtls_md4_ret(const unsigned char *input,
333 size_t ilen,
334 unsigned char output[16])
Paul Bakker5121ce52009-01-03 21:22:43 +0000335{
Janos Follath24eed8d2019-11-22 13:21:35 +0000336 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200337 mbedtls_md4_context ctx;
Paul Bakker5121ce52009-01-03 21:22:43 +0000338
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100339 mbedtls_md4_init(&ctx);
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100340
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100341 if ((ret = mbedtls_md4_starts_ret(&ctx)) != 0) {
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100342 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100343 }
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100344
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100345 if ((ret = mbedtls_md4_update_ret(&ctx, input, ilen)) != 0) {
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100346 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100347 }
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100348
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100349 if ((ret = mbedtls_md4_finish_ret(&ctx, output)) != 0) {
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100350 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100351 }
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100352
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100353exit:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100354 mbedtls_md4_free(&ctx);
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100355
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100356 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000357}
358
Manuel Pégourié-Gonnard93c08472021-04-15 12:23:55 +0200359#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100360void mbedtls_md4(const unsigned char *input,
361 size_t ilen,
362 unsigned char output[16])
Manuel Pégourié-Gonnard93c08472021-04-15 12:23:55 +0200363{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100364 mbedtls_md4_ret(input, ilen, output);
Manuel Pégourié-Gonnard93c08472021-04-15 12:23:55 +0200365}
366#endif
367
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200368#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000369
370/*
371 * RFC 1320 test vectors
372 */
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100373static const unsigned char md4_test_str[7][81] =
Paul Bakker5121ce52009-01-03 21:22:43 +0000374{
Paul Bakker9af723c2014-05-01 13:03:14 +0200375 { "" },
Paul Bakker5121ce52009-01-03 21:22:43 +0000376 { "a" },
377 { "abc" },
378 { "message digest" },
379 { "abcdefghijklmnopqrstuvwxyz" },
380 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
Guido Vranken962e4ee2020-08-21 21:08:56 +0200381 { "12345678901234567890123456789012345678901234567890123456789012345678901234567890" }
Paul Bakker5121ce52009-01-03 21:22:43 +0000382};
383
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100384static const size_t md4_test_strlen[7] =
385{
386 0, 1, 3, 14, 26, 62, 80
387};
388
Paul Bakker5121ce52009-01-03 21:22:43 +0000389static const unsigned char md4_test_sum[7][16] =
390{
391 { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31,
392 0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 },
393 { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46,
394 0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 },
395 { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52,
396 0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D },
397 { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8,
398 0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B },
399 { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD,
400 0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 },
401 { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35,
402 0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 },
403 { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19,
404 0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 }
405};
406
407/*
408 * Checkup routine
409 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100410int mbedtls_md4_self_test(int verbose)
Paul Bakker5121ce52009-01-03 21:22:43 +0000411{
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100412 int i, ret = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000413 unsigned char md4sum[16];
414
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100415 for (i = 0; i < 7; i++) {
416 if (verbose != 0) {
417 mbedtls_printf(" MD4 test #%d: ", i + 1);
418 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000419
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100420 ret = mbedtls_md4_ret(md4_test_str[i], md4_test_strlen[i], md4sum);
421 if (ret != 0) {
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100422 goto fail;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100423 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000424
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100425 if (memcmp(md4sum, md4_test_sum[i], 16) != 0) {
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100426 ret = 1;
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100427 goto fail;
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100428 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000429
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100430 if (verbose != 0) {
431 mbedtls_printf("passed\n");
432 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000433 }
434
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100435 if (verbose != 0) {
436 mbedtls_printf("\n");
437 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000438
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100439 return 0;
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100440
441fail:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100442 if (verbose != 0) {
443 mbedtls_printf("failed\n");
444 }
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100445
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100446 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000447}
448
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200449#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +0000450
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200451#endif /* MBEDTLS_MD4_C */