reapack

Package manager for REAPER
Log | Files | Refs | Submodules | README | LICENSE

commit ae5f85ee913ad86b5e0d2c9e56bdb3ad7fae685b
parent 0c37d1a43650261685c1cea2c87adf7487f3c40b
Author: cfillion <cfillion@users.noreply.github.com>
Date:   Sun,  8 May 2022 11:01:52 -0400

add support for Linux systems shipping with OpenSSL 3

Fixes #47

Diffstat:
M.appveyor.yml | 1+
MCMakeLists.txt | 3+++
Msrc/CMakeLists.txt | 6+++++-
Msrc/hash.cpp | 130+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
Msrc/hash.hpp | 1+
5 files changed, 131 insertions(+), 10 deletions(-)

diff --git a/.appveyor.yml b/.appveyor.yml @@ -10,6 +10,7 @@ build_script: -DCMAKE_TOOLCHAIN_FILE=~/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=arch-env -DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=$TOOLCHAIN -DCMAKE_OSX_ARCHITECTURES=$ARCH -DCMAKE_OSX_DEPLOYMENT_TARGET=$DEPLOY_TARGET + -DRUNTIME_OPENSSL=YES - cmake --build build test_script: diff --git a/CMakeLists.txt b/CMakeLists.txt @@ -1,5 +1,8 @@ cmake_minimum_required(VERSION 3.15) +option(RUNTIME_OPENSSL + "Load OpenSSL at runtime instead of linking against a specific version" OFF) + if(DEFINED ENV{VCPKG_ROOT} AND NOT DEFINED CMAKE_TOOLCHAIN_FILE) set(CMAKE_TOOLCHAIN_FILE "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" CACHE STRING "") diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt @@ -139,7 +139,11 @@ target_link_libraries(reapack ) if(OPENSSL_FOUND) - target_link_libraries(reapack OpenSSL::Crypto) + if(RUNTIME_OPENSSL) + target_compile_definitions(reapack PRIVATE RUNTIME_OPENSSL) + else() + target_link_libraries(reapack OpenSSL::Crypto) + endif() endif() if(SWELL_FOUND) diff --git a/src/hash.cpp b/src/hash.cpp @@ -111,14 +111,9 @@ private: unsigned long m_hashLength; }; -#else // Unix systems - -# ifdef __APPLE__ -# define COMMON_DIGEST_FOR_OPENSSL -# include <CommonCrypto/CommonDigest.h> -# else -# include <openssl/sha.h> -# endif +#elif __APPLE__ +# define COMMON_DIGEST_FOR_OPENSSL +# include <CommonCrypto/CommonDigest.h> class Hash::SHA256Context : public Hash::Context { public: @@ -146,6 +141,120 @@ private: SHA256_CTX m_context; }; +#else +# include <openssl/evp.h> + +# ifdef RUNTIME_OPENSSL +# include <dlfcn.h> + +static struct OpenSSL { + OpenSSL() + : m_loaded { true } + { + constexpr const char *names[] { "libcrypto.so.3", "libcrypto.so.1.1" }; + + for(const char *name : names) { + if((m_so = dlopen(name, RTLD_LAZY))) + return; + } + + m_loaded = false; + } + + ~OpenSSL() + { + if(m_so) + dlclose(m_so); + } + + bool isLoaded() const { return m_loaded; } + + template<typename T> T get(const char *name) + { + const T func { m_so ? reinterpret_cast<T>(dlsym(m_so, name)) : nullptr }; + if(!func) + m_loaded = false; + return func; + } + +private: + void *m_so; + bool m_loaded; +} g_openssl; + +# define IMPORT_OPENSSL(func) \ + static auto _##func { g_openssl.get<decltype(&func)>(#func) }; + +IMPORT_OPENSSL(EVP_DigestFinal_ex); +# define EVP_DigestFinal_ex _EVP_DigestFinal_ex +IMPORT_OPENSSL(EVP_DigestInit_ex); +# define EVP_DigestInit_ex _EVP_DigestInit_ex +IMPORT_OPENSSL(EVP_DigestUpdate); +# define EVP_DigestUpdate _EVP_DigestUpdate +IMPORT_OPENSSL(EVP_MD_CTX_new); +# define EVP_MD_CTX_new _EVP_MD_CTX_new +IMPORT_OPENSSL(EVP_MD_CTX_free); +# define EVP_MD_CTX_free _EVP_MD_CTX_free +# ifdef EVP_MD_size // OpenSSL 3 +IMPORT_OPENSSL(EVP_MD_get_size); +# undef EVP_MD_size +# define EVP_MD_size _EVP_MD_get_size +# else +IMPORT_OPENSSL(EVP_MD_size); +# define EVP_MD_size _EVP_MD_size +# endif +IMPORT_OPENSSL(EVP_sha256); +# define EVP_sha256 _EVP_sha256 +# endif + +class Hash::EVPContext : public Hash::Context { +public: + static const EVP_MD *getAlgo(const Algorithm algo) + { +#ifdef RUNTIME_OPENSSL + if(!g_openssl.isLoaded()) + return nullptr; +#endif + + switch(algo) { + case SHA256: + return EVP_sha256(); + default: + return nullptr; + } + } + + EVPContext(const EVP_MD *md) + : m_md { md } + { + m_ctx = EVP_MD_CTX_new(); + EVP_DigestInit_ex(m_ctx, m_md, nullptr); + } + + ~EVPContext() + { + EVP_MD_CTX_free(m_ctx); + } + + size_t hashSize() const override + { + return EVP_MD_size(m_md); + } + + void addData(const char *data, const size_t len) override + { + EVP_DigestUpdate(m_ctx, data, len); + } + + void getHash(unsigned char *out) override + { + EVP_DigestFinal_ex(m_ctx, out, nullptr); + } + +private: + EVP_MD_CTX *m_ctx; + const EVP_MD *m_md; +}; #endif Hash::Hash(const Algorithm algo) @@ -154,12 +263,15 @@ Hash::Hash(const Algorithm algo) #ifdef _WIN32 if(const auto &algoProvider = CNGAlgorithmProvider::get(algo)) m_context = std::make_unique<CNGContext>(algoProvider); -#else +#elif __APPLE__ switch(algo) { case SHA256: m_context = std::make_unique<SHA256Context>(); break; } +#else + if(const auto &algoDesc = EVPContext::getAlgo(algo)) + m_context = std::make_unique<EVPContext>(algoDesc); #endif } diff --git a/src/hash.hpp b/src/hash.hpp @@ -46,6 +46,7 @@ private: class CNGContext; class SHA256Context; + class EVPContext; Algorithm m_algo; std::string m_value;