Coverage Report

Created: 2026-03-12 06:35

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