1/***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2019, 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#endif
33#ifdef USE_MBEDTLS
34#include <mbedtls/config.h>
35#endif
36
37#if defined(USE_GNUTLS_NETTLE)
38
39#include <nettle/md4.h>
40
41#include "curl_memory.h"
42
43/* The last #include file should be: */
44#include "memdebug.h"
45
46typedef struct md4_ctx MD4_CTX;
47
48static void MD4_Init(MD4_CTX *ctx)
49{
50 md4_init(ctx);
51}
52
53static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
54{
55 md4_update(ctx, size, data);
56}
57
58static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
59{
60 md4_digest(ctx, MD4_DIGEST_SIZE, result);
61}
62
63#elif defined(USE_GNUTLS)
64
65#include <gcrypt.h>
66
67#include "curl_memory.h"
68/* The last #include file should be: */
69#include "memdebug.h"
70
71typedef struct gcry_md_hd_t MD4_CTX;
72
73static void MD4_Init(MD4_CTX *ctx)
74{
75 gcry_md_open(ctx, GCRY_MD_MD4, 0);
76}
77
78static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
79{
80 gcry_md_write(*ctx, data, size);
81}
82
83static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
84{
85 memcpy(result, gcry_md_read(ctx, 0), MD4_DIGEST_LENGTH);
86 gcry_md_close(ctx);
87}
88
89#elif defined(USE_OPENSSL) && !defined(OPENSSL_NO_MD4)
90/* When OpenSSL is available we use the MD4-functions from OpenSSL */
91#include <openssl/md4.h>
92
93#elif defined(USE_SECTRANSP)
94
95#include <CommonCrypto/CommonDigest.h>
96
97#include "curl_memory.h"
98/* The last #include file should be: */
99#include "memdebug.h"
100
101typedef struct {
102 void *data;
103 unsigned long size;
104} MD4_CTX;
105
106static void MD4_Init(MD4_CTX *ctx)
107{
108 ctx->data = NULL;
109 ctx->size = 0;
110}
111
112static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
113{
114 if(ctx->data == NULL) {
115 ctx->data = malloc(size);
116 if(ctx->data != NULL) {
117 memcpy(ctx->data, data, size);
118 ctx->size = size;
119 }
120 }
121}
122
123static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
124{
125 if(ctx->data != NULL) {
126 (void)CC_MD4(ctx->data, (CC_LONG) ctx->size, result);
127
128 Curl_safefree(ctx->data);
129 ctx->size = 0;
130 }
131}
132
133#elif defined(USE_WIN32_CRYPTO)
134
135#include <wincrypt.h>
136
137#include "curl_memory.h"
138 /* The last #include file should be: */
139#include "memdebug.h"
140
141typedef struct {
142 HCRYPTPROV hCryptProv;
143 HCRYPTHASH hHash;
144} MD4_CTX;
145
146static void MD4_Init(MD4_CTX *ctx)
147{
148 ctx->hCryptProv = 0;
149 ctx->hHash = 0;
150
151 if(CryptAcquireContext(&ctx->hCryptProv, NULL, NULL, PROV_RSA_FULL,
152 CRYPT_VERIFYCONTEXT)) {
153 CryptCreateHash(ctx->hCryptProv, CALG_MD4, 0, 0, &ctx->hHash);
154 }
155}
156
157static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
158{
159 CryptHashData(ctx->hHash, data, (unsigned int) size, 0);
160}
161
162static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
163{
164 unsigned long length = 0;
165
166 CryptGetHashParam(ctx->hHash, HP_HASHVAL, NULL, &length, 0);
167 if(length == MD4_DIGEST_LENGTH)
168 CryptGetHashParam(ctx->hHash, HP_HASHVAL, result, &length, 0);
169
170 if(ctx->hHash)
171 CryptDestroyHash(ctx->hHash);
172
173 if(ctx->hCryptProv)
174 CryptReleaseContext(ctx->hCryptProv, 0);
175}
176
177#elif(defined(USE_MBEDTLS) && defined(MBEDTLS_MD4_C))
178
179#include <mbedtls/md4.h>
180
181#include "curl_memory.h"
182/* The last #include file should be: */
183#include "memdebug.h"
184
185typedef struct {
186 void *data;
187 unsigned long size;
188} MD4_CTX;
189
190static void MD4_Init(MD4_CTX *ctx)
191{
192 ctx->data = NULL;
193 ctx->size = 0;
194}
195
196static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
197{
198 if(ctx->data == NULL) {
199 ctx->data = malloc(size);
200 if(ctx->data != NULL) {
201 memcpy(ctx->data, data, size);
202 ctx->size = size;
203 }
204 }
205}
206
207static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
208{
209 if(ctx->data != NULL) {
210 mbedtls_md4(ctx->data, ctx->size, result);
211
212 Curl_safefree(ctx->data);
213 ctx->size = 0;
214 }
215}
216
217#else
218/* When no other crypto library is available, or the crypto library doesn't
219 * support MD4, we use this code segment this implementation of it
220 *
221 * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
222 * MD4 Message-Digest Algorithm (RFC 1320).
223 *
224 * Homepage:
225 https://openwall.info/wiki/people/solar/software/public-domain-source-code/md4
226 *
227 * Author:
228 * Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
229 *
230 * This software was written by Alexander Peslyak in 2001. No copyright is
231 * claimed, and the software is hereby placed in the public domain. In case
232 * this attempt to disclaim copyright and place the software in the public
233 * domain is deemed null and void, then the software is Copyright (c) 2001
234 * Alexander Peslyak and it is hereby released to the general public under the
235 * following terms:
236 *
237 * Redistribution and use in source and binary forms, with or without
238 * modification, are permitted.
239 *
240 * There's ABSOLUTELY NO WARRANTY, express or implied.
241 *
242 * (This is a heavily cut-down "BSD license".)
243 *
244 * This differs from Colin Plumb's older public domain implementation in that
245 * no exactly 32-bit integer data type is required (any 32-bit or wider
246 * unsigned integer data type will do), there's no compile-time endianness
247 * configuration, and the function prototypes match OpenSSL's. No code from
248 * Colin Plumb's implementation has been reused; this comment merely compares
249 * the properties of the two independent implementations.
250 *
251 * The primary goals of this implementation are portability and ease of use.
252 * It is meant to be fast, but not as fast as possible. Some known
253 * optimizations are not included to reduce source code size and avoid
254 * compile-time configuration.
255 */
256
257
258#include <string.h>
259
260/* Any 32-bit or wider unsigned integer data type will do */
261typedef unsigned int MD4_u32plus;
262
263typedef struct {
264 MD4_u32plus lo, hi;
265 MD4_u32plus a, b, c, d;
266 unsigned char buffer[64];
267 MD4_u32plus block[16];
268} MD4_CTX;
269
270static void MD4_Init(MD4_CTX *ctx);
271static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size);
272static 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 */
319static 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
409static void 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}
419
420static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
421{
422 MD4_u32plus saved_lo;
423 unsigned long used;
424
425 saved_lo = ctx->lo;
426 ctx->lo = (saved_lo + size) & 0x1fffffff;
427 if(ctx->lo < saved_lo)
428 ctx->hi++;
429 ctx->hi += (MD4_u32plus)size >> 29;
430
431 used = saved_lo & 0x3f;
432
433 if(used) {
434 unsigned long available = 64 - used;
435
436 if(size < available) {
437 memcpy(&ctx->buffer[used], data, size);
438 return;
439 }
440
441 memcpy(&ctx->buffer[used], data, available);
442 data = (const unsigned char *)data + available;
443 size -= available;
444 body(ctx, ctx->buffer, 64);
445 }
446
447 if(size >= 64) {
448 data = body(ctx, data, size & ~(unsigned long)0x3f);
449 size &= 0x3f;
450 }
451
452 memcpy(ctx->buffer, data, size);
453}
454
455static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
456{
457 unsigned long used, available;
458
459 used = ctx->lo & 0x3f;
460
461 ctx->buffer[used++] = 0x80;
462
463 available = 64 - used;
464
465 if(available < 8) {
466 memset(&ctx->buffer[used], 0, available);
467 body(ctx, ctx->buffer, 64);
468 used = 0;
469 available = 64;
470 }
471
472 memset(&ctx->buffer[used], 0, available - 8);
473
474 ctx->lo <<= 3;
475 ctx->buffer[56] = curlx_ultouc((ctx->lo)&0xff);
476 ctx->buffer[57] = curlx_ultouc((ctx->lo >> 8)&0xff);
477 ctx->buffer[58] = curlx_ultouc((ctx->lo >> 16)&0xff);
478 ctx->buffer[59] = curlx_ultouc((ctx->lo >> 24)&0xff);
479 ctx->buffer[60] = curlx_ultouc((ctx->hi)&0xff);
480 ctx->buffer[61] = curlx_ultouc((ctx->hi >> 8)&0xff);
481 ctx->buffer[62] = curlx_ultouc((ctx->hi >> 16)&0xff);
482 ctx->buffer[63] = curlx_ultouc(ctx->hi >> 24);
483
484 body(ctx, ctx->buffer, 64);
485
486 result[0] = curlx_ultouc((ctx->a)&0xff);
487 result[1] = curlx_ultouc((ctx->a >> 8)&0xff);
488 result[2] = curlx_ultouc((ctx->a >> 16)&0xff);
489 result[3] = curlx_ultouc(ctx->a >> 24);
490 result[4] = curlx_ultouc((ctx->b)&0xff);
491 result[5] = curlx_ultouc((ctx->b >> 8)&0xff);
492 result[6] = curlx_ultouc((ctx->b >> 16)&0xff);
493 result[7] = curlx_ultouc(ctx->b >> 24);
494 result[8] = curlx_ultouc((ctx->c)&0xff);
495 result[9] = curlx_ultouc((ctx->c >> 8)&0xff);
496 result[10] = curlx_ultouc((ctx->c >> 16)&0xff);
497 result[11] = curlx_ultouc(ctx->c >> 24);
498 result[12] = curlx_ultouc((ctx->d)&0xff);
499 result[13] = curlx_ultouc((ctx->d >> 8)&0xff);
500 result[14] = curlx_ultouc((ctx->d >> 16)&0xff);
501 result[15] = curlx_ultouc(ctx->d >> 24);
502
503 memset(ctx, 0, sizeof(*ctx));
504}
505
506#endif /* CRYPTO LIBS */
507
508void Curl_md4it(unsigned char *output, const unsigned char *input, size_t len)
509{
510 MD4_CTX ctx;
511 MD4_Init(&ctx);
512 MD4_Update(&ctx, input, curlx_uztoui(len));
513 MD4_Final(output, &ctx);
514}
515
516#endif /* CURL_DISABLE_CRYPTO_AUTH */
517