Coverage Report

Created: 2025-12-14 06:39

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