Coverage Report

Created: 2026-04-12 06:56

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