1/***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
9 *
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at https://curl.se/docs/copyright.html.
13 *
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ***************************************************************************/
22
23#include "curl_setup.h"
24
25#if !defined(CURL_DISABLE_CRYPTO_AUTH)
26
27#include "curl_md4.h"
28#include "warnless.h"
29
30#ifdef USE_OPENSSL
31#include <openssl/opensslconf.h>
32#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
33/* OpenSSL 3.0.0 marks the MD4 functions as deprecated */
34#define OPENSSL_NO_MD4
35#endif
36#endif /* USE_OPENSSL */
37
38#ifdef USE_MBEDTLS
39#include <mbedtls/version.h>
40#if MBEDTLS_VERSION_NUMBER >= 0x03000000
41#include <mbedtls/mbedtls_config.h>
42#else
43#include <mbedtls/config.h>
44#endif
45
46#if(MBEDTLS_VERSION_NUMBER >= 0x02070000)
47 #define HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS
48#endif
49#endif /* USE_MBEDTLS */
50
51#if defined(USE_GNUTLS)
52
53#include <nettle/md4.h>
54
55#include "curl_memory.h"
56
57/* The last #include file should be: */
58#include "memdebug.h"
59
60typedef struct md4_ctx MD4_CTX;
61
62static void MD4_Init(MD4_CTX *ctx)
63{
64 md4_init(ctx);
65}
66
67static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
68{
69 md4_update(ctx, size, data);
70}
71
72static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
73{
74 md4_digest(ctx, MD4_DIGEST_SIZE, result);
75}
76
77#elif defined(USE_OPENSSL) && !defined(OPENSSL_NO_MD4)
78/* When OpenSSL is available we use the MD4-functions from OpenSSL */
79#include <openssl/md4.h>
80
81#elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \
82 (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040) && \
83 defined(__MAC_OS_X_VERSION_MIN_ALLOWED) && \
84 (__MAC_OS_X_VERSION_MIN_ALLOWED < 101500)) || \
85 (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && \
86 (__IPHONE_OS_VERSION_MAX_ALLOWED >= 20000))
87
88#include <CommonCrypto/CommonDigest.h>
89
90#include "curl_memory.h"
91
92/* The last #include file should be: */
93#include "memdebug.h"
94
95typedef CC_MD4_CTX MD4_CTX;
96
97static void MD4_Init(MD4_CTX *ctx)
98{
99 (void)CC_MD4_Init(ctx);
100}
101
102static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
103{
104 (void)CC_MD4_Update(ctx, data, (CC_LONG)size);
105}
106
107static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
108{
109 (void)CC_MD4_Final(result, ctx);
110}
111
112#elif defined(USE_WIN32_CRYPTO)
113
114#include <wincrypt.h>
115
116#include "curl_memory.h"
117
118/* The last #include file should be: */
119#include "memdebug.h"
120
121struct md4_ctx {
122 HCRYPTPROV hCryptProv;
123 HCRYPTHASH hHash;
124};
125typedef struct md4_ctx MD4_CTX;
126
127static void MD4_Init(MD4_CTX *ctx)
128{
129 ctx->hCryptProv = 0;
130 ctx->hHash = 0;
131
132 if(CryptAcquireContext(&ctx->hCryptProv, NULL, NULL, PROV_RSA_FULL,
133 CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
134 CryptCreateHash(ctx->hCryptProv, CALG_MD4, 0, 0, &ctx->hHash);
135 }
136}
137
138static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
139{
140 CryptHashData(ctx->hHash, (BYTE *)data, (unsigned int) size, 0);
141}
142
143static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
144{
145 unsigned long length = 0;
146
147 CryptGetHashParam(ctx->hHash, HP_HASHVAL, NULL, &length, 0);
148 if(length == MD4_DIGEST_LENGTH)
149 CryptGetHashParam(ctx->hHash, HP_HASHVAL, result, &length, 0);
150
151 if(ctx->hHash)
152 CryptDestroyHash(ctx->hHash);
153
154 if(ctx->hCryptProv)
155 CryptReleaseContext(ctx->hCryptProv, 0);
156}
157
158#elif(defined(USE_MBEDTLS) && defined(MBEDTLS_MD4_C))
159
160#include <mbedtls/md4.h>
161
162#include "curl_memory.h"
163
164/* The last #include file should be: */
165#include "memdebug.h"
166
167struct md4_ctx {
168 void *data;
169 unsigned long size;
170};
171typedef struct md4_ctx MD4_CTX;
172
173static void MD4_Init(MD4_CTX *ctx)
174{
175 ctx->data = NULL;
176 ctx->size = 0;
177}
178
179static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
180{
181 if(!ctx->data) {
182 ctx->data = malloc(size);
183 if(ctx->data != NULL) {
184 memcpy(ctx->data, data, size);
185 ctx->size = size;
186 }
187 }
188}
189
190static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
191{
192 if(ctx->data != NULL) {
193#if !defined(HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS)
194 mbedtls_md4(ctx->data, ctx->size, result);
195#else
196 (void) mbedtls_md4_ret(ctx->data, ctx->size, result);
197#endif
198
199 Curl_safefree(ctx->data);
200 ctx->size = 0;
201 }
202}
203
204#else
205/* When no other crypto library is available, or the crypto library doesn't
206 * support MD4, we use this code segment this implementation of it
207 *
208 * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
209 * MD4 Message-Digest Algorithm (RFC 1320).
210 *
211 * Homepage:
212 https://openwall.info/wiki/people/solar/software/public-domain-source-code/md4
213 *
214 * Author:
215 * Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
216 *
217 * This software was written by Alexander Peslyak in 2001. No copyright is
218 * claimed, and the software is hereby placed in the public domain. In case
219 * this attempt to disclaim copyright and place the software in the public
220 * domain is deemed null and void, then the software is Copyright (c) 2001
221 * Alexander Peslyak and it is hereby released to the general public under the
222 * following terms:
223 *
224 * Redistribution and use in source and binary forms, with or without
225 * modification, are permitted.
226 *
227 * There's ABSOLUTELY NO WARRANTY, express or implied.
228 *
229 * (This is a heavily cut-down "BSD license".)
230 *
231 * This differs from Colin Plumb's older public domain implementation in that
232 * no exactly 32-bit integer data type is required (any 32-bit or wider
233 * unsigned integer data type will do), there's no compile-time endianness
234 * configuration, and the function prototypes match OpenSSL's. No code from
235 * Colin Plumb's implementation has been reused; this comment merely compares
236 * the properties of the two independent implementations.
237 *
238 * The primary goals of this implementation are portability and ease of use.
239 * It is meant to be fast, but not as fast as possible. Some known
240 * optimizations are not included to reduce source code size and avoid
241 * compile-time configuration.
242 */
243
244
245#include <string.h>
246
247/* Any 32-bit or wider unsigned integer data type will do */
248typedef unsigned int MD4_u32plus;
249
250struct md4_ctx {
251 MD4_u32plus lo, hi;
252 MD4_u32plus a, b, c, d;
253 unsigned char buffer[64];
254 MD4_u32plus block[16];
255};
256typedef struct md4_ctx MD4_CTX;
257
258static void MD4_Init(MD4_CTX *ctx);
259static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size);
260static void MD4_Final(unsigned char *result, MD4_CTX *ctx);
261
262/*
263 * The basic MD4 functions.
264 *
265 * F and G are optimized compared to their RFC 1320 definitions, with the
266 * optimization for F borrowed from Colin Plumb's MD5 implementation.
267 */
268#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
269#define G(x, y, z) (((x) & ((y) | (z))) | ((y) & (z)))
270#define H(x, y, z) ((x) ^ (y) ^ (z))
271
272/*
273 * The MD4 transformation for all three rounds.
274 */
275#define STEP(f, a, b, c, d, x, s) \
276 (a) += f((b), (c), (d)) + (x); \
277 (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s))));
278
279/*
280 * SET reads 4 input bytes in little-endian byte order and stores them
281 * in a properly aligned word in host byte order.
282 *
283 * The check for little-endian architectures that tolerate unaligned
284 * memory accesses is just an optimization. Nothing will break if it
285 * doesn't work.
286 */
287#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
288#define SET(n) \
289 (*(MD4_u32plus *)(void *)&ptr[(n) * 4])
290#define GET(n) \
291 SET(n)
292#else
293#define SET(n) \
294 (ctx->block[(n)] = \
295 (MD4_u32plus)ptr[(n) * 4] | \
296 ((MD4_u32plus)ptr[(n) * 4 + 1] << 8) | \
297 ((MD4_u32plus)ptr[(n) * 4 + 2] << 16) | \
298 ((MD4_u32plus)ptr[(n) * 4 + 3] << 24))
299#define GET(n) \
300 (ctx->block[(n)])
301#endif
302
303/*
304 * This processes one or more 64-byte data blocks, but does NOT update
305 * the bit counters. There are no alignment requirements.
306 */
307static const void *body(MD4_CTX *ctx, const void *data, unsigned long size)
308{
309 const unsigned char *ptr;
310 MD4_u32plus a, b, c, d;
311
312 ptr = (const unsigned char *)data;
313
314 a = ctx->a;
315 b = ctx->b;
316 c = ctx->c;
317 d = ctx->d;
318
319 do {
320 MD4_u32plus saved_a, saved_b, saved_c, saved_d;
321
322 saved_a = a;
323 saved_b = b;
324 saved_c = c;
325 saved_d = d;
326
327/* Round 1 */
328 STEP(F, a, b, c, d, SET(0), 3)
329 STEP(F, d, a, b, c, SET(1), 7)
330 STEP(F, c, d, a, b, SET(2), 11)
331 STEP(F, b, c, d, a, SET(3), 19)
332 STEP(F, a, b, c, d, SET(4), 3)
333 STEP(F, d, a, b, c, SET(5), 7)
334 STEP(F, c, d, a, b, SET(6), 11)
335 STEP(F, b, c, d, a, SET(7), 19)
336 STEP(F, a, b, c, d, SET(8), 3)
337 STEP(F, d, a, b, c, SET(9), 7)
338 STEP(F, c, d, a, b, SET(10), 11)
339 STEP(F, b, c, d, a, SET(11), 19)
340 STEP(F, a, b, c, d, SET(12), 3)
341 STEP(F, d, a, b, c, SET(13), 7)
342 STEP(F, c, d, a, b, SET(14), 11)
343 STEP(F, b, c, d, a, SET(15), 19)
344
345/* Round 2 */
346 STEP(G, a, b, c, d, GET(0) + 0x5a827999, 3)
347 STEP(G, d, a, b, c, GET(4) + 0x5a827999, 5)
348 STEP(G, c, d, a, b, GET(8) + 0x5a827999, 9)
349 STEP(G, b, c, d, a, GET(12) + 0x5a827999, 13)
350 STEP(G, a, b, c, d, GET(1) + 0x5a827999, 3)
351 STEP(G, d, a, b, c, GET(5) + 0x5a827999, 5)
352 STEP(G, c, d, a, b, GET(9) + 0x5a827999, 9)
353 STEP(G, b, c, d, a, GET(13) + 0x5a827999, 13)
354 STEP(G, a, b, c, d, GET(2) + 0x5a827999, 3)
355 STEP(G, d, a, b, c, GET(6) + 0x5a827999, 5)
356 STEP(G, c, d, a, b, GET(10) + 0x5a827999, 9)
357 STEP(G, b, c, d, a, GET(14) + 0x5a827999, 13)
358 STEP(G, a, b, c, d, GET(3) + 0x5a827999, 3)
359 STEP(G, d, a, b, c, GET(7) + 0x5a827999, 5)
360 STEP(G, c, d, a, b, GET(11) + 0x5a827999, 9)
361 STEP(G, b, c, d, a, GET(15) + 0x5a827999, 13)
362
363/* Round 3 */
364 STEP(H, a, b, c, d, GET(0) + 0x6ed9eba1, 3)
365 STEP(H, d, a, b, c, GET(8) + 0x6ed9eba1, 9)
366 STEP(H, c, d, a, b, GET(4) + 0x6ed9eba1, 11)
367 STEP(H, b, c, d, a, GET(12) + 0x6ed9eba1, 15)
368 STEP(H, a, b, c, d, GET(2) + 0x6ed9eba1, 3)
369 STEP(H, d, a, b, c, GET(10) + 0x6ed9eba1, 9)
370 STEP(H, c, d, a, b, GET(6) + 0x6ed9eba1, 11)
371 STEP(H, b, c, d, a, GET(14) + 0x6ed9eba1, 15)
372 STEP(H, a, b, c, d, GET(1) + 0x6ed9eba1, 3)
373 STEP(H, d, a, b, c, GET(9) + 0x6ed9eba1, 9)
374 STEP(H, c, d, a, b, GET(5) + 0x6ed9eba1, 11)
375 STEP(H, b, c, d, a, GET(13) + 0x6ed9eba1, 15)
376 STEP(H, a, b, c, d, GET(3) + 0x6ed9eba1, 3)
377 STEP(H, d, a, b, c, GET(11) + 0x6ed9eba1, 9)
378 STEP(H, c, d, a, b, GET(7) + 0x6ed9eba1, 11)
379 STEP(H, b, c, d, a, GET(15) + 0x6ed9eba1, 15)
380
381 a += saved_a;
382 b += saved_b;
383 c += saved_c;
384 d += saved_d;
385
386 ptr += 64;
387 } while(size -= 64);
388
389 ctx->a = a;
390 ctx->b = b;
391 ctx->c = c;
392 ctx->d = d;
393
394 return ptr;
395}
396
397static void MD4_Init(MD4_CTX *ctx)
398{
399 ctx->a = 0x67452301;
400 ctx->b = 0xefcdab89;
401 ctx->c = 0x98badcfe;
402 ctx->d = 0x10325476;
403
404 ctx->lo = 0;
405 ctx->hi = 0;
406}
407
408static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
409{
410 MD4_u32plus saved_lo;
411 unsigned long used;
412
413 saved_lo = ctx->lo;
414 ctx->lo = (saved_lo + size) & 0x1fffffff;
415 if(ctx->lo < saved_lo)
416 ctx->hi++;
417 ctx->hi += (MD4_u32plus)size >> 29;
418
419 used = saved_lo & 0x3f;
420
421 if(used) {
422 unsigned long available = 64 - used;
423
424 if(size < available) {
425 memcpy(&ctx->buffer[used], data, size);
426 return;
427 }
428
429 memcpy(&ctx->buffer[used], data, available);
430 data = (const unsigned char *)data + available;
431 size -= available;
432 body(ctx, ctx->buffer, 64);
433 }
434
435 if(size >= 64) {
436 data = body(ctx, data, size & ~(unsigned long)0x3f);
437 size &= 0x3f;
438 }
439
440 memcpy(ctx->buffer, data, size);
441}
442
443static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
444{
445 unsigned long used, available;
446
447 used = ctx->lo & 0x3f;
448
449 ctx->buffer[used++] = 0x80;
450
451 available = 64 - used;
452
453 if(available < 8) {
454 memset(&ctx->buffer[used], 0, available);
455 body(ctx, ctx->buffer, 64);
456 used = 0;
457 available = 64;
458 }
459
460 memset(&ctx->buffer[used], 0, available - 8);
461
462 ctx->lo <<= 3;
463 ctx->buffer[56] = curlx_ultouc((ctx->lo)&0xff);
464 ctx->buffer[57] = curlx_ultouc((ctx->lo >> 8)&0xff);
465 ctx->buffer[58] = curlx_ultouc((ctx->lo >> 16)&0xff);
466 ctx->buffer[59] = curlx_ultouc((ctx->lo >> 24)&0xff);
467 ctx->buffer[60] = curlx_ultouc((ctx->hi)&0xff);
468 ctx->buffer[61] = curlx_ultouc((ctx->hi >> 8)&0xff);
469 ctx->buffer[62] = curlx_ultouc((ctx->hi >> 16)&0xff);
470 ctx->buffer[63] = curlx_ultouc(ctx->hi >> 24);
471
472 body(ctx, ctx->buffer, 64);
473
474 result[0] = curlx_ultouc((ctx->a)&0xff);
475 result[1] = curlx_ultouc((ctx->a >> 8)&0xff);
476 result[2] = curlx_ultouc((ctx->a >> 16)&0xff);
477 result[3] = curlx_ultouc(ctx->a >> 24);
478 result[4] = curlx_ultouc((ctx->b)&0xff);
479 result[5] = curlx_ultouc((ctx->b >> 8)&0xff);
480 result[6] = curlx_ultouc((ctx->b >> 16)&0xff);
481 result[7] = curlx_ultouc(ctx->b >> 24);
482 result[8] = curlx_ultouc((ctx->c)&0xff);
483 result[9] = curlx_ultouc((ctx->c >> 8)&0xff);
484 result[10] = curlx_ultouc((ctx->c >> 16)&0xff);
485 result[11] = curlx_ultouc(ctx->c >> 24);
486 result[12] = curlx_ultouc((ctx->d)&0xff);
487 result[13] = curlx_ultouc((ctx->d >> 8)&0xff);
488 result[14] = curlx_ultouc((ctx->d >> 16)&0xff);
489 result[15] = curlx_ultouc(ctx->d >> 24);
490
491 memset(ctx, 0, sizeof(*ctx));
492}
493
494#endif /* CRYPTO LIBS */
495
496void Curl_md4it(unsigned char *output, const unsigned char *input,
497 const size_t len)
498{
499 MD4_CTX ctx;
500
501 MD4_Init(&ctx);
502 MD4_Update(&ctx, input, curlx_uztoui(len));
503 MD4_Final(output, &ctx);
504}
505
506#endif /* CURL_DISABLE_CRYPTO_AUTH */
507