Coverage Report

Created: 2026-07-16 06:10

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