Coverage Report

Created: 2026-10-15 06:17

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
  (void)CC_MD5_Init(ctx);  /* always returns 1 */
181
  return CURLE_OK;
182
}
183
184
static void my_md5_update(void *ctx,
185
                          const unsigned char *input, unsigned int len)
186
{
187
  CC_MD5_Update(ctx, input, len);
188
}
189
190
static void my_md5_final(unsigned char *digest, void *ctx)
191
{
192
  CC_MD5_Final(digest, ctx);
193
}
194
195
#elif defined(USE_WIN32_CRYPTO)
196
#include <wincrypt.h>
197
198
struct md5_ctx {
199
  HCRYPTPROV hCryptProv;
200
  HCRYPTHASH hHash;
201
};
202
typedef struct md5_ctx my_md5_ctx;
203
204
static CURLcode my_md5_init(void *in)
205
{
206
  my_md5_ctx *ctx = (my_md5_ctx *)in;
207
  if(!CryptAcquireContext(&ctx->hCryptProv, NULL, NULL, PROV_RSA_FULL,
208
                          CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
209
    return CURLE_OUT_OF_MEMORY;
210
211
  if(!CryptCreateHash(ctx->hCryptProv, CALG_MD5, 0, 0, &ctx->hHash)) {
212
    CryptReleaseContext(ctx->hCryptProv, 0);
213
    ctx->hCryptProv = 0;
214
    return CURLE_FAILED_INIT;
215
  }
216
217
  return CURLE_OK;
218
}
219
220
static void my_md5_update(void *in,
221
                          const unsigned char *input, unsigned int len)
222
{
223
  my_md5_ctx *ctx = in;
224
  CryptHashData(ctx->hHash, (const BYTE *)input, len, 0);
225
}
226
227
static void my_md5_final(unsigned char *digest, void *in)
228
{
229
  my_md5_ctx *ctx = (my_md5_ctx *)in;
230
  unsigned long length = 0;
231
  CryptGetHashParam(ctx->hHash, HP_HASHVAL, NULL, &length, 0);
232
  if(length == MD5_DIGEST_LEN)
233
    CryptGetHashParam(ctx->hHash, HP_HASHVAL, digest, &length, 0);
234
  if(ctx->hHash)
235
    CryptDestroyHash(ctx->hHash);
236
  if(ctx->hCryptProv)
237
    CryptReleaseContext(ctx->hCryptProv, 0);
238
}
239
240
#else
241
242
/* When no other crypto library is available we use this code segment */
243
244
/*
245
 * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
246
 * MD5 Message-Digest Algorithm (RFC 1321).
247
 *
248
 * Homepage:
249
 * https://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
250
 *
251
 * Author:
252
 * Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
253
 *
254
 * This software was written by Alexander Peslyak in 2001. No copyright is
255
 * claimed, and the software is hereby placed in the public domain. In case
256
 * this attempt to disclaim copyright and place the software in the public
257
 * domain is deemed null and void, then the software is Copyright (c) 2001
258
 * Alexander Peslyak and it is hereby released to the general public under
259
 * the following terms:
260
 *
261
 * Redistribution and use in source and binary forms, with or without
262
 * modification, are permitted.
263
 *
264
 * There is ABSOLUTELY NO WARRANTY, express or implied.
265
 *
266
 * (This is a heavily cut-down "BSD license".)
267
 */
268
269
struct md5_ctx {
270
  uint32_t lo, hi;
271
  uint32_t a, b, c, d;
272
  unsigned char buffer[64];
273
  uint32_t block[16];
274
};
275
typedef struct md5_ctx my_md5_ctx;
276
277
/*
278
 * The basic MD5 functions.
279
 *
280
 * F and G are optimized compared to their RFC 1321 definitions for
281
 * architectures that lack an AND-NOT instruction, like in Colin Plumb's
282
 * implementation.
283
 */
284
#define MD5_F(x, y, z)                  ((z) ^ ((x) & ((y) ^ (z))))
285
#define MD5_G(x, y, z)                  ((y) ^ ((z) & ((x) ^ (y))))
286
#define MD5_H(x, y, z)                  (((x) ^ (y)) ^ (z))
287
#define MD5_H2(x, y, z)                 ((x) ^ ((y) ^ (z)))
288
#define MD5_I(x, y, z)                  ((y) ^ ((x) | ~(z)))
289
290
/*
291
 * The MD5 transformation for all four rounds.
292
 */
293
#define MD5_STEP(f, a, b, c, d, x, t, s) \
294
  (a) += f(b, c, d) + (x) + (t); \
295
  (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
296
  (a) += (b);
297
298
/*
299
 * SET reads 4 input bytes in little-endian byte order and stores them
300
 * in a properly aligned word in host byte order.
301
 *
302
 * The check for little-endian architectures that tolerate unaligned memory
303
 * accesses is an optimization. Nothing will break if it does not work.
304
 */
305
#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
306
#define MD5_SET(n) (*(const uint32_t *)(const void *)&ptr[(n) * 4])
307
#define MD5_GET(n) MD5_SET(n)
308
#else
309
#define MD5_SET(n) (ctx->block[n] =      \
310
   (uint32_t)ptr[(n) * 4]              | \
311
  ((uint32_t)ptr[((n) * 4) + 1] <<  8) | \
312
  ((uint32_t)ptr[((n) * 4) + 2] << 16) | \
313
  ((uint32_t)ptr[((n) * 4) + 3] << 24))
314
#define MD5_GET(n) ctx->block[n]
315
#endif
316
317
/*
318
 * This processes one or more 64-byte data blocks, but does NOT update
319
 * the bit counters. There are no alignment requirements.
320
 */
321
static const void *my_md5_body(my_md5_ctx *ctx,
322
                               const void *data, unsigned long size)
323
{
324
  const unsigned char *ptr;
325
  uint32_t a, b, c, d;
326
327
  ptr = (const unsigned char *)data;
328
329
  a = ctx->a;
330
  b = ctx->b;
331
  c = ctx->c;
332
  d = ctx->d;
333
334
  do {
335
    uint32_t saved_a, saved_b, saved_c, saved_d;
336
337
    saved_a = a;
338
    saved_b = b;
339
    saved_c = c;
340
    saved_d = d;
341
342
    /* Round 1 */
343
    MD5_STEP(MD5_F, a, b, c, d, MD5_SET(0), 0xd76aa478, 7)
344
    MD5_STEP(MD5_F, d, a, b, c, MD5_SET(1), 0xe8c7b756, 12)
345
    MD5_STEP(MD5_F, c, d, a, b, MD5_SET(2), 0x242070db, 17)
346
    MD5_STEP(MD5_F, b, c, d, a, MD5_SET(3), 0xc1bdceee, 22)
347
    MD5_STEP(MD5_F, a, b, c, d, MD5_SET(4), 0xf57c0faf, 7)
348
    MD5_STEP(MD5_F, d, a, b, c, MD5_SET(5), 0x4787c62a, 12)
349
    MD5_STEP(MD5_F, c, d, a, b, MD5_SET(6), 0xa8304613, 17)
350
    MD5_STEP(MD5_F, b, c, d, a, MD5_SET(7), 0xfd469501, 22)
351
    MD5_STEP(MD5_F, a, b, c, d, MD5_SET(8), 0x698098d8, 7)
352
    MD5_STEP(MD5_F, d, a, b, c, MD5_SET(9), 0x8b44f7af, 12)
353
    MD5_STEP(MD5_F, c, d, a, b, MD5_SET(10), 0xffff5bb1, 17)
354
    MD5_STEP(MD5_F, b, c, d, a, MD5_SET(11), 0x895cd7be, 22)
355
    MD5_STEP(MD5_F, a, b, c, d, MD5_SET(12), 0x6b901122, 7)
356
    MD5_STEP(MD5_F, d, a, b, c, MD5_SET(13), 0xfd987193, 12)
357
    MD5_STEP(MD5_F, c, d, a, b, MD5_SET(14), 0xa679438e, 17)
358
    MD5_STEP(MD5_F, b, c, d, a, MD5_SET(15), 0x49b40821, 22)
359
360
    /* Round 2 */
361
    MD5_STEP(MD5_G, a, b, c, d, MD5_GET(1), 0xf61e2562, 5)
362
    MD5_STEP(MD5_G, d, a, b, c, MD5_GET(6), 0xc040b340, 9)
363
    MD5_STEP(MD5_G, c, d, a, b, MD5_GET(11), 0x265e5a51, 14)
364
    MD5_STEP(MD5_G, b, c, d, a, MD5_GET(0), 0xe9b6c7aa, 20)
365
    MD5_STEP(MD5_G, a, b, c, d, MD5_GET(5), 0xd62f105d, 5)
366
    MD5_STEP(MD5_G, d, a, b, c, MD5_GET(10), 0x02441453, 9)
367
    MD5_STEP(MD5_G, c, d, a, b, MD5_GET(15), 0xd8a1e681, 14)
368
    MD5_STEP(MD5_G, b, c, d, a, MD5_GET(4), 0xe7d3fbc8, 20)
369
    MD5_STEP(MD5_G, a, b, c, d, MD5_GET(9), 0x21e1cde6, 5)
370
    MD5_STEP(MD5_G, d, a, b, c, MD5_GET(14), 0xc33707d6, 9)
371
    MD5_STEP(MD5_G, c, d, a, b, MD5_GET(3), 0xf4d50d87, 14)
372
    MD5_STEP(MD5_G, b, c, d, a, MD5_GET(8), 0x455a14ed, 20)
373
    MD5_STEP(MD5_G, a, b, c, d, MD5_GET(13), 0xa9e3e905, 5)
374
    MD5_STEP(MD5_G, d, a, b, c, MD5_GET(2), 0xfcefa3f8, 9)
375
    MD5_STEP(MD5_G, c, d, a, b, MD5_GET(7), 0x676f02d9, 14)
376
    MD5_STEP(MD5_G, b, c, d, a, MD5_GET(12), 0x8d2a4c8a, 20)
377
378
    /* Round 3 */
379
    MD5_STEP(MD5_H, a, b, c, d, MD5_GET(5), 0xfffa3942, 4)
380
    MD5_STEP(MD5_H2, d, a, b, c, MD5_GET(8), 0x8771f681, 11)
381
    MD5_STEP(MD5_H, c, d, a, b, MD5_GET(11), 0x6d9d6122, 16)
382
    MD5_STEP(MD5_H2, b, c, d, a, MD5_GET(14), 0xfde5380c, 23)
383
    MD5_STEP(MD5_H, a, b, c, d, MD5_GET(1), 0xa4beea44, 4)
384
    MD5_STEP(MD5_H2, d, a, b, c, MD5_GET(4), 0x4bdecfa9, 11)
385
    MD5_STEP(MD5_H, c, d, a, b, MD5_GET(7), 0xf6bb4b60, 16)
386
    MD5_STEP(MD5_H2, b, c, d, a, MD5_GET(10), 0xbebfbc70, 23)
387
    MD5_STEP(MD5_H, a, b, c, d, MD5_GET(13), 0x289b7ec6, 4)
388
    MD5_STEP(MD5_H2, d, a, b, c, MD5_GET(0), 0xeaa127fa, 11)
389
    MD5_STEP(MD5_H, c, d, a, b, MD5_GET(3), 0xd4ef3085, 16)
390
    MD5_STEP(MD5_H2, b, c, d, a, MD5_GET(6), 0x04881d05, 23)
391
    MD5_STEP(MD5_H, a, b, c, d, MD5_GET(9), 0xd9d4d039, 4)
392
    MD5_STEP(MD5_H2, d, a, b, c, MD5_GET(12), 0xe6db99e5, 11)
393
    MD5_STEP(MD5_H, c, d, a, b, MD5_GET(15), 0x1fa27cf8, 16)
394
    MD5_STEP(MD5_H2, b, c, d, a, MD5_GET(2), 0xc4ac5665, 23)
395
396
    /* Round 4 */
397
    MD5_STEP(MD5_I, a, b, c, d, MD5_GET(0), 0xf4292244, 6)
398
    MD5_STEP(MD5_I, d, a, b, c, MD5_GET(7), 0x432aff97, 10)
399
    MD5_STEP(MD5_I, c, d, a, b, MD5_GET(14), 0xab9423a7, 15)
400
    MD5_STEP(MD5_I, b, c, d, a, MD5_GET(5), 0xfc93a039, 21)
401
    MD5_STEP(MD5_I, a, b, c, d, MD5_GET(12), 0x655b59c3, 6)
402
    MD5_STEP(MD5_I, d, a, b, c, MD5_GET(3), 0x8f0ccc92, 10)
403
    MD5_STEP(MD5_I, c, d, a, b, MD5_GET(10), 0xffeff47d, 15)
404
    MD5_STEP(MD5_I, b, c, d, a, MD5_GET(1), 0x85845dd1, 21)
405
    MD5_STEP(MD5_I, a, b, c, d, MD5_GET(8), 0x6fa87e4f, 6)
406
    MD5_STEP(MD5_I, d, a, b, c, MD5_GET(15), 0xfe2ce6e0, 10)
407
    MD5_STEP(MD5_I, c, d, a, b, MD5_GET(6), 0xa3014314, 15)
408
    MD5_STEP(MD5_I, b, c, d, a, MD5_GET(13), 0x4e0811a1, 21)
409
    MD5_STEP(MD5_I, a, b, c, d, MD5_GET(4), 0xf7537e82, 6)
410
    MD5_STEP(MD5_I, d, a, b, c, MD5_GET(11), 0xbd3af235, 10)
411
    MD5_STEP(MD5_I, c, d, a, b, MD5_GET(2), 0x2ad7d2bb, 15)
412
    MD5_STEP(MD5_I, b, c, d, a, MD5_GET(9), 0xeb86d391, 21)
413
414
    a += saved_a;
415
    b += saved_b;
416
    c += saved_c;
417
    d += saved_d;
418
419
    ptr += 64;
420
  } while(size -= 64);
421
422
  ctx->a = a;
423
  ctx->b = b;
424
  ctx->c = c;
425
  ctx->d = d;
426
427
  return ptr;
428
}
429
430
static CURLcode my_md5_init(void *in)
431
{
432
  my_md5_ctx *ctx = (my_md5_ctx *)in;
433
  ctx->a = 0x67452301;
434
  ctx->b = 0xefcdab89;
435
  ctx->c = 0x98badcfe;
436
  ctx->d = 0x10325476;
437
438
  ctx->lo = 0;
439
  ctx->hi = 0;
440
441
  return CURLE_OK;
442
}
443
444
static void my_md5_update(void *in,
445
                          const unsigned char *input, unsigned int len)
446
{
447
  uint32_t saved_lo;
448
  unsigned int used;
449
  my_md5_ctx *ctx = (my_md5_ctx *)in;
450
451
  saved_lo = ctx->lo;
452
  ctx->lo = (saved_lo + len) & 0x1fffffff;
453
  if(ctx->lo < saved_lo)
454
    ctx->hi++;
455
  ctx->hi += (uint32_t)len >> 29;
456
457
  used = saved_lo & 0x3f;
458
459
  if(used) {
460
    unsigned int available = 64 - used;
461
462
    if(len < available) {
463
      memcpy(&ctx->buffer[used], input, len);
464
      return;
465
    }
466
467
    memcpy(&ctx->buffer[used], input, available);
468
    input = (const unsigned char *)input + available;
469
    len -= available;
470
    my_md5_body(ctx, ctx->buffer, 64);
471
  }
472
473
  if(len >= 64) {
474
    input = my_md5_body(ctx, input, len & ~(unsigned long)0x3f);
475
    len &= 0x3f;
476
  }
477
478
  memcpy(ctx->buffer, input, len);
479
}
480
481
static void my_md5_final(unsigned char *digest, void *in)
482
{
483
  unsigned int used, available;
484
  my_md5_ctx *ctx = (my_md5_ctx *)in;
485
486
  used = ctx->lo & 0x3f;
487
488
  ctx->buffer[used++] = 0x80;
489
490
  available = 64 - used;
491
492
  if(available < 8) {
493
    memset(&ctx->buffer[used], 0, available);
494
    my_md5_body(ctx, ctx->buffer, 64);
495
    used = 0;
496
    available = 64;
497
  }
498
499
  memset(&ctx->buffer[used], 0, available - 8);
500
501
  ctx->lo <<= 3;
502
  ctx->buffer[56] = curlx_ultouc((ctx->lo) & 0xff);
503
  ctx->buffer[57] = curlx_ultouc((ctx->lo >> 8) & 0xff);
504
  ctx->buffer[58] = curlx_ultouc((ctx->lo >> 16) & 0xff);
505
  ctx->buffer[59] = curlx_ultouc(ctx->lo >> 24);
506
  ctx->buffer[60] = curlx_ultouc((ctx->hi) & 0xff);
507
  ctx->buffer[61] = curlx_ultouc((ctx->hi >> 8) & 0xff);
508
  ctx->buffer[62] = curlx_ultouc((ctx->hi >> 16) & 0xff);
509
  ctx->buffer[63] = curlx_ultouc(ctx->hi >> 24);
510
511
  my_md5_body(ctx, ctx->buffer, 64);
512
513
  digest[0] = curlx_ultouc((ctx->a) & 0xff);
514
  digest[1] = curlx_ultouc((ctx->a >> 8) & 0xff);
515
  digest[2] = curlx_ultouc((ctx->a >> 16) & 0xff);
516
  digest[3] = curlx_ultouc(ctx->a >> 24);
517
  digest[4] = curlx_ultouc((ctx->b) & 0xff);
518
  digest[5] = curlx_ultouc((ctx->b >> 8) & 0xff);
519
  digest[6] = curlx_ultouc((ctx->b >> 16) & 0xff);
520
  digest[7] = curlx_ultouc(ctx->b >> 24);
521
  digest[8] = curlx_ultouc((ctx->c) & 0xff);
522
  digest[9] = curlx_ultouc((ctx->c >> 8) & 0xff);
523
  digest[10] = curlx_ultouc((ctx->c >> 16) & 0xff);
524
  digest[11] = curlx_ultouc(ctx->c >> 24);
525
  digest[12] = curlx_ultouc((ctx->d) & 0xff);
526
  digest[13] = curlx_ultouc((ctx->d >> 8) & 0xff);
527
  digest[14] = curlx_ultouc((ctx->d >> 16) & 0xff);
528
  digest[15] = curlx_ultouc(ctx->d >> 24);
529
530
  memset(ctx, 0, sizeof(*ctx));
531
}
532
533
#endif /* CRYPTO LIBS */
534
535
const struct HMAC_params Curl_HMAC_MD5 = {
536
  my_md5_init,        /* Hash initialization function. */
537
  my_md5_update,      /* Hash update function. */
538
  my_md5_final,       /* Hash computation end function. */
539
  sizeof(my_md5_ctx), /* Size of hash context structure. */
540
  64,                 /* Maximum key length. */
541
  MD5_DIGEST_LEN      /* Result size. */
542
};
543
544
const struct MD5_params Curl_DIGEST_MD5 = {
545
  my_md5_init,        /* Digest initialization function */
546
  my_md5_update,      /* Digest update function */
547
  my_md5_final,       /* Digest computation end function */
548
  sizeof(my_md5_ctx), /* Size of digest context struct */
549
  MD5_DIGEST_LEN      /* Result size */
550
};
551
552
/*
553
 * @unittest: 1601
554
 * Returns CURLE_OK on success.
555
 */
556
CURLcode Curl_md5it(unsigned char *output,
557
                    const unsigned char *input, size_t len)
558
0
{
559
0
  CURLcode result;
560
0
  my_md5_ctx ctx;
561
562
0
  result = my_md5_init(&ctx);
563
0
  if(!result) {
564
0
    do {
565
0
      unsigned int ilen = (unsigned int)CURLMIN(len, UINT_MAX);
566
0
      my_md5_update(&ctx, input, ilen);
567
0
      input += ilen;
568
0
      len -= ilen;
569
0
    } while(len);
570
0
    my_md5_final(output, &ctx);
571
0
  }
572
0
  return result;
573
0
}
574
575
struct MD5_context *Curl_MD5_init(const struct MD5_params *md5params)
576
0
{
577
0
  struct MD5_context *ctxt;
578
579
  /* Create MD5 context */
580
0
  ctxt = curlx_malloc(sizeof(*ctxt));
581
582
0
  if(!ctxt)
583
0
    return ctxt;
584
585
0
  ctxt->md5_hashctx = curlx_malloc(md5params->md5_ctxtsize);
586
587
0
  if(!ctxt->md5_hashctx) {
588
0
    curlx_free(ctxt);
589
0
    return NULL;
590
0
  }
591
592
0
  ctxt->md5_hash = md5params;
593
594
0
  if((*md5params->md5_init_func)(ctxt->md5_hashctx)) {
595
0
    curlx_free(ctxt->md5_hashctx);
596
0
    curlx_free(ctxt);
597
0
    return NULL;
598
0
  }
599
600
0
  return ctxt;
601
0
}
602
603
CURLcode Curl_MD5_update(struct MD5_context *context,
604
                         const unsigned char *input, unsigned int len)
605
0
{
606
0
  (*context->md5_hash->md5_update_func)(context->md5_hashctx, input, len);
607
608
0
  return CURLE_OK;
609
0
}
610
611
CURLcode Curl_MD5_final(struct MD5_context *context, unsigned char *result)
612
0
{
613
0
  (*context->md5_hash->md5_final_func)(result, context->md5_hashctx);
614
615
0
  curlx_free(context->md5_hashctx);
616
0
  curlx_free(context);
617
618
0
  return CURLE_OK;
619
0
}
620
621
#endif /* Using NTLM (without SSPI) || Digest */