* [PATCH 0/7] MD5 library functions
@ 2025-08-03 20:44 Eric Biggers
2025-08-03 20:44 ` [PATCH 1/7] mips: cavium-octeon: Remove Octeon optimized MD5 code Eric Biggers
` (6 more replies)
0 siblings, 7 replies; 26+ messages in thread
From: Eric Biggers @ 2025-08-03 20:44 UTC (permalink / raw)
To: linux-crypto
Cc: linux-kernel, Ard Biesheuvel, Jason A . Donenfeld, linux-mips,
linuxppc-dev, sparclinux, Eric Biggers
This series is targeting libcrypto-next and can also be retrieved from:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux.git md5-lib-v1
Patches 1-4 remove the MD5 implementations for mips, powerpc, and sparc.
These were the only architecture-optimized MD5 implementations and are
not worth keeping around.
Patches 5-7 introduce a library API for MD5 and HMAC-MD5 and reimplement
the crypto_shash "md5" and "hmac(md5)" on top of it.
The library API will also be usable directly by various in-kernel users
that are stuck with MD5 due to having to implement legacy protocols.
This should again look quite boring and familiar, as it mirrors the
SHA-1 and SHA-2 changes closely. The MD5 changes are quite a bit
simpler, though, since we'll only be supporting the generic C MD5 code.
Of course there's also only one variant of MD5, unlike e.g. SHA-2.
Eric Biggers (7):
mips: cavium-octeon: Remove Octeon optimized MD5 code
mips: cavium-octeon: Move octeon-crypto.c into parent dir
crypto: powerpc/md5 - Remove PowerPC optimized MD5 code
crypto: sparc/md5 - Remove SPARC64 optimized MD5 code
lib/crypto: md5: Add MD5 and HMAC-MD5 library functions
crypto: md5 - Wrap library and add HMAC support
lib/crypto: tests: Add KUnit tests for MD5 and HMAC-MD5
arch/mips/cavium-octeon/Makefile | 2 +-
arch/mips/cavium-octeon/crypto/Makefile | 8 -
arch/mips/cavium-octeon/crypto/octeon-md5.c | 214 -----------
.../{crypto => }/octeon-crypto.c | 0
arch/mips/configs/cavium_octeon_defconfig | 1 -
arch/mips/crypto/Kconfig | 10 -
arch/mips/include/asm/octeon/crypto.h | 21 +-
arch/powerpc/configs/powernv_defconfig | 1 -
arch/powerpc/configs/ppc64_defconfig | 1 -
arch/powerpc/crypto/Kconfig | 8 -
arch/powerpc/crypto/Makefile | 2 -
arch/powerpc/crypto/md5-asm.S | 235 ------------
arch/powerpc/crypto/md5-glue.c | 99 -----
arch/sparc/crypto/Kconfig | 10 -
arch/sparc/crypto/Makefile | 4 -
arch/sparc/crypto/md5_asm.S | 70 ----
arch/sparc/crypto/md5_glue.c | 174 ---------
crypto/Kconfig | 2 +-
crypto/md5.c | 359 ++++++++----------
crypto/testmgr.c | 3 +
drivers/crypto/img-hash.c | 2 +-
include/crypto/md5.h | 181 ++++++++-
lib/crypto/Kconfig | 6 +
lib/crypto/Makefile | 3 +
lib/crypto/md5.c | 290 ++++++++++++++
lib/crypto/tests/Kconfig | 10 +
lib/crypto/tests/Makefile | 1 +
lib/crypto/tests/md5-testvecs.h | 186 +++++++++
lib/crypto/tests/md5_kunit.c | 39 ++
29 files changed, 891 insertions(+), 1051 deletions(-)
delete mode 100644 arch/mips/cavium-octeon/crypto/Makefile
delete mode 100644 arch/mips/cavium-octeon/crypto/octeon-md5.c
rename arch/mips/cavium-octeon/{crypto => }/octeon-crypto.c (100%)
delete mode 100644 arch/powerpc/crypto/md5-asm.S
delete mode 100644 arch/powerpc/crypto/md5-glue.c
delete mode 100644 arch/sparc/crypto/md5_asm.S
delete mode 100644 arch/sparc/crypto/md5_glue.c
create mode 100644 lib/crypto/md5.c
create mode 100644 lib/crypto/tests/md5-testvecs.h
create mode 100644 lib/crypto/tests/md5_kunit.c
base-commit: 186f3edfdd41f2ae87fc40a9ccba52a3bf930994
--
2.50.1
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH 1/7] mips: cavium-octeon: Remove Octeon optimized MD5 code
2025-08-03 20:44 [PATCH 0/7] MD5 library functions Eric Biggers
@ 2025-08-03 20:44 ` Eric Biggers
2025-08-03 20:44 ` [PATCH 2/7] mips: cavium-octeon: Move octeon-crypto.c into parent dir Eric Biggers
` (5 subsequent siblings)
6 siblings, 0 replies; 26+ messages in thread
From: Eric Biggers @ 2025-08-03 20:44 UTC (permalink / raw)
To: linux-crypto
Cc: linux-kernel, Ard Biesheuvel, Jason A . Donenfeld, linux-mips,
linuxppc-dev, sparclinux, Eric Biggers
MD5 is insecure, is no longer commonly used, and has never been
optimized for the most common architectures in the kernel. Only mips,
powerpc, and sparc have optimized MD5 code in the kernel. Of these,
only the powerpc one is actually testable in QEMU. The mips one works
only on Cavium Octeon SoCs.
Taken together, it's clear that it's time to retire these additional MD5
implementations, and focus maintenance on the MD5 generic C code.
This commit removes the Cavium Octeon optimized MD5 code.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
arch/mips/cavium-octeon/crypto/Makefile | 2 -
arch/mips/cavium-octeon/crypto/octeon-md5.c | 214 --------------------
arch/mips/configs/cavium_octeon_defconfig | 1 -
arch/mips/crypto/Kconfig | 10 -
arch/mips/include/asm/octeon/crypto.h | 21 +-
5 files changed, 4 insertions(+), 244 deletions(-)
delete mode 100644 arch/mips/cavium-octeon/crypto/octeon-md5.c
diff --git a/arch/mips/cavium-octeon/crypto/Makefile b/arch/mips/cavium-octeon/crypto/Makefile
index 83f2f5dd93ccc..b7d03e8a03187 100644
--- a/arch/mips/cavium-octeon/crypto/Makefile
+++ b/arch/mips/cavium-octeon/crypto/Makefile
@@ -2,7 +2,5 @@
#
# OCTEON-specific crypto modules.
#
obj-y += octeon-crypto.o
-
-obj-$(CONFIG_CRYPTO_MD5_OCTEON) += octeon-md5.o
diff --git a/arch/mips/cavium-octeon/crypto/octeon-md5.c b/arch/mips/cavium-octeon/crypto/octeon-md5.c
deleted file mode 100644
index a8ce831e2cebd..0000000000000
--- a/arch/mips/cavium-octeon/crypto/octeon-md5.c
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * Cryptographic API.
- *
- * MD5 Message Digest Algorithm (RFC1321).
- *
- * Adapted for OCTEON by Aaro Koskinen <aaro.koskinen@iki.fi>.
- *
- * Based on crypto/md5.c, which is:
- *
- * Derived from cryptoapi implementation, originally based on the
- * public domain implementation written by Colin Plumb in 1993.
- *
- * Copyright (c) Cryptoapi developers.
- * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-#include <asm/octeon/crypto.h>
-#include <asm/octeon/octeon.h>
-#include <crypto/internal/hash.h>
-#include <crypto/md5.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/unaligned.h>
-
-struct octeon_md5_state {
- __le32 hash[MD5_HASH_WORDS];
- u64 byte_count;
-};
-
-/*
- * We pass everything as 64-bit. OCTEON can handle misaligned data.
- */
-
-static void octeon_md5_store_hash(struct octeon_md5_state *ctx)
-{
- u64 *hash = (u64 *)ctx->hash;
-
- write_octeon_64bit_hash_dword(hash[0], 0);
- write_octeon_64bit_hash_dword(hash[1], 1);
-}
-
-static void octeon_md5_read_hash(struct octeon_md5_state *ctx)
-{
- u64 *hash = (u64 *)ctx->hash;
-
- hash[0] = read_octeon_64bit_hash_dword(0);
- hash[1] = read_octeon_64bit_hash_dword(1);
-}
-
-static void octeon_md5_transform(const void *_block)
-{
- const u64 *block = _block;
-
- write_octeon_64bit_block_dword(block[0], 0);
- write_octeon_64bit_block_dword(block[1], 1);
- write_octeon_64bit_block_dword(block[2], 2);
- write_octeon_64bit_block_dword(block[3], 3);
- write_octeon_64bit_block_dword(block[4], 4);
- write_octeon_64bit_block_dword(block[5], 5);
- write_octeon_64bit_block_dword(block[6], 6);
- octeon_md5_start(block[7]);
-}
-
-static int octeon_md5_init(struct shash_desc *desc)
-{
- struct octeon_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 octeon_md5_update(struct shash_desc *desc, const u8 *data,
- unsigned int len)
-{
- struct octeon_md5_state *mctx = shash_desc_ctx(desc);
- struct octeon_cop2_state state;
- unsigned long flags;
-
- mctx->byte_count += len;
- flags = octeon_crypto_enable(&state);
- octeon_md5_store_hash(mctx);
-
- do {
- octeon_md5_transform(data);
- data += MD5_HMAC_BLOCK_SIZE;
- len -= MD5_HMAC_BLOCK_SIZE;
- } while (len >= MD5_HMAC_BLOCK_SIZE);
-
- octeon_md5_read_hash(mctx);
- octeon_crypto_disable(&state, flags);
- mctx->byte_count -= len;
- return len;
-}
-
-static int octeon_md5_finup(struct shash_desc *desc, const u8 *src,
- unsigned int offset, u8 *out)
-{
- struct octeon_md5_state *mctx = shash_desc_ctx(desc);
- int padding = 56 - (offset + 1);
- struct octeon_cop2_state state;
- u32 block[MD5_BLOCK_WORDS];
- unsigned long flags;
- char *p;
-
- p = memcpy(block, src, offset);
- p += offset;
- *p++ = 0x80;
-
- flags = octeon_crypto_enable(&state);
- octeon_md5_store_hash(mctx);
-
- if (padding < 0) {
- memset(p, 0x00, padding + sizeof(u64));
- octeon_md5_transform(block);
- p = (char *)block;
- padding = 56;
- }
-
- memset(p, 0, padding);
- mctx->byte_count += offset;
- block[14] = mctx->byte_count << 3;
- block[15] = mctx->byte_count >> 29;
- cpu_to_le32_array(block + 14, 2);
- octeon_md5_transform(block);
-
- octeon_md5_read_hash(mctx);
- octeon_crypto_disable(&state, flags);
-
- memzero_explicit(block, sizeof(block));
- memcpy(out, mctx->hash, sizeof(mctx->hash));
-
- return 0;
-}
-
-static int octeon_md5_export(struct shash_desc *desc, void *out)
-{
- struct octeon_md5_state *ctx = 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(ctx->hash[i]), p.u32++);
- put_unaligned(ctx->byte_count, p.u64);
- return 0;
-}
-
-static int octeon_md5_import(struct shash_desc *desc, const void *in)
-{
- struct octeon_md5_state *ctx = 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++)
- ctx->hash[i] = cpu_to_le32(get_unaligned(p.u32++));
- ctx->byte_count = get_unaligned(p.u64);
- return 0;
-}
-
-static struct shash_alg alg = {
- .digestsize = MD5_DIGEST_SIZE,
- .init = octeon_md5_init,
- .update = octeon_md5_update,
- .finup = octeon_md5_finup,
- .export = octeon_md5_export,
- .import = octeon_md5_import,
- .statesize = MD5_STATE_SIZE,
- .descsize = sizeof(struct octeon_md5_state),
- .base = {
- .cra_name = "md5",
- .cra_driver_name= "octeon-md5",
- .cra_priority = OCTEON_CR_OPCODE_PRIORITY,
- .cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY,
- .cra_blocksize = MD5_HMAC_BLOCK_SIZE,
- .cra_module = THIS_MODULE,
- }
-};
-
-static int __init md5_mod_init(void)
-{
- if (!octeon_has_crypto())
- return -ENOTSUPP;
- return crypto_register_shash(&alg);
-}
-
-static void __exit md5_mod_fini(void)
-{
- crypto_unregister_shash(&alg);
-}
-
-module_init(md5_mod_init);
-module_exit(md5_mod_fini);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("MD5 Message Digest Algorithm (OCTEON)");
-MODULE_AUTHOR("Aaro Koskinen <aaro.koskinen@iki.fi>");
diff --git a/arch/mips/configs/cavium_octeon_defconfig b/arch/mips/configs/cavium_octeon_defconfig
index 3f50e1d78894a..68c363366bceb 100644
--- a/arch/mips/configs/cavium_octeon_defconfig
+++ b/arch/mips/configs/cavium_octeon_defconfig
@@ -153,11 +153,10 @@ CONFIG_NLS_ISO8859_1=y
CONFIG_NLS_UTF8=y
CONFIG_SECURITY=y
CONFIG_SECURITY_NETWORK=y
CONFIG_CRYPTO_CBC=y
CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_MD5_OCTEON=y
CONFIG_CRYPTO_DES=y
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
CONFIG_DEBUG_FS=y
CONFIG_MAGIC_SYSRQ=y
# CONFIG_SCHED_DEBUG is not set
diff --git a/arch/mips/crypto/Kconfig b/arch/mips/crypto/Kconfig
index 7b91f4ec65bff..6a5bd5074867e 100644
--- a/arch/mips/crypto/Kconfig
+++ b/arch/mips/crypto/Kconfig
@@ -1,15 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
menu "Accelerated Cryptographic Algorithms for CPU (mips)"
-config CRYPTO_MD5_OCTEON
- tristate "Digests: MD5 (OCTEON)"
- depends on CPU_CAVIUM_OCTEON
- select CRYPTO_MD5
- select CRYPTO_HASH
- help
- MD5 message digest algorithm (RFC1321)
-
- Architecture: mips OCTEON using crypto instructions, when available
-
endmenu
diff --git a/arch/mips/include/asm/octeon/crypto.h b/arch/mips/include/asm/octeon/crypto.h
index cb68f9e284bba..76601e9153d87 100644
--- a/arch/mips/include/asm/octeon/crypto.h
+++ b/arch/mips/include/asm/octeon/crypto.h
@@ -3,43 +3,41 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2012-2013 Cavium Inc., All Rights Reserved.
*
- * MD5/SHA1/SHA256/SHA512 instruction definitions added by
+ * SHA1, SHA256, and SHA512 instruction definitions added by
* Aaro Koskinen <aaro.koskinen@iki.fi>.
*
*/
#ifndef __LINUX_OCTEON_CRYPTO_H
#define __LINUX_OCTEON_CRYPTO_H
#include <linux/sched.h>
#include <asm/mipsregs.h>
-#define OCTEON_CR_OPCODE_PRIORITY 300
-
extern unsigned long octeon_crypto_enable(struct octeon_cop2_state *state);
extern void octeon_crypto_disable(struct octeon_cop2_state *state,
unsigned long flags);
/*
- * Macros needed to implement MD5/SHA1/SHA256:
+ * Macros needed to implement SHA1 and SHA256:
*/
/*
- * The index can be 0-1 (MD5) or 0-2 (SHA1), 0-3 (SHA256).
+ * The index can be 0-2 (SHA1) or 0-3 (SHA256).
*/
#define write_octeon_64bit_hash_dword(value, index) \
do { \
__asm__ __volatile__ ( \
"dmtc2 %[rt],0x0048+" STR(index) \
: \
: [rt] "d" (cpu_to_be64(value))); \
} while (0)
/*
- * The index can be 0-1 (MD5) or 0-2 (SHA1), 0-3 (SHA256).
+ * The index can be 0-2 (SHA1) or 0-3 (SHA256).
*/
#define read_octeon_64bit_hash_dword(index) \
({ \
__be64 __value; \
\
@@ -60,21 +58,10 @@ do { \
"dmtc2 %[rt],0x0040+" STR(index) \
: \
: [rt] "d" (cpu_to_be64(value))); \
} while (0)
-/*
- * The value is the final block dword (64-bit).
- */
-#define octeon_md5_start(value) \
-do { \
- __asm__ __volatile__ ( \
- "dmtc2 %[rt],0x4047" \
- : \
- : [rt] "d" (cpu_to_be64(value))); \
-} while (0)
-
/*
* The value is the final block dword (64-bit).
*/
#define octeon_sha1_start(value) \
do { \
--
2.50.1
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH 2/7] mips: cavium-octeon: Move octeon-crypto.c into parent dir
2025-08-03 20:44 [PATCH 0/7] MD5 library functions Eric Biggers
2025-08-03 20:44 ` [PATCH 1/7] mips: cavium-octeon: Remove Octeon optimized MD5 code Eric Biggers
@ 2025-08-03 20:44 ` Eric Biggers
2025-08-03 20:44 ` [PATCH 3/7] crypto: powerpc/md5 - Remove PowerPC optimized MD5 code Eric Biggers
` (4 subsequent siblings)
6 siblings, 0 replies; 26+ messages in thread
From: Eric Biggers @ 2025-08-03 20:44 UTC (permalink / raw)
To: linux-crypto
Cc: linux-kernel, Ard Biesheuvel, Jason A . Donenfeld, linux-mips,
linuxppc-dev, sparclinux, Eric Biggers
Since octeon-crypto.c is the only remaining source file in
arch/mips/cavium-octeon/crypto/, move it into its parent directory
arch/mips/cavium-octeon/. Then remove the directory
arch/mips/cavium-octeon/crypto/, including its Makefile.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
arch/mips/cavium-octeon/Makefile | 2 +-
arch/mips/cavium-octeon/crypto/Makefile | 6 ------
arch/mips/cavium-octeon/{crypto => }/octeon-crypto.c | 0
3 files changed, 1 insertion(+), 7 deletions(-)
delete mode 100644 arch/mips/cavium-octeon/crypto/Makefile
rename arch/mips/cavium-octeon/{crypto => }/octeon-crypto.c (100%)
diff --git a/arch/mips/cavium-octeon/Makefile b/arch/mips/cavium-octeon/Makefile
index 2a59265788413..ab84ede0cbe0e 100644
--- a/arch/mips/cavium-octeon/Makefile
+++ b/arch/mips/cavium-octeon/Makefile
@@ -9,12 +9,12 @@
# Copyright (C) 2005-2009 Cavium Networks
#
obj-y := cpu.o setup.o octeon-platform.o octeon-irq.o csrc-octeon.o
obj-y += dma-octeon.o
+obj-y += octeon-crypto.o
obj-y += octeon-memcpy.o
obj-y += executive/
-obj-y += crypto/
obj-$(CONFIG_MTD) += flash_setup.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_OCTEON_ILM) += oct_ilm.o
diff --git a/arch/mips/cavium-octeon/crypto/Makefile b/arch/mips/cavium-octeon/crypto/Makefile
deleted file mode 100644
index b7d03e8a03187..0000000000000
--- a/arch/mips/cavium-octeon/crypto/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-#
-# OCTEON-specific crypto modules.
-#
-
-obj-y += octeon-crypto.o
diff --git a/arch/mips/cavium-octeon/crypto/octeon-crypto.c b/arch/mips/cavium-octeon/octeon-crypto.c
similarity index 100%
rename from arch/mips/cavium-octeon/crypto/octeon-crypto.c
rename to arch/mips/cavium-octeon/octeon-crypto.c
--
2.50.1
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH 3/7] crypto: powerpc/md5 - Remove PowerPC optimized MD5 code
2025-08-03 20:44 [PATCH 0/7] MD5 library functions Eric Biggers
2025-08-03 20:44 ` [PATCH 1/7] mips: cavium-octeon: Remove Octeon optimized MD5 code Eric Biggers
2025-08-03 20:44 ` [PATCH 2/7] mips: cavium-octeon: Move octeon-crypto.c into parent dir Eric Biggers
@ 2025-08-03 20:44 ` Eric Biggers
2025-08-03 22:07 ` Segher Boessenkool
2025-08-04 17:42 ` Christophe Leroy
2025-08-03 20:44 ` [PATCH 4/7] crypto: sparc/md5 - Remove SPARC64 " Eric Biggers
` (3 subsequent siblings)
6 siblings, 2 replies; 26+ messages in thread
From: Eric Biggers @ 2025-08-03 20:44 UTC (permalink / raw)
To: linux-crypto
Cc: linux-kernel, Ard Biesheuvel, Jason A . Donenfeld, linux-mips,
linuxppc-dev, sparclinux, Eric Biggers
MD5 is insecure, is no longer commonly used, and has never been
optimized for the most common architectures in the kernel. Only mips,
powerpc, and sparc have optimized MD5 code in the kernel. Of these,
only the powerpc one is actually testable in QEMU. The mips one works
only on Cavium Octeon SoCs.
Taken together, it's clear that it's time to retire these additional MD5
implementations, and focus maintenance on the MD5 generic C code.
This commit removes the PowerPC optimized MD5 code.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
arch/powerpc/configs/powernv_defconfig | 1 -
arch/powerpc/configs/ppc64_defconfig | 1 -
arch/powerpc/crypto/Kconfig | 8 -
arch/powerpc/crypto/Makefile | 2 -
arch/powerpc/crypto/md5-asm.S | 235 -------------------------
arch/powerpc/crypto/md5-glue.c | 99 -----------
6 files changed, 346 deletions(-)
delete mode 100644 arch/powerpc/crypto/md5-asm.S
delete mode 100644 arch/powerpc/crypto/md5-glue.c
diff --git a/arch/powerpc/configs/powernv_defconfig b/arch/powerpc/configs/powernv_defconfig
index d06388b0f66e3..bd4685612de6d 100644
--- a/arch/powerpc/configs/powernv_defconfig
+++ b/arch/powerpc/configs/powernv_defconfig
@@ -318,11 +318,10 @@ CONFIG_FTR_FIXUP_SELFTEST=y
CONFIG_MSI_BITMAP_SELFTEST=y
CONFIG_XMON=y
CONFIG_CRYPTO_BENCHMARK=m
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_MD5_PPC=m
CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_SHA256=y
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_ANUBIS=m
CONFIG_CRYPTO_BLOWFISH=m
diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig
index ce34597e9f3e1..2d92c11eea7e4 100644
--- a/arch/powerpc/configs/ppc64_defconfig
+++ b/arch/powerpc/configs/ppc64_defconfig
@@ -385,11 +385,10 @@ CONFIG_CRYPTO_TWOFISH=m
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_SHA256=y
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_LZO=m
-CONFIG_CRYPTO_MD5_PPC=m
CONFIG_CRYPTO_AES_GCM_P10=m
CONFIG_CRYPTO_DEV_NX=y
CONFIG_CRYPTO_DEV_NX_ENCRYPT=m
CONFIG_CRYPTO_DEV_VMX=y
CONFIG_SYSTEM_TRUSTED_KEYRING=y
diff --git a/arch/powerpc/crypto/Kconfig b/arch/powerpc/crypto/Kconfig
index cfe39fc221cf8..f4b779c7352de 100644
--- a/arch/powerpc/crypto/Kconfig
+++ b/arch/powerpc/crypto/Kconfig
@@ -13,18 +13,10 @@ config CRYPTO_CURVE25519_PPC64
Curve25519 algorithm
Architecture: PowerPC64
- Little-endian
-config CRYPTO_MD5_PPC
- tristate "Digests: MD5"
- select CRYPTO_HASH
- help
- MD5 message digest algorithm (RFC1321)
-
- Architecture: powerpc
-
config CRYPTO_AES_PPC_SPE
tristate "Ciphers: AES, modes: ECB/CBC/CTR/XTS (SPE)"
depends on SPE
select CRYPTO_SKCIPHER
help
diff --git a/arch/powerpc/crypto/Makefile b/arch/powerpc/crypto/Makefile
index bc8fd27344b8b..9eb59dce67f36 100644
--- a/arch/powerpc/crypto/Makefile
+++ b/arch/powerpc/crypto/Makefile
@@ -4,17 +4,15 @@
#
# Arch-specific CryptoAPI modules.
#
obj-$(CONFIG_CRYPTO_AES_PPC_SPE) += aes-ppc-spe.o
-obj-$(CONFIG_CRYPTO_MD5_PPC) += md5-ppc.o
obj-$(CONFIG_CRYPTO_AES_GCM_P10) += aes-gcm-p10-crypto.o
obj-$(CONFIG_CRYPTO_DEV_VMX_ENCRYPT) += vmx-crypto.o
obj-$(CONFIG_CRYPTO_CURVE25519_PPC64) += curve25519-ppc64le.o
aes-ppc-spe-y := aes-spe-core.o aes-spe-keys.o aes-tab-4k.o aes-spe-modes.o aes-spe-glue.o
-md5-ppc-y := md5-asm.o md5-glue.o
aes-gcm-p10-crypto-y := aes-gcm-p10-glue.o aes-gcm-p10.o ghashp10-ppc.o aesp10-ppc.o
vmx-crypto-objs := vmx.o aesp8-ppc.o ghashp8-ppc.o aes.o aes_cbc.o aes_ctr.o aes_xts.o ghash.o
curve25519-ppc64le-y := curve25519-ppc64le-core.o curve25519-ppc64le_asm.o
ifeq ($(CONFIG_CPU_LITTLE_ENDIAN),y)
diff --git a/arch/powerpc/crypto/md5-asm.S b/arch/powerpc/crypto/md5-asm.S
deleted file mode 100644
index fa6bc440cf4ac..0000000000000
--- a/arch/powerpc/crypto/md5-asm.S
+++ /dev/null
@@ -1,235 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Fast MD5 implementation for PPC
- *
- * Copyright (c) 2015 Markus Stockhausen <stockhausen@collogia.de>
- */
-#include <asm/ppc_asm.h>
-#include <asm/asm-offsets.h>
-#include <asm/asm-compat.h>
-
-#define rHP r3
-#define rWP r4
-
-#define rH0 r0
-#define rH1 r6
-#define rH2 r7
-#define rH3 r5
-
-#define rW00 r8
-#define rW01 r9
-#define rW02 r10
-#define rW03 r11
-#define rW04 r12
-#define rW05 r14
-#define rW06 r15
-#define rW07 r16
-#define rW08 r17
-#define rW09 r18
-#define rW10 r19
-#define rW11 r20
-#define rW12 r21
-#define rW13 r22
-#define rW14 r23
-#define rW15 r24
-
-#define rT0 r25
-#define rT1 r26
-
-#define INITIALIZE \
- PPC_STLU r1,-INT_FRAME_SIZE(r1); \
- SAVE_GPRS(14, 26, r1) /* push registers onto stack */
-
-#define FINALIZE \
- REST_GPRS(14, 26, r1); /* pop registers from stack */ \
- addi r1,r1,INT_FRAME_SIZE
-
-#ifdef __BIG_ENDIAN__
-#define LOAD_DATA(reg, off) \
- lwbrx reg,0,rWP; /* load data */
-#define INC_PTR \
- addi rWP,rWP,4; /* increment per word */
-#define NEXT_BLOCK /* nothing to do */
-#else
-#define LOAD_DATA(reg, off) \
- lwz reg,off(rWP); /* load data */
-#define INC_PTR /* nothing to do */
-#define NEXT_BLOCK \
- addi rWP,rWP,64; /* increment per block */
-#endif
-
-#define R_00_15(a, b, c, d, w0, w1, p, q, off, k0h, k0l, k1h, k1l) \
- LOAD_DATA(w0, off) /* W */ \
- and rT0,b,c; /* 1: f = b and c */ \
- INC_PTR /* ptr++ */ \
- andc rT1,d,b; /* 1: f' = ~b and d */ \
- LOAD_DATA(w1, off+4) /* W */ \
- or rT0,rT0,rT1; /* 1: f = f or f' */ \
- addi w0,w0,k0l; /* 1: wk = w + k */ \
- add a,a,rT0; /* 1: a = a + f */ \
- addis w0,w0,k0h; /* 1: wk = w + k' */ \
- addis w1,w1,k1h; /* 2: wk = w + k */ \
- add a,a,w0; /* 1: a = a + wk */ \
- addi w1,w1,k1l; /* 2: wk = w + k' */ \
- rotrwi a,a,p; /* 1: a = a rotl x */ \
- add d,d,w1; /* 2: a = a + wk */ \
- add a,a,b; /* 1: a = a + b */ \
- and rT0,a,b; /* 2: f = b and c */ \
- andc rT1,c,a; /* 2: f' = ~b and d */ \
- or rT0,rT0,rT1; /* 2: f = f or f' */ \
- add d,d,rT0; /* 2: a = a + f */ \
- INC_PTR /* ptr++ */ \
- rotrwi d,d,q; /* 2: a = a rotl x */ \
- add d,d,a; /* 2: a = a + b */
-
-#define R_16_31(a, b, c, d, w0, w1, p, q, k0h, k0l, k1h, k1l) \
- andc rT0,c,d; /* 1: f = c and ~d */ \
- and rT1,b,d; /* 1: f' = b and d */ \
- addi w0,w0,k0l; /* 1: wk = w + k */ \
- or rT0,rT0,rT1; /* 1: f = f or f' */ \
- addis w0,w0,k0h; /* 1: wk = w + k' */ \
- add a,a,rT0; /* 1: a = a + f */ \
- addi w1,w1,k1l; /* 2: wk = w + k */ \
- add a,a,w0; /* 1: a = a + wk */ \
- addis w1,w1,k1h; /* 2: wk = w + k' */ \
- andc rT0,b,c; /* 2: f = c and ~d */ \
- rotrwi a,a,p; /* 1: a = a rotl x */ \
- add a,a,b; /* 1: a = a + b */ \
- add d,d,w1; /* 2: a = a + wk */ \
- and rT1,a,c; /* 2: f' = b and d */ \
- or rT0,rT0,rT1; /* 2: f = f or f' */ \
- add d,d,rT0; /* 2: a = a + f */ \
- rotrwi d,d,q; /* 2: a = a rotl x */ \
- add d,d,a; /* 2: a = a +b */
-
-#define R_32_47(a, b, c, d, w0, w1, p, q, k0h, k0l, k1h, k1l) \
- xor rT0,b,c; /* 1: f' = b xor c */ \
- addi w0,w0,k0l; /* 1: wk = w + k */ \
- xor rT1,rT0,d; /* 1: f = f xor f' */ \
- addis w0,w0,k0h; /* 1: wk = w + k' */ \
- add a,a,rT1; /* 1: a = a + f */ \
- addi w1,w1,k1l; /* 2: wk = w + k */ \
- add a,a,w0; /* 1: a = a + wk */ \
- addis w1,w1,k1h; /* 2: wk = w + k' */ \
- rotrwi a,a,p; /* 1: a = a rotl x */ \
- add d,d,w1; /* 2: a = a + wk */ \
- add a,a,b; /* 1: a = a + b */ \
- xor rT1,rT0,a; /* 2: f = b xor f' */ \
- add d,d,rT1; /* 2: a = a + f */ \
- rotrwi d,d,q; /* 2: a = a rotl x */ \
- add d,d,a; /* 2: a = a + b */
-
-#define R_48_63(a, b, c, d, w0, w1, p, q, k0h, k0l, k1h, k1l) \
- addi w0,w0,k0l; /* 1: w = w + k */ \
- orc rT0,b,d; /* 1: f = b or ~d */ \
- addis w0,w0,k0h; /* 1: w = w + k' */ \
- xor rT0,rT0,c; /* 1: f = f xor c */ \
- add a,a,w0; /* 1: a = a + wk */ \
- addi w1,w1,k1l; /* 2: w = w + k */ \
- add a,a,rT0; /* 1: a = a + f */ \
- addis w1,w1,k1h; /* 2: w = w + k' */ \
- rotrwi a,a,p; /* 1: a = a rotl x */ \
- add a,a,b; /* 1: a = a + b */ \
- orc rT0,a,c; /* 2: f = b or ~d */ \
- add d,d,w1; /* 2: a = a + wk */ \
- xor rT0,rT0,b; /* 2: f = f xor c */ \
- add d,d,rT0; /* 2: a = a + f */ \
- rotrwi d,d,q; /* 2: a = a rotl x */ \
- add d,d,a; /* 2: a = a + b */
-
-_GLOBAL(ppc_md5_transform)
- INITIALIZE
-
- mtctr r5
- lwz rH0,0(rHP)
- lwz rH1,4(rHP)
- lwz rH2,8(rHP)
- lwz rH3,12(rHP)
-
-ppc_md5_main:
- R_00_15(rH0, rH1, rH2, rH3, rW00, rW01, 25, 20, 0,
- 0xd76b, -23432, 0xe8c8, -18602)
- R_00_15(rH2, rH3, rH0, rH1, rW02, rW03, 15, 10, 8,
- 0x2420, 0x70db, 0xc1be, -12562)
- R_00_15(rH0, rH1, rH2, rH3, rW04, rW05, 25, 20, 16,
- 0xf57c, 0x0faf, 0x4788, -14806)
- R_00_15(rH2, rH3, rH0, rH1, rW06, rW07, 15, 10, 24,
- 0xa830, 0x4613, 0xfd47, -27391)
- R_00_15(rH0, rH1, rH2, rH3, rW08, rW09, 25, 20, 32,
- 0x6981, -26408, 0x8b45, -2129)
- R_00_15(rH2, rH3, rH0, rH1, rW10, rW11, 15, 10, 40,
- 0xffff, 0x5bb1, 0x895d, -10306)
- R_00_15(rH0, rH1, rH2, rH3, rW12, rW13, 25, 20, 48,
- 0x6b90, 0x1122, 0xfd98, 0x7193)
- R_00_15(rH2, rH3, rH0, rH1, rW14, rW15, 15, 10, 56,
- 0xa679, 0x438e, 0x49b4, 0x0821)
-
- R_16_31(rH0, rH1, rH2, rH3, rW01, rW06, 27, 23,
- 0x0d56, 0x6e0c, 0x1810, 0x6d2d)
- R_16_31(rH2, rH3, rH0, rH1, rW11, rW00, 18, 12,
- 0x9d02, -32109, 0x124c, 0x2332)
- R_16_31(rH0, rH1, rH2, rH3, rW05, rW10, 27, 23,
- 0x8ea7, 0x4a33, 0x0245, -18270)
- R_16_31(rH2, rH3, rH0, rH1, rW15, rW04, 18, 12,
- 0x8eee, -8608, 0xf258, -5095)
- R_16_31(rH0, rH1, rH2, rH3, rW09, rW14, 27, 23,
- 0x969d, -10697, 0x1cbe, -15288)
- R_16_31(rH2, rH3, rH0, rH1, rW03, rW08, 18, 12,
- 0x3317, 0x3e99, 0xdbd9, 0x7c15)
- R_16_31(rH0, rH1, rH2, rH3, rW13, rW02, 27, 23,
- 0xac4b, 0x7772, 0xd8cf, 0x331d)
- R_16_31(rH2, rH3, rH0, rH1, rW07, rW12, 18, 12,
- 0x6a28, 0x6dd8, 0x219a, 0x3b68)
-
- R_32_47(rH0, rH1, rH2, rH3, rW05, rW08, 28, 21,
- 0x29cb, 0x28e5, 0x4218, -7788)
- R_32_47(rH2, rH3, rH0, rH1, rW11, rW14, 16, 9,
- 0x473f, 0x06d1, 0x3aae, 0x3036)
- R_32_47(rH0, rH1, rH2, rH3, rW01, rW04, 28, 21,
- 0xaea1, -15134, 0x640b, -11295)
- R_32_47(rH2, rH3, rH0, rH1, rW07, rW10, 16, 9,
- 0x8f4c, 0x4887, 0xbc7c, -22499)
- R_32_47(rH0, rH1, rH2, rH3, rW13, rW00, 28, 21,
- 0x7eb8, -27199, 0x00ea, 0x6050)
- R_32_47(rH2, rH3, rH0, rH1, rW03, rW06, 16, 9,
- 0xe01a, 0x22fe, 0x4447, 0x69c5)
- R_32_47(rH0, rH1, rH2, rH3, rW09, rW12, 28, 21,
- 0xb7f3, 0x0253, 0x59b1, 0x4d5b)
- R_32_47(rH2, rH3, rH0, rH1, rW15, rW02, 16, 9,
- 0x4701, -27017, 0xc7bd, -19859)
-
- R_48_63(rH0, rH1, rH2, rH3, rW00, rW07, 26, 22,
- 0x0988, -1462, 0x4c70, -19401)
- R_48_63(rH2, rH3, rH0, rH1, rW14, rW05, 17, 11,
- 0xadaf, -5221, 0xfc99, 0x66f7)
- R_48_63(rH0, rH1, rH2, rH3, rW12, rW03, 26, 22,
- 0x7e80, -16418, 0xba1e, -25587)
- R_48_63(rH2, rH3, rH0, rH1, rW10, rW01, 17, 11,
- 0x4130, 0x380d, 0xe0c5, 0x738d)
- lwz rW00,0(rHP)
- R_48_63(rH0, rH1, rH2, rH3, rW08, rW15, 26, 22,
- 0xe837, -30770, 0xde8a, 0x69e8)
- lwz rW14,4(rHP)
- R_48_63(rH2, rH3, rH0, rH1, rW06, rW13, 17, 11,
- 0x9e79, 0x260f, 0x256d, -27941)
- lwz rW12,8(rHP)
- R_48_63(rH0, rH1, rH2, rH3, rW04, rW11, 26, 22,
- 0xab75, -20775, 0x4f9e, -28397)
- lwz rW10,12(rHP)
- R_48_63(rH2, rH3, rH0, rH1, rW02, rW09, 17, 11,
- 0x662b, 0x7c56, 0x11b2, 0x0358)
-
- add rH0,rH0,rW00
- stw rH0,0(rHP)
- add rH1,rH1,rW14
- stw rH1,4(rHP)
- add rH2,rH2,rW12
- stw rH2,8(rHP)
- add rH3,rH3,rW10
- stw rH3,12(rHP)
- NEXT_BLOCK
-
- bdnz ppc_md5_main
-
- FINALIZE
- blr
diff --git a/arch/powerpc/crypto/md5-glue.c b/arch/powerpc/crypto/md5-glue.c
deleted file mode 100644
index 204440a90cd84..0000000000000
--- a/arch/powerpc/crypto/md5-glue.c
+++ /dev/null
@@ -1,99 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Glue code for MD5 implementation for PPC assembler
- *
- * Based on generic implementation.
- *
- * Copyright (c) 2015 Markus Stockhausen <stockhausen@collogia.de>
- */
-
-#include <crypto/internal/hash.h>
-#include <crypto/md5.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/string.h>
-
-extern void ppc_md5_transform(u32 *state, const u8 *src, u32 blocks);
-
-static int ppc_md5_init(struct shash_desc *desc)
-{
- struct md5_state *sctx = shash_desc_ctx(desc);
-
- sctx->hash[0] = MD5_H0;
- sctx->hash[1] = MD5_H1;
- sctx->hash[2] = MD5_H2;
- sctx->hash[3] = MD5_H3;
- sctx->byte_count = 0;
-
- return 0;
-}
-
-static int ppc_md5_update(struct shash_desc *desc, const u8 *data,
- unsigned int len)
-{
- struct md5_state *sctx = shash_desc_ctx(desc);
-
- sctx->byte_count += round_down(len, MD5_HMAC_BLOCK_SIZE);
- ppc_md5_transform(sctx->hash, data, len >> 6);
- return len - round_down(len, MD5_HMAC_BLOCK_SIZE);
-}
-
-static int ppc_md5_finup(struct shash_desc *desc, const u8 *src,
- unsigned int offset, u8 *out)
-{
- struct md5_state *sctx = shash_desc_ctx(desc);
- __le64 block[MD5_BLOCK_WORDS] = {};
- u8 *p = memcpy(block, src, offset);
- __le32 *dst = (__le32 *)out;
- __le64 *pbits;
-
- 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);
- ppc_md5_transform(sctx->hash, src, (pbits - block + 1) / 8);
- memzero_explicit(block, sizeof(block));
-
- dst[0] = cpu_to_le32(sctx->hash[0]);
- dst[1] = cpu_to_le32(sctx->hash[1]);
- dst[2] = cpu_to_le32(sctx->hash[2]);
- dst[3] = cpu_to_le32(sctx->hash[3]);
- return 0;
-}
-
-static struct shash_alg alg = {
- .digestsize = MD5_DIGEST_SIZE,
- .init = ppc_md5_init,
- .update = ppc_md5_update,
- .finup = ppc_md5_finup,
- .descsize = MD5_STATE_SIZE,
- .base = {
- .cra_name = "md5",
- .cra_driver_name= "md5-ppc",
- .cra_priority = 200,
- .cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY,
- .cra_blocksize = MD5_HMAC_BLOCK_SIZE,
- .cra_module = THIS_MODULE,
- }
-};
-
-static int __init ppc_md5_mod_init(void)
-{
- return crypto_register_shash(&alg);
-}
-
-static void __exit ppc_md5_mod_fini(void)
-{
- crypto_unregister_shash(&alg);
-}
-
-module_init(ppc_md5_mod_init);
-module_exit(ppc_md5_mod_fini);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("MD5 Secure Hash Algorithm, PPC assembler");
-
-MODULE_ALIAS_CRYPTO("md5");
-MODULE_ALIAS_CRYPTO("md5-ppc");
--
2.50.1
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH 4/7] crypto: sparc/md5 - Remove SPARC64 optimized MD5 code
2025-08-03 20:44 [PATCH 0/7] MD5 library functions Eric Biggers
` (2 preceding siblings ...)
2025-08-03 20:44 ` [PATCH 3/7] crypto: powerpc/md5 - Remove PowerPC optimized MD5 code Eric Biggers
@ 2025-08-03 20:44 ` Eric Biggers
2025-08-04 4:44 ` Simon Richter
2025-08-03 20:44 ` [PATCH 5/7] lib/crypto: md5: Add MD5 and HMAC-MD5 library functions Eric Biggers
` (2 subsequent siblings)
6 siblings, 1 reply; 26+ messages in thread
From: Eric Biggers @ 2025-08-03 20:44 UTC (permalink / raw)
To: linux-crypto
Cc: linux-kernel, Ard Biesheuvel, Jason A . Donenfeld, linux-mips,
linuxppc-dev, sparclinux, Eric Biggers
MD5 is insecure, is no longer commonly used, and has never been
optimized for the most common architectures in the kernel. Only mips,
powerpc, and sparc have optimized MD5 code in the kernel. Of these,
only the powerpc one is actually testable in QEMU. The mips one works
only on Cavium Octeon SoCs.
Taken together, it's clear that it's time to retire these additional MD5
implementations, and focus maintenance on the MD5 generic C code.
This commit removes the SPARC64 optimized MD5 code.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
arch/sparc/crypto/Kconfig | 10 --
arch/sparc/crypto/Makefile | 4 -
arch/sparc/crypto/md5_asm.S | 70 --------------
arch/sparc/crypto/md5_glue.c | 174 -----------------------------------
4 files changed, 258 deletions(-)
delete mode 100644 arch/sparc/crypto/md5_asm.S
delete mode 100644 arch/sparc/crypto/md5_glue.c
diff --git a/arch/sparc/crypto/Kconfig b/arch/sparc/crypto/Kconfig
index f5b2e720fec3c..f755da9795346 100644
--- a/arch/sparc/crypto/Kconfig
+++ b/arch/sparc/crypto/Kconfig
@@ -14,20 +14,10 @@ config CRYPTO_DES_SPARC64
Length-preserving ciphers: DES with ECB and CBC modes
Length-preserving ciphers: Tripe DES EDE with ECB and CBC modes
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
select CRYPTO_SKCIPHER
help
diff --git a/arch/sparc/crypto/Makefile b/arch/sparc/crypto/Makefile
index 0d05a17988c4c..7b4796842ddd7 100644
--- a/arch/sparc/crypto/Makefile
+++ b/arch/sparc/crypto/Makefile
@@ -1,16 +1,12 @@
# SPDX-License-Identifier: GPL-2.0
#
# 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
diff --git a/arch/sparc/crypto/md5_asm.S b/arch/sparc/crypto/md5_asm.S
deleted file mode 100644
index 60b544e4d205b..0000000000000
--- a/arch/sparc/crypto/md5_asm.S
+++ /dev/null
@@ -1,70 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <linux/linkage.h>
-#include <asm/opcodes.h>
-#include <asm/visasm.h>
-
-ENTRY(md5_sparc64_transform)
- /* %o0 = digest, %o1 = data, %o2 = rounds */
- VISEntryHalf
- ld [%o0 + 0x00], %f0
- ld [%o0 + 0x04], %f1
- andcc %o1, 0x7, %g0
- ld [%o0 + 0x08], %f2
- bne,pn %xcc, 10f
- ld [%o0 + 0x0c], %f3
-
-1:
- ldd [%o1 + 0x00], %f8
- ldd [%o1 + 0x08], %f10
- ldd [%o1 + 0x10], %f12
- ldd [%o1 + 0x18], %f14
- ldd [%o1 + 0x20], %f16
- ldd [%o1 + 0x28], %f18
- ldd [%o1 + 0x30], %f20
- ldd [%o1 + 0x38], %f22
-
- MD5
-
- subcc %o2, 1, %o2
- bne,pt %xcc, 1b
- add %o1, 0x40, %o1
-
-5:
- st %f0, [%o0 + 0x00]
- st %f1, [%o0 + 0x04]
- st %f2, [%o0 + 0x08]
- st %f3, [%o0 + 0x0c]
- retl
- VISExitHalf
-10:
- alignaddr %o1, %g0, %o1
-
- ldd [%o1 + 0x00], %f10
-1:
- ldd [%o1 + 0x08], %f12
- ldd [%o1 + 0x10], %f14
- ldd [%o1 + 0x18], %f16
- ldd [%o1 + 0x20], %f18
- ldd [%o1 + 0x28], %f20
- ldd [%o1 + 0x30], %f22
- ldd [%o1 + 0x38], %f24
- ldd [%o1 + 0x40], %f26
-
- faligndata %f10, %f12, %f8
- faligndata %f12, %f14, %f10
- faligndata %f14, %f16, %f12
- faligndata %f16, %f18, %f14
- faligndata %f18, %f20, %f16
- faligndata %f20, %f22, %f18
- faligndata %f22, %f24, %f20
- faligndata %f24, %f26, %f22
-
- MD5
-
- subcc %o2, 1, %o2
- fsrc2 %f26, %f10
- bne,pt %xcc, 1b
- add %o1, 0x40, %o1
-
- ba,a,pt %xcc, 5b
-ENDPROC(md5_sparc64_transform)
diff --git a/arch/sparc/crypto/md5_glue.c b/arch/sparc/crypto/md5_glue.c
deleted file mode 100644
index b3615f0cdf626..0000000000000
--- a/arch/sparc/crypto/md5_glue.c
+++ /dev/null
@@ -1,174 +0,0 @@
-// 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"
--
2.50.1
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH 5/7] lib/crypto: md5: Add MD5 and HMAC-MD5 library functions
2025-08-03 20:44 [PATCH 0/7] MD5 library functions Eric Biggers
` (3 preceding siblings ...)
2025-08-03 20:44 ` [PATCH 4/7] crypto: sparc/md5 - Remove SPARC64 " Eric Biggers
@ 2025-08-03 20:44 ` Eric Biggers
2025-08-03 20:44 ` [PATCH 6/7] crypto: md5 - Wrap library and add HMAC support Eric Biggers
2025-08-03 20:44 ` [PATCH 7/7] lib/crypto: tests: Add KUnit tests for MD5 and HMAC-MD5 Eric Biggers
6 siblings, 0 replies; 26+ messages in thread
From: Eric Biggers @ 2025-08-03 20:44 UTC (permalink / raw)
To: linux-crypto
Cc: linux-kernel, Ard Biesheuvel, Jason A . Donenfeld, linux-mips,
linuxppc-dev, sparclinux, Eric Biggers
Add library functions for MD5, including HMAC support. The MD5
implementation is derived from crypto/md5.c. This closely mirrors the
corresponding SHA-1 and SHA-2 changes; however, support for architecture
optimized MD5 implementations isn't included since it is unnecessary.
While MD5 is an insecure legacy algorithm, it still has various
in-kernel users that implement legacy protocols. Switching to a simple
library API, which is the way the code should have been organized
originally, will greatly simplify their code. For example:
MD5:
drivers/md/dm-crypt.c (for lmk IV generation)
fs/nfsd/nfs4recover.c
fs/ecryptfs/
fs/smb/client/
net/{ipv4,ipv6}/ (for TCP-MD5 signatures)
HMAC-MD5:
fs/smb/client/
fs/smb/server/
(Also net/sctp/ if it continues using HMAC-MD5 for cookie generation.
However, that use case has the flexibility to upgrade to a more modern
algorithm, which I'll be proposing instead.)
As usual, the "md5" and "hmac(md5)" crypto_shash algorithms will also be
reimplemented on top of these library functions. For "hmac(md5)" this
will provide a faster, more streamlined implementation.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
include/crypto/md5.h | 181 ++++++++++++++++++++++++++-
lib/crypto/Kconfig | 6 +
lib/crypto/Makefile | 3 +
lib/crypto/md5.c | 290 +++++++++++++++++++++++++++++++++++++++++++
4 files changed, 479 insertions(+), 1 deletion(-)
create mode 100644 lib/crypto/md5.c
diff --git a/include/crypto/md5.h b/include/crypto/md5.h
index 28ee533a0507a..d8e4d3c7c0369 100644
--- a/include/crypto/md5.h
+++ b/include/crypto/md5.h
@@ -5,10 +5,11 @@
#include <crypto/hash.h>
#include <linux/types.h>
#define MD5_DIGEST_SIZE 16
#define MD5_HMAC_BLOCK_SIZE 64
+#define MD5_BLOCK_SIZE 64
#define MD5_BLOCK_WORDS 16
#define MD5_HASH_WORDS 4
#define MD5_STATE_SIZE 24
#define MD5_H0 0x67452301UL
@@ -25,6 +26,184 @@ struct md5_state {
u32 hash[MD5_HASH_WORDS];
u64 byte_count;
u32 block[MD5_BLOCK_WORDS];
};
-#endif
+/* State for the MD5 compression function */
+struct md5_block_state {
+ u32 h[MD5_HASH_WORDS];
+};
+
+/**
+ * struct md5_ctx - Context for hashing a message with MD5
+ * @state: the compression function state
+ * @bytecount: number of bytes processed so far
+ * @buf: partial block buffer; bytecount % MD5_BLOCK_SIZE bytes are valid
+ */
+struct md5_ctx {
+ struct md5_block_state state;
+ u64 bytecount;
+ u8 buf[MD5_BLOCK_SIZE] __aligned(__alignof__(__le64));
+};
+
+/**
+ * md5_init() - Initialize an MD5 context for a new message
+ * @ctx: the context to initialize
+ *
+ * If you don't need incremental computation, consider md5() instead.
+ *
+ * Context: Any context.
+ */
+void md5_init(struct md5_ctx *ctx);
+
+/**
+ * md5_update() - Update an MD5 context with message data
+ * @ctx: the context to update; must have been initialized
+ * @data: the message data
+ * @len: the data length in bytes
+ *
+ * This can be called any number of times.
+ *
+ * Context: Any context.
+ */
+void md5_update(struct md5_ctx *ctx, const u8 *data, size_t len);
+
+/**
+ * md5_final() - Finish computing an MD5 message digest
+ * @ctx: the context to finalize; must have been initialized
+ * @out: (output) the resulting MD5 message digest
+ *
+ * After finishing, this zeroizes @ctx. So the caller does not need to do it.
+ *
+ * Context: Any context.
+ */
+void md5_final(struct md5_ctx *ctx, u8 out[MD5_DIGEST_SIZE]);
+
+/**
+ * md5() - Compute MD5 message digest in one shot
+ * @data: the message data
+ * @len: the data length in bytes
+ * @out: (output) the resulting MD5 message digest
+ *
+ * Context: Any context.
+ */
+void md5(const u8 *data, size_t len, u8 out[MD5_DIGEST_SIZE]);
+
+/**
+ * struct hmac_md5_key - Prepared key for HMAC-MD5
+ * @istate: private
+ * @ostate: private
+ */
+struct hmac_md5_key {
+ struct md5_block_state istate;
+ struct md5_block_state ostate;
+};
+
+/**
+ * struct hmac_md5_ctx - Context for computing HMAC-MD5 of a message
+ * @hash_ctx: private
+ * @ostate: private
+ */
+struct hmac_md5_ctx {
+ struct md5_ctx hash_ctx;
+ struct md5_block_state ostate;
+};
+
+/**
+ * hmac_md5_preparekey() - Prepare a key for HMAC-MD5
+ * @key: (output) the key structure to initialize
+ * @raw_key: the raw HMAC-MD5 key
+ * @raw_key_len: the key length in bytes. All key lengths are supported.
+ *
+ * Note: the caller is responsible for zeroizing both the struct hmac_md5_key
+ * and the raw key once they are no longer needed.
+ *
+ * Context: Any context.
+ */
+void hmac_md5_preparekey(struct hmac_md5_key *key,
+ const u8 *raw_key, size_t raw_key_len);
+
+/**
+ * hmac_md5_init() - Initialize an HMAC-MD5 context for a new message
+ * @ctx: (output) the HMAC context to initialize
+ * @key: the prepared HMAC key
+ *
+ * If you don't need incremental computation, consider hmac_md5() instead.
+ *
+ * Context: Any context.
+ */
+void hmac_md5_init(struct hmac_md5_ctx *ctx, const struct hmac_md5_key *key);
+
+/**
+ * hmac_md5_init_usingrawkey() - Initialize an HMAC-MD5 context for a new
+ * message, using a raw key
+ * @ctx: (output) the HMAC context to initialize
+ * @raw_key: the raw HMAC-MD5 key
+ * @raw_key_len: the key length in bytes. All key lengths are supported.
+ *
+ * If you don't need incremental computation, consider hmac_md5_usingrawkey()
+ * instead.
+ *
+ * Context: Any context.
+ */
+void hmac_md5_init_usingrawkey(struct hmac_md5_ctx *ctx,
+ const u8 *raw_key, size_t raw_key_len);
+
+/**
+ * hmac_md5_update() - Update an HMAC-MD5 context with message data
+ * @ctx: the HMAC context to update; must have been initialized
+ * @data: the message data
+ * @data_len: the data length in bytes
+ *
+ * This can be called any number of times.
+ *
+ * Context: Any context.
+ */
+static inline void hmac_md5_update(struct hmac_md5_ctx *ctx,
+ const u8 *data, size_t data_len)
+{
+ md5_update(&ctx->hash_ctx, data, data_len);
+}
+
+/**
+ * hmac_md5_final() - Finish computing an HMAC-MD5 value
+ * @ctx: the HMAC context to finalize; must have been initialized
+ * @out: (output) the resulting HMAC-MD5 value
+ *
+ * After finishing, this zeroizes @ctx. So the caller does not need to do it.
+ *
+ * Context: Any context.
+ */
+void hmac_md5_final(struct hmac_md5_ctx *ctx, u8 out[MD5_DIGEST_SIZE]);
+
+/**
+ * hmac_md5() - Compute HMAC-MD5 in one shot, using a prepared key
+ * @key: the prepared HMAC key
+ * @data: the message data
+ * @data_len: the data length in bytes
+ * @out: (output) the resulting HMAC-MD5 value
+ *
+ * If you're using the key only once, consider using hmac_md5_usingrawkey().
+ *
+ * Context: Any context.
+ */
+void hmac_md5(const struct hmac_md5_key *key, const u8 *data, size_t data_len,
+ u8 out[MD5_DIGEST_SIZE]);
+
+/**
+ * hmac_md5_usingrawkey() - Compute HMAC-MD5 in one shot, using a raw key
+ * @raw_key: the raw HMAC-MD5 key
+ * @raw_key_len: the key length in bytes. All key lengths are supported.
+ * @data: the message data
+ * @data_len: the data length in bytes
+ * @out: (output) the resulting HMAC-MD5 value
+ *
+ * If you're using the key multiple times, prefer to use hmac_md5_preparekey()
+ * followed by multiple calls to hmac_md5() instead.
+ *
+ * Context: Any context.
+ */
+void hmac_md5_usingrawkey(const u8 *raw_key, size_t raw_key_len,
+ const u8 *data, size_t data_len,
+ u8 out[MD5_DIGEST_SIZE]);
+
+#endif /* _CRYPTO_MD5_H */
diff --git a/lib/crypto/Kconfig b/lib/crypto/Kconfig
index c2b65b6a9bb6f..f1b2a51450df2 100644
--- a/lib/crypto/Kconfig
+++ b/lib/crypto/Kconfig
@@ -99,10 +99,16 @@ config CRYPTO_LIB_CURVE25519
one, if one is available and enabled.
config CRYPTO_LIB_DES
tristate
+config CRYPTO_LIB_MD5
+ tristate
+ help
+ The MD5 and HMAC-MD5 library functions. Select this if your module
+ uses any of the functions from <crypto/md5.h>.
+
config CRYPTO_LIB_POLY1305_RSIZE
int
default 2 if MIPS
default 11 if X86_64
default 9 if ARM || ARM64
diff --git a/lib/crypto/Makefile b/lib/crypto/Makefile
index e4151be2ebd44..252480ab97e9c 100644
--- a/lib/crypto/Makefile
+++ b/lib/crypto/Makefile
@@ -57,10 +57,13 @@ libcurve25519-y += curve25519.o
libcurve25519-$(CONFIG_CRYPTO_SELFTESTS) += curve25519-selftest.o
obj-$(CONFIG_CRYPTO_LIB_DES) += libdes.o
libdes-y := des.o
+obj-$(CONFIG_CRYPTO_LIB_MD5) += libmd5.o
+libmd5-y := md5.o
+
obj-$(CONFIG_CRYPTO_LIB_POLY1305) += libpoly1305.o
libpoly1305-y += poly1305.o
obj-$(CONFIG_CRYPTO_LIB_POLY1305_GENERIC) += libpoly1305-generic.o
libpoly1305-generic-y := poly1305-donna32.o
diff --git a/lib/crypto/md5.c b/lib/crypto/md5.c
new file mode 100644
index 0000000000000..17323340963b5
--- /dev/null
+++ b/lib/crypto/md5.c
@@ -0,0 +1,290 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * MD5 and HMAC-MD5 library functions
+ *
+ * md5_transform() is derived from cryptoapi implementation, originally based on
+ * the public domain implementation written by Colin Plumb in 1993.
+ *
+ * Copyright (c) Cryptoapi developers.
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ * Copyright 2025 Google LLC
+ */
+
+#include <crypto/hmac.h>
+#include <crypto/md5.h>
+#include <linux/export.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/unaligned.h>
+#include <linux/wordpart.h>
+
+static const struct md5_block_state md5_iv = {
+ .h = { MD5_H0, MD5_H1, MD5_H2, MD5_H3 },
+};
+
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+#define MD5STEP(f, w, x, y, z, in, s) \
+ (w += f(x, y, z) + in, w = (w << s | w >> (32 - s)) + x)
+
+static void md5_transform(struct md5_block_state *state,
+ const u8 data[MD5_BLOCK_SIZE])
+{
+ u32 in[MD5_BLOCK_WORDS];
+ u32 a, b, c, d;
+
+ memcpy(in, data, MD5_BLOCK_SIZE);
+ le32_to_cpu_array(in, ARRAY_SIZE(in));
+
+ a = state->h[0];
+ b = state->h[1];
+ c = state->h[2];
+ d = state->h[3];
+
+ MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
+ MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
+ MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
+ MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
+ MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
+ MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
+ MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
+ MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
+ MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
+ MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
+ MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
+ MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
+ MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
+ MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
+ MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
+ MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
+
+ MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
+ MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
+ MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
+ MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
+ MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
+ MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
+ MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
+ MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
+ MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
+ MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
+ MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
+ MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
+ MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
+ MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
+ MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
+ MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
+
+ MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
+ MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
+ MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
+ MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
+ MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
+ MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
+ MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
+ MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
+ MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
+ MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
+ MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
+ MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
+ MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
+ MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
+ MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
+ MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
+
+ MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
+ MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
+ MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
+ MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
+ MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
+ MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
+ MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
+ MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
+ MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
+ MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
+ MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
+ MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
+ MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
+ MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
+ MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
+ MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
+
+ state->h[0] += a;
+ state->h[1] += b;
+ state->h[2] += c;
+ state->h[3] += d;
+}
+
+void md5_init(struct md5_ctx *ctx)
+{
+ ctx->state = md5_iv;
+ ctx->bytecount = 0;
+}
+EXPORT_SYMBOL_GPL(md5_init);
+
+void md5_update(struct md5_ctx *ctx, const u8 *data, size_t len)
+{
+ size_t partial = ctx->bytecount % MD5_BLOCK_SIZE;
+
+ ctx->bytecount += len;
+
+ if (partial + len >= MD5_BLOCK_SIZE) {
+
+ if (partial) {
+ size_t l = MD5_BLOCK_SIZE - partial;
+
+ memcpy(&ctx->buf[partial], data, l);
+ data += l;
+ len -= l;
+
+ md5_transform(&ctx->state, ctx->buf);
+ }
+
+ while (len >= MD5_BLOCK_SIZE) {
+ md5_transform(&ctx->state, data);
+ data += MD5_BLOCK_SIZE;
+ len -= MD5_BLOCK_SIZE;
+ }
+ partial = 0;
+ }
+ if (len)
+ memcpy(&ctx->buf[partial], data, len);
+}
+EXPORT_SYMBOL_GPL(md5_update);
+
+static void __md5_final(struct md5_ctx *ctx, u8 out[MD5_DIGEST_SIZE])
+{
+ u64 bitcount = ctx->bytecount << 3;
+ size_t partial = ctx->bytecount % MD5_BLOCK_SIZE;
+
+ ctx->buf[partial++] = 0x80;
+ if (partial > MD5_BLOCK_SIZE - 8) {
+ memset(&ctx->buf[partial], 0, MD5_BLOCK_SIZE - partial);
+ md5_transform(&ctx->state, ctx->buf);
+ partial = 0;
+ }
+ memset(&ctx->buf[partial], 0, MD5_BLOCK_SIZE - 8 - partial);
+ *(__le64 *)&ctx->buf[MD5_BLOCK_SIZE - 8] = cpu_to_le64(bitcount);
+ md5_transform(&ctx->state, ctx->buf);
+
+ cpu_to_le32_array(ctx->state.h, ARRAY_SIZE(ctx->state.h));
+ memcpy(out, ctx->state.h, MD5_DIGEST_SIZE);
+}
+
+void md5_final(struct md5_ctx *ctx, u8 out[MD5_DIGEST_SIZE])
+{
+ __md5_final(ctx, out);
+ memzero_explicit(ctx, sizeof(*ctx));
+}
+EXPORT_SYMBOL_GPL(md5_final);
+
+void md5(const u8 *data, size_t len, u8 out[MD5_DIGEST_SIZE])
+{
+ struct md5_ctx ctx;
+
+ md5_init(&ctx);
+ md5_update(&ctx, data, len);
+ md5_final(&ctx, out);
+}
+EXPORT_SYMBOL_GPL(md5);
+
+static void __hmac_md5_preparekey(struct md5_block_state *istate,
+ struct md5_block_state *ostate,
+ const u8 *raw_key, size_t raw_key_len)
+{
+ union {
+ u8 b[MD5_BLOCK_SIZE];
+ unsigned long w[MD5_BLOCK_SIZE / sizeof(unsigned long)];
+ } derived_key = { 0 };
+
+ if (unlikely(raw_key_len > MD5_BLOCK_SIZE))
+ md5(raw_key, raw_key_len, derived_key.b);
+ else
+ memcpy(derived_key.b, raw_key, raw_key_len);
+
+ for (size_t i = 0; i < ARRAY_SIZE(derived_key.w); i++)
+ derived_key.w[i] ^= REPEAT_BYTE(HMAC_IPAD_VALUE);
+ *istate = md5_iv;
+ md5_transform(istate, derived_key.b);
+
+ for (size_t i = 0; i < ARRAY_SIZE(derived_key.w); i++)
+ derived_key.w[i] ^= REPEAT_BYTE(HMAC_OPAD_VALUE ^
+ HMAC_IPAD_VALUE);
+ *ostate = md5_iv;
+ md5_transform(ostate, derived_key.b);
+
+ memzero_explicit(&derived_key, sizeof(derived_key));
+}
+
+void hmac_md5_preparekey(struct hmac_md5_key *key,
+ const u8 *raw_key, size_t raw_key_len)
+{
+ __hmac_md5_preparekey(&key->istate, &key->ostate, raw_key, raw_key_len);
+}
+EXPORT_SYMBOL_GPL(hmac_md5_preparekey);
+
+void hmac_md5_init(struct hmac_md5_ctx *ctx, const struct hmac_md5_key *key)
+{
+ ctx->hash_ctx.state = key->istate;
+ ctx->hash_ctx.bytecount = MD5_BLOCK_SIZE;
+ ctx->ostate = key->ostate;
+}
+EXPORT_SYMBOL_GPL(hmac_md5_init);
+
+void hmac_md5_init_usingrawkey(struct hmac_md5_ctx *ctx,
+ const u8 *raw_key, size_t raw_key_len)
+{
+ __hmac_md5_preparekey(&ctx->hash_ctx.state, &ctx->ostate,
+ raw_key, raw_key_len);
+ ctx->hash_ctx.bytecount = MD5_BLOCK_SIZE;
+}
+EXPORT_SYMBOL_GPL(hmac_md5_init_usingrawkey);
+
+void hmac_md5_final(struct hmac_md5_ctx *ctx, u8 out[MD5_DIGEST_SIZE])
+{
+ /* Generate the padded input for the outer hash in ctx->hash_ctx.buf. */
+ __md5_final(&ctx->hash_ctx, ctx->hash_ctx.buf);
+ memset(&ctx->hash_ctx.buf[MD5_DIGEST_SIZE], 0,
+ MD5_BLOCK_SIZE - MD5_DIGEST_SIZE);
+ ctx->hash_ctx.buf[MD5_DIGEST_SIZE] = 0x80;
+ *(__le64 *)&ctx->hash_ctx.buf[MD5_BLOCK_SIZE - 8] =
+ cpu_to_le64(8 * (MD5_BLOCK_SIZE + MD5_DIGEST_SIZE));
+
+ /* Compute the outer hash, which gives the HMAC value. */
+ md5_transform(&ctx->ostate, ctx->hash_ctx.buf);
+ cpu_to_le32_array(ctx->ostate.h, ARRAY_SIZE(ctx->ostate.h));
+ memcpy(out, ctx->ostate.h, MD5_DIGEST_SIZE);
+
+ memzero_explicit(ctx, sizeof(*ctx));
+}
+EXPORT_SYMBOL_GPL(hmac_md5_final);
+
+void hmac_md5(const struct hmac_md5_key *key, const u8 *data, size_t data_len,
+ u8 out[MD5_DIGEST_SIZE])
+{
+ struct hmac_md5_ctx ctx;
+
+ hmac_md5_init(&ctx, key);
+ hmac_md5_update(&ctx, data, data_len);
+ hmac_md5_final(&ctx, out);
+}
+EXPORT_SYMBOL_GPL(hmac_md5);
+
+void hmac_md5_usingrawkey(const u8 *raw_key, size_t raw_key_len,
+ const u8 *data, size_t data_len,
+ u8 out[MD5_DIGEST_SIZE])
+{
+ struct hmac_md5_ctx ctx;
+
+ hmac_md5_init_usingrawkey(&ctx, raw_key, raw_key_len);
+ hmac_md5_update(&ctx, data, data_len);
+ hmac_md5_final(&ctx, out);
+}
+EXPORT_SYMBOL_GPL(hmac_md5_usingrawkey);
+
+MODULE_DESCRIPTION("MD5 and HMAC-MD5 library functions");
+MODULE_LICENSE("GPL");
--
2.50.1
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH 6/7] crypto: md5 - Wrap library and add HMAC support
2025-08-03 20:44 [PATCH 0/7] MD5 library functions Eric Biggers
` (4 preceding siblings ...)
2025-08-03 20:44 ` [PATCH 5/7] lib/crypto: md5: Add MD5 and HMAC-MD5 library functions Eric Biggers
@ 2025-08-03 20:44 ` Eric Biggers
2025-08-03 20:44 ` [PATCH 7/7] lib/crypto: tests: Add KUnit tests for MD5 and HMAC-MD5 Eric Biggers
6 siblings, 0 replies; 26+ messages in thread
From: Eric Biggers @ 2025-08-03 20:44 UTC (permalink / raw)
To: linux-crypto
Cc: linux-kernel, Ard Biesheuvel, Jason A . Donenfeld, linux-mips,
linuxppc-dev, sparclinux, Eric Biggers
Reimplement crypto/md5.c on top of the new MD5 library functions. Also
add support for HMAC-MD5, again just wrapping the library functions.
This closely mirrors crypto/sha1.c.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
crypto/Kconfig | 2 +-
crypto/md5.c | 359 ++++++++++++++++++--------------------
crypto/testmgr.c | 3 +
drivers/crypto/img-hash.c | 2 +-
4 files changed, 171 insertions(+), 195 deletions(-)
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 23bd98981ae8e..331c4fbb158b2 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -937,11 +937,11 @@ config CRYPTO_MD4
config CRYPTO_MD5
tristate "MD5"
select CRYPTO_HASH
help
- MD5 message digest algorithm (RFC1321)
+ MD5 message digest algorithm (RFC1321), including HMAC support.
config CRYPTO_MICHAEL_MIC
tristate "Michael MIC"
select CRYPTO_HASH
help
diff --git a/crypto/md5.c b/crypto/md5.c
index 32c0819f51185..d05c53e6f3c2c 100644
--- a/crypto/md5.c
+++ b/crypto/md5.c
@@ -1,224 +1,197 @@
-/*
- * Cryptographic API.
- *
- * MD5 Message Digest Algorithm (RFC1321).
- *
- * Derived from cryptoapi implementation, originally based on the
- * public domain implementation written by Colin Plumb in 1993.
- *
- * Copyright (c) Cryptoapi developers.
- * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Crypto API support for MD5 and HMAC-MD5
*
+ * Copyright 2025 Google LLC
*/
#include <crypto/internal/hash.h>
#include <crypto/md5.h>
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/string.h>
+
+/*
+ * Export and import functions. crypto_shash wants a particular format that
+ * matches that used by some legacy drivers. It currently is the same as the
+ * library MD5 context, except the value in bytecount must be block-aligned and
+ * the remainder must be stored in an extra u8 appended to the struct.
+ */
+
+#define MD5_SHASH_STATE_SIZE (sizeof(struct md5_ctx) + 1)
+static_assert(sizeof(struct md5_ctx) == sizeof(struct md5_state));
+static_assert(offsetof(struct md5_ctx, state) == offsetof(struct md5_state, hash));
+static_assert(offsetof(struct md5_ctx, bytecount) == offsetof(struct md5_state, byte_count));
+static_assert(offsetof(struct md5_ctx, buf) == offsetof(struct md5_state, block));
+
+static int __crypto_md5_export(const struct md5_ctx *ctx0, void *out)
+{
+ struct md5_ctx ctx = *ctx0;
+ unsigned int partial;
+ u8 *p = out;
+
+ partial = ctx.bytecount % MD5_BLOCK_SIZE;
+ ctx.bytecount -= partial;
+ memcpy(p, &ctx, sizeof(ctx));
+ p += sizeof(ctx);
+ *p = partial;
+ return 0;
+}
+
+static int __crypto_md5_import(struct md5_ctx *ctx, const void *in)
+{
+ const u8 *p = in;
+
+ memcpy(ctx, p, sizeof(*ctx));
+ p += sizeof(*ctx);
+ ctx->bytecount += *p;
+ return 0;
+}
const u8 md5_zero_message_hash[MD5_DIGEST_SIZE] = {
0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04,
0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e,
};
EXPORT_SYMBOL_GPL(md5_zero_message_hash);
-#define F1(x, y, z) (z ^ (x & (y ^ z)))
-#define F2(x, y, z) F1(z, x, y)
-#define F3(x, y, z) (x ^ y ^ z)
-#define F4(x, y, z) (y ^ (x | ~z))
-
-#define MD5STEP(f, w, x, y, z, in, s) \
- (w += f(x, y, z) + in, w = (w<<s | w>>(32-s)) + x)
-
-static void md5_transform(__u32 *hash, __u32 const *in)
-{
- u32 a, b, c, d;
-
- a = hash[0];
- b = hash[1];
- c = hash[2];
- d = hash[3];
-
- MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
- MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
- MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
- MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
- MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
- MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
- MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
- MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
- MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
- MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
- MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
- MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
- MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
- MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
- MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
- MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
-
- MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
- MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
- MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
- MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
- MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
- MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
- MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
- MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
- MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
- MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
- MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
- MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
- MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
- MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
- MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
- MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
-
- MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
- MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
- MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
- MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
- MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
- MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
- MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
- MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
- MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
- MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
- MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
- MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
- MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
- MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
- MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
- MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
-
- MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
- MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
- MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
- MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
- MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
- MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
- MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
- MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
- MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
- MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
- MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
- MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
- MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
- MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
- MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
- MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
-
- hash[0] += a;
- hash[1] += b;
- hash[2] += c;
- hash[3] += d;
-}
-
-static inline void md5_transform_helper(struct md5_state *ctx,
- u32 block[MD5_BLOCK_WORDS])
-{
- le32_to_cpu_array(block, MD5_BLOCK_WORDS);
- md5_transform(ctx->hash, block);
-}
-
-static int md5_init(struct shash_desc *desc)
-{
- struct md5_state *mctx = shash_desc_ctx(desc);
-
- mctx->hash[0] = MD5_H0;
- mctx->hash[1] = MD5_H1;
- mctx->hash[2] = MD5_H2;
- mctx->hash[3] = MD5_H3;
- mctx->byte_count = 0;
+#define MD5_CTX(desc) ((struct md5_ctx *)shash_desc_ctx(desc))
+static int crypto_md5_init(struct shash_desc *desc)
+{
+ md5_init(MD5_CTX(desc));
return 0;
}
-static int md5_update(struct shash_desc *desc, const u8 *data, unsigned int len)
-{
- struct md5_state *mctx = shash_desc_ctx(desc);
- u32 block[MD5_BLOCK_WORDS];
-
- mctx->byte_count += len;
- do {
- memcpy(block, data, sizeof(block));
- md5_transform_helper(mctx, block);
- data += sizeof(block);
- len -= sizeof(block);
- } while (len >= sizeof(block));
- memzero_explicit(block, sizeof(block));
- mctx->byte_count -= len;
- return len;
-}
-
-static int md5_finup(struct shash_desc *desc, const u8 *data, unsigned int len,
- u8 *out)
-{
- struct md5_state *mctx = shash_desc_ctx(desc);
- u32 block[MD5_BLOCK_WORDS];
- unsigned int offset;
- int padding;
- char *p;
-
- memcpy(block, data, len);
-
- offset = len;
- p = (char *)block + offset;
- padding = 56 - (offset + 1);
-
- *p++ = 0x80;
- if (padding < 0) {
- memset(p, 0x00, padding + sizeof (u64));
- md5_transform_helper(mctx, block);
- p = (char *)block;
- padding = 56;
- }
-
- memset(p, 0, padding);
- mctx->byte_count += len;
- block[14] = mctx->byte_count << 3;
- block[15] = mctx->byte_count >> 29;
- le32_to_cpu_array(block, (sizeof(block) - sizeof(u64)) / sizeof(u32));
- md5_transform(mctx->hash, block);
- memzero_explicit(block, sizeof(block));
- cpu_to_le32_array(mctx->hash, sizeof(mctx->hash) / sizeof(u32));
- memcpy(out, mctx->hash, sizeof(mctx->hash));
+static int crypto_md5_update(struct shash_desc *desc,
+ const u8 *data, unsigned int len)
+{
+ md5_update(MD5_CTX(desc), data, len);
+ return 0;
+}
+static int crypto_md5_final(struct shash_desc *desc, u8 *out)
+{
+ md5_final(MD5_CTX(desc), out);
return 0;
}
-static struct shash_alg alg = {
- .digestsize = MD5_DIGEST_SIZE,
- .init = md5_init,
- .update = md5_update,
- .finup = md5_finup,
- .descsize = MD5_STATE_SIZE,
- .base = {
- .cra_name = "md5",
- .cra_driver_name = "md5-generic",
- .cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY,
- .cra_blocksize = MD5_HMAC_BLOCK_SIZE,
- .cra_module = THIS_MODULE,
- }
-};
+static int crypto_md5_digest(struct shash_desc *desc,
+ const u8 *data, unsigned int len, u8 *out)
+{
+ md5(data, len, out);
+ return 0;
+}
+
+static int crypto_md5_export(struct shash_desc *desc, void *out)
+{
+ return __crypto_md5_export(MD5_CTX(desc), out);
+}
+
+static int crypto_md5_import(struct shash_desc *desc, const void *in)
+{
+ return __crypto_md5_import(MD5_CTX(desc), in);
+}
-static int __init md5_mod_init(void)
+#define HMAC_MD5_KEY(tfm) ((struct hmac_md5_key *)crypto_shash_ctx(tfm))
+#define HMAC_MD5_CTX(desc) ((struct hmac_md5_ctx *)shash_desc_ctx(desc))
+
+static int crypto_hmac_md5_setkey(struct crypto_shash *tfm,
+ const u8 *raw_key, unsigned int keylen)
+{
+ hmac_md5_preparekey(HMAC_MD5_KEY(tfm), raw_key, keylen);
+ return 0;
+}
+
+static int crypto_hmac_md5_init(struct shash_desc *desc)
+{
+ hmac_md5_init(HMAC_MD5_CTX(desc), HMAC_MD5_KEY(desc->tfm));
+ return 0;
+}
+
+static int crypto_hmac_md5_update(struct shash_desc *desc,
+ const u8 *data, unsigned int len)
+{
+ hmac_md5_update(HMAC_MD5_CTX(desc), data, len);
+ return 0;
+}
+
+static int crypto_hmac_md5_final(struct shash_desc *desc, u8 *out)
+{
+ hmac_md5_final(HMAC_MD5_CTX(desc), out);
+ return 0;
+}
+
+static int crypto_hmac_md5_digest(struct shash_desc *desc,
+ const u8 *data, unsigned int len, u8 *out)
+{
+ hmac_md5(HMAC_MD5_KEY(desc->tfm), data, len, out);
+ return 0;
+}
+
+static int crypto_hmac_md5_export(struct shash_desc *desc, void *out)
{
- return crypto_register_shash(&alg);
+ return __crypto_md5_export(&HMAC_MD5_CTX(desc)->hash_ctx, out);
}
-static void __exit md5_mod_fini(void)
+static int crypto_hmac_md5_import(struct shash_desc *desc, const void *in)
{
- crypto_unregister_shash(&alg);
+ struct hmac_md5_ctx *ctx = HMAC_MD5_CTX(desc);
+
+ ctx->ostate = HMAC_MD5_KEY(desc->tfm)->ostate;
+ return __crypto_md5_import(&ctx->hash_ctx, in);
}
-module_init(md5_mod_init);
-module_exit(md5_mod_fini);
+static struct shash_alg algs[] = {
+ {
+ .base.cra_name = "md5",
+ .base.cra_driver_name = "md5-lib",
+ .base.cra_priority = 300,
+ .base.cra_blocksize = MD5_BLOCK_SIZE,
+ .base.cra_module = THIS_MODULE,
+ .digestsize = MD5_DIGEST_SIZE,
+ .init = crypto_md5_init,
+ .update = crypto_md5_update,
+ .final = crypto_md5_final,
+ .digest = crypto_md5_digest,
+ .export = crypto_md5_export,
+ .import = crypto_md5_import,
+ .descsize = sizeof(struct md5_ctx),
+ .statesize = MD5_SHASH_STATE_SIZE,
+ },
+ {
+ .base.cra_name = "hmac(md5)",
+ .base.cra_driver_name = "hmac-md5-lib",
+ .base.cra_priority = 300,
+ .base.cra_blocksize = MD5_BLOCK_SIZE,
+ .base.cra_ctxsize = sizeof(struct hmac_md5_key),
+ .base.cra_module = THIS_MODULE,
+ .digestsize = MD5_DIGEST_SIZE,
+ .setkey = crypto_hmac_md5_setkey,
+ .init = crypto_hmac_md5_init,
+ .update = crypto_hmac_md5_update,
+ .final = crypto_hmac_md5_final,
+ .digest = crypto_hmac_md5_digest,
+ .export = crypto_hmac_md5_export,
+ .import = crypto_hmac_md5_import,
+ .descsize = sizeof(struct hmac_md5_ctx),
+ .statesize = MD5_SHASH_STATE_SIZE,
+ },
+};
+
+static int __init crypto_md5_mod_init(void)
+{
+ return crypto_register_shashes(algs, ARRAY_SIZE(algs));
+}
+module_init(crypto_md5_mod_init);
+
+static void __exit crypto_md5_mod_exit(void)
+{
+ crypto_unregister_shashes(algs, ARRAY_SIZE(algs));
+}
+module_exit(crypto_md5_mod_exit);
MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("MD5 Message Digest Algorithm");
+MODULE_DESCRIPTION("Crypto API support for MD5 and HMAC-MD5");
+
MODULE_ALIAS_CRYPTO("md5");
+MODULE_ALIAS_CRYPTO("md5-lib");
+MODULE_ALIAS_CRYPTO("hmac(md5)");
+MODULE_ALIAS_CRYPTO("hmac-md5-lib");
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index ee33ba21ae2bc..beab926ba102e 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -4176,10 +4176,11 @@ static const struct alg_test_desc alg_test_descs[] = {
.suite = {
.cprng = __VECS(ansi_cprng_aes_tv_template)
}
}, {
.alg = "authenc(hmac(md5),ecb(cipher_null))",
+ .generic_driver = "authenc(hmac-md5-lib,ecb-cipher_null)",
.test = alg_test_aead,
.suite = {
.aead = __VECS(hmac_md5_ecb_cipher_null_tv_template)
}
}, {
@@ -5062,10 +5063,11 @@ static const struct alg_test_desc alg_test_descs[] = {
.suite = {
.cipher = __VECS(aes_hctr2_tv_template)
}
}, {
.alg = "hmac(md5)",
+ .generic_driver = "hmac-md5-lib",
.test = alg_test_hash,
.suite = {
.hash = __VECS(hmac_md5_tv_template)
}
}, {
@@ -5248,10 +5250,11 @@ static const struct alg_test_desc alg_test_descs[] = {
.suite = {
.hash = __VECS(md4_tv_template)
}
}, {
.alg = "md5",
+ .generic_driver = "md5-lib",
.test = alg_test_hash,
.suite = {
.hash = __VECS(md5_tv_template)
}
}, {
diff --git a/drivers/crypto/img-hash.c b/drivers/crypto/img-hash.c
index 76b7ecb5624b1..f22c12e36b56c 100644
--- a/drivers/crypto/img-hash.c
+++ b/drivers/crypto/img-hash.c
@@ -698,11 +698,11 @@ static int img_hash_cra_init(struct crypto_tfm *tfm, const char *alg_name)
return 0;
}
static int img_hash_cra_md5_init(struct crypto_tfm *tfm)
{
- return img_hash_cra_init(tfm, "md5-generic");
+ return img_hash_cra_init(tfm, "md5-lib");
}
static int img_hash_cra_sha1_init(struct crypto_tfm *tfm)
{
return img_hash_cra_init(tfm, "sha1-lib");
--
2.50.1
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH 7/7] lib/crypto: tests: Add KUnit tests for MD5 and HMAC-MD5
2025-08-03 20:44 [PATCH 0/7] MD5 library functions Eric Biggers
` (5 preceding siblings ...)
2025-08-03 20:44 ` [PATCH 6/7] crypto: md5 - Wrap library and add HMAC support Eric Biggers
@ 2025-08-03 20:44 ` Eric Biggers
6 siblings, 0 replies; 26+ messages in thread
From: Eric Biggers @ 2025-08-03 20:44 UTC (permalink / raw)
To: linux-crypto
Cc: linux-kernel, Ard Biesheuvel, Jason A . Donenfeld, linux-mips,
linuxppc-dev, sparclinux, Eric Biggers
Add a KUnit test suite for the MD5 library functions, including the
corresponding HMAC support. The core test logic is in the
previously-added hash-test-template.h. This commit just adds the actual
KUnit suite, and it adds the generated test vectors to the tree so that
gen-hash-testvecs.py won't have to be run at build time.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
lib/crypto/tests/Kconfig | 10 ++
lib/crypto/tests/Makefile | 1 +
lib/crypto/tests/md5-testvecs.h | 186 ++++++++++++++++++++++++++++++++
lib/crypto/tests/md5_kunit.c | 39 +++++++
4 files changed, 236 insertions(+)
create mode 100644 lib/crypto/tests/md5-testvecs.h
create mode 100644 lib/crypto/tests/md5_kunit.c
diff --git a/lib/crypto/tests/Kconfig b/lib/crypto/tests/Kconfig
index de7e8babb6afc..c21d53fd4b0ce 100644
--- a/lib/crypto/tests/Kconfig
+++ b/lib/crypto/tests/Kconfig
@@ -1,7 +1,17 @@
# SPDX-License-Identifier: GPL-2.0-or-later
+config CRYPTO_LIB_MD5_KUNIT_TEST
+ tristate "KUnit tests for MD5" if !KUNIT_ALL_TESTS
+ depends on KUNIT
+ default KUNIT_ALL_TESTS || CRYPTO_SELFTESTS
+ select CRYPTO_LIB_BENCHMARK_VISIBLE
+ select CRYPTO_LIB_MD5
+ help
+ KUnit tests for the MD5 cryptographic hash function and its
+ corresponding HMAC.
+
config CRYPTO_LIB_POLY1305_KUNIT_TEST
tristate "KUnit tests for Poly1305" if !KUNIT_ALL_TESTS
depends on KUNIT
default KUNIT_ALL_TESTS || CRYPTO_SELFTESTS
select CRYPTO_LIB_BENCHMARK_VISIBLE
diff --git a/lib/crypto/tests/Makefile b/lib/crypto/tests/Makefile
index 8601dccd6fdda..f6f82c6f9cb5d 100644
--- a/lib/crypto/tests/Makefile
+++ b/lib/crypto/tests/Makefile
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-or-later
+obj-$(CONFIG_CRYPTO_LIB_MD5_KUNIT_TEST) += md5_kunit.o
obj-$(CONFIG_CRYPTO_LIB_POLY1305_KUNIT_TEST) += poly1305_kunit.o
obj-$(CONFIG_CRYPTO_LIB_SHA1_KUNIT_TEST) += sha1_kunit.o
obj-$(CONFIG_CRYPTO_LIB_SHA256_KUNIT_TEST) += sha224_kunit.o sha256_kunit.o
obj-$(CONFIG_CRYPTO_LIB_SHA512_KUNIT_TEST) += sha384_kunit.o sha512_kunit.o
diff --git a/lib/crypto/tests/md5-testvecs.h b/lib/crypto/tests/md5-testvecs.h
new file mode 100644
index 0000000000000..be6727feb2966
--- /dev/null
+++ b/lib/crypto/tests/md5-testvecs.h
@@ -0,0 +1,186 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* This file was generated by: ./scripts/crypto/gen-hash-testvecs.py md5 */
+
+static const struct {
+ size_t data_len;
+ u8 digest[MD5_DIGEST_SIZE];
+} hash_testvecs[] = {
+ {
+ .data_len = 0,
+ .digest = {
+ 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04,
+ 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e,
+ },
+ },
+ {
+ .data_len = 1,
+ .digest = {
+ 0x16, 0x7b, 0x86, 0xf2, 0x1d, 0xf3, 0x76, 0xc9,
+ 0x6f, 0x10, 0xa0, 0x61, 0x5b, 0x14, 0x20, 0x0b,
+ },
+ },
+ {
+ .data_len = 2,
+ .digest = {
+ 0x2d, 0x30, 0x96, 0xc7, 0x43, 0x40, 0xed, 0xb2,
+ 0xfb, 0x84, 0x63, 0x9a, 0xec, 0xc7, 0x3c, 0x3c,
+ },
+ },
+ {
+ .data_len = 3,
+ .digest = {
+ 0xe5, 0x0f, 0xce, 0xe0, 0xc8, 0xff, 0x4e, 0x08,
+ 0x5e, 0x19, 0xe5, 0xf2, 0x08, 0x11, 0x19, 0x16,
+ },
+ },
+ {
+ .data_len = 16,
+ .digest = {
+ 0xe8, 0xca, 0x29, 0x05, 0x2f, 0xd1, 0xf3, 0x99,
+ 0x40, 0x71, 0xf5, 0xc2, 0xf7, 0xf8, 0x17, 0x3e,
+ },
+ },
+ {
+ .data_len = 32,
+ .digest = {
+ 0xe3, 0x20, 0xc1, 0xd8, 0x21, 0x14, 0x44, 0x59,
+ 0x1a, 0xf5, 0x91, 0xaf, 0x69, 0xbe, 0x93, 0x9d,
+ },
+ },
+ {
+ .data_len = 48,
+ .digest = {
+ 0xfb, 0x06, 0xb0, 0xf0, 0x00, 0x10, 0x4b, 0x68,
+ 0x3d, 0x75, 0xf9, 0x70, 0xde, 0xbb, 0x32, 0x16,
+ },
+ },
+ {
+ .data_len = 49,
+ .digest = {
+ 0x52, 0x86, 0x48, 0x8b, 0xae, 0x91, 0x7c, 0x4e,
+ 0xc2, 0x2a, 0x69, 0x07, 0x35, 0xcc, 0xb2, 0x88,
+ },
+ },
+ {
+ .data_len = 63,
+ .digest = {
+ 0xfa, 0xd3, 0xf6, 0xe6, 0x7b, 0x1a, 0xc6, 0x05,
+ 0x73, 0x35, 0x02, 0xab, 0xc7, 0xb3, 0x47, 0xcb,
+ },
+ },
+ {
+ .data_len = 64,
+ .digest = {
+ 0xc5, 0x59, 0x29, 0xe9, 0x0a, 0x4a, 0x86, 0x43,
+ 0x7c, 0xaf, 0xdf, 0x83, 0xd3, 0xb8, 0x33, 0x5f,
+ },
+ },
+ {
+ .data_len = 65,
+ .digest = {
+ 0x80, 0x05, 0x75, 0x39, 0xec, 0x44, 0x8a, 0x81,
+ 0xe7, 0x6e, 0x8d, 0xd1, 0xc6, 0xeb, 0xc2, 0xf0,
+ },
+ },
+ {
+ .data_len = 127,
+ .digest = {
+ 0x3f, 0x02, 0xe8, 0xc6, 0xb8, 0x6a, 0x39, 0xc3,
+ 0xa4, 0x1c, 0xd9, 0x8f, 0x4a, 0x71, 0x40, 0x30,
+ },
+ },
+ {
+ .data_len = 128,
+ .digest = {
+ 0x89, 0x4f, 0x79, 0x3e, 0xff, 0x0c, 0x22, 0x60,
+ 0xa2, 0xdc, 0x10, 0x5f, 0x23, 0x0a, 0xe7, 0xc6,
+ },
+ },
+ {
+ .data_len = 129,
+ .digest = {
+ 0x06, 0x56, 0x61, 0xb8, 0x8a, 0x82, 0x77, 0x1b,
+ 0x2c, 0x35, 0xb8, 0x9f, 0xd6, 0xf7, 0xbd, 0x5a,
+ },
+ },
+ {
+ .data_len = 256,
+ .digest = {
+ 0x5d, 0xdf, 0x7d, 0xc8, 0x43, 0x96, 0x3b, 0xdb,
+ 0xc7, 0x0e, 0x44, 0x42, 0x23, 0xf7, 0xed, 0xdf,
+ },
+ },
+ {
+ .data_len = 511,
+ .digest = {
+ 0xf6, 0x5f, 0x26, 0x51, 0x8a, 0x5a, 0x46, 0x8f,
+ 0x48, 0x72, 0x90, 0x74, 0x9d, 0x87, 0xbd, 0xdf,
+ },
+ },
+ {
+ .data_len = 513,
+ .digest = {
+ 0xd8, 0x2c, 0xc9, 0x76, 0xfa, 0x67, 0x2e, 0xa6,
+ 0xc8, 0x12, 0x4a, 0x64, 0xaa, 0x0b, 0x3d, 0xbd,
+ },
+ },
+ {
+ .data_len = 1000,
+ .digest = {
+ 0xe2, 0x7e, 0xb4, 0x5f, 0xe1, 0x74, 0x51, 0xfc,
+ 0xe0, 0xc8, 0xd5, 0xe6, 0x8b, 0x40, 0xd2, 0x0e,
+ },
+ },
+ {
+ .data_len = 3333,
+ .digest = {
+ 0xcd, 0x7d, 0x56, 0xa9, 0x4c, 0x47, 0xea, 0xc2,
+ 0x34, 0x0b, 0x84, 0x05, 0xf9, 0xad, 0xbb, 0x46,
+ },
+ },
+ {
+ .data_len = 4096,
+ .digest = {
+ 0x63, 0x6e, 0x58, 0xb3, 0x94, 0x6b, 0x83, 0x5f,
+ 0x1f, 0x0e, 0xd3, 0x66, 0x78, 0x71, 0x98, 0x42,
+ },
+ },
+ {
+ .data_len = 4128,
+ .digest = {
+ 0x9d, 0x68, 0xfc, 0x26, 0x8b, 0x4c, 0xa8, 0xe7,
+ 0x30, 0x0b, 0x19, 0x52, 0x6e, 0xa5, 0x65, 0x1c,
+ },
+ },
+ {
+ .data_len = 4160,
+ .digest = {
+ 0x1c, 0xaa, 0x7d, 0xee, 0x91, 0x01, 0xe2, 0x5a,
+ 0xec, 0xe9, 0xde, 0x57, 0x0a, 0xb6, 0x4c, 0x2f,
+ },
+ },
+ {
+ .data_len = 4224,
+ .digest = {
+ 0x1b, 0x31, 0xe3, 0x14, 0x07, 0x16, 0x17, 0xc6,
+ 0x98, 0x79, 0x88, 0x23, 0xb6, 0x3b, 0x25, 0xc4,
+ },
+ },
+ {
+ .data_len = 16384,
+ .digest = {
+ 0xc6, 0x3d, 0x56, 0x90, 0xf0, 0xf6, 0xe6, 0x50,
+ 0xf4, 0x76, 0x78, 0x67, 0xa3, 0xdd, 0x62, 0x7b,
+ },
+ },
+};
+
+static const u8 hash_testvec_consolidated[MD5_DIGEST_SIZE] = {
+ 0x70, 0x86, 0x9e, 0x6c, 0xa4, 0xc6, 0x71, 0x43,
+ 0x26, 0x02, 0x1b, 0x3f, 0xfd, 0x56, 0x9f, 0xa6,
+};
+
+static const u8 hmac_testvec_consolidated[MD5_DIGEST_SIZE] = {
+ 0x10, 0x02, 0x74, 0xf6, 0x4d, 0xb3, 0x3c, 0xc7,
+ 0xa1, 0xf7, 0xe6, 0xd4, 0x32, 0x64, 0xfa, 0x6d,
+};
diff --git a/lib/crypto/tests/md5_kunit.c b/lib/crypto/tests/md5_kunit.c
new file mode 100644
index 0000000000000..38bd52c25ae3e
--- /dev/null
+++ b/lib/crypto/tests/md5_kunit.c
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright 2025 Google LLC
+ */
+#include <crypto/md5.h>
+#include "md5-testvecs.h"
+
+#define HASH md5
+#define HASH_CTX md5_ctx
+#define HASH_SIZE MD5_DIGEST_SIZE
+#define HASH_INIT md5_init
+#define HASH_UPDATE md5_update
+#define HASH_FINAL md5_final
+#define HMAC_KEY hmac_md5_key
+#define HMAC_CTX hmac_md5_ctx
+#define HMAC_PREPAREKEY hmac_md5_preparekey
+#define HMAC_INIT hmac_md5_init
+#define HMAC_UPDATE hmac_md5_update
+#define HMAC_FINAL hmac_md5_final
+#define HMAC hmac_md5
+#define HMAC_USINGRAWKEY hmac_md5_usingrawkey
+#include "hash-test-template.h"
+
+static struct kunit_case hash_test_cases[] = {
+ HASH_KUNIT_CASES,
+ KUNIT_CASE(benchmark_hash),
+ {},
+};
+
+static struct kunit_suite hash_test_suite = {
+ .name = "md5",
+ .test_cases = hash_test_cases,
+ .suite_init = hash_suite_init,
+ .suite_exit = hash_suite_exit,
+};
+kunit_test_suite(hash_test_suite);
+
+MODULE_DESCRIPTION("KUnit tests and benchmark for MD5 and HMAC-MD5");
+MODULE_LICENSE("GPL");
--
2.50.1
^ permalink raw reply related [flat|nested] 26+ messages in thread
* Re: [PATCH 3/7] crypto: powerpc/md5 - Remove PowerPC optimized MD5 code
2025-08-03 20:44 ` [PATCH 3/7] crypto: powerpc/md5 - Remove PowerPC optimized MD5 code Eric Biggers
@ 2025-08-03 22:07 ` Segher Boessenkool
2025-08-03 22:14 ` Eric Biggers
2025-08-04 17:42 ` Christophe Leroy
1 sibling, 1 reply; 26+ messages in thread
From: Segher Boessenkool @ 2025-08-03 22:07 UTC (permalink / raw)
To: Eric Biggers
Cc: linux-crypto, linux-kernel, Ard Biesheuvel, Jason A . Donenfeld,
linux-mips, linuxppc-dev, sparclinux
On Sun, Aug 03, 2025 at 01:44:29PM -0700, Eric Biggers wrote:
> MD5 is insecure,
Really? Have you found an attack? Can you explain it to the rest of
the world?
MD5 is not recommended for future cryptographic purposes, there have
been some collission "attacks" on it (quotes because such a thing is
never an attack at all, merely an indication that not all is well with
it, somewhere in the future an actual vulnerability might be found).
Since there are newer, better, *cheaper* alternatives available, of
course you should not use MD5 for anything new anymore. But claiming it
is insecure is FUD.
> This commit removes the PowerPC optimized MD5 code.
Why? It would help to have real arguments for it!
If you just want to remove code you have no interest in, there are much
bigger targets available...
Segher
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 3/7] crypto: powerpc/md5 - Remove PowerPC optimized MD5 code
2025-08-03 22:07 ` Segher Boessenkool
@ 2025-08-03 22:14 ` Eric Biggers
2025-08-03 22:27 ` Segher Boessenkool
0 siblings, 1 reply; 26+ messages in thread
From: Eric Biggers @ 2025-08-03 22:14 UTC (permalink / raw)
To: Segher Boessenkool
Cc: linux-crypto, linux-kernel, Ard Biesheuvel, Jason A . Donenfeld,
linux-mips, linuxppc-dev, sparclinux
On Sun, Aug 03, 2025 at 05:07:10PM -0500, Segher Boessenkool wrote:
> On Sun, Aug 03, 2025 at 01:44:29PM -0700, Eric Biggers wrote:
> > MD5 is insecure,
>
> Really? Have you found an attack? Can you explain it to the rest of
> the world?
>
> MD5 is not recommended for future cryptographic purposes, there have
> been some collission "attacks" on it (quotes because such a thing is
> never an attack at all, merely an indication that not all is well with
> it, somewhere in the future an actual vulnerability might be found).
>
> Since there are newer, better, *cheaper* alternatives available, of
> course you should not use MD5 for anything new anymore. But claiming it
> is insecure is FUD.
Many attacks, including practical attacks, have been found on MD5 over
the past few decades. Check out https://en.wikipedia.org/wiki/MD5
> > This commit removes the PowerPC optimized MD5 code.
>
> Why? It would help to have real arguments for it!
Sure, check out the commit message which mentioned multiple reasons why
maintaining this code is not worthwhile.
- Eric
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 3/7] crypto: powerpc/md5 - Remove PowerPC optimized MD5 code
2025-08-03 22:14 ` Eric Biggers
@ 2025-08-03 22:27 ` Segher Boessenkool
2025-08-03 22:56 ` Eric Biggers
0 siblings, 1 reply; 26+ messages in thread
From: Segher Boessenkool @ 2025-08-03 22:27 UTC (permalink / raw)
To: Eric Biggers
Cc: linux-crypto, linux-kernel, Ard Biesheuvel, Jason A . Donenfeld,
linux-mips, linuxppc-dev, sparclinux
On Sun, Aug 03, 2025 at 03:14:38PM -0700, Eric Biggers wrote:
> On Sun, Aug 03, 2025 at 05:07:10PM -0500, Segher Boessenkool wrote:
> > On Sun, Aug 03, 2025 at 01:44:29PM -0700, Eric Biggers wrote:
> > > MD5 is insecure,
> >
> > Really? Have you found an attack? Can you explain it to the rest of
> > the world?
> >
> > MD5 is not recommended for future cryptographic purposes, there have
> > been some collission "attacks" on it (quotes because such a thing is
> > never an attack at all, merely an indication that not all is well with
> > it, somewhere in the future an actual vulnerability might be found).
> >
> > Since there are newer, better, *cheaper* alternatives available, of
> > course you should not use MD5 for anything new anymore. But claiming it
> > is insecure is FUD.
>
> Many attacks, including practical attacks, have been found on MD5 over
> the past few decades. Check out https://en.wikipedia.org/wiki/MD5
There is no new information on that page. There are no practical
attacks mentioned there, either, just some collission things (which
never can be practical attacks for most applications).
> > > This commit removes the PowerPC optimized MD5 code.
> >
> > Why? It would help to have real arguments for it!
>
> Sure, check out the commit message which mentioned multiple reasons why
> maintaining this code is not worthwhile.
Of course I have read that, but that information went missing, if you
intended to provide it :-(
You are replacing a known-working target implementation by a lower
performance generic implementation. But is that one known-working at
all? Does it come with tests? Was it tested to have the same outputs
as the existing thing, maybe? Just on a few inputs maybe.
We were not told anything like that.
Segher
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 3/7] crypto: powerpc/md5 - Remove PowerPC optimized MD5 code
2025-08-03 22:27 ` Segher Boessenkool
@ 2025-08-03 22:56 ` Eric Biggers
0 siblings, 0 replies; 26+ messages in thread
From: Eric Biggers @ 2025-08-03 22:56 UTC (permalink / raw)
To: Segher Boessenkool
Cc: linux-crypto, linux-kernel, Ard Biesheuvel, Jason A . Donenfeld,
linux-mips, linuxppc-dev, sparclinux
On Sun, Aug 03, 2025 at 05:27:01PM -0500, Segher Boessenkool wrote:
> You are replacing a known-working target implementation by a lower
> performance generic implementation.
That's probably correct, though FWIW there have been quite a few cases
where optimized assembly code in the kernel actually turned out to be
slower than the C code. (That primarily happens when the assembly code
doesn't take advantage of any special CPU features, which was the case
for this PowerPC code.) I don't have PowerPC hardware to check the
exact performance differential here, but IMO even if there was a
slowdown the factors still weigh strongly in favor of retiring this.
> But is that one known-working at all? Does it come with tests? Was
> it tested to have the same outputs as the existing thing, maybe? Just
> on a few inputs maybe.
Of course. Patch 7 adds a KUnit test suite for MD5, and there are still
the older tests in crypto/testmgr.c. And of course generic code is much
easier to test than arch-specific code. So not only is it tested, but
the test coverage is much better than it was before.
- Eric
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 4/7] crypto: sparc/md5 - Remove SPARC64 optimized MD5 code
2025-08-03 20:44 ` [PATCH 4/7] crypto: sparc/md5 - Remove SPARC64 " Eric Biggers
@ 2025-08-04 4:44 ` Simon Richter
2025-08-04 6:07 ` Eric Biggers
0 siblings, 1 reply; 26+ messages in thread
From: Simon Richter @ 2025-08-04 4:44 UTC (permalink / raw)
To: Eric Biggers, linux-crypto
Cc: linux-kernel, Ard Biesheuvel, Jason A . Donenfeld, linux-mips,
linuxppc-dev, sparclinux
Hi,
On 8/4/25 05:44, Eric Biggers wrote:
> Taken together, it's clear that it's time to retire these additional MD5
> implementations, and focus maintenance on the MD5 generic C code.
[...]
> - ldd [%o1 + 0x00], %f8
> - ldd [%o1 + 0x08], %f10
> - ldd [%o1 + 0x10], %f12
> - ldd [%o1 + 0x18], %f14
> - ldd [%o1 + 0x20], %f16
> - ldd [%o1 + 0x28], %f18
> - ldd [%o1 + 0x30], %f20
> - ldd [%o1 + 0x38], %f22
> -
> - MD5
This is a literal CPU instruction that ingests sixteen registers (f8 to
f23) and updates the hash state in f0 to f3.
I can see the point of removing hand-optimized assembler code when a
compiler can generate something that runs just as well from generic
code, but this here is using CPU extensions that were made for this
specific purpose.
This is exactly the kind of thing you would point to as an argument why
asynchronous hardware offload support is unnecessary.
Simon
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 4/7] crypto: sparc/md5 - Remove SPARC64 optimized MD5 code
2025-08-04 4:44 ` Simon Richter
@ 2025-08-04 6:07 ` Eric Biggers
0 siblings, 0 replies; 26+ messages in thread
From: Eric Biggers @ 2025-08-04 6:07 UTC (permalink / raw)
To: Simon Richter
Cc: linux-crypto, linux-kernel, Ard Biesheuvel, Jason A . Donenfeld,
linux-mips, linuxppc-dev, sparclinux
On Mon, Aug 04, 2025 at 01:44:21PM +0900, Simon Richter wrote:
> Hi,
>
> On 8/4/25 05:44, Eric Biggers wrote:
>
> > Taken together, it's clear that it's time to retire these additional MD5
> > implementations, and focus maintenance on the MD5 generic C code.
>
> [...]
>
> > - ldd [%o1 + 0x00], %f8
> > - ldd [%o1 + 0x08], %f10
> > - ldd [%o1 + 0x10], %f12
> > - ldd [%o1 + 0x18], %f14
> > - ldd [%o1 + 0x20], %f16
> > - ldd [%o1 + 0x28], %f18
> > - ldd [%o1 + 0x30], %f20
> > - ldd [%o1 + 0x38], %f22
> > -
> > - MD5
>
> This is a literal CPU instruction that ingests sixteen registers (f8 to f23)
> and updates the hash state in f0 to f3.
Note that QEMU doesn't support this instruction. I don't actually know
whether the SPARC64 MD5 code even works, especially after (presumably
untested) refactoring like commit cc1f5bbe428c91. I don't think anyone
does, TBH. No one seems to be running the crypto tests on SPARC64.
> I can see the point of removing hand-optimized assembler code when a
> compiler can generate something that runs just as well from generic code,
> but this here is using CPU extensions that were made for this specific
> purpose.
You do realize this is MD5, right? And also SPARC64?
I'm confused why people are so attached to still having MD5 assembly
code in 2025, and *only for rare platforms*. It's illogical.
We should just treat MD5 like the other legacy algorithms MD4 and RC4,
for which the kernel just has generic C code. That works perfectly fine
for the few users that still need those algorithms for compatibility
reasons.
> This is exactly the kind of thing you would point to as an argument why
> asynchronous hardware offload support is unnecessary.
For an algorithm that is actually worthwhile to accelerate, sure. For
MD5, it's not worthwhile anyway.
- Eric
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 3/7] crypto: powerpc/md5 - Remove PowerPC optimized MD5 code
2025-08-03 20:44 ` [PATCH 3/7] crypto: powerpc/md5 - Remove PowerPC optimized MD5 code Eric Biggers
2025-08-03 22:07 ` Segher Boessenkool
@ 2025-08-04 17:42 ` Christophe Leroy
2025-08-04 18:09 ` Eric Biggers
1 sibling, 1 reply; 26+ messages in thread
From: Christophe Leroy @ 2025-08-04 17:42 UTC (permalink / raw)
To: Eric Biggers, linux-crypto
Cc: linux-kernel, Ard Biesheuvel, Jason A . Donenfeld, linux-mips,
linuxppc-dev, sparclinux
Le 03/08/2025 à 22:44, Eric Biggers a écrit :
> MD5 is insecure, is no longer commonly used, and has never been
> optimized for the most common architectures in the kernel. Only mips,
> powerpc, and sparc have optimized MD5 code in the kernel. Of these,
> only the powerpc one is actually testable in QEMU. The mips one works
> only on Cavium Octeon SoCs.
>
> Taken together, it's clear that it's time to retire these additional MD5
> implementations, and focus maintenance on the MD5 generic C code.
Sorry, for me it is not that clear. Even if MD5 is depracated we still
have several applications that use MD5 for various reasons on our boards.
I ran the test on kernel v6.16 with following file:
# ls -l avion.au
-rw------- 1 root root 12130159 Jan 1 1970 avion.au
With CONFIG_CRYPTO_MD5_PPC:
# time md5sum avion.au
6513851d6109d42477b20cd56bf57f28 avion.au
real 0m 1.02s
user 0m 0.01s
sys 0m 1.01s
Without CONFIG_CRYPTO_MD5_PPC:
# time md5sum avion.au
6513851d6109d42477b20cd56bf57f28 avion.au
real 0m 1.35s
user 0m 0.01s
sys 0m 1.34s
I think the difference is big enough to consider keeping optimised MD5 code.
Christophe
>
> This commit removes the PowerPC optimized MD5 code.
>
> Signed-off-by: Eric Biggers <ebiggers@kernel.org>
> ---
> arch/powerpc/configs/powernv_defconfig | 1 -
> arch/powerpc/configs/ppc64_defconfig | 1 -
> arch/powerpc/crypto/Kconfig | 8 -
> arch/powerpc/crypto/Makefile | 2 -
> arch/powerpc/crypto/md5-asm.S | 235 -------------------------
> arch/powerpc/crypto/md5-glue.c | 99 -----------
> 6 files changed, 346 deletions(-)
> delete mode 100644 arch/powerpc/crypto/md5-asm.S
> delete mode 100644 arch/powerpc/crypto/md5-glue.c
>
> diff --git a/arch/powerpc/configs/powernv_defconfig b/arch/powerpc/configs/powernv_defconfig
> index d06388b0f66e3..bd4685612de6d 100644
> --- a/arch/powerpc/configs/powernv_defconfig
> +++ b/arch/powerpc/configs/powernv_defconfig
> @@ -318,11 +318,10 @@ CONFIG_FTR_FIXUP_SELFTEST=y
> CONFIG_MSI_BITMAP_SELFTEST=y
> CONFIG_XMON=y
> CONFIG_CRYPTO_BENCHMARK=m
> CONFIG_CRYPTO_PCBC=m
> CONFIG_CRYPTO_HMAC=y
> -CONFIG_CRYPTO_MD5_PPC=m
> CONFIG_CRYPTO_MICHAEL_MIC=m
> CONFIG_CRYPTO_SHA256=y
> CONFIG_CRYPTO_WP512=m
> CONFIG_CRYPTO_ANUBIS=m
> CONFIG_CRYPTO_BLOWFISH=m
> diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig
> index ce34597e9f3e1..2d92c11eea7e4 100644
> --- a/arch/powerpc/configs/ppc64_defconfig
> +++ b/arch/powerpc/configs/ppc64_defconfig
> @@ -385,11 +385,10 @@ CONFIG_CRYPTO_TWOFISH=m
> CONFIG_CRYPTO_PCBC=m
> CONFIG_CRYPTO_MICHAEL_MIC=m
> CONFIG_CRYPTO_SHA256=y
> CONFIG_CRYPTO_WP512=m
> CONFIG_CRYPTO_LZO=m
> -CONFIG_CRYPTO_MD5_PPC=m
> CONFIG_CRYPTO_AES_GCM_P10=m
> CONFIG_CRYPTO_DEV_NX=y
> CONFIG_CRYPTO_DEV_NX_ENCRYPT=m
> CONFIG_CRYPTO_DEV_VMX=y
> CONFIG_SYSTEM_TRUSTED_KEYRING=y
> diff --git a/arch/powerpc/crypto/Kconfig b/arch/powerpc/crypto/Kconfig
> index cfe39fc221cf8..f4b779c7352de 100644
> --- a/arch/powerpc/crypto/Kconfig
> +++ b/arch/powerpc/crypto/Kconfig
> @@ -13,18 +13,10 @@ config CRYPTO_CURVE25519_PPC64
> Curve25519 algorithm
>
> Architecture: PowerPC64
> - Little-endian
>
> -config CRYPTO_MD5_PPC
> - tristate "Digests: MD5"
> - select CRYPTO_HASH
> - help
> - MD5 message digest algorithm (RFC1321)
> -
> - Architecture: powerpc
> -
> config CRYPTO_AES_PPC_SPE
> tristate "Ciphers: AES, modes: ECB/CBC/CTR/XTS (SPE)"
> depends on SPE
> select CRYPTO_SKCIPHER
> help
> diff --git a/arch/powerpc/crypto/Makefile b/arch/powerpc/crypto/Makefile
> index bc8fd27344b8b..9eb59dce67f36 100644
> --- a/arch/powerpc/crypto/Makefile
> +++ b/arch/powerpc/crypto/Makefile
> @@ -4,17 +4,15 @@
> #
> # Arch-specific CryptoAPI modules.
> #
>
> obj-$(CONFIG_CRYPTO_AES_PPC_SPE) += aes-ppc-spe.o
> -obj-$(CONFIG_CRYPTO_MD5_PPC) += md5-ppc.o
> obj-$(CONFIG_CRYPTO_AES_GCM_P10) += aes-gcm-p10-crypto.o
> obj-$(CONFIG_CRYPTO_DEV_VMX_ENCRYPT) += vmx-crypto.o
> obj-$(CONFIG_CRYPTO_CURVE25519_PPC64) += curve25519-ppc64le.o
>
> aes-ppc-spe-y := aes-spe-core.o aes-spe-keys.o aes-tab-4k.o aes-spe-modes.o aes-spe-glue.o
> -md5-ppc-y := md5-asm.o md5-glue.o
> aes-gcm-p10-crypto-y := aes-gcm-p10-glue.o aes-gcm-p10.o ghashp10-ppc.o aesp10-ppc.o
> vmx-crypto-objs := vmx.o aesp8-ppc.o ghashp8-ppc.o aes.o aes_cbc.o aes_ctr.o aes_xts.o ghash.o
> curve25519-ppc64le-y := curve25519-ppc64le-core.o curve25519-ppc64le_asm.o
>
> ifeq ($(CONFIG_CPU_LITTLE_ENDIAN),y)
> diff --git a/arch/powerpc/crypto/md5-asm.S b/arch/powerpc/crypto/md5-asm.S
> deleted file mode 100644
> index fa6bc440cf4ac..0000000000000
> --- a/arch/powerpc/crypto/md5-asm.S
> +++ /dev/null
> @@ -1,235 +0,0 @@
> -/* SPDX-License-Identifier: GPL-2.0-or-later */
> -/*
> - * Fast MD5 implementation for PPC
> - *
> - * Copyright (c) 2015 Markus Stockhausen <stockhausen@collogia.de>
> - */
> -#include <asm/ppc_asm.h>
> -#include <asm/asm-offsets.h>
> -#include <asm/asm-compat.h>
> -
> -#define rHP r3
> -#define rWP r4
> -
> -#define rH0 r0
> -#define rH1 r6
> -#define rH2 r7
> -#define rH3 r5
> -
> -#define rW00 r8
> -#define rW01 r9
> -#define rW02 r10
> -#define rW03 r11
> -#define rW04 r12
> -#define rW05 r14
> -#define rW06 r15
> -#define rW07 r16
> -#define rW08 r17
> -#define rW09 r18
> -#define rW10 r19
> -#define rW11 r20
> -#define rW12 r21
> -#define rW13 r22
> -#define rW14 r23
> -#define rW15 r24
> -
> -#define rT0 r25
> -#define rT1 r26
> -
> -#define INITIALIZE \
> - PPC_STLU r1,-INT_FRAME_SIZE(r1); \
> - SAVE_GPRS(14, 26, r1) /* push registers onto stack */
> -
> -#define FINALIZE \
> - REST_GPRS(14, 26, r1); /* pop registers from stack */ \
> - addi r1,r1,INT_FRAME_SIZE
> -
> -#ifdef __BIG_ENDIAN__
> -#define LOAD_DATA(reg, off) \
> - lwbrx reg,0,rWP; /* load data */
> -#define INC_PTR \
> - addi rWP,rWP,4; /* increment per word */
> -#define NEXT_BLOCK /* nothing to do */
> -#else
> -#define LOAD_DATA(reg, off) \
> - lwz reg,off(rWP); /* load data */
> -#define INC_PTR /* nothing to do */
> -#define NEXT_BLOCK \
> - addi rWP,rWP,64; /* increment per block */
> -#endif
> -
> -#define R_00_15(a, b, c, d, w0, w1, p, q, off, k0h, k0l, k1h, k1l) \
> - LOAD_DATA(w0, off) /* W */ \
> - and rT0,b,c; /* 1: f = b and c */ \
> - INC_PTR /* ptr++ */ \
> - andc rT1,d,b; /* 1: f' = ~b and d */ \
> - LOAD_DATA(w1, off+4) /* W */ \
> - or rT0,rT0,rT1; /* 1: f = f or f' */ \
> - addi w0,w0,k0l; /* 1: wk = w + k */ \
> - add a,a,rT0; /* 1: a = a + f */ \
> - addis w0,w0,k0h; /* 1: wk = w + k' */ \
> - addis w1,w1,k1h; /* 2: wk = w + k */ \
> - add a,a,w0; /* 1: a = a + wk */ \
> - addi w1,w1,k1l; /* 2: wk = w + k' */ \
> - rotrwi a,a,p; /* 1: a = a rotl x */ \
> - add d,d,w1; /* 2: a = a + wk */ \
> - add a,a,b; /* 1: a = a + b */ \
> - and rT0,a,b; /* 2: f = b and c */ \
> - andc rT1,c,a; /* 2: f' = ~b and d */ \
> - or rT0,rT0,rT1; /* 2: f = f or f' */ \
> - add d,d,rT0; /* 2: a = a + f */ \
> - INC_PTR /* ptr++ */ \
> - rotrwi d,d,q; /* 2: a = a rotl x */ \
> - add d,d,a; /* 2: a = a + b */
> -
> -#define R_16_31(a, b, c, d, w0, w1, p, q, k0h, k0l, k1h, k1l) \
> - andc rT0,c,d; /* 1: f = c and ~d */ \
> - and rT1,b,d; /* 1: f' = b and d */ \
> - addi w0,w0,k0l; /* 1: wk = w + k */ \
> - or rT0,rT0,rT1; /* 1: f = f or f' */ \
> - addis w0,w0,k0h; /* 1: wk = w + k' */ \
> - add a,a,rT0; /* 1: a = a + f */ \
> - addi w1,w1,k1l; /* 2: wk = w + k */ \
> - add a,a,w0; /* 1: a = a + wk */ \
> - addis w1,w1,k1h; /* 2: wk = w + k' */ \
> - andc rT0,b,c; /* 2: f = c and ~d */ \
> - rotrwi a,a,p; /* 1: a = a rotl x */ \
> - add a,a,b; /* 1: a = a + b */ \
> - add d,d,w1; /* 2: a = a + wk */ \
> - and rT1,a,c; /* 2: f' = b and d */ \
> - or rT0,rT0,rT1; /* 2: f = f or f' */ \
> - add d,d,rT0; /* 2: a = a + f */ \
> - rotrwi d,d,q; /* 2: a = a rotl x */ \
> - add d,d,a; /* 2: a = a +b */
> -
> -#define R_32_47(a, b, c, d, w0, w1, p, q, k0h, k0l, k1h, k1l) \
> - xor rT0,b,c; /* 1: f' = b xor c */ \
> - addi w0,w0,k0l; /* 1: wk = w + k */ \
> - xor rT1,rT0,d; /* 1: f = f xor f' */ \
> - addis w0,w0,k0h; /* 1: wk = w + k' */ \
> - add a,a,rT1; /* 1: a = a + f */ \
> - addi w1,w1,k1l; /* 2: wk = w + k */ \
> - add a,a,w0; /* 1: a = a + wk */ \
> - addis w1,w1,k1h; /* 2: wk = w + k' */ \
> - rotrwi a,a,p; /* 1: a = a rotl x */ \
> - add d,d,w1; /* 2: a = a + wk */ \
> - add a,a,b; /* 1: a = a + b */ \
> - xor rT1,rT0,a; /* 2: f = b xor f' */ \
> - add d,d,rT1; /* 2: a = a + f */ \
> - rotrwi d,d,q; /* 2: a = a rotl x */ \
> - add d,d,a; /* 2: a = a + b */
> -
> -#define R_48_63(a, b, c, d, w0, w1, p, q, k0h, k0l, k1h, k1l) \
> - addi w0,w0,k0l; /* 1: w = w + k */ \
> - orc rT0,b,d; /* 1: f = b or ~d */ \
> - addis w0,w0,k0h; /* 1: w = w + k' */ \
> - xor rT0,rT0,c; /* 1: f = f xor c */ \
> - add a,a,w0; /* 1: a = a + wk */ \
> - addi w1,w1,k1l; /* 2: w = w + k */ \
> - add a,a,rT0; /* 1: a = a + f */ \
> - addis w1,w1,k1h; /* 2: w = w + k' */ \
> - rotrwi a,a,p; /* 1: a = a rotl x */ \
> - add a,a,b; /* 1: a = a + b */ \
> - orc rT0,a,c; /* 2: f = b or ~d */ \
> - add d,d,w1; /* 2: a = a + wk */ \
> - xor rT0,rT0,b; /* 2: f = f xor c */ \
> - add d,d,rT0; /* 2: a = a + f */ \
> - rotrwi d,d,q; /* 2: a = a rotl x */ \
> - add d,d,a; /* 2: a = a + b */
> -
> -_GLOBAL(ppc_md5_transform)
> - INITIALIZE
> -
> - mtctr r5
> - lwz rH0,0(rHP)
> - lwz rH1,4(rHP)
> - lwz rH2,8(rHP)
> - lwz rH3,12(rHP)
> -
> -ppc_md5_main:
> - R_00_15(rH0, rH1, rH2, rH3, rW00, rW01, 25, 20, 0,
> - 0xd76b, -23432, 0xe8c8, -18602)
> - R_00_15(rH2, rH3, rH0, rH1, rW02, rW03, 15, 10, 8,
> - 0x2420, 0x70db, 0xc1be, -12562)
> - R_00_15(rH0, rH1, rH2, rH3, rW04, rW05, 25, 20, 16,
> - 0xf57c, 0x0faf, 0x4788, -14806)
> - R_00_15(rH2, rH3, rH0, rH1, rW06, rW07, 15, 10, 24,
> - 0xa830, 0x4613, 0xfd47, -27391)
> - R_00_15(rH0, rH1, rH2, rH3, rW08, rW09, 25, 20, 32,
> - 0x6981, -26408, 0x8b45, -2129)
> - R_00_15(rH2, rH3, rH0, rH1, rW10, rW11, 15, 10, 40,
> - 0xffff, 0x5bb1, 0x895d, -10306)
> - R_00_15(rH0, rH1, rH2, rH3, rW12, rW13, 25, 20, 48,
> - 0x6b90, 0x1122, 0xfd98, 0x7193)
> - R_00_15(rH2, rH3, rH0, rH1, rW14, rW15, 15, 10, 56,
> - 0xa679, 0x438e, 0x49b4, 0x0821)
> -
> - R_16_31(rH0, rH1, rH2, rH3, rW01, rW06, 27, 23,
> - 0x0d56, 0x6e0c, 0x1810, 0x6d2d)
> - R_16_31(rH2, rH3, rH0, rH1, rW11, rW00, 18, 12,
> - 0x9d02, -32109, 0x124c, 0x2332)
> - R_16_31(rH0, rH1, rH2, rH3, rW05, rW10, 27, 23,
> - 0x8ea7, 0x4a33, 0x0245, -18270)
> - R_16_31(rH2, rH3, rH0, rH1, rW15, rW04, 18, 12,
> - 0x8eee, -8608, 0xf258, -5095)
> - R_16_31(rH0, rH1, rH2, rH3, rW09, rW14, 27, 23,
> - 0x969d, -10697, 0x1cbe, -15288)
> - R_16_31(rH2, rH3, rH0, rH1, rW03, rW08, 18, 12,
> - 0x3317, 0x3e99, 0xdbd9, 0x7c15)
> - R_16_31(rH0, rH1, rH2, rH3, rW13, rW02, 27, 23,
> - 0xac4b, 0x7772, 0xd8cf, 0x331d)
> - R_16_31(rH2, rH3, rH0, rH1, rW07, rW12, 18, 12,
> - 0x6a28, 0x6dd8, 0x219a, 0x3b68)
> -
> - R_32_47(rH0, rH1, rH2, rH3, rW05, rW08, 28, 21,
> - 0x29cb, 0x28e5, 0x4218, -7788)
> - R_32_47(rH2, rH3, rH0, rH1, rW11, rW14, 16, 9,
> - 0x473f, 0x06d1, 0x3aae, 0x3036)
> - R_32_47(rH0, rH1, rH2, rH3, rW01, rW04, 28, 21,
> - 0xaea1, -15134, 0x640b, -11295)
> - R_32_47(rH2, rH3, rH0, rH1, rW07, rW10, 16, 9,
> - 0x8f4c, 0x4887, 0xbc7c, -22499)
> - R_32_47(rH0, rH1, rH2, rH3, rW13, rW00, 28, 21,
> - 0x7eb8, -27199, 0x00ea, 0x6050)
> - R_32_47(rH2, rH3, rH0, rH1, rW03, rW06, 16, 9,
> - 0xe01a, 0x22fe, 0x4447, 0x69c5)
> - R_32_47(rH0, rH1, rH2, rH3, rW09, rW12, 28, 21,
> - 0xb7f3, 0x0253, 0x59b1, 0x4d5b)
> - R_32_47(rH2, rH3, rH0, rH1, rW15, rW02, 16, 9,
> - 0x4701, -27017, 0xc7bd, -19859)
> -
> - R_48_63(rH0, rH1, rH2, rH3, rW00, rW07, 26, 22,
> - 0x0988, -1462, 0x4c70, -19401)
> - R_48_63(rH2, rH3, rH0, rH1, rW14, rW05, 17, 11,
> - 0xadaf, -5221, 0xfc99, 0x66f7)
> - R_48_63(rH0, rH1, rH2, rH3, rW12, rW03, 26, 22,
> - 0x7e80, -16418, 0xba1e, -25587)
> - R_48_63(rH2, rH3, rH0, rH1, rW10, rW01, 17, 11,
> - 0x4130, 0x380d, 0xe0c5, 0x738d)
> - lwz rW00,0(rHP)
> - R_48_63(rH0, rH1, rH2, rH3, rW08, rW15, 26, 22,
> - 0xe837, -30770, 0xde8a, 0x69e8)
> - lwz rW14,4(rHP)
> - R_48_63(rH2, rH3, rH0, rH1, rW06, rW13, 17, 11,
> - 0x9e79, 0x260f, 0x256d, -27941)
> - lwz rW12,8(rHP)
> - R_48_63(rH0, rH1, rH2, rH3, rW04, rW11, 26, 22,
> - 0xab75, -20775, 0x4f9e, -28397)
> - lwz rW10,12(rHP)
> - R_48_63(rH2, rH3, rH0, rH1, rW02, rW09, 17, 11,
> - 0x662b, 0x7c56, 0x11b2, 0x0358)
> -
> - add rH0,rH0,rW00
> - stw rH0,0(rHP)
> - add rH1,rH1,rW14
> - stw rH1,4(rHP)
> - add rH2,rH2,rW12
> - stw rH2,8(rHP)
> - add rH3,rH3,rW10
> - stw rH3,12(rHP)
> - NEXT_BLOCK
> -
> - bdnz ppc_md5_main
> -
> - FINALIZE
> - blr
> diff --git a/arch/powerpc/crypto/md5-glue.c b/arch/powerpc/crypto/md5-glue.c
> deleted file mode 100644
> index 204440a90cd84..0000000000000
> --- a/arch/powerpc/crypto/md5-glue.c
> +++ /dev/null
> @@ -1,99 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-or-later
> -/*
> - * Glue code for MD5 implementation for PPC assembler
> - *
> - * Based on generic implementation.
> - *
> - * Copyright (c) 2015 Markus Stockhausen <stockhausen@collogia.de>
> - */
> -
> -#include <crypto/internal/hash.h>
> -#include <crypto/md5.h>
> -#include <linux/kernel.h>
> -#include <linux/module.h>
> -#include <linux/string.h>
> -
> -extern void ppc_md5_transform(u32 *state, const u8 *src, u32 blocks);
> -
> -static int ppc_md5_init(struct shash_desc *desc)
> -{
> - struct md5_state *sctx = shash_desc_ctx(desc);
> -
> - sctx->hash[0] = MD5_H0;
> - sctx->hash[1] = MD5_H1;
> - sctx->hash[2] = MD5_H2;
> - sctx->hash[3] = MD5_H3;
> - sctx->byte_count = 0;
> -
> - return 0;
> -}
> -
> -static int ppc_md5_update(struct shash_desc *desc, const u8 *data,
> - unsigned int len)
> -{
> - struct md5_state *sctx = shash_desc_ctx(desc);
> -
> - sctx->byte_count += round_down(len, MD5_HMAC_BLOCK_SIZE);
> - ppc_md5_transform(sctx->hash, data, len >> 6);
> - return len - round_down(len, MD5_HMAC_BLOCK_SIZE);
> -}
> -
> -static int ppc_md5_finup(struct shash_desc *desc, const u8 *src,
> - unsigned int offset, u8 *out)
> -{
> - struct md5_state *sctx = shash_desc_ctx(desc);
> - __le64 block[MD5_BLOCK_WORDS] = {};
> - u8 *p = memcpy(block, src, offset);
> - __le32 *dst = (__le32 *)out;
> - __le64 *pbits;
> -
> - 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);
> - ppc_md5_transform(sctx->hash, src, (pbits - block + 1) / 8);
> - memzero_explicit(block, sizeof(block));
> -
> - dst[0] = cpu_to_le32(sctx->hash[0]);
> - dst[1] = cpu_to_le32(sctx->hash[1]);
> - dst[2] = cpu_to_le32(sctx->hash[2]);
> - dst[3] = cpu_to_le32(sctx->hash[3]);
> - return 0;
> -}
> -
> -static struct shash_alg alg = {
> - .digestsize = MD5_DIGEST_SIZE,
> - .init = ppc_md5_init,
> - .update = ppc_md5_update,
> - .finup = ppc_md5_finup,
> - .descsize = MD5_STATE_SIZE,
> - .base = {
> - .cra_name = "md5",
> - .cra_driver_name= "md5-ppc",
> - .cra_priority = 200,
> - .cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY,
> - .cra_blocksize = MD5_HMAC_BLOCK_SIZE,
> - .cra_module = THIS_MODULE,
> - }
> -};
> -
> -static int __init ppc_md5_mod_init(void)
> -{
> - return crypto_register_shash(&alg);
> -}
> -
> -static void __exit ppc_md5_mod_fini(void)
> -{
> - crypto_unregister_shash(&alg);
> -}
> -
> -module_init(ppc_md5_mod_init);
> -module_exit(ppc_md5_mod_fini);
> -
> -MODULE_LICENSE("GPL");
> -MODULE_DESCRIPTION("MD5 Secure Hash Algorithm, PPC assembler");
> -
> -MODULE_ALIAS_CRYPTO("md5");
> -MODULE_ALIAS_CRYPTO("md5-ppc");
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 3/7] crypto: powerpc/md5 - Remove PowerPC optimized MD5 code
2025-08-04 17:42 ` Christophe Leroy
@ 2025-08-04 18:09 ` Eric Biggers
2025-08-04 19:02 ` Christophe Leroy
0 siblings, 1 reply; 26+ messages in thread
From: Eric Biggers @ 2025-08-04 18:09 UTC (permalink / raw)
To: Christophe Leroy
Cc: linux-crypto, linux-kernel, Ard Biesheuvel, Jason A . Donenfeld,
linux-mips, linuxppc-dev, sparclinux
On Mon, Aug 04, 2025 at 07:42:15PM +0200, Christophe Leroy wrote:
>
>
> Le 03/08/2025 à 22:44, Eric Biggers a écrit :
> > MD5 is insecure, is no longer commonly used, and has never been
> > optimized for the most common architectures in the kernel. Only mips,
> > powerpc, and sparc have optimized MD5 code in the kernel. Of these,
> > only the powerpc one is actually testable in QEMU. The mips one works
> > only on Cavium Octeon SoCs.
> >
> > Taken together, it's clear that it's time to retire these additional MD5
> > implementations, and focus maintenance on the MD5 generic C code.
>
> Sorry, for me it is not that clear. Even if MD5 is depracated we still have
> several applications that use MD5 for various reasons on our boards.
>
> I ran the test on kernel v6.16 with following file:
>
> # ls -l avion.au
> -rw------- 1 root root 12130159 Jan 1 1970 avion.au
>
> With CONFIG_CRYPTO_MD5_PPC:
>
> # time md5sum avion.au
> 6513851d6109d42477b20cd56bf57f28 avion.au
> real 0m 1.02s
> user 0m 0.01s
> sys 0m 1.01s
>
> Without CONFIG_CRYPTO_MD5_PPC:
>
> # time md5sum avion.au
> 6513851d6109d42477b20cd56bf57f28 avion.au
> real 0m 1.35s
> user 0m 0.01s
> sys 0m 1.34s
>
> I think the difference is big enough to consider keeping optimised MD5 code.
But md5sum doesn't use the kernel's MD5 code. So it's implausible that
it has any effect on md5sum. The difference you saw must be due to an
unrelated reason like I/O caching, CPU frequency, etc. Try running your
test multiple times to eliminate other sources of variation.
- Eric
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 3/7] crypto: powerpc/md5 - Remove PowerPC optimized MD5 code
2025-08-04 18:09 ` Eric Biggers
@ 2025-08-04 19:02 ` Christophe Leroy
2025-08-04 22:59 ` Eric Biggers
0 siblings, 1 reply; 26+ messages in thread
From: Christophe Leroy @ 2025-08-04 19:02 UTC (permalink / raw)
To: Eric Biggers
Cc: linux-crypto, linux-kernel, Ard Biesheuvel, Jason A . Donenfeld,
linux-mips, linuxppc-dev, sparclinux
Le 04/08/2025 à 20:09, Eric Biggers a écrit :
> On Mon, Aug 04, 2025 at 07:42:15PM +0200, Christophe Leroy wrote:
>>
>>
>> Le 03/08/2025 à 22:44, Eric Biggers a écrit :
>>> MD5 is insecure, is no longer commonly used, and has never been
>>> optimized for the most common architectures in the kernel. Only mips,
>>> powerpc, and sparc have optimized MD5 code in the kernel. Of these,
>>> only the powerpc one is actually testable in QEMU. The mips one works
>>> only on Cavium Octeon SoCs.
>>>
>>> Taken together, it's clear that it's time to retire these additional MD5
>>> implementations, and focus maintenance on the MD5 generic C code.
>>
>> Sorry, for me it is not that clear. Even if MD5 is depracated we still have
>> several applications that use MD5 for various reasons on our boards.
>>
>> I ran the test on kernel v6.16 with following file:
>>
>> # ls -l avion.au
>> -rw------- 1 root root 12130159 Jan 1 1970 avion.au
>>
>> With CONFIG_CRYPTO_MD5_PPC:
>>
>> # time md5sum avion.au
>> 6513851d6109d42477b20cd56bf57f28 avion.au
>> real 0m 1.02s
>> user 0m 0.01s
>> sys 0m 1.01s
>>
>> Without CONFIG_CRYPTO_MD5_PPC:
>>
>> # time md5sum avion.au
>> 6513851d6109d42477b20cd56bf57f28 avion.au
>> real 0m 1.35s
>> user 0m 0.01s
>> sys 0m 1.34s
>>
>> I think the difference is big enough to consider keeping optimised MD5 code.
>
> But md5sum doesn't use the kernel's MD5 code. So it's implausible that
> it has any effect on md5sum. The difference you saw must be due to an
> unrelated reason like I/O caching, CPU frequency, etc. Try running your
> test multiple times to eliminate other sources of variation.
md5sum uses the kernel's MD5 code:
# ldd `which md5sum`
linux-vdso32.so.1 (0x77b90000)
libkcapi.so.1 => /usr/lib/libkcapi.so.1 (0x6ffa0000) <==
libcrypt.so.1 => /lib/libcrypt.so.1 (0x6ff50000)
libc.so.6 => /lib/libc.so.6 (0x6fd10000)
/lib/ld.so.1 => //lib/ld.so.1 (0x77ba0000)
Previous test was on an mpc8xx.
I now did the test on mpc832x and the difference is even bigger:
With CONFIG_CRYPTO_MD5_PPC:
# time md5sum avion.au
6513851d6109d42477b20cd56bf57f28 avion.au
real 0m 0.41s
user 0m 0.00s
sys 0m 0.34s
Without CONFIG_CRYPTO_MD5_PPC:
# time md5sum avion.au
6513851d6109d42477b20cd56bf57f28 avion.au
real 0m 0.58s
user 0m 0.00s
sys 0m 0.47s
Christophe
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 3/7] crypto: powerpc/md5 - Remove PowerPC optimized MD5 code
2025-08-04 19:02 ` Christophe Leroy
@ 2025-08-04 22:59 ` Eric Biggers
2025-08-04 23:09 ` Eric Biggers
` (2 more replies)
0 siblings, 3 replies; 26+ messages in thread
From: Eric Biggers @ 2025-08-04 22:59 UTC (permalink / raw)
To: Christophe Leroy
Cc: linux-crypto, linux-kernel, Ard Biesheuvel, Jason A . Donenfeld,
linux-mips, linuxppc-dev, sparclinux
On Mon, Aug 04, 2025 at 09:02:27PM +0200, Christophe Leroy wrote:
>
>
> Le 04/08/2025 à 20:09, Eric Biggers a écrit :
> > On Mon, Aug 04, 2025 at 07:42:15PM +0200, Christophe Leroy wrote:
> > >
> > >
> > > Le 03/08/2025 à 22:44, Eric Biggers a écrit :
> > > > MD5 is insecure, is no longer commonly used, and has never been
> > > > optimized for the most common architectures in the kernel. Only mips,
> > > > powerpc, and sparc have optimized MD5 code in the kernel. Of these,
> > > > only the powerpc one is actually testable in QEMU. The mips one works
> > > > only on Cavium Octeon SoCs.
> > > >
> > > > Taken together, it's clear that it's time to retire these additional MD5
> > > > implementations, and focus maintenance on the MD5 generic C code.
> > >
> > > Sorry, for me it is not that clear. Even if MD5 is depracated we still have
> > > several applications that use MD5 for various reasons on our boards.
> > >
> > > I ran the test on kernel v6.16 with following file:
> > >
> > > # ls -l avion.au
> > > -rw------- 1 root root 12130159 Jan 1 1970 avion.au
> > >
> > > With CONFIG_CRYPTO_MD5_PPC:
> > >
> > > # time md5sum avion.au
> > > 6513851d6109d42477b20cd56bf57f28 avion.au
> > > real 0m 1.02s
> > > user 0m 0.01s
> > > sys 0m 1.01s
> > >
> > > Without CONFIG_CRYPTO_MD5_PPC:
> > >
> > > # time md5sum avion.au
> > > 6513851d6109d42477b20cd56bf57f28 avion.au
> > > real 0m 1.35s
> > > user 0m 0.01s
> > > sys 0m 1.34s
> > >
> > > I think the difference is big enough to consider keeping optimised MD5 code.
> >
> > But md5sum doesn't use the kernel's MD5 code. So it's implausible that
> > it has any effect on md5sum. The difference you saw must be due to an
> > unrelated reason like I/O caching, CPU frequency, etc. Try running your
> > test multiple times to eliminate other sources of variation.
>
> md5sum uses the kernel's MD5 code:
What? That's crazy. Userspace MD5 code would be faster and more
reliable. No need to make syscalls, transfer data to and from the
kernel, have an external dependency, etc. Is this the coreutils md5sum?
We need to get this reported and fixed.
- Eric
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 3/7] crypto: powerpc/md5 - Remove PowerPC optimized MD5 code
2025-08-04 22:59 ` Eric Biggers
@ 2025-08-04 23:09 ` Eric Biggers
2025-08-05 6:21 ` Christophe Leroy
2025-08-05 4:49 ` Crypto use cases (was: Remove PowerPC optimized MD5 code) Simon Richter
2025-08-05 6:27 ` [PATCH 3/7] crypto: powerpc/md5 - Remove PowerPC optimized MD5 code Christophe Leroy
2 siblings, 1 reply; 26+ messages in thread
From: Eric Biggers @ 2025-08-04 23:09 UTC (permalink / raw)
To: Christophe Leroy
Cc: linux-crypto, linux-kernel, Ard Biesheuvel, Jason A . Donenfeld,
linux-mips, linuxppc-dev, sparclinux
On Mon, Aug 04, 2025 at 10:59:01PM +0000, Eric Biggers wrote:
> On Mon, Aug 04, 2025 at 09:02:27PM +0200, Christophe Leroy wrote:
> >
> >
> > Le 04/08/2025 à 20:09, Eric Biggers a écrit :
> > > On Mon, Aug 04, 2025 at 07:42:15PM +0200, Christophe Leroy wrote:
> > > >
> > > >
> > > > Le 03/08/2025 à 22:44, Eric Biggers a écrit :
> > > > > MD5 is insecure, is no longer commonly used, and has never been
> > > > > optimized for the most common architectures in the kernel. Only mips,
> > > > > powerpc, and sparc have optimized MD5 code in the kernel. Of these,
> > > > > only the powerpc one is actually testable in QEMU. The mips one works
> > > > > only on Cavium Octeon SoCs.
> > > > >
> > > > > Taken together, it's clear that it's time to retire these additional MD5
> > > > > implementations, and focus maintenance on the MD5 generic C code.
> > > >
> > > > Sorry, for me it is not that clear. Even if MD5 is depracated we still have
> > > > several applications that use MD5 for various reasons on our boards.
> > > >
> > > > I ran the test on kernel v6.16 with following file:
> > > >
> > > > # ls -l avion.au
> > > > -rw------- 1 root root 12130159 Jan 1 1970 avion.au
> > > >
> > > > With CONFIG_CRYPTO_MD5_PPC:
> > > >
> > > > # time md5sum avion.au
> > > > 6513851d6109d42477b20cd56bf57f28 avion.au
> > > > real 0m 1.02s
> > > > user 0m 0.01s
> > > > sys 0m 1.01s
> > > >
> > > > Without CONFIG_CRYPTO_MD5_PPC:
> > > >
> > > > # time md5sum avion.au
> > > > 6513851d6109d42477b20cd56bf57f28 avion.au
> > > > real 0m 1.35s
> > > > user 0m 0.01s
> > > > sys 0m 1.34s
> > > >
> > > > I think the difference is big enough to consider keeping optimised MD5 code.
> > >
> > > But md5sum doesn't use the kernel's MD5 code. So it's implausible that
> > > it has any effect on md5sum. The difference you saw must be due to an
> > > unrelated reason like I/O caching, CPU frequency, etc. Try running your
> > > test multiple times to eliminate other sources of variation.
> >
> > md5sum uses the kernel's MD5 code:
> >
> > libkcapi.so.1 => /usr/lib/libkcapi.so.1 (0x6ffa0000) <==
Oh, I think you used the obscure implementation of md5sum from
libkcapi-tools, instead of the normal md5sum. Why? Did you check how
the normal md5sum performs too? Just doing the calculation in userspace
is much more efficient.
- Eric
^ permalink raw reply [flat|nested] 26+ messages in thread
* Crypto use cases (was: Remove PowerPC optimized MD5 code)
2025-08-04 22:59 ` Eric Biggers
2025-08-04 23:09 ` Eric Biggers
@ 2025-08-05 4:49 ` Simon Richter
2025-08-05 4:58 ` Eric Biggers
2025-08-05 6:27 ` [PATCH 3/7] crypto: powerpc/md5 - Remove PowerPC optimized MD5 code Christophe Leroy
2 siblings, 1 reply; 26+ messages in thread
From: Simon Richter @ 2025-08-05 4:49 UTC (permalink / raw)
To: Eric Biggers, Christophe Leroy
Cc: linux-crypto, linux-kernel, Ard Biesheuvel, Jason A . Donenfeld,
linux-mips, linuxppc-dev, sparclinux
Hi,
On 8/5/25 07:59, Eric Biggers wrote:
>> md5sum uses the kernel's MD5 code:
> What? That's crazy. Userspace MD5 code would be faster and more
> reliable. No need to make syscalls, transfer data to and from the
> kernel, have an external dependency, etc. Is this the coreutils md5sum?
> We need to get this reported and fixed.
The userspace API allows zero-copy transfers from userspace, and AFAIK
also directly operating on files without ever transferring the data to
userspace (so we save one copy).
Userspace requests are also where the asynchronous hardware offload
units get to chomp on large blocks of data while the CPU is doing
something else:
$ time dd if=test.bin of=/dev/zero bs=1G # warm up caches
real 0m1.541s
user 0m0.000s
sys 0m0.732s
$ time gzip -9 <test.bin >test.bin.gz # compress with the CPU
real 2m57.789s
user 2m55.986s
sys 0m1.508s
$ time ./gzfht_test test.bin # compress with NEST unit
real 0m3.207s
user 0m0.584s
sys 0m2.487s
$ time gzip -d <test.bin.nx.gz >test.bin.nx # decompress with CPU
real 1m0.103s
user 0m57.990s
sys 0m1.878s
$ time ./gunz_test test.bin.gz # decompress with NEST unit
real 0m2.722s
user 0m0.200s
sys 0m1.872s
That's why I'm objecting to measuring the general usefulness of hardware
crypto units by the standards of fscrypt, which has an artificial
limitation of never submitting blocks larger than 4kB: there are other
use cases that don't have that limitation, and where the overhead is
negligible because it is incurred only once for a few gigabytes of data.
That's why I suggested changing from a priority field to "speed" and
"overhead" fields, and calculate priority for each application as
(size/speed+overhead) -- smallest number wins, size is what the
application expects to use as the typical request size (which for
fscrypt and IPsec is on the small side, so it would always select the
CPU unless there was a low-overhead offload engine available)
This probably needs some adjustment to allow selecting a low-power
implementation (e.g. on mobile, I'd want to use offloading for fscrypt
even if it is slower), and model request batching which reduces the
overhead in a busy system, but it should be a good start.
Simon
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: Crypto use cases (was: Remove PowerPC optimized MD5 code)
2025-08-05 4:49 ` Crypto use cases (was: Remove PowerPC optimized MD5 code) Simon Richter
@ 2025-08-05 4:58 ` Eric Biggers
2025-08-05 7:17 ` Crypto use cases Simon Richter
0 siblings, 1 reply; 26+ messages in thread
From: Eric Biggers @ 2025-08-05 4:58 UTC (permalink / raw)
To: Simon Richter
Cc: Christophe Leroy, linux-crypto, linux-kernel, Ard Biesheuvel,
Jason A . Donenfeld, linux-mips, linuxppc-dev, sparclinux
On Tue, Aug 05, 2025 at 01:49:31PM +0900, Simon Richter wrote:
> Hi,
>
> On 8/5/25 07:59, Eric Biggers wrote:
>
> > > md5sum uses the kernel's MD5 code:
>
> > What? That's crazy. Userspace MD5 code would be faster and more
> > reliable. No need to make syscalls, transfer data to and from the
> > kernel, have an external dependency, etc. Is this the coreutils md5sum?
> > We need to get this reported and fixed.
>
> The userspace API allows zero-copy transfers from userspace, and AFAIK also
> directly operating on files without ever transferring the data to userspace
> (so we save one copy).
>
> Userspace requests are also where the asynchronous hardware offload units
> get to chomp on large blocks of data while the CPU is doing something else:
>
> $ time dd if=test.bin of=/dev/zero bs=1G # warm up caches
> real 0m1.541s
> user 0m0.000s
> sys 0m0.732s
>
> $ time gzip -9 <test.bin >test.bin.gz # compress with the CPU
> real 2m57.789s
> user 2m55.986s
> sys 0m1.508s
>
> $ time ./gzfht_test test.bin # compress with NEST unit
> real 0m3.207s
> user 0m0.584s
> sys 0m2.487s
>
> $ time gzip -d <test.bin.nx.gz >test.bin.nx # decompress with CPU
> real 1m0.103s
> user 0m57.990s
> sys 0m1.878s
>
> $ time ./gunz_test test.bin.gz # decompress with NEST unit
> real 0m2.722s
> user 0m0.200s
> sys 0m1.872s
>
> That's why I'm objecting to measuring the general usefulness of hardware
> crypto units by the standards of fscrypt, which has an artificial limitation
> of never submitting blocks larger than 4kB: there are other use cases that
> don't have that limitation, and where the overhead is negligible because it
> is incurred only once for a few gigabytes of data.
>
> That's why I suggested changing from a priority field to "speed" and
> "overhead" fields, and calculate priority for each application as
> (size/speed+overhead) -- smallest number wins, size is what the application
> expects to use as the typical request size (which for fscrypt and IPsec is
> on the small side, so it would always select the CPU unless there was a
> low-overhead offload engine available)
>
> This probably needs some adjustment to allow selecting a low-power
> implementation (e.g. on mobile, I'd want to use offloading for fscrypt even
> if it is slower), and model request batching which reduces the overhead in a
> busy system, but it should be a good start.
What does this have to do with this thread, which is about the PowerPC
optimized MD5 code?
- Eric
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 3/7] crypto: powerpc/md5 - Remove PowerPC optimized MD5 code
2025-08-04 23:09 ` Eric Biggers
@ 2025-08-05 6:21 ` Christophe Leroy
0 siblings, 0 replies; 26+ messages in thread
From: Christophe Leroy @ 2025-08-05 6:21 UTC (permalink / raw)
To: Eric Biggers
Cc: linux-crypto, linux-kernel, Ard Biesheuvel, Jason A . Donenfeld,
linux-mips, linuxppc-dev, sparclinux
Le 05/08/2025 à 01:09, Eric Biggers a écrit :
> On Mon, Aug 04, 2025 at 10:59:01PM +0000, Eric Biggers wrote:
>> On Mon, Aug 04, 2025 at 09:02:27PM +0200, Christophe Leroy wrote:
>>>
>>>
>>> Le 04/08/2025 à 20:09, Eric Biggers a écrit :
>>>> On Mon, Aug 04, 2025 at 07:42:15PM +0200, Christophe Leroy wrote:
>>>>>
>>>>>
>>>>> Le 03/08/2025 à 22:44, Eric Biggers a écrit :
>>>>>> MD5 is insecure, is no longer commonly used, and has never been
>>>>>> optimized for the most common architectures in the kernel. Only mips,
>>>>>> powerpc, and sparc have optimized MD5 code in the kernel. Of these,
>>>>>> only the powerpc one is actually testable in QEMU. The mips one works
>>>>>> only on Cavium Octeon SoCs.
>>>>>>
>>>>>> Taken together, it's clear that it's time to retire these additional MD5
>>>>>> implementations, and focus maintenance on the MD5 generic C code.
>>>>>
>>>>> Sorry, for me it is not that clear. Even if MD5 is depracated we still have
>>>>> several applications that use MD5 for various reasons on our boards.
>>>>>
>>>>> I ran the test on kernel v6.16 with following file:
>>>>>
>>>>> # ls -l avion.au
>>>>> -rw------- 1 root root 12130159 Jan 1 1970 avion.au
>>>>>
>>>>> With CONFIG_CRYPTO_MD5_PPC:
>>>>>
>>>>> # time md5sum avion.au
>>>>> 6513851d6109d42477b20cd56bf57f28 avion.au
>>>>> real 0m 1.02s
>>>>> user 0m 0.01s
>>>>> sys 0m 1.01s
>>>>>
>>>>> Without CONFIG_CRYPTO_MD5_PPC:
>>>>>
>>>>> # time md5sum avion.au
>>>>> 6513851d6109d42477b20cd56bf57f28 avion.au
>>>>> real 0m 1.35s
>>>>> user 0m 0.01s
>>>>> sys 0m 1.34s
>>>>>
>>>>> I think the difference is big enough to consider keeping optimised MD5 code.
>>>>
>>>> But md5sum doesn't use the kernel's MD5 code. So it's implausible that
>>>> it has any effect on md5sum. The difference you saw must be due to an
>>>> unrelated reason like I/O caching, CPU frequency, etc. Try running your
>>>> test multiple times to eliminate other sources of variation.
>>>
>>> md5sum uses the kernel's MD5 code:
>>>
>>> libkcapi.so.1 => /usr/lib/libkcapi.so.1 (0x6ffa0000) <==
>
> Oh, I think you used the obscure implementation of md5sum from
> libkcapi-tools, instead of the normal md5sum. Why? Did you check how
> the normal md5sum performs too? Just doing the calculation in userspace
> is much more efficient.
Calculation in userspace is less efficient on my board:
# time md5sum avion.au
6513851d6109d42477b20cd56bf57f28 avion.au
real 0m 1.87s
user 0m 1.51s
sys 0m 0.35s
Christophe
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 3/7] crypto: powerpc/md5 - Remove PowerPC optimized MD5 code
2025-08-04 22:59 ` Eric Biggers
2025-08-04 23:09 ` Eric Biggers
2025-08-05 4:49 ` Crypto use cases (was: Remove PowerPC optimized MD5 code) Simon Richter
@ 2025-08-05 6:27 ` Christophe Leroy
2025-08-05 16:16 ` Eric Biggers
2 siblings, 1 reply; 26+ messages in thread
From: Christophe Leroy @ 2025-08-05 6:27 UTC (permalink / raw)
To: Eric Biggers
Cc: linux-crypto, linux-kernel, Ard Biesheuvel, Jason A . Donenfeld,
linux-mips, linuxppc-dev, sparclinux
Le 05/08/2025 à 00:59, Eric Biggers a écrit :
> On Mon, Aug 04, 2025 at 09:02:27PM +0200, Christophe Leroy wrote:
>>
>>
>> Le 04/08/2025 à 20:09, Eric Biggers a écrit :
>>> On Mon, Aug 04, 2025 at 07:42:15PM +0200, Christophe Leroy wrote:
>>>>
>>>>
>>>> Le 03/08/2025 à 22:44, Eric Biggers a écrit :
>>>>> MD5 is insecure, is no longer commonly used, and has never been
>>>>> optimized for the most common architectures in the kernel. Only mips,
>>>>> powerpc, and sparc have optimized MD5 code in the kernel. Of these,
>>>>> only the powerpc one is actually testable in QEMU. The mips one works
>>>>> only on Cavium Octeon SoCs.
>>>>>
>>>>> Taken together, it's clear that it's time to retire these additional MD5
>>>>> implementations, and focus maintenance on the MD5 generic C code.
>>>>
>>>> Sorry, for me it is not that clear. Even if MD5 is depracated we still have
>>>> several applications that use MD5 for various reasons on our boards.
>>>>
>>>> I ran the test on kernel v6.16 with following file:
>>>>
>>>> # ls -l avion.au
>>>> -rw------- 1 root root 12130159 Jan 1 1970 avion.au
>>>>
>>>> With CONFIG_CRYPTO_MD5_PPC:
>>>>
>>>> # time md5sum avion.au
>>>> 6513851d6109d42477b20cd56bf57f28 avion.au
>>>> real 0m 1.02s
>>>> user 0m 0.01s
>>>> sys 0m 1.01s
>>>>
>>>> Without CONFIG_CRYPTO_MD5_PPC:
>>>>
>>>> # time md5sum avion.au
>>>> 6513851d6109d42477b20cd56bf57f28 avion.au
>>>> real 0m 1.35s
>>>> user 0m 0.01s
>>>> sys 0m 1.34s
>>>>
>>>> I think the difference is big enough to consider keeping optimised MD5 code.
>>>
>>> But md5sum doesn't use the kernel's MD5 code. So it's implausible that
>>> it has any effect on md5sum. The difference you saw must be due to an
>>> unrelated reason like I/O caching, CPU frequency, etc. Try running your
>>> test multiple times to eliminate other sources of variation.
>>
>> md5sum uses the kernel's MD5 code:
>
> What? That's crazy. Userspace MD5 code would be faster and more
> reliable. No need to make syscalls, transfer data to and from the
> kernel, have an external dependency, etc. Is this the coreutils md5sum?
> We need to get this reported and fixed.
Content of files is already buffered inside the kernel. likcapi doesn't
tranfer data, it uses splice().
As far as I know, coreutil is not able to use the TALITOS Security
engine we have on the mpc885 and mpc8321 microcontroleurs. We primarily
use libkcapi for that.
In order to keep things consistant, we use the same userspace on boards
which don't have a security engine, ie the mpc866, we rely on the kernel
providing an optimised software implementation fallback.
Christophe
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: Crypto use cases
2025-08-05 4:58 ` Eric Biggers
@ 2025-08-05 7:17 ` Simon Richter
2025-08-05 17:15 ` Eric Biggers
0 siblings, 1 reply; 26+ messages in thread
From: Simon Richter @ 2025-08-05 7:17 UTC (permalink / raw)
To: Eric Biggers
Cc: Christophe Leroy, linux-crypto, linux-kernel, Ard Biesheuvel,
Jason A . Donenfeld, linux-mips, linuxppc-dev, sparclinux
Hi,
On 8/5/25 13:58, Eric Biggers wrote:
> What does this have to do with this thread, which is about the PowerPC
> optimized MD5 code?
Hence the new subject. It is still related to removal of code, but asks
about the bigger picture.
The code removal changes you've been pushing lately absolutely make
sense in the context of "the crypto subsystem is for internal use by the
kernel, and all known users will only ever submit small work items."
However, there is also the userspace API, and hardware accelerators also
register with the crypto subsystem, so it is *also* the way for
userspace to use specialized hardware.
If these are separate, then it makes sense to acknowledge that the
kernel will never use asynchronous transforms for anything, simplify the
internal API, and move all the hardware support to a separate registry
that is for userspace applications only.
However if we don't want separate registries, then it makes no sense for
the kernel to set policy for userspace here; it should offer all the
alternatives. The kernel can, and should, define policy for itself, and
I wholeheartedly agree that offloading small requests does not make
sense, unless we're on battery power.
I'm also not convinced that fscrypt cannot ever learn to submit a single
large request or a large batch of small requests if it is asked to
decrypt a large file, so in my opinion the common registry makes more sense.
Making sure that hardware support actually works and is tested is the
responsibility of the driver and port maintainers. We understand that
subsystem maintainers do not have all the hardware available, but the
same goes for all the other subsystems -- the DRM maintainers routinely
merge drivers for hardware they do not own, because the changes come
from people who *do* own the hardware, and have tested the changes.
The latter is a project management issue, mostly: if there is a lack of
working relationships with driver and port maintainers, then that needs
to be fixed, not assumed to be an unchangeable part of the environment
that technical decisions are made in.
Simon
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 3/7] crypto: powerpc/md5 - Remove PowerPC optimized MD5 code
2025-08-05 6:27 ` [PATCH 3/7] crypto: powerpc/md5 - Remove PowerPC optimized MD5 code Christophe Leroy
@ 2025-08-05 16:16 ` Eric Biggers
0 siblings, 0 replies; 26+ messages in thread
From: Eric Biggers @ 2025-08-05 16:16 UTC (permalink / raw)
To: Christophe Leroy
Cc: linux-crypto, linux-kernel, Ard Biesheuvel, Jason A . Donenfeld,
linux-mips, linuxppc-dev, sparclinux
On Tue, Aug 05, 2025 at 08:27:14AM +0200, Christophe Leroy wrote:
> > What? That's crazy. Userspace MD5 code would be faster and more
> > reliable. No need to make syscalls, transfer data to and from the
> > kernel, have an external dependency, etc. Is this the coreutils md5sum?
> > We need to get this reported and fixed.
>
> Content of files is already buffered inside the kernel. likcapi doesn't
> tranfer data, it uses splice().
>
> As far as I know, coreutil is not able to use the TALITOS Security engine we
> have on the mpc885 and mpc8321 microcontroleurs. We primarily use libkcapi
> for that.
>
> In order to keep things consistant, we use the same userspace on boards
> which don't have a security engine, ie the mpc866, we rely on the kernel
> providing an optimised software implementation fallback.
Even if the data is transferred in a zero-copy manner, the AF_ALG
version still has a lot of overhead from system calls. Running the
exact same PPC optimized code in userspace would of course be faster.
Now, it sounds like you don't have the PPC optimized MD5 code in
userspace, and that's why you're measuring the AF_ALG based md5sum to be
faster. But that's just the wrong design, and it does not give optimal
performance. The fact that the kernel allows access to software code
via AF_ALG is basically a bug.
For now we'll keep the PPC optimized MD5 around in the kernel to
accomodate userspace code that is depending on this bug, but for future
reference we don't add new software implementations purely for use by
userspace. (And BTW this is nothing new; this has already been the
policy for many years.) Please work to bring the optimized code you
need into userspace. For example contribute it to OpenSSL.
- Eric
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: Crypto use cases
2025-08-05 7:17 ` Crypto use cases Simon Richter
@ 2025-08-05 17:15 ` Eric Biggers
0 siblings, 0 replies; 26+ messages in thread
From: Eric Biggers @ 2025-08-05 17:15 UTC (permalink / raw)
To: Simon Richter
Cc: Christophe Leroy, linux-crypto, linux-kernel, Ard Biesheuvel,
Jason A . Donenfeld, linux-mips, linuxppc-dev, sparclinux
On Tue, Aug 05, 2025 at 04:17:49PM +0900, Simon Richter wrote:
> Hi,
>
> On 8/5/25 13:58, Eric Biggers wrote:
>
> > What does this have to do with this thread, which is about the PowerPC
> > optimized MD5 code?
>
> Hence the new subject. It is still related to removal of code, but asks
> about the bigger picture.
>
> The code removal changes you've been pushing lately absolutely make sense in
> the context of "the crypto subsystem is for internal use by the kernel, and
> all known users will only ever submit small work items."
>
> However, there is also the userspace API, and hardware accelerators also
> register with the crypto subsystem, so it is *also* the way for userspace to
> use specialized hardware.
>
> If these are separate, then it makes sense to acknowledge that the kernel
> will never use asynchronous transforms for anything, simplify the internal
> API, and move all the hardware support to a separate registry that is for
> userspace applications only.
I think you're grouping together different things that aren't actually
very related. For example this patch series proposed removing some
software code, not async drivers. The only async driver I removed
recently is one of the crc32c ones.
Doesn't lib/crypto/ largely accomplish what you're thinking of as
"separate registries"? As we migrate more in-kernel users to
lib/crypto/, the old-school crypto API becomes more focused just on
accomodating AF_ALG users. However, that is, and will continue to be, a
long process. In the mean time we still have many in-kernel users of
the old-school crypto API to decide what to do with.
> I'm also not convinced that fscrypt cannot ever learn to submit a single
> large request or a large batch of small requests if it is asked to decrypt a
> large file, so in my opinion the common registry makes more sense.
It's certainly never going to be the entire file or a single batch.
That's just not how filesystems work.
As for offloading entire I/O requests, fscrypt already supports that,
just for inline crypto engines instead of the old-school separate ones.
Inline encryption is fundamentally much more efficient. The same
efficiency can't be achieved with a separate engine, even with a large
batch. If people would like to continue to explore that approach
anyway, they're free to do so, but it's not a promising approach, at
least not on any of the platforms I examined. (And pointing to
irrelevant data, like for compression, is not helpful.)
> Making sure that hardware support actually works and is tested is the
> responsibility of the driver and port maintainers. We understand that
> subsystem maintainers do not have all the hardware available, but the same
> goes for all the other subsystems -- the DRM maintainers routinely merge
> drivers for hardware they do not own, because the changes come from people
> who *do* own the hardware, and have tested the changes.
>
> The latter is a project management issue, mostly: if there is a lack of
> working relationships with driver and port maintainers, then that needs to
> be fixed, not assumed to be an unchangeable part of the environment that
> technical decisions are made in.
This significantly understates the challenge that exists with a large
number of drivers, including orphaned drivers and architectures, as well
as the high standard of correctness that cryptography code needs to have
vs. more everyday device drivers. And also the fact that async offload
drivers are fundamentally much harder to get correct than software code.
The odds are really stacked against everyone here, and I think calling
it a "project management issue" largely misses the point.
- Eric
^ permalink raw reply [flat|nested] 26+ messages in thread
end of thread, other threads:[~2025-08-05 17:16 UTC | newest]
Thread overview: 26+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-08-03 20:44 [PATCH 0/7] MD5 library functions Eric Biggers
2025-08-03 20:44 ` [PATCH 1/7] mips: cavium-octeon: Remove Octeon optimized MD5 code Eric Biggers
2025-08-03 20:44 ` [PATCH 2/7] mips: cavium-octeon: Move octeon-crypto.c into parent dir Eric Biggers
2025-08-03 20:44 ` [PATCH 3/7] crypto: powerpc/md5 - Remove PowerPC optimized MD5 code Eric Biggers
2025-08-03 22:07 ` Segher Boessenkool
2025-08-03 22:14 ` Eric Biggers
2025-08-03 22:27 ` Segher Boessenkool
2025-08-03 22:56 ` Eric Biggers
2025-08-04 17:42 ` Christophe Leroy
2025-08-04 18:09 ` Eric Biggers
2025-08-04 19:02 ` Christophe Leroy
2025-08-04 22:59 ` Eric Biggers
2025-08-04 23:09 ` Eric Biggers
2025-08-05 6:21 ` Christophe Leroy
2025-08-05 4:49 ` Crypto use cases (was: Remove PowerPC optimized MD5 code) Simon Richter
2025-08-05 4:58 ` Eric Biggers
2025-08-05 7:17 ` Crypto use cases Simon Richter
2025-08-05 17:15 ` Eric Biggers
2025-08-05 6:27 ` [PATCH 3/7] crypto: powerpc/md5 - Remove PowerPC optimized MD5 code Christophe Leroy
2025-08-05 16:16 ` Eric Biggers
2025-08-03 20:44 ` [PATCH 4/7] crypto: sparc/md5 - Remove SPARC64 " Eric Biggers
2025-08-04 4:44 ` Simon Richter
2025-08-04 6:07 ` Eric Biggers
2025-08-03 20:44 ` [PATCH 5/7] lib/crypto: md5: Add MD5 and HMAC-MD5 library functions Eric Biggers
2025-08-03 20:44 ` [PATCH 6/7] crypto: md5 - Wrap library and add HMAC support Eric Biggers
2025-08-03 20:44 ` [PATCH 7/7] lib/crypto: tests: Add KUnit tests for MD5 and HMAC-MD5 Eric Biggers
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).