Coverage Report

Created: 2025-10-30 06:17

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