Coverage Report

Created: 2025-10-10 06:31

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