Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

lib/crypto: arm/sha1: Migrate optimized code into library

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>

+60 -283
-1
arch/arm/configs/exynos_defconfig
··· 363 363 CONFIG_CRYPTO_USER_API_SKCIPHER=m 364 364 CONFIG_CRYPTO_USER_API_RNG=m 365 365 CONFIG_CRYPTO_USER_API_AEAD=m 366 - CONFIG_CRYPTO_SHA1_ARM_NEON=m 367 366 CONFIG_CRYPTO_AES_ARM_BS=m 368 367 CONFIG_CRYPTO_CHACHA20_NEON=m 369 368 CONFIG_CRYPTO_DEV_EXYNOS_RNG=y
-2
arch/arm/configs/milbeaut_m10v_defconfig
··· 98 98 CONFIG_CRYPTO_AES=y 99 99 CONFIG_CRYPTO_SEQIV=m 100 100 CONFIG_CRYPTO_GHASH_ARM_CE=m 101 - CONFIG_CRYPTO_SHA1_ARM_NEON=m 102 - CONFIG_CRYPTO_SHA1_ARM_CE=m 103 101 CONFIG_CRYPTO_AES_ARM=m 104 102 CONFIG_CRYPTO_AES_ARM_BS=m 105 103 CONFIG_CRYPTO_AES_ARM_CE=m
-2
arch/arm/configs/multi_v7_defconfig
··· 1280 1280 CONFIG_CRYPTO_USER_API_RNG=m 1281 1281 CONFIG_CRYPTO_USER_API_AEAD=m 1282 1282 CONFIG_CRYPTO_GHASH_ARM_CE=m 1283 - CONFIG_CRYPTO_SHA1_ARM_NEON=m 1284 - CONFIG_CRYPTO_SHA1_ARM_CE=m 1285 1283 CONFIG_CRYPTO_AES_ARM=m 1286 1284 CONFIG_CRYPTO_AES_ARM_BS=m 1287 1285 CONFIG_CRYPTO_AES_ARM_CE=m
-1
arch/arm/configs/omap2plus_defconfig
··· 704 704 CONFIG_SECURITY=y 705 705 CONFIG_CRYPTO_MICHAEL_MIC=y 706 706 CONFIG_CRYPTO_GHASH_ARM_CE=m 707 - CONFIG_CRYPTO_SHA1_ARM_NEON=m 708 707 CONFIG_CRYPTO_AES_ARM=m 709 708 CONFIG_CRYPTO_AES_ARM_BS=m 710 709 CONFIG_CRYPTO_CHACHA20_NEON=m
-1
arch/arm/configs/pxa_defconfig
··· 658 658 CONFIG_CRYPTO_XCBC=m 659 659 CONFIG_CRYPTO_DEFLATE=y 660 660 CONFIG_CRYPTO_LZO=y 661 - CONFIG_CRYPTO_SHA1_ARM=m 662 661 CONFIG_CRYPTO_AES_ARM=m 663 662 CONFIG_FONTS=y 664 663 CONFIG_FONT_8x8=y
-31
arch/arm/crypto/Kconfig
··· 62 62 much faster than the SHA-2 family and slightly faster than 63 63 SHA-1. 64 64 65 - config CRYPTO_SHA1_ARM 66 - tristate "Hash functions: SHA-1" 67 - select CRYPTO_SHA1 68 - select CRYPTO_HASH 69 - help 70 - SHA-1 secure hash algorithm (FIPS 180) 71 - 72 - Architecture: arm 73 - 74 - config CRYPTO_SHA1_ARM_NEON 75 - tristate "Hash functions: SHA-1 (NEON)" 76 - depends on KERNEL_MODE_NEON 77 - select CRYPTO_SHA1_ARM 78 - select CRYPTO_SHA1 79 - select CRYPTO_HASH 80 - help 81 - SHA-1 secure hash algorithm (FIPS 180) 82 - 83 - Architecture: arm using 84 - - NEON (Advanced SIMD) extensions 85 - 86 - config CRYPTO_SHA1_ARM_CE 87 - tristate "Hash functions: SHA-1 (ARMv8 Crypto Extensions)" 88 - depends on KERNEL_MODE_NEON 89 - select CRYPTO_SHA1_ARM 90 - select CRYPTO_HASH 91 - help 92 - SHA-1 secure hash algorithm (FIPS 180) 93 - 94 - Architecture: arm using ARMv8 Crypto Extensions 95 - 96 65 config CRYPTO_AES_ARM 97 66 tristate "Ciphers: AES" 98 67 select CRYPTO_ALGAPI
-6
arch/arm/crypto/Makefile
··· 5 5 6 6 obj-$(CONFIG_CRYPTO_AES_ARM) += aes-arm.o 7 7 obj-$(CONFIG_CRYPTO_AES_ARM_BS) += aes-arm-bs.o 8 - obj-$(CONFIG_CRYPTO_SHA1_ARM) += sha1-arm.o 9 - obj-$(CONFIG_CRYPTO_SHA1_ARM_NEON) += sha1-arm-neon.o 10 8 obj-$(CONFIG_CRYPTO_BLAKE2B_NEON) += blake2b-neon.o 11 9 obj-$(CONFIG_CRYPTO_NHPOLY1305_NEON) += nhpoly1305-neon.o 12 10 obj-$(CONFIG_CRYPTO_CURVE25519_NEON) += curve25519-neon.o 13 11 14 12 obj-$(CONFIG_CRYPTO_AES_ARM_CE) += aes-arm-ce.o 15 - obj-$(CONFIG_CRYPTO_SHA1_ARM_CE) += sha1-arm-ce.o 16 13 obj-$(CONFIG_CRYPTO_GHASH_ARM_CE) += ghash-arm-ce.o 17 14 18 15 aes-arm-y := aes-cipher-core.o aes-cipher-glue.o 19 16 aes-arm-bs-y := aes-neonbs-core.o aes-neonbs-glue.o 20 - sha1-arm-y := sha1-armv4-large.o sha1_glue.o 21 - sha1-arm-neon-y := sha1-armv7-neon.o sha1_neon_glue.o 22 17 blake2b-neon-y := blake2b-neon-core.o blake2b-neon-glue.o 23 - sha1-arm-ce-y := sha1-ce-core.o sha1-ce-glue.o 24 18 aes-arm-ce-y := aes-ce-core.o aes-ce-glue.o 25 19 ghash-arm-ce-y := ghash-ce-core.o ghash-ce-glue.o 26 20 nhpoly1305-neon-y := nh-neon-core.o nhpoly1305-neon-glue.o
arch/arm/crypto/sha1-armv4-large.S lib/crypto/arm/sha1-armv4-large.S
+6 -7
arch/arm/crypto/sha1-armv7-neon.S lib/crypto/arm/sha1-armv7-neon.S
··· 282 282 283 283 284 284 /* 285 - * Transform nblks*64 bytes (nblks*16 32-bit words) at DATA. 285 + * Transform nblocks*64 bytes (nblocks*16 32-bit words) at DATA. 286 286 * 287 - * unsigned int 288 - * sha1_transform_neon (void *ctx, const unsigned char *data, 289 - * unsigned int nblks) 287 + * void sha1_transform_neon(struct sha1_block_state *state, 288 + * const u8 *data, size_t nblocks); 290 289 */ 291 290 .align 3 292 291 ENTRY(sha1_transform_neon) 293 292 /* input: 294 - * r0: ctx, CTX 295 - * r1: data (64*nblks bytes) 296 - * r2: nblks 293 + * r0: state 294 + * r1: data (64*nblocks bytes) 295 + * r2: nblocks 297 296 */ 298 297 299 298 cmp RNBLKS, #0;
+2 -2
arch/arm/crypto/sha1-ce-core.S lib/crypto/arm/sha1-ce-core.S
··· 59 59 .word 0xca62c1d6, 0xca62c1d6, 0xca62c1d6, 0xca62c1d6 60 60 61 61 /* 62 - * void sha1_ce_transform(struct sha1_state *sst, u8 const *src, 63 - * int blocks); 62 + * void sha1_ce_transform(struct sha1_block_state *state, 63 + * const u8 *data, size_t nblocks); 64 64 */ 65 65 ENTRY(sha1_ce_transform) 66 66 /* load round constants */
-72
arch/arm/crypto/sha1-ce-glue.c
··· 1 - // SPDX-License-Identifier: GPL-2.0-only 2 - /* 3 - * sha1-ce-glue.c - SHA-1 secure hash using ARMv8 Crypto Extensions 4 - * 5 - * Copyright (C) 2015 Linaro Ltd <ard.biesheuvel@linaro.org> 6 - */ 7 - 8 - #include <asm/neon.h> 9 - #include <crypto/internal/hash.h> 10 - #include <crypto/sha1.h> 11 - #include <crypto/sha1_base.h> 12 - #include <linux/cpufeature.h> 13 - #include <linux/kernel.h> 14 - #include <linux/module.h> 15 - 16 - MODULE_DESCRIPTION("SHA1 secure hash using ARMv8 Crypto Extensions"); 17 - MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>"); 18 - MODULE_LICENSE("GPL v2"); 19 - 20 - asmlinkage void sha1_ce_transform(struct sha1_state *sst, u8 const *src, 21 - int blocks); 22 - 23 - static int sha1_ce_update(struct shash_desc *desc, const u8 *data, 24 - unsigned int len) 25 - { 26 - int remain; 27 - 28 - kernel_neon_begin(); 29 - remain = sha1_base_do_update_blocks(desc, data, len, sha1_ce_transform); 30 - kernel_neon_end(); 31 - 32 - return remain; 33 - } 34 - 35 - static int sha1_ce_finup(struct shash_desc *desc, const u8 *data, 36 - unsigned int len, u8 *out) 37 - { 38 - kernel_neon_begin(); 39 - sha1_base_do_finup(desc, data, len, sha1_ce_transform); 40 - kernel_neon_end(); 41 - 42 - return sha1_base_finish(desc, out); 43 - } 44 - 45 - static struct shash_alg alg = { 46 - .init = sha1_base_init, 47 - .update = sha1_ce_update, 48 - .finup = sha1_ce_finup, 49 - .descsize = SHA1_STATE_SIZE, 50 - .digestsize = SHA1_DIGEST_SIZE, 51 - .base = { 52 - .cra_name = "sha1", 53 - .cra_driver_name = "sha1-ce", 54 - .cra_priority = 200, 55 - .cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY, 56 - .cra_blocksize = SHA1_BLOCK_SIZE, 57 - .cra_module = THIS_MODULE, 58 - } 59 - }; 60 - 61 - static int __init sha1_ce_mod_init(void) 62 - { 63 - return crypto_register_shash(&alg); 64 - } 65 - 66 - static void __exit sha1_ce_mod_fini(void) 67 - { 68 - crypto_unregister_shash(&alg); 69 - } 70 - 71 - module_cpu_feature_match(SHA1, sha1_ce_mod_init); 72 - module_exit(sha1_ce_mod_fini);
-75
arch/arm/crypto/sha1_glue.c
··· 1 - // SPDX-License-Identifier: GPL-2.0-or-later 2 - /* 3 - * Cryptographic API. 4 - * Glue code for the SHA1 Secure Hash Algorithm assembler implementation 5 - * 6 - * This file is based on sha1_generic.c and sha1_ssse3_glue.c 7 - * 8 - * Copyright (c) Alan Smithee. 9 - * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk> 10 - * Copyright (c) Jean-Francois Dive <jef@linuxbe.org> 11 - * Copyright (c) Mathias Krause <minipli@googlemail.com> 12 - */ 13 - 14 - #include <crypto/internal/hash.h> 15 - #include <crypto/sha1.h> 16 - #include <crypto/sha1_base.h> 17 - #include <linux/kernel.h> 18 - #include <linux/module.h> 19 - 20 - asmlinkage void sha1_block_data_order(struct sha1_state *digest, 21 - const u8 *data, int rounds); 22 - 23 - static int sha1_update_arm(struct shash_desc *desc, const u8 *data, 24 - unsigned int len) 25 - { 26 - /* make sure signature matches sha1_block_fn() */ 27 - BUILD_BUG_ON(offsetof(struct sha1_state, state) != 0); 28 - 29 - return sha1_base_do_update_blocks(desc, data, len, 30 - sha1_block_data_order); 31 - } 32 - 33 - static int sha1_finup_arm(struct shash_desc *desc, const u8 *data, 34 - unsigned int len, u8 *out) 35 - { 36 - sha1_base_do_finup(desc, data, len, sha1_block_data_order); 37 - return sha1_base_finish(desc, out); 38 - } 39 - 40 - static struct shash_alg alg = { 41 - .digestsize = SHA1_DIGEST_SIZE, 42 - .init = sha1_base_init, 43 - .update = sha1_update_arm, 44 - .finup = sha1_finup_arm, 45 - .descsize = SHA1_STATE_SIZE, 46 - .base = { 47 - .cra_name = "sha1", 48 - .cra_driver_name= "sha1-asm", 49 - .cra_priority = 150, 50 - .cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY, 51 - .cra_blocksize = SHA1_BLOCK_SIZE, 52 - .cra_module = THIS_MODULE, 53 - } 54 - }; 55 - 56 - 57 - static int __init sha1_mod_init(void) 58 - { 59 - return crypto_register_shash(&alg); 60 - } 61 - 62 - 63 - static void __exit sha1_mod_fini(void) 64 - { 65 - crypto_unregister_shash(&alg); 66 - } 67 - 68 - 69 - module_init(sha1_mod_init); 70 - module_exit(sha1_mod_fini); 71 - 72 - MODULE_LICENSE("GPL"); 73 - MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm (ARM)"); 74 - MODULE_ALIAS_CRYPTO("sha1"); 75 - MODULE_AUTHOR("David McCullough <ucdevel@gmail.com>");
-83
arch/arm/crypto/sha1_neon_glue.c
··· 1 - // SPDX-License-Identifier: GPL-2.0-or-later 2 - /* 3 - * Glue code for the SHA1 Secure Hash Algorithm assembler implementation using 4 - * ARM NEON instructions. 5 - * 6 - * Copyright © 2014 Jussi Kivilinna <jussi.kivilinna@iki.fi> 7 - * 8 - * This file is based on sha1_generic.c and sha1_ssse3_glue.c: 9 - * Copyright (c) Alan Smithee. 10 - * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk> 11 - * Copyright (c) Jean-Francois Dive <jef@linuxbe.org> 12 - * Copyright (c) Mathias Krause <minipli@googlemail.com> 13 - * Copyright (c) Chandramouli Narayanan <mouli@linux.intel.com> 14 - */ 15 - 16 - #include <asm/neon.h> 17 - #include <crypto/internal/hash.h> 18 - #include <crypto/sha1.h> 19 - #include <crypto/sha1_base.h> 20 - #include <linux/kernel.h> 21 - #include <linux/module.h> 22 - 23 - asmlinkage void sha1_transform_neon(struct sha1_state *state_h, 24 - const u8 *data, int rounds); 25 - 26 - static int sha1_neon_update(struct shash_desc *desc, const u8 *data, 27 - unsigned int len) 28 - { 29 - int remain; 30 - 31 - kernel_neon_begin(); 32 - remain = sha1_base_do_update_blocks(desc, data, len, 33 - sha1_transform_neon); 34 - kernel_neon_end(); 35 - 36 - return remain; 37 - } 38 - 39 - static int sha1_neon_finup(struct shash_desc *desc, const u8 *data, 40 - unsigned int len, u8 *out) 41 - { 42 - kernel_neon_begin(); 43 - sha1_base_do_finup(desc, data, len, sha1_transform_neon); 44 - kernel_neon_end(); 45 - 46 - return sha1_base_finish(desc, out); 47 - } 48 - 49 - static struct shash_alg alg = { 50 - .digestsize = SHA1_DIGEST_SIZE, 51 - .init = sha1_base_init, 52 - .update = sha1_neon_update, 53 - .finup = sha1_neon_finup, 54 - .descsize = SHA1_STATE_SIZE, 55 - .base = { 56 - .cra_name = "sha1", 57 - .cra_driver_name = "sha1-neon", 58 - .cra_priority = 250, 59 - .cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY, 60 - .cra_blocksize = SHA1_BLOCK_SIZE, 61 - .cra_module = THIS_MODULE, 62 - } 63 - }; 64 - 65 - static int __init sha1_neon_mod_init(void) 66 - { 67 - if (!cpu_has_neon()) 68 - return -ENODEV; 69 - 70 - return crypto_register_shash(&alg); 71 - } 72 - 73 - static void __exit sha1_neon_mod_fini(void) 74 - { 75 - crypto_unregister_shash(&alg); 76 - } 77 - 78 - module_init(sha1_neon_mod_init); 79 - module_exit(sha1_neon_mod_fini); 80 - 81 - MODULE_LICENSE("GPL"); 82 - MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm, NEON accelerated"); 83 - MODULE_ALIAS_CRYPTO("sha1");
+1
lib/crypto/Kconfig
··· 146 146 config CRYPTO_LIB_SHA1_ARCH 147 147 bool 148 148 depends on CRYPTO_LIB_SHA1 && !UML 149 + default y if ARM 149 150 150 151 config CRYPTO_LIB_SHA256 151 152 tristate
+5
lib/crypto/Makefile
··· 71 71 libsha1-y := sha1.o 72 72 ifeq ($(CONFIG_CRYPTO_LIB_SHA1_ARCH),y) 73 73 CFLAGS_sha1.o += -I$(src)/$(SRCARCH) 74 + ifeq ($(CONFIG_ARM),y) 75 + libsha1-y += arm/sha1-armv4-large.o 76 + libsha1-$(CONFIG_KERNEL_MODE_NEON) += arm/sha1-armv7-neon.o \ 77 + arm/sha1-ce-core.o 78 + endif 74 79 endif # CONFIG_CRYPTO_LIB_SHA1_ARCH 75 80 76 81 ################################################################################
+46
lib/crypto/arm/sha1.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 + /* 3 + * SHA-1 optimized for ARM 4 + * 5 + * Copyright 2025 Google LLC 6 + */ 7 + #include <asm/neon.h> 8 + #include <asm/simd.h> 9 + 10 + static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_neon); 11 + static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_ce); 12 + 13 + asmlinkage void sha1_block_data_order(struct sha1_block_state *state, 14 + const u8 *data, size_t nblocks); 15 + asmlinkage void sha1_transform_neon(struct sha1_block_state *state, 16 + const u8 *data, size_t nblocks); 17 + asmlinkage void sha1_ce_transform(struct sha1_block_state *state, 18 + const u8 *data, size_t nblocks); 19 + 20 + static void sha1_blocks(struct sha1_block_state *state, 21 + const u8 *data, size_t nblocks) 22 + { 23 + if (IS_ENABLED(CONFIG_KERNEL_MODE_NEON) && 24 + static_branch_likely(&have_neon) && likely(may_use_simd())) { 25 + kernel_neon_begin(); 26 + if (static_branch_likely(&have_ce)) 27 + sha1_ce_transform(state, data, nblocks); 28 + else 29 + sha1_transform_neon(state, data, nblocks); 30 + kernel_neon_end(); 31 + } else { 32 + sha1_block_data_order(state, data, nblocks); 33 + } 34 + } 35 + 36 + #ifdef CONFIG_KERNEL_MODE_NEON 37 + #define sha1_mod_init_arch sha1_mod_init_arch 38 + static inline void sha1_mod_init_arch(void) 39 + { 40 + if (elf_hwcap & HWCAP_NEON) { 41 + static_branch_enable(&have_neon); 42 + if (elf_hwcap2 & HWCAP2_SHA1) 43 + static_branch_enable(&have_ce); 44 + } 45 + } 46 + #endif /* CONFIG_KERNEL_MODE_NEON */