Coverage Report

Created: 2025-08-26 07:08

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