summaryrefslogtreecommitdiff
path: root/apt-pkg/contrib
diff options
context:
space:
mode:
authorJulian Andres Klode <julian.klode@canonical.com>2024-12-18 19:37:40 +0100
committerJulian Andres Klode <julian.klode@canonical.com>2024-12-22 22:55:39 +0100
commit90270f0959d490d56db891809d83c91b3d4b9bf0 (patch)
tree80589894ae2a0eda080b6c6cf416882b52eaef7d /apt-pkg/contrib
parent470f5cf449ac20c7d7bf50ad805c72a5f52d256f (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/contrib')
-rw-r--r--apt-pkg/contrib/hashes.cc73
1 files changed, 71 insertions, 2 deletions
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: