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