]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
lib/crypto: arm/sha1: Migrate optimized code into library
authorEric Biggers <ebiggers@kernel.org>
Sat, 12 Jul 2025 23:22:58 +0000 (16:22 -0700)
committerEric Biggers <ebiggers@kernel.org>
Mon, 14 Jul 2025 18:11:29 +0000 (11:11 -0700)
Instead of exposing the arm-optimized SHA-1 code via arm-specific
crypto_shash algorithms, instead just implement the sha1_blocks()
library function.  This is much simpler, it makes the SHA-1 library
functions be arm-optimized, and it fixes the longstanding issue where
the arm-optimized SHA-1 code was disabled by default.  SHA-1 still
remains available through crypto_shash, but individual architectures no
longer need to handle it.

To match sha1_blocks(), change the type of the nblocks parameter of the
assembly functions from int to size_t.  The assembly functions actually
already treated it as size_t.

Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
Link: https://lore.kernel.org/r/20250712232329.818226-8-ebiggers@kernel.org
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
16 files changed:
arch/arm/configs/exynos_defconfig
arch/arm/configs/milbeaut_m10v_defconfig
arch/arm/configs/multi_v7_defconfig
arch/arm/configs/omap2plus_defconfig
arch/arm/configs/pxa_defconfig
arch/arm/crypto/Kconfig
arch/arm/crypto/Makefile
arch/arm/crypto/sha1-ce-glue.c [deleted file]
arch/arm/crypto/sha1_glue.c [deleted file]
arch/arm/crypto/sha1_neon_glue.c [deleted file]
lib/crypto/Kconfig
lib/crypto/Makefile
lib/crypto/arm/sha1-armv4-large.S [moved from arch/arm/crypto/sha1-armv4-large.S with 100% similarity]
lib/crypto/arm/sha1-armv7-neon.S [moved from arch/arm/crypto/sha1-armv7-neon.S with 98% similarity]
lib/crypto/arm/sha1-ce-core.S [moved from arch/arm/crypto/sha1-ce-core.S with 96% similarity]
lib/crypto/arm/sha1.h [new file with mode: 0644]

index d58e300693045ad96d5236e5141da3ec417e4fd5..6915c766923a2faad63afa5045c94c1b2d19ddfd 100644 (file)
@@ -363,7 +363,6 @@ CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
 CONFIG_CRYPTO_USER_API_RNG=m
 CONFIG_CRYPTO_USER_API_AEAD=m
-CONFIG_CRYPTO_SHA1_ARM_NEON=m
 CONFIG_CRYPTO_AES_ARM_BS=m
 CONFIG_CRYPTO_CHACHA20_NEON=m
 CONFIG_CRYPTO_DEV_EXYNOS_RNG=y
index 8ebf8bd872fe8a3693ccd507eb52a4cdb91eedab..a3be0b2ede09c7b32da0ce151d4ddebd606d39bc 100644 (file)
@@ -98,8 +98,6 @@ CONFIG_CRYPTO_SELFTESTS=y
 CONFIG_CRYPTO_AES=y
 CONFIG_CRYPTO_SEQIV=m
 CONFIG_CRYPTO_GHASH_ARM_CE=m
-CONFIG_CRYPTO_SHA1_ARM_NEON=m
-CONFIG_CRYPTO_SHA1_ARM_CE=m
 CONFIG_CRYPTO_AES_ARM=m
 CONFIG_CRYPTO_AES_ARM_BS=m
 CONFIG_CRYPTO_AES_ARM_CE=m
index 3fd07e864ca8554e29c11e8e86bb320c8b8e3afc..fb63f487a623222ff07580797627227ab4e97605 100644 (file)
@@ -1280,8 +1280,6 @@ CONFIG_CRYPTO_USER_API_SKCIPHER=m
 CONFIG_CRYPTO_USER_API_RNG=m
 CONFIG_CRYPTO_USER_API_AEAD=m
 CONFIG_CRYPTO_GHASH_ARM_CE=m
-CONFIG_CRYPTO_SHA1_ARM_NEON=m
-CONFIG_CRYPTO_SHA1_ARM_CE=m
 CONFIG_CRYPTO_AES_ARM=m
 CONFIG_CRYPTO_AES_ARM_BS=m
 CONFIG_CRYPTO_AES_ARM_CE=m
index 530dfb8338c98e6d2eb4936fb533f21cb56d8298..046467637901323ba4cbcc480712973edb265503 100644 (file)
@@ -704,7 +704,6 @@ CONFIG_NLS_ISO8859_1=y
 CONFIG_SECURITY=y
 CONFIG_CRYPTO_MICHAEL_MIC=y
 CONFIG_CRYPTO_GHASH_ARM_CE=m
-CONFIG_CRYPTO_SHA1_ARM_NEON=m
 CONFIG_CRYPTO_AES_ARM=m
 CONFIG_CRYPTO_AES_ARM_BS=m
 CONFIG_CRYPTO_CHACHA20_NEON=m
index eaa44574d4a64603811f5983e509a4a7bd44c19e..1a80602c12845d2faad55468894d6f561c6f19de 100644 (file)
@@ -658,7 +658,6 @@ CONFIG_CRYPTO_ANUBIS=m
 CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_DEFLATE=y
 CONFIG_CRYPTO_LZO=y
-CONFIG_CRYPTO_SHA1_ARM=m
 CONFIG_CRYPTO_AES_ARM=m
 CONFIG_FONTS=y
 CONFIG_FONT_8x8=y
index a18f97f1597cbe7b46bfa9aed92b755862d65561..1e5f3cdf691c4f7390ca817b239cb61855bb848d 100644 (file)
@@ -62,37 +62,6 @@ config CRYPTO_BLAKE2B_NEON
          much faster than the SHA-2 family and slightly faster than
          SHA-1.
 
-config CRYPTO_SHA1_ARM
-       tristate "Hash functions: SHA-1"
-       select CRYPTO_SHA1
-       select CRYPTO_HASH
-       help
-         SHA-1 secure hash algorithm (FIPS 180)
-
-         Architecture: arm
-
-config CRYPTO_SHA1_ARM_NEON
-       tristate "Hash functions: SHA-1 (NEON)"
-       depends on KERNEL_MODE_NEON
-       select CRYPTO_SHA1_ARM
-       select CRYPTO_SHA1
-       select CRYPTO_HASH
-       help
-         SHA-1 secure hash algorithm (FIPS 180)
-
-         Architecture: arm using
-         - NEON (Advanced SIMD) extensions
-
-config CRYPTO_SHA1_ARM_CE
-       tristate "Hash functions: SHA-1 (ARMv8 Crypto Extensions)"
-       depends on KERNEL_MODE_NEON
-       select CRYPTO_SHA1_ARM
-       select CRYPTO_HASH
-       help
-         SHA-1 secure hash algorithm (FIPS 180)
-
-         Architecture: arm using ARMv8 Crypto Extensions
-
 config CRYPTO_AES_ARM
        tristate "Ciphers: AES"
        select CRYPTO_ALGAPI
index 78a4042d8761c14baf0fbfa85560e8262b35cd0c..4f23999ae17dfe3d27626bb04bb9c19d453605b4 100644 (file)
@@ -5,22 +5,16 @@
 
 obj-$(CONFIG_CRYPTO_AES_ARM) += aes-arm.o
 obj-$(CONFIG_CRYPTO_AES_ARM_BS) += aes-arm-bs.o
-obj-$(CONFIG_CRYPTO_SHA1_ARM) += sha1-arm.o
-obj-$(CONFIG_CRYPTO_SHA1_ARM_NEON) += sha1-arm-neon.o
 obj-$(CONFIG_CRYPTO_BLAKE2B_NEON) += blake2b-neon.o
 obj-$(CONFIG_CRYPTO_NHPOLY1305_NEON) += nhpoly1305-neon.o
 obj-$(CONFIG_CRYPTO_CURVE25519_NEON) += curve25519-neon.o
 
 obj-$(CONFIG_CRYPTO_AES_ARM_CE) += aes-arm-ce.o
-obj-$(CONFIG_CRYPTO_SHA1_ARM_CE) += sha1-arm-ce.o
 obj-$(CONFIG_CRYPTO_GHASH_ARM_CE) += ghash-arm-ce.o
 
 aes-arm-y      := aes-cipher-core.o aes-cipher-glue.o
 aes-arm-bs-y   := aes-neonbs-core.o aes-neonbs-glue.o
-sha1-arm-y     := sha1-armv4-large.o sha1_glue.o
-sha1-arm-neon-y        := sha1-armv7-neon.o sha1_neon_glue.o
 blake2b-neon-y  := blake2b-neon-core.o blake2b-neon-glue.o
-sha1-arm-ce-y  := sha1-ce-core.o sha1-ce-glue.o
 aes-arm-ce-y   := aes-ce-core.o aes-ce-glue.o
 ghash-arm-ce-y := ghash-ce-core.o ghash-ce-glue.o
 nhpoly1305-neon-y := nh-neon-core.o nhpoly1305-neon-glue.o
diff --git a/arch/arm/crypto/sha1-ce-glue.c b/arch/arm/crypto/sha1-ce-glue.c
deleted file mode 100644 (file)
index fac07a4..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * sha1-ce-glue.c - SHA-1 secure hash using ARMv8 Crypto Extensions
- *
- * Copyright (C) 2015 Linaro Ltd <ard.biesheuvel@linaro.org>
- */
-
-#include <asm/neon.h>
-#include <crypto/internal/hash.h>
-#include <crypto/sha1.h>
-#include <crypto/sha1_base.h>
-#include <linux/cpufeature.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-
-MODULE_DESCRIPTION("SHA1 secure hash using ARMv8 Crypto Extensions");
-MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
-MODULE_LICENSE("GPL v2");
-
-asmlinkage void sha1_ce_transform(struct sha1_state *sst, u8 const *src,
-                                 int blocks);
-
-static int sha1_ce_update(struct shash_desc *desc, const u8 *data,
-                         unsigned int len)
-{
-       int remain;
-
-       kernel_neon_begin();
-       remain = sha1_base_do_update_blocks(desc, data, len, sha1_ce_transform);
-       kernel_neon_end();
-
-       return remain;
-}
-
-static int sha1_ce_finup(struct shash_desc *desc, const u8 *data,
-                        unsigned int len, u8 *out)
-{
-       kernel_neon_begin();
-       sha1_base_do_finup(desc, data, len, sha1_ce_transform);
-       kernel_neon_end();
-
-       return sha1_base_finish(desc, out);
-}
-
-static struct shash_alg alg = {
-       .init                   = sha1_base_init,
-       .update                 = sha1_ce_update,
-       .finup                  = sha1_ce_finup,
-       .descsize               = SHA1_STATE_SIZE,
-       .digestsize             = SHA1_DIGEST_SIZE,
-       .base                   = {
-               .cra_name               = "sha1",
-               .cra_driver_name        = "sha1-ce",
-               .cra_priority           = 200,
-               .cra_flags              = CRYPTO_AHASH_ALG_BLOCK_ONLY,
-               .cra_blocksize          = SHA1_BLOCK_SIZE,
-               .cra_module             = THIS_MODULE,
-       }
-};
-
-static int __init sha1_ce_mod_init(void)
-{
-       return crypto_register_shash(&alg);
-}
-
-static void __exit sha1_ce_mod_fini(void)
-{
-       crypto_unregister_shash(&alg);
-}
-
-module_cpu_feature_match(SHA1, sha1_ce_mod_init);
-module_exit(sha1_ce_mod_fini);
diff --git a/arch/arm/crypto/sha1_glue.c b/arch/arm/crypto/sha1_glue.c
deleted file mode 100644 (file)
index 255da00..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Cryptographic API.
- * Glue code for the SHA1 Secure Hash Algorithm assembler implementation
- *
- * This file is based on sha1_generic.c and sha1_ssse3_glue.c
- *
- * Copyright (c) Alan Smithee.
- * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
- * Copyright (c) Jean-Francois Dive <jef@linuxbe.org>
- * Copyright (c) Mathias Krause <minipli@googlemail.com>
- */
-
-#include <crypto/internal/hash.h>
-#include <crypto/sha1.h>
-#include <crypto/sha1_base.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-
-asmlinkage void sha1_block_data_order(struct sha1_state *digest,
-               const u8 *data, int rounds);
-
-static int sha1_update_arm(struct shash_desc *desc, const u8 *data,
-                          unsigned int len)
-{
-       /* make sure signature matches sha1_block_fn() */
-       BUILD_BUG_ON(offsetof(struct sha1_state, state) != 0);
-
-       return sha1_base_do_update_blocks(desc, data, len,
-                                         sha1_block_data_order);
-}
-
-static int sha1_finup_arm(struct shash_desc *desc, const u8 *data,
-                         unsigned int len, u8 *out)
-{
-       sha1_base_do_finup(desc, data, len, sha1_block_data_order);
-       return sha1_base_finish(desc, out);
-}
-
-static struct shash_alg alg = {
-       .digestsize     =       SHA1_DIGEST_SIZE,
-       .init           =       sha1_base_init,
-       .update         =       sha1_update_arm,
-       .finup          =       sha1_finup_arm,
-       .descsize       =       SHA1_STATE_SIZE,
-       .base           =       {
-               .cra_name       =       "sha1",
-               .cra_driver_name=       "sha1-asm",
-               .cra_priority   =       150,
-               .cra_flags      =       CRYPTO_AHASH_ALG_BLOCK_ONLY,
-               .cra_blocksize  =       SHA1_BLOCK_SIZE,
-               .cra_module     =       THIS_MODULE,
-       }
-};
-
-
-static int __init sha1_mod_init(void)
-{
-       return crypto_register_shash(&alg);
-}
-
-
-static void __exit sha1_mod_fini(void)
-{
-       crypto_unregister_shash(&alg);
-}
-
-
-module_init(sha1_mod_init);
-module_exit(sha1_mod_fini);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm (ARM)");
-MODULE_ALIAS_CRYPTO("sha1");
-MODULE_AUTHOR("David McCullough <ucdevel@gmail.com>");
diff --git a/arch/arm/crypto/sha1_neon_glue.c b/arch/arm/crypto/sha1_neon_glue.c
deleted file mode 100644 (file)
index d321850..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Glue code for the SHA1 Secure Hash Algorithm assembler implementation using
- * ARM NEON instructions.
- *
- * Copyright © 2014 Jussi Kivilinna <jussi.kivilinna@iki.fi>
- *
- * This file is based on sha1_generic.c and sha1_ssse3_glue.c:
- *  Copyright (c) Alan Smithee.
- *  Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
- *  Copyright (c) Jean-Francois Dive <jef@linuxbe.org>
- *  Copyright (c) Mathias Krause <minipli@googlemail.com>
- *  Copyright (c) Chandramouli Narayanan <mouli@linux.intel.com>
- */
-
-#include <asm/neon.h>
-#include <crypto/internal/hash.h>
-#include <crypto/sha1.h>
-#include <crypto/sha1_base.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-
-asmlinkage void sha1_transform_neon(struct sha1_state *state_h,
-                                   const u8 *data, int rounds);
-
-static int sha1_neon_update(struct shash_desc *desc, const u8 *data,
-                         unsigned int len)
-{
-       int remain;
-
-       kernel_neon_begin();
-       remain = sha1_base_do_update_blocks(desc, data, len,
-                                           sha1_transform_neon);
-       kernel_neon_end();
-
-       return remain;
-}
-
-static int sha1_neon_finup(struct shash_desc *desc, const u8 *data,
-                          unsigned int len, u8 *out)
-{
-       kernel_neon_begin();
-       sha1_base_do_finup(desc, data, len, sha1_transform_neon);
-       kernel_neon_end();
-
-       return sha1_base_finish(desc, out);
-}
-
-static struct shash_alg alg = {
-       .digestsize     =       SHA1_DIGEST_SIZE,
-       .init           =       sha1_base_init,
-       .update         =       sha1_neon_update,
-       .finup          =       sha1_neon_finup,
-       .descsize               = SHA1_STATE_SIZE,
-       .base           =       {
-               .cra_name               = "sha1",
-               .cra_driver_name        = "sha1-neon",
-               .cra_priority           = 250,
-               .cra_flags              = CRYPTO_AHASH_ALG_BLOCK_ONLY,
-               .cra_blocksize          = SHA1_BLOCK_SIZE,
-               .cra_module             = THIS_MODULE,
-       }
-};
-
-static int __init sha1_neon_mod_init(void)
-{
-       if (!cpu_has_neon())
-               return -ENODEV;
-
-       return crypto_register_shash(&alg);
-}
-
-static void __exit sha1_neon_mod_fini(void)
-{
-       crypto_unregister_shash(&alg);
-}
-
-module_init(sha1_neon_mod_init);
-module_exit(sha1_neon_mod_fini);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm, NEON accelerated");
-MODULE_ALIAS_CRYPTO("sha1");
index 5aaf484fc9de43654deca5b60368a8a7beb76456..519c5d6a050fddff2941b83202f8f99b0d55b1e1 100644 (file)
@@ -146,6 +146,7 @@ config CRYPTO_LIB_SHA1
 config CRYPTO_LIB_SHA1_ARCH
        bool
        depends on CRYPTO_LIB_SHA1 && !UML
+       default y if ARM
 
 config CRYPTO_LIB_SHA256
        tristate
index 0eb0906d693f2f0de6d7f51beb2a536594fee807..699a421339271cf926b3b646df116a67a4691d98 100644 (file)
@@ -71,6 +71,11 @@ obj-$(CONFIG_CRYPTO_LIB_SHA1) += libsha1.o
 libsha1-y := sha1.o
 ifeq ($(CONFIG_CRYPTO_LIB_SHA1_ARCH),y)
 CFLAGS_sha1.o += -I$(src)/$(SRCARCH)
+ifeq ($(CONFIG_ARM),y)
+libsha1-y += arm/sha1-armv4-large.o
+libsha1-$(CONFIG_KERNEL_MODE_NEON) += arm/sha1-armv7-neon.o \
+                                     arm/sha1-ce-core.o
+endif
 endif # CONFIG_CRYPTO_LIB_SHA1_ARCH
 
 ################################################################################
similarity index 98%
rename from arch/arm/crypto/sha1-armv7-neon.S
rename to lib/crypto/arm/sha1-armv7-neon.S
index 28d816a6a530777af2b1b4f32052afbbb7a28728..6edba3ab62e8b940ab835e7349e9459379f19bf4 100644 (file)
 
 
 /*
- * Transform nblks*64 bytes (nblks*16 32-bit words) at DATA.
+ * Transform nblocks*64 bytes (nblocks*16 32-bit words) at DATA.
  *
- * unsigned int
- * sha1_transform_neon (void *ctx, const unsigned char *data,
- *                      unsigned int nblks)
+ * void sha1_transform_neon(struct sha1_block_state *state,
+ *                         const u8 *data, size_t nblocks);
  */
 .align 3
 ENTRY(sha1_transform_neon)
   /* input:
-   *   r0: ctx, CTX
-   *   r1: data (64*nblks bytes)
-   *   r2: nblks
+   *   r0: state
+   *   r1: data (64*nblocks bytes)
+   *   r2: nblocks
    */
 
   cmp RNBLKS, #0;
similarity index 96%
rename from arch/arm/crypto/sha1-ce-core.S
rename to lib/crypto/arm/sha1-ce-core.S
index 8a702e051738a3712765b51c15a74bb4079cfe35..2de40dd25e47e8ada3c66877a1b09720c3032496 100644 (file)
@@ -59,8 +59,8 @@
        .word           0xca62c1d6, 0xca62c1d6, 0xca62c1d6, 0xca62c1d6
 
        /*
-        * void sha1_ce_transform(struct sha1_state *sst, u8 const *src,
-        *                        int blocks);
+        * void sha1_ce_transform(struct sha1_block_state *state,
+        *                        const u8 *data, size_t nblocks);
         */
 ENTRY(sha1_ce_transform)
        /* load round constants */
diff --git a/lib/crypto/arm/sha1.h b/lib/crypto/arm/sha1.h
new file mode 100644 (file)
index 0000000..fa1e924
--- /dev/null
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * SHA-1 optimized for ARM
+ *
+ * Copyright 2025 Google LLC
+ */
+#include <asm/neon.h>
+#include <asm/simd.h>
+
+static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_neon);
+static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_ce);
+
+asmlinkage void sha1_block_data_order(struct sha1_block_state *state,
+                                     const u8 *data, size_t nblocks);
+asmlinkage void sha1_transform_neon(struct sha1_block_state *state,
+                                   const u8 *data, size_t nblocks);
+asmlinkage void sha1_ce_transform(struct sha1_block_state *state,
+                                 const u8 *data, size_t nblocks);
+
+static void sha1_blocks(struct sha1_block_state *state,
+                       const u8 *data, size_t nblocks)
+{
+       if (IS_ENABLED(CONFIG_KERNEL_MODE_NEON) &&
+           static_branch_likely(&have_neon) && likely(may_use_simd())) {
+               kernel_neon_begin();
+               if (static_branch_likely(&have_ce))
+                       sha1_ce_transform(state, data, nblocks);
+               else
+                       sha1_transform_neon(state, data, nblocks);
+               kernel_neon_end();
+       } else {
+               sha1_block_data_order(state, data, nblocks);
+       }
+}
+
+#ifdef CONFIG_KERNEL_MODE_NEON
+#define sha1_mod_init_arch sha1_mod_init_arch
+static inline void sha1_mod_init_arch(void)
+{
+       if (elf_hwcap & HWCAP_NEON) {
+               static_branch_enable(&have_neon);
+               if (elf_hwcap2 & HWCAP2_SHA1)
+                       static_branch_enable(&have_ce);
+       }
+}
+#endif /* CONFIG_KERNEL_MODE_NEON */