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

Configure Feed

Select the types of activity you want to include in your feed.

lib/crypto: sparc/md5: Migrate optimized code into library

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

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

Link: https://lore.kernel.org/r/20250805222855.10362-6-ebiggers@kernel.org
Signed-off-by: Eric Biggers <ebiggers@kernel.org>

+50 -188
-10
arch/sparc/crypto/Kconfig
··· 16 16 17 17 Architecture: sparc64 18 18 19 - config CRYPTO_MD5_SPARC64 20 - tristate "Digests: MD5" 21 - depends on SPARC64 22 - select CRYPTO_MD5 23 - select CRYPTO_HASH 24 - help 25 - MD5 message digest algorithm (RFC1321) 26 - 27 - Architecture: sparc64 using crypto instructions, when available 28 - 29 19 config CRYPTO_AES_SPARC64 30 20 tristate "Ciphers: AES, modes: ECB, CBC, CTR" 31 21 depends on SPARC64
-4
arch/sparc/crypto/Makefile
··· 3 3 # Arch-specific CryptoAPI modules. 4 4 # 5 5 6 - obj-$(CONFIG_CRYPTO_MD5_SPARC64) += md5-sparc64.o 7 - 8 6 obj-$(CONFIG_CRYPTO_AES_SPARC64) += aes-sparc64.o 9 7 obj-$(CONFIG_CRYPTO_DES_SPARC64) += des-sparc64.o 10 8 obj-$(CONFIG_CRYPTO_CAMELLIA_SPARC64) += camellia-sparc64.o 11 - 12 - md5-sparc64-y := md5_asm.o md5_glue.o 13 9 14 10 aes-sparc64-y := aes_asm.o aes_glue.o 15 11 des-sparc64-y := des_asm.o des_glue.o
arch/sparc/crypto/md5_asm.S lib/crypto/sparc/md5_asm.S
-174
arch/sparc/crypto/md5_glue.c
··· 1 - // SPDX-License-Identifier: GPL-2.0-only 2 - /* Glue code for MD5 hashing optimized for sparc64 crypto opcodes. 3 - * 4 - * This is based largely upon arch/x86/crypto/sha1_ssse3_glue.c 5 - * and crypto/md5.c which are: 6 - * 7 - * Copyright (c) Alan Smithee. 8 - * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk> 9 - * Copyright (c) Jean-Francois Dive <jef@linuxbe.org> 10 - * Copyright (c) Mathias Krause <minipli@googlemail.com> 11 - * Copyright (c) Cryptoapi developers. 12 - * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> 13 - */ 14 - 15 - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 16 - 17 - #include <asm/elf.h> 18 - #include <asm/opcodes.h> 19 - #include <asm/pstate.h> 20 - #include <crypto/internal/hash.h> 21 - #include <crypto/md5.h> 22 - #include <linux/errno.h> 23 - #include <linux/kernel.h> 24 - #include <linux/module.h> 25 - #include <linux/string.h> 26 - #include <linux/unaligned.h> 27 - 28 - struct sparc_md5_state { 29 - __le32 hash[MD5_HASH_WORDS]; 30 - u64 byte_count; 31 - }; 32 - 33 - asmlinkage void md5_sparc64_transform(__le32 *digest, const char *data, 34 - unsigned int rounds); 35 - 36 - static int md5_sparc64_init(struct shash_desc *desc) 37 - { 38 - struct sparc_md5_state *mctx = shash_desc_ctx(desc); 39 - 40 - mctx->hash[0] = cpu_to_le32(MD5_H0); 41 - mctx->hash[1] = cpu_to_le32(MD5_H1); 42 - mctx->hash[2] = cpu_to_le32(MD5_H2); 43 - mctx->hash[3] = cpu_to_le32(MD5_H3); 44 - mctx->byte_count = 0; 45 - 46 - return 0; 47 - } 48 - 49 - static int md5_sparc64_update(struct shash_desc *desc, const u8 *data, 50 - unsigned int len) 51 - { 52 - struct sparc_md5_state *sctx = shash_desc_ctx(desc); 53 - 54 - sctx->byte_count += round_down(len, MD5_HMAC_BLOCK_SIZE); 55 - md5_sparc64_transform(sctx->hash, data, len / MD5_HMAC_BLOCK_SIZE); 56 - return len - round_down(len, MD5_HMAC_BLOCK_SIZE); 57 - } 58 - 59 - /* Add padding and return the message digest. */ 60 - static int md5_sparc64_finup(struct shash_desc *desc, const u8 *src, 61 - unsigned int offset, u8 *out) 62 - { 63 - struct sparc_md5_state *sctx = shash_desc_ctx(desc); 64 - __le64 block[MD5_BLOCK_WORDS] = {}; 65 - u8 *p = memcpy(block, src, offset); 66 - __le32 *dst = (__le32 *)out; 67 - __le64 *pbits; 68 - int i; 69 - 70 - src = p; 71 - p += offset; 72 - *p++ = 0x80; 73 - sctx->byte_count += offset; 74 - pbits = &block[(MD5_BLOCK_WORDS / (offset > 55 ? 1 : 2)) - 1]; 75 - *pbits = cpu_to_le64(sctx->byte_count << 3); 76 - md5_sparc64_transform(sctx->hash, src, (pbits - block + 1) / 8); 77 - memzero_explicit(block, sizeof(block)); 78 - 79 - /* Store state in digest */ 80 - for (i = 0; i < MD5_HASH_WORDS; i++) 81 - dst[i] = sctx->hash[i]; 82 - 83 - return 0; 84 - } 85 - 86 - static int md5_sparc64_export(struct shash_desc *desc, void *out) 87 - { 88 - struct sparc_md5_state *sctx = shash_desc_ctx(desc); 89 - union { 90 - u8 *u8; 91 - u32 *u32; 92 - u64 *u64; 93 - } p = { .u8 = out }; 94 - int i; 95 - 96 - for (i = 0; i < MD5_HASH_WORDS; i++) 97 - put_unaligned(le32_to_cpu(sctx->hash[i]), p.u32++); 98 - put_unaligned(sctx->byte_count, p.u64); 99 - return 0; 100 - } 101 - 102 - static int md5_sparc64_import(struct shash_desc *desc, const void *in) 103 - { 104 - struct sparc_md5_state *sctx = shash_desc_ctx(desc); 105 - union { 106 - const u8 *u8; 107 - const u32 *u32; 108 - const u64 *u64; 109 - } p = { .u8 = in }; 110 - int i; 111 - 112 - for (i = 0; i < MD5_HASH_WORDS; i++) 113 - sctx->hash[i] = cpu_to_le32(get_unaligned(p.u32++)); 114 - sctx->byte_count = get_unaligned(p.u64); 115 - return 0; 116 - } 117 - 118 - static struct shash_alg alg = { 119 - .digestsize = MD5_DIGEST_SIZE, 120 - .init = md5_sparc64_init, 121 - .update = md5_sparc64_update, 122 - .finup = md5_sparc64_finup, 123 - .export = md5_sparc64_export, 124 - .import = md5_sparc64_import, 125 - .descsize = sizeof(struct sparc_md5_state), 126 - .statesize = sizeof(struct sparc_md5_state), 127 - .base = { 128 - .cra_name = "md5", 129 - .cra_driver_name= "md5-sparc64", 130 - .cra_priority = SPARC_CR_OPCODE_PRIORITY, 131 - .cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY, 132 - .cra_blocksize = MD5_HMAC_BLOCK_SIZE, 133 - .cra_module = THIS_MODULE, 134 - } 135 - }; 136 - 137 - static bool __init sparc64_has_md5_opcode(void) 138 - { 139 - unsigned long cfr; 140 - 141 - if (!(sparc64_elf_hwcap & HWCAP_SPARC_CRYPTO)) 142 - return false; 143 - 144 - __asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr)); 145 - if (!(cfr & CFR_MD5)) 146 - return false; 147 - 148 - return true; 149 - } 150 - 151 - static int __init md5_sparc64_mod_init(void) 152 - { 153 - if (sparc64_has_md5_opcode()) { 154 - pr_info("Using sparc64 md5 opcode optimized MD5 implementation\n"); 155 - return crypto_register_shash(&alg); 156 - } 157 - pr_info("sparc64 md5 opcode not available.\n"); 158 - return -ENODEV; 159 - } 160 - 161 - static void __exit md5_sparc64_mod_fini(void) 162 - { 163 - crypto_unregister_shash(&alg); 164 - } 165 - 166 - module_init(md5_sparc64_mod_init); 167 - module_exit(md5_sparc64_mod_fini); 168 - 169 - MODULE_LICENSE("GPL"); 170 - MODULE_DESCRIPTION("MD5 Message Digest Algorithm, sparc64 md5 opcode accelerated"); 171 - 172 - MODULE_ALIAS_CRYPTO("md5"); 173 - 174 - #include "crop_devid.c"
+1
lib/crypto/Kconfig
··· 112 112 depends on CRYPTO_LIB_MD5 && !UML 113 113 default y if MIPS && CPU_CAVIUM_OCTEON 114 114 default y if PPC 115 + default y if SPARC64 115 116 116 117 config CRYPTO_LIB_POLY1305_RSIZE 117 118 int
+1
lib/crypto/Makefile
··· 66 66 ifeq ($(CONFIG_CRYPTO_LIB_MD5_ARCH),y) 67 67 CFLAGS_md5.o += -I$(src)/$(SRCARCH) 68 68 libmd5-$(CONFIG_PPC) += powerpc/md5-asm.o 69 + libmd5-$(CONFIG_SPARC) += sparc/md5_asm.o 69 70 endif # CONFIG_CRYPTO_LIB_MD5_ARCH 70 71 71 72 ################################################################################
+48
lib/crypto/sparc/md5.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * MD5 accelerated using the sparc64 crypto opcodes 4 + * 5 + * Copyright (c) Alan Smithee. 6 + * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk> 7 + * Copyright (c) Jean-Francois Dive <jef@linuxbe.org> 8 + * Copyright (c) Mathias Krause <minipli@googlemail.com> 9 + * Copyright (c) Cryptoapi developers. 10 + * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> 11 + */ 12 + 13 + #include <asm/elf.h> 14 + #include <asm/opcodes.h> 15 + #include <asm/pstate.h> 16 + 17 + static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_md5_opcodes); 18 + 19 + asmlinkage void md5_sparc64_transform(struct md5_block_state *state, 20 + const u8 *data, size_t nblocks); 21 + 22 + static void md5_blocks(struct md5_block_state *state, 23 + const u8 *data, size_t nblocks) 24 + { 25 + if (static_branch_likely(&have_md5_opcodes)) { 26 + cpu_to_le32_array(state->h, ARRAY_SIZE(state->h)); 27 + md5_sparc64_transform(state, data, nblocks); 28 + le32_to_cpu_array(state->h, ARRAY_SIZE(state->h)); 29 + } else { 30 + md5_blocks_generic(state, data, nblocks); 31 + } 32 + } 33 + 34 + #define md5_mod_init_arch md5_mod_init_arch 35 + static inline void md5_mod_init_arch(void) 36 + { 37 + unsigned long cfr; 38 + 39 + if (!(sparc64_elf_hwcap & HWCAP_SPARC_CRYPTO)) 40 + return; 41 + 42 + __asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr)); 43 + if (!(cfr & CFR_MD5)) 44 + return; 45 + 46 + static_branch_enable(&have_md5_opcodes); 47 + pr_info("Using sparc64 md5 opcode optimized MD5 implementation\n"); 48 + }