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



Reply via email to