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