Hi Jack and Samuel, "Jack O'Connor" <[email protected]> writes:
> Oops, I forgot to include a link to the OpenSSL GH issue, which > describes the specific commit that made the change: > https://github.com/openssl/openssl/issues/29340 > > On Mon, Dec 8, 2025 at 2:02 PM Jack O'Connor <[email protected]> wrote: >> >> Upgrading OpenSSL from v3.5 to v3.6 causes a ~3x slowdown for >> `sha256sum` (~2x for `sha1sum`) on machines that support SHA-NI. It >> looks like this was caused by a change in why/how >> `OPENSSL_cpuid_setup` gets called. >> >> I don't know who's "to blame" or what the proper fix will be, but as a >> hacky example here's a patch that fixes the performance regression in >> `sha256sum` by calling `OpenSSL_add_all_algorithms` early in `main`: Thanks for both reports and for the debugging. I commented on the OpenSSL bug what I think is happening here. The low level deprecated OpenSSL functions will not call OPENSSL_cpuid_setup like the EVP ones will. OpenSSL 3.5 would call OPENSSL_cpuid_setup when the library was loaded, but OpenSSL 3.6 will not. We use the low-level deprecated APIs, e.g., SHA256_Init, SHA256_Update, and SHA256_Final, because the EVP APIs are overkill for our purposes. If my understanding is correct, that means OpenSSL 3.6 never checks what instructions your CPU supports. >> diff --git a/src/cksum.c b/src/cksum.c >> index ac3e3f1..c7c20f0 100644 >> --- a/src/cksum.c >> +++ b/src/cksum.c >> @@ -52,6 +52,9 @@ >> #if HASH_ALGO_SHA256 || HASH_ALGO_SHA224 || HASH_ALGO_CKSUM >> # include "sha256.h" >> #endif >> +#if HASH_ALGO_SHA256 && HAVE_OPENSSL_SHA256 >> +# include <openssl/evp.h> >> +#endif >> #if HASH_ALGO_SHA512 || HASH_ALGO_SHA384 || HASH_ALGO_CKSUM >> # include "sha512.h" >> #endif >> @@ -1505,6 +1508,10 @@ main (int argc, char **argv) >> so that processes running in parallel do not intersperse their output. >> */ >> setvbuf (stdout, nullptr, _IOLBF, 0); >> >> +#if HASH_ALGO_SHA256 && HAVE_OPENSSL_SHA256 >> + OpenSSL_add_all_algorithms(); >> +#endif >> + >> #if HASH_ALGO_SUM >> char const *short_opts = "rs"; >> #elif HASH_ALGO_CKSUM Thanks, this patch is on the right track. Mine covers the rest of the programs that use OpenSSL. I'll hold off pushing and watch the OpenSSL bug report, since I think this change was unintentional. diff --git a/src/cksum.c b/src/cksum.c index ac3e3f10e..e4d548079 100644 --- a/src/cksum.c +++ b/src/cksum.c @@ -67,6 +67,7 @@ /* The official name of this program (e.g., no 'g' prefix). */ #if HASH_ALGO_SUM +# define OPENSSL_INIT() # define PROGRAM_NAME "sum" # define DIGEST_TYPE_STRING "BSD" # define DIGEST_STREAM sumfns[sum_algorithm] @@ -74,6 +75,14 @@ # define DIGEST_BITS 16 # define DIGEST_ALIGN 4 #elif HASH_ALGO_CKSUM +# if (HAVE_OPENSSL_MD5 || HAVE_OPENSSL_SHA1 || HAVE_OPENSSL_SHA256 || \ + HAVE_OPENSSL_SHA512 || HAVE_OPENSSL_SHA3) +# include <openssl/crypto.h> +# define OPENSSL_INIT() OPENSSL_init_crypto (OPENSSL_INIT_ADD_ALL_CIPHERS, \ + nullptr) +# else +# define OPENSSL_INIT() +# endif # define MAX_DIGEST_BITS 512 # define MAX_DIGEST_ALIGN 8 # define PROGRAM_NAME "cksum" @@ -83,6 +92,13 @@ # define DIGEST_BITS MAX_DIGEST_BITS # define DIGEST_ALIGN MAX_DIGEST_ALIGN #elif HASH_ALGO_MD5 +# if HAVE_OPENSSL_MD5 +# include <openssl/crypto.h> +# define OPENSSL_INIT() OPENSSL_init_crypto (OPENSSL_INIT_ADD_ALL_CIPHERS, \ + nullptr) +# else +# define OPENSSL_INIT() +# endif # define PROGRAM_NAME "md5sum" # define DIGEST_TYPE_STRING "MD5" # define DIGEST_STREAM md5_stream @@ -90,6 +106,7 @@ # define DIGEST_REFERENCE "RFC 1321" # define DIGEST_ALIGN 4 #elif HASH_ALGO_BLAKE2 +# define OPENSSL_INIT() # define PROGRAM_NAME "b2sum" # define DIGEST_TYPE_STRING "BLAKE2b" # define DIGEST_STREAM blake2b_stream @@ -97,6 +114,13 @@ # define DIGEST_REFERENCE "RFC 7693" # define DIGEST_ALIGN 8 #elif HASH_ALGO_SHA1 +# if HAVE_OPENSSL_SHA1 +# include <openssl/crypto.h> +# define OPENSSL_INIT() OPENSSL_init_crypto (OPENSSL_INIT_ADD_ALL_CIPHERS, \ + nullptr) +# else +# define OPENSSL_INIT() +# endif # define PROGRAM_NAME "sha1sum" # define DIGEST_TYPE_STRING "SHA1" # define DIGEST_STREAM sha1_stream @@ -104,6 +128,13 @@ # define DIGEST_REFERENCE "FIPS-180-1" # define DIGEST_ALIGN 4 #elif HASH_ALGO_SHA256 +# if HAVE_OPENSSL_SHA256 +# include <openssl/crypto.h> +# define OPENSSL_INIT() OPENSSL_init_crypto (OPENSSL_INIT_ADD_ALL_CIPHERS, \ + nullptr) +# else +# define OPENSSL_INIT() +# endif # define PROGRAM_NAME "sha256sum" # define DIGEST_TYPE_STRING "SHA256" # define DIGEST_STREAM sha256_stream @@ -111,6 +142,13 @@ # define DIGEST_REFERENCE "FIPS-180-2" # define DIGEST_ALIGN 4 #elif HASH_ALGO_SHA224 +# if HAVE_OPENSSL_SHA256 +# include <openssl/crypto.h> +# define OPENSSL_INIT() OPENSSL_init_crypto (OPENSSL_INIT_ADD_ALL_CIPHERS, \ + nullptr) +# else +# define OPENSSL_INIT() +# endif # define PROGRAM_NAME "sha224sum" # define DIGEST_TYPE_STRING "SHA224" # define DIGEST_STREAM sha224_stream @@ -118,6 +156,13 @@ # define DIGEST_REFERENCE "RFC 3874" # define DIGEST_ALIGN 4 #elif HASH_ALGO_SHA512 +# if HAVE_OPENSSL_SHA512 +# include <openssl/crypto.h> +# define OPENSSL_INIT() OPENSSL_init_crypto (OPENSSL_INIT_ADD_ALL_CIPHERS, \ + nullptr) +# else +# define OPENSSL_INIT() +# endif # define PROGRAM_NAME "sha512sum" # define DIGEST_TYPE_STRING "SHA512" # define DIGEST_STREAM sha512_stream @@ -125,6 +170,13 @@ # define DIGEST_REFERENCE "FIPS-180-2" # define DIGEST_ALIGN 8 #elif HASH_ALGO_SHA384 +# if HAVE_OPENSSL_SHA512 +# include <openssl/crypto.h> +# define OPENSSL_INIT() OPENSSL_init_crypto (OPENSSL_INIT_ADD_ALL_CIPHERS, \ + nullptr) +# else +# define OPENSSL_INIT() +# endif # define PROGRAM_NAME "sha384sum" # define DIGEST_TYPE_STRING "SHA384" # define DIGEST_STREAM sha384_stream @@ -1505,6 +1557,8 @@ main (int argc, char **argv) so that processes running in parallel do not intersperse their output. */ setvbuf (stdout, nullptr, _IOLBF, 0); + OPENSSL_INIT (); + #if HASH_ALGO_SUM char const *short_opts = "rs"; #elif HASH_ALGO_CKSUM Collin
