diff --git a/src/Utils.cpp b/src/Utils.cpp index d83e3ee5..22d264c7 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -28,6 +28,7 @@ #ifdef HAVE_LIBSSL #include #include +#include #include #if (OPENSSL_VERSION_NUMBER < 0x10100000L) || (defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER < 0x20700000L)) #define X509_getm_notBefore X509_get_notBefore @@ -279,13 +280,22 @@ bool CUtils::ConstantTimeEquals(const CString& a, const CString& b) { if (a.length() != b.length()) { return false; } - unsigned char acc = 0; - const unsigned char* pa = reinterpret_cast(a.data()); - const unsigned char* pb = reinterpret_cast(b.data()); +#ifdef HAVE_LIBSSL + return CRYPTO_memcmp(a.data(), b.data(), a.length()) == 0; +#else + // Best-effort fallback when OpenSSL is unavailable: an optimizer is + // in principle allowed to short-circuit this loop, so the volatile + // accumulator and pointers are a hint rather than a guarantee. + volatile unsigned char acc = 0; + const volatile unsigned char* pa = + reinterpret_cast(a.data()); + const volatile unsigned char* pb = + reinterpret_cast(b.data()); for (size_t i = 0; i < a.length(); ++i) { acc |= static_cast(pa[i] ^ pb[i]); } return acc == 0; +#endif } CString CUtils::GetPass(const CString& sPrompt) {