Coverage Report

Created: 2026-10-28 06:38

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 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
{
82
  EVP_MD_CTX **ctx = (EVP_MD_CTX **)in;
83
  *ctx = EVP_MD_CTX_new();
84
  if(!*ctx)
85
    return CURLE_OUT_OF_MEMORY;
86
87
  if(!EVP_DigestInit_ex(*ctx, EVP_md5(), NULL)) {
88
    EVP_MD_CTX_free(*ctx);
89
    *ctx = NULL;
90
    return CURLE_FAILED_INIT;
91
  }
92
  return CURLE_OK;
93
}
94
95
static void my_md5_update(void *in,
96
                          const unsigned char *input, unsigned int len)
97
{
98
  EVP_MD_CTX **ctx = (EVP_MD_CTX **)in;
99
  (void)EVP_DigestUpdate(*ctx, input, len);
100
}
101
102
static void my_md5_final(unsigned char *digest, void *in)
103
{
104
  EVP_MD_CTX **ctx = (EVP_MD_CTX **)in;
105
  (void)EVP_DigestFinal_ex(*ctx, digest, NULL);
106
  EVP_MD_CTX_free(*ctx);
107
  *ctx = NULL;
108
}
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
0
#define MD5_F(x, y, z)                  ((z) ^ ((x) & ((y) ^ (z))))
285
0
#define MD5_G(x, y, z)                  ((y) ^ ((z) & ((x) ^ (y))))
286
0
#define MD5_H(x, y, z)                  (((x) ^ (y)) ^ (z))
287
0
#define MD5_H2(x, y, z)                 ((x) ^ ((y) ^ (z)))
288
0
#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
0
  (a) += f(b, c, d) + (x) + (t); \
295
0
  (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
296
0
  (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
0
{
324
0
  const unsigned char *ptr;
325
0
  uint32_t a, b, c, d;
326
327
0
  ptr = (const unsigned char *)data;
328
329
0
  a = ctx->a;
330
0
  b = ctx->b;
331
0
  c = ctx->c;
332
0
  d = ctx->d;
333
334
0
  do {
335
0
    uint32_t saved_a, saved_b, saved_c, saved_d;
336
337
0
    saved_a = a;
338
0
    saved_b = b;
339
0
    saved_c = c;
340
0
    saved_d = d;
341
342
    /* Round 1 */
343
0
    MD5_STEP(MD5_F, a, b, c, d, MD5_SET(0), 0xd76aa478, 7)
344
0
    MD5_STEP(MD5_F, d, a, b, c, MD5_SET(1), 0xe8c7b756, 12)
345
0
    MD5_STEP(MD5_F, c, d, a, b, MD5_SET(2), 0x242070db, 17)
346
0
    MD5_STEP(MD5_F, b, c, d, a, MD5_SET(3), 0xc1bdceee, 22)
347
0
    MD5_STEP(MD5_F, a, b, c, d, MD5_SET(4), 0xf57c0faf, 7)
348
0
    MD5_STEP(MD5_F, d, a, b, c, MD5_SET(5), 0x4787c62a, 12)
349
0
    MD5_STEP(MD5_F, c, d, a, b, MD5_SET(6), 0xa8304613, 17)
350
0
    MD5_STEP(MD5_F, b, c, d, a, MD5_SET(7), 0xfd469501, 22)
351
0
    MD5_STEP(MD5_F, a, b, c, d, MD5_SET(8), 0x698098d8, 7)
352
0
    MD5_STEP(MD5_F, d, a, b, c, MD5_SET(9), 0x8b44f7af, 12)
353
0
    MD5_STEP(MD5_F, c, d, a, b, MD5_SET(10), 0xffff5bb1, 17)
354
0
    MD5_STEP(MD5_F, b, c, d, a, MD5_SET(11), 0x895cd7be, 22)
355
0
    MD5_STEP(MD5_F, a, b, c, d, MD5_SET(12), 0x6b901122, 7)
356
0
    MD5_STEP(MD5_F, d, a, b, c, MD5_SET(13), 0xfd987193, 12)
357
0
    MD5_STEP(MD5_F, c, d, a, b, MD5_SET(14), 0xa679438e, 17)
358
0
    MD5_STEP(MD5_F, b, c, d, a, MD5_SET(15), 0x49b40821, 22)
359
360
    /* Round 2 */
361
0
    MD5_STEP(MD5_G, a, b, c, d, MD5_GET(1), 0xf61e2562, 5)
362
0
    MD5_STEP(MD5_G, d, a, b, c, MD5_GET(6), 0xc040b340, 9)
363
0
    MD5_STEP(MD5_G, c, d, a, b, MD5_GET(11), 0x265e5a51, 14)
364
0
    MD5_STEP(MD5_G, b, c, d, a, MD5_GET(0), 0xe9b6c7aa, 20)
365
0
    MD5_STEP(MD5_G, a, b, c, d, MD5_GET(5), 0xd62f105d, 5)
366
0
    MD5_STEP(MD5_G, d, a, b, c, MD5_GET(10), 0x02441453, 9)
367
0
    MD5_STEP(MD5_G, c, d, a, b, MD5_GET(15), 0xd8a1e681, 14)
368
0
    MD5_STEP(MD5_G, b, c, d, a, MD5_GET(4), 0xe7d3fbc8, 20)
369
0
    MD5_STEP(MD5_G, a, b, c, d, MD5_GET(9), 0x21e1cde6, 5)
370
0
    MD5_STEP(MD5_G, d, a, b, c, MD5_GET(14), 0xc33707d6, 9)
371
0
    MD5_STEP(MD5_G, c, d, a, b, MD5_GET(3), 0xf4d50d87, 14)
372
0
    MD5_STEP(MD5_G, b, c, d, a, MD5_GET(8), 0x455a14ed, 20)
373
0
    MD5_STEP(MD5_G, a, b, c, d, MD5_GET(13), 0xa9e3e905, 5)
374
0
    MD5_STEP(MD5_G, d, a, b, c, MD5_GET(2), 0xfcefa3f8, 9)
375
0
    MD5_STEP(MD5_G, c, d, a, b, MD5_GET(7), 0x676f02d9, 14)
376
0
    MD5_STEP(MD5_G, b, c, d, a, MD5_GET(12), 0x8d2a4c8a, 20)
377
378
    /* Round 3 */
379
0
    MD5_STEP(MD5_H, a, b, c, d, MD5_GET(5), 0xfffa3942, 4)
380
0
    MD5_STEP(MD5_H2, d, a, b, c, MD5_GET(8), 0x8771f681, 11)
381
0
    MD5_STEP(MD5_H, c, d, a, b, MD5_GET(11), 0x6d9d6122, 16)
382
0
    MD5_STEP(MD5_H2, b, c, d, a, MD5_GET(14), 0xfde5380c, 23)
383
0
    MD5_STEP(MD5_H, a, b, c, d, MD5_GET(1), 0xa4beea44, 4)
384
0
    MD5_STEP(MD5_H2, d, a, b, c, MD5_GET(4), 0x4bdecfa9, 11)
385
0
    MD5_STEP(MD5_H, c, d, a, b, MD5_GET(7), 0xf6bb4b60, 16)
386
0
    MD5_STEP(MD5_H2, b, c, d, a, MD5_GET(10), 0xbebfbc70, 23)
387
0
    MD5_STEP(MD5_H, a, b, c, d, MD5_GET(13), 0x289b7ec6, 4)
388
0
    MD5_STEP(MD5_H2, d, a, b, c, MD5_GET(0), 0xeaa127fa, 11)
389
0
    MD5_STEP(MD5_H, c, d, a, b, MD5_GET(3), 0xd4ef3085, 16)
390
0
    MD5_STEP(MD5_H2, b, c, d, a, MD5_GET(6), 0x04881d05, 23)
391
0
    MD5_STEP(MD5_H, a, b, c, d, MD5_GET(9), 0xd9d4d039, 4)
392
0
    MD5_STEP(MD5_H2, d, a, b, c, MD5_GET(12), 0xe6db99e5, 11)
393
0
    MD5_STEP(MD5_H, c, d, a, b, MD5_GET(15), 0x1fa27cf8, 16)
394
0
    MD5_STEP(MD5_H2, b, c, d, a, MD5_GET(2), 0xc4ac5665, 23)
395
396
    /* Round 4 */
397
0
    MD5_STEP(MD5_I, a, b, c, d, MD5_GET(0), 0xf4292244, 6)
398
0
    MD5_STEP(MD5_I, d, a, b, c, MD5_GET(7), 0x432aff97, 10)
399
0
    MD5_STEP(MD5_I, c, d, a, b, MD5_GET(14), 0xab9423a7, 15)
400
0
    MD5_STEP(MD5_I, b, c, d, a, MD5_GET(5), 0xfc93a039, 21)
401
0
    MD5_STEP(MD5_I, a, b, c, d, MD5_GET(12), 0x655b59c3, 6)
402
0
    MD5_STEP(MD5_I, d, a, b, c, MD5_GET(3), 0x8f0ccc92, 10)
403
0
    MD5_STEP(MD5_I, c, d, a, b, MD5_GET(10), 0xffeff47d, 15)
404
0
    MD5_STEP(MD5_I, b, c, d, a, MD5_GET(1), 0x85845dd1, 21)
405
0
    MD5_STEP(MD5_I, a, b, c, d, MD5_GET(8), 0x6fa87e4f, 6)
406
0
    MD5_STEP(MD5_I, d, a, b, c, MD5_GET(15), 0xfe2ce6e0, 10)
407
0
    MD5_STEP(MD5_I, c, d, a, b, MD5_GET(6), 0xa3014314, 15)
408
0
    MD5_STEP(MD5_I, b, c, d, a, MD5_GET(13), 0x4e0811a1, 21)
409
0
    MD5_STEP(MD5_I, a, b, c, d, MD5_GET(4), 0xf7537e82, 6)
410
0
    MD5_STEP(MD5_I, d, a, b, c, MD5_GET(11), 0xbd3af235, 10)
411
0
    MD5_STEP(MD5_I, c, d, a, b, MD5_GET(2), 0x2ad7d2bb, 15)
412
0
    MD5_STEP(MD5_I, b, c, d, a, MD5_GET(9), 0xeb86d391, 21)
413
414
0
    a += saved_a;
415
0
    b += saved_b;
416
0
    c += saved_c;
417
0
    d += saved_d;
418
419
0
    ptr += 64;
420
0
  } while(size -= 64);
421
422
0
  ctx->a = a;
423
0
  ctx->b = b;
424
0
  ctx->c = c;
425
0
  ctx->d = d;
426
427
0
  return ptr;
428
0
}
429
430
static CURLcode my_md5_init(void *in)
431
0
{
432
0
  my_md5_ctx *ctx = (my_md5_ctx *)in;
433
0
  ctx->a = 0x67452301;
434
0
  ctx->b = 0xefcdab89;
435
0
  ctx->c = 0x98badcfe;
436
0
  ctx->d = 0x10325476;
437
438
0
  ctx->lo = 0;
439
0
  ctx->hi = 0;
440
441
0
  return CURLE_OK;
442
0
}
443
444
static void my_md5_update(void *in,
445
                          const unsigned char *input, unsigned int len)
446
0
{
447
0
  uint32_t saved_lo;
448
0
  unsigned int used;
449
0
  my_md5_ctx *ctx = (my_md5_ctx *)in;
450
451
0
  saved_lo = ctx->lo;
452
0
  ctx->lo = (saved_lo + len) & 0x1fffffff;
453
0
  if(ctx->lo < saved_lo)
454
0
    ctx->hi++;
455
0
  ctx->hi += (uint32_t)len >> 29;
456
457
0
  used = saved_lo & 0x3f;
458
459
0
  if(used) {
460
0
    unsigned int available = 64 - used;
461
462
0
    if(len < available) {
463
0
      memcpy(&ctx->buffer[used], input, len);
464
0
      return;
465
0
    }
466
467
0
    memcpy(&ctx->buffer[used], input, available);
468
0
    input = (const unsigned char *)input + available;
469
0
    len -= available;
470
0
    my_md5_body(ctx, ctx->buffer, 64);
471
0
  }
472
473
0
  if(len >= 64) {
474
0
    input = my_md5_body(ctx, input, len & ~(unsigned long)0x3f);
475
0
    len &= 0x3f;
476
0
  }
477
478
0
  memcpy(ctx->buffer, input, len);
479
0
}
480
481
static void my_md5_final(unsigned char *digest, void *in)
482
0
{
483
0
  unsigned int used, available;
484
0
  my_md5_ctx *ctx = (my_md5_ctx *)in;
485
486
0
  used = ctx->lo & 0x3f;
487
488
0
  ctx->buffer[used++] = 0x80;
489
490
0
  available = 64 - used;
491
492
0
  if(available < 8) {
493
0
    memset(&ctx->buffer[used], 0, available);
494
0
    my_md5_body(ctx, ctx->buffer, 64);
495
0
    used = 0;
496
0
    available = 64;
497
0
  }
498
499
0
  memset(&ctx->buffer[used], 0, available - 8);
500
501
0
  ctx->lo <<= 3;
502
0
  ctx->buffer[56] = curlx_ultouc((ctx->lo) & 0xff);
503
0
  ctx->buffer[57] = curlx_ultouc((ctx->lo >> 8) & 0xff);
504
0
  ctx->buffer[58] = curlx_ultouc((ctx->lo >> 16) & 0xff);
505
0
  ctx->buffer[59] = curlx_ultouc(ctx->lo >> 24);
506
0
  ctx->buffer[60] = curlx_ultouc((ctx->hi) & 0xff);
507
0
  ctx->buffer[61] = curlx_ultouc((ctx->hi >> 8) & 0xff);
508
0
  ctx->buffer[62] = curlx_ultouc((ctx->hi >> 16) & 0xff);
509
0
  ctx->buffer[63] = curlx_ultouc(ctx->hi >> 24);
510
511
0
  my_md5_body(ctx, ctx->buffer, 64);
512
513
0
  digest[0] = curlx_ultouc((ctx->a) & 0xff);
514
0
  digest[1] = curlx_ultouc((ctx->a >> 8) & 0xff);
515
0
  digest[2] = curlx_ultouc((ctx->a >> 16) & 0xff);
516
0
  digest[3] = curlx_ultouc(ctx->a >> 24);
517
0
  digest[4] = curlx_ultouc((ctx->b) & 0xff);
518
0
  digest[5] = curlx_ultouc((ctx->b >> 8) & 0xff);
519
0
  digest[6] = curlx_ultouc((ctx->b >> 16) & 0xff);
520
0
  digest[7] = curlx_ultouc(ctx->b >> 24);
521
0
  digest[8] = curlx_ultouc((ctx->c) & 0xff);
522
0
  digest[9] = curlx_ultouc((ctx->c >> 8) & 0xff);
523
0
  digest[10] = curlx_ultouc((ctx->c >> 16) & 0xff);
524
0
  digest[11] = curlx_ultouc(ctx->c >> 24);
525
0
  digest[12] = curlx_ultouc((ctx->d) & 0xff);
526
0
  digest[13] = curlx_ultouc((ctx->d >> 8) & 0xff);
527
0
  digest[14] = curlx_ultouc((ctx->d >> 16) & 0xff);
528
0
  digest[15] = curlx_ultouc(ctx->d >> 24);
529
530
0
  memset(ctx, 0, sizeof(*ctx));
531
0
}
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 */