Coverage Report

Created: 2023-03-26 06:11

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