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