• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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