Coverage Report

Created: 2026-07-14 07:09

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