From: Sebastian Andrzej Siewior <sebast...@breakpoint.cc> I created a test file via dd if=/dev/zero bs=1024k count=1024 | xz -v -0 -Csha256
and compared the in-tree sha256 implementation on a Ryzen (CPU acceleration available): | Performance counter stats for 'xz --test sha256.xz' (5 runs): | | 20.748.708.638 cycles # 4,174 GHz ( +- 1,23% ) (83,29%) | 63.371.432.190 instructions # 3,05 insn per cycle | # 0,23 stalled cycles per insn ( +- 0,01% ) (83,37%) | 4,9778 +- 0,0488 seconds time elapsed ( +- 0,98% ) vs OpenSSL's: | Performance counter stats for './src/xz/xz --test sha256.xz' (5 runs): | | 10.037.180.776 cycles # 4,230 GHz ( +- 0,03% ) (83,18%) | 16.126.619.033 instructions # 1,61 insn per cycle | # 0,50 stalled cycles per insn ( +- 0,01% ) (83,43%) | 2,37200 +- 0,00621 seconds time elapsed ( +- 0,26% ) worse insn/cycle ratio, much less instructions half run time. It is even slightly better compared to crc64: | Performance counter stats for './src/xz/xz --test crc64.xz' (5 runs): | | 10.989.495.452 cycles # 4,250 GHz ( +- 0,04% ) (83,22%) | 17.829.100.301 instructions # 1,62 insn per cycle | # 0,43 stalled cycles per insn ( +- 0,02% ) (83,42%) | 2,5850 +- 0,0103 seconds time elapsed ( +- 0,40% ) For the protocol, compared to no checksum: | Performance counter stats for './src/xz/xz --test none.xz' (5 runs): | | 7.857.471.590 cycles # 4,237 GHz ( +- 0,03% ) (83,08%) | 13.257.837.157 instructions # 1,69 insn per cycle | | 1,85337 +- 0,00440 seconds time elapsed ( +- 0,24% ) Signed-off-by: Sebastian Andrzej Siewior <sebast...@breakpoint.cc> --- I learned here that rpm is using sha256 based checksums. So that might be a good thing. configure.ac | 24 +++++++++++++++++++++++- src/liblzma/Makefile.am | 1 + src/liblzma/check/check.h | 33 ++++++++++++++++++++++++++++++++- src/lzmainfo/Makefile.am | 2 +- src/xz/Makefile.am | 2 +- src/xzdec/Makefile.am | 2 +- 6 files changed, 59 insertions(+), 5 deletions(-) diff --git a/configure.ac b/configure.ac index 2418e4b039e61..5e0eaefc99c92 100644 --- a/configure.ac +++ b/configure.ac @@ -289,6 +289,19 @@ else AC_MSG_RESULT([no]) fi +AC_MSG_CHECKING([if openssl should be used]) +AC_ARG_ENABLE([openssl], AS_HELP_STRING([--enable-openssl], + [Use openssl from the operating system. + See INSTALL for possible subtle problems.]), + [], [enable_openssl=no]) +if test "x$enable_openssl" != "xyes"; then + enable_openssl=no +fi +if test "x$enable_openssl" = xyes; then + AC_MSG_RESULT([yes]) +else + AC_MSG_RESULT([no]) +fi ########################### # Assembler optimizations # @@ -740,6 +753,7 @@ TUKLIB_MBSTR sha256_header_found=no sha256_type_found=no sha256_func_found=no +openssl_found=no if test "x$enable_external_sha256" = "xyes"; then # Test for Common Crypto before others, because Darwin has sha256.h # too and we don't want to use that, because on older versions it @@ -770,11 +784,19 @@ if test "x$enable_external_sha256" = "xyes"; then [sha256_func_found=yes ; break]) fi fi +elif test "x$enable_openssl" = "xyes"; then + PKG_CHECK_MODULES([OPENSSL_CRYPTO], [libcrypto], + [AC_DEFINE([HAVE_OPENSSL_CRYPTO], [1], [Use SHA256 from openssl]) + openssl_found=yes]) fi -AM_CONDITIONAL([COND_INTERNAL_SHA256], [test "x$sha256_func_found" = xno]) + +AM_CONDITIONAL([COND_INTERNAL_SHA256], [test "x$sha256_func_found" = xno -a "x$openssl_found" = xno]) if test "x$enable_external_sha256$sha256_func_found" = xyesno; then AC_MSG_ERROR([--enable-external-sha256 was specified but no supported external SHA-256 implementation was found]) fi +if test "x$enable_openssl$openssl_found" = xyesno; then + AC_MSG_ERROR([--enable-openssl was specified but openssl was not found.]) +fi # Check for SSE2 intrinsics. AC_CHECK_DECL([_mm_movemask_epi8], diff --git a/src/liblzma/Makefile.am b/src/liblzma/Makefile.am index 6323e26aade10..3afb08169840c 100644 --- a/src/liblzma/Makefile.am +++ b/src/liblzma/Makefile.am @@ -25,6 +25,7 @@ liblzma_la_CPPFLAGS = \ -I$(top_srcdir)/src/common \ -DTUKLIB_SYMBOL_PREFIX=lzma_ liblzma_la_LDFLAGS = -no-undefined -version-info 8:99:3 +liblzma_la_LDFLAGS += $(OPENSSL_CRYPTO_LIBS) EXTRA_DIST += liblzma.map validate_map.sh if COND_SYMVERS diff --git a/src/liblzma/check/check.h b/src/liblzma/check/check.h index 3007d889b0f3a..0249025ec179a 100644 --- a/src/liblzma/check/check.h +++ b/src/liblzma/check/check.h @@ -20,6 +20,7 @@ // both a usable header and a type have already been found. #if !(defined(HAVE_CC_SHA256_INIT) \ || defined(HAVE_SHA256_INIT) \ + || defined(HAVE_OPENSSL_CRYPTO) \ || defined(HAVE_SHA256INIT)) # define HAVE_INTERNAL_SHA256 1 #endif @@ -34,6 +35,8 @@ #elif defined(HAVE_SHA2_H) # include <sys/types.h> # include <sha2.h> +#elif defined(HAVE_OPENSSL_CRYPTO) +# include <openssl/evp.h> #endif #if defined(HAVE_INTERNAL_SHA256) @@ -51,6 +54,11 @@ typedef CC_SHA256_CTX lzma_sha256_state; typedef SHA256_CTX lzma_sha256_state; #elif defined(HAVE_SHA2_CTX) typedef SHA2_CTX lzma_sha256_state; +#elif defined(HAVE_OPENSSL_CRYPTO) +typedef struct { + EVP_MD_CTX *ctx; + +} lzma_sha256_state; #endif #if defined(HAVE_INTERNAL_SHA256) @@ -121,8 +129,31 @@ extern void lzma_check_update(lzma_check_state *check, lzma_check type, /// Finish the check calculation and store the result to check->buffer.u8. extern void lzma_check_finish(lzma_check_state *check, lzma_check type); +#ifdef HAVE_OPENSSL_CRYPTO -#ifndef LZMA_SHA256FUNC +/// Prepare SHA-256 state for new input. +static inline void lzma_sha256_init(lzma_check_state *check) +{ + check->state.sha256.ctx = EVP_MD_CTX_new(); + EVP_DigestInit_ex(check->state.sha256.ctx, + EVP_get_digestbyname("sha256"), NULL); +} + +/// Update the SHA-256 hash state +static inline void lzma_sha256_update( + const uint8_t *buf, size_t size, lzma_check_state *check) +{ + EVP_DigestUpdate(check->state.sha256.ctx, buf, size); +} + +/// Finish the SHA-256 calculation and store the result to check->buffer.u8. +static inline void lzma_sha256_finish(lzma_check_state *check) +{ + EVP_DigestFinal_ex(check->state.sha256.ctx, check->buffer.u8, NULL); + EVP_MD_CTX_free(check->state.sha256.ctx); +} + +#elif !defined(LZMA_SHA256FUNC) /// Prepare SHA-256 state for new input. extern void lzma_sha256_init(lzma_check_state *check); diff --git a/src/lzmainfo/Makefile.am b/src/lzmainfo/Makefile.am index ff7172b50f380..51424effb750a 100644 --- a/src/lzmainfo/Makefile.am +++ b/src/lzmainfo/Makefile.am @@ -28,7 +28,7 @@ if COND_GNULIB lzmainfo_LDADD += $(top_builddir)/lib/libgnu.a endif -lzmainfo_LDADD += $(LTLIBINTL) +lzmainfo_LDADD += $(LTLIBINTL) $(OPENSSL_CRYPTO_LIBS) dist_man_MANS = lzmainfo.1 diff --git a/src/xz/Makefile.am b/src/xz/Makefile.am index 4bc64f360ada5..8d6604c8ffb22 100644 --- a/src/xz/Makefile.am +++ b/src/xz/Makefile.am @@ -60,7 +60,7 @@ xz_LDADD += $(top_builddir)/lib/libgnu.a endif # libgnu.a may need these libs, so this must be after libgnu.a. -xz_LDADD += $(LTLIBINTL) +xz_LDADD += $(LTLIBINTL) $(OPENSSL_CRYPTO_LIBS) # Windows resource compiler support diff --git a/src/xzdec/Makefile.am b/src/xzdec/Makefile.am index 90f1e922a07c6..59ad965eb1678 100644 --- a/src/xzdec/Makefile.am +++ b/src/xzdec/Makefile.am @@ -32,7 +32,7 @@ if COND_GNULIB xzdec_LDADD += $(top_builddir)/lib/libgnu.a endif -xzdec_LDADD += $(LTLIBINTL) +xzdec_LDADD += $(LTLIBINTL) $(OPENSSL_CRYPTO_LIBS) lzmadec_SOURCES = \ -- 2.30.0