Coverage Report

Created: 2023-12-08 06:48

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