Coverage Report

Created: 2025-06-09 07:42

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