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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010040void mbedtls_md4_init(mbedtls_md4_context *ctx)
Paul Bakker5b4af392014-06-26 12:09:34 +020041{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010042 memset(ctx, 0, sizeof(mbedtls_md4_context));
Paul Bakker5b4af392014-06-26 12:09:34 +020043}
44
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010045void mbedtls_md4_free(mbedtls_md4_context *ctx)
Paul Bakker5b4af392014-06-26 12:09:34 +020046{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010047 if (ctx == NULL) {
Paul Bakker5b4af392014-06-26 12:09:34 +020048 return;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010049 }
Paul Bakker5b4af392014-06-26 12:09:34 +020050
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010051 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_md4_context));
Paul Bakker5b4af392014-06-26 12:09:34 +020052}
53
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010054void 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 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010063int 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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010073 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)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010077void mbedtls_md4_starts(mbedtls_md4_context *ctx)
Manuel Pégourié-Gonnard93c08472021-04-15 12:23:55 +020078{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010079 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)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010084int mbedtls_internal_md4_process(mbedtls_md4_context *ctx,
85 const unsigned char data[64])
Paul Bakker5121ce52009-01-03 21:22:43 +000086{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010087 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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010091 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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100108#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)))
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100116#define P(a, b, c, d, x, s) \
Hanno Becker26d02e12018-10-30 09:29:25 +0000117 do \
118 { \
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100119 (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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100124 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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100144#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 { \
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100148 (a) += F((b), (c), (d)) + (x) + 0x5A827999; \
149 (a) = S((a), (s)); \
150 } while (0)
Paul Bakker5121ce52009-01-03 21:22:43 +0000151
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100152 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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100172#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 { \
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100176 (a) += F((b), (c), (d)) + (x) + 0x6ED9EBA1; \
177 (a) = S((a), (s)); \
178 } while (0)
Paul Bakker5121ce52009-01-03 21:22:43 +0000179
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100180 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. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100206 mbedtls_platform_zeroize(&local, sizeof(local));
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100207
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100208 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)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100212void mbedtls_md4_process(mbedtls_md4_context *ctx,
213 const unsigned char data[64])
Manuel Pégourié-Gonnard93c08472021-04-15 12:23:55 +0200214{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100215 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 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100223int 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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100231 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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100241 if (ctx->total[0] < (uint32_t) ilen) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000242 ctx->total[1]++;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100243 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000244
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100245 if (left && ilen >= fill) {
246 memcpy((void *) (ctx->buffer + left),
247 (void *) input, fill);
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100248
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100249 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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100258 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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100267 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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100272 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)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100276void 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{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100280 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{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100286 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 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100295int 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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100303 high = (ctx->total[0] >> 29)
304 | (ctx->total[1] << 3);
305 low = (ctx->total[0] << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000306
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100307 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;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100311 padn = (last < 56) ? (56 - last) : (120 - last);
Paul Bakker5121ce52009-01-03 21:22:43 +0000312
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100313 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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100318 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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100323 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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100328 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)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100332void mbedtls_md4_finish(mbedtls_md4_context *ctx,
333 unsigned char output[16])
Manuel Pégourié-Gonnard93c08472021-04-15 12:23:55 +0200334{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100335 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 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100344int 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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100351 mbedtls_md4_init(&ctx);
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100352
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100353 if ((ret = mbedtls_md4_starts_ret(&ctx)) != 0) {
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100354 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100355 }
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100356
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100357 if ((ret = mbedtls_md4_update_ret(&ctx, input, ilen)) != 0) {
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100358 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100359 }
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100360
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100361 if ((ret = mbedtls_md4_finish_ret(&ctx, output)) != 0) {
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100362 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100363 }
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100364
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100365exit:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100366 mbedtls_md4_free(&ctx);
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100367
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100368 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)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100372void 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{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100376 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 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100422int 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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100427 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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100432 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;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100435 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000436
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100437 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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100442 if (verbose != 0) {
443 mbedtls_printf("passed\n");
444 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000445 }
446
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100447 if (verbose != 0) {
448 mbedtls_printf("\n");
449 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000450
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100451 return 0;
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100452
453fail:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100454 if (verbose != 0) {
455 mbedtls_printf("failed\n");
456 }
Andres Amaya Garciabee06352017-04-28 17:00:30 +0100457
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100458 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 */