Coverage Report

Created: 2023-06-07 07:02

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