summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Andres Klode <julian.klode@canonical.com>2024-12-18 19:11:26 +0100
committerJulian Andres Klode <julian.klode@canonical.com>2024-12-21 13:31:06 +0100
commit470f5cf449ac20c7d7bf50ad805c72a5f52d256f (patch)
tree59ab3c90456ff7ae26391c000a3d8a43957d0025
parentef435a3ed9c3e835c799df651f160b658eeee56a (diff)
hashes: Add GnuTLS backend, make it default
The GnuTLS backend avoids the need to link in libgcrypt, and gets us another certified library people will be happy with. This should be an intermediate step on the road to OpenSSL.
-rw-r--r--CMakeLists.txt4
-rw-r--r--apt-pkg/CMakeLists.txt2
-rw-r--r--apt-pkg/contrib/hashes.cc66
3 files changed, 71 insertions, 1 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c6977675e..4d2a5414d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -141,7 +141,9 @@ if (SECCOMP_FOUND)
set(HAVE_SECCOMP 1)
endif()
-find_package(GCRYPT REQUIRED)
+if (NOT HAVE_GNUTLS)
+ find_package(GCRYPT REQUIRED)
+endif()
find_package(XXHASH REQUIRED)
# Mount()ing and stat()ing and friends
diff --git a/apt-pkg/CMakeLists.txt b/apt-pkg/CMakeLists.txt
index 63052faad..c68b7bddc 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:${GNUTLS_FOUND}>:${GNUTLS_INCLUDE_DIRS}>
$<$<BOOL:${GCRYPT_FOUND}>:${GCRYPT_INCLUDE_DIRS}>
$<$<BOOL:${XXHASH_FOUND}>:${XXHASH_INCLUDE_DIRS}>
)
@@ -71,6 +72,7 @@ target_link_libraries(apt-pkg
$<$<BOOL:${UDEV_FOUND}>:${UDEV_LIBRARIES}>
$<$<BOOL:${SYSTEMD_FOUND}>:${SYSTEMD_LIBRARIES}>
${ICONV_LIBRARIES}
+ $<$<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 a4d5026b4..033cd0845 100644
--- a/apt-pkg/contrib/hashes.cc
+++ b/apt-pkg/contrib/hashes.cc
@@ -26,10 +26,15 @@
#include <cstddef>
#include <cstdlib>
#include <iostream>
+#include <optional>
#include <string>
#include <unistd.h>
+#ifdef HAVE_GNUTLS
+#include <gnutls/crypto.h>
+#else
#include <gcrypt.h>
+#endif
/*}}}*/
const char * HashString::_SupportedHashes[] =
@@ -324,6 +329,66 @@ class PrivateHashes
unsigned long long FileSize{0};
private:
+#ifdef HAVE_GNUTLS
+ std::array<std::optional<gnutls_hash_hd_t>, 4> digs{};
+
+ public:
+ struct HashAlgo
+ {
+ size_t index;
+ const char *name;
+ gnutls_digest_algorithm_t gnuTlsAlgo;
+ Hashes::SupportedHashes ourAlgo;
+ };
+
+ static constexpr std::array<HashAlgo, 4> Algorithms{
+ HashAlgo{0, "MD5Sum", GNUTLS_DIG_MD5, Hashes::MD5SUM},
+ HashAlgo{1, "SHA1", GNUTLS_DIG_SHA1, Hashes::SHA1SUM},
+ HashAlgo{2, "SHA256", GNUTLS_DIG_SHA256, Hashes::SHA256SUM},
+ HashAlgo{3, "SHA512", GNUTLS_DIG_SHA512, Hashes::SHA512SUM},
+ };
+
+ bool Write(unsigned char const *Data, size_t Size)
+ {
+ for (auto &dig : digs)
+ {
+ if (dig)
+ gnutls_hash(*dig, Data, Size);
+ }
+ return true;
+ }
+
+ std::string HexDigest(HashAlgo const &algo)
+ {
+ auto Size = gnutls_hash_get_len(algo.gnuTlsAlgo);
+ unsigned char Sum[Size];
+ if (auto copy = gnutls_hash_copy(*digs[algo.index]))
+ gnutls_hash_deinit(copy, &Sum);
+ return ::HexDigest(std::basic_string_view<unsigned char>(Sum, Size));
+ }
+ bool Enable(HashAlgo const &algo)
+ {
+ digs[algo.index].emplace();
+ if (gnutls_hash_init(&*digs[algo.index], algo.gnuTlsAlgo) == 0)
+ return true;
+ digs[algo.index] = std::nullopt;
+ return false;
+ }
+ bool IsEnabled(HashAlgo const &algo)
+ {
+ return bool{digs[algo.index]};
+ }
+
+ explicit PrivateHashes() {}
+ ~PrivateHashes()
+ {
+ for (auto &dig : digs)
+ {
+ if (dig)
+ gnutls_hash_deinit(*dig, nullptr);
+ }
+ }
+#else
gcry_md_hd_t hd;
void maybeInit()
@@ -395,6 +460,7 @@ class PrivateHashes
{
gcry_md_close(hd);
}
+#endif
explicit PrivateHashes(unsigned int const CalcHashes) : PrivateHashes()
{