Coverage Report

Created: 2026-09-14 07:04

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