diff options
| author | Julian Andres Klode <julian.klode@canonical.com> | 2024-12-18 19:37:40 +0100 |
|---|---|---|
| committer | Julian Andres Klode <julian.klode@canonical.com> | 2024-12-22 22:55:39 +0100 |
| commit | 90270f0959d490d56db891809d83c91b3d4b9bf0 (patch) | |
| tree | 80589894ae2a0eda080b6c6cf416882b52eaef7d /apt-pkg | |
| parent | 470f5cf449ac20c7d7bf50ad805c72a5f52d256f (diff) | |
hashes, methods: Add OpenSSL backends
Introduce an OpenSSL::Crypto backend for the hashes library
and an OpenSSL::SSL backend for the TLS support in our https
method.
Many thanks to curl for showing the way with how to handle
a CRL file. There are some memory leaks here with the
TlsFd itself as well as the proxy support; and we should
reorganize the code to generate the ssl object as late
as possible.
A peculiar aspect of OpenSSL is that SSL_has_pending() returns
1 even if SSL_read() will fail to read anything and return the
equivalent of EAGAIN. We work around this here by also peeking
ahead 1 byte. I was running a very high RTT connection from
Germany to Australia for testing, and with the peeking it's
using negligible amounts of CPU; before that, it was busy
looping at 100%. Bad OpenSSL!
Diffstat (limited to 'apt-pkg')
| -rw-r--r-- | apt-pkg/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | apt-pkg/contrib/hashes.cc | 73 |
2 files changed, 73 insertions, 2 deletions
diff --git a/apt-pkg/CMakeLists.txt b/apt-pkg/CMakeLists.txt index c68b7bddc..88f07fb79 100644 --- a/apt-pkg/CMakeLists.txt +++ b/apt-pkg/CMakeLists.txt @@ -56,6 +56,7 @@ target_include_directories(apt-pkg $<$<BOOL:${UDEV_FOUND}>:${UDEV_INCLUDE_DIRS}> $<$<BOOL:${SYSTEMD_FOUND}>:${SYSTEMD_INCLUDE_DIRS}> ${ICONV_INCLUDE_DIRS} + $<$<BOOL:${WITH_OPENSSL}>:${OPENSSL_INCLUDE_DIRS}> $<$<BOOL:${GNUTLS_FOUND}>:${GNUTLS_INCLUDE_DIRS}> $<$<BOOL:${GCRYPT_FOUND}>:${GCRYPT_INCLUDE_DIRS}> $<$<BOOL:${XXHASH_FOUND}>:${XXHASH_INCLUDE_DIRS}> @@ -72,6 +73,7 @@ target_link_libraries(apt-pkg $<$<BOOL:${UDEV_FOUND}>:${UDEV_LIBRARIES}> $<$<BOOL:${SYSTEMD_FOUND}>:${SYSTEMD_LIBRARIES}> ${ICONV_LIBRARIES} + $<$<BOOL:${WITH_OPENSSL}>:OpenSSL::Crypto> $<$<BOOL:${GNUTLS_FOUND}>:${GNUTLS_LIBRARIES}> $<$<BOOL:${GCRYPT_FOUND}>:${GCRYPT_LIBRARIES}> $<$<BOOL:${XXHASH_FOUND}>:${XXHASH_LIBRARIES}> diff --git a/apt-pkg/contrib/hashes.cc b/apt-pkg/contrib/hashes.cc index 033cd0845..664ad0ac7 100644 --- a/apt-pkg/contrib/hashes.cc +++ b/apt-pkg/contrib/hashes.cc @@ -30,7 +30,9 @@ #include <string> #include <unistd.h> -#ifdef HAVE_GNUTLS +#if defined(WITH_OPENSSL) +#include <openssl/evp.h> +#elif defined(HAVE_GNUTLS) #include <gnutls/crypto.h> #else #include <gcrypt.h> @@ -329,7 +331,74 @@ class PrivateHashes unsigned long long FileSize{0}; private: -#ifdef HAVE_GNUTLS +#if defined(WITH_OPENSSL) + std::array<EVP_MD_CTX *, 4> contexts{}; + + public: + struct HashAlgo + { + size_t index; + const char *name; + const EVP_MD *(*evpLink)(void); + Hashes::SupportedHashes ourAlgo; + }; + + static constexpr std::array<HashAlgo, 4> Algorithms{ + HashAlgo{0, "MD5Sum", EVP_md5, Hashes::MD5SUM}, + HashAlgo{1, "SHA1", EVP_sha1, Hashes::SHA1SUM}, + HashAlgo{2, "SHA256", EVP_sha256, Hashes::SHA256SUM}, + HashAlgo{3, "SHA512", EVP_sha512, Hashes::SHA512SUM}, + }; + + bool Write(unsigned char const *Data, size_t Size) + { + for (auto &context : contexts) + { + if (context) + EVP_DigestUpdate(context, Data, Size); + } + return true; + } + + std::string HexDigest(HashAlgo const &algo) + { + auto Size = EVP_MD_size(algo.evpLink()); + unsigned char Sum[Size]; + + // We need to work on a copy, as we update the hash after creating a digest... + auto tmpContext = EVP_MD_CTX_create(); + EVP_MD_CTX_copy(tmpContext, contexts[algo.index]); + EVP_DigestFinal_ex(tmpContext, Sum, nullptr); + EVP_MD_CTX_destroy(tmpContext); + + return ::HexDigest(std::basic_string_view<unsigned char>(Sum, Size)); + } + + bool Enable(HashAlgo const &algo) + { + contexts[algo.index] = EVP_MD_CTX_new(); + if (contexts[algo.index] == nullptr) + return false; + if (EVP_DigestInit_ex(contexts[algo.index], algo.evpLink(), NULL)) + return true; + EVP_MD_CTX_destroy(contexts[algo.index]); + contexts[algo.index] = nullptr; + return false; + } + bool IsEnabled(HashAlgo const &algo) + { + return contexts[algo.index] != nullptr; + } + + explicit PrivateHashes() {} + ~PrivateHashes() + { + for (auto ctx : contexts) + if (ctx != nullptr) + EVP_MD_CTX_free(ctx); + } + +#elif defined(HAVE_GNUTLS) std::array<std::optional<gnutls_hash_hd_t>, 4> digs{}; public: |
