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