From 50dca24f5067f275b827747fc772e609a205e605 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 4 Mar 2024 16:59:51 -0600 Subject: [PATCH] refactor: aggregate crypto handles when computing digests (#6662) * refactor: aggregate per-crypto-pkg fields instead of using inheritance --- Transmission.xcodeproj/project.pbxproj | 6 + libtransmission/CMakeLists.txt | 6 +- libtransmission/crypto-utils-ccrypto.cc | 151 ++++++--------- libtransmission/crypto-utils-mbedtls.cc | 200 +++++++++----------- libtransmission/crypto-utils-openssl.cc | 242 ++++++++++-------------- libtransmission/crypto-utils-wolfssl.cc | 134 ++++++------- libtransmission/crypto-utils.h | 72 +++++-- libtransmission/handshake.cc | 6 +- libtransmission/inout.cc | 6 +- libtransmission/makemeta.cc | 8 +- libtransmission/verify.cc | 8 +- release/windows/build-openssl.ps1 | 2 +- release/windows/build-qt6.ps1 | 2 +- tests/libtransmission/CMakeLists.txt | 1 - tests/libtransmission/crypto-test-ref.h | 116 ------------ tests/libtransmission/crypto-test.cc | 17 +- 16 files changed, 392 insertions(+), 585 deletions(-) delete mode 100644 tests/libtransmission/crypto-test-ref.h diff --git a/Transmission.xcodeproj/project.pbxproj b/Transmission.xcodeproj/project.pbxproj index b535f65c1..f0503bcbf 100644 --- a/Transmission.xcodeproj/project.pbxproj +++ b/Transmission.xcodeproj/project.pbxproj @@ -3951,6 +3951,7 @@ "-DWIDE_INTEGER_DISABLE_IOSTREAM", "-DRAPIDJSON_HAS_STDSTRING=1", "-DHAVE_FLOCK", + "-DWITH_CCRYPTO", ); PRODUCT_NAME = transmission; SYSTEM_HEADER_SEARCH_PATHS = ( @@ -4137,6 +4138,7 @@ OTHER_CFLAGS = ( "$(inherited)", "-DFMT_HEADER_ONLY", + "-DWITH_CCRYPTO", ); OTHER_CPLUSPLUSFLAGS = "$(OTHER_CFLAGS)"; PRODUCT_BUNDLE_IDENTIFIER = org.m0k.transmission; @@ -4203,6 +4205,7 @@ "-DWIDE_INTEGER_DISABLE_IOSTREAM", "-DRAPIDJSON_HAS_STDSTRING=1", "-DHAVE_FLOCK", + "-DWITH_CCRYPTO", ); PRODUCT_NAME = transmission; SYSTEM_HEADER_SEARCH_PATHS = ( @@ -4343,6 +4346,7 @@ OTHER_CFLAGS = ( "$(inherited)", "-DFMT_HEADER_ONLY", + "-DWITH_CCRYPTO", "-DNDEBUG", ); OTHER_CPLUSPLUSFLAGS = "$(OTHER_CFLAGS)"; @@ -4446,6 +4450,7 @@ OTHER_CFLAGS = ( "$(inherited)", "-DFMT_HEADER_ONLY", + "-DWITH_CCRYPTO", ); OTHER_CPLUSPLUSFLAGS = "$(OTHER_CFLAGS)"; PRODUCT_BUNDLE_IDENTIFIER = org.m0k.transmission; @@ -4529,6 +4534,7 @@ "-DWIDE_INTEGER_DISABLE_IOSTREAM", "-DRAPIDJSON_HAS_STDSTRING=1", "-DHAVE_FLOCK", + "-DWITH_CCRYPTO", ); PRODUCT_NAME = transmission; SYSTEM_HEADER_SEARCH_PATHS = ( diff --git a/libtransmission/CMakeLists.txt b/libtransmission/CMakeLists.txt index 1a994780e..170760da8 100644 --- a/libtransmission/CMakeLists.txt +++ b/libtransmission/CMakeLists.txt @@ -226,6 +226,10 @@ target_compile_definitions(${TR_NAME} $<$:USE_SYSTEM_B64> $<$:HAVE_SO_REUSEPORT=1> PUBLIC + $<$:WITH_CCRYPTO> + $<$:WITH_MBEDTLS> + $<$:WITH_OPENSSL> + $<$:WITH_WOLFSSL> $<$>:DISABLE_GETTEXT>) tr_target_compile_definitions_for_headers(${TR_NAME} @@ -275,7 +279,6 @@ target_link_libraries(${TR_NAME} PRIVATE Threads::Threads deflate::deflate - transmission::crypto_impl CURL::libcurl FastFloat::fast_float psl::psl @@ -297,6 +300,7 @@ target_link_libraries(${TR_NAME} "$<$:-framework Foundation>" "$<$:${log-lib}>" PUBLIC + transmission::crypto_impl fmt::fmt-header-only small::small libevent::event) diff --git a/libtransmission/crypto-utils-ccrypto.cc b/libtransmission/crypto-utils-ccrypto.cc index ec3e2fb3a..ea05781a7 100644 --- a/libtransmission/crypto-utils-ccrypto.cc +++ b/libtransmission/crypto-utils-ccrypto.cc @@ -93,101 +93,72 @@ bool check_ccrypto_result(CCCryptorStatus result, char const* file, long line) } // namespace -// --- +// --- sha1 -namespace +tr_sha1::tr_sha1() { - -class Sha1Impl final : public tr_sha1 -{ -public: - Sha1Impl() - { - clear(); - } - - ~Sha1Impl() override = default; - - void clear() override - { - CC_SHA1_Init(&handle_); - } - - void add(void const* data, size_t data_length) override - { - static auto constexpr Max = static_cast(std::numeric_limits::max()); - auto const* sha_data = static_cast(data); - while (data_length > 0) - { - auto const n_bytes = static_cast(std::min(data_length, Max)); - CC_SHA1_Update(&handle_, sha_data, n_bytes); - data_length -= n_bytes; - sha_data += n_bytes; - } - } - - [[nodiscard]] tr_sha1_digest_t finish() override - { - auto digest = tr_sha1_digest_t{}; - CC_SHA1_Final(reinterpret_cast(std::data(digest)), &handle_); - clear(); - return digest; - } - -private: - CC_SHA1_CTX handle_ = {}; -}; - -class Sha256Impl final : public tr_sha256 -{ -public: - Sha256Impl() - { - clear(); - } - - ~Sha256Impl() override = default; - - void clear() override - { - CC_SHA256_Init(&handle_); - } - - void add(void const* data, size_t data_length) override - { - static auto constexpr Max = static_cast(std::numeric_limits::max()); - auto const* sha_data = static_cast(data); - while (data_length > 0) - { - auto const n_bytes = static_cast(std::min(data_length, Max)); - CC_SHA256_Update(&handle_, sha_data, n_bytes); - data_length -= n_bytes; - sha_data += n_bytes; - } - } - - [[nodiscard]] tr_sha256_digest_t finish() override - { - auto digest = tr_sha256_digest_t{}; - CC_SHA256_Final(reinterpret_cast(std::data(digest)), &handle_); - clear(); - return digest; - } - -private: - CC_SHA256_CTX handle_; -}; - -} // namespace - -std::unique_ptr tr_sha1::create() -{ - return std::make_unique(); + clear(); } -std::unique_ptr tr_sha256::create() +tr_sha1::~tr_sha1() { - return std::make_unique(); +} + +void tr_sha1::clear() +{ + CC_SHA1_Init(&handle_); +} + +void tr_sha1::add(void const* data, size_t data_length) +{ + if (data_length == 0U) + { + return; + } + + CC_SHA1_Update(&handle_, data, data_length); +} + +tr_sha1_digest_t tr_sha1::finish() +{ + auto digest = tr_sha1_digest_t{}; + CC_SHA1_Final(reinterpret_cast(std::data(digest)), &handle_); + clear(); + return digest; +} + +// --- sha256 + +tr_sha256::tr_sha256() +{ + clear(); +} + +tr_sha256::~tr_sha256() +{ +} + +void tr_sha256::clear() +{ + CC_SHA256_Init(&handle_); +} + +void tr_sha256::add(void const* data, size_t data_length) +{ + if (data_length == 0U) + { + return; + } + + CC_SHA256_Update(&handle_, data, data_length); +} + +tr_sha256_digest_t tr_sha256::finish() +{ + auto digest = tr_sha256_digest_t{}; + CC_SHA256_Final(reinterpret_cast(std::data(digest)), &handle_); + clear(); + return digest; } // --- diff --git a/libtransmission/crypto-utils-mbedtls.cc b/libtransmission/crypto-utils-mbedtls.cc index 9a4d4f4a8..d58e15598 100644 --- a/libtransmission/crypto-utils-mbedtls.cc +++ b/libtransmission/crypto-utils-mbedtls.cc @@ -25,6 +25,10 @@ #define TR_CRYPTO_X509_FALLBACK #include "libtransmission/crypto-utils-fallback.cc" // NOLINT(bugprone-suspicious-include) +#if !defined(WITH_MBEDTLS) +#error mbedtls module +#endif + namespace { void log_mbedtls_error(int error_code, char const* file, int line) @@ -99,120 +103,100 @@ mbedtls_ctr_drbg_context* get_rng() std::recursive_mutex rng_mutex_; -// --- - -class Sha1Impl final : public tr_sha1 -{ -public: - Sha1Impl() - { - clear(); - } - - ~Sha1Impl() override = default; - - void clear() override - { - mbedtls_sha1_init(&handle_); - -#if MBEDTLS_VERSION_NUMBER >= 0x02070000 - mbedtls_sha1_starts_ret(&handle_); -#else - mbedtls_sha1_starts(&handle_); -#endif - } - - void add(void const* data, size_t data_length) override - { - if (data_length > 0U) - { -#if MBEDTLS_VERSION_NUMBER >= 0x02070000 - mbedtls_sha1_update_ret(&handle_, static_cast(data), data_length); -#else - mbedtls_sha1_update(&handle_, static_cast(data), data_length); -#endif - } - } - - [[nodiscard]] tr_sha1_digest_t finish() override - { - auto digest = tr_sha1_digest_t{}; - auto* const digest_as_uchar = reinterpret_cast(std::data(digest)); -#if MBEDTLS_VERSION_NUMBER >= 0x02070000 - mbedtls_sha1_finish_ret(&handle_, digest_as_uchar); -#else - mbedtls_sha1_finish(&handle_, digest_as_uchar); -#endif - - mbedtls_sha1_free(&handle_); - return digest; - } - -private: - mbedtls_sha1_context handle_ = {}; -}; - -class Sha256Impl final : public tr_sha256 -{ -public: - Sha256Impl() - { - clear(); - } - - ~Sha256Impl() override = default; - - void clear() override - { - mbedtls_sha256_init(&handle_); - -#if MBEDTLS_VERSION_NUMBER >= 0x02070000 - mbedtls_sha256_starts_ret(&handle_, 0); -#else - mbedtls_sha256_starts(&handle_); -#endif - } - - void add(void const* data, size_t data_length) override - { - if (data_length > 0U) - { -#if MBEDTLS_VERSION_NUMBER >= 0x02070000 - mbedtls_sha256_update_ret(&handle_, static_cast(data), data_length); -#else - mbedtls_sha256_update(&handle_, static_cast(data), data_length); -#endif - } - } - - [[nodiscard]] tr_sha256_digest_t finish() override - { - auto digest = tr_sha256_digest_t{}; - auto* const digest_as_uchar = reinterpret_cast(std::data(digest)); -#if MBEDTLS_VERSION_NUMBER >= 0x02070000 - mbedtls_sha256_finish_ret(&handle_, digest_as_uchar); -#else - mbedtls_sha256_finish(&handle_, digest_as_uchar); -#endif - - mbedtls_sha256_free(&handle_); - return digest; - } - -private: - mbedtls_sha256_context handle_ = {}; -}; - } // namespace -std::unique_ptr tr_sha1::create() +// --- sha1 + +tr_sha1::tr_sha1() { - return std::make_unique(); + clear(); } -std::unique_ptr tr_sha256::create() +tr_sha1::~tr_sha1() = default; + +void tr_sha1::clear() { - return std::make_unique(); + mbedtls_sha1_init(&handle_); + +#if MBEDTLS_VERSION_NUMBER >= 0x02070000 + mbedtls_sha1_starts_ret(&handle_); +#else + mbedtls_sha1_starts(&handle_); +#endif +} + +void tr_sha1::add(void const* data, size_t data_length) +{ + if (data_length == 0U) + { + return; + } + +#if MBEDTLS_VERSION_NUMBER >= 0x02070000 + mbedtls_sha1_update_ret(&handle_, static_cast(data), data_length); +#else + mbedtls_sha1_update(&handle_, static_cast(data), data_length); +#endif +} + +tr_sha1_digest_t tr_sha1::finish() +{ + auto digest = tr_sha1_digest_t{}; + auto* const digest_as_uchar = reinterpret_cast(std::data(digest)); +#if MBEDTLS_VERSION_NUMBER >= 0x02070000 + mbedtls_sha1_finish_ret(&handle_, digest_as_uchar); +#else + mbedtls_sha1_finish(&handle_, digest_as_uchar); +#endif + clear(); + return digest; +} + +// --- sha256 + +tr_sha256::tr_sha256() +{ + clear(); +} + +tr_sha256::~tr_sha256() = default; + +void tr_sha256::clear() +{ + mbedtls_sha256_init(&handle_); + +#if MBEDTLS_VERSION_NUMBER >= 0x02070000 + mbedtls_sha256_starts_ret(&handle_, 0); +#else + mbedtls_sha256_starts(&handle_); +#endif +} + +void tr_sha256::add(void const* data, size_t data_length) +{ + if (data_length == 0U) + { + return; + } + +#if MBEDTLS_VERSION_NUMBER >= 0x02070000 + mbedtls_sha256_update_ret(&handle_, static_cast(data), data_length); +#else + mbedtls_sha256_update(&handle_, static_cast(data), data_length); +#endif +} + +tr_sha256_digest_t tr_sha256::finish() +{ + auto digest = tr_sha256_digest_t{}; + auto* const digest_as_uchar = reinterpret_cast(std::data(digest)); +#if MBEDTLS_VERSION_NUMBER >= 0x02070000 + mbedtls_sha256_finish_ret(&handle_, digest_as_uchar); +#else + mbedtls_sha256_finish(&handle_, digest_as_uchar); +#endif + clear(); + return digest; } // --- diff --git a/libtransmission/crypto-utils-openssl.cc b/libtransmission/crypto-utils-openssl.cc index 90e095ff6..494932e6b 100644 --- a/libtransmission/crypto-utils-openssl.cc +++ b/libtransmission/crypto-utils-openssl.cc @@ -29,37 +29,43 @@ #include "libtransmission/tr-macros.h" // tr_sha1_digest_t, tr_sha25... #include "libtransmission/utils.h" +#if !defined(WITH_OPENSSL) +#error OPENSSL module +#endif + namespace { void log_openssl_error(char const* file, int line) { - unsigned long const error_code = ERR_get_error(); - - if (tr_logLevelIsActive(TR_LOG_ERROR)) + if (!tr_logLevelIsActive(TR_LOG_ERROR)) + { + return; + } + + auto const error_code = ERR_get_error(); + + if (static bool strings_loaded = false; !strings_loaded) { - if (static bool strings_loaded = false; !strings_loaded) - { #if OPENSSL_VERSION_NUMBER < 0x10100000 || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000) - ERR_load_crypto_strings(); + ERR_load_crypto_strings(); #else - OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS, nullptr); + OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS, nullptr); #endif - strings_loaded = true; - } - - auto buf = std::array{}; - ERR_error_string_n(error_code, std::data(buf), std::size(buf)); - tr_logAddMessage( - file, - line, - TR_LOG_ERROR, - fmt::format( - _("{crypto_library} error: {error} ({error_code})"), - fmt::arg("crypto_library", "OpenSSL"), - fmt::arg("error", std::data(buf)), - fmt::arg("error_code", error_code))); + strings_loaded = true; } + + auto buf = std::array{}; + ERR_error_string_n(error_code, std::data(buf), std::size(buf)); + tr_logAddMessage( + file, + line, + TR_LOG_ERROR, + fmt::format( + _("{crypto_library} error: {error} ({error_code})"), + fmt::arg("crypto_library", "OpenSSL"), + fmt::arg("error", std::data(buf)), + fmt::arg("error_code", error_code))); } #define log_error() log_openssl_error(__FILE__, __LINE__) @@ -78,136 +84,84 @@ bool check_openssl_result(int result, int expected_result, bool expected_equal, #define check_result(result) check_openssl_result((result), 1, true, __FILE__, __LINE__) -namespace sha_helpers +void digest_add_bytes(EVP_MD_CTX* ctx, void const* data, size_t data_length) { - -class ShaHelper -{ -public: - using EvpFunc = decltype((EVP_sha1)); - - explicit ShaHelper(EvpFunc evp_func) - : evp_func_{ evp_func } + if (data_length != 0U) { - clear(); + EVP_DigestUpdate(ctx, data, data_length); } - - void clear() const - { - EVP_DigestInit_ex(handle_.get(), evp_func_(), nullptr); - } - - void update(void const* data, size_t data_length) const - { - if (data_length != 0U) - { - EVP_DigestUpdate(handle_.get(), data, data_length); - } - } - - template - [[nodiscard]] DigestType digest() - { - TR_ASSERT(handle_ != nullptr); - - unsigned int hash_length = 0; - auto digest = DigestType{}; - auto* const digest_as_uchar = reinterpret_cast(std::data(digest)); - [[maybe_unused]] bool const ok = check_result(EVP_DigestFinal_ex(handle_.get(), digest_as_uchar, &hash_length)); - TR_ASSERT(!ok || hash_length == std::size(digest)); - - clear(); - return digest; - } - -private: - struct MessageDigestDeleter - { - void operator()(EVP_MD_CTX* ctx) const noexcept - { - EVP_MD_CTX_destroy(ctx); - } - }; - - EvpFunc evp_func_; - std::unique_ptr const handle_{ EVP_MD_CTX_create() }; -}; - -class Sha1Impl final : public tr_sha1 -{ -public: - Sha1Impl() = default; - Sha1Impl(Sha1Impl&&) = delete; - Sha1Impl(Sha1Impl const&) = delete; - ~Sha1Impl() override = default; - Sha1Impl& operator=(Sha1Impl&&) = delete; - Sha1Impl& operator=(Sha1Impl const&) = delete; - - void clear() override - { - helper_.clear(); - } - - void add(void const* data, size_t data_length) override - { - helper_.update(data, data_length); - } - - [[nodiscard]] tr_sha1_digest_t finish() override - { - return helper_.digest(); - } - -private: - ShaHelper helper_{ EVP_sha1 }; -}; - -class Sha256Impl final : public tr_sha256 -{ -public: - Sha256Impl() = default; - Sha256Impl(Sha256Impl&&) = delete; - Sha256Impl(Sha256Impl const&) = delete; - ~Sha256Impl() override = default; - Sha256Impl& operator=(Sha256Impl&&) = delete; - Sha256Impl& operator=(Sha256Impl const&) = delete; - - void clear() override - { - helper_.clear(); - } - - void add(void const* data, size_t data_length) override - { - helper_.update(data, data_length); - } - - [[nodiscard]] tr_sha256_digest_t finish() override - { - return helper_.digest(); - } - -private: - ShaHelper helper_{ EVP_sha256 }; -}; - -} // namespace sha_helpers -} // namespace - -// --- sha - -std::unique_ptr tr_sha1::create() -{ - using namespace sha_helpers; - - return std::make_unique(); } -std::unique_ptr tr_sha256::create() +template +DigestType digest_finish(EVP_MD_CTX* ctx) { - using namespace sha_helpers; + unsigned int hash_length = 0; + auto digest = DigestType{}; + auto* const digest_as_uchar = reinterpret_cast(std::data(digest)); + [[maybe_unused]] bool const ok = check_result(EVP_DigestFinal_ex(ctx, digest_as_uchar, &hash_length)); + TR_ASSERT(!ok || hash_length == std::size(digest)); + return digest; +} +} // namespace - return std::make_unique(); +// --- sha1 + +tr_sha1::tr_sha1() + : handle_{ EVP_MD_CTX_create() } +{ + clear(); +} + +tr_sha1::~tr_sha1() +{ + EVP_MD_CTX_destroy(handle_); +} + +void tr_sha1::clear() +{ + EVP_DigestInit_ex(handle_, EVP_sha1(), nullptr); +} + +void tr_sha1::add(void const* data, size_t data_length) +{ + digest_add_bytes(handle_, data, data_length); +} + +tr_sha1_digest_t tr_sha1::finish() +{ + auto digest = digest_finish(handle_); + clear(); + return digest; +} + +// --- sha256 + +tr_sha256::tr_sha256() + : handle_{ EVP_MD_CTX_create() } +{ + clear(); +} + +tr_sha256::~tr_sha256() +{ + EVP_MD_CTX_destroy(handle_); +} + +void tr_sha256::clear() +{ + EVP_DigestInit_ex(handle_, EVP_sha256(), nullptr); +} + +void tr_sha256::add(void const* data, size_t data_length) +{ + digest_add_bytes(handle_, data, data_length); +} + +tr_sha256_digest_t tr_sha256::finish() +{ + auto digest = digest_finish(handle_); + clear(); + return digest; } // --- x509 diff --git a/libtransmission/crypto-utils-wolfssl.cc b/libtransmission/crypto-utils-wolfssl.cc index 5f1b40108..6bfafdef6 100644 --- a/libtransmission/crypto-utils-wolfssl.cc +++ b/libtransmission/crypto-utils-wolfssl.cc @@ -22,6 +22,10 @@ #include "libtransmission/tr-assert.h" #include "libtransmission/utils.h" +#ifndef WITH_WOLFSSL +#error wolfssl module +#endif + #if LIBWOLFSSL_VERSION_HEX >= 0x04000000 // 4.0.0 using TR_WC_RNG = WC_RNG; #else @@ -85,88 +89,66 @@ TR_WC_RNG* get_rng() std::mutex rng_mutex_; -// --- - -class Sha1Impl final : public tr_sha1 -{ -public: - Sha1Impl() - { - clear(); - } - - ~Sha1Impl() override = default; - - void clear() override - { - wc_InitSha(&handle_); - } - - void add(void const* data, size_t data_length) override - { - if (data_length > 0U) - { - wc_ShaUpdate(&handle_, static_cast(data), data_length); - } - } - - [[nodiscard]] tr_sha1_digest_t finish() override - { - auto digest = tr_sha1_digest_t{}; - wc_ShaFinal(&handle_, reinterpret_cast(std::data(digest))); - clear(); - return digest; - } - -private: - wc_Sha handle_ = {}; -}; - -class Sha256Impl final : public tr_sha256 -{ -public: - Sha256Impl() - { - clear(); - } - - ~Sha256Impl() override = default; - - void clear() override - { - wc_InitSha256(&handle_); - } - - void add(void const* data, size_t data_length) override - { - if (data_length > 0U) - { - wc_Sha256Update(&handle_, static_cast(data), data_length); - } - } - - [[nodiscard]] tr_sha256_digest_t finish() override - { - auto digest = tr_sha256_digest_t{}; - wc_Sha256Final(&handle_, reinterpret_cast(std::data(digest))); - clear(); - return digest; - } - -private: - wc_Sha256 handle_ = {}; -}; - } // namespace -std::unique_ptr tr_sha1::create() +// --- sha1 + +tr_sha1::tr_sha1() { - return std::make_unique(); + clear(); } -std::unique_ptr tr_sha256::create() +tr_sha1::~tr_sha1() = default; + +void tr_sha1::clear() { - return std::make_unique(); + wc_InitSha(&handle_); +} + +void tr_sha1::add(void const* data, size_t data_length) +{ + if (data_length > 0U) + { + wc_ShaUpdate(&handle_, static_cast(data), data_length); + } +} + +tr_sha1_digest_t tr_sha1::finish() +{ + auto digest = tr_sha1_digest_t{}; + wc_ShaFinal(&handle_, reinterpret_cast(std::data(digest))); + clear(); + return digest; +} + +// --- sha256 + +tr_sha256::tr_sha256() +{ + clear(); +} + +tr_sha256::~tr_sha256() = default; + +void tr_sha256::clear() +{ + wc_InitSha256(&handle_); +} + +void tr_sha256::add(void const* data, size_t data_length) +{ + if (data_length > 0U) + { + wc_Sha256Update(&handle_, static_cast(data), data_length); + } +} + +tr_sha256_digest_t tr_sha256::finish() +{ + auto digest = tr_sha256_digest_t{}; + wc_Sha256Final(&handle_, reinterpret_cast(std::data(digest))); + clear(); + return digest; } // --- diff --git a/libtransmission/crypto-utils.h b/libtransmission/crypto-utils.h index c99caf9bc..6736b7f78 100644 --- a/libtransmission/crypto-utils.h +++ b/libtransmission/crypto-utils.h @@ -19,6 +19,28 @@ #include "libtransmission/tr-macros.h" // tr_sha1_digest_t, tr_sha256_d... #include "libtransmission/tr-strbuf.h" +#if defined(WITH_CCRYPTO) +#include +using tr_sha1_context_t = CC_SHA1_CTX; +using tr_sha256_context_t = CC_SHA256_CTX; +#elif defined(WITH_MBEDTLS) +#include +#include +using tr_sha1_context_t = mbedtls_sha1_context; +using tr_sha256_context_t = mbedtls_sha256_context; +#elif defined(WITH_OPENSSL) +#include +using tr_sha1_context_t = EVP_MD_CTX*; +using tr_sha256_context_t = EVP_MD_CTX*; +#elif defined(WITH_WOLFSSL) +#include +#include +using tr_sha1_context_t = wc_Sha; +using tr_sha256_context_t = wc_Sha256; +#else +#error no crypto library specified +#endif + /** * @addtogroup utils Utilities * @{ @@ -27,39 +49,53 @@ class tr_sha1 { public: - static std::unique_ptr create(); - virtual ~tr_sha1() = default; + tr_sha1(); + tr_sha1(tr_sha1&&) = delete; + tr_sha1(tr_sha1 const&) = delete; + tr_sha1& operator=(tr_sha1&&) = delete; + tr_sha1& operator=(tr_sha1 const&) = delete; + ~tr_sha1(); - virtual void clear() = 0; - virtual void add(void const* data, size_t data_length) = 0; - [[nodiscard]] virtual tr_sha1_digest_t finish() = 0; + void add(void const* data, size_t data_length); + [[nodiscard]] tr_sha1_digest_t finish(); + void clear(); template - [[nodiscard]] static tr_sha1_digest_t digest(T const&... args) + [[nodiscard]] static auto digest(T const&... args) { - auto context = tr_sha1::create(); - (context->add(std::data(args), std::size(args)), ...); - return context->finish(); + auto context = tr_sha1{}; + (context.add(std::data(args), std::size(args)), ...); + return context.finish(); } + +private: + tr_sha1_context_t handle_; }; class tr_sha256 { public: - static std::unique_ptr create(); - virtual ~tr_sha256() = default; + tr_sha256(); + tr_sha256(tr_sha256&&) = delete; + tr_sha256(tr_sha256 const&) = delete; + tr_sha256& operator=(tr_sha256&&) = delete; + tr_sha256& operator=(tr_sha256 const&) = delete; + ~tr_sha256(); - virtual void clear() = 0; - virtual void add(void const* data, size_t data_length) = 0; - [[nodiscard]] virtual tr_sha256_digest_t finish() = 0; + void add(void const* data, size_t data_length); + [[nodiscard]] tr_sha256_digest_t finish(); + void clear(); template - [[nodiscard]] static tr_sha256_digest_t digest(T const&... args) + [[nodiscard]] static auto digest(T const&... args) { - auto context = tr_sha256::create(); - (context->add(std::data(args), std::size(args)), ...); - return context->finish(); + auto context = tr_sha256{}; + (context.add(std::data(args), std::size(args)), ...); + return context.finish(); } + +private: + tr_sha256_context_t handle_; }; /** @brief Opaque SSL context type. */ diff --git a/libtransmission/handshake.cc b/libtransmission/handshake.cc index 958e12a2d..0753136c6 100644 --- a/libtransmission/handshake.cc +++ b/libtransmission/handshake.cc @@ -33,7 +33,7 @@ tr_logAddTrace(msg, fmt::format("handshake {}", (handshake)->peer_io_->display_name())) using namespace std::literals; -using DH = tr_message_stream_encryption::DH; +using key_bigend_t = tr_message_stream_encryption::DH::key_bigend_t; // --- Outgoing Connections @@ -60,7 +60,7 @@ ReadState tr_handshake::read_yb(tr_peerIo* peer_io) return READ_NOW; } - auto peer_public_key = DH::key_bigend_t{}; + auto peer_public_key = key_bigend_t{}; tr_logAddTraceHand( this, fmt::format("in read_yb... need {}, have {}", std::size(peer_public_key), peer_io->read_buffer_size())); @@ -354,7 +354,7 @@ ReadState tr_handshake::read_ya(tr_peerIo* peer_io) return READ_NOW; } - auto peer_public_key = DH::key_bigend_t{}; + auto peer_public_key = key_bigend_t{}; tr_logAddTraceHand( this, fmt::format("in read_ya... need {}, have {}", std::size(peer_public_key), peer_io->read_buffer_size())); diff --git a/libtransmission/inout.cc b/libtransmission/inout.cc index 747e303bf..604a9251e 100644 --- a/libtransmission/inout.cc +++ b/libtransmission/inout.cc @@ -207,7 +207,7 @@ std::optional recalculate_hash(tr_torrent const& tor, tr_piece { TR_ASSERT(piece < tor.piece_count()); - auto sha = tr_sha1::create(); + auto sha = tr_sha1{}; auto buffer = std::array{}; auto& cache = tor.session->cache; @@ -236,12 +236,12 @@ std::optional recalculate_hash(tr_torrent const& tor, tr_piece end -= (block_loc.byte + block_len - end_byte); } - sha->add(begin, end - begin); + sha.add(begin, end - begin); n_bytes_checked += (end - begin); } TR_ASSERT(tor.piece_size(piece) == n_bytes_checked); - return sha->finish(); + return sha.finish(); } } // namespace diff --git a/libtransmission/makemeta.cc b/libtransmission/makemeta.cc index 9730af471..11c03fc67 100644 --- a/libtransmission/makemeta.cc +++ b/libtransmission/makemeta.cc @@ -165,7 +165,7 @@ bool tr_metainfo_builder::blocking_make_checksums(tr_error* error) auto hashes = std::vector(std::size(tr_sha1_digest_t{}) * piece_count()); auto* walk = std::data(hashes); - auto sha = tr_sha1::create(); + auto sha = tr_sha1{}; auto file_index = tr_file_index_t{ 0U }; auto piece_index = tr_piece_index_t{ 0U }; @@ -229,10 +229,10 @@ bool tr_metainfo_builder::blocking_make_checksums(tr_error* error) TR_ASSERT(bufptr - std::data(buf) == (int)piece_size); TR_ASSERT(left_in_piece == 0); - sha->add(std::data(buf), std::size(buf)); - auto const digest = sha->finish(); + sha.add(std::data(buf), std::size(buf)); + auto const digest = sha.finish(); walk = std::copy(std::begin(digest), std::end(digest), walk); - sha->clear(); + sha.clear(); total_remain -= piece_size; ++piece_index; diff --git a/libtransmission/verify.cc b/libtransmission/verify.cc index 78a134658..839fefa2e 100644 --- a/libtransmission/verify.cc +++ b/libtransmission/verify.cc @@ -45,7 +45,7 @@ void tr_verify_worker::verify_torrent( tr_file_index_t prev_file_index = ~file_index; tr_piece_index_t piece = 0U; auto buffer = std::vector(1024U * 256U); - auto sha = tr_sha1::create(); + auto sha = tr_sha1{}; auto last_slept_at = current_time_secs(); auto const& metainfo = verify_mediator.metainfo(); @@ -74,7 +74,7 @@ void tr_verify_worker::verify_torrent( if (tr_sys_file_read_at(fd, std::data(buffer), bytes_this_pass, file_pos, &num_read) && num_read > 0U) { bytes_this_pass = num_read; - sha->add(std::data(buffer), bytes_this_pass); + sha.add(std::data(buffer), bytes_this_pass); } } @@ -87,7 +87,7 @@ void tr_verify_worker::verify_torrent( /* if we're finishing a piece... */ if (left_in_piece == 0U) { - auto const has_piece = sha->finish() == metainfo.piece_hash(piece); + auto const has_piece = sha.finish() == metainfo.piece_hash(piece); verify_mediator.on_piece_checked(piece, has_piece); if (sleep_per_seconds_during_verify > std::chrono::milliseconds::zero()) @@ -101,7 +101,7 @@ void tr_verify_worker::verify_torrent( } } - sha->clear(); + sha.clear(); ++piece; piece_pos = 0U; } diff --git a/release/windows/build-openssl.ps1 b/release/windows/build-openssl.ps1 index 5350df10a..c220798d4 100644 --- a/release/windows/build-openssl.ps1 +++ b/release/windows/build-openssl.ps1 @@ -1,6 +1,6 @@ #!/usr/bin/env pwsh -$global:OpenSslVersion = '3.1.4' +$global:OpenSslVersion = '3.1.5' $global:OpenSslDeps = @() diff --git a/release/windows/build-qt6.ps1 b/release/windows/build-qt6.ps1 index af2e1a275..96b1389d3 100644 --- a/release/windows/build-qt6.ps1 +++ b/release/windows/build-qt6.ps1 @@ -1,6 +1,6 @@ #!/usr/bin/env pwsh -$global:Qt6Version = '6.6.0' +$global:Qt6Version = '6.6.2' $global:Qt6Deps = @( 'DBus' diff --git a/tests/libtransmission/CMakeLists.txt b/tests/libtransmission/CMakeLists.txt index 2040575ff..a90afe2f7 100644 --- a/tests/libtransmission/CMakeLists.txt +++ b/tests/libtransmission/CMakeLists.txt @@ -15,7 +15,6 @@ target_sources(libtransmission-test clients-test.cc completion-test.cc copy-test.cc - crypto-test-ref.h crypto-test.cc error-test.cc dht-test.cc diff --git a/tests/libtransmission/crypto-test-ref.h b/tests/libtransmission/crypto-test-ref.h deleted file mode 100644 index cbbe00cea..000000000 --- a/tests/libtransmission/crypto-test-ref.h +++ /dev/null @@ -1,116 +0,0 @@ -// This file Copyright (C) 2015-2022 Mnemosyne LLC. -// It may be used under GPLv2 (SPDX: GPL-2.0-only), GPLv3 (SPDX: GPL-3.0-only), -// or any future license endorsed by Mnemosyne LLC. -// License text can be found in the licenses/ folder. - -#ifndef TR_CRYPTO_TEST_REF_H -#define TR_CRYPTO_TEST_REF_H - -/* #define CRYPTO_REFERENCE_CHECK */ - -#ifdef CRYPTO_REFERENCE_CHECK - -#define tr_base64_decode tr_base64_decode_ -#define tr_base64_decode_impl tr_base64_decode_impl_ -#define tr_base64_encode tr_base64_encode_ -#define tr_base64_encode_impl tr_base64_encode_impl_ -#define tr_rand_buffer tr_rand_buffer_ -#define tr_rand_buffer_crypto tr_rand_buffer_crypto_ -#define tr_rand_buffer_std tr_rand_buffer_std_ -#define tr_rand_int tr_rand_int_ -#define tr_rand_obj tr_rand_obj_ -#define tr_salt_shaker tr_salt_shaker_ -#define tr_sha1 tr_sha1_ -#define tr_sha1_from_string tr_sha1_from_string_ -#define tr_sha1_to_string tr_sha1_to_string_ -#define tr_sha256 tr_sha256_ -#define tr_sha256_from_string tr_sha256_from_string_ -#define tr_sha256_to_string tr_sha256_to_string_ -#define tr_ssha1 tr_ssha1_ -#define tr_ssha1_matches tr_ssha1_matches_ -#define tr_ssha1_test tr_ssha1_test_ -#define tr_ssl_ctx_t tr_ssl_ctx_t_ -#define tr_ssl_get_x509_store tr_ssl_get_x509_store_ -#define tr_urbg tr_urbg_ -#define tr_x509_cert_free tr_x509_cert_free_ -#define tr_x509_cert_new tr_x509_cert_new_ -#define tr_x509_cert_t tr_x509_cert_t_ -#define tr_x509_store_add tr_x509_store_add_ -#define tr_x509_store_t tr_x509_store_t_ - -#undef TR_ENCRYPTION_H -#undef TR_CRYPTO_UTILS_H - -#include -#include -#include - -#undef tr_base64_decode -#undef tr_base64_decode_impl -#undef tr_base64_encode -#undef tr_base64_encode_impl -#undef tr_rand_buffer -#undef tr_rand_buffer_crypto -#undef tr_rand_buffer_std -#undef tr_rand_int -#undef tr_rand_obj -#undef tr_salt_shaker -#undef tr_sha1 -#undef tr_sha1_from_string -#undef tr_sha1_to_string -#undef tr_sha256 -#undef tr_sha256_from_string -#undef tr_sha256_to_string -#undef tr_ssha1 -#undef tr_ssha1_matches -#undef tr_ssha1_test -#undef tr_ssl_ctx_t -#undef tr_ssl_get_x509_store -#undef tr_urbg -#undef tr_x509_cert_free -#undef tr_x509_cert_new -#undef tr_x509_cert_t -#undef tr_x509_store_add -#undef tr_x509_store_t - -#else /* CRYPTO_REFERENCE_CHECK */ - -#define tr_base64_decode_ tr_base64_decode -#define tr_base64_decode_impl_ tr_base64_decode_impl -#define tr_base64_encode_ tr_base64_encode -#define tr_base64_encode_impl_ tr_base64_encode_impl -#define tr_rand_buffer_ tr_rand_buffer -#define tr_rand_buffer_crypto_ tr_rand_buffer_crypto -#define tr_rand_buffer_std_ tr_rand_buffer_std -#define tr_rand_int_ tr_rand_int -#define tr_rand_obj_ tr_rand_obj -#define tr_salt_shaker_ tr_salt_shaker -#define tr_sha1_ tr_sha1 -#define tr_sha1_ctx_t_ tr_sha1_ctx_t -#define tr_sha1_final_ tr_sha1_final -#define tr_sha1_from_string_ tr_sha1_from_string -#define tr_sha1_init_ tr_sha1_init -#define tr_sha1_to_string_ tr_sha1_to_string -#define tr_sha1_update_ tr_sha1_update -#define tr_sha256_ tr_sha256 -#define tr_sha256_ctx_t_ tr_sha256_ctx_t -#define tr_sha256_final_ tr_sha256_final -#define tr_sha256_from_string_ tr_sha256_from_string -#define tr_sha256_init_ tr_sha256_init -#define tr_sha256_to_string_ tr_sha256_to_string -#define tr_sha256_update_ tr_sha256_update -#define tr_ssha1_ tr_ssha1 -#define tr_ssha1_matches_ tr_ssha1_matches -#define tr_ssha1_test_ tr_ssha1_test -#define tr_ssl_ctx_t_ tr_ssl_ctx_t -#define tr_ssl_get_x509_store_ tr_ssl_get_x509_store -#define tr_urbg_ tr_urbg -#define tr_x509_cert_free_ tr_x509_cert_free -#define tr_x509_cert_new_ tr_x509_cert_new -#define tr_x509_cert_t_ tr_x509_cert_t -#define tr_x509_store_add_ tr_x509_store_add -#define tr_x509_store_t_ tr_x509_store_t - -#endif /* CRYPTO_REFERENCE_CHECK */ - -#endif /* TR_CRYPTO_TEST_REF_H */ diff --git a/tests/libtransmission/crypto-test.cc b/tests/libtransmission/crypto-test.cc index 72331e9eb..c1fa8e5e4 100644 --- a/tests/libtransmission/crypto-test.cc +++ b/tests/libtransmission/crypto-test.cc @@ -18,8 +18,6 @@ #include #include -#include "crypto-test-ref.h" - #include "gtest/gtest.h" using namespace std::literals; @@ -150,19 +148,11 @@ TEST(Crypto, ssha1) hashes.reserve(HashCount); EXPECT_TRUE(tr_ssha1_matches(ssha1, plain_text)); - EXPECT_TRUE(tr_ssha1_matches_(ssha1, plain_text)); - - using ssha1_func = std::string (*)(std::string_view plain_text); - static auto constexpr Ssha1Funcs = std::array{ tr_ssha1, tr_ssha1_ }; for (size_t j = 0; j < HashCount; ++j) { - auto const hash = Ssha1Funcs[j % 2](plain_text); - - // phrase matches each of generated hashes + auto const hash = tr_ssha1(plain_text); EXPECT_TRUE(tr_ssha1_matches(hash, plain_text)); - EXPECT_TRUE(tr_ssha1_matches_(hash, plain_text)); - hashes.insert(hash); } @@ -171,15 +161,12 @@ TEST(Crypto, ssha1) /* exchange two first chars */ auto phrase = std::string{ plain_text }; - phrase[0] ^= phrase[1]; - phrase[1] ^= phrase[0]; - phrase[0] ^= phrase[1]; + std::swap(phrase[0], phrase[1]); for (auto const& hash : hashes) { /* changed phrase doesn't match the hashes */ EXPECT_FALSE(tr_ssha1_matches(hash, phrase)); - EXPECT_FALSE(tr_ssha1_matches_(hash, phrase)); } }