summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Andres Klode <julian.klode@canonical.com>2020-01-07 19:21:40 +0100
committerJulian Andres Klode <julian.klode@canonical.com>2020-01-14 13:10:36 +0100
commit814ffcfaf34ad1d35e397eeaaafefbf03faed9cf (patch)
treec38fc09ea9a52fd3d0c8d2b57ca6ac83dc48e92c
parentcfeae24843e8357c7e8d2ff3b23ee81cac330017 (diff)
hashes: Use Libgcrypt for hashing purposes
Switch the code of the Hashes class to use libgcrypt, which allows us to use hardware-accelerated implementations of SHA1 and friends.
-rw-r--r--CMake/FindGcrypt.cmake25
-rw-r--r--CMakeLists.txt2
-rw-r--r--apt-pkg/CMakeLists.txt2
-rw-r--r--apt-pkg/contrib/hashes.cc106
-rw-r--r--apt-pkg/contrib/hashes.h8
-rw-r--r--debian/control1
6 files changed, 104 insertions, 40 deletions
diff --git a/CMake/FindGcrypt.cmake b/CMake/FindGcrypt.cmake
new file mode 100644
index 000000000..56bfc9fef
--- /dev/null
+++ b/CMake/FindGcrypt.cmake
@@ -0,0 +1,25 @@
+# - Try to find GCRYPT
+# Once done, this will define
+#
+# GCRYPT_FOUND - system has GCRYPT
+# GCRYPT_INCLUDE_DIRS - the GCRYPT include directories
+# GCRYPT_LIBRARIES - the GCRYPT library
+find_package(PkgConfig)
+
+pkg_check_modules(GCRYPT_PKGCONF libgcrypt)
+
+find_path(GCRYPT_INCLUDE_DIRS
+ NAMES gcrypt.h
+ PATHS ${GCRYPT_PKGCONF_INCLUDE_DIRS}
+)
+
+
+find_library(GCRYPT_LIBRARIES
+ NAMES gcrypt
+ PATHS ${GCRYPT_PKGCONF_LIBRARY_DIRS}
+)
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(GCRYPT DEFAULT_MSG GCRYPT_INCLUDE_DIRS GCRYPT_LIBRARIES)
+
+mark_as_advanced(GCRYPT_INCLUDE_DIRS GCRYPT_LIBRARIES)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ab08b8f4e..862a5d4ed 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -134,6 +134,8 @@ if (SECCOMP_FOUND)
set(HAVE_SECCOMP 1)
endif()
+find_package(Gcrypt REQUIRED)
+
# Mount()ing and stat()ing and friends
check_symbol_exists(statfs sys/vfs.h HAVE_VFS_H)
check_include_files(sys/params.h HAVE_PARAMS_H)
diff --git a/apt-pkg/CMakeLists.txt b/apt-pkg/CMakeLists.txt
index db23a30f7..e9a629ccf 100644
--- a/apt-pkg/CMakeLists.txt
+++ b/apt-pkg/CMakeLists.txt
@@ -48,6 +48,7 @@ target_include_directories(apt-pkg
$<$<BOOL:${UDEV_FOUND}>:${UDEV_INCLUDE_DIRS}>
$<$<BOOL:${SYSTEMD_FOUND}>:${SYSTEMD_INCLUDE_DIRS}>
${ICONV_INCLUDE_DIRS}
+ $<$<BOOL:${GCRYPT_FOUND}>:${GCRYPT_INCLUDE_DIRS}>
)
target_link_libraries(apt-pkg
@@ -61,6 +62,7 @@ target_link_libraries(apt-pkg
$<$<BOOL:${UDEV_FOUND}>:${UDEV_LIBRARIES}>
$<$<BOOL:${SYSTEMD_FOUND}>:${SYSTEMD_LIBRARIES}>
${ICONV_LIBRARIES}
+ $<$<BOOL:${GCRYPT_FOUND}>:${GCRYPT_LIBRARIES}>
)
set_target_properties(apt-pkg PROPERTIES VERSION ${MAJOR}.${MINOR})
set_target_properties(apt-pkg PROPERTIES SOVERSION ${MAJOR})
diff --git a/apt-pkg/contrib/hashes.cc b/apt-pkg/contrib/hashes.cc
index 366133b02..d68919778 100644
--- a/apt-pkg/contrib/hashes.cc
+++ b/apt-pkg/contrib/hashes.cc
@@ -15,18 +15,30 @@
#include <apt-pkg/configuration.h>
#include <apt-pkg/fileutl.h>
#include <apt-pkg/hashes.h>
-#include <apt-pkg/md5.h>
-#include <apt-pkg/sha1.h>
-#include <apt-pkg/sha2.h>
#include <algorithm>
#include <iostream>
#include <string>
+#include <assert.h>
#include <stddef.h>
#include <stdlib.h>
#include <unistd.h>
+
+#include <gcrypt.h>
/*}}}*/
+static const constexpr struct HashAlgo
+{
+ const char *name;
+ int gcryAlgo;
+ Hashes::SupportedHashes ourAlgo;
+} Algorithms[] = {
+ {"MD5Sum", GCRY_MD_MD5, Hashes::MD5SUM},
+ {"SHA1", GCRY_MD_SHA1, Hashes::SHA1SUM},
+ {"SHA256", GCRY_MD_SHA256, Hashes::SHA256SUM},
+ {"SHA512", GCRY_MD_SHA512, Hashes::SHA512SUM},
+};
+
const char * HashString::_SupportedHashes[] =
{
"SHA512", "SHA256", "SHA1", "MD5Sum", "Checksum-FileSize", NULL
@@ -286,39 +298,41 @@ bool HashStringList::operator!=(HashStringList const &other) const
class PrivateHashes {
public:
unsigned long long FileSize;
- unsigned int CalcHashes;
+ gcry_md_hd_t hd;
+
+ explicit PrivateHashes(unsigned int const CalcHashes) : FileSize(0)
+ {
+ gcry_md_open(&hd, 0, 0);
+ for (auto & Algo : Algorithms)
+ {
+ if ((CalcHashes & Algo.ourAlgo) == Algo.ourAlgo)
+ gcry_md_enable(hd, Algo.gcryAlgo);
+ }
+ }
- explicit PrivateHashes(unsigned int const CalcHashes) : FileSize(0), CalcHashes(CalcHashes) {}
explicit PrivateHashes(HashStringList const &Hashes) : FileSize(0) {
- unsigned int calcHashes = Hashes.usable() ? 0 : ~0;
- if (Hashes.find("MD5Sum") != NULL)
- calcHashes |= Hashes::MD5SUM;
- if (Hashes.find("SHA1") != NULL)
- calcHashes |= Hashes::SHA1SUM;
- if (Hashes.find("SHA256") != NULL)
- calcHashes |= Hashes::SHA256SUM;
- if (Hashes.find("SHA512") != NULL)
- calcHashes |= Hashes::SHA512SUM;
- CalcHashes = calcHashes;
+ gcry_md_open(&hd, 0, 0);
+ for (auto & Algo : Algorithms)
+ {
+ if (not Hashes.usable() || Hashes.find(Algo.name) != NULL)
+ gcry_md_enable(hd, Algo.gcryAlgo);
+ }
+ }
+ ~PrivateHashes()
+ {
+ gcry_md_close(hd);
}
};
/*}}}*/
// Hashes::Add* - Add the contents of data or FD /*{{{*/
bool Hashes::Add(const unsigned char * const Data, unsigned long long const Size)
{
- if (Size == 0)
- return true;
- bool Res = true;
- if ((d->CalcHashes & MD5SUM) == MD5SUM)
- Res &= MD5.Add(Data, Size);
- if ((d->CalcHashes & SHA1SUM) == SHA1SUM)
- Res &= SHA1.Add(Data, Size);
- if ((d->CalcHashes & SHA256SUM) == SHA256SUM)
- Res &= SHA256.Add(Data, Size);
- if ((d->CalcHashes & SHA512SUM) == SHA512SUM)
- Res &= SHA512.Add(Data, Size);
- d->FileSize += Size;
- return Res;
+ if (Size != 0)
+ {
+ gcry_md_write(d->hd, Data, Size);
+ d->FileSize += Size;
+ }
+ return true;
}
bool Hashes::AddFD(int const Fd,unsigned long long Size)
{
@@ -364,18 +378,38 @@ bool Hashes::AddFD(FileFd &Fd,unsigned long long Size)
return true;
}
/*}}}*/
+
+static APT_PURE std::string HexDigest(gcry_md_hd_t hd, int algo)
+{
+ char Conv[16] =
+ {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b',
+ 'c', 'd', 'e', 'f'};
+
+ auto Size = gcry_md_get_algo_dlen(algo);
+ char Result[((Size)*2) + 1];
+ Result[(Size)*2] = 0;
+
+ auto Sum = gcry_md_read(hd, algo);
+
+ // Convert each char into two letters
+ size_t J = 0;
+ size_t I = 0;
+ for (; I != (Size)*2; J++, I += 2)
+ {
+ Result[I] = Conv[Sum[J] >> 4];
+ Result[I + 1] = Conv[Sum[J] & 0xF];
+ }
+ return std::string(Result);
+};
+
HashStringList Hashes::GetHashStringList()
{
HashStringList hashes;
- if ((d->CalcHashes & MD5SUM) == MD5SUM)
- hashes.push_back(HashString("MD5Sum", MD5.Result().Value()));
- if ((d->CalcHashes & SHA1SUM) == SHA1SUM)
- hashes.push_back(HashString("SHA1", SHA1.Result().Value()));
- if ((d->CalcHashes & SHA256SUM) == SHA256SUM)
- hashes.push_back(HashString("SHA256", SHA256.Result().Value()));
- if ((d->CalcHashes & SHA512SUM) == SHA512SUM)
- hashes.push_back(HashString("SHA512", SHA512.Result().Value()));
+ for (auto & Algo : Algorithms)
+ if (gcry_md_is_enabled(d->hd, Algo.gcryAlgo))
+ hashes.push_back(HashString(Algo.name, HexDigest(d->hd, Algo.gcryAlgo)));
hashes.FileSize(d->FileSize);
+
return hashes;
}
Hashes::Hashes() : d(new PrivateHashes(~0)) { }
diff --git a/apt-pkg/contrib/hashes.h b/apt-pkg/contrib/hashes.h
index e9b8a0519..14100e13b 100644
--- a/apt-pkg/contrib/hashes.h
+++ b/apt-pkg/contrib/hashes.h
@@ -173,10 +173,10 @@ class Hashes
PrivateHashes * const d;
/* TODO: those will disappear in the future as it is hard to add new ones this way.
* Use Add* to build the results and get them via GetHashStringList() instead */
- MD5Summation MD5;
- SHA1Summation SHA1;
- SHA256Summation SHA256;
- SHA512Summation SHA512;
+ MD5Summation MD5 APT_PKG_590("Remove");
+ SHA1Summation SHA1 APT_PKG_590("Remove");
+ SHA256Summation SHA256 APT_PKG_590("Remove");
+ SHA512Summation SHA512 APT_PKG_590("Remove");
public:
static const int UntilEOF = 0;
diff --git a/debian/control b/debian/control
index d12f93e1b..4bc1e0c33 100644
--- a/debian/control
+++ b/debian/control
@@ -17,6 +17,7 @@ Build-Depends: cmake (>= 3.4),
libbz2-dev,
libdb-dev,
libgnutls28-dev (>= 3.4.6),
+ libgcrypt20-dev,
liblz4-dev (>= 0.0~r126),
liblzma-dev,
libseccomp-dev [amd64 arm64 armel armhf i386 mips mips64el mipsel ppc64el s390x hppa powerpc powerpcspe ppc64 x32],