Coverage Report

Created: 2025-10-30 06:17

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