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