From 6f1efdf04cd569f1191e365ac4c5d473bdfe2c15 Mon Sep 17 00:00:00 2001 From: Nicolás Reynolds Date: Tue, 21 Jan 2014 03:40:08 +0000 Subject: Tue Jan 21 03:36:05 UTC 2014 --- core/libgcrypt/PKGBUILD | 26 +++++- core/libgcrypt/fix_avx_detection.patch | 159 +++++++++++++++++++++++++++++++++ core/libgcrypt/fix_slow_PBKDF2.patch | 75 ++++++++++++++++ 3 files changed, 256 insertions(+), 4 deletions(-) create mode 100644 core/libgcrypt/fix_avx_detection.patch create mode 100644 core/libgcrypt/fix_slow_PBKDF2.patch (limited to 'core/libgcrypt') diff --git a/core/libgcrypt/PKGBUILD b/core/libgcrypt/PKGBUILD index fabc45ca3..b7cbad492 100644 --- a/core/libgcrypt/PKGBUILD +++ b/core/libgcrypt/PKGBUILD @@ -1,9 +1,13 @@ -# $Id: PKGBUILD 203657 2014-01-13 17:30:34Z foutrelis $ +# $Id: PKGBUILD 204471 2014-01-20 16:59:28Z andyrtr $ # Maintainer: Andreas Radke +# after a .so bump first rebuild dirmngr +# with sudo testing-x86_64-build -- -I libgcrypt-1.6.0-1-x86_64.pkg.tar.xz +# then cp /usr/lib/libgcrypt.so.11 /var/lib/archbuild/staging-x86_64/root/usr/lib/ and do staging-x86_64-build + pkgname=libgcrypt pkgver=1.6.0 -pkgrel=1 +pkgrel=2 pkgdesc="General purpose cryptographic library based on the code from GnuPG" arch=(i686 x86_64) url="http://www.gnupg.org" @@ -11,8 +15,22 @@ license=('LGPL') depends=('libgpg-error>=1.10-2') options=('!emptydirs') install=$pkgname.install -source=(ftp://ftp.gnupg.org/gcrypt/${pkgname}/${pkgname}-${pkgver}.tar.bz2) -sha1sums=('43283c0b41c41e3d3bc13c2d8f937dfe2aaa1a77') +source=(ftp://ftp.gnupg.org/gcrypt/${pkgname}/${pkgname}-${pkgver}.tar.bz2 + fix_avx_detection.patch + fix_slow_PBKDF2.patch) +sha1sums=('43283c0b41c41e3d3bc13c2d8f937dfe2aaa1a77' + '5219ee3d6e08155149f0fa410b07736d4f502d17' + 'a27baab3f4bda7ff6fb493115f6bdd1c990184f1') + +prepare() { + cd ${pkgname}-${pkgver} + + # fix AVX/AVX2 detextion + patch -Np1 -i ${srcdir}/fix_avx_detection.patch + + # fix slow PBKDF2 + patch -Np1 -i ${srcdir}/fix_slow_PBKDF2.patch +} build() { cd ${pkgname}-${pkgver} diff --git a/core/libgcrypt/fix_avx_detection.patch b/core/libgcrypt/fix_avx_detection.patch new file mode 100644 index 000000000..5d21c4232 --- /dev/null +++ b/core/libgcrypt/fix_avx_detection.patch @@ -0,0 +1,159 @@ +From: Jussi Kivilinna +Date: Sun, 12 Jan 2014 09:31:20 +0000 (+0200) +Subject: Fix buggy/incomplete detection of AVX/AVX2 support +X-Git-Url: http://git.gnupg.org/cgi-bin/gitweb.cgi?p=libgcrypt.git;a=commitdiff_plain;h=8302d66d140d5c78c5e808fa1555ed7a8ee27921 + +Fix buggy/incomplete detection of AVX/AVX2 support + +* configure.ac: Also check for 'xgetbv' instruction in AVX and AVX2 +inline assembly checks. +* src/hwf-x86.c [__i386__] (get_xgetbv): New function. +[__x86_64__] (get_xgetbv): New function. +[HAS_X86_CPUID] (detect_x86_gnuc): Check for OSXSAVE and OS support for +XMM&YMM registers and enable AVX/AVX2 only if XMM&YMM registers are +supported by OS. +-- + +This patch is based on original patch and bug report by Panagiotis Christopoulos: + + Adding better detection of AVX/AVX2 support + + After upgrading libgcrypt from 1.5.3 to 1.6.0 on a remote XEN system (linode) my + gpg2 stopped working properly, throwing SIGILL signals when doing sha512 + operations etc. I managed to debug this with the help of Doublas Freed + (dwfreed at mtu.edu) and it seems that the current AVX detection just checks for + bit 28 on cpuid but the check still works on systems that have disabled the avx/avx2 + instructions for some reason (eg. performance/unstability) resulting in SIGILLs + (eg. when trying _gcry_sha512_transform_amd64_avx() ). + From Intel resources[1][2], I found additional checks for better AVX + detection and applied them in the following patch. Please review/change + accordingly and commit some better AVX detection mechanism. The AVX part is + tested but could not test the AVX2 one, because I lack proper hardware. I can + provide additional information upon request. Use the patch only as a guideline, + as it's not thoroughly tested. + + [1] http://software.intel.com/en-us/blogs/2011/04/14/is-avx-enabled + [2] http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-manual-325462.pdf (sections 14.3 +and 14.7.1) + +Reported-by: Panagiotis Christopoulos (pchrist) +Cc: Doublas Freed +Cc: Tim Harder +Signed-off-by: Jussi Kivilinna +(cherry picked from commit bbcb12187afb1756cb27296166b57fa19ee45d4d) +--- + +diff --git a/configure.ac b/configure.ac +index a47e13e..3387b9a 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1035,7 +1035,7 @@ AC_CACHE_CHECK([whether GCC inline assembler supports AVX instructions], + [gcry_cv_gcc_inline_asm_avx=no + AC_COMPILE_IFELSE([AC_LANG_SOURCE( + [[void a(void) { +- __asm__("vaesdeclast (%[mem]),%%xmm0,%%xmm7\n\t"::[mem]"r"(0):); ++ __asm__("xgetbv; vaesdeclast (%[mem]),%%xmm0,%%xmm7\n\t"::[mem]"r"(0):); + }]])], + [gcry_cv_gcc_inline_asm_avx=yes])]) + if test "$gcry_cv_gcc_inline_asm_avx" = "yes" ; then +@@ -1052,7 +1052,7 @@ AC_CACHE_CHECK([whether GCC inline assembler supports AVX2 instructions], + [gcry_cv_gcc_inline_asm_avx2=no + AC_COMPILE_IFELSE([AC_LANG_SOURCE( + [[void a(void) { +- __asm__("vpbroadcastb %%xmm7,%%ymm1\n\t":::"cc"); ++ __asm__("xgetbv; vpbroadcastb %%xmm7,%%ymm1\n\t":::"cc"); + }]])], + [gcry_cv_gcc_inline_asm_avx2=yes])]) + if test "$gcry_cv_gcc_inline_asm_avx2" = "yes" ; then +diff --git a/src/hwf-x86.c b/src/hwf-x86.c +index 4e82558..0591b4f 100644 +--- a/src/hwf-x86.c ++++ b/src/hwf-x86.c +@@ -95,6 +95,21 @@ get_cpuid(unsigned int in, unsigned int *eax, unsigned int *ebx, + if (edx) + *edx = regs[3]; + } ++ ++static unsigned int ++get_xgetbv(void) ++{ ++ unsigned int t_eax; ++ ++ asm volatile ++ ("xgetbv\n\t" ++ : "=a" (t_eax) ++ : "c" (0) ++ ); ++ ++ return t_eax; ++} ++ + #endif /* i386 && GNUC */ + + +@@ -129,6 +144,21 @@ get_cpuid(unsigned int in, unsigned int *eax, unsigned int *ebx, + if (edx) + *edx = regs[3]; + } ++ ++static unsigned int ++get_xgetbv(void) ++{ ++ unsigned int t_eax; ++ ++ asm volatile ++ ("xgetbv\n\t" ++ : "=a" (t_eax) ++ : "c" (0) ++ ); ++ ++ return t_eax; ++} ++ + #endif /* x86-64 && GNUC */ + + +@@ -138,9 +168,12 @@ detect_x86_gnuc (void) + { + char vendor_id[12+1]; + unsigned int features; ++ unsigned int os_supports_avx_avx2_registers = 0; + unsigned int max_cpuid_level; + unsigned int result = 0; + ++ (void)os_supports_avx_avx2_registers; ++ + if (!is_cpuid_available()) + return 0; + +@@ -215,10 +248,20 @@ detect_x86_gnuc (void) + if (features & 0x02000000) + result |= HWF_INTEL_AESNI; + #endif /*ENABLE_AESNI_SUPPORT*/ ++#if defined(ENABLE_AVX_SUPPORT) || defined(ENABLE_AVX2_SUPPORT) ++ /* Test bit 27 for OSXSAVE (required for AVX/AVX2). */ ++ if (features & 0x08000000) ++ { ++ /* Check that OS has enabled both XMM and YMM state support. */ ++ if ((get_xgetbv() & 0x6) == 0x6) ++ os_supports_avx_avx2_registers = 1; ++ } ++#endif + #ifdef ENABLE_AVX_SUPPORT + /* Test bit 28 for AVX. */ + if (features & 0x10000000) +- result |= HWF_INTEL_AVX; ++ if (os_supports_avx_avx2_registers) ++ result |= HWF_INTEL_AVX; + #endif /*ENABLE_AVX_SUPPORT*/ + #ifdef ENABLE_DRNG_SUPPORT + /* Test bit 30 for RDRAND. */ +@@ -242,6 +285,7 @@ detect_x86_gnuc (void) + #ifdef ENABLE_AVX2_SUPPORT + /* Test bit 5 for AVX2. */ + if (features & 0x00000020) ++ if (os_supports_avx_avx2_registers) + result |= HWF_INTEL_AVX2; + #endif /*ENABLE_AVX_SUPPORT*/ + } + diff --git a/core/libgcrypt/fix_slow_PBKDF2.patch b/core/libgcrypt/fix_slow_PBKDF2.patch new file mode 100644 index 000000000..ee1eafd52 --- /dev/null +++ b/core/libgcrypt/fix_slow_PBKDF2.patch @@ -0,0 +1,75 @@ +From: Milan Broz +Date: Mon, 13 Jan 2014 20:30:42 +0000 (+0100) +Subject: PBKDF2: Use gcry_md_reset to speed up calculation. +X-Git-Url: http://git.gnupg.org/cgi-bin/gitweb.cgi?p=libgcrypt.git;a=commitdiff_plain;h=ead3a097a9ee5908e562e6ec683707c38191acf3 + +PBKDF2: Use gcry_md_reset to speed up calculation. + +* cipher/kdf.c (_gcry_kdf_pkdf2): Use gcry_md_reset +to speed up calculation. +-- + +Current PBKDF2 implementation uses gcry_md_set_key in every iteration +which is extremely slow (even in comparison with other implementations). + +Use gcry_md_reset instead and set key only once. + +With this test program: + + char input[32000], salt[8], key[16]; + gcry_kdf_derive(input, sizeof(input), GCRY_KDF_PBKDF2, + gcry_md_map_name("sha1"), + salt, sizeof(salt), 100000, sizeof(key), key); + +running time without patch: + real 0m11.165s + user 0m11.136s + sys 0m0.000s + +and with patch applied + real 0m0.230s + user 0m0.184s + sys 0m0.024s + +(The problem was found when cryptsetup started to use gcrypt internal PBKDF2 +and for very long keyfiles unlocking time increased drastically. +See https://bugzilla.redhat.com/show_bug.cgi?id=1051733) + +Signed-off-by: Milan Broz +(cherry picked from commit 04cda6b7cc16f3f52c12d9d3e46c56701003496e) +--- + +diff --git a/cipher/kdf.c b/cipher/kdf.c +index 503f068..af0dc48 100644 +--- a/cipher/kdf.c ++++ b/cipher/kdf.c +@@ -175,19 +175,21 @@ _gcry_kdf_pkdf2 (const void *passphrase, size_t passphraselen, + return ec; + } + ++ ec = _gcry_md_setkey (md, passphrase, passphraselen); ++ if (ec) ++ { ++ _gcry_md_close (md); ++ xfree (sbuf); ++ return ec; ++ } ++ + /* Step 3 and 4. */ + memcpy (sbuf, salt, saltlen); + for (lidx = 1; lidx <= l; lidx++) + { + for (iter = 0; iter < iterations; iter++) + { +- ec = _gcry_md_setkey (md, passphrase, passphraselen); +- if (ec) +- { +- _gcry_md_close (md); +- xfree (sbuf); +- return ec; +- } ++ _gcry_md_reset (md); + if (!iter) /* Compute U_1: */ + { + sbuf[saltlen] = (lidx >> 24); + -- cgit v1.2.3-54-g00ecf