Commit a1848f6e authored by Eric Biggers's avatar Eric Biggers
Browse files

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: default avatarEric Biggers <ebiggers@kernel.org>
parent 09371e13
Loading
Loading
Loading
Loading
+0 −10
Original line number Diff line number Diff line
@@ -16,16 +16,6 @@ config CRYPTO_DES_SPARC64

	  Architecture: sparc64

config CRYPTO_MD5_SPARC64
	tristate "Digests: MD5"
	depends on SPARC64
	select CRYPTO_MD5
	select CRYPTO_HASH
	help
	  MD5 message digest algorithm (RFC1321)

	  Architecture: sparc64 using crypto instructions, when available

config CRYPTO_AES_SPARC64
	tristate "Ciphers: AES, modes: ECB, CBC, CTR"
	depends on SPARC64
+0 −4
Original line number Diff line number Diff line
@@ -3,14 +3,10 @@
# Arch-specific CryptoAPI modules.
#

obj-$(CONFIG_CRYPTO_MD5_SPARC64) += md5-sparc64.o

obj-$(CONFIG_CRYPTO_AES_SPARC64) += aes-sparc64.o
obj-$(CONFIG_CRYPTO_DES_SPARC64) += des-sparc64.o
obj-$(CONFIG_CRYPTO_CAMELLIA_SPARC64) += camellia-sparc64.o

md5-sparc64-y := md5_asm.o md5_glue.o

aes-sparc64-y := aes_asm.o aes_glue.o
des-sparc64-y := des_asm.o des_glue.o
camellia-sparc64-y := camellia_asm.o camellia_glue.o

arch/sparc/crypto/md5_glue.c

deleted100644 → 0
+0 −174
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/* Glue code for MD5 hashing optimized for sparc64 crypto opcodes.
 *
 * This is based largely upon arch/x86/crypto/sha1_ssse3_glue.c
 * and crypto/md5.c which are:
 *
 * 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) Cryptoapi developers.
 * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
 */

#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt

#include <asm/elf.h>
#include <asm/opcodes.h>
#include <asm/pstate.h>
#include <crypto/internal/hash.h>
#include <crypto/md5.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/unaligned.h>

struct sparc_md5_state {
	__le32 hash[MD5_HASH_WORDS];
	u64 byte_count;
};

asmlinkage void md5_sparc64_transform(__le32 *digest, const char *data,
				      unsigned int rounds);

static int md5_sparc64_init(struct shash_desc *desc)
{
	struct sparc_md5_state *mctx = shash_desc_ctx(desc);

	mctx->hash[0] = cpu_to_le32(MD5_H0);
	mctx->hash[1] = cpu_to_le32(MD5_H1);
	mctx->hash[2] = cpu_to_le32(MD5_H2);
	mctx->hash[3] = cpu_to_le32(MD5_H3);
	mctx->byte_count = 0;

	return 0;
}

static int md5_sparc64_update(struct shash_desc *desc, const u8 *data,
			      unsigned int len)
{
	struct sparc_md5_state *sctx = shash_desc_ctx(desc);

	sctx->byte_count += round_down(len, MD5_HMAC_BLOCK_SIZE);
	md5_sparc64_transform(sctx->hash, data, len / MD5_HMAC_BLOCK_SIZE);
	return len - round_down(len, MD5_HMAC_BLOCK_SIZE);
}

/* Add padding and return the message digest. */
static int md5_sparc64_finup(struct shash_desc *desc, const u8 *src,
			     unsigned int offset, u8 *out)
{
	struct sparc_md5_state *sctx = shash_desc_ctx(desc);
	__le64 block[MD5_BLOCK_WORDS] = {};
	u8 *p = memcpy(block, src, offset);
	__le32 *dst = (__le32 *)out;
	__le64 *pbits;
	int i;

	src = p;
	p += offset;
	*p++ = 0x80;
	sctx->byte_count += offset;
	pbits = &block[(MD5_BLOCK_WORDS / (offset > 55 ? 1 : 2)) - 1];
	*pbits = cpu_to_le64(sctx->byte_count << 3);
	md5_sparc64_transform(sctx->hash, src, (pbits - block + 1) / 8);
	memzero_explicit(block, sizeof(block));

	/* Store state in digest */
	for (i = 0; i < MD5_HASH_WORDS; i++)
		dst[i] = sctx->hash[i];

	return 0;
}

static int md5_sparc64_export(struct shash_desc *desc, void *out)
{
	struct sparc_md5_state *sctx = shash_desc_ctx(desc);
	union {
		u8 *u8;
		u32 *u32;
		u64 *u64;
	} p = { .u8 = out };
	int i;

	for (i = 0; i < MD5_HASH_WORDS; i++)
		put_unaligned(le32_to_cpu(sctx->hash[i]), p.u32++);
	put_unaligned(sctx->byte_count, p.u64);
	return 0;
}

static int md5_sparc64_import(struct shash_desc *desc, const void *in)
{
	struct sparc_md5_state *sctx = shash_desc_ctx(desc);
	union {
		const u8 *u8;
		const u32 *u32;
		const u64 *u64;
	} p = { .u8 = in };
	int i;

	for (i = 0; i < MD5_HASH_WORDS; i++)
		sctx->hash[i] = cpu_to_le32(get_unaligned(p.u32++));
	sctx->byte_count = get_unaligned(p.u64);
	return 0;
}

static struct shash_alg alg = {
	.digestsize	=	MD5_DIGEST_SIZE,
	.init		=	md5_sparc64_init,
	.update		=	md5_sparc64_update,
	.finup		=	md5_sparc64_finup,
	.export		=	md5_sparc64_export,
	.import		=	md5_sparc64_import,
	.descsize	=	sizeof(struct sparc_md5_state),
	.statesize	=	sizeof(struct sparc_md5_state),
	.base		=	{
		.cra_name	=	"md5",
		.cra_driver_name=	"md5-sparc64",
		.cra_priority	=	SPARC_CR_OPCODE_PRIORITY,
		.cra_flags	=	CRYPTO_AHASH_ALG_BLOCK_ONLY,
		.cra_blocksize	=	MD5_HMAC_BLOCK_SIZE,
		.cra_module	=	THIS_MODULE,
	}
};

static bool __init sparc64_has_md5_opcode(void)
{
	unsigned long cfr;

	if (!(sparc64_elf_hwcap & HWCAP_SPARC_CRYPTO))
		return false;

	__asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr));
	if (!(cfr & CFR_MD5))
		return false;

	return true;
}

static int __init md5_sparc64_mod_init(void)
{
	if (sparc64_has_md5_opcode()) {
		pr_info("Using sparc64 md5 opcode optimized MD5 implementation\n");
		return crypto_register_shash(&alg);
	}
	pr_info("sparc64 md5 opcode not available.\n");
	return -ENODEV;
}

static void __exit md5_sparc64_mod_fini(void)
{
	crypto_unregister_shash(&alg);
}

module_init(md5_sparc64_mod_init);
module_exit(md5_sparc64_mod_fini);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("MD5 Message Digest Algorithm, sparc64 md5 opcode accelerated");

MODULE_ALIAS_CRYPTO("md5");

#include "crop_devid.c"
+1 −0
Original line number Diff line number Diff line
@@ -112,6 +112,7 @@ config CRYPTO_LIB_MD5_ARCH
	depends on CRYPTO_LIB_MD5 && !UML
	default y if MIPS && CPU_CAVIUM_OCTEON
	default y if PPC
	default y if SPARC64

config CRYPTO_LIB_POLY1305_RSIZE
	int
+1 −0
Original line number Diff line number Diff line
@@ -66,6 +66,7 @@ libmd5-y := md5.o
ifeq ($(CONFIG_CRYPTO_LIB_MD5_ARCH),y)
CFLAGS_md5.o += -I$(src)/$(SRCARCH)
libmd5-$(CONFIG_PPC) += powerpc/md5-asm.o
libmd5-$(CONFIG_SPARC) += sparc/md5_asm.o
endif # CONFIG_CRYPTO_LIB_MD5_ARCH

################################################################################
Loading