Coverage Report

Created: 2025-08-26 07:08

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