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