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