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

lib/crypto: sparc/sha512: Migrate optimized SHA-512 code to library

Instead of exposing the sparc-optimized SHA-512 code via sparc-specific
crypto_shash algorithms, instead just implement the sha512_blocks()
library function. This is much simpler, it makes the SHA-512 (and
SHA-384) library functions be sparc-optimized, and it fixes the
longstanding issue where the sparc-optimized SHA-512 code was disabled
by default. SHA-512 still remains available through crypto_shash, but
individual architectures no longer need to handle it.

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

Note: to see the diff from arch/sparc/crypto/sha512_glue.c to
lib/crypto/sparc/sha512.h, view this commit with 'git show -M10'.

Acked-by: Ard Biesheuvel <ardb@kernel.org>
Link: https://lore.kernel.org/r/20250630160320.2888-14-ebiggers@kernel.org
Signed-off-by: Eric Biggers <ebiggers@kernel.org>

+44 -134
-10
arch/sparc/crypto/Kconfig
··· 36 36 37 37 Architecture: sparc64 38 38 39 - config CRYPTO_SHA512_SPARC64 40 - tristate "Hash functions: SHA-384 and SHA-512" 41 - depends on SPARC64 42 - select CRYPTO_SHA512 43 - select CRYPTO_HASH 44 - help 45 - SHA-384 and SHA-512 secure hash algorithms (FIPS 180) 46 - 47 - Architecture: sparc64 using crypto instructions, when available 48 - 49 39 config CRYPTO_AES_SPARC64 50 40 tristate "Ciphers: AES, modes: ECB, CBC, CTR" 51 41 depends on SPARC64
-2
arch/sparc/crypto/Makefile
··· 4 4 # 5 5 6 6 obj-$(CONFIG_CRYPTO_SHA1_SPARC64) += sha1-sparc64.o 7 - obj-$(CONFIG_CRYPTO_SHA512_SPARC64) += sha512-sparc64.o 8 7 obj-$(CONFIG_CRYPTO_MD5_SPARC64) += md5-sparc64.o 9 8 10 9 obj-$(CONFIG_CRYPTO_AES_SPARC64) += aes-sparc64.o ··· 11 12 obj-$(CONFIG_CRYPTO_CAMELLIA_SPARC64) += camellia-sparc64.o 12 13 13 14 sha1-sparc64-y := sha1_asm.o sha1_glue.o 14 - sha512-sparc64-y := sha512_asm.o sha512_glue.o 15 15 md5-sparc64-y := md5_asm.o md5_glue.o 16 16 17 17 aes-sparc64-y := aes_asm.o aes_glue.o
arch/sparc/crypto/sha512_asm.S lib/crypto/sparc/sha512_asm.S
-122
arch/sparc/crypto/sha512_glue.c
··· 1 - // SPDX-License-Identifier: GPL-2.0-only 2 - /* Glue code for SHA512 hashing optimized for sparc64 crypto opcodes. 3 - * 4 - * This is based largely upon crypto/sha512_generic.c 5 - * 6 - * Copyright (c) Jean-Luc Cooke <jlcooke@certainkey.com> 7 - * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk> 8 - * Copyright (c) 2003 Kyle McMartin <kyle@debian.org> 9 - */ 10 - 11 - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 12 - 13 - #include <asm/elf.h> 14 - #include <asm/opcodes.h> 15 - #include <asm/pstate.h> 16 - #include <crypto/internal/hash.h> 17 - #include <crypto/sha2.h> 18 - #include <crypto/sha512_base.h> 19 - #include <linux/kernel.h> 20 - #include <linux/module.h> 21 - 22 - asmlinkage void sha512_sparc64_transform(u64 *digest, const char *data, 23 - unsigned int rounds); 24 - 25 - static void sha512_block(struct sha512_state *sctx, const u8 *src, int blocks) 26 - { 27 - sha512_sparc64_transform(sctx->state, src, blocks); 28 - } 29 - 30 - static int sha512_sparc64_update(struct shash_desc *desc, const u8 *data, 31 - unsigned int len) 32 - { 33 - return sha512_base_do_update_blocks(desc, data, len, sha512_block); 34 - } 35 - 36 - static int sha512_sparc64_finup(struct shash_desc *desc, const u8 *src, 37 - unsigned int len, u8 *out) 38 - { 39 - sha512_base_do_finup(desc, src, len, sha512_block); 40 - return sha512_base_finish(desc, out); 41 - } 42 - 43 - static struct shash_alg sha512_alg = { 44 - .digestsize = SHA512_DIGEST_SIZE, 45 - .init = sha512_base_init, 46 - .update = sha512_sparc64_update, 47 - .finup = sha512_sparc64_finup, 48 - .descsize = SHA512_STATE_SIZE, 49 - .base = { 50 - .cra_name = "sha512", 51 - .cra_driver_name= "sha512-sparc64", 52 - .cra_priority = SPARC_CR_OPCODE_PRIORITY, 53 - .cra_blocksize = SHA512_BLOCK_SIZE, 54 - .cra_module = THIS_MODULE, 55 - } 56 - }; 57 - 58 - static struct shash_alg sha384_alg = { 59 - .digestsize = SHA384_DIGEST_SIZE, 60 - .init = sha384_base_init, 61 - .update = sha512_sparc64_update, 62 - .finup = sha512_sparc64_finup, 63 - .descsize = SHA512_STATE_SIZE, 64 - .base = { 65 - .cra_name = "sha384", 66 - .cra_driver_name= "sha384-sparc64", 67 - .cra_priority = SPARC_CR_OPCODE_PRIORITY, 68 - .cra_blocksize = SHA384_BLOCK_SIZE, 69 - .cra_module = THIS_MODULE, 70 - } 71 - }; 72 - 73 - static bool __init sparc64_has_sha512_opcode(void) 74 - { 75 - unsigned long cfr; 76 - 77 - if (!(sparc64_elf_hwcap & HWCAP_SPARC_CRYPTO)) 78 - return false; 79 - 80 - __asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr)); 81 - if (!(cfr & CFR_SHA512)) 82 - return false; 83 - 84 - return true; 85 - } 86 - 87 - static int __init sha512_sparc64_mod_init(void) 88 - { 89 - if (sparc64_has_sha512_opcode()) { 90 - int ret = crypto_register_shash(&sha384_alg); 91 - if (ret < 0) 92 - return ret; 93 - 94 - ret = crypto_register_shash(&sha512_alg); 95 - if (ret < 0) { 96 - crypto_unregister_shash(&sha384_alg); 97 - return ret; 98 - } 99 - 100 - pr_info("Using sparc64 sha512 opcode optimized SHA-512/SHA-384 implementation\n"); 101 - return 0; 102 - } 103 - pr_info("sparc64 sha512 opcode not available.\n"); 104 - return -ENODEV; 105 - } 106 - 107 - static void __exit sha512_sparc64_mod_fini(void) 108 - { 109 - crypto_unregister_shash(&sha384_alg); 110 - crypto_unregister_shash(&sha512_alg); 111 - } 112 - 113 - module_init(sha512_sparc64_mod_init); 114 - module_exit(sha512_sparc64_mod_fini); 115 - 116 - MODULE_LICENSE("GPL"); 117 - MODULE_DESCRIPTION("SHA-384 and SHA-512 Secure Hash Algorithm, sparc64 sha512 opcode accelerated"); 118 - 119 - MODULE_ALIAS_CRYPTO("sha384"); 120 - MODULE_ALIAS_CRYPTO("sha512"); 121 - 122 - #include "crop_devid.c"
+1
lib/crypto/Kconfig
··· 182 182 default y if MIPS && CPU_CAVIUM_OCTEON 183 183 default y if RISCV && 64BIT && RISCV_ISA_V && TOOLCHAIN_HAS_VECTOR_CRYPTO 184 184 default y if S390 185 + default y if SPARC64 185 186 186 187 config CRYPTO_LIB_SM3 187 188 tristate
+1
lib/crypto/Makefile
··· 94 94 endif 95 95 96 96 libsha512-$(CONFIG_RISCV) += riscv/sha512-riscv64-zvknhb-zvkb.o 97 + libsha512-$(CONFIG_SPARC) += sparc/sha512_asm.o 97 98 endif # CONFIG_CRYPTO_LIB_SHA512_ARCH 98 99 99 100 obj-$(CONFIG_MPILIB) += mpi/
+42
lib/crypto/sparc/sha512.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * SHA-512 accelerated using the sparc64 sha512 opcodes 4 + * 5 + * Copyright (c) Jean-Luc Cooke <jlcooke@certainkey.com> 6 + * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk> 7 + * Copyright (c) 2003 Kyle McMartin <kyle@debian.org> 8 + */ 9 + 10 + #include <asm/elf.h> 11 + #include <asm/opcodes.h> 12 + #include <asm/pstate.h> 13 + 14 + static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_sha512_opcodes); 15 + 16 + asmlinkage void sha512_sparc64_transform(struct sha512_block_state *state, 17 + const u8 *data, size_t nblocks); 18 + 19 + static void sha512_blocks(struct sha512_block_state *state, 20 + const u8 *data, size_t nblocks) 21 + { 22 + if (static_branch_likely(&have_sha512_opcodes)) 23 + sha512_sparc64_transform(state, data, nblocks); 24 + else 25 + sha512_blocks_generic(state, data, nblocks); 26 + } 27 + 28 + #define sha512_mod_init_arch sha512_mod_init_arch 29 + static inline void sha512_mod_init_arch(void) 30 + { 31 + unsigned long cfr; 32 + 33 + if (!(sparc64_elf_hwcap & HWCAP_SPARC_CRYPTO)) 34 + return; 35 + 36 + __asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr)); 37 + if (!(cfr & CFR_SHA512)) 38 + return; 39 + 40 + static_branch_enable(&have_sha512_opcodes); 41 + pr_info("Using sparc64 sha512 opcode optimized SHA-512/SHA-384 implementation\n"); 42 + }