quickjs-tart

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

md4.c (15934B)


      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)
     28 
     29 #include <string.h>
     30 
     31 #include "strdup.h"
     32 #include "curl_md4.h"
     33 #include "curlx/warnless.h"
     34 
     35 #ifdef USE_OPENSSL
     36 #include <openssl/opensslv.h>
     37 #if (OPENSSL_VERSION_NUMBER >= 0x30000000L) && !defined(USE_AMISSL)
     38 /* OpenSSL 3.0.0 marks the MD4 functions as deprecated */
     39 #define OPENSSL_NO_MD4
     40 #else
     41 /* Cover also OPENSSL_NO_MD4 configured in openssl */
     42 #include <openssl/opensslconf.h>
     43 #endif
     44 #endif /* USE_OPENSSL */
     45 
     46 #ifdef USE_WOLFSSL
     47 #include <wolfssl/options.h>
     48 #define VOID_MD4_INIT
     49 #ifdef NO_MD4
     50 #define WOLFSSL_NO_MD4
     51 #endif
     52 #endif
     53 
     54 #ifdef USE_MBEDTLS
     55 #include <mbedtls/version.h>
     56 #if MBEDTLS_VERSION_NUMBER >= 0x03000000
     57 #include <mbedtls/mbedtls_config.h>
     58 #else
     59 #include <mbedtls/config.h>
     60 #endif
     61 #if(MBEDTLS_VERSION_NUMBER >= 0x02070000) && \
     62    (MBEDTLS_VERSION_NUMBER < 0x03000000)
     63   #define HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS
     64 #endif
     65 #endif /* USE_MBEDTLS */
     66 
     67 #if defined(USE_GNUTLS)
     68 #include <nettle/md4.h>
     69 /* When OpenSSL or wolfSSL is available, we use their MD4 functions. */
     70 #elif defined(USE_WOLFSSL) && !defined(WOLFSSL_NO_MD4)
     71 #include <wolfssl/openssl/md4.h>
     72 #elif defined(USE_OPENSSL) && !defined(OPENSSL_NO_MD4)
     73 #include <openssl/md4.h>
     74 #elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \
     75               (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040) && \
     76        defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && \
     77               (__MAC_OS_X_VERSION_MIN_REQUIRED < 101500)) || \
     78       (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && \
     79               (__IPHONE_OS_VERSION_MAX_ALLOWED >= 20000) && \
     80        defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && \
     81               (__IPHONE_OS_VERSION_MIN_REQUIRED < 130000))
     82 #define AN_APPLE_OS
     83 #include <CommonCrypto/CommonDigest.h>
     84 #elif defined(USE_WIN32_CRYPTO)
     85 #include <wincrypt.h>
     86 #elif(defined(USE_MBEDTLS) && defined(MBEDTLS_MD4_C))
     87 #include <mbedtls/md4.h>
     88 #endif
     89 
     90 /* The last 3 #include files should be in this order */
     91 #include "curl_printf.h"
     92 #include "curl_memory.h"
     93 #include "memdebug.h"
     94 
     95 
     96 #if defined(USE_GNUTLS)
     97 
     98 typedef struct md4_ctx MD4_CTX;
     99 
    100 static int MD4_Init(MD4_CTX *ctx)
    101 {
    102   md4_init(ctx);
    103   return 1;
    104 }
    105 
    106 static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
    107 {
    108   md4_update(ctx, size, data);
    109 }
    110 
    111 static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
    112 {
    113   md4_digest(ctx, MD4_DIGEST_SIZE, result);
    114 }
    115 
    116 #elif defined(USE_WOLFSSL) && !defined(WOLFSSL_NO_MD4)
    117 
    118 #ifdef OPENSSL_COEXIST
    119   #define MD4_CTX WOLFSSL_MD4_CTX
    120   #define MD4_Init wolfSSL_MD4_Init
    121   #define MD4_Update wolfSSL_MD4_Update
    122   #define MD4_Final wolfSSL_MD4_Final
    123 #endif
    124 
    125 #elif defined(USE_OPENSSL) && !defined(OPENSSL_NO_MD4)
    126 
    127 #elif defined(AN_APPLE_OS)
    128 typedef CC_MD4_CTX MD4_CTX;
    129 
    130 static int MD4_Init(MD4_CTX *ctx)
    131 {
    132   return CC_MD4_Init(ctx);
    133 }
    134 
    135 static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
    136 {
    137   (void)CC_MD4_Update(ctx, data, (CC_LONG)size);
    138 }
    139 
    140 static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
    141 {
    142   (void)CC_MD4_Final(result, ctx);
    143 }
    144 
    145 #elif defined(USE_WIN32_CRYPTO)
    146 
    147 struct md4_ctx {
    148   HCRYPTPROV hCryptProv;
    149   HCRYPTHASH hHash;
    150 };
    151 typedef struct md4_ctx MD4_CTX;
    152 
    153 static int MD4_Init(MD4_CTX *ctx)
    154 {
    155   ctx->hCryptProv = 0;
    156   ctx->hHash = 0;
    157 
    158   if(!CryptAcquireContext(&ctx->hCryptProv, NULL, NULL, PROV_RSA_FULL,
    159                           CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
    160     return 0;
    161 
    162   if(!CryptCreateHash(ctx->hCryptProv, CALG_MD4, 0, 0, &ctx->hHash)) {
    163     CryptReleaseContext(ctx->hCryptProv, 0);
    164     ctx->hCryptProv = 0;
    165     return 0;
    166   }
    167 
    168   return 1;
    169 }
    170 
    171 static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
    172 {
    173 #ifdef __MINGW32CE__
    174   CryptHashData(ctx->hHash, (BYTE *)CURL_UNCONST(data),
    175                 (unsigned int) size, 0);
    176 #else
    177   CryptHashData(ctx->hHash, (const BYTE *)data, (unsigned int) size, 0);
    178 #endif
    179 }
    180 
    181 static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
    182 {
    183   unsigned long length = 0;
    184 
    185   CryptGetHashParam(ctx->hHash, HP_HASHVAL, NULL, &length, 0);
    186   if(length == MD4_DIGEST_LENGTH)
    187     CryptGetHashParam(ctx->hHash, HP_HASHVAL, result, &length, 0);
    188 
    189   if(ctx->hHash)
    190     CryptDestroyHash(ctx->hHash);
    191 
    192   if(ctx->hCryptProv)
    193     CryptReleaseContext(ctx->hCryptProv, 0);
    194 }
    195 
    196 #elif(defined(USE_MBEDTLS) && defined(MBEDTLS_MD4_C))
    197 
    198 struct md4_ctx {
    199   void *data;
    200   unsigned long size;
    201 };
    202 typedef struct md4_ctx MD4_CTX;
    203 
    204 static int MD4_Init(MD4_CTX *ctx)
    205 {
    206   ctx->data = NULL;
    207   ctx->size = 0;
    208   return 1;
    209 }
    210 
    211 static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
    212 {
    213   if(!ctx->data) {
    214     ctx->data = Curl_memdup(data, size);
    215     if(ctx->data)
    216       ctx->size = size;
    217   }
    218 }
    219 
    220 static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
    221 {
    222   if(ctx->data) {
    223 #if !defined(HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS)
    224     mbedtls_md4(ctx->data, ctx->size, result);
    225 #else
    226     (void) mbedtls_md4_ret(ctx->data, ctx->size, result);
    227 #endif
    228 
    229     Curl_safefree(ctx->data);
    230     ctx->size = 0;
    231   }
    232 }
    233 
    234 #else
    235 /* When no other crypto library is available, or the crypto library does not
    236  * support MD4, we use this code segment this implementation of it
    237  *
    238  * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
    239  * MD4 Message-Digest Algorithm (RFC 1320).
    240  *
    241  * Homepage:
    242  https://openwall.info/wiki/people/solar/software/public-domain-source-code/md4
    243  *
    244  * Author:
    245  * Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
    246  *
    247  * This software was written by Alexander Peslyak in 2001. No copyright is
    248  * claimed, and the software is hereby placed in the public domain. In case
    249  * this attempt to disclaim copyright and place the software in the public
    250  * domain is deemed null and void, then the software is Copyright (c) 2001
    251  * Alexander Peslyak and it is hereby released to the general public under the
    252  * following terms:
    253  *
    254  * Redistribution and use in source and binary forms, with or without
    255  * modification, are permitted.
    256  *
    257  * There is ABSOLUTELY NO WARRANTY, express or implied.
    258  *
    259  * (This is a heavily cut-down "BSD license".)
    260  *
    261  * This differs from Colin Plumb's older public domain implementation in that
    262  * no exactly 32-bit integer data type is required (any 32-bit or wider
    263  * unsigned integer data type will do), there is no compile-time endianness
    264  * configuration, and the function prototypes match OpenSSL's. No code from
    265  * Colin Plumb's implementation has been reused; this comment merely compares
    266  * the properties of the two independent implementations.
    267  *
    268  * The primary goals of this implementation are portability and ease of use.
    269  * It is meant to be fast, but not as fast as possible. Some known
    270  * optimizations are not included to reduce source code size and avoid
    271  * compile-time configuration.
    272  */
    273 
    274 /* Any 32-bit or wider unsigned integer data type will do */
    275 typedef unsigned int MD4_u32plus;
    276 
    277 struct md4_ctx {
    278   MD4_u32plus lo, hi;
    279   MD4_u32plus a, b, c, d;
    280   unsigned char buffer[64];
    281   MD4_u32plus block[16];
    282 };
    283 typedef struct md4_ctx MD4_CTX;
    284 
    285 static int MD4_Init(MD4_CTX *ctx);
    286 static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size);
    287 static void MD4_Final(unsigned char *result, MD4_CTX *ctx);
    288 
    289 /*
    290  * The basic MD4 functions.
    291  *
    292  * F and G are optimized compared to their RFC 1320 definitions, with the
    293  * optimization for F borrowed from Colin Plumb's MD5 implementation.
    294  */
    295 #define MD4_F(x, y, z)                  ((z) ^ ((x) & ((y) ^ (z))))
    296 #define MD4_G(x, y, z)                  (((x) & ((y) | (z))) | ((y) & (z)))
    297 #define MD4_H(x, y, z)                  ((x) ^ (y) ^ (z))
    298 
    299 /*
    300  * The MD4 transformation for all three rounds.
    301  */
    302 #define MD4_STEP(f, a, b, c, d, x, s) \
    303         (a) += f((b), (c), (d)) + (x); \
    304         (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s))));
    305 
    306 /*
    307  * SET reads 4 input bytes in little-endian byte order and stores them
    308  * in a properly aligned word in host byte order.
    309  *
    310  * The check for little-endian architectures that tolerate unaligned
    311  * memory accesses is just an optimization. Nothing will break if it
    312  * does not work.
    313  */
    314 #if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
    315 #define MD4_SET(n) \
    316         (*(const MD4_u32plus *)(const void *)&ptr[(n) * 4])
    317 #define MD4_GET(n) \
    318         MD4_SET(n)
    319 #else
    320 #define MD4_SET(n) \
    321         (ctx->block[(n)] = \
    322           (MD4_u32plus)ptr[(n) * 4] | \
    323           ((MD4_u32plus)ptr[(n) * 4 + 1] << 8) | \
    324           ((MD4_u32plus)ptr[(n) * 4 + 2] << 16) | \
    325           ((MD4_u32plus)ptr[(n) * 4 + 3] << 24))
    326 #define MD4_GET(n) \
    327         (ctx->block[(n)])
    328 #endif
    329 
    330 /*
    331  * This processes one or more 64-byte data blocks, but does NOT update
    332  * the bit counters. There are no alignment requirements.
    333  */
    334 static const void *my_md4_body(MD4_CTX *ctx,
    335                                const void *data, unsigned long size)
    336 {
    337   const unsigned char *ptr;
    338   MD4_u32plus a, b, c, d;
    339 
    340   ptr = (const unsigned char *)data;
    341 
    342   a = ctx->a;
    343   b = ctx->b;
    344   c = ctx->c;
    345   d = ctx->d;
    346 
    347   do {
    348     MD4_u32plus saved_a, saved_b, saved_c, saved_d;
    349 
    350     saved_a = a;
    351     saved_b = b;
    352     saved_c = c;
    353     saved_d = d;
    354 
    355 /* Round 1 */
    356     MD4_STEP(MD4_F, a, b, c, d, MD4_SET(0), 3)
    357     MD4_STEP(MD4_F, d, a, b, c, MD4_SET(1), 7)
    358     MD4_STEP(MD4_F, c, d, a, b, MD4_SET(2), 11)
    359     MD4_STEP(MD4_F, b, c, d, a, MD4_SET(3), 19)
    360     MD4_STEP(MD4_F, a, b, c, d, MD4_SET(4), 3)
    361     MD4_STEP(MD4_F, d, a, b, c, MD4_SET(5), 7)
    362     MD4_STEP(MD4_F, c, d, a, b, MD4_SET(6), 11)
    363     MD4_STEP(MD4_F, b, c, d, a, MD4_SET(7), 19)
    364     MD4_STEP(MD4_F, a, b, c, d, MD4_SET(8), 3)
    365     MD4_STEP(MD4_F, d, a, b, c, MD4_SET(9), 7)
    366     MD4_STEP(MD4_F, c, d, a, b, MD4_SET(10), 11)
    367     MD4_STEP(MD4_F, b, c, d, a, MD4_SET(11), 19)
    368     MD4_STEP(MD4_F, a, b, c, d, MD4_SET(12), 3)
    369     MD4_STEP(MD4_F, d, a, b, c, MD4_SET(13), 7)
    370     MD4_STEP(MD4_F, c, d, a, b, MD4_SET(14), 11)
    371     MD4_STEP(MD4_F, b, c, d, a, MD4_SET(15), 19)
    372 
    373 /* Round 2 */
    374     MD4_STEP(MD4_G, a, b, c, d, MD4_GET(0) + 0x5a827999, 3)
    375     MD4_STEP(MD4_G, d, a, b, c, MD4_GET(4) + 0x5a827999, 5)
    376     MD4_STEP(MD4_G, c, d, a, b, MD4_GET(8) + 0x5a827999, 9)
    377     MD4_STEP(MD4_G, b, c, d, a, MD4_GET(12) + 0x5a827999, 13)
    378     MD4_STEP(MD4_G, a, b, c, d, MD4_GET(1) + 0x5a827999, 3)
    379     MD4_STEP(MD4_G, d, a, b, c, MD4_GET(5) + 0x5a827999, 5)
    380     MD4_STEP(MD4_G, c, d, a, b, MD4_GET(9) + 0x5a827999, 9)
    381     MD4_STEP(MD4_G, b, c, d, a, MD4_GET(13) + 0x5a827999, 13)
    382     MD4_STEP(MD4_G, a, b, c, d, MD4_GET(2) + 0x5a827999, 3)
    383     MD4_STEP(MD4_G, d, a, b, c, MD4_GET(6) + 0x5a827999, 5)
    384     MD4_STEP(MD4_G, c, d, a, b, MD4_GET(10) + 0x5a827999, 9)
    385     MD4_STEP(MD4_G, b, c, d, a, MD4_GET(14) + 0x5a827999, 13)
    386     MD4_STEP(MD4_G, a, b, c, d, MD4_GET(3) + 0x5a827999, 3)
    387     MD4_STEP(MD4_G, d, a, b, c, MD4_GET(7) + 0x5a827999, 5)
    388     MD4_STEP(MD4_G, c, d, a, b, MD4_GET(11) + 0x5a827999, 9)
    389     MD4_STEP(MD4_G, b, c, d, a, MD4_GET(15) + 0x5a827999, 13)
    390 
    391 /* Round 3 */
    392     MD4_STEP(MD4_H, a, b, c, d, MD4_GET(0) + 0x6ed9eba1, 3)
    393     MD4_STEP(MD4_H, d, a, b, c, MD4_GET(8) + 0x6ed9eba1, 9)
    394     MD4_STEP(MD4_H, c, d, a, b, MD4_GET(4) + 0x6ed9eba1, 11)
    395     MD4_STEP(MD4_H, b, c, d, a, MD4_GET(12) + 0x6ed9eba1, 15)
    396     MD4_STEP(MD4_H, a, b, c, d, MD4_GET(2) + 0x6ed9eba1, 3)
    397     MD4_STEP(MD4_H, d, a, b, c, MD4_GET(10) + 0x6ed9eba1, 9)
    398     MD4_STEP(MD4_H, c, d, a, b, MD4_GET(6) + 0x6ed9eba1, 11)
    399     MD4_STEP(MD4_H, b, c, d, a, MD4_GET(14) + 0x6ed9eba1, 15)
    400     MD4_STEP(MD4_H, a, b, c, d, MD4_GET(1) + 0x6ed9eba1, 3)
    401     MD4_STEP(MD4_H, d, a, b, c, MD4_GET(9) + 0x6ed9eba1, 9)
    402     MD4_STEP(MD4_H, c, d, a, b, MD4_GET(5) + 0x6ed9eba1, 11)
    403     MD4_STEP(MD4_H, b, c, d, a, MD4_GET(13) + 0x6ed9eba1, 15)
    404     MD4_STEP(MD4_H, a, b, c, d, MD4_GET(3) + 0x6ed9eba1, 3)
    405     MD4_STEP(MD4_H, d, a, b, c, MD4_GET(11) + 0x6ed9eba1, 9)
    406     MD4_STEP(MD4_H, c, d, a, b, MD4_GET(7) + 0x6ed9eba1, 11)
    407     MD4_STEP(MD4_H, b, c, d, a, MD4_GET(15) + 0x6ed9eba1, 15)
    408 
    409     a += saved_a;
    410     b += saved_b;
    411     c += saved_c;
    412     d += saved_d;
    413 
    414     ptr += 64;
    415   } while(size -= 64);
    416 
    417   ctx->a = a;
    418   ctx->b = b;
    419   ctx->c = c;
    420   ctx->d = d;
    421 
    422   return ptr;
    423 }
    424 
    425 static int MD4_Init(MD4_CTX *ctx)
    426 {
    427   ctx->a = 0x67452301;
    428   ctx->b = 0xefcdab89;
    429   ctx->c = 0x98badcfe;
    430   ctx->d = 0x10325476;
    431 
    432   ctx->lo = 0;
    433   ctx->hi = 0;
    434   return 1;
    435 }
    436 
    437 static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
    438 {
    439   MD4_u32plus saved_lo;
    440   unsigned long used;
    441 
    442   saved_lo = ctx->lo;
    443   ctx->lo = (saved_lo + size) & 0x1fffffff;
    444   if(ctx->lo < saved_lo)
    445     ctx->hi++;
    446   ctx->hi += (MD4_u32plus)size >> 29;
    447 
    448   used = saved_lo & 0x3f;
    449 
    450   if(used) {
    451     unsigned long available = 64 - used;
    452 
    453     if(size < available) {
    454       memcpy(&ctx->buffer[used], data, size);
    455       return;
    456     }
    457 
    458     memcpy(&ctx->buffer[used], data, available);
    459     data = (const unsigned char *)data + available;
    460     size -= available;
    461     my_md4_body(ctx, ctx->buffer, 64);
    462   }
    463 
    464   if(size >= 64) {
    465     data = my_md4_body(ctx, data, size & ~(unsigned long)0x3f);
    466     size &= 0x3f;
    467   }
    468 
    469   memcpy(ctx->buffer, data, size);
    470 }
    471 
    472 static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
    473 {
    474   unsigned long used, available;
    475 
    476   used = ctx->lo & 0x3f;
    477 
    478   ctx->buffer[used++] = 0x80;
    479 
    480   available = 64 - used;
    481 
    482   if(available < 8) {
    483     memset(&ctx->buffer[used], 0, available);
    484     my_md4_body(ctx, ctx->buffer, 64);
    485     used = 0;
    486     available = 64;
    487   }
    488 
    489   memset(&ctx->buffer[used], 0, available - 8);
    490 
    491   ctx->lo <<= 3;
    492   ctx->buffer[56] = curlx_ultouc((ctx->lo)&0xff);
    493   ctx->buffer[57] = curlx_ultouc((ctx->lo >> 8)&0xff);
    494   ctx->buffer[58] = curlx_ultouc((ctx->lo >> 16)&0xff);
    495   ctx->buffer[59] = curlx_ultouc((ctx->lo >> 24)&0xff);
    496   ctx->buffer[60] = curlx_ultouc((ctx->hi)&0xff);
    497   ctx->buffer[61] = curlx_ultouc((ctx->hi >> 8)&0xff);
    498   ctx->buffer[62] = curlx_ultouc((ctx->hi >> 16)&0xff);
    499   ctx->buffer[63] = curlx_ultouc(ctx->hi >> 24);
    500 
    501   my_md4_body(ctx, ctx->buffer, 64);
    502 
    503   result[0] = curlx_ultouc((ctx->a)&0xff);
    504   result[1] = curlx_ultouc((ctx->a >> 8)&0xff);
    505   result[2] = curlx_ultouc((ctx->a >> 16)&0xff);
    506   result[3] = curlx_ultouc(ctx->a >> 24);
    507   result[4] = curlx_ultouc((ctx->b)&0xff);
    508   result[5] = curlx_ultouc((ctx->b >> 8)&0xff);
    509   result[6] = curlx_ultouc((ctx->b >> 16)&0xff);
    510   result[7] = curlx_ultouc(ctx->b >> 24);
    511   result[8] = curlx_ultouc((ctx->c)&0xff);
    512   result[9] = curlx_ultouc((ctx->c >> 8)&0xff);
    513   result[10] = curlx_ultouc((ctx->c >> 16)&0xff);
    514   result[11] = curlx_ultouc(ctx->c >> 24);
    515   result[12] = curlx_ultouc((ctx->d)&0xff);
    516   result[13] = curlx_ultouc((ctx->d >> 8)&0xff);
    517   result[14] = curlx_ultouc((ctx->d >> 16)&0xff);
    518   result[15] = curlx_ultouc(ctx->d >> 24);
    519 
    520   memset(ctx, 0, sizeof(*ctx));
    521 }
    522 
    523 #endif /* CRYPTO LIBS */
    524 
    525 CURLcode Curl_md4it(unsigned char *output, const unsigned char *input,
    526                     const size_t len)
    527 {
    528   MD4_CTX ctx;
    529 
    530 #ifdef VOID_MD4_INIT
    531   MD4_Init(&ctx);
    532 #else
    533   if(!MD4_Init(&ctx))
    534     return CURLE_FAILED_INIT;
    535 #endif
    536 
    537   MD4_Update(&ctx, input, curlx_uztoui(len));
    538   MD4_Final(output, &ctx);
    539   return CURLE_OK;
    540 }
    541 
    542 #endif /* USE_CURL_NTLM_CORE */