Coverage Report

Created: 2026-02-26 06:40

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
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
  (defined(USE_WOLFSSL) && !defined(NO_MD5) && !defined(OPENSSL_COEXIST))
73
#ifdef USE_OPENSSL
74
#include <openssl/md5.h>
75
#else
76
#include <wolfssl/openssl/md5.h>
77
#endif
78
79
typedef MD5_CTX my_md5_ctx;
80
81
static CURLcode my_md5_init(void *ctx)
82
2.86k
{
83
2.86k
  if(!MD5_Init(ctx))
84
0
    return CURLE_OUT_OF_MEMORY;
85
86
2.86k
  return CURLE_OK;
87
2.86k
}
88
89
static void my_md5_update(void *ctx,
90
                          const unsigned char *input, unsigned int len)
91
21.1k
{
92
21.1k
  (void)MD5_Update(ctx, input, len);
93
21.1k
}
94
95
static void my_md5_final(unsigned char *digest, void *ctx)
96
2.86k
{
97
2.86k
  (void)MD5_Final(digest, ctx);
98
2.86k
}
99
100
#elif defined(USE_WOLFSSL) && !defined(NO_MD5)
101
#include <wolfssl/openssl/md5.h>
102
103
typedef WOLFSSL_MD5_CTX my_md5_ctx;
104
105
static CURLcode my_md5_init(void *ctx)
106
{
107
  if(!wolfSSL_MD5_Init(ctx))
108
    return CURLE_OUT_OF_MEMORY;
109
110
  return CURLE_OK;
111
}
112
113
static void my_md5_update(void *ctx,
114
                          const unsigned char *input, unsigned int len)
115
{
116
  (void)wolfSSL_MD5_Update(ctx, input, len);
117
}
118
119
static void my_md5_final(unsigned char *digest, void *ctx)
120
{
121
  (void)wolfSSL_MD5_Final(digest, ctx);
122
}
123
124
#elif defined(USE_MBEDTLS) && \
125
  defined(PSA_WANT_ALG_MD5) && PSA_WANT_ALG_MD5  /* mbedTLS 4+ */
126
#include <psa/crypto.h>
127
128
typedef psa_hash_operation_t my_md5_ctx;
129
130
static CURLcode my_md5_init(void *ctx)
131
{
132
  memset(ctx, 0, sizeof(my_md5_ctx));
133
  if(psa_hash_setup(ctx, 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, just 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
295
 * memory accesses is just an optimization. Nothing will break if it
296
 * does not work.
297
 */
298
#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
299
#define MD5_SET(n) (*(const uint32_t *)(const void *)&ptr[(n) * 4])
300
#define MD5_GET(n) MD5_SET(n)
301
#else
302
#define MD5_SET(n) (ctx->block[n] =      \
303
   (uint32_t)ptr[(n) * 4]              | \
304
  ((uint32_t)ptr[((n) * 4) + 1] <<  8) | \
305
  ((uint32_t)ptr[((n) * 4) + 2] << 16) | \
306
  ((uint32_t)ptr[((n) * 4) + 3] << 24))
307
#define MD5_GET(n) ctx->block[n]
308
#endif
309
310
/*
311
 * This processes one or more 64-byte data blocks, but does NOT update
312
 * the bit counters. There are no alignment requirements.
313
 */
314
static const void *my_md5_body(my_md5_ctx *ctx,
315
                               const void *data, unsigned long size)
316
{
317
  const unsigned char *ptr;
318
  uint32_t a, b, c, d;
319
320
  ptr = (const unsigned char *)data;
321
322
  a = ctx->a;
323
  b = ctx->b;
324
  c = ctx->c;
325
  d = ctx->d;
326
327
  do {
328
    uint32_t saved_a, saved_b, saved_c, saved_d;
329
330
    saved_a = a;
331
    saved_b = b;
332
    saved_c = c;
333
    saved_d = d;
334
335
    /* Round 1 */
336
    MD5_STEP(MD5_F, a, b, c, d, MD5_SET(0), 0xd76aa478, 7)
337
    MD5_STEP(MD5_F, d, a, b, c, MD5_SET(1), 0xe8c7b756, 12)
338
    MD5_STEP(MD5_F, c, d, a, b, MD5_SET(2), 0x242070db, 17)
339
    MD5_STEP(MD5_F, b, c, d, a, MD5_SET(3), 0xc1bdceee, 22)
340
    MD5_STEP(MD5_F, a, b, c, d, MD5_SET(4), 0xf57c0faf, 7)
341
    MD5_STEP(MD5_F, d, a, b, c, MD5_SET(5), 0x4787c62a, 12)
342
    MD5_STEP(MD5_F, c, d, a, b, MD5_SET(6), 0xa8304613, 17)
343
    MD5_STEP(MD5_F, b, c, d, a, MD5_SET(7), 0xfd469501, 22)
344
    MD5_STEP(MD5_F, a, b, c, d, MD5_SET(8), 0x698098d8, 7)
345
    MD5_STEP(MD5_F, d, a, b, c, MD5_SET(9), 0x8b44f7af, 12)
346
    MD5_STEP(MD5_F, c, d, a, b, MD5_SET(10), 0xffff5bb1, 17)
347
    MD5_STEP(MD5_F, b, c, d, a, MD5_SET(11), 0x895cd7be, 22)
348
    MD5_STEP(MD5_F, a, b, c, d, MD5_SET(12), 0x6b901122, 7)
349
    MD5_STEP(MD5_F, d, a, b, c, MD5_SET(13), 0xfd987193, 12)
350
    MD5_STEP(MD5_F, c, d, a, b, MD5_SET(14), 0xa679438e, 17)
351
    MD5_STEP(MD5_F, b, c, d, a, MD5_SET(15), 0x49b40821, 22)
352
353
    /* Round 2 */
354
    MD5_STEP(MD5_G, a, b, c, d, MD5_GET(1), 0xf61e2562, 5)
355
    MD5_STEP(MD5_G, d, a, b, c, MD5_GET(6), 0xc040b340, 9)
356
    MD5_STEP(MD5_G, c, d, a, b, MD5_GET(11), 0x265e5a51, 14)
357
    MD5_STEP(MD5_G, b, c, d, a, MD5_GET(0), 0xe9b6c7aa, 20)
358
    MD5_STEP(MD5_G, a, b, c, d, MD5_GET(5), 0xd62f105d, 5)
359
    MD5_STEP(MD5_G, d, a, b, c, MD5_GET(10), 0x02441453, 9)
360
    MD5_STEP(MD5_G, c, d, a, b, MD5_GET(15), 0xd8a1e681, 14)
361
    MD5_STEP(MD5_G, b, c, d, a, MD5_GET(4), 0xe7d3fbc8, 20)
362
    MD5_STEP(MD5_G, a, b, c, d, MD5_GET(9), 0x21e1cde6, 5)
363
    MD5_STEP(MD5_G, d, a, b, c, MD5_GET(14), 0xc33707d6, 9)
364
    MD5_STEP(MD5_G, c, d, a, b, MD5_GET(3), 0xf4d50d87, 14)
365
    MD5_STEP(MD5_G, b, c, d, a, MD5_GET(8), 0x455a14ed, 20)
366
    MD5_STEP(MD5_G, a, b, c, d, MD5_GET(13), 0xa9e3e905, 5)
367
    MD5_STEP(MD5_G, d, a, b, c, MD5_GET(2), 0xfcefa3f8, 9)
368
    MD5_STEP(MD5_G, c, d, a, b, MD5_GET(7), 0x676f02d9, 14)
369
    MD5_STEP(MD5_G, b, c, d, a, MD5_GET(12), 0x8d2a4c8a, 20)
370
371
    /* Round 3 */
372
    MD5_STEP(MD5_H, a, b, c, d, MD5_GET(5), 0xfffa3942, 4)
373
    MD5_STEP(MD5_H2, d, a, b, c, MD5_GET(8), 0x8771f681, 11)
374
    MD5_STEP(MD5_H, c, d, a, b, MD5_GET(11), 0x6d9d6122, 16)
375
    MD5_STEP(MD5_H2, b, c, d, a, MD5_GET(14), 0xfde5380c, 23)
376
    MD5_STEP(MD5_H, a, b, c, d, MD5_GET(1), 0xa4beea44, 4)
377
    MD5_STEP(MD5_H2, d, a, b, c, MD5_GET(4), 0x4bdecfa9, 11)
378
    MD5_STEP(MD5_H, c, d, a, b, MD5_GET(7), 0xf6bb4b60, 16)
379
    MD5_STEP(MD5_H2, b, c, d, a, MD5_GET(10), 0xbebfbc70, 23)
380
    MD5_STEP(MD5_H, a, b, c, d, MD5_GET(13), 0x289b7ec6, 4)
381
    MD5_STEP(MD5_H2, d, a, b, c, MD5_GET(0), 0xeaa127fa, 11)
382
    MD5_STEP(MD5_H, c, d, a, b, MD5_GET(3), 0xd4ef3085, 16)
383
    MD5_STEP(MD5_H2, b, c, d, a, MD5_GET(6), 0x04881d05, 23)
384
    MD5_STEP(MD5_H, a, b, c, d, MD5_GET(9), 0xd9d4d039, 4)
385
    MD5_STEP(MD5_H2, d, a, b, c, MD5_GET(12), 0xe6db99e5, 11)
386
    MD5_STEP(MD5_H, c, d, a, b, MD5_GET(15), 0x1fa27cf8, 16)
387
    MD5_STEP(MD5_H2, b, c, d, a, MD5_GET(2), 0xc4ac5665, 23)
388
389
    /* Round 4 */
390
    MD5_STEP(MD5_I, a, b, c, d, MD5_GET(0), 0xf4292244, 6)
391
    MD5_STEP(MD5_I, d, a, b, c, MD5_GET(7), 0x432aff97, 10)
392
    MD5_STEP(MD5_I, c, d, a, b, MD5_GET(14), 0xab9423a7, 15)
393
    MD5_STEP(MD5_I, b, c, d, a, MD5_GET(5), 0xfc93a039, 21)
394
    MD5_STEP(MD5_I, a, b, c, d, MD5_GET(12), 0x655b59c3, 6)
395
    MD5_STEP(MD5_I, d, a, b, c, MD5_GET(3), 0x8f0ccc92, 10)
396
    MD5_STEP(MD5_I, c, d, a, b, MD5_GET(10), 0xffeff47d, 15)
397
    MD5_STEP(MD5_I, b, c, d, a, MD5_GET(1), 0x85845dd1, 21)
398
    MD5_STEP(MD5_I, a, b, c, d, MD5_GET(8), 0x6fa87e4f, 6)
399
    MD5_STEP(MD5_I, d, a, b, c, MD5_GET(15), 0xfe2ce6e0, 10)
400
    MD5_STEP(MD5_I, c, d, a, b, MD5_GET(6), 0xa3014314, 15)
401
    MD5_STEP(MD5_I, b, c, d, a, MD5_GET(13), 0x4e0811a1, 21)
402
    MD5_STEP(MD5_I, a, b, c, d, MD5_GET(4), 0xf7537e82, 6)
403
    MD5_STEP(MD5_I, d, a, b, c, MD5_GET(11), 0xbd3af235, 10)
404
    MD5_STEP(MD5_I, c, d, a, b, MD5_GET(2), 0x2ad7d2bb, 15)
405
    MD5_STEP(MD5_I, b, c, d, a, MD5_GET(9), 0xeb86d391, 21)
406
407
    a += saved_a;
408
    b += saved_b;
409
    c += saved_c;
410
    d += saved_d;
411
412
    ptr += 64;
413
  } while(size -= 64);
414
415
  ctx->a = a;
416
  ctx->b = b;
417
  ctx->c = c;
418
  ctx->d = d;
419
420
  return ptr;
421
}
422
423
static CURLcode my_md5_init(void *in)
424
{
425
  my_md5_ctx *ctx = (my_md5_ctx *)in;
426
  ctx->a = 0x67452301;
427
  ctx->b = 0xefcdab89;
428
  ctx->c = 0x98badcfe;
429
  ctx->d = 0x10325476;
430
431
  ctx->lo = 0;
432
  ctx->hi = 0;
433
434
  return CURLE_OK;
435
}
436
437
static void my_md5_update(void *in,
438
                          const unsigned char *input, unsigned int len)
439
{
440
  uint32_t saved_lo;
441
  unsigned int used;
442
  my_md5_ctx *ctx = (my_md5_ctx *)in;
443
444
  saved_lo = ctx->lo;
445
  ctx->lo = (saved_lo + len) & 0x1fffffff;
446
  if(ctx->lo < saved_lo)
447
    ctx->hi++;
448
  ctx->hi += (uint32_t)len >> 29;
449
450
  used = saved_lo & 0x3f;
451
452
  if(used) {
453
    unsigned int available = 64 - used;
454
455
    if(len < available) {
456
      memcpy(&ctx->buffer[used], input, len);
457
      return;
458
    }
459
460
    memcpy(&ctx->buffer[used], input, available);
461
    input = (const unsigned char *)input + available;
462
    len -= available;
463
    my_md5_body(ctx, ctx->buffer, 64);
464
  }
465
466
  if(len >= 64) {
467
    input = my_md5_body(ctx, input, len & ~(unsigned long)0x3f);
468
    len &= 0x3f;
469
  }
470
471
  memcpy(ctx->buffer, input, len);
472
}
473
474
static void my_md5_final(unsigned char *digest, void *in)
475
{
476
  unsigned int used, available;
477
  my_md5_ctx *ctx = (my_md5_ctx *)in;
478
479
  used = ctx->lo & 0x3f;
480
481
  ctx->buffer[used++] = 0x80;
482
483
  available = 64 - used;
484
485
  if(available < 8) {
486
    memset(&ctx->buffer[used], 0, available);
487
    my_md5_body(ctx, ctx->buffer, 64);
488
    used = 0;
489
    available = 64;
490
  }
491
492
  memset(&ctx->buffer[used], 0, available - 8);
493
494
  ctx->lo <<= 3;
495
  ctx->buffer[56] = curlx_ultouc((ctx->lo) & 0xff);
496
  ctx->buffer[57] = curlx_ultouc((ctx->lo >> 8) & 0xff);
497
  ctx->buffer[58] = curlx_ultouc((ctx->lo >> 16) & 0xff);
498
  ctx->buffer[59] = curlx_ultouc(ctx->lo >> 24);
499
  ctx->buffer[60] = curlx_ultouc((ctx->hi) & 0xff);
500
  ctx->buffer[61] = curlx_ultouc((ctx->hi >> 8) & 0xff);
501
  ctx->buffer[62] = curlx_ultouc((ctx->hi >> 16) & 0xff);
502
  ctx->buffer[63] = curlx_ultouc(ctx->hi >> 24);
503
504
  my_md5_body(ctx, ctx->buffer, 64);
505
506
  digest[0] = curlx_ultouc((ctx->a) & 0xff);
507
  digest[1] = curlx_ultouc((ctx->a >> 8) & 0xff);
508
  digest[2] = curlx_ultouc((ctx->a >> 16) & 0xff);
509
  digest[3] = curlx_ultouc(ctx->a >> 24);
510
  digest[4] = curlx_ultouc((ctx->b) & 0xff);
511
  digest[5] = curlx_ultouc((ctx->b >> 8) & 0xff);
512
  digest[6] = curlx_ultouc((ctx->b >> 16) & 0xff);
513
  digest[7] = curlx_ultouc(ctx->b >> 24);
514
  digest[8] = curlx_ultouc((ctx->c) & 0xff);
515
  digest[9] = curlx_ultouc((ctx->c >> 8) & 0xff);
516
  digest[10] = curlx_ultouc((ctx->c >> 16) & 0xff);
517
  digest[11] = curlx_ultouc(ctx->c >> 24);
518
  digest[12] = curlx_ultouc((ctx->d) & 0xff);
519
  digest[13] = curlx_ultouc((ctx->d >> 8) & 0xff);
520
  digest[14] = curlx_ultouc((ctx->d >> 16) & 0xff);
521
  digest[15] = curlx_ultouc(ctx->d >> 24);
522
523
  memset(ctx, 0, sizeof(*ctx));
524
}
525
526
#endif /* CRYPTO LIBS */
527
528
const struct HMAC_params Curl_HMAC_MD5 = {
529
  my_md5_init,        /* Hash initialization function. */
530
  my_md5_update,      /* Hash update function. */
531
  my_md5_final,       /* Hash computation end function. */
532
  sizeof(my_md5_ctx), /* Size of hash context structure. */
533
  64,                 /* Maximum key length. */
534
  16                  /* Result size. */
535
};
536
537
const struct MD5_params Curl_DIGEST_MD5 = {
538
  my_md5_init,        /* Digest initialization function */
539
  my_md5_update,      /* Digest update function */
540
  my_md5_final,       /* Digest computation end function */
541
  sizeof(my_md5_ctx), /* Size of digest context struct */
542
  16                  /* Result size */
543
};
544
545
/*
546
 * @unittest: 1601
547
 * Returns CURLE_OK on success.
548
 */
549
CURLcode Curl_md5it(unsigned char *output,
550
                    const unsigned char *input, const size_t len)
551
2.54k
{
552
2.54k
  CURLcode result;
553
2.54k
  my_md5_ctx ctx;
554
555
2.54k
  result = my_md5_init(&ctx);
556
2.54k
  if(!result) {
557
2.54k
    my_md5_update(&ctx, input, curlx_uztoui(len));
558
2.54k
    my_md5_final(output, &ctx);
559
2.54k
  }
560
2.54k
  return result;
561
2.54k
}
562
563
struct MD5_context *Curl_MD5_init(const struct MD5_params *md5params)
564
12
{
565
12
  struct MD5_context *ctxt;
566
567
  /* Create MD5 context */
568
12
  ctxt = curlx_malloc(sizeof(*ctxt));
569
570
12
  if(!ctxt)
571
0
    return ctxt;
572
573
12
  ctxt->md5_hashctx = curlx_malloc(md5params->md5_ctxtsize);
574
575
12
  if(!ctxt->md5_hashctx) {
576
0
    curlx_free(ctxt);
577
0
    return NULL;
578
0
  }
579
580
12
  ctxt->md5_hash = md5params;
581
582
12
  if((*md5params->md5_init_func)(ctxt->md5_hashctx)) {
583
0
    curlx_free(ctxt->md5_hashctx);
584
0
    curlx_free(ctxt);
585
0
    return NULL;
586
0
  }
587
588
12
  return ctxt;
589
12
}
590
591
CURLcode Curl_MD5_update(struct MD5_context *context,
592
                         const unsigned char *input, unsigned int len)
593
24
{
594
24
  (*context->md5_hash->md5_update_func)(context->md5_hashctx, input, len);
595
596
24
  return CURLE_OK;
597
24
}
598
599
CURLcode Curl_MD5_final(struct MD5_context *context, unsigned char *result)
600
12
{
601
12
  (*context->md5_hash->md5_final_func)(result, context->md5_hashctx);
602
603
12
  curlx_free(context->md5_hashctx);
604
12
  curlx_free(context);
605
606
12
  return CURLE_OK;
607
12
}
608
609
#endif /* Using NTLM (without SSPI) || Digest */