Skip to contentSkip to conversation

GHASH library

PATCH Applied Eric Biggers 2 participants 22 messages Mar 19 – Mar 24

Subsystems (12)
Arm (32-bit) x86 PowerPC RISC-V +8 more subsystems
lore
Share & tools
lore

Eric Biggers

author maintainer
#0 lore raw

cover GHASH library

This series is targeting libcrypto-next. It can also be retrieved from:

git fetch https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux.git ghash-lib-v1

This series migrates the standalone GHASH code to lib/crypto/, then converts the "gcm" template and AES-GCM library code to use it. (GHASH is the universal hash function used by GCM mode.) As was the case with POLYVAL and Poly1305 as well, the library is a much better fit for it.

Since GHASH and POLYVAL are closely related and it often makes sense to implement one in terms of the other, the existing "polyval" library module is renamed to "gf128hash" and the GHASH support is added to it.

The generic implementation of GHASH is also replaced with a better one utilizing the existing polyval_mul_generic().

Note that some GHASH implementations, often faster ones using more recent CPU features, still exist in arch/*/crypto/ as internal components of AES-GCM implementations. Those are left as-is for now. The goal with this GHASH library is just to provide parity with the existing standalone GHASH support, which is used when a full implementation of AES-GCM (or ${someothercipher}-GCM, if another block cipher is being used) is unavailable. Migrating the architecture-optimized AES-GCM code to lib/crypto/ will be a next step.

Eric Biggers (19):
lib/crypto: gf128hash: Rename polyval module to gf128hash lib/crypto: gf128hash: Support GF128HASH_ARCH without all POLYVAL
functions
lib/crypto: gf128hash: Add GHASH support
lib/crypto: tests: Add KUnit tests for GHASH
crypto: arm/ghash - Make the "ghash" crypto_shash NEON-only
crypto: arm/ghash - Move NEON GHASH assembly into its own file lib/crypto: arm/ghash: Migrate optimized code into library
crypto: arm64/ghash - Move NEON GHASH assembly into its own file lib/crypto: arm64/ghash: Migrate optimized code into library
crypto: arm64/aes-gcm - Rename struct ghash_key and make fixed-sized lib/crypto: powerpc/ghash: Migrate optimized code into library lib/crypto: riscv/ghash: Migrate optimized code into library lib/crypto: s390/ghash: Migrate optimized code into library lib/crypto: x86/ghash: Migrate optimized code into library
crypto: gcm - Use GHASH library instead of crypto_ahash
crypto: ghash - Remove ghash from crypto_shash API lib/crypto: gf128mul: Remove unused 4k_lle functions lib/crypto: gf128hash: Remove unused content from ghash.h lib/crypto: aesgcm: Use GHASH library API

 MAINTAINERS                                   |   4 +-
 arch/arm/crypto/Kconfig                       |  13 +-
 arch/arm/crypto/ghash-ce-core.S               | 171 +-------
 arch/arm/crypto/ghash-ce-glue.c               | 166 +------
 arch/arm64/crypto/Kconfig                     |   5 +-
 arch/arm64/crypto/ghash-ce-core.S             | 221 +---------
 arch/arm64/crypto/ghash-ce-glue.c             | 164 +------
 arch/powerpc/crypto/Kconfig                   |   5 +-
 arch/powerpc/crypto/Makefile                  |   8 +-
 arch/powerpc/crypto/aesp8-ppc.h               |   1 -
 arch/powerpc/crypto/ghash.c                   | 160 -------
 arch/powerpc/crypto/vmx.c                     |  10 +-
 arch/riscv/crypto/Kconfig                     |  11 -
 arch/riscv/crypto/Makefile                    |   3 -
 arch/riscv/crypto/ghash-riscv64-glue.c        | 146 -------
 arch/s390/configs/debug_defconfig             |   1 -
 arch/s390/configs/defconfig                   |   1 -
 arch/s390/crypto/Kconfig                      |  10 -
 arch/s390/crypto/Makefile                     |   1 -
 arch/s390/crypto/ghash_s390.c                 | 144 ------
 arch/x86/crypto/Kconfig                       |  10 -
 arch/x86/crypto/Makefile                      |   3 -
 arch/x86/crypto/aesni-intel_glue.c            |   1 +
 arch/x86/crypto/ghash-clmulni-intel_glue.c    | 163 -------
 crypto/Kconfig                                |  11 +-
 crypto/Makefile                               |   1 -
 crypto/gcm.c                                  | 413 ++++--------------
 crypto/ghash-generic.c                        | 162 -------
 crypto/hctr2.c                                |   2 +-
 crypto/tcrypt.c                               |   9 -
 crypto/testmgr.c                              |  16 +-
 crypto/testmgr.h                              | 109 -----
 drivers/crypto/starfive/jh7110-aes.c          |   2 +-
 include/crypto/gcm.h                          |   4 +-
 include/crypto/{polyval.h => gf128hash.h}     | 126 +++++-
 include/crypto/gf128mul.h                     |  17 +-
 include/crypto/ghash.h                        |  12 -
 lib/crypto/.kunitconfig                       |   1 +
 lib/crypto/Kconfig                            |  31 +-
 lib/crypto/Makefile                           |  47 +-
 lib/crypto/aesgcm.c                           |  55 +--
 lib/crypto/arm/gf128hash.h                    |  43 ++
 lib/crypto/arm/ghash-neon-core.S              | 209 +++++++++
 lib/crypto/arm64/gf128hash.h                  | 137 ++++++
 lib/crypto/arm64/ghash-neon-core.S            | 220 ++++++++++
 lib/crypto/arm64/polyval.h                    |  80 ----
 lib/crypto/{polyval.c => gf128hash.c}         | 183 ++++++--
 lib/crypto/gf128mul.c                         |  73 +---
 lib/crypto/powerpc/.gitignore                 |   1 +
 lib/crypto/powerpc/gf128hash.h                | 109 +++++
 .../crypto/powerpc}/ghashp8-ppc.pl            |   1 +
 lib/crypto/riscv/gf128hash.h                  |  57 +++
 .../crypto/riscv}/ghash-riscv64-zvkg.S        |  13 +-
 lib/crypto/s390/gf128hash.h                   |  54 +++
 lib/crypto/tests/Kconfig                      |  12 +-
 lib/crypto/tests/Makefile                     |   1 +
 lib/crypto/tests/ghash-testvecs.h             | 186 ++++++++
 lib/crypto/tests/ghash_kunit.c                | 194 ++++++++
 lib/crypto/tests/polyval_kunit.c              |   2 +-
 lib/crypto/x86/{polyval.h => gf128hash.h}     |  72 ++-
 .../crypto/x86/ghash-pclmul.S                 |  98 ++---
 scripts/crypto/gen-hash-testvecs.py           |  63 ++-
 62 files changed, 1903 insertions(+), 2345 deletions(-)
 delete mode 100644 arch/powerpc/crypto/ghash.c
 delete mode 100644 arch/riscv/crypto/ghash-riscv64-glue.c
 delete mode 100644 arch/s390/crypto/ghash_s390.c
 delete mode 100644 arch/x86/crypto/ghash-clmulni-intel_glue.c
 delete mode 100644 crypto/ghash-generic.c
 rename include/crypto/{polyval.h => gf128hash.h} (60%)
 create mode 100644 lib/crypto/arm/gf128hash.h
 create mode 100644 lib/crypto/arm/ghash-neon-core.S
 create mode 100644 lib/crypto/arm64/gf128hash.h
 create mode 100644 lib/crypto/arm64/ghash-neon-core.S
 delete mode 100644 lib/crypto/arm64/polyval.h
 rename lib/crypto/{polyval.c => gf128hash.c} (61%)
 create mode 100644 lib/crypto/powerpc/gf128hash.h
 rename {arch/powerpc/crypto => lib/crypto/powerpc}/ghashp8-ppc.pl (98%)
 create mode 100644 lib/crypto/riscv/gf128hash.h
 rename {arch/riscv/crypto => lib/crypto/riscv}/ghash-riscv64-zvkg.S (91%)
 create mode 100644 lib/crypto/s390/gf128hash.h
 create mode 100644 lib/crypto/tests/ghash-testvecs.h
 create mode 100644 lib/crypto/tests/ghash_kunit.c
 rename lib/crypto/x86/{polyval.h => gf128hash.h} (51%)
 rename arch/x86/crypto/ghash-clmulni-intel_asm.S => lib/crypto/x86/ghash-pclmul.S (54%)

base-commit: 520a39fb6916ac3a269ad4ea87a6cb9af9d5a910

Signature · 1 line
2.53.0
author maintainer
#1 lore raw

PATCH 1/19 lib/crypto: gf128hash: Rename polyval module to gf128hash

Currently, the standalone GHASH code is coupled with crypto_shash. This has resulted in unnecessary complexity and overhead, as well as the code being unavailable to library code such as the AES-GCM library. Like was done with POLYVAL, it needs to find a new home in lib/crypto/.

GHASH and POLYVAL are closely related and can each be implemented in terms of each other. Optimized code for one can be reused with the other. But also since GHASH tends to be difficult to implement directly due to its unnatural bit order, most modern GHASH implementations (including the existing arm, arm64, powerpc, and x86 optimized GHASH code, and the new generic GHASH code I'll be adding) actually reinterpret the GHASH computation as an equivalent POLYVAL computation, pre and post-processing the inputs and outputs to map to/from POLYVAL.

Given this close relationship, it makes sense to group the GHASH and POLYVAL code together in the same module. This gives us a wide range of options for implementing them, reusing code between the two and properly utilizing whatever instructions each architecture provides.

Thus, GHASH support will be added to the library module that is currently called "polyval". Rename it to an appropriate name:
"gf128hash". Rename files, options, functions, etc. where appropriate to reflect the upcoming sharing with GHASH. (Note: polyval_kunit is not renamed, as ghash_kunit will be added alongside it instead.)

---
 crypto/Kconfig                              |  2 +-
 crypto/hctr2.c                              |  2 +-
 include/crypto/{polyval.h => gf128hash.h}   | 16 ++++++-------
 lib/crypto/Kconfig                          | 24 +++++++++----------
 lib/crypto/Makefile                         | 20 ++++++++--------
 lib/crypto/arm64/{polyval.h => gf128hash.h} |  4 ++--
 lib/crypto/{polyval.c => gf128hash.c}       | 26 ++++++++++-----------
 lib/crypto/tests/Kconfig                    |  4 ++--
 lib/crypto/tests/polyval_kunit.c            |  2 +-
 lib/crypto/x86/{polyval.h => gf128hash.h}   |  4 ++--
 10 files changed, 52 insertions(+), 52 deletions(-)
 rename include/crypto/{polyval.h => gf128hash.h} (94%)
 rename lib/crypto/arm64/{polyval.h => gf128hash.h} (95%)
 rename lib/crypto/{polyval.c => gf128hash.c} (94%)
 rename lib/crypto/x86/{polyval.h => gf128hash.h} (95%)
crypto/Kconfig +1 -1
index b8608ef6823b..5627b3691561 100644
@@ -684,11 +684,11 @@ config CRYPTO_ECB
 	  ECB (Electronic Codebook) mode (NIST SP800-38A)
 
 config CRYPTO_HCTR2
 	tristate "HCTR2"
 	select CRYPTO_XCTR
-	select CRYPTO_LIB_POLYVAL
+	select CRYPTO_LIB_GF128HASH
 	select CRYPTO_MANAGER
 	help
 	  HCTR2 length-preserving encryption mode
 
 	  A mode for storage encryption that is efficient on processors with
crypto/hctr2.c +1 -1
index f4cd6c29b4d3..ad5edf9366ac 100644
@@ -14,13 +14,13 @@
  *
  * For more details, see the paper: "Length-preserving encryption with HCTR2"
  * (https://eprint.iacr.org/2021/1441.pdf)
  */
 
+#include <crypto/gf128hash.h>
 #include <crypto/internal/cipher.h>
 #include <crypto/internal/skcipher.h>
-#include <crypto/polyval.h>
 #include <crypto/scatterwalk.h>
 #include <linux/module.h>
 
 #define BLOCKCIPHER_BLOCK_SIZE		16
 
include/crypto/gf128hash.h renamed from include/crypto/polyval.h +8 -8
similarity index 94%
rename from include/crypto/polyval.h
rename to include/crypto/gf128hash.h
index b28b8ef11353..5ffa86f5c13f 100644
@@ -1,14 +1,14 @@
 /* SPDX-License-Identifier: GPL-2.0-or-later */
 /*
- * POLYVAL library API
+ * GF(2^128) polynomial hashing: GHASH and POLYVAL
  *
  * Copyright 2025 Google LLC
  */
 
-#ifndef _CRYPTO_POLYVAL_H
-#define _CRYPTO_POLYVAL_H
+#ifndef _CRYPTO_GF128HASH_H
+#define _CRYPTO_GF128HASH_H
 
 #include <linux/string.h>
 #include <linux/types.h>
 
 #define POLYVAL_BLOCK_SIZE	16
@@ -42,24 +42,24 @@ struct polyval_elem {
  *
  * By H^i we mean H^(i-1) * H * x^-128, with base case H^1 = H.  I.e. the
  * exponentiation repeats the POLYVAL dot operation, with its "extra" x^-128.
  */
 struct polyval_key {
-#ifdef CONFIG_CRYPTO_LIB_POLYVAL_ARCH
+#ifdef CONFIG_CRYPTO_LIB_GF128HASH_ARCH
 #ifdef CONFIG_ARM64
 	/** @h_powers: Powers of the hash key H^8 through H^1 */
 	struct polyval_elem h_powers[8];
 #elif defined(CONFIG_X86)
 	/** @h_powers: Powers of the hash key H^8 through H^1 */
 	struct polyval_elem h_powers[8];
 #else
 #error "Unhandled arch"
 #endif
-#else /* CONFIG_CRYPTO_LIB_POLYVAL_ARCH */
+#else /* CONFIG_CRYPTO_LIB_GF128HASH_ARCH */
 	/** @h: The hash key H */
 	struct polyval_elem h;
-#endif /* !CONFIG_CRYPTO_LIB_POLYVAL_ARCH */
+#endif /* !CONFIG_CRYPTO_LIB_GF128HASH_ARCH */
 };
 
 /**
  * struct polyval_ctx - Context for computing a POLYVAL value
  * @key: Pointer to the prepared POLYVAL key.  The user of the API is
@@ -82,11 +82,11 @@ struct polyval_ctx {
  * copy, or it may involve precomputing powers of the key, depending on the
  * platform's POLYVAL implementation.
  *
  * Context: Any context.
  */
-#ifdef CONFIG_CRYPTO_LIB_POLYVAL_ARCH
+#ifdef CONFIG_CRYPTO_LIB_GF128HASH_ARCH
 void polyval_preparekey(struct polyval_key *key,
 			const u8 raw_key[POLYVAL_BLOCK_SIZE]);
 
 #else
 static inline void polyval_preparekey(struct polyval_key *key,
@@ -185,6 +185,6 @@ static inline void polyval(const struct polyval_key *key,
 	polyval_init(&ctx, key);
 	polyval_update(&ctx, data, len);
 	polyval_final(&ctx, out);
 }
 
-#endif /* _CRYPTO_POLYVAL_H */
+#endif /* _CRYPTO_GF128HASH_H */
lib/crypto/Kconfig +12 -12
index 4910fe20e42a..98cedd95c2a5 100644
@@ -108,10 +108,22 @@ config CRYPTO_LIB_CURVE25519_GENERIC
 	default y if !CRYPTO_LIB_CURVE25519_ARCH || ARM || X86_64
 
 config CRYPTO_LIB_DES
 	tristate
 
+config CRYPTO_LIB_GF128HASH
+	tristate
+	help
+	  The GHASH and POLYVAL library functions.  Select this if your module
+	  uses any of the functions from <crypto/gf128hash.h>.
+
+config CRYPTO_LIB_GF128HASH_ARCH
+	bool
+	depends on CRYPTO_LIB_GF128HASH && !UML
+	default y if ARM64
+	default y if X86_64
+
 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>.
@@ -176,22 +188,10 @@ config CRYPTO_LIB_POLY1305_RSIZE
 	default 2 if MIPS || RISCV
 	default 11 if X86_64
 	default 9 if ARM || ARM64
 	default 1
 
-config CRYPTO_LIB_POLYVAL
-	tristate
-	help
-	  The POLYVAL library functions.  Select this if your module uses any of
-	  the functions from <crypto/polyval.h>.
-
-config CRYPTO_LIB_POLYVAL_ARCH
-	bool
-	depends on CRYPTO_LIB_POLYVAL && !UML
-	default y if ARM64
-	default y if X86_64
-
 config CRYPTO_LIB_CHACHA20POLY1305
 	tristate
 	select CRYPTO_LIB_CHACHA
 	select CRYPTO_LIB_POLY1305
 	select CRYPTO_LIB_UTILS
lib/crypto/Makefile +10 -10
index a961615c8c7f..fc30622123d2 100644
@@ -152,10 +152,20 @@ endif
 obj-$(CONFIG_CRYPTO_LIB_DES)			+= libdes.o
 libdes-y					:= des.o
 
 ################################################################################
 
+obj-$(CONFIG_CRYPTO_LIB_GF128HASH) += libgf128hash.o
+libgf128hash-y := gf128hash.o
+ifeq ($(CONFIG_CRYPTO_LIB_GF128HASH_ARCH),y)
+CFLAGS_gf128hash.o += -I$(src)/$(SRCARCH)
+libgf128hash-$(CONFIG_ARM64) += arm64/polyval-ce-core.o
+libgf128hash-$(CONFIG_X86) += x86/polyval-pclmul-avx.o
+endif
+
+################################################################################
+
 obj-$(CONFIG_CRYPTO_LIB_MD5) += libmd5.o
 libmd5-y := md5.o
 ifeq ($(CONFIG_CRYPTO_LIB_MD5_ARCH),y)
 CFLAGS_md5.o += -I$(src)/$(SRCARCH)
 libmd5-$(CONFIG_PPC) += powerpc/md5-asm.o
@@ -249,20 +259,10 @@ clean-files += arm/poly1305-core.S \
 	       riscv/poly1305-core.S \
 	       x86/poly1305-x86_64-cryptogams.S
 
 ################################################################################
 
-obj-$(CONFIG_CRYPTO_LIB_POLYVAL) += libpolyval.o
-libpolyval-y := polyval.o
-ifeq ($(CONFIG_CRYPTO_LIB_POLYVAL_ARCH),y)
-CFLAGS_polyval.o += -I$(src)/$(SRCARCH)
-libpolyval-$(CONFIG_ARM64) += arm64/polyval-ce-core.o
-libpolyval-$(CONFIG_X86) += x86/polyval-pclmul-avx.o
-endif
-
-################################################################################
-
 obj-$(CONFIG_CRYPTO_LIB_SHA1) += libsha1.o
 libsha1-y := sha1.o
 ifeq ($(CONFIG_CRYPTO_LIB_SHA1_ARCH),y)
 CFLAGS_sha1.o += -I$(src)/$(SRCARCH)
 ifeq ($(CONFIG_ARM),y)
lib/crypto/arm64/gf128hash.h renamed from lib/crypto/arm64/polyval.h +2 -2
similarity index 95%
rename from lib/crypto/arm64/polyval.h
rename to lib/crypto/arm64/gf128hash.h
index a39763395e9b..c1012007adcf 100644
@@ -70,11 +70,11 @@ static void polyval_blocks_arch(struct polyval_elem *acc,
 		polyval_blocks_generic(acc, &key->h_powers[NUM_H_POWERS - 1],
 				       data, nblocks);
 	}
 }
 
-#define polyval_mod_init_arch polyval_mod_init_arch
-static void polyval_mod_init_arch(void)
+#define gf128hash_mod_init_arch gf128hash_mod_init_arch
+static void gf128hash_mod_init_arch(void)
 {
 	if (cpu_have_named_feature(PMULL))
 		static_branch_enable(&have_pmull);
 }
lib/crypto/gf128hash.c renamed from lib/crypto/polyval.c +13 -13
similarity index 94%
rename from lib/crypto/polyval.c
rename to lib/crypto/gf128hash.c
index 5796275f574a..8bb848bf26b7 100644
@@ -1,13 +1,13 @@
 // SPDX-License-Identifier: GPL-2.0-or-later
 /*
- * POLYVAL library functions
+ * GF(2^128) polynomial hashing: GHASH and POLYVAL
  *
  * Copyright 2025 Google LLC
  */
 
-#include <crypto/polyval.h>
+#include <crypto/gf128hash.h>
 #include <linux/export.h>
 #include <linux/module.h>
 #include <linux/string.h>
 #include <linux/unaligned.h>
 
@@ -216,12 +216,12 @@ polyval_blocks_generic(struct polyval_elem *acc, const struct polyval_elem *key,
 		data += POLYVAL_BLOCK_SIZE;
 	} while (--nblocks);
 }
 
 /* Include the arch-optimized implementation of POLYVAL, if one is available. */
-#ifdef CONFIG_CRYPTO_LIB_POLYVAL_ARCH
-#include "polyval.h" /* $(SRCARCH)/polyval.h */
+#ifdef CONFIG_CRYPTO_LIB_GF128HASH_ARCH
+#include "gf128hash.h" /* $(SRCARCH)/gf128hash.h */
 void polyval_preparekey(struct polyval_key *key,
 			const u8 raw_key[POLYVAL_BLOCK_SIZE])
 {
 	polyval_preparekey_arch(key, raw_key);
 }
@@ -236,21 +236,21 @@ EXPORT_SYMBOL_GPL(polyval_preparekey);
  * code is needed to pass the appropriate key argument.
  */
 
 static void polyval_mul(struct polyval_ctx *ctx)
 {
-#ifdef CONFIG_CRYPTO_LIB_POLYVAL_ARCH
+#ifdef CONFIG_CRYPTO_LIB_GF128HASH_ARCH
 	polyval_mul_arch(&ctx->acc, ctx->key);
 #else
 	polyval_mul_generic(&ctx->acc, &ctx->key->h);
 #endif
 }
 
 static void polyval_blocks(struct polyval_ctx *ctx,
 			   const u8 *data, size_t nblocks)
 {
-#ifdef CONFIG_CRYPTO_LIB_POLYVAL_ARCH
+#ifdef CONFIG_CRYPTO_LIB_GF128HASH_ARCH
 	polyval_blocks_arch(&ctx->acc, ctx->key, data, nblocks);
 #else
 	polyval_blocks_generic(&ctx->acc, &ctx->key->h, data, nblocks);
 #endif
 }
@@ -287,21 +287,21 @@ void polyval_final(struct polyval_ctx *ctx, u8 out[POLYVAL_BLOCK_SIZE])
 	memcpy(out, &ctx->acc, POLYVAL_BLOCK_SIZE);
 	memzero_explicit(ctx, sizeof(*ctx));
 }
 EXPORT_SYMBOL_GPL(polyval_final);
 
-#ifdef polyval_mod_init_arch
-static int __init polyval_mod_init(void)
+#ifdef gf128hash_mod_init_arch
+static int __init gf128hash_mod_init(void)
 {
-	polyval_mod_init_arch();
+	gf128hash_mod_init_arch();
 	return 0;
 }
-subsys_initcall(polyval_mod_init);
+subsys_initcall(gf128hash_mod_init);
 
-static void __exit polyval_mod_exit(void)
+static void __exit gf128hash_mod_exit(void)
 {
 }
-module_exit(polyval_mod_exit);
+module_exit(gf128hash_mod_exit);
 #endif
 
-MODULE_DESCRIPTION("POLYVAL almost-XOR-universal hash function");
+MODULE_DESCRIPTION("GF(2^128) polynomial hashing: GHASH and POLYVAL");
 MODULE_LICENSE("GPL");
lib/crypto/tests/Kconfig +2 -2
index 42e1770e1883..aa627b6b9855 100644
@@ -67,11 +67,11 @@ config CRYPTO_LIB_POLY1305_KUNIT_TEST
 	help
 	  KUnit tests for the Poly1305 library functions.
 
 config CRYPTO_LIB_POLYVAL_KUNIT_TEST
 	tristate "KUnit tests for POLYVAL" if !KUNIT_ALL_TESTS
-	depends on KUNIT && CRYPTO_LIB_POLYVAL
+	depends on KUNIT && CRYPTO_LIB_GF128HASH
 	default KUNIT_ALL_TESTS
 	select CRYPTO_LIB_BENCHMARK_VISIBLE
 	help
 	  KUnit tests for the POLYVAL library functions.
 
@@ -120,15 +120,15 @@ config CRYPTO_LIB_ENABLE_ALL_FOR_KUNIT
 	tristate "Enable all crypto library code for KUnit tests"
 	depends on KUNIT
 	select CRYPTO_LIB_AES_CBC_MACS
 	select CRYPTO_LIB_BLAKE2B
 	select CRYPTO_LIB_CURVE25519
+	select CRYPTO_LIB_GF128HASH
 	select CRYPTO_LIB_MD5
 	select CRYPTO_LIB_MLDSA
 	select CRYPTO_LIB_NH
 	select CRYPTO_LIB_POLY1305
-	select CRYPTO_LIB_POLYVAL
 	select CRYPTO_LIB_SHA1
 	select CRYPTO_LIB_SHA256
 	select CRYPTO_LIB_SHA512
 	select CRYPTO_LIB_SHA3
 	help
lib/crypto/tests/polyval_kunit.c +1 -1
index f47f41a39a41..d1f53a690ab8 100644
@@ -1,10 +1,10 @@
 // SPDX-License-Identifier: GPL-2.0-or-later
 /*
  * Copyright 2025 Google LLC
  */
-#include <crypto/polyval.h>
+#include <crypto/gf128hash.h>
 #include "polyval-testvecs.h"
 
 /*
  * A fixed key used when presenting POLYVAL as an unkeyed hash function in order
  * to reuse hash-test-template.h.  At the beginning of the test suite, this is
lib/crypto/x86/gf128hash.h renamed from lib/crypto/x86/polyval.h +2 -2
similarity index 95%
rename from lib/crypto/x86/polyval.h
rename to lib/crypto/x86/gf128hash.h
index ef8797521420..fe506cf6431b 100644
@@ -72,12 +72,12 @@ static void polyval_blocks_arch(struct polyval_elem *acc,
 		polyval_blocks_generic(acc, &key->h_powers[NUM_H_POWERS - 1],
 				       data, nblocks);
 	}
 }
 
-#define polyval_mod_init_arch polyval_mod_init_arch
-static void polyval_mod_init_arch(void)
+#define gf128hash_mod_init_arch gf128hash_mod_init_arch
+static void gf128hash_mod_init_arch(void)
 {
 	if (boot_cpu_has(X86_FEATURE_PCLMULQDQ) &&
 	    boot_cpu_has(X86_FEATURE_AVX))
 		static_branch_enable(&have_pclmul_avx);
 }
Signature · 1 line
2.53.0
author maintainer
#2 lore raw

PATCH 2/19 lib/crypto: gf128hash: Support GF128HASH_ARCH without all POLYVAL functions

In reply to Eric Biggers

Currently, some architectures (arm64 and x86) have optimized code for both GHASH and POLYVAL. Others (arm, powerpc, riscv, and s390) have optimized code only for GHASH. While POLYVAL support could be implemented on these other architectures, until then we need to support the case where arch-optimized functions are present only for GHASH.

Therefore, update the support for arch-optimized POLYVAL functions to allow architectures to opt into supporting these functions individually.

The new meaning of CONFIG_CRYPTO_LIB_GF128HASH_ARCH is that some level of GHASH and/or POLYVAL acceleration is provided.

Also provide an implementation of polyval_mul() based on polyval_blocks_arch(), for when polyval_mul_arch() isn't implemented.

---
 include/crypto/gf128hash.h   | 22 +++-------------------
 lib/crypto/arm64/gf128hash.h |  3 +++
 lib/crypto/gf128hash.c       | 16 ++++++++++++----
 lib/crypto/x86/gf128hash.h   |  3 +++
 4 files changed, 21 insertions(+), 23 deletions(-)
include/crypto/gf128hash.h +3 -19
index 5ffa86f5c13f..1052041e3499 100644
@@ -42,24 +42,18 @@ struct polyval_elem {
  *
  * By H^i we mean H^(i-1) * H * x^-128, with base case H^1 = H.  I.e. the
  * exponentiation repeats the POLYVAL dot operation, with its "extra" x^-128.
  */
 struct polyval_key {
-#ifdef CONFIG_CRYPTO_LIB_GF128HASH_ARCH
-#ifdef CONFIG_ARM64
-	/** @h_powers: Powers of the hash key H^8 through H^1 */
-	struct polyval_elem h_powers[8];
-#elif defined(CONFIG_X86)
+#if defined(CONFIG_CRYPTO_LIB_GF128HASH_ARCH) && \
+	(defined(CONFIG_ARM64) || defined(CONFIG_X86))
 	/** @h_powers: Powers of the hash key H^8 through H^1 */
 	struct polyval_elem h_powers[8];
 #else
-#error "Unhandled arch"
-#endif
-#else /* CONFIG_CRYPTO_LIB_GF128HASH_ARCH */
 	/** @h: The hash key H */
 	struct polyval_elem h;
-#endif /* !CONFIG_CRYPTO_LIB_GF128HASH_ARCH */
+#endif
 };
 
 /**
  * struct polyval_ctx - Context for computing a POLYVAL value
  * @key: Pointer to the prepared POLYVAL key.  The user of the API is
@@ -82,23 +76,13 @@ struct polyval_ctx {
  * copy, or it may involve precomputing powers of the key, depending on the
  * platform's POLYVAL implementation.
  *
  * Context: Any context.
  */
-#ifdef CONFIG_CRYPTO_LIB_GF128HASH_ARCH
 void polyval_preparekey(struct polyval_key *key,
 			const u8 raw_key[POLYVAL_BLOCK_SIZE]);
 
-#else
-static inline void polyval_preparekey(struct polyval_key *key,
-				      const u8 raw_key[POLYVAL_BLOCK_SIZE])
-{
-	/* Just a simple copy, so inline it. */
-	memcpy(key->h.bytes, raw_key, POLYVAL_BLOCK_SIZE);
-}
-#endif
-
 /**
  * polyval_init() - Initialize a POLYVAL context for a new message
  * @ctx: The context to initialize
  * @key: The key to use.  Note that a pointer to the key is saved in the
  *	 context, so the key must live at least as long as the context.
lib/crypto/arm64/gf128hash.h +3 -0
index c1012007adcf..796c36804dda 100644
@@ -15,10 +15,11 @@ asmlinkage void polyval_mul_pmull(struct polyval_elem *a,
 				  const struct polyval_elem *b);
 asmlinkage void polyval_blocks_pmull(struct polyval_elem *acc,
 				     const struct polyval_key *key,
 				     const u8 *data, size_t nblocks);
 
+#define polyval_preparekey_arch polyval_preparekey_arch
 static void polyval_preparekey_arch(struct polyval_key *key,
 				    const u8 raw_key[POLYVAL_BLOCK_SIZE])
 {
 	static_assert(ARRAY_SIZE(key->h_powers) == NUM_H_POWERS);
 	memcpy(&key->h_powers[NUM_H_POWERS - 1], raw_key, POLYVAL_BLOCK_SIZE);
@@ -38,10 +39,11 @@ static void polyval_preparekey_arch(struct polyval_key *key,
 					    &key->h_powers[NUM_H_POWERS - 1]);
 		}
 	}
 }
 
+#define polyval_mul_arch polyval_mul_arch
 static void polyval_mul_arch(struct polyval_elem *acc,
 			     const struct polyval_key *key)
 {
 	if (static_branch_likely(&have_pmull) && may_use_simd()) {
 		scoped_ksimd()
@@ -49,10 +51,11 @@ static void polyval_mul_arch(struct polyval_elem *acc,
 	} else {
 		polyval_mul_generic(acc, &key->h_powers[NUM_H_POWERS - 1]);
 	}
 }
 
+#define polyval_blocks_arch polyval_blocks_arch
 static void polyval_blocks_arch(struct polyval_elem *acc,
 				const struct polyval_key *key,
 				const u8 *data, size_t nblocks)
 {
 	if (static_branch_likely(&have_pmull) && may_use_simd()) {
lib/crypto/gf128hash.c +12 -4
index 8bb848bf26b7..05f44a9193f7 100644
@@ -215,20 +215,24 @@ polyval_blocks_generic(struct polyval_elem *acc, const struct polyval_elem *key,
 		polyval_mul_generic(acc, key);
 		data += POLYVAL_BLOCK_SIZE;
 	} while (--nblocks);
 }
 
-/* Include the arch-optimized implementation of POLYVAL, if one is available. */
 #ifdef CONFIG_CRYPTO_LIB_GF128HASH_ARCH
 #include "gf128hash.h" /* $(SRCARCH)/gf128hash.h */
+#endif
+
 void polyval_preparekey(struct polyval_key *key,
 			const u8 raw_key[POLYVAL_BLOCK_SIZE])
 {
+#ifdef polyval_preparekey_arch
 	polyval_preparekey_arch(key, raw_key);
+#else
+	memcpy(key->h.bytes, raw_key, POLYVAL_BLOCK_SIZE);
+#endif
 }
 EXPORT_SYMBOL_GPL(polyval_preparekey);
-#endif /* Else, polyval_preparekey() is an inline function. */
 
 /*
  * polyval_mul_generic() and polyval_blocks_generic() take the key as a
  * polyval_elem rather than a polyval_key, so that arch-optimized
  * implementations with a different key format can use it as a fallback (if they
@@ -236,21 +240,25 @@ EXPORT_SYMBOL_GPL(polyval_preparekey);
  * code is needed to pass the appropriate key argument.
  */
 
 static void polyval_mul(struct polyval_ctx *ctx)
 {
-#ifdef CONFIG_CRYPTO_LIB_GF128HASH_ARCH
+#ifdef polyval_mul_arch
 	polyval_mul_arch(&ctx->acc, ctx->key);
+#elif defined(polyval_blocks_arch)
+	static const u8 zeroes[POLYVAL_BLOCK_SIZE];
+
+	polyval_blocks_arch(&ctx->acc, ctx->key, zeroes, 1);
 #else
 	polyval_mul_generic(&ctx->acc, &ctx->key->h);
 #endif
 }
 
 static void polyval_blocks(struct polyval_ctx *ctx,
 			   const u8 *data, size_t nblocks)
 {
-#ifdef CONFIG_CRYPTO_LIB_GF128HASH_ARCH
+#ifdef polyval_blocks_arch
 	polyval_blocks_arch(&ctx->acc, ctx->key, data, nblocks);
 #else
 	polyval_blocks_generic(&ctx->acc, &ctx->key->h, data, nblocks);
 #endif
 }
lib/crypto/x86/gf128hash.h +3 -0
index fe506cf6431b..adf6147ea677 100644
@@ -15,10 +15,11 @@ asmlinkage void polyval_mul_pclmul_avx(struct polyval_elem *a,
 				       const struct polyval_elem *b);
 asmlinkage void polyval_blocks_pclmul_avx(struct polyval_elem *acc,
 					  const struct polyval_key *key,
 					  const u8 *data, size_t nblocks);
 
+#define polyval_preparekey_arch polyval_preparekey_arch
 static void polyval_preparekey_arch(struct polyval_key *key,
 				    const u8 raw_key[POLYVAL_BLOCK_SIZE])
 {
 	static_assert(ARRAY_SIZE(key->h_powers) == NUM_H_POWERS);
 	memcpy(&key->h_powers[NUM_H_POWERS - 1], raw_key, POLYVAL_BLOCK_SIZE);
@@ -38,10 +39,11 @@ static void polyval_preparekey_arch(struct polyval_key *key,
 					    &key->h_powers[NUM_H_POWERS - 1]);
 		}
 	}
 }
 
+#define polyval_mul_arch polyval_mul_arch
 static void polyval_mul_arch(struct polyval_elem *acc,
 			     const struct polyval_key *key)
 {
 	if (static_branch_likely(&have_pclmul_avx) && irq_fpu_usable()) {
 		kernel_fpu_begin();
@@ -50,10 +52,11 @@ static void polyval_mul_arch(struct polyval_elem *acc,
 	} else {
 		polyval_mul_generic(acc, &key->h_powers[NUM_H_POWERS - 1]);
 	}
 }
 
+#define polyval_blocks_arch polyval_blocks_arch
 static void polyval_blocks_arch(struct polyval_elem *acc,
 				const struct polyval_key *key,
 				const u8 *data, size_t nblocks)
 {
 	if (static_branch_likely(&have_pclmul_avx) && irq_fpu_usable()) {
Signature · 1 line
2.53.0
author maintainer
#3 lore raw

PATCH 3/19 lib/crypto: gf128hash: Add GHASH support

In reply to Eric Biggers

Add GHASH support to the gf128hash module.

This will replace the GHASH support in the crypto_shash API. It will be used by the "gcm" template and by the AES-GCM library (when an arch-optimized implementation of the full AES-GCM is unavailable).

This consists of a simple API that mirrors the existing POLYVAL API, a generic implementation of that API based on the existing efficient and side-channel-resistant polyval_mul_generic(), and the framework for architecture-optimized implementations of the GHASH functions.

The GHASH accumulator is stored in POLYVAL format rather than GHASH format, since this is what most modern GHASH implementations actually need. The few implementations that expect the accumulator in GHASH format will just convert the accumulator to/from GHASH format temporarily. (Supporting architecture-specific accumulator formats would be possible, but doesn't seem worth the complexity.)

However, architecture-specific formats of struct ghash_key will be supported, since a variety of formats will be needed there anyway. The default format is just the key in POLYVAL format.

---
 include/crypto/gf128hash.h |  95 ++++++++++++++++++++++++
 lib/crypto/gf128hash.c     | 145 +++++++++++++++++++++++++++++++++----
 2 files changed, 227 insertions(+), 13 deletions(-)
include/crypto/gf128hash.h +95 -0
index 1052041e3499..5090fbaa87f8 100644
@@ -9,10 +9,12 @@
 #define _CRYPTO_GF128HASH_H
 
 #include <linux/string.h>
 #include <linux/types.h>
 
+#define GHASH_BLOCK_SIZE	16
+#define GHASH_DIGEST_SIZE	16
 #define POLYVAL_BLOCK_SIZE	16
 #define POLYVAL_DIGEST_SIZE	16
 
 /**
  * struct polyval_elem - An element of the POLYVAL finite field
@@ -31,10 +33,20 @@ struct polyval_elem {
 			__le64 hi;
 		};
 	};
 };
 
+/**
+ * struct ghash_key - Prepared key for GHASH
+ *
+ * Use ghash_preparekey() to initialize this.
+ */
+struct ghash_key {
+	/** @h: The hash key H, in POLYVAL format */
+	struct polyval_elem h;
+};
+
 /**
  * struct polyval_key - Prepared key for POLYVAL
  *
  * This may contain just the raw key H, or it may contain precomputed key
  * powers, depending on the platform's POLYVAL implementation.  Use
@@ -52,10 +64,24 @@ struct polyval_key {
 	/** @h: The hash key H */
 	struct polyval_elem h;
 #endif
 };
 
+/**
+ * struct ghash_ctx - Context for computing a GHASH value
+ * @key: Pointer to the prepared GHASH key.  The user of the API is
+ *	 responsible for ensuring that the key lives as long as the context.
+ * @acc: The accumulator.  It is stored in POLYVAL format rather than GHASH
+ *	 format, since most implementations want it in POLYVAL format.
+ * @partial: Number of data bytes processed so far modulo GHASH_BLOCK_SIZE
+ */
+struct ghash_ctx {
+	const struct ghash_key *key;
+	struct polyval_elem acc;
+	size_t partial;
+};
+
 /**
  * struct polyval_ctx - Context for computing a POLYVAL value
  * @key: Pointer to the prepared POLYVAL key.  The user of the API is
  *	 responsible for ensuring that the key lives as long as the context.
  * @acc: The accumulator
@@ -65,10 +91,22 @@ struct polyval_ctx {
 	const struct polyval_key *key;
 	struct polyval_elem acc;
 	size_t partial;
 };
 
+/**
+ * ghash_preparekey() - Prepare a GHASH key
+ * @key: (output) The key structure to initialize
+ * @raw_key: The raw hash key
+ *
+ * Initialize a GHASH key structure from a raw key.
+ *
+ * Context: Any context.
+ */
+void ghash_preparekey(struct ghash_key *key,
+		      const u8 raw_key[GHASH_BLOCK_SIZE]);
+
 /**
  * polyval_preparekey() - Prepare a POLYVAL key
  * @key: (output) The key structure to initialize
  * @raw_key: The raw hash key
  *
@@ -79,10 +117,22 @@ struct polyval_ctx {
  * Context: Any context.
  */
 void polyval_preparekey(struct polyval_key *key,
 			const u8 raw_key[POLYVAL_BLOCK_SIZE]);
 
+/**
+ * ghash_init() - Initialize a GHASH context for a new message
+ * @ctx: The context to initialize
+ * @key: The key to use.  Note that a pointer to the key is saved in the
+ *	 context, so the key must live at least as long as the context.
+ */
+static inline void ghash_init(struct ghash_ctx *ctx,
+			      const struct ghash_key *key)
+{
+	*ctx = (struct ghash_ctx){ .key = key };
+}
+
 /**
  * polyval_init() - Initialize a POLYVAL context for a new message
  * @ctx: The context to initialize
  * @key: The key to use.  Note that a pointer to the key is saved in the
  *	 context, so the key must live at least as long as the context.
@@ -123,10 +173,22 @@ static inline void polyval_export_blkaligned(const struct polyval_ctx *ctx,
 					     struct polyval_elem *acc)
 {
 	*acc = ctx->acc;
 }
 
+/**
+ * ghash_update() - Update a GHASH context with message data
+ * @ctx: The context to update; must have been initialized
+ * @data: The message data
+ * @len: The data length in bytes.  Doesn't need to be block-aligned.
+ *
+ * This can be called any number of times.
+ *
+ * Context: Any context.
+ */
+void ghash_update(struct ghash_ctx *ctx, const u8 *data, size_t len);
+
 /**
  * polyval_update() - Update a POLYVAL context with message data
  * @ctx: The context to update; must have been initialized
  * @data: The message data
  * @len: The data length in bytes.  Doesn't need to be block-aligned.
@@ -135,10 +197,24 @@ static inline void polyval_export_blkaligned(const struct polyval_ctx *ctx,
  *
  * Context: Any context.
  */
 void polyval_update(struct polyval_ctx *ctx, const u8 *data, size_t len);
 
+/**
+ * ghash_final() - Finish computing a GHASH value
+ * @ctx: The context to finalize
+ * @out: The output value
+ *
+ * If the total data length isn't a multiple of GHASH_BLOCK_SIZE, then the
+ * final block is automatically zero-padded.
+ *
+ * After finishing, this zeroizes @ctx.  So the caller does not need to do it.
+ *
+ * Context: Any context.
+ */
+void ghash_final(struct ghash_ctx *ctx, u8 out[GHASH_BLOCK_SIZE]);
+
 /**
  * polyval_final() - Finish computing a POLYVAL value
  * @ctx: The context to finalize
  * @out: The output value
  *
@@ -149,10 +225,29 @@ void polyval_update(struct polyval_ctx *ctx, const u8 *data, size_t len);
  *
  * Context: Any context.
  */
 void polyval_final(struct polyval_ctx *ctx, u8 out[POLYVAL_BLOCK_SIZE]);
 
+/**
+ * ghash() - Compute a GHASH value
+ * @key: The prepared key
+ * @data: The message data
+ * @len: The data length in bytes.  Doesn't need to be block-aligned.
+ * @out: The output value
+ *
+ * Context: Any context.
+ */
+static inline void ghash(const struct ghash_key *key, const u8 *data,
+			 size_t len, u8 out[GHASH_BLOCK_SIZE])
+{
+	struct ghash_ctx ctx;
+
+	ghash_init(&ctx, key);
+	ghash_update(&ctx, data, len);
+	ghash_final(&ctx, out);
+}
+
 /**
  * polyval() - Compute a POLYVAL value
  * @key: The prepared key
  * @data: The message data
  * @len: The data length in bytes.  Doesn't need to be block-aligned.
lib/crypto/gf128hash.c +132 -13

193 lines not on this page · raw message

Signature · 1 line
2.53.0
author maintainer
#4 lore raw

PATCH 4/19 lib/crypto: tests: Add KUnit tests for GHASH

In reply to Eric Biggers

Add a KUnit test suite for the GHASH library functions.

It closely mirrors the POLYVAL test suite.

---
 lib/crypto/.kunitconfig             |   1 +
 lib/crypto/tests/Kconfig            |   8 ++
 lib/crypto/tests/Makefile           |   1 +
 lib/crypto/tests/ghash-testvecs.h   | 186 ++++++++++++++++++++++++++
 lib/crypto/tests/ghash_kunit.c      | 194 ++++++++++++++++++++++++++++
 scripts/crypto/gen-hash-testvecs.py |  63 ++++++++-
 6 files changed, 452 insertions(+), 1 deletion(-)
 create mode 100644 lib/crypto/tests/ghash-testvecs.h
 create mode 100644 lib/crypto/tests/ghash_kunit.c
lib/crypto/.kunitconfig +1 -0
index 63a592731d1d..391836511c8b 100644
@@ -4,10 +4,11 @@ CONFIG_CRYPTO_LIB_ENABLE_ALL_FOR_KUNIT=y
 
 CONFIG_CRYPTO_LIB_AES_CBC_MACS_KUNIT_TEST=y
 CONFIG_CRYPTO_LIB_BLAKE2B_KUNIT_TEST=y
 CONFIG_CRYPTO_LIB_BLAKE2S_KUNIT_TEST=y
 CONFIG_CRYPTO_LIB_CURVE25519_KUNIT_TEST=y
+CONFIG_CRYPTO_LIB_GHASH_KUNIT_TEST=y
 CONFIG_CRYPTO_LIB_MD5_KUNIT_TEST=y
 CONFIG_CRYPTO_LIB_MLDSA_KUNIT_TEST=y
 CONFIG_CRYPTO_LIB_NH_KUNIT_TEST=y
 CONFIG_CRYPTO_LIB_POLY1305_KUNIT_TEST=y
 CONFIG_CRYPTO_LIB_POLYVAL_KUNIT_TEST=y
lib/crypto/tests/Kconfig +8 -0
index aa627b6b9855..279ff1a339be 100644
@@ -33,10 +33,18 @@ config CRYPTO_LIB_CURVE25519_KUNIT_TEST
 	default KUNIT_ALL_TESTS
 	select CRYPTO_LIB_BENCHMARK_VISIBLE
 	help
 	  KUnit tests for the Curve25519 Diffie-Hellman function.
 
+config CRYPTO_LIB_GHASH_KUNIT_TEST
+	tristate "KUnit tests for GHASH" if !KUNIT_ALL_TESTS
+	depends on KUNIT && CRYPTO_LIB_GF128HASH
+	default KUNIT_ALL_TESTS
+	select CRYPTO_LIB_BENCHMARK_VISIBLE
+	help
+	  KUnit tests for GHASH library functions.
+
 config CRYPTO_LIB_MD5_KUNIT_TEST
 	tristate "KUnit tests for MD5" if !KUNIT_ALL_TESTS
 	depends on KUNIT && CRYPTO_LIB_MD5
 	default KUNIT_ALL_TESTS
 	select CRYPTO_LIB_BENCHMARK_VISIBLE
lib/crypto/tests/Makefile +1 -0
index f864e0ffbee4..751ae507fdd0 100644
@@ -2,10 +2,11 @@
 
 obj-$(CONFIG_CRYPTO_LIB_AES_CBC_MACS_KUNIT_TEST) += aes_cbc_macs_kunit.o
 obj-$(CONFIG_CRYPTO_LIB_BLAKE2B_KUNIT_TEST) += blake2b_kunit.o
 obj-$(CONFIG_CRYPTO_LIB_BLAKE2S_KUNIT_TEST) += blake2s_kunit.o
 obj-$(CONFIG_CRYPTO_LIB_CURVE25519_KUNIT_TEST) += curve25519_kunit.o
+obj-$(CONFIG_CRYPTO_LIB_GHASH_KUNIT_TEST) += ghash_kunit.o
 obj-$(CONFIG_CRYPTO_LIB_MD5_KUNIT_TEST) += md5_kunit.o
 obj-$(CONFIG_CRYPTO_LIB_MLDSA_KUNIT_TEST) += mldsa_kunit.o
 obj-$(CONFIG_CRYPTO_LIB_NH_KUNIT_TEST) += nh_kunit.o
 obj-$(CONFIG_CRYPTO_LIB_POLY1305_KUNIT_TEST) += poly1305_kunit.o
 obj-$(CONFIG_CRYPTO_LIB_POLYVAL_KUNIT_TEST) += polyval_kunit.o
lib/crypto/tests/ghash-testvecs.h new file +186 -0

186 lines not on this page · raw message

lib/crypto/tests/ghash_kunit.c new file +194 -0

194 lines not on this page · raw message

scripts/crypto/gen-hash-testvecs.py +62 -1

113 lines not on this page · raw message

Signature · 1 line
2.53.0
author maintainer
#5 lore raw

PATCH 5/19 crypto: arm/ghash - Make the "ghash" crypto_shash NEON-only

In reply to Eric Biggers

arch/arm/crypto/ghash-ce-glue.c originally provided only a "ghash" crypto_shash algorithm using PMULL if available, else NEON.

Significantly later, it was updated to also provide a full AES-GCM implementation using PMULL.

This made the PMULL support in the "ghash" crypto_shash largely obsolete. Indeed, the arm64 equivalent of this file unconditionally uses only ASIMD in its "ghash" crypto_shash.

Given that inconsistency and the fact that the NEON-only code is more easily separable into the GHASH library than the PMULL based code is, let's align with arm64 and just support NEON-only for the pure GHASH.

---
 arch/arm/crypto/ghash-ce-glue.c | 32 ++++++--------------------------
 1 file changed, 6 insertions(+), 26 deletions(-)
arch/arm/crypto/ghash-ce-glue.c +6 -26
index 454adcc62cc6..d7d787de7dd3 100644
@@ -34,11 +34,11 @@ MODULE_ALIAS_CRYPTO("rfc4106(gcm(aes))");
 
 #define RFC4106_NONCE_SIZE	4
 
 struct ghash_key {
 	be128	k;
-	u64	h[][2];
+	u64	h[1][2];
 };
 
 struct gcm_key {
 	u64	h[4][2];
 	u32	rk[AES_MAX_KEYLENGTH_U32];
@@ -49,16 +49,14 @@ struct gcm_key {
 struct arm_ghash_desc_ctx {
 	u64 digest[GHASH_DIGEST_SIZE/sizeof(u64)];
 };
 
 asmlinkage void pmull_ghash_update_p64(int blocks, u64 dg[], const char *src,
-				       u64 const h[][2], const char *head);
+				       u64 const h[4][2], const char *head);
 
 asmlinkage void pmull_ghash_update_p8(int blocks, u64 dg[], const char *src,
-				      u64 const h[][2], const char *head);
-
-static __ro_after_init DEFINE_STATIC_KEY_FALSE(use_p64);
+				      u64 const h[1][2], const char *head);
 
 static int ghash_init(struct shash_desc *desc)
 {
 	struct arm_ghash_desc_ctx *ctx = shash_desc_ctx(desc);
 
@@ -68,14 +66,11 @@ static int ghash_init(struct shash_desc *desc)
 
 static void ghash_do_update(int blocks, u64 dg[], const char *src,
 			    struct ghash_key *key, const char *head)
 {
 	kernel_neon_begin();
-	if (static_branch_likely(&use_p64))
-		pmull_ghash_update_p64(blocks, dg, src, key->h, head);
-	else
-		pmull_ghash_update_p8(blocks, dg, src, key->h, head);
+	pmull_ghash_update_p8(blocks, dg, src, key->h, head);
 	kernel_neon_end();
 }
 
 static int ghash_update(struct shash_desc *desc, const u8 *src,
 			unsigned int len)
@@ -145,23 +140,10 @@ static int ghash_setkey(struct crypto_shash *tfm,
 		return -EINVAL;
 
 	/* needed for the fallback */
 	memcpy(&key->k, inkey, GHASH_BLOCK_SIZE);
 	ghash_reflect(key->h[0], &key->k);
-
-	if (static_branch_likely(&use_p64)) {
-		be128 h = key->k;
-
-		gf128mul_lle(&h, &key->k);
-		ghash_reflect(key->h[1], &h);
-
-		gf128mul_lle(&h, &key->k);
-		ghash_reflect(key->h[2], &h);
-
-		gf128mul_lle(&h, &key->k);
-		ghash_reflect(key->h[3], &h);
-	}
 	return 0;
 }
 
 static struct shash_alg ghash_alg = {
 	.digestsize		= GHASH_DIGEST_SIZE,
@@ -173,15 +155,15 @@ static struct shash_alg ghash_alg = {
 	.import			= ghash_import,
 	.descsize		= sizeof(struct arm_ghash_desc_ctx),
 	.statesize		= sizeof(struct ghash_desc_ctx),
 
 	.base.cra_name		= "ghash",
-	.base.cra_driver_name	= "ghash-ce",
+	.base.cra_driver_name	= "ghash-neon",
 	.base.cra_priority	= 300,
 	.base.cra_flags		= CRYPTO_AHASH_ALG_BLOCK_ONLY,
 	.base.cra_blocksize	= GHASH_BLOCK_SIZE,
-	.base.cra_ctxsize	= sizeof(struct ghash_key) + sizeof(u64[2]),
+	.base.cra_ctxsize	= sizeof(struct ghash_key),
 	.base.cra_module	= THIS_MODULE,
 };
 
 void pmull_gcm_encrypt(int blocks, u64 dg[], const char *src,
 		       struct gcm_key const *k, char *dst,
@@ -569,12 +551,10 @@ static int __init ghash_ce_mod_init(void)
 	if (elf_hwcap2 & HWCAP2_PMULL) {
 		err = crypto_register_aeads(gcm_aes_algs,
 					    ARRAY_SIZE(gcm_aes_algs));
 		if (err)
 			return err;
-		ghash_alg.base.cra_ctxsize += 3 * sizeof(u64[2]);
-		static_branch_enable(&use_p64);
 	}
 
 	err = crypto_register_shash(&ghash_alg);
 	if (err)
 		goto err_aead;
Signature · 1 line
2.53.0
author maintainer
#6 lore raw

PATCH 6/19 crypto: arm/ghash - Move NEON GHASH assembly into its own file

In reply to Eric Biggers

arch/arm/crypto/ghash-ce-core.S implements pmull_ghash_update_p8(), which is used only by a crypto_shash implementation of GHASH. It also implements other functions, including pmull_ghash_update_p64() and others, which are used only by a crypto_aead implementation of AES-GCM.

While some code is shared between pmull_ghash_update_p8() and pmull_ghash_update_p64(), it's not very much. Since pmull_ghash_update_p8() will also need to be migrated into lib/crypto/ to achieve parity in the standalone GHASH support, let's move it into a separate file ghash-neon-core.S.

---
 arch/arm/crypto/Makefile          |   2 +-
 arch/arm/crypto/ghash-ce-core.S   | 171 ++----------------------
 arch/arm/crypto/ghash-neon-core.S | 207 ++++++++++++++++++++++++++++++
 3 files changed, 222 insertions(+), 158 deletions(-)
 create mode 100644 arch/arm/crypto/ghash-neon-core.S
arch/arm/crypto/Makefile +1 -1
index e73099e120b3..cedce94d5ee5 100644
@@ -8,6 +8,6 @@ obj-$(CONFIG_CRYPTO_AES_ARM_BS) += aes-arm-bs.o
 obj-$(CONFIG_CRYPTO_AES_ARM_CE) += aes-arm-ce.o
 obj-$(CONFIG_CRYPTO_GHASH_ARM_CE) += ghash-arm-ce.o
 
 aes-arm-bs-y	:= aes-neonbs-core.o aes-neonbs-glue.o
 aes-arm-ce-y	:= aes-ce-core.o aes-ce-glue.o
-ghash-arm-ce-y	:= ghash-ce-core.o ghash-ce-glue.o
+ghash-arm-ce-y	:= ghash-ce-core.o ghash-ce-glue.o ghash-neon-core.o
arch/arm/crypto/ghash-ce-core.S +14 -157

310 lines not on this page · raw message

arch/arm/crypto/ghash-neon-core.S new file +207 -0

207 lines not on this page · raw message

Signature · 1 line
2.53.0
author maintainer
#7 lore raw

PATCH 7/19 lib/crypto: arm/ghash: Migrate optimized code into library

In reply to Eric Biggers

Remove the "ghash-neon" crypto_shash algorithm. Move the corresponding assembly code into lib/crypto/, and wire it up to the GHASH library.

This makes the GHASH library be optimized on arm (though only with NEON, not PMULL; for now the goal is just parity with crypto_shash). It greatly reduces the amount of arm-specific glue code that is needed, and it fixes the issue where this optimization was disabled by default.

To integrate the assembly code correctly with the library, make the following tweaks:

- Change the type of 'blocks' from int to size_t.
- Change the types of 'dg' and 'k' to polyval_elem. Note that this simply reflects the format that the code was already using, at least on little endian CPUs. For big endian CPUs, add byte-swaps.
- Remove the 'head' argument, which is no longer needed.

---
 arch/arm/crypto/Kconfig                       |  13 +-
 arch/arm/crypto/Makefile                      |   2 +-
 arch/arm/crypto/ghash-ce-glue.c               | 144 +-----------------
 lib/crypto/Kconfig                            |   1 +
 lib/crypto/Makefile                           |   1 +
 lib/crypto/arm/gf128hash.h                    |  43 ++++++
 .../crypto/arm}/ghash-neon-core.S             |  24 +--
 7 files changed, 66 insertions(+), 162 deletions(-)
 create mode 100644 lib/crypto/arm/gf128hash.h
 rename {arch/arm/crypto => lib/crypto/arm}/ghash-neon-core.S (92%)
arch/arm/crypto/Kconfig +2 -11
index b9c28c818b7c..f884b8b2fd93 100644
@@ -1,30 +1,21 @@
 # SPDX-License-Identifier: GPL-2.0
 
 menu "Accelerated Cryptographic Algorithms for CPU (arm)"
 
 config CRYPTO_GHASH_ARM_CE
-	tristate "Hash functions: GHASH (PMULL/NEON/ARMv8 Crypto Extensions)"
+	tristate "AEAD cipher: AES in GCM mode (ARMv8 Crypto Extensions)"
 	depends on KERNEL_MODE_NEON
 	select CRYPTO_AEAD
-	select CRYPTO_HASH
-	select CRYPTO_CRYPTD
 	select CRYPTO_LIB_AES
 	select CRYPTO_LIB_GF128MUL
 	help
-	  GCM GHASH function (NIST SP800-38D)
+	  AEAD cipher: AES-GCM
 
 	  Architecture: arm using
-	  - PMULL (Polynomial Multiply Long) instructions
-	  - NEON (Advanced SIMD) extensions
 	  - ARMv8 Crypto Extensions
 
-	  Use an implementation of GHASH (used by the GCM AEAD chaining mode)
-	  that uses the 64x64 to 128 bit polynomial multiplication (vmull.p64)
-	  that is part of the ARMv8 Crypto Extensions, or a slower variant that
-	  uses the vmull.p8 instruction that is part of the basic NEON ISA.
-
 config CRYPTO_AES_ARM_BS
 	tristate "Ciphers: AES, modes: ECB/CBC/CTR/XTS (bit-sliced NEON)"
 	depends on KERNEL_MODE_NEON
 	select CRYPTO_SKCIPHER
 	select CRYPTO_LIB_AES
arch/arm/crypto/Makefile +1 -1
index cedce94d5ee5..e73099e120b3 100644
@@ -8,6 +8,6 @@ obj-$(CONFIG_CRYPTO_AES_ARM_BS) += aes-arm-bs.o
 obj-$(CONFIG_CRYPTO_AES_ARM_CE) += aes-arm-ce.o
 obj-$(CONFIG_CRYPTO_GHASH_ARM_CE) += ghash-arm-ce.o
 
 aes-arm-bs-y	:= aes-neonbs-core.o aes-neonbs-glue.o
 aes-arm-ce-y	:= aes-ce-core.o aes-ce-glue.o
-ghash-arm-ce-y	:= ghash-ce-core.o ghash-ce-glue.o ghash-neon-core.o
+ghash-arm-ce-y	:= ghash-ce-core.o ghash-ce-glue.o
arch/arm/crypto/ghash-ce-glue.c +5 -139

213 lines not on this page · raw message

lib/crypto/Kconfig +1 -0
index 98cedd95c2a5..4f1a79883a56 100644
@@ -117,10 +117,11 @@ config CRYPTO_LIB_GF128HASH
 	  uses any of the functions from <crypto/gf128hash.h>.
 
 config CRYPTO_LIB_GF128HASH_ARCH
 	bool
 	depends on CRYPTO_LIB_GF128HASH && !UML
+	default y if ARM && KERNEL_MODE_NEON
 	default y if ARM64
 	default y if X86_64
 
 config CRYPTO_LIB_MD5
 	tristate
lib/crypto/Makefile +1 -0
index fc30622123d2..8a06dd6a43ea 100644
@@ -156,10 +156,11 @@ libdes-y					:= des.o
 
 obj-$(CONFIG_CRYPTO_LIB_GF128HASH) += libgf128hash.o
 libgf128hash-y := gf128hash.o
 ifeq ($(CONFIG_CRYPTO_LIB_GF128HASH_ARCH),y)
 CFLAGS_gf128hash.o += -I$(src)/$(SRCARCH)
+libgf128hash-$(CONFIG_ARM) += arm/ghash-neon-core.o
 libgf128hash-$(CONFIG_ARM64) += arm64/polyval-ce-core.o
 libgf128hash-$(CONFIG_X86) += x86/polyval-pclmul-avx.o
 endif
 
 ################################################################################
lib/crypto/arm/gf128hash.h new file +43 -0

43 lines not on this page · raw message

lib/crypto/arm/ghash-neon-core.S renamed from arch/arm/crypto/ghash-neon-core.S +13 -11
similarity index 92%
rename from arch/arm/crypto/ghash-neon-core.S
rename to lib/crypto/arm/ghash-neon-core.S
index bdf6fb6d063c..bf423fb06a75 100644
@@ -139,26 +139,25 @@
 	veor		XL, XL, T1
 	vshr.u64	T1, T1, #6
 	vshr.u64	XL, XL, #1
 	.endm
 
+	.macro		vrev64_if_be	a
+#ifdef CONFIG_CPU_BIG_ENDIAN
+	vrev64.8	\a, \a
+#endif
+	.endm
+
 	.macro		ghash_update
 	vld1.64		{XL}, [r1]
-
-	/* do the head block first, if supplied */
-	ldr		ip, [sp]
-	teq		ip, #0
-	beq		0f
-	vld1.64		{T1}, [ip]
-	teq		r0, #0
-	b		3f
+	vrev64_if_be	XL
 
 0:
 	vld1.8		{T1}, [r2]!
 	subs		r0, r0, #1
 
-3:	/* multiply XL by SHASH in GF(2^128) */
+	/* multiply XL by SHASH in GF(2^128) */
 	vrev64.8	T1, T1
 
 	vext.8		IN1, T1, T1, #8
 	veor		T1_L, T1_L, XL_H
 	veor		XL, XL, IN1
@@ -178,15 +177,17 @@
 
 	bne		0b
 	.endm
 
 	/*
-	 * void pmull_ghash_update_p8(int blocks, u64 dg[], const char *src,
-	 *			      u64 const h[1][2], const char *head)
+	 * void pmull_ghash_update_p8(size_t blocks, struct polyval_elem *dg,
+	 *			      const u8 *src,
+	 *			      const struct polyval_elem *k)
 	 */
 ENTRY(pmull_ghash_update_p8)
 	vld1.64		{SHASH}, [r3]
+	vrev64_if_be	SHASH
 	veor		SHASH2_p8, SHASH_L, SHASH_H
 
 	vext.8		s1l, SHASH_L, SHASH_L, #1
 	vext.8		s2l, SHASH_L, SHASH_L, #2
 	vext.8		s3l, SHASH_L, SHASH_L, #3
@@ -199,9 +200,10 @@ ENTRY(pmull_ghash_update_p8)
 	vmov.i64	k16, #0xffff
 	vmov.i64	k32, #0xffffffff
 	vmov.i64	k48, #0xffffffffffff
 
 	ghash_update
+	vrev64_if_be	XL
 	vst1.64		{XL}, [r1]
 
 	bx		lr
 ENDPROC(pmull_ghash_update_p8)
Signature · 1 line
2.53.0
author maintainer
#8 lore raw

PATCH 8/19 crypto: arm64/ghash - Move NEON GHASH assembly into its own file

In reply to Eric Biggers

arch/arm64/crypto/ghash-ce-core.S implements pmull_ghash_update_p8(), which is used only by a crypto_shash implementation of GHASH. It also implements other functions, including pmull_ghash_update_p64() and others, which are used only by a crypto_aead implementation of AES-GCM.

While some code is shared between pmull_ghash_update_p8() and pmull_ghash_update_p64(), it's not very much. Since pmull_ghash_update_p8() will also need to be migrated into lib/crypto/ to achieve parity in the standalone GHASH support, let's move it into a separate file ghash-neon-core.S.

---
 arch/arm64/crypto/Makefile          |   2 +-
 arch/arm64/crypto/ghash-ce-core.S   | 207 ++-----------------------
 arch/arm64/crypto/ghash-neon-core.S | 226 ++++++++++++++++++++++++++++
 3 files changed, 239 insertions(+), 196 deletions(-)
 create mode 100644 arch/arm64/crypto/ghash-neon-core.S
arch/arm64/crypto/Makefile +1 -1
index 8a8e3e551ed3..b7ba43ce8584 100644
@@ -25,11 +25,11 @@ sm4-ce-gcm-y := sm4-ce-gcm-glue.o sm4-ce-gcm-core.o
 
 obj-$(CONFIG_CRYPTO_SM4_ARM64_NEON_BLK) += sm4-neon.o
 sm4-neon-y := sm4-neon-glue.o sm4-neon-core.o
 
 obj-$(CONFIG_CRYPTO_GHASH_ARM64_CE) += ghash-ce.o
-ghash-ce-y := ghash-ce-glue.o ghash-ce-core.o
+ghash-ce-y := ghash-ce-glue.o ghash-ce-core.o ghash-neon-core.o
 
 obj-$(CONFIG_CRYPTO_AES_ARM64_CE_CCM) += aes-ce-ccm.o
 aes-ce-ccm-y := aes-ce-ccm-glue.o aes-ce-ccm-core.o
 
 obj-$(CONFIG_CRYPTO_AES_ARM64_CE_BLK) += aes-ce-blk.o
arch/arm64/crypto/ghash-ce-core.S +12 -195

300 lines not on this page · raw message

arch/arm64/crypto/ghash-neon-core.S new file +226 -0

226 lines not on this page · raw message

Signature · 1 line
2.53.0
author maintainer
#9 lore raw

PATCH 9/19 lib/crypto: arm64/ghash: Migrate optimized code into library

In reply to Eric Biggers

Remove the "ghash-neon" crypto_shash algorithm. Move the corresponding assembly code into lib/crypto/, and wire it up to the GHASH library.

This makes the GHASH library be optimized on arm64 (though only with NEON, not PMULL; for now the goal is just parity with crypto_shash). It greatly reduces the amount of arm64-specific glue code that is needed, and it fixes the issue where this optimization was disabled by default.

To integrate the assembly code correctly with the library, make the following tweaks:

- Change the type of 'blocks' from int to size_t
- Change the types of 'dg' and 'k' to polyval_elem. Note that this simply reflects the format that the code was already using.
- Remove the 'head' argument, which is no longer needed.
- Remove the CFI stubs, as indirect calls are no longer used.

---
 arch/arm64/crypto/Kconfig                     |   5 +-
 arch/arm64/crypto/Makefile                    |   2 +-
 arch/arm64/crypto/ghash-ce-core.S             |   3 +-
 arch/arm64/crypto/ghash-ce-glue.c             | 146 ++----------------
 lib/crypto/Makefile                           |   3 +-
 lib/crypto/arm64/gf128hash.h                  |  68 +++++++-
 .../crypto/arm64}/ghash-neon-core.S           |  20 +--
 7 files changed, 86 insertions(+), 161 deletions(-)
 rename {arch/arm64/crypto => lib/crypto/arm64}/ghash-neon-core.S (93%)
arch/arm64/crypto/Kconfig +2 -3
index 82794afaffc9..1a0c553fbfd7 100644
@@ -1,18 +1,17 @@
 # SPDX-License-Identifier: GPL-2.0
 
 menu "Accelerated Cryptographic Algorithms for CPU (arm64)"
 
 config CRYPTO_GHASH_ARM64_CE
-	tristate "Hash functions: GHASH (ARMv8 Crypto Extensions)"
+	tristate "AEAD cipher: AES in GCM mode (ARMv8 Crypto Extensions)"
 	depends on KERNEL_MODE_NEON
-	select CRYPTO_HASH
 	select CRYPTO_LIB_AES
 	select CRYPTO_LIB_GF128MUL
 	select CRYPTO_AEAD
 	help
-	  GCM GHASH function (NIST SP800-38D)
+	  AEAD cipher: AES-GCM
 
 	  Architecture: arm64 using:
 	  - ARMv8 Crypto Extensions
 
 config CRYPTO_SM3_NEON
arch/arm64/crypto/Makefile +1 -1
index b7ba43ce8584..8a8e3e551ed3 100644
@@ -25,11 +25,11 @@ sm4-ce-gcm-y := sm4-ce-gcm-glue.o sm4-ce-gcm-core.o
 
 obj-$(CONFIG_CRYPTO_SM4_ARM64_NEON_BLK) += sm4-neon.o
 sm4-neon-y := sm4-neon-glue.o sm4-neon-core.o
 
 obj-$(CONFIG_CRYPTO_GHASH_ARM64_CE) += ghash-ce.o
-ghash-ce-y := ghash-ce-glue.o ghash-ce-core.o ghash-neon-core.o
+ghash-ce-y := ghash-ce-glue.o ghash-ce-core.o
 
 obj-$(CONFIG_CRYPTO_AES_ARM64_CE_CCM) += aes-ce-ccm.o
 aes-ce-ccm-y := aes-ce-ccm-glue.o aes-ce-ccm-core.o
 
 obj-$(CONFIG_CRYPTO_AES_ARM64_CE_BLK) += aes-ce-blk.o
arch/arm64/crypto/ghash-ce-core.S +1 -2
index 4344fe213d14..a01f136f4fb2 100644
@@ -4,11 +4,10 @@
  *
  * Copyright (C) 2014 - 2018 Linaro Ltd. <[email protected]>
  */
 
 #include <linux/linkage.h>
-#include <linux/cfi_types.h>
 #include <asm/assembler.h>
 
 	SHASH		.req	v0
 	SHASH2		.req	v1
 	T1		.req	v2
@@ -65,11 +64,11 @@
 
 	/*
 	 * void pmull_ghash_update_p64(int blocks, u64 dg[], const char *src,
 	 *			       u64 const h[][2], const char *head)
 	 */
-SYM_TYPED_FUNC_START(pmull_ghash_update_p64)
+SYM_FUNC_START(pmull_ghash_update_p64)
 	ld1		{SHASH.2d}, [x3]
 	ld1		{XL.2d}, [x1]
 
 	__pmull_pre_p64
 
arch/arm64/crypto/ghash-ce-glue.c +12 -134

241 lines not on this page · raw message

lib/crypto/Makefile +2 -1
index 8a06dd6a43ea..4ce0bac8fd93 100644
@@ -157,11 +157,12 @@ libdes-y					:= des.o
 obj-$(CONFIG_CRYPTO_LIB_GF128HASH) += libgf128hash.o
 libgf128hash-y := gf128hash.o
 ifeq ($(CONFIG_CRYPTO_LIB_GF128HASH_ARCH),y)
 CFLAGS_gf128hash.o += -I$(src)/$(SRCARCH)
 libgf128hash-$(CONFIG_ARM) += arm/ghash-neon-core.o
-libgf128hash-$(CONFIG_ARM64) += arm64/polyval-ce-core.o
+libgf128hash-$(CONFIG_ARM64) += arm64/ghash-neon-core.o \
+				arm64/polyval-ce-core.o
 libgf128hash-$(CONFIG_X86) += x86/polyval-pclmul-avx.o
 endif
 
 ################################################################################
 
lib/crypto/arm64/gf128hash.h +61 -7

111 lines not on this page · raw message

lib/crypto/arm64/ghash-neon-core.S renamed from arch/arm64/crypto/ghash-neon-core.S +7 -13
similarity index 93%
rename from arch/arm64/crypto/ghash-neon-core.S
rename to lib/crypto/arm64/ghash-neon-core.S
index 6157135ad566..eadd6da47247 100644
@@ -4,11 +4,10 @@
  *
  * Copyright (C) 2014 - 2018 Linaro Ltd. <[email protected]>
  */
 
 #include <linux/linkage.h>
-#include <linux/cfi_types.h>
 #include <asm/assembler.h>
 
 	SHASH		.req	v0
 	SHASH2		.req	v1
 	T1		.req	v2
@@ -177,29 +176,24 @@
 	ushr		T2.2d, T2.2d, #6
 	ushr		XL.2d, XL.2d, #1
 	.endm
 
 	/*
-	 * void pmull_ghash_update_p8(int blocks, u64 dg[], const char *src,
-	 *			      u64 const h[][2], const char *head)
+	 * void pmull_ghash_update_p8(size_t blocks, struct polyval_elem *dg,
+	 *			      const u8 *src,
+	 *			      const struct polyval_elem *k)
 	 */
-SYM_TYPED_FUNC_START(pmull_ghash_update_p8)
+SYM_FUNC_START(pmull_ghash_update_p8)
 	ld1		{SHASH.2d}, [x3]
 	ld1		{XL.2d}, [x1]
 
 	__pmull_pre_p8
 
-	/* do the head block first, if supplied */
-	cbz		x4, 0f
-	ld1		{T1.2d}, [x4]
-	mov		x4, xzr
-	b		3f
-
 0:	ld1		{T1.2d}, [x2], #16
-	sub		w0, w0, #1
+	sub		x0, x0, #1
 
-3:	/* multiply XL by SHASH in GF(2^128) */
+	/* multiply XL by SHASH in GF(2^128) */
 CPU_LE(	rev64		T1.16b, T1.16b	)
 
 	ext		T2.16b, XL.16b, XL.16b, #8
 	ext		IN1.16b, T1.16b, T1.16b, #8
 	eor		T1.16b, T1.16b, T2.16b
@@ -217,10 +211,10 @@ CPU_LE(	rev64		T1.16b, T1.16b	)
 	__pmull_reduce_p8
 
 	eor		T2.16b, T2.16b, XH.16b
 	eor		XL.16b, XL.16b, T2.16b
 
-	cbnz		w0, 0b
+	cbnz		x0, 0b
 
 	st1		{XL.2d}, [x1]
 	ret
 SYM_FUNC_END(pmull_ghash_update_p8)
Signature · 1 line
2.53.0
author maintainer
#10 lore raw

PATCH 10/19 crypto: arm64/aes-gcm - Rename struct ghash_key and make fixed-sized

In reply to Eric Biggers

Rename the 'struct ghash_key' in arch/arm64/crypto/ghash-ce-glue.c to prevent a naming conflict with the library 'struct ghash_key'. In addition, declare the 'h' field with an explicit size, now that there's no longer any reason for it to be a flexible array.

Update the comments in the assembly file to match the C code. Note that some of these were out-of-date.

---
 arch/arm64/crypto/ghash-ce-core.S | 15 ++++++++-------
 arch/arm64/crypto/ghash-ce-glue.c | 20 +++++++++-----------
 2 files changed, 17 insertions(+), 18 deletions(-)
arch/arm64/crypto/ghash-ce-core.S +8 -7
index a01f136f4fb2..33772d8fe6b5 100644
@@ -62,11 +62,11 @@
 	pmull		XL.1q, XL.1d, MASK.1d
 	.endm
 
 	/*
 	 * void pmull_ghash_update_p64(int blocks, u64 dg[], const char *src,
-	 *			       u64 const h[][2], const char *head)
+	 *			       u64 const h[4][2], const char *head)
 	 */
 SYM_FUNC_START(pmull_ghash_update_p64)
 	ld1		{SHASH.2d}, [x3]
 	ld1		{XL.2d}, [x1]
 
@@ -411,22 +411,23 @@ CPU_LE(	rev		w8, w8		)
 	.endif
 	b		3b
 	.endm
 
 	/*
-	 * void pmull_gcm_encrypt(int blocks, u8 dst[], const u8 src[],
-	 *			  struct ghash_key const *k, u64 dg[], u8 ctr[],
-	 *			  int rounds, u8 tag)
+	 * void pmull_gcm_encrypt(int bytes, u8 dst[], const u8 src[],
+	 *			  u64 const h[4][2], u64 dg[], u8 ctr[],
+	 *			  u32 const rk[], int rounds, u8 tag[])
 	 */
 SYM_FUNC_START(pmull_gcm_encrypt)
 	pmull_gcm_do_crypt	1
 SYM_FUNC_END(pmull_gcm_encrypt)
 
 	/*
-	 * void pmull_gcm_decrypt(int blocks, u8 dst[], const u8 src[],
-	 *			  struct ghash_key const *k, u64 dg[], u8 ctr[],
-	 *			  int rounds, u8 tag)
+	 * int pmull_gcm_decrypt(int bytes, u8 dst[], const u8 src[],
+	 *			 u64 const h[4][2], u64 dg[], u8 ctr[],
+	 *			 u32 const rk[], int rounds, const u8 l[],
+	 *			 const u8 tag[], u64 authsize)
 	 */
 SYM_FUNC_START(pmull_gcm_decrypt)
 	pmull_gcm_do_crypt	0
 SYM_FUNC_END(pmull_gcm_decrypt)
 
arch/arm64/crypto/ghash-ce-glue.c +9 -11
index 42fb46bdc124..c74066d430fa 100644
@@ -28,38 +28,38 @@ MODULE_LICENSE("GPL v2");
 MODULE_ALIAS_CRYPTO("gcm(aes)");
 MODULE_ALIAS_CRYPTO("rfc4106(gcm(aes))");
 
 #define RFC4106_NONCE_SIZE	4
 
-struct ghash_key {
+struct arm_ghash_key {
 	be128			k;
-	u64			h[][2];
+	u64			h[4][2];
 };
 
 struct arm_ghash_desc_ctx {
 	u64 digest[GHASH_DIGEST_SIZE/sizeof(u64)];
 };
 
 struct gcm_aes_ctx {
 	struct aes_enckey	aes_key;
 	u8			nonce[RFC4106_NONCE_SIZE];
-	struct ghash_key	ghash_key;
+	struct arm_ghash_key	ghash_key;
 };
 
 asmlinkage void pmull_ghash_update_p64(int blocks, u64 dg[], const char *src,
-				       u64 const h[][2], const char *head);
+				       u64 const h[4][2], const char *head);
 
 asmlinkage void pmull_gcm_encrypt(int bytes, u8 dst[], const u8 src[],
-				  u64 const h[][2], u64 dg[], u8 ctr[],
+				  u64 const h[4][2], u64 dg[], u8 ctr[],
 				  u32 const rk[], int rounds, u8 tag[]);
 asmlinkage int pmull_gcm_decrypt(int bytes, u8 dst[], const u8 src[],
-				 u64 const h[][2], u64 dg[], u8 ctr[],
+				 u64 const h[4][2], u64 dg[], u8 ctr[],
 				 u32 const rk[], int rounds, const u8 l[],
 				 const u8 tag[], u64 authsize);
 
 static void ghash_do_simd_update(int blocks, u64 dg[], const char *src,
-				 struct ghash_key *key, const char *head)
+				 struct arm_ghash_key *key, const char *head)
 {
 	scoped_ksimd()
 		pmull_ghash_update_p64(blocks, dg, src, key->h, head);
 }
 
@@ -365,12 +365,11 @@ static struct aead_alg gcm_aes_algs[] = {{
 
 	.base.cra_name		= "gcm(aes)",
 	.base.cra_driver_name	= "gcm-aes-ce",
 	.base.cra_priority	= 300,
 	.base.cra_blocksize	= 1,
-	.base.cra_ctxsize	= sizeof(struct gcm_aes_ctx) +
-				  4 * sizeof(u64[2]),
+	.base.cra_ctxsize	= sizeof(struct gcm_aes_ctx),
 	.base.cra_module	= THIS_MODULE,
 }, {
 	.ivsize			= GCM_RFC4106_IV_SIZE,
 	.chunksize		= AES_BLOCK_SIZE,
 	.maxauthsize		= AES_BLOCK_SIZE,
@@ -381,12 +380,11 @@ static struct aead_alg gcm_aes_algs[] = {{
 
 	.base.cra_name		= "rfc4106(gcm(aes))",
 	.base.cra_driver_name	= "rfc4106-gcm-aes-ce",
 	.base.cra_priority	= 300,
 	.base.cra_blocksize	= 1,
-	.base.cra_ctxsize	= sizeof(struct gcm_aes_ctx) +
-				  4 * sizeof(u64[2]),
+	.base.cra_ctxsize	= sizeof(struct gcm_aes_ctx),
 	.base.cra_module	= THIS_MODULE,
 }};
 
 static int __init ghash_ce_mod_init(void)
 {
Signature · 1 line
2.53.0
author maintainer
#11 lore raw

PATCH 11/19 lib/crypto: powerpc/ghash: Migrate optimized code into library

In reply to Eric Biggers

Remove the "p8_ghash" crypto_shash algorithm. Move the corresponding assembly code into lib/crypto/, and wire it up to the GHASH library.

This makes the GHASH library be optimized for POWER8. It also greatly reduces the amount of powerpc-specific glue code that is needed, and it fixes the issue where this optimized GHASH code was disabled by default.

Note that previously the C code defined the POWER8 GHASH key format as "u128 htable[16]", despite the assembly code only using four entries. Fix the C code to use the correct key format. To fulfill the library API contract, also make the key preparation work in all contexts.

Note that the POWER8 assembly code takes the accumulator in GHASH format, but it actually byte-reflects it to get it into POLYVAL format. The library already works with POLYVAL natively. For now, just wire up this existing code by converting it to/from GHASH format in C code. This should be cleaned up to eliminate the unnecessary conversion later.

---
 MAINTAINERS                                   |   4 +-
 arch/powerpc/crypto/Kconfig                   |   5 +-
 arch/powerpc/crypto/Makefile                  |   8 +-
 arch/powerpc/crypto/aesp8-ppc.h               |   1 -
 arch/powerpc/crypto/ghash.c                   | 160 ------------------
 arch/powerpc/crypto/vmx.c                     |  10 +-
 include/crypto/gf128hash.h                    |   4 +
 lib/crypto/Kconfig                            |   1 +
 lib/crypto/Makefile                           |  25 ++-
 lib/crypto/powerpc/.gitignore                 |   1 +
 lib/crypto/powerpc/gf128hash.h                | 109 ++++++++++++
 .../crypto/powerpc}/ghashp8-ppc.pl            |   1 +
 12 files changed, 143 insertions(+), 186 deletions(-)
 delete mode 100644 arch/powerpc/crypto/ghash.c
 create mode 100644 lib/crypto/powerpc/gf128hash.h
 rename {arch/powerpc/crypto => lib/crypto/powerpc}/ghashp8-ppc.pl (98%)
MAINTAINERS +2 -2
index 77fdfcb55f06..f088f4085653 100644
@@ -12265,14 +12265,14 @@ F:	arch/powerpc/crypto/Makefile
 F:	arch/powerpc/crypto/aes.c
 F:	arch/powerpc/crypto/aes_cbc.c
 F:	arch/powerpc/crypto/aes_ctr.c
 F:	arch/powerpc/crypto/aes_xts.c
 F:	arch/powerpc/crypto/aesp8-ppc.*
-F:	arch/powerpc/crypto/ghash.c
-F:	arch/powerpc/crypto/ghashp8-ppc.pl
 F:	arch/powerpc/crypto/ppc-xlate.pl
 F:	arch/powerpc/crypto/vmx.c
+F:	lib/crypto/powerpc/gf128hash.h
+F:	lib/crypto/powerpc/ghashp8-ppc.pl
 
 IBM ServeRAID RAID DRIVER
 S:	Orphan
 F:	drivers/scsi/ips.*
 
arch/powerpc/crypto/Kconfig +2 -3
index 2d056f1fc90f..b247f7ed973e 100644
@@ -52,14 +52,13 @@ config CRYPTO_DEV_VMX_ENCRYPT
 	tristate "Encryption acceleration support on P8 CPU"
 	depends on CRYPTO_DEV_VMX
 	select CRYPTO_AES
 	select CRYPTO_CBC
 	select CRYPTO_CTR
-	select CRYPTO_GHASH
 	select CRYPTO_XTS
 	default m
 	help
 	  Support for VMX cryptographic acceleration instructions on Power8 CPU.
-	  This module supports acceleration for AES and GHASH in hardware. If you
-	  choose 'M' here, this module will be called vmx-crypto.
+	  This module supports acceleration for AES in hardware. If you choose
+	  'M' here, this module will be called vmx-crypto.
 
 endmenu
arch/powerpc/crypto/Makefile +2 -6
index 3ac0886282a2..a1fe102a90ae 100644
@@ -9,11 +9,11 @@ obj-$(CONFIG_CRYPTO_AES_PPC_SPE) += aes-ppc-spe.o
 obj-$(CONFIG_CRYPTO_AES_GCM_P10) += aes-gcm-p10-crypto.o
 obj-$(CONFIG_CRYPTO_DEV_VMX_ENCRYPT) += vmx-crypto.o
 
 aes-ppc-spe-y := aes-spe-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 ghashp8-ppc.o aes_cbc.o aes_ctr.o aes_xts.o ghash.o
+vmx-crypto-objs := vmx.o aes_cbc.o aes_ctr.o aes_xts.o
 
 ifeq ($(CONFIG_CPU_LITTLE_ENDIAN),y)
 override flavour := linux-ppc64le
 else
 ifdef CONFIG_PPC64_ELF_ABI_V2
@@ -24,16 +24,12 @@ endif
 endif
 
 quiet_cmd_perl = PERL    $@
       cmd_perl = $(PERL) $< $(flavour) > $@
 
-targets += aesp10-ppc.S ghashp10-ppc.S ghashp8-ppc.S
+targets += aesp10-ppc.S ghashp10-ppc.S
 
 $(obj)/aesp10-ppc.S $(obj)/ghashp10-ppc.S: $(obj)/%.S: $(src)/%.pl FORCE
 	$(call if_changed,perl)
 
-$(obj)/ghashp8-ppc.S: $(obj)/%.S: $(src)/%.pl FORCE
-	$(call if_changed,perl)
-
 OBJECT_FILES_NON_STANDARD_aesp10-ppc.o := y
 OBJECT_FILES_NON_STANDARD_ghashp10-ppc.o := y
-OBJECT_FILES_NON_STANDARD_ghashp8-ppc.o := y
arch/powerpc/crypto/aesp8-ppc.h +0 -1
index 6862c605cc33..c68f5b6965fa 100644
@@ -1,8 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 #include <linux/types.h>
 #include <crypto/aes.h>
 
-extern struct shash_alg p8_ghash_alg;
 extern struct skcipher_alg p8_aes_cbc_alg;
 extern struct skcipher_alg p8_aes_ctr_alg;
 extern struct skcipher_alg p8_aes_xts_alg;
arch/powerpc/crypto/ghash.c deleted +0 -160

160 lines not on this page · raw message

arch/powerpc/crypto/vmx.c +1 -9
index 7d2beb774f99..08da5311dfdf 100644
@@ -12,26 +12,21 @@
 #include <linux/types.h>
 #include <linux/err.h>
 #include <linux/cpufeature.h>
 #include <linux/crypto.h>
 #include <asm/cputable.h>
-#include <crypto/internal/hash.h>
 #include <crypto/internal/skcipher.h>
 
 #include "aesp8-ppc.h"
 
 static int __init p8_init(void)
 {
 	int ret;
 
-	ret = crypto_register_shash(&p8_ghash_alg);
-	if (ret)
-		goto err;
-
 	ret = crypto_register_skcipher(&p8_aes_cbc_alg);
 	if (ret)
-		goto err_unregister_ghash;
+		goto err;
 
 	ret = crypto_register_skcipher(&p8_aes_ctr_alg);
 	if (ret)
 		goto err_unregister_aes_cbc;
 
@@ -43,22 +38,19 @@ static int __init p8_init(void)
 
 err_unregister_aes_ctr:
 	crypto_unregister_skcipher(&p8_aes_ctr_alg);
 err_unregister_aes_cbc:
 	crypto_unregister_skcipher(&p8_aes_cbc_alg);
-err_unregister_ghash:
-	crypto_unregister_shash(&p8_ghash_alg);
 err:
 	return ret;
 }
 
 static void __exit p8_exit(void)
 {
 	crypto_unregister_skcipher(&p8_aes_xts_alg);
 	crypto_unregister_skcipher(&p8_aes_ctr_alg);
 	crypto_unregister_skcipher(&p8_aes_cbc_alg);
-	crypto_unregister_shash(&p8_ghash_alg);
 }
 
 module_cpu_feature_match(PPC_MODULE_FEATURE_VEC_CRYPTO, p8_init);
 module_exit(p8_exit);
 
include/crypto/gf128hash.h +4 -0
index 5090fbaa87f8..650652dd6003 100644
@@ -39,10 +39,14 @@ struct polyval_elem {
  * struct ghash_key - Prepared key for GHASH
  *
  * Use ghash_preparekey() to initialize this.
  */
 struct ghash_key {
+#if defined(CONFIG_CRYPTO_LIB_GF128HASH_ARCH) && defined(CONFIG_PPC64)
+	/** @htable: GHASH key format used by the POWER8 assembly code */
+	u64 htable[4][2];
+#endif
 	/** @h: The hash key H, in POLYVAL format */
 	struct polyval_elem h;
 };
 
 /**
lib/crypto/Kconfig +1 -0
index 4f1a79883a56..f54add7d9070 100644
@@ -119,10 +119,11 @@ config CRYPTO_LIB_GF128HASH
 config CRYPTO_LIB_GF128HASH_ARCH
 	bool
 	depends on CRYPTO_LIB_GF128HASH && !UML
 	default y if ARM && KERNEL_MODE_NEON
 	default y if ARM64
+	default y if PPC64 && VSX
 	default y if X86_64
 
 config CRYPTO_LIB_MD5
 	tristate
 	help
lib/crypto/Makefile +20 -5
index 4ce0bac8fd93..8a9084188778 100644
@@ -6,10 +6,14 @@ quiet_cmd_perlasm = PERLASM $@
       cmd_perlasm = $(PERL) $(<) > $(@)
 
 quiet_cmd_perlasm_with_args = PERLASM $@
       cmd_perlasm_with_args = $(PERL) $(<) void $(@)
 
+ppc64-perlasm-flavour-y := linux-ppc64
+ppc64-perlasm-flavour-$(CONFIG_PPC64_ELF_ABI_V2) := linux-ppc64-elfv2
+ppc64-perlasm-flavour-$(CONFIG_CPU_LITTLE_ENDIAN) := linux-ppc64le
+
 obj-$(CONFIG_KUNIT)				+= tests/
 
 obj-$(CONFIG_CRYPTO_HASH_INFO)			+= hash_info.o
 
 obj-$(CONFIG_CRYPTO_LIB_UTILS)			+= libcryptoutils.o
@@ -34,15 +38,12 @@ libaes-y += powerpc/aes-spe-core.o \
 	    powerpc/aes-spe-keys.o \
 	    powerpc/aes-spe-modes.o \
 	    powerpc/aes-tab-4k.o
 else
 libaes-y += powerpc/aesp8-ppc.o
-aes-perlasm-flavour-y := linux-ppc64
-aes-perlasm-flavour-$(CONFIG_PPC64_ELF_ABI_V2) := linux-ppc64-elfv2
-aes-perlasm-flavour-$(CONFIG_CPU_LITTLE_ENDIAN) := linux-ppc64le
 quiet_cmd_perlasm_aes = PERLASM $@
-      cmd_perlasm_aes = $(PERL) $< $(aes-perlasm-flavour-y) $@
+      cmd_perlasm_aes = $(PERL) $< $(ppc64-perlasm-flavour-y) $@
 # Use if_changed instead of cmd, in case the flavour changed.
 $(obj)/powerpc/aesp8-ppc.S: $(src)/powerpc/aesp8-ppc.pl FORCE
 	$(call if_changed,perlasm_aes)
 targets += powerpc/aesp8-ppc.S
 OBJECT_FILES_NON_STANDARD_powerpc/aesp8-ppc.o := y
@@ -159,13 +160,27 @@ libgf128hash-y := gf128hash.o
 ifeq ($(CONFIG_CRYPTO_LIB_GF128HASH_ARCH),y)
 CFLAGS_gf128hash.o += -I$(src)/$(SRCARCH)
 libgf128hash-$(CONFIG_ARM) += arm/ghash-neon-core.o
 libgf128hash-$(CONFIG_ARM64) += arm64/ghash-neon-core.o \
 				arm64/polyval-ce-core.o
-libgf128hash-$(CONFIG_X86) += x86/polyval-pclmul-avx.o
+
+ifeq ($(CONFIG_PPC),y)
+libgf128hash-y += powerpc/ghashp8-ppc.o
+quiet_cmd_perlasm_ghash = PERLASM $@
+      cmd_perlasm_ghash = $(PERL) $< $(ppc64-perlasm-flavour-y) $@
+$(obj)/powerpc/ghashp8-ppc.S: $(src)/powerpc/ghashp8-ppc.pl FORCE
+	$(call if_changed,perlasm_ghash)
+targets += powerpc/ghashp8-ppc.S
+OBJECT_FILES_NON_STANDARD_powerpc/ghashp8-ppc.o := y
 endif
 
+libgf128hash-$(CONFIG_X86) += x86/polyval-pclmul-avx.o
+endif # CONFIG_CRYPTO_LIB_GF128HASH_ARCH
+
+# clean-files must be defined unconditionally
+clean-files += powerpc/ghashp8-ppc.S
+
 ################################################################################
 
 obj-$(CONFIG_CRYPTO_LIB_MD5) += libmd5.o
 libmd5-y := md5.o
 ifeq ($(CONFIG_CRYPTO_LIB_MD5_ARCH),y)
lib/crypto/powerpc/.gitignore +1 -0
index 598ca7aff6b1..7aa71d83f739 100644
@@ -1,2 +1,3 @@
 # SPDX-License-Identifier: GPL-2.0-only
 aesp8-ppc.S
+ghashp8-ppc.S
lib/crypto/powerpc/gf128hash.h new file +109 -0

109 lines not on this page · raw message

lib/crypto/powerpc/ghashp8-ppc.pl renamed from arch/powerpc/crypto/ghashp8-ppc.pl +1 -0
similarity index 98%
rename from arch/powerpc/crypto/ghashp8-ppc.pl
rename to lib/crypto/powerpc/ghashp8-ppc.pl
index 041e633c214f..7c38eedc02cc 100644
@@ -45,10 +45,11 @@ if ($flavour =~ /64/) {
 } else { die "nonsense $flavour"; }
 
 $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
 ( $xlate="${dir}ppc-xlate.pl" and -f $xlate ) or
 ( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or
+( $xlate="${dir}../../../arch/powerpc/crypto/ppc-xlate.pl" and -f $xlate) or
 die "can't locate ppc-xlate.pl";
 
 open STDOUT,"| $^X $xlate $flavour $output" || die "can't call $xlate: $!";
 
 my ($Xip,$Htbl,$inp,$len)=map("r$_",(3..6));	# argument block
Signature · 1 line
2.53.0
author maintainer
#12 lore raw

PATCH 12/19 lib/crypto: riscv/ghash: Migrate optimized code into library

In reply to Eric Biggers

Remove the "ghash-riscv64-zvkg" crypto_shash algorithm. Move the corresponding assembly code into lib/crypto/, modify it to take the length in blocks instead of bytes, and wire it up to the GHASH library.

This makes the GHASH library be optimized with the RISC-V Vector Cryptography Extension. It also greatly reduces the amount of riscv-specific glue code that is needed, and it fixes the issue where this optimized GHASH code was disabled by default.

Note that this RISC-V code has multiple opportunities for improvement, such as adding more parallelism, providing an optimized multiplication function, and directly supporting POLYVAL. But for now, this commit simply tweaks ghash_zvkg() slightly to make it compatible with the library, then wires it up to ghash_blocks_arch().

ghash_preparekey_arch() is also implemented to store the copy of the raw key needed by the vghsh.vv instruction.

---
 arch/riscv/crypto/Kconfig                     |  11 --
 arch/riscv/crypto/Makefile                    |   3 -
 arch/riscv/crypto/ghash-riscv64-glue.c        | 146 ------------------
 include/crypto/gf128hash.h                    |   3 +
 lib/crypto/Kconfig                            |   2 +
 lib/crypto/Makefile                           |   1 +
 lib/crypto/riscv/gf128hash.h                  |  57 +++++++
 .../crypto/riscv}/ghash-riscv64-zvkg.S        |  13 +-
 8 files changed, 69 insertions(+), 167 deletions(-)
 delete mode 100644 arch/riscv/crypto/ghash-riscv64-glue.c
 create mode 100644 lib/crypto/riscv/gf128hash.h
 rename {arch/riscv/crypto => lib/crypto/riscv}/ghash-riscv64-zvkg.S (91%)
arch/riscv/crypto/Kconfig +0 -11
index 22d4eaab15f3..c208f54afbcd 100644
@@ -15,21 +15,10 @@ config CRYPTO_AES_RISCV64
 	  - Zvkned vector crypto extension
 	  - Zvbb vector extension (XTS)
 	  - Zvkb vector crypto extension (CTR)
 	  - Zvkg vector crypto extension (XTS)
 
-config CRYPTO_GHASH_RISCV64
-	tristate "Hash functions: GHASH"
-	depends on 64BIT && TOOLCHAIN_HAS_VECTOR_CRYPTO && \
-		   RISCV_EFFICIENT_VECTOR_UNALIGNED_ACCESS
-	select CRYPTO_GCM
-	help
-	  GCM GHASH function (NIST SP 800-38D)
-
-	  Architecture: riscv64 using:
-	  - Zvkg vector crypto extension
-
 config CRYPTO_SM3_RISCV64
 	tristate "Hash functions: SM3 (ShangMi 3)"
 	depends on 64BIT && TOOLCHAIN_HAS_VECTOR_CRYPTO && \
 		   RISCV_EFFICIENT_VECTOR_UNALIGNED_ACCESS
 	select CRYPTO_HASH
arch/riscv/crypto/Makefile +0 -3
index 183495a95cc0..5c9ee1b876fa 100644
@@ -2,13 +2,10 @@
 
 obj-$(CONFIG_CRYPTO_AES_RISCV64) += aes-riscv64.o
 aes-riscv64-y := aes-riscv64-glue.o aes-riscv64-zvkned.o \
 		 aes-riscv64-zvkned-zvbb-zvkg.o aes-riscv64-zvkned-zvkb.o
 
-obj-$(CONFIG_CRYPTO_GHASH_RISCV64) += ghash-riscv64.o
-ghash-riscv64-y := ghash-riscv64-glue.o ghash-riscv64-zvkg.o
-
 obj-$(CONFIG_CRYPTO_SM3_RISCV64) += sm3-riscv64.o
 sm3-riscv64-y := sm3-riscv64-glue.o sm3-riscv64-zvksh-zvkb.o
 
 obj-$(CONFIG_CRYPTO_SM4_RISCV64) += sm4-riscv64.o
 sm4-riscv64-y := sm4-riscv64-glue.o sm4-riscv64-zvksed-zvkb.o
arch/riscv/crypto/ghash-riscv64-glue.c deleted +0 -146

146 lines not on this page · raw message

include/crypto/gf128hash.h +3 -0
index 650652dd6003..b798438cce23 100644
@@ -42,10 +42,13 @@ struct polyval_elem {
  */
 struct ghash_key {
 #if defined(CONFIG_CRYPTO_LIB_GF128HASH_ARCH) && defined(CONFIG_PPC64)
 	/** @htable: GHASH key format used by the POWER8 assembly code */
 	u64 htable[4][2];
+#elif defined(CONFIG_CRYPTO_LIB_GF128HASH_ARCH) && defined(CONFIG_RISCV)
+	/** @h_raw: The hash key H, in GHASH format */
+	u8 h_raw[GHASH_BLOCK_SIZE];
 #endif
 	/** @h: The hash key H, in POLYVAL format */
 	struct polyval_elem h;
 };
 
lib/crypto/Kconfig +2 -0
index f54add7d9070..027802e0de33 100644
@@ -120,10 +120,12 @@ config CRYPTO_LIB_GF128HASH_ARCH
 	bool
 	depends on CRYPTO_LIB_GF128HASH && !UML
 	default y if ARM && KERNEL_MODE_NEON
 	default y if ARM64
 	default y if PPC64 && VSX
+	default y if RISCV && 64BIT && TOOLCHAIN_HAS_VECTOR_CRYPTO && \
+		     RISCV_EFFICIENT_VECTOR_UNALIGNED_ACCESS
 	default y if X86_64
 
 config CRYPTO_LIB_MD5
 	tristate
 	help
lib/crypto/Makefile +1 -0
index 8a9084188778..8950509833af 100644
@@ -171,10 +171,11 @@ $(obj)/powerpc/ghashp8-ppc.S: $(src)/powerpc/ghashp8-ppc.pl FORCE
 	$(call if_changed,perlasm_ghash)
 targets += powerpc/ghashp8-ppc.S
 OBJECT_FILES_NON_STANDARD_powerpc/ghashp8-ppc.o := y
 endif
 
+libgf128hash-$(CONFIG_RISCV) += riscv/ghash-riscv64-zvkg.o
 libgf128hash-$(CONFIG_X86) += x86/polyval-pclmul-avx.o
 endif # CONFIG_CRYPTO_LIB_GF128HASH_ARCH
 
 # clean-files must be defined unconditionally
 clean-files += powerpc/ghashp8-ppc.S
lib/crypto/riscv/gf128hash.h new file +57 -0

57 lines not on this page · raw message

lib/crypto/riscv/ghash-riscv64-zvkg.S renamed from arch/riscv/crypto/ghash-riscv64-zvkg.S +6 -7
similarity index 91%
rename from arch/riscv/crypto/ghash-riscv64-zvkg.S
rename to lib/crypto/riscv/ghash-riscv64-zvkg.S
index f2b43fb4d434..2839ff1a990c 100644
@@ -48,25 +48,24 @@
 .option arch, +zvkg
 
 #define ACCUMULATOR	a0
 #define KEY		a1
 #define DATA		a2
-#define LEN		a3
+#define NBLOCKS		a3
 
-// void ghash_zvkg(be128 *accumulator, const be128 *key, const u8 *data,
-//		   size_t len);
-//
-// |len| must be nonzero and a multiple of 16 (GHASH_BLOCK_SIZE).
+// void ghash_zvkg(u8 accumulator[GHASH_BLOCK_SIZE],
+//		   const u8 key[GHASH_BLOCK_SIZE],
+//		   const u8 *data, size_t nblocks);
 SYM_FUNC_START(ghash_zvkg)
 	vsetivli	zero, 4, e32, m1, ta, ma
 	vle32.v		v1, (ACCUMULATOR)
 	vle32.v		v2, (KEY)
 .Lnext_block:
 	vle32.v		v3, (DATA)
 	vghsh.vv	v1, v2, v3
 	addi		DATA, DATA, 16
-	addi		LEN, LEN, -16
-	bnez		LEN, .Lnext_block
+	addi		NBLOCKS, NBLOCKS, -1
+	bnez		NBLOCKS, .Lnext_block
 
 	vse32.v		v1, (ACCUMULATOR)
 	ret
 SYM_FUNC_END(ghash_zvkg)
Signature · 1 line
2.53.0
author maintainer
#13 lore raw

PATCH 13/19 lib/crypto: s390/ghash: Migrate optimized code into library

In reply to Eric Biggers

Remove the "ghash-s390" crypto_shash algorithm, and replace it with an implementation of ghash_blocks_arch() for the GHASH library.

This makes the GHASH library be optimized with CPACF. It also greatly reduces the amount of s390-specific glue code that is needed, and it fixes the issue where this GHASH optimization was disabled by default.

---
 arch/s390/configs/debug_defconfig |   1 -
 arch/s390/configs/defconfig       |   1 -
 arch/s390/crypto/Kconfig          |  10 ---
 arch/s390/crypto/Makefile         |   1 -
 arch/s390/crypto/ghash_s390.c     | 144 ------------------------------
 include/crypto/gf128hash.h        |   3 +-
 lib/crypto/Kconfig                |   1 +
 lib/crypto/s390/gf128hash.h       |  54 +++++++++++
 8 files changed, 57 insertions(+), 158 deletions(-)
 delete mode 100644 arch/s390/crypto/ghash_s390.c
 create mode 100644 lib/crypto/s390/gf128hash.h
arch/s390/configs/debug_defconfig +0 -1
index 98fd0a2f51c6..aa862d4fcc68 100644
@@ -807,11 +807,10 @@ CONFIG_CRYPTO_LZ4HC=m
 CONFIG_CRYPTO_ZSTD=m
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
 CONFIG_CRYPTO_USER_API_RNG=m
 CONFIG_CRYPTO_USER_API_AEAD=m
-CONFIG_CRYPTO_GHASH_S390=m
 CONFIG_CRYPTO_AES_S390=m
 CONFIG_CRYPTO_DES_S390=m
 CONFIG_CRYPTO_HMAC_S390=m
 CONFIG_ZCRYPT=m
 CONFIG_PKEY=m
arch/s390/configs/defconfig +0 -1
index 0f4cedcab3ce..74f943307c46 100644
@@ -792,11 +792,10 @@ CONFIG_CRYPTO_ZSTD=m
 CONFIG_CRYPTO_JITTERENTROPY_OSR=1
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
 CONFIG_CRYPTO_USER_API_RNG=m
 CONFIG_CRYPTO_USER_API_AEAD=m
-CONFIG_CRYPTO_GHASH_S390=m
 CONFIG_CRYPTO_AES_S390=m
 CONFIG_CRYPTO_DES_S390=m
 CONFIG_CRYPTO_HMAC_S390=m
 CONFIG_ZCRYPT=m
 CONFIG_PKEY=m
arch/s390/crypto/Kconfig +0 -10
index 79a2d0034258..ee83052dbc15 100644
@@ -1,19 +1,9 @@
 # SPDX-License-Identifier: GPL-2.0
 
 menu "Accelerated Cryptographic Algorithms for CPU (s390)"
 
-config CRYPTO_GHASH_S390
-	tristate "Hash functions: GHASH"
-	select CRYPTO_HASH
-	help
-	  GCM GHASH hash function (NIST SP800-38D)
-
-	  Architecture: s390
-
-	  It is available as of z196.
-
 config CRYPTO_AES_S390
 	tristate "Ciphers: AES, modes: ECB, CBC, CTR, XTS, GCM"
 	select CRYPTO_SKCIPHER
 	help
 	  AEAD cipher: AES with GCM
arch/s390/crypto/Makefile +0 -1
index 387a229e1038..4449c1b19ef5 100644
@@ -5,9 +5,8 @@
 
 obj-$(CONFIG_CRYPTO_DES_S390) += des_s390.o
 obj-$(CONFIG_CRYPTO_AES_S390) += aes_s390.o
 obj-$(CONFIG_CRYPTO_PAES_S390) += paes_s390.o
 obj-$(CONFIG_S390_PRNG) += prng.o
-obj-$(CONFIG_CRYPTO_GHASH_S390) += ghash_s390.o
 obj-$(CONFIG_CRYPTO_HMAC_S390) += hmac_s390.o
 obj-$(CONFIG_CRYPTO_PHMAC_S390) += phmac_s390.o
 obj-y += arch_random.o
arch/s390/crypto/ghash_s390.c deleted +0 -144

144 lines not on this page · raw message

include/crypto/gf128hash.h +2 -1
index b798438cce23..0bc649d01e12 100644
@@ -42,11 +42,12 @@ struct polyval_elem {
  */
 struct ghash_key {
 #if defined(CONFIG_CRYPTO_LIB_GF128HASH_ARCH) && defined(CONFIG_PPC64)
 	/** @htable: GHASH key format used by the POWER8 assembly code */
 	u64 htable[4][2];
-#elif defined(CONFIG_CRYPTO_LIB_GF128HASH_ARCH) && defined(CONFIG_RISCV)
+#elif defined(CONFIG_CRYPTO_LIB_GF128HASH_ARCH) && \
+	(defined(CONFIG_RISCV) || defined(CONFIG_S390))
 	/** @h_raw: The hash key H, in GHASH format */
 	u8 h_raw[GHASH_BLOCK_SIZE];
 #endif
 	/** @h: The hash key H, in POLYVAL format */
 	struct polyval_elem h;
lib/crypto/Kconfig +1 -0
index 027802e0de33..a39e7707e9ee 100644
@@ -122,10 +122,11 @@ config CRYPTO_LIB_GF128HASH_ARCH
 	default y if ARM && KERNEL_MODE_NEON
 	default y if ARM64
 	default y if PPC64 && VSX
 	default y if RISCV && 64BIT && TOOLCHAIN_HAS_VECTOR_CRYPTO && \
 		     RISCV_EFFICIENT_VECTOR_UNALIGNED_ACCESS
+	default y if S390
 	default y if X86_64
 
 config CRYPTO_LIB_MD5
 	tristate
 	help
lib/crypto/s390/gf128hash.h new file +54 -0

54 lines not on this page · raw message

Signature · 1 line
2.53.0
author maintainer
#14 lore raw

PATCH 14/19 lib/crypto: x86/ghash: Migrate optimized code into library

In reply to Eric Biggers

Remove the "ghash-pclmulqdqni" crypto_shash algorithm. Move the corresponding assembly code into lib/crypto/, and wire it up to the GHASH library.

This makes the GHASH library be optimized with x86's carryless multiplication instructions. It also greatly reduces the amount of x86-specific glue code that is needed, and it fixes the issue where this GHASH optimization was disabled by default.

Rename and adjust the prototypes of the assembly functions to make them fit better with the library. Remove the byte-swaps (pshufb instructions) that are no longer necessary because the library keeps the accumulator in POLYVAL format rather than GHASH format.

Rename clmul_ghash_mul() to polyval_mul_pclmul() to reflect that it really does a POLYVAL style multiplication. Wire it up to both ghash_mul_arch() and polyval_mul_arch().

---
 arch/x86/crypto/Kconfig                       |  10 --
 arch/x86/crypto/Makefile                      |   3 -
 arch/x86/crypto/ghash-clmulni-intel_glue.c    | 163 ------------------
 lib/crypto/Makefile                           |   3 +-
 lib/crypto/x86/gf128hash.h                    |  65 ++++++-
 .../crypto/x86/ghash-pclmul.S                 |  98 +++++------
 6 files changed, 104 insertions(+), 238 deletions(-)
 delete mode 100644 arch/x86/crypto/ghash-clmulni-intel_glue.c
 rename arch/x86/crypto/ghash-clmulni-intel_asm.S => lib/crypto/x86/ghash-pclmul.S (54%)
arch/x86/crypto/Kconfig +0 -10
index 7fb2319a0916..905e8a23cec3 100644
@@ -342,16 +342,6 @@ config CRYPTO_SM3_AVX_X86_64
 	  Architecture: x86_64 using:
 	  - AVX (Advanced Vector Extensions)
 
 	  If unsure, say N.
 
-config CRYPTO_GHASH_CLMUL_NI_INTEL
-	tristate "Hash functions: GHASH (CLMUL-NI)"
-	depends on 64BIT
-	select CRYPTO_CRYPTD
-	help
-	  GCM GHASH hash function (NIST SP800-38D)
-
-	  Architecture: x86_64 using:
-	  - CLMUL-NI (carry-less multiplication new instructions)
-
 endmenu
arch/x86/crypto/Makefile +0 -3
index b21ad0978c52..d562f4341da6 100644
@@ -48,13 +48,10 @@ aesni-intel-$(CONFIG_64BIT) += aes-ctr-avx-x86_64.o \
 			       aes-gcm-aesni-x86_64.o \
 			       aes-gcm-vaes-avx2.o \
 			       aes-gcm-vaes-avx512.o \
 			       aes-xts-avx-x86_64.o
 
-obj-$(CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL) += ghash-clmulni-intel.o
-ghash-clmulni-intel-y := ghash-clmulni-intel_asm.o ghash-clmulni-intel_glue.o
-
 obj-$(CONFIG_CRYPTO_SM3_AVX_X86_64) += sm3-avx-x86_64.o
 sm3-avx-x86_64-y := sm3-avx-asm_64.o sm3_avx_glue.o
 
 obj-$(CONFIG_CRYPTO_SM4_AESNI_AVX_X86_64) += sm4-aesni-avx-x86_64.o
 sm4-aesni-avx-x86_64-y := sm4-aesni-avx-asm_64.o sm4_aesni_avx_glue.o
arch/x86/crypto/ghash-clmulni-intel_glue.c deleted +0 -163

163 lines not on this page · raw message

lib/crypto/Makefile +2 -1
index 8950509833af..19c67f70fb38 100644
@@ -172,11 +172,12 @@ $(obj)/powerpc/ghashp8-ppc.S: $(src)/powerpc/ghashp8-ppc.pl FORCE
 targets += powerpc/ghashp8-ppc.S
 OBJECT_FILES_NON_STANDARD_powerpc/ghashp8-ppc.o := y
 endif
 
 libgf128hash-$(CONFIG_RISCV) += riscv/ghash-riscv64-zvkg.o
-libgf128hash-$(CONFIG_X86) += x86/polyval-pclmul-avx.o
+libgf128hash-$(CONFIG_X86) += x86/ghash-pclmul.o \
+			      x86/polyval-pclmul-avx.o
 endif # CONFIG_CRYPTO_LIB_GF128HASH_ARCH
 
 # clean-files must be defined unconditionally
 clean-files += powerpc/ghashp8-ppc.S
 
lib/crypto/x86/gf128hash.h +56 -9

105 lines not on this page · raw message

lib/crypto/x86/ghash-pclmul.S renamed from arch/x86/crypto/ghash-clmulni-intel_asm.S +46 -52

160 lines not on this page · raw message

Signature · 1 line
2.53.0
author maintainer
#15 lore raw

PATCH 15/19 crypto: gcm - Use GHASH library instead of crypto_ahash

In reply to Eric Biggers

Make the "gcm" template access GHASH using the library API instead of crypto_ahash. This is much simpler and more efficient, especially given that all GHASH implementations are synchronous and CPU-based anyway.

Note that this allows "ghash" to be removed from the crypto_ahash (and crypto_shash) API, which a later commit will do.

This mirrors the similar cleanup that was done with POLYVAL.

---
 crypto/Kconfig                       |   2 +-
 crypto/gcm.c                         | 413 +++++----------------------
 crypto/testmgr.c                     |  10 +-
 drivers/crypto/starfive/jh7110-aes.c |   2 +-
 4 files changed, 85 insertions(+), 342 deletions(-)
crypto/Kconfig +1 -1
index 5627b3691561..13ccf5ac2f1a 100644
@@ -792,11 +792,11 @@ config CRYPTO_CCM
 
 config CRYPTO_GCM
 	tristate "GCM (Galois/Counter Mode) and GMAC (GCM MAC)"
 	select CRYPTO_CTR
 	select CRYPTO_AEAD
-	select CRYPTO_GHASH
+	select CRYPTO_LIB_GF128HASH
 	select CRYPTO_MANAGER
 	help
 	  GCM (Galois/Counter Mode) authenticated encryption mode and GMAC
 	  (GCM Message Authentication Code) (NIST SP800-38D)
 
crypto/gcm.c +78 -335

670 lines not on this page · raw message

crypto/testmgr.c +5 -5
index fec950f1628b..0b0ad358e091 100644
@@ -4963,26 +4963,26 @@ static const struct alg_test_desc alg_test_descs[] = {
 			.kpp = __VECS(ffdhe8192_dh_tv_template)
 		}
 	}, {
 #endif /* CONFIG_CRYPTO_DH_RFC7919_GROUPS */
 		.alg = "gcm(aes)",
-		.generic_driver = "gcm_base(ctr(aes-lib),ghash-generic)",
+		.generic_driver = "gcm_base(ctr(aes-lib),ghash-lib)",
 		.test = alg_test_aead,
 		.fips_allowed = 1,
 		.suite = {
 			.aead = __VECS(aes_gcm_tv_template)
 		}
 	}, {
 		.alg = "gcm(aria)",
-		.generic_driver = "gcm_base(ctr(aria-generic),ghash-generic)",
+		.generic_driver = "gcm_base(ctr(aria-generic),ghash-lib)",
 		.test = alg_test_aead,
 		.suite = {
 			.aead = __VECS(aria_gcm_tv_template)
 		}
 	}, {
 		.alg = "gcm(sm4)",
-		.generic_driver = "gcm_base(ctr(sm4-generic),ghash-generic)",
+		.generic_driver = "gcm_base(ctr(sm4-generic),ghash-lib)",
 		.test = alg_test_aead,
 		.suite = {
 			.aead = __VECS(sm4_gcm_tv_template)
 		}
 	}, {
@@ -5312,11 +5312,11 @@ static const struct alg_test_desc alg_test_descs[] = {
 		.suite = {
 			.cipher = __VECS(sm4_ctr_rfc3686_tv_template)
 		}
 	}, {
 		.alg = "rfc4106(gcm(aes))",
-		.generic_driver = "rfc4106(gcm_base(ctr(aes-lib),ghash-generic))",
+		.generic_driver = "rfc4106(gcm_base(ctr(aes-lib),ghash-lib))",
 		.test = alg_test_aead,
 		.fips_allowed = 1,
 		.suite = {
 			.aead = {
 				____VECS(aes_gcm_rfc4106_tv_template),
@@ -5336,11 +5336,11 @@ static const struct alg_test_desc alg_test_descs[] = {
 				.aad_iv = 1,
 			}
 		}
 	}, {
 		.alg = "rfc4543(gcm(aes))",
-		.generic_driver = "rfc4543(gcm_base(ctr(aes-lib),ghash-generic))",
+		.generic_driver = "rfc4543(gcm_base(ctr(aes-lib),ghash-lib))",
 		.test = alg_test_aead,
 		.suite = {
 			.aead = {
 				____VECS(aes_gcm_rfc4543_tv_template),
 				.einval_allowed = 1,
drivers/crypto/starfive/jh7110-aes.c +1 -1
index 2e2d97d17e6c..a0713aa21250 100644
@@ -1006,11 +1006,11 @@ static int starfive_aes_ccm_init_tfm(struct crypto_aead *tfm)
 	return starfive_aes_aead_init_tfm(tfm, "ccm_base(ctr(aes-lib),cbcmac-aes-lib)");
 }
 
 static int starfive_aes_gcm_init_tfm(struct crypto_aead *tfm)
 {
-	return starfive_aes_aead_init_tfm(tfm, "gcm_base(ctr(aes-lib),ghash-generic)");
+	return starfive_aes_aead_init_tfm(tfm, "gcm_base(ctr(aes-lib),ghash-lib)");
 }
 
 static struct skcipher_engine_alg skcipher_algs[] = {
 {
 	.base.init			= starfive_aes_ecb_init_tfm,
Signature · 1 line
2.53.0
author maintainer
#16 lore raw

PATCH 16/19 crypto: ghash - Remove ghash from crypto_shash API

In reply to Eric Biggers

Now that there are no users of the "ghash" crypto_shash algorithm, remove it. GHASH remains supported via the library API.

---
 crypto/Kconfig         |   7 --
 crypto/Makefile        |   1 -
 crypto/ghash-generic.c | 162 -----------------------------------------
 crypto/tcrypt.c        |   9 ---
 crypto/testmgr.c       |   6 --
 crypto/testmgr.h       | 109 ---------------------------
 6 files changed, 294 deletions(-)
 delete mode 100644 crypto/ghash-generic.c
crypto/Kconfig +0 -7
index 13ccf5ac2f1a..efb482ea192d 100644
@@ -886,17 +886,10 @@ config CRYPTO_CMAC
 	select CRYPTO_MANAGER
 	help
 	  CMAC (Cipher-based Message Authentication Code) authentication
 	  mode (NIST SP800-38B and IETF RFC4493)
 
-config CRYPTO_GHASH
-	tristate "GHASH"
-	select CRYPTO_HASH
-	select CRYPTO_LIB_GF128MUL
-	help
-	  GCM GHASH function (NIST SP800-38D)
-
 config CRYPTO_HMAC
 	tristate "HMAC (Keyed-Hash MAC)"
 	select CRYPTO_HASH
 	select CRYPTO_MANAGER
 	help
crypto/Makefile +0 -1
index 04e269117589..17f4fca9b9e5 100644
@@ -169,11 +169,10 @@ CFLAGS_jitterentropy.o = -O0
 KASAN_SANITIZE_jitterentropy.o = n
 UBSAN_SANITIZE_jitterentropy.o = n
 jitterentropy_rng-y := jitterentropy.o jitterentropy-kcapi.o
 obj-$(CONFIG_CRYPTO_JITTERENTROPY_TESTINTERFACE) += jitterentropy-testing.o
 obj-$(CONFIG_CRYPTO_BENCHMARK) += tcrypt.o
-obj-$(CONFIG_CRYPTO_GHASH) += ghash-generic.o
 obj-$(CONFIG_CRYPTO_USER_API) += af_alg.o
 obj-$(CONFIG_CRYPTO_USER_API_HASH) += algif_hash.o
 obj-$(CONFIG_CRYPTO_USER_API_SKCIPHER) += algif_skcipher.o
 obj-$(CONFIG_CRYPTO_USER_API_RNG) += algif_rng.o
 obj-$(CONFIG_CRYPTO_USER_API_AEAD) += algif_aead.o
crypto/ghash-generic.c deleted +0 -162

162 lines not on this page · raw message

crypto/tcrypt.c +0 -9
index aded37546137..1773f5f71351 100644
@@ -1648,14 +1648,10 @@ static int do_test(const char *alg, u32 type, u32 mask, int m, u32 num_mb)
 
 	case 45:
 		ret = min(ret, tcrypt_test("rfc4309(ccm(aes))"));
 		break;
 
-	case 46:
-		ret = min(ret, tcrypt_test("ghash"));
-		break;
-
 	case 48:
 		ret = min(ret, tcrypt_test("sha3-224"));
 		break;
 
 	case 49:
@@ -2249,15 +2245,10 @@ static int do_test(const char *alg, u32 type, u32 mask, int m, u32 num_mb)
 		fallthrough;
 	case 317:
 		test_hash_speed("blake2b-512", sec, generic_hash_speed_template);
 		if (mode > 300 && mode < 400) break;
 		fallthrough;
-	case 318:
-		klen = 16;
-		test_hash_speed("ghash", sec, generic_hash_speed_template);
-		if (mode > 300 && mode < 400) break;
-		fallthrough;
 	case 319:
 		test_hash_speed("crc32c", sec, generic_hash_speed_template);
 		if (mode > 300 && mode < 400) break;
 		fallthrough;
 	case 322:
crypto/testmgr.c +0 -6
index 0b0ad358e091..dd01f86dd6fe 100644
@@ -4983,16 +4983,10 @@ static const struct alg_test_desc alg_test_descs[] = {
 		.generic_driver = "gcm_base(ctr(sm4-generic),ghash-lib)",
 		.test = alg_test_aead,
 		.suite = {
 			.aead = __VECS(sm4_gcm_tv_template)
 		}
-	}, {
-		.alg = "ghash",
-		.test = alg_test_hash,
-		.suite = {
-			.hash = __VECS(ghash_tv_template)
-		}
 	}, {
 		.alg = "hctr2(aes)",
 		.generic_driver = "hctr2_base(xctr(aes-lib),polyval-lib)",
 		.test = alg_test_skcipher,
 		.suite = {
crypto/testmgr.h +0 -109

119 lines not on this page · raw message

Signature · 1 line
2.53.0
author maintainer
#17 lore raw

PATCH 17/19 lib/crypto: gf128mul: Remove unused 4k_lle functions

In reply to Eric Biggers

Remove the 4k_lle multiplication functions and the associated gf128mul_table_le data table. Their only user was the generic implementation of GHASH, which has now been changed to use a different implementation based on standard integer multiplication.

---
 include/crypto/gf128mul.h | 17 ++-------
 lib/crypto/gf128mul.c     | 73 +--------------------------------------
 2 files changed, 4 insertions(+), 86 deletions(-)
include/crypto/gf128mul.h +3 -14
index b0853f7cada0..6ed2a8351902 100644
@@ -213,29 +213,18 @@ static inline void gf128mul_x_ble(le128 *r, const le128 *x)
 
 	r->a = cpu_to_le64((a << 1) | (b >> 63));
 	r->b = cpu_to_le64((b << 1) ^ _tt);
 }
 
-/* 4k table optimization */
-
-struct gf128mul_4k {
-	be128 t[256];
-};
-
-struct gf128mul_4k *gf128mul_init_4k_lle(const be128 *g);
-void gf128mul_4k_lle(be128 *a, const struct gf128mul_4k *t);
 void gf128mul_x8_ble(le128 *r, const le128 *x);
-static inline void gf128mul_free_4k(struct gf128mul_4k *t)
-{
-	kfree_sensitive(t);
-}
-
 
 /* 64k table optimization, implemented for bbe */
 
 struct gf128mul_64k {
-	struct gf128mul_4k *t[16];
+	struct {
+		be128 t[256];
+	} *t[16];
 };
 
 /* First initialize with the constant factor with which you
  * want to multiply and then call gf128mul_64k_bbe with the other
  * factor in the first argument, and the table in the second.
lib/crypto/gf128mul.c +1 -72

92 lines not on this page · raw message

Signature · 1 line
2.53.0
author maintainer
#18 lore raw

PATCH 18/19 lib/crypto: gf128hash: Remove unused content from ghash.h

In reply to Eric Biggers

Now that the structures in <crypto/ghash.h> are no longer used, remove them. Since this leaves <crypto/ghash.h> as just containing constants, include it from <crypto/gf128hash.h> to deduplicate these definitions.

---
 include/crypto/gf128hash.h |  3 +--
 include/crypto/ghash.h     | 12 ------------
 2 files changed, 1 insertion(+), 14 deletions(-)
include/crypto/gf128hash.h +1 -2
index 0bc649d01e12..41c557d55965 100644
@@ -6,15 +6,14 @@
  */
 
 #ifndef _CRYPTO_GF128HASH_H
 #define _CRYPTO_GF128HASH_H
 
+#include <crypto/ghash.h>
 #include <linux/string.h>
 #include <linux/types.h>
 
-#define GHASH_BLOCK_SIZE	16
-#define GHASH_DIGEST_SIZE	16
 #define POLYVAL_BLOCK_SIZE	16
 #define POLYVAL_DIGEST_SIZE	16
 
 /**
  * struct polyval_elem - An element of the POLYVAL finite field
include/crypto/ghash.h +0 -12
index 043d938e9a2c..d187e5af9925 100644
@@ -4,21 +4,9 @@
  */
 
 #ifndef __CRYPTO_GHASH_H__
 #define __CRYPTO_GHASH_H__
 
-#include <linux/types.h>
-
 #define GHASH_BLOCK_SIZE	16
 #define GHASH_DIGEST_SIZE	16
 
-struct gf128mul_4k;
-
-struct ghash_ctx {
-	struct gf128mul_4k *gf128;
-};
-
-struct ghash_desc_ctx {
-	u8 buffer[GHASH_BLOCK_SIZE];
-};
-
 #endif
Signature · 1 line
2.53.0
author maintainer
#19 lore raw

PATCH 19/19 lib/crypto: aesgcm: Use GHASH library API

In reply to Eric Biggers

Make the AES-GCM library use the GHASH library instead of directly calling gf128mul_lle(). This allows the architecture-optimized GHASH implementations to be used, or the improved generic implementation if no architecture-optimized implementation is usable.

Note: this means that <crypto/gcm.h> no longer needs to include <crypto/gf128mul.h>. Remove that inclusion, and include <crypto/gf128mul.h> explicitly from arch/x86/crypto/aesni-intel_glue.c which previously was relying on the transitive inclusion.

---
 arch/x86/crypto/aesni-intel_glue.c |  1 +
 include/crypto/gcm.h               |  4 +--
 lib/crypto/Kconfig                 |  2 +-
 lib/crypto/aesgcm.c                | 55 +++++++++++++++---------------
 4 files changed, 32 insertions(+), 30 deletions(-)
arch/x86/crypto/aesni-intel_glue.c +1 -0
index e6c38d1d8a92..f522fff9231e 100644
@@ -23,10 +23,11 @@
 #include <linux/err.h>
 #include <crypto/algapi.h>
 #include <crypto/aes.h>
 #include <crypto/b128ops.h>
 #include <crypto/gcm.h>
+#include <crypto/gf128mul.h>
 #include <crypto/xts.h>
 #include <asm/cpu_device_id.h>
 #include <asm/simd.h>
 #include <crypto/scatterwalk.h>
 #include <crypto/internal/aead.h>
include/crypto/gcm.h +2 -2
index b524e47bd4d0..1d5f39ff1dc4 100644
@@ -2,11 +2,11 @@
 #define _CRYPTO_GCM_H
 
 #include <linux/errno.h>
 
 #include <crypto/aes.h>
-#include <crypto/gf128mul.h>
+#include <crypto/gf128hash.h>
 
 #define GCM_AES_IV_SIZE 12
 #define GCM_RFC4106_IV_SIZE 8
 #define GCM_RFC4543_IV_SIZE 8
 
@@ -63,11 +63,11 @@ static inline int crypto_ipsec_check_assoclen(unsigned int assoclen)
 
 	return 0;
 }
 
 struct aesgcm_ctx {
-	be128			ghash_key;
+	struct ghash_key	ghash_key;
 	struct aes_enckey	aes_key;
 	unsigned int		authsize;
 };
 
 int aesgcm_expandkey(struct aesgcm_ctx *ctx, const u8 *key,
lib/crypto/Kconfig +1 -1
index a39e7707e9ee..32fafe245f47 100644
@@ -39,11 +39,11 @@ config CRYPTO_LIB_AES_CBC_MACS
 	  <crypto/aes-cbc-macs.h>.
 
 config CRYPTO_LIB_AESGCM
 	tristate
 	select CRYPTO_LIB_AES
-	select CRYPTO_LIB_GF128MUL
+	select CRYPTO_LIB_GF128HASH
 	select CRYPTO_LIB_UTILS
 
 config CRYPTO_LIB_ARC4
 	tristate
 
lib/crypto/aesgcm.c +28 -27

102 lines not on this page · raw message

Signature · 1 line
2.53.0
maintainer Acked-by on the v1 series
#20 lore raw
In reply to Eric Biggers
Quoted 40 lines · Eric Biggers

This series is targeting libcrypto-next. It can also be retrieved from:

git fetch
https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux.git
ghash-lib-v1

This series migrates the standalone GHASH code to lib/crypto/, then converts the "gcm" template and AES-GCM library code to use it. (GHASH is the universal hash function used by GCM mode.) As was the case with POLYVAL and Poly1305 as well, the library is a much better fit for it.

Since GHASH and POLYVAL are closely related and it often makes sense to implement one in terms of the other, the existing "polyval" library module is renamed to "gf128hash" and the GHASH support is added to it.

The generic implementation of GHASH is also replaced with a better one utilizing the existing polyval_mul_generic().

Note that some GHASH implementations, often faster ones using more recent CPU features, still exist in arch/*/crypto/ as internal components of AES-GCM implementations. Those are left as-is for now. The goal with this GHASH library is just to provide parity with the existing standalone GHASH support, which is used when a full implementation of AES-GCM (or ${someothercipher}-GCM, if another block cipher is being used) is unavailable. Migrating the architecture-optimized AES-GCM code to lib/crypto/ will be a next step.

Eric Biggers (19):
lib/crypto: gf128hash: Rename polyval module to gf128hash lib/crypto: gf128hash: Support GF128HASH_ARCH without all POLYVAL
functions
lib/crypto: gf128hash: Add GHASH support
lib/crypto: tests: Add KUnit tests for GHASH
crypto: arm/ghash - Make the "ghash" crypto_shash NEON-only
crypto: arm/ghash - Move NEON GHASH assembly into its own file lib/crypto: arm/ghash: Migrate optimized code into library
crypto: arm64/ghash - Move NEON GHASH assembly into its own file lib/crypto: arm64/ghash: Migrate optimized code into library
crypto: arm64/aes-gcm - Rename struct ghash_key and make fixed-sized lib/crypto: powerpc/ghash: Migrate optimized code into library

Quoted 9 lines

lib/crypto: riscv/ghash: Migrate optimized code into library lib/crypto: s390/ghash: Migrate optimized code into library lib/crypto: x86/ghash: Migrate optimized code into library
crypto: gcm - Use GHASH library instead of crypto_ahash
crypto: ghash - Remove ghash from crypto_shash API lib/crypto: gf128mul: Remove unused 4k_lle functions lib/crypto: gf128hash: Remove unused content from ghash.h lib/crypto: aesgcm: Use GHASH library API

author maintainer Applied
#21 lore raw
In reply to Eric Biggers
Quoted 16 lines · Eric Biggers

This series is targeting libcrypto-next. It can also be retrieved from:

git fetch https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux.git ghash-lib-v1

This series migrates the standalone GHASH code to lib/crypto/, then converts the "gcm" template and AES-GCM library code to use it. (GHASH is the universal hash function used by GCM mode.) As was the case with POLYVAL and Poly1305 as well, the library is a much better fit for it.

Since GHASH and POLYVAL are closely related and it often makes sense to implement one in terms of the other, the existing "polyval" library module is renamed to "gf128hash" and the GHASH support is added to it.

The generic implementation of GHASH is also replaced with a better one utilizing the existing polyval_mul_generic().

Quoted 9 lines

Note that some GHASH implementations, often faster ones using more recent CPU features, still exist in arch/*/crypto/ as internal components of AES-GCM implementations. Those are left as-is for now. The goal with this GHASH library is just to provide parity with the existing standalone GHASH support, which is used when a full implementation of AES-GCM (or ${someothercipher}-GCM, if another block cipher is being used) is unavailable. Migrating the architecture-optimized AES-GCM code to lib/crypto/ will be a next step.

Applied to https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux.git/log/?h=libcrypto-next

As usual, the s390 code will need to be tested by someone who has the privilege of access to a z/Architecture mainframe. That is the only way to test that code, given that the s390 community has not yet updated QEMU to support the CPACF_KIMD_GHASH instruction.

From another review pass I also folded in some trivial cleanups that don't seem worth sending a v2 for unless something else comes up. Removed a definition I forgot to remove, dropped unnecessary rename of 'h' to 'k', improved consistency in a couple places, etc.

arch/arm64/crypto/ghash-ce-glue.c +0 -4
index c74066d430fa..eaf2932ceaf5 100644
@@ -35,10 +35,6 @@ struct arm_ghash_key {
 	u64			h[4][2];
 };
 
-struct arm_ghash_desc_ctx {
-	u64 digest[GHASH_DIGEST_SIZE/sizeof(u64)];
-};
-
 struct gcm_aes_ctx {
 	struct aes_enckey	aes_key;
 	u8			nonce[RFC4106_NONCE_SIZE];
lib/crypto/arm/gf128hash.h +1 -1
index cb929bed29d5..c33c8cbe51fe 100644
@@ -12,7 +12,7 @@
 static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_neon);
 
 void pmull_ghash_update_p8(size_t blocks, struct polyval_elem *dg,
-			   const u8 *src, const struct polyval_elem *k);
+			   const u8 *src, const struct polyval_elem *h);
 
 #define ghash_blocks_arch ghash_blocks_arch
 static void ghash_blocks_arch(struct polyval_elem *acc,
lib/crypto/arm/ghash-neon-core.S +1 -1
index bf423fb06a75..eeffd12504a9 100644
@@ -181,7 +181,7 @@
 	/*
 	 * void pmull_ghash_update_p8(size_t blocks, struct polyval_elem *dg,
 	 *			      const u8 *src,
-	 *			      const struct polyval_elem *k)
+	 *			      const struct polyval_elem *h)
 	 */
 ENTRY(pmull_ghash_update_p8)
 	vld1.64		{SHASH}, [r3]
lib/crypto/arm64/gf128hash.h +5 -5
index d5ef1b1b77e1..b2c85585b758 100644
@@ -12,14 +12,14 @@
 static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_asimd);
 static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_pmull);
 
+asmlinkage void pmull_ghash_update_p8(size_t blocks, struct polyval_elem *dg,
+				      const u8 *src,
+				      const struct polyval_elem *h);
 asmlinkage void polyval_mul_pmull(struct polyval_elem *a,
 				  const struct polyval_elem *b);
 asmlinkage void polyval_blocks_pmull(struct polyval_elem *acc,
 				     const struct polyval_key *key,
 				     const u8 *data, size_t nblocks);
-asmlinkage void pmull_ghash_update_p8(size_t blocks, struct polyval_elem *dg,
-				      const u8 *src,
-				      const struct polyval_elem *k);
 
 #define polyval_preparekey_arch polyval_preparekey_arch
 static void polyval_preparekey_arch(struct polyval_key *key,
@@ -91,8 +91,8 @@ static void ghash_blocks_arch(struct polyval_elem *acc,
 	if (static_branch_likely(&have_asimd) && may_use_simd()) {
 		do {
 			/* Allow rescheduling every 4 KiB. */
-			size_t n =
-				min_t(size_t, nblocks, 4096 / GHASH_BLOCK_SIZE);
+			size_t n = min_t(size_t, nblocks,
+					 4096 / GHASH_BLOCK_SIZE);
 
 			scoped_ksimd()
 				pmull_ghash_update_p8(n, acc, data, &key->h);
lib/crypto/arm64/ghash-neon-core.S +1 -1
index eadd6da47247..85b20fcd98fe 100644
@@ -180,7 +180,7 @@
 	/*
 	 * void pmull_ghash_update_p8(size_t blocks, struct polyval_elem *dg,
 	 *			      const u8 *src,
-	 *			      const struct polyval_elem *k)
+	 *			      const struct polyval_elem *h)
 	 */
 SYM_FUNC_START(pmull_ghash_update_p8)
 	ld1		{SHASH.2d}, [x3]
lib/crypto/riscv/ghash-riscv64-zvkg.S +2 -0
index 2839ff1a990c..6a2a2f2bc7c8 100644
@@ -55,6 +55,8 @@
 // void ghash_zvkg(u8 accumulator[GHASH_BLOCK_SIZE],
 //		   const u8 key[GHASH_BLOCK_SIZE],
 //		   const u8 *data, size_t nblocks);
+//
+// |nblocks| must be nonzero.
 SYM_FUNC_START(ghash_zvkg)
 	vsetivli	zero, 4, e32, m1, ta, ma
 	vle32.v		v1, (ACCUMULATOR)
lib/crypto/tests/Kconfig +1 -1
index 279ff1a339be..5b60d5c3644b 100644
@@ -41,7 +41,7 @@ config CRYPTO_LIB_GHASH_KUNIT_TEST
 	default KUNIT_ALL_TESTS
 	select CRYPTO_LIB_BENCHMARK_VISIBLE
 	help
-	  KUnit tests for GHASH library functions.
+	  KUnit tests for the GHASH library functions.
 
 config CRYPTO_LIB_MD5_KUNIT_TEST
 	tristate "KUnit tests for MD5" if !KUNIT_ALL_TESTS