I did this
(the following report comes from Codex Security, copied mostly as-is. Trimmed a little since it is just so much.)
References this commit: 01f08dc by @vszakats which was a follow-up to #21169
Summary
Introduced build-only bug: GnuTLS DES availability was narrowed to HAVE_GNUTLS_DES, but subsequent conditional compilation still keys off USE_GNUTLS. This can break NTLM builds for certain MultiSSL configurations using GnuTLS with Nettle 4+ and another DES-capable backend.
The patch changes the GnuTLS DES include/selection path to require HAVE_GNUTLS_DES, which is only defined for Nettle versions below 4. However, the later NTLM DES implementation branches still test USE_GNUTLS directly. In a build that enables GnuTLS with Nettle 4+ together with another DES-capable fallback backend such as mbedTLS, the initial backend-selection block can choose USE_MBEDTLS_DES, but the implementation blocks will still select the USE_GNUTLS branches and reference struct des_ctx, des_set_key, and des_encrypt even though nettle/des.h was not included. This is a compile-time backend-selection mismatch, not a runtime memory-safety or authentication vulnerability.
Validation
Report
Validated the finding as a deterministic build-only bug. Code review of /workspace/curl/lib/curl_ntlm_core.c shows the commit added HAVE_GNUTLS_DES only when USE_GNUTLS and NETTLE_VERSION_MAJOR < 4 at lines 52-57, and the top DES backend selection falls through to mbedTLS at lines 73-82 when Nettle 4+ is used. However, later implementation branches still use #elif defined(USE_GNUTLS) at lines 185, 324, and 377, causing the GnuTLS/Nettle DES code to compile even though nettle/des.h was not included and mbedTLS DES was selected. I created /workspace/ntlm_des_poc with curl_ntlm_core.c copied byte-for-byte from the repository (matching sha256 ac675eb2833007eea832220487f977dfde9f131845cd53df1f9edd8c28b0fd44) and fake headers modeling USE_GNUTLS + NETTLE_VERSION_MAJOR 4 + USE_MBEDTLS + HAVE_MBEDTLS_DES_CRYPT_ECB. Preprocessing showed: #define USE_GNUTLS 1, #define USE_MBEDTLS 1, #define USE_MBEDTLS_DES, #define NETTLE_VERSION_MAJOR 4, and no HAVE_GNUTLS_DES. Compiling the original source with ./build_original.sh fails with undefined/incomplete GnuTLS DES symbols: struct des_ctx, curl_des_set_odd_parity, des_set_key, and des_encrypt. As a control, curl_ntlm_core_fixed.c changes only the later USE_GNUTLS implementation guards to HAVE_GNUTLS_DES; ./build_fixed.sh exits 0 under the same fake MultiSSL/Nettle4/mbedTLS configuration. Runtime crash, valgrind, and debugger validation were attempted but are not applicable because the original source does not compile into an executable; valgrind is unavailable in the container and lldb cannot trace a compile-time failure. This confirms the suspected backend-selection mismatch and confirms it is not a runtime security vulnerability.
Evidence
lib/curl_ntlm_core.c (L185 to 198)
Note: The setup_des_key implementation still selects the GnuTLS DES path based on USE_GNUTLS rather than HAVE_GNUTLS_DES, causing references to Nettle DES types/functions even when GnuTLS DES was disabled.
#elif defined(USE_GNUTLS)
static void setup_des_key(const unsigned char *key_56, struct des_ctx *des)
{
char key[8];
/* Expand the 56-bit key to 64 bits */
extend_key_56_to_64(key_56, key);
/* Set the key parity to odd */
curl_des_set_odd_parity((unsigned char *)key, sizeof(key));
/* Set the key */
des_set_key(des, (const uint8_t *)key);
}
lib/curl_ntlm_core.c (L324 to 331)
Note: The NTLM LM response path still selects GnuTLS DES using USE_GNUTLS, which is inconsistent with the new HAVE_GNUTLS_DES availability check.
#elif defined(USE_GNUTLS)
struct des_ctx des;
setup_des_key(keys, &des);
des_encrypt(&des, 8, results, plaintext);
setup_des_key(keys + 7, &des);
des_encrypt(&des, 8, results + 8, plaintext);
setup_des_key(keys + 14, &des);
des_encrypt(&des, 8, results + 16, plaintext);
lib/curl_ntlm_core.c (L377 to 382)
Note: The LAN Manager hash path similarly uses USE_GNUTLS instead of HAVE_GNUTLS_DES, completing the same backend mismatch.
#elif defined(USE_GNUTLS)
struct des_ctx des;
setup_des_key(pw, &des);
des_encrypt(&des, 8, lmbuffer, magic);
setup_des_key(pw + 7, &des);
des_encrypt(&des, 8, lmbuffer + 8, magic);
lib/curl_ntlm_core.c (L52 to 90)
Note: The patch defines HAVE_GNUTLS_DES only for Nettle versions below 4 and uses it to decide whether nettle/des.h is included. With Nettle 4+, this block may fall through to another DES backend such as mbedTLS.
#ifdef USE_GNUTLS
#include <nettle/version.h>
#if NETTLE_VERSION_MAJOR < 4
#define HAVE_GNUTLS_DES
#endif
#endif
#if defined(USE_OPENSSL) && defined(HAVE_DES_ECB_ENCRYPT)
# include <openssl/des.h>
# ifdef OPENSSL_IS_AWSLC /* for versions 1.2.0 to 1.30.1 */
# define DES_set_key_unchecked (void)DES_set_key
# endif
# define USE_OPENSSL_DES
#elif defined(USE_WOLFSSL) && defined(HAVE_WC_DES_ECBENCRYPT)
# include <wolfssl/options.h>
# include <wolfssl/wolfcrypt/des3.h>
# define USE_WOLFSSL_DES
#elif defined(HAVE_GNUTLS_DES)
# include <nettle/des.h>
# define USE_CURL_DES_SET_ODD_PARITY
#elif defined(USE_MBEDTLS) && defined(HAVE_MBEDTLS_DES_CRYPT_ECB)
# include <mbedtls/version.h>
# if MBEDTLS_VERSION_NUMBER < 0x03020000
# error "mbedTLS 3.2.0 or later required"
# endif
# include <mbedtls/des.h>
# define USE_MBEDTLS_DES
#elif defined(USE_OS400CRYPTO)
# include "cipher.mih" /* mih/cipher */
# define USE_CURL_DES_SET_ODD_PARITY
#elif defined(USE_WIN32_CRYPTO)
# include <wincrypt.h>
# define USE_CURL_DES_SET_ODD_PARITY
#else
# error "cannot compile NTLM support without a crypto library with DES."
I expected the following
No response
curl/libcurl version
git master
operating system
any
I did this
(the following report comes from Codex Security, copied mostly as-is. Trimmed a little since it is just so much.)
References this commit: 01f08dc by @vszakats which was a follow-up to #21169
Summary
Introduced build-only bug: GnuTLS DES availability was narrowed to HAVE_GNUTLS_DES, but subsequent conditional compilation still keys off USE_GNUTLS. This can break NTLM builds for certain MultiSSL configurations using GnuTLS with Nettle 4+ and another DES-capable backend.
The patch changes the GnuTLS DES include/selection path to require HAVE_GNUTLS_DES, which is only defined for Nettle versions below 4. However, the later NTLM DES implementation branches still test USE_GNUTLS directly. In a build that enables GnuTLS with Nettle 4+ together with another DES-capable fallback backend such as mbedTLS, the initial backend-selection block can choose USE_MBEDTLS_DES, but the implementation blocks will still select the USE_GNUTLS branches and reference struct des_ctx, des_set_key, and des_encrypt even though nettle/des.h was not included. This is a compile-time backend-selection mismatch, not a runtime memory-safety or authentication vulnerability.
Validation
Report
Validated the finding as a deterministic build-only bug. Code review of /workspace/curl/lib/curl_ntlm_core.c shows the commit added HAVE_GNUTLS_DES only when USE_GNUTLS and NETTLE_VERSION_MAJOR < 4 at lines 52-57, and the top DES backend selection falls through to mbedTLS at lines 73-82 when Nettle 4+ is used. However, later implementation branches still use #elif defined(USE_GNUTLS) at lines 185, 324, and 377, causing the GnuTLS/Nettle DES code to compile even though nettle/des.h was not included and mbedTLS DES was selected. I created /workspace/ntlm_des_poc with curl_ntlm_core.c copied byte-for-byte from the repository (matching sha256 ac675eb2833007eea832220487f977dfde9f131845cd53df1f9edd8c28b0fd44) and fake headers modeling USE_GNUTLS + NETTLE_VERSION_MAJOR 4 + USE_MBEDTLS + HAVE_MBEDTLS_DES_CRYPT_ECB. Preprocessing showed: #define USE_GNUTLS 1, #define USE_MBEDTLS 1, #define USE_MBEDTLS_DES, #define NETTLE_VERSION_MAJOR 4, and no HAVE_GNUTLS_DES. Compiling the original source with ./build_original.sh fails with undefined/incomplete GnuTLS DES symbols: struct des_ctx, curl_des_set_odd_parity, des_set_key, and des_encrypt. As a control, curl_ntlm_core_fixed.c changes only the later USE_GNUTLS implementation guards to HAVE_GNUTLS_DES; ./build_fixed.sh exits 0 under the same fake MultiSSL/Nettle4/mbedTLS configuration. Runtime crash, valgrind, and debugger validation were attempted but are not applicable because the original source does not compile into an executable; valgrind is unavailable in the container and lldb cannot trace a compile-time failure. This confirms the suspected backend-selection mismatch and confirms it is not a runtime security vulnerability.
Evidence
lib/curl_ntlm_core.c (L185 to 198)
Note: The setup_des_key implementation still selects the GnuTLS DES path based on USE_GNUTLS rather than HAVE_GNUTLS_DES, causing references to Nettle DES types/functions even when GnuTLS DES was disabled.
lib/curl_ntlm_core.c (L324 to 331)
Note: The NTLM LM response path still selects GnuTLS DES using USE_GNUTLS, which is inconsistent with the new HAVE_GNUTLS_DES availability check.
lib/curl_ntlm_core.c (L377 to 382)
Note: The LAN Manager hash path similarly uses USE_GNUTLS instead of HAVE_GNUTLS_DES, completing the same backend mismatch.
lib/curl_ntlm_core.c (L52 to 90)
Note: The patch defines HAVE_GNUTLS_DES only for Nettle versions below 4 and uses it to decide whether nettle/des.h is included. With Nettle 4+, this block may fall through to another DES backend such as mbedTLS.
I expected the following
No response
curl/libcurl version
git master
operating system
any