From 814ffcfaf34ad1d35e397eeaaafefbf03faed9cf Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Tue, 7 Jan 2020 19:21:40 +0100 Subject: 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. --- CMake/FindGcrypt.cmake | 25 +++++++++++ CMakeLists.txt | 2 + apt-pkg/CMakeLists.txt | 2 + apt-pkg/contrib/hashes.cc | 106 ++++++++++++++++++++++++++++++---------------- apt-pkg/contrib/hashes.h | 8 ++-- debian/control | 1 + 6 files changed, 104 insertions(+), 40 deletions(-) create mode 100644 CMake/FindGcrypt.cmake 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 $<$:${UDEV_INCLUDE_DIRS}> $<$:${SYSTEMD_INCLUDE_DIRS}> ${ICONV_INCLUDE_DIRS} + $<$:${GCRYPT_INCLUDE_DIRS}> ) target_link_libraries(apt-pkg @@ -61,6 +62,7 @@ target_link_libraries(apt-pkg $<$:${UDEV_LIBRARIES}> $<$:${SYSTEMD_LIBRARIES}> ${ICONV_LIBRARIES} + $<$:${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 #include #include -#include -#include -#include #include #include #include +#include #include #include #include + +#include /*}}}*/ +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], -- cgit v1.2.3