Coverage Report

Created: 2026-06-15 07:03

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Utilities/cmcurl/lib/md5.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
#include "curl_setup.h"
25
26
#if (defined(USE_CURL_NTLM_CORE) && !defined(USE_WINDOWS_SSPI)) || \
27
  !defined(CURL_DISABLE_DIGEST_AUTH)
28
29
#include "curl_md5.h"
30
#include "curl_hmac.h"
31
32
#ifdef USE_OPENSSL
33
#include <openssl/opensslconf.h>
34
#endif
35
36
#ifdef USE_WOLFSSL
37
#include <wolfssl/options.h>
38
#endif
39
40
#ifdef USE_MBEDTLS
41
#include <mbedtls/version.h>
42
#if MBEDTLS_VERSION_NUMBER < 0x03020000
43
#error "mbedTLS 3.2.0 or later required"
44
#endif
45
#include <psa/crypto_config.h>
46
#endif
47
48
#ifdef USE_GNUTLS
49
#include <nettle/md5.h>
50
51
typedef struct md5_ctx my_md5_ctx;
52
53
static CURLcode my_md5_init(void *ctx)
54
{
55
  md5_init(ctx);
56
  return CURLE_OK;
57
}
58
59
static void my_md5_update(void *ctx,
60
                          const unsigned char *input, unsigned int len)
61
{
62
  md5_update(ctx, len, input);
63
}
64
65
static void my_md5_final(unsigned char *digest, void *ctx)
66
{
67
  md5_digest(ctx, 16, digest);
68
}
69
70
#elif defined(USE_OPENSSL) && \
71
  !defined(OPENSSL_NO_MD5) && !defined(OPENSSL_NO_DEPRECATED_3_0)
72
#include <openssl/md5.h>
73
74
typedef MD5_CTX my_md5_ctx;
75
76
static CURLcode my_md5_init(void *ctx)
77
{
78
  if(!MD5_Init(ctx))
79
    return CURLE_OUT_OF_MEMORY;
80
81
  return CURLE_OK;
82
}
83
84
static void my_md5_update(void *ctx,
85
                          const unsigned char *input, unsigned int len)
86
{
87
  (void)MD5_Update(ctx, input, len);
88
}
89
90
static void my_md5_final(unsigned char *digest, void *ctx)
91
{
92
  (void)MD5_Final(digest, ctx);
93
}
94
95
#elif defined(USE_WOLFSSL) && !defined(NO_MD5)
96
#include <wolfssl/wolfcrypt/md5.h>
97
98
typedef wc_Md5 my_md5_ctx;
99
100
static CURLcode my_md5_init(void *ctx)
101
{
102
  if(wc_InitMd5(ctx))
103
    return CURLE_OUT_OF_MEMORY;
104
  return CURLE_OK;
105
}
106
107
static void my_md5_update(void *ctx,
108
                          const unsigned char *input, unsigned int len)
109
{
110
  (void)wc_Md5Update(ctx, input, (word32)len);
111
}
112
113
static void my_md5_final(unsigned char *digest, void *ctx)
114
{
115
  (void)wc_Md5Final(ctx, digest);
116
}
117
118
#elif defined(USE_MBEDTLS) && \
119
  defined(PSA_WANT_ALG_MD5) && PSA_WANT_ALG_MD5  /* mbedTLS 4+ */
120
#include <psa/crypto.h>
121
122
typedef psa_hash_operation_t my_md5_ctx;
123
124
static CURLcode my_md5_init(void *ctx)
125
{
126
  memset(ctx, 0, sizeof(my_md5_ctx));
127
  if(psa_hash_setup(ctx, PSA_ALG_MD5) != PSA_SUCCESS)
128
    return CURLE_OUT_OF_MEMORY;
129
  return CURLE_OK;
130
}
131
132
static void my_md5_update(void *ctx,
133
                          const unsigned char *input, unsigned int len)
134
{
135
  (void)psa_hash_update(ctx, input, len);
136
}
137
138
static void my_md5_final(unsigned char *digest, void *ctx)
139
{
140
  size_t actual_length;
141
  (void)psa_hash_finish(ctx, digest, 16, &actual_length);
142
}
143
144
#elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \
145
              (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040) && \
146
       defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && \
147
              (__MAC_OS_X_VERSION_MIN_REQUIRED < 101500)) || \
148
      (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && \
149
              (__IPHONE_OS_VERSION_MAX_ALLOWED >= 20000) && \
150
       defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && \
151
              (__IPHONE_OS_VERSION_MIN_REQUIRED < 130000))
152
#include <CommonCrypto/CommonDigest.h>
153
154
/* For Apple operating systems: CommonCrypto has the functions we need.
155
   These functions are available on Tiger and later, as well as iOS 2.0
156
   and later. If you are building for an older cat, well, sorry.
157
158
   Declaring the functions as static like this seems to be a bit more
159
   reliable than defining COMMON_DIGEST_FOR_OPENSSL on older cats. */
160
#  define my_md5_ctx CC_MD5_CTX
161
162
static CURLcode my_md5_init(void *ctx)
163
{
164
  if(!CC_MD5_Init(ctx))
165
    return CURLE_OUT_OF_MEMORY;
166
167
  return CURLE_OK;
168
}
169
170
static void my_md5_update(void *ctx,
171
                          const unsigned char *input, unsigned int len)
172
{
173
  CC_MD5_Update(ctx, input, len);
174
}
175
176
static void my_md5_final(unsigned char *digest, void *ctx)
177
{
178
  CC_MD5_Final(digest, ctx);
179
}
180
181
#elif defined(USE_WIN32_CRYPTO)
182
#include <wincrypt.h>
183
184
struct md5_ctx {
185
  HCRYPTPROV hCryptProv;
186
  HCRYPTHASH hHash;
187
};
188
typedef struct md5_ctx my_md5_ctx;
189
190
static CURLcode my_md5_init(void *in)
191
{
192
  my_md5_ctx *ctx = (my_md5_ctx *)in;
193
  if(!CryptAcquireContext(&ctx->hCryptProv, NULL, NULL, PROV_RSA_FULL,
194
                          CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
195
    return CURLE_OUT_OF_MEMORY;
196
197
  if(!CryptCreateHash(ctx->hCryptProv, CALG_MD5, 0, 0, &ctx->hHash)) {
198
    CryptReleaseContext(ctx->hCryptProv, 0);
199
    ctx->hCryptProv = 0;
200
    return CURLE_FAILED_INIT;
201
  }
202
203
  return CURLE_OK;
204
}
205
206
static void my_md5_update(void *in,
207
                          const unsigned char *input, unsigned int len)
208
{
209
  my_md5_ctx *ctx = in;
210
  CryptHashData(ctx->hHash, (const BYTE *)input, len, 0);
211
}
212
213
static void my_md5_final(unsigned char *digest, void *in)
214
{
215
  my_md5_ctx *ctx = (my_md5_ctx *)in;
216
  unsigned long length = 0;
217
  CryptGetHashParam(ctx->hHash, HP_HASHVAL, NULL, &length, 0);
218
  if(length == 16)
219
    CryptGetHashParam(ctx->hHash, HP_HASHVAL, digest, &length, 0);
220
  if(ctx->hHash)
221
    CryptDestroyHash(ctx->hHash);
222
  if(ctx->hCryptProv)
223
    CryptReleaseContext(ctx->hCryptProv, 0);
224
}
225
226
#else
227
228
/* When no other crypto library is available we use this code segment */
229
230
/*
231
 * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
232
 * MD5 Message-Digest Algorithm (RFC 1321).
233
 *
234
 * Homepage:
235
 * https://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
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
245
 * the following terms:
246
 *
247
 * Redistribution and use in source and binary forms, with or without
248
 * modification, are permitted.
249
 *
250
 * There is ABSOLUTELY NO WARRANTY, express or implied.
251
 *
252
 * (This is a heavily cut-down "BSD license".)
253
 */
254
255
struct md5_ctx {
256
  uint32_t lo, hi;
257
  uint32_t a, b, c, d;
258
  unsigned char buffer[64];
259
  uint32_t block[16];
260
};
261
typedef struct md5_ctx my_md5_ctx;
262
263
/*
264
 * The basic MD5 functions.
265
 *
266
 * F and G are optimized compared to their RFC 1321 definitions for
267
 * architectures that lack an AND-NOT instruction, like in Colin Plumb's
268
 * implementation.
269
 */
270
0
#define MD5_F(x, y, z)                  ((z) ^ ((x) & ((y) ^ (z))))
271
0
#define MD5_G(x, y, z)                  ((y) ^ ((z) & ((x) ^ (y))))
272
0
#define MD5_H(x, y, z)                  (((x) ^ (y)) ^ (z))
273
0
#define MD5_H2(x, y, z)                 ((x) ^ ((y) ^ (z)))
274
0
#define MD5_I(x, y, z)                  ((y) ^ ((x) | ~(z)))
275
276
/*
277
 * The MD5 transformation for all four rounds.
278
 */
279
#define MD5_STEP(f, a, b, c, d, x, t, s) \
280
0
  (a) += f(b, c, d) + (x) + (t); \
281
0
  (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
282
0
  (a) += (b);
283
284
/*
285
 * SET reads 4 input bytes in little-endian byte order and stores them
286
 * in a properly aligned word in host byte order.
287
 *
288
 * The check for little-endian architectures that tolerate unaligned memory
289
 * accesses is an optimization. Nothing will break if it does not work.
290
 */
291
#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
292
#define MD5_SET(n) (*(const uint32_t *)(const void *)&ptr[(n) * 4])
293
#define MD5_GET(n) MD5_SET(n)
294
#else
295
#define MD5_SET(n) (ctx->block[n] =      \
296
   (uint32_t)ptr[(n) * 4]              | \
297
  ((uint32_t)ptr[((n) * 4) + 1] <<  8) | \
298
  ((uint32_t)ptr[((n) * 4) + 2] << 16) | \
299
  ((uint32_t)ptr[((n) * 4) + 3] << 24))
300
#define MD5_GET(n) ctx->block[n]
301
#endif
302
303
/*
304
 * This processes one or more 64-byte data blocks, but does NOT update
305
 * the bit counters. There are no alignment requirements.
306
 */
307
static const void *my_md5_body(my_md5_ctx *ctx,
308
                               const void *data, unsigned long size)
309
0
{
310
0
  const unsigned char *ptr;
311
0
  uint32_t a, b, c, d;
312
313
0
  ptr = (const unsigned char *)data;
314
315
0
  a = ctx->a;
316
0
  b = ctx->b;
317
0
  c = ctx->c;
318
0
  d = ctx->d;
319
320
0
  do {
321
0
    uint32_t saved_a, saved_b, saved_c, saved_d;
322
323
0
    saved_a = a;
324
0
    saved_b = b;
325
0
    saved_c = c;
326
0
    saved_d = d;
327
328
    /* Round 1 */
329
0
    MD5_STEP(MD5_F, a, b, c, d, MD5_SET(0), 0xd76aa478, 7)
330
0
    MD5_STEP(MD5_F, d, a, b, c, MD5_SET(1), 0xe8c7b756, 12)
331
0
    MD5_STEP(MD5_F, c, d, a, b, MD5_SET(2), 0x242070db, 17)
332
0
    MD5_STEP(MD5_F, b, c, d, a, MD5_SET(3), 0xc1bdceee, 22)
333
0
    MD5_STEP(MD5_F, a, b, c, d, MD5_SET(4), 0xf57c0faf, 7)
334
0
    MD5_STEP(MD5_F, d, a, b, c, MD5_SET(5), 0x4787c62a, 12)
335
0
    MD5_STEP(MD5_F, c, d, a, b, MD5_SET(6), 0xa8304613, 17)
336
0
    MD5_STEP(MD5_F, b, c, d, a, MD5_SET(7), 0xfd469501, 22)
337
0
    MD5_STEP(MD5_F, a, b, c, d, MD5_SET(8), 0x698098d8, 7)
338
0
    MD5_STEP(MD5_F, d, a, b, c, MD5_SET(9), 0x8b44f7af, 12)
339
0
    MD5_STEP(MD5_F, c, d, a, b, MD5_SET(10), 0xffff5bb1, 17)
340
0
    MD5_STEP(MD5_F, b, c, d, a, MD5_SET(11), 0x895cd7be, 22)
341
0
    MD5_STEP(MD5_F, a, b, c, d, MD5_SET(12), 0x6b901122, 7)
342
0
    MD5_STEP(MD5_F, d, a, b, c, MD5_SET(13), 0xfd987193, 12)
343
0
    MD5_STEP(MD5_F, c, d, a, b, MD5_SET(14), 0xa679438e, 17)
344
0
    MD5_STEP(MD5_F, b, c, d, a, MD5_SET(15), 0x49b40821, 22)
345
346
    /* Round 2 */
347
0
    MD5_STEP(MD5_G, a, b, c, d, MD5_GET(1), 0xf61e2562, 5)
348
0
    MD5_STEP(MD5_G, d, a, b, c, MD5_GET(6), 0xc040b340, 9)
349
0
    MD5_STEP(MD5_G, c, d, a, b, MD5_GET(11), 0x265e5a51, 14)
350
0
    MD5_STEP(MD5_G, b, c, d, a, MD5_GET(0), 0xe9b6c7aa, 20)
351
0
    MD5_STEP(MD5_G, a, b, c, d, MD5_GET(5), 0xd62f105d, 5)
352
0
    MD5_STEP(MD5_G, d, a, b, c, MD5_GET(10), 0x02441453, 9)
353
0
    MD5_STEP(MD5_G, c, d, a, b, MD5_GET(15), 0xd8a1e681, 14)
354
0
    MD5_STEP(MD5_G, b, c, d, a, MD5_GET(4), 0xe7d3fbc8, 20)
355
0
    MD5_STEP(MD5_G, a, b, c, d, MD5_GET(9), 0x21e1cde6, 5)
356
0
    MD5_STEP(MD5_G, d, a, b, c, MD5_GET(14), 0xc33707d6, 9)
357
0
    MD5_STEP(MD5_G, c, d, a, b, MD5_GET(3), 0xf4d50d87, 14)
358
0
    MD5_STEP(MD5_G, b, c, d, a, MD5_GET(8), 0x455a14ed, 20)
359
0
    MD5_STEP(MD5_G, a, b, c, d, MD5_GET(13), 0xa9e3e905, 5)
360
0
    MD5_STEP(MD5_G, d, a, b, c, MD5_GET(2), 0xfcefa3f8, 9)
361
0
    MD5_STEP(MD5_G, c, d, a, b, MD5_GET(7), 0x676f02d9, 14)
362
0
    MD5_STEP(MD5_G, b, c, d, a, MD5_GET(12), 0x8d2a4c8a, 20)
363
364
    /* Round 3 */
365
0
    MD5_STEP(MD5_H, a, b, c, d, MD5_GET(5), 0xfffa3942, 4)
366
0
    MD5_STEP(MD5_H2, d, a, b, c, MD5_GET(8), 0x8771f681, 11)
367
0
    MD5_STEP(MD5_H, c, d, a, b, MD5_GET(11), 0x6d9d6122, 16)
368
0
    MD5_STEP(MD5_H2, b, c, d, a, MD5_GET(14), 0xfde5380c, 23)
369
0
    MD5_STEP(MD5_H, a, b, c, d, MD5_GET(1), 0xa4beea44, 4)
370
0
    MD5_STEP(MD5_H2, d, a, b, c, MD5_GET(4), 0x4bdecfa9, 11)
371
0
    MD5_STEP(MD5_H, c, d, a, b, MD5_GET(7), 0xf6bb4b60, 16)
372
0
    MD5_STEP(MD5_H2, b, c, d, a, MD5_GET(10), 0xbebfbc70, 23)
373
0
    MD5_STEP(MD5_H, a, b, c, d, MD5_GET(13), 0x289b7ec6, 4)
374
0
    MD5_STEP(MD5_H2, d, a, b, c, MD5_GET(0), 0xeaa127fa, 11)
375
0
    MD5_STEP(MD5_H, c, d, a, b, MD5_GET(3), 0xd4ef3085, 16)
376
0
    MD5_STEP(MD5_H2, b, c, d, a, MD5_GET(6), 0x04881d05, 23)
377
0
    MD5_STEP(MD5_H, a, b, c, d, MD5_GET(9), 0xd9d4d039, 4)
378
0
    MD5_STEP(MD5_H2, d, a, b, c, MD5_GET(12), 0xe6db99e5, 11)
379
0
    MD5_STEP(MD5_H, c, d, a, b, MD5_GET(15), 0x1fa27cf8, 16)
380
0
    MD5_STEP(MD5_H2, b, c, d, a, MD5_GET(2), 0xc4ac5665, 23)
381
382
    /* Round 4 */
383
0
    MD5_STEP(MD5_I, a, b, c, d, MD5_GET(0), 0xf4292244, 6)
384
0
    MD5_STEP(MD5_I, d, a, b, c, MD5_GET(7), 0x432aff97, 10)
385
0
    MD5_STEP(MD5_I, c, d, a, b, MD5_GET(14), 0xab9423a7, 15)
386
0
    MD5_STEP(MD5_I, b, c, d, a, MD5_GET(5), 0xfc93a039, 21)
387
0
    MD5_STEP(MD5_I, a, b, c, d, MD5_GET(12), 0x655b59c3, 6)
388
0
    MD5_STEP(MD5_I, d, a, b, c, MD5_GET(3), 0x8f0ccc92, 10)
389
0
    MD5_STEP(MD5_I, c, d, a, b, MD5_GET(10), 0xffeff47d, 15)
390
0
    MD5_STEP(MD5_I, b, c, d, a, MD5_GET(1), 0x85845dd1, 21)
391
0
    MD5_STEP(MD5_I, a, b, c, d, MD5_GET(8), 0x6fa87e4f, 6)
392
0
    MD5_STEP(MD5_I, d, a, b, c, MD5_GET(15), 0xfe2ce6e0, 10)
393
0
    MD5_STEP(MD5_I, c, d, a, b, MD5_GET(6), 0xa3014314, 15)
394
0
    MD5_STEP(MD5_I, b, c, d, a, MD5_GET(13), 0x4e0811a1, 21)
395
0
    MD5_STEP(MD5_I, a, b, c, d, MD5_GET(4), 0xf7537e82, 6)
396
0
    MD5_STEP(MD5_I, d, a, b, c, MD5_GET(11), 0xbd3af235, 10)
397
0
    MD5_STEP(MD5_I, c, d, a, b, MD5_GET(2), 0x2ad7d2bb, 15)
398
0
    MD5_STEP(MD5_I, b, c, d, a, MD5_GET(9), 0xeb86d391, 21)
399
400
0
    a += saved_a;
401
0
    b += saved_b;
402
0
    c += saved_c;
403
0
    d += saved_d;
404
405
0
    ptr += 64;
406
0
  } while(size -= 64);
407
408
0
  ctx->a = a;
409
0
  ctx->b = b;
410
0
  ctx->c = c;
411
0
  ctx->d = d;
412
413
0
  return ptr;
414
0
}
415
416
static CURLcode my_md5_init(void *in)
417
0
{
418
0
  my_md5_ctx *ctx = (my_md5_ctx *)in;
419
0
  ctx->a = 0x67452301;
420
0
  ctx->b = 0xefcdab89;
421
0
  ctx->c = 0x98badcfe;
422
0
  ctx->d = 0x10325476;
423
424
0
  ctx->lo = 0;
425
0
  ctx->hi = 0;
426
427
0
  return CURLE_OK;
428
0
}
429
430
static void my_md5_update(void *in,
431
                          const unsigned char *input, unsigned int len)
432
0
{
433
0
  uint32_t saved_lo;
434
0
  unsigned int used;
435
0
  my_md5_ctx *ctx = (my_md5_ctx *)in;
436
437
0
  saved_lo = ctx->lo;
438
0
  ctx->lo = (saved_lo + len) & 0x1fffffff;
439
0
  if(ctx->lo < saved_lo)
440
0
    ctx->hi++;
441
0
  ctx->hi += (uint32_t)len >> 29;
442
443
0
  used = saved_lo & 0x3f;
444
445
0
  if(used) {
446
0
    unsigned int available = 64 - used;
447
448
0
    if(len < available) {
449
0
      memcpy(&ctx->buffer[used], input, len);
450
0
      return;
451
0
    }
452
453
0
    memcpy(&ctx->buffer[used], input, available);
454
0
    input = (const unsigned char *)input + available;
455
0
    len -= available;
456
0
    my_md5_body(ctx, ctx->buffer, 64);
457
0
  }
458
459
0
  if(len >= 64) {
460
0
    input = my_md5_body(ctx, input, len & ~(unsigned long)0x3f);
461
0
    len &= 0x3f;
462
0
  }
463
464
0
  memcpy(ctx->buffer, input, len);
465
0
}
466
467
static void my_md5_final(unsigned char *digest, void *in)
468
0
{
469
0
  unsigned int used, available;
470
0
  my_md5_ctx *ctx = (my_md5_ctx *)in;
471
472
0
  used = ctx->lo & 0x3f;
473
474
0
  ctx->buffer[used++] = 0x80;
475
476
0
  available = 64 - used;
477
478
0
  if(available < 8) {
479
0
    memset(&ctx->buffer[used], 0, available);
480
0
    my_md5_body(ctx, ctx->buffer, 64);
481
0
    used = 0;
482
0
    available = 64;
483
0
  }
484
485
0
  memset(&ctx->buffer[used], 0, available - 8);
486
487
0
  ctx->lo <<= 3;
488
0
  ctx->buffer[56] = curlx_ultouc((ctx->lo) & 0xff);
489
0
  ctx->buffer[57] = curlx_ultouc((ctx->lo >> 8) & 0xff);
490
0
  ctx->buffer[58] = curlx_ultouc((ctx->lo >> 16) & 0xff);
491
0
  ctx->buffer[59] = curlx_ultouc(ctx->lo >> 24);
492
0
  ctx->buffer[60] = curlx_ultouc((ctx->hi) & 0xff);
493
0
  ctx->buffer[61] = curlx_ultouc((ctx->hi >> 8) & 0xff);
494
0
  ctx->buffer[62] = curlx_ultouc((ctx->hi >> 16) & 0xff);
495
0
  ctx->buffer[63] = curlx_ultouc(ctx->hi >> 24);
496
497
0
  my_md5_body(ctx, ctx->buffer, 64);
498
499
0
  digest[0] = curlx_ultouc((ctx->a) & 0xff);
500
0
  digest[1] = curlx_ultouc((ctx->a >> 8) & 0xff);
501
0
  digest[2] = curlx_ultouc((ctx->a >> 16) & 0xff);
502
0
  digest[3] = curlx_ultouc(ctx->a >> 24);
503
0
  digest[4] = curlx_ultouc((ctx->b) & 0xff);
504
0
  digest[5] = curlx_ultouc((ctx->b >> 8) & 0xff);
505
0
  digest[6] = curlx_ultouc((ctx->b >> 16) & 0xff);
506
0
  digest[7] = curlx_ultouc(ctx->b >> 24);
507
0
  digest[8] = curlx_ultouc((ctx->c) & 0xff);
508
0
  digest[9] = curlx_ultouc((ctx->c >> 8) & 0xff);
509
0
  digest[10] = curlx_ultouc((ctx->c >> 16) & 0xff);
510
0
  digest[11] = curlx_ultouc(ctx->c >> 24);
511
0
  digest[12] = curlx_ultouc((ctx->d) & 0xff);
512
0
  digest[13] = curlx_ultouc((ctx->d >> 8) & 0xff);
513
0
  digest[14] = curlx_ultouc((ctx->d >> 16) & 0xff);
514
0
  digest[15] = curlx_ultouc(ctx->d >> 24);
515
516
0
  memset(ctx, 0, sizeof(*ctx));
517
0
}
518
519
#endif /* CRYPTO LIBS */
520
521
const struct HMAC_params Curl_HMAC_MD5 = {
522
  my_md5_init,        /* Hash initialization function. */
523
  my_md5_update,      /* Hash update function. */
524
  my_md5_final,       /* Hash computation end function. */
525
  sizeof(my_md5_ctx), /* Size of hash context structure. */
526
  64,                 /* Maximum key length. */
527
  16                  /* Result size. */
528
};
529
530
const struct MD5_params Curl_DIGEST_MD5 = {
531
  my_md5_init,        /* Digest initialization function */
532
  my_md5_update,      /* Digest update function */
533
  my_md5_final,       /* Digest computation end function */
534
  sizeof(my_md5_ctx), /* Size of digest context struct */
535
  16                  /* Result size */
536
};
537
538
/*
539
 * @unittest: 1601
540
 * Returns CURLE_OK on success.
541
 */
542
CURLcode Curl_md5it(unsigned char *output,
543
                    const unsigned char *input, size_t len)
544
0
{
545
0
  CURLcode result;
546
0
  my_md5_ctx ctx;
547
548
0
  result = my_md5_init(&ctx);
549
0
  if(!result) {
550
0
    do {
551
0
      unsigned int ilen = (unsigned int)CURLMIN(len, UINT_MAX);
552
0
      my_md5_update(&ctx, input, ilen);
553
0
      input += ilen;
554
0
      len -= ilen;
555
0
    } while(len);
556
0
    my_md5_final(output, &ctx);
557
0
  }
558
0
  return result;
559
0
}
560
561
struct MD5_context *Curl_MD5_init(const struct MD5_params *md5params)
562
0
{
563
0
  struct MD5_context *ctxt;
564
565
  /* Create MD5 context */
566
0
  ctxt = curlx_malloc(sizeof(*ctxt));
567
568
0
  if(!ctxt)
569
0
    return ctxt;
570
571
0
  ctxt->md5_hashctx = curlx_malloc(md5params->md5_ctxtsize);
572
573
0
  if(!ctxt->md5_hashctx) {
574
0
    curlx_free(ctxt);
575
0
    return NULL;
576
0
  }
577
578
0
  ctxt->md5_hash = md5params;
579
580
0
  if((*md5params->md5_init_func)(ctxt->md5_hashctx)) {
581
0
    curlx_free(ctxt->md5_hashctx);
582
0
    curlx_free(ctxt);
583
0
    return NULL;
584
0
  }
585
586
0
  return ctxt;
587
0
}
588
589
CURLcode Curl_MD5_update(struct MD5_context *context,
590
                         const unsigned char *input, unsigned int len)
591
0
{
592
0
  (*context->md5_hash->md5_update_func)(context->md5_hashctx, input, len);
593
594
0
  return CURLE_OK;
595
0
}
596
597
CURLcode Curl_MD5_final(struct MD5_context *context, unsigned char *result)
598
0
{
599
0
  (*context->md5_hash->md5_final_func)(result, context->md5_hashctx);
600
601
0
  curlx_free(context->md5_hashctx);
602
0
  curlx_free(context);
603
604
0
  return CURLE_OK;
605
0
}
606
607
#endif /* Using NTLM (without SSPI) || Digest */