quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

md5.c (20287B)


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