NH library and Adiantum cleanup
Subsystems (9)
Eric Biggers
maintainercover NH library and Adiantum cleanup
This series can also be retrieved from:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux.git nh-lib-v1
This series removes the nhpoly1305 crypto_shash algorithm, which existed only to fit Adiantum hashing into the traditional Linux crypto API paradigm. It replaces it with an nh() library function, combined with code in the "adiantum" template that handles the Poly1305 step.
The result is simpler code. As usual, I've also fixed the issue where the architecture-optimized code was disabled by default.
I've also included some additional cleanups for the Adiantum code.
I'm planning to take this via libcrypto-next.
Eric Biggers (12):
lib/crypto: nh: Add NH library
lib/crypto: tests: Add KUnit tests for NH
lib/crypto: arm/nh: Migrate optimized code into library lib/crypto: arm64/nh: Migrate optimized code into library lib/crypto: x86/nh: Migrate optimized code into library
crypto: adiantum - Convert to use NH library
crypto: adiantum - Use scatter_walk API instead of sg_miter
crypto: adiantum - Use memcpy_{to,from}_sglist()
crypto: adiantum - Drop support for asynchronous xchacha ciphers
crypto: nhpoly1305 - Remove crypto_shash support
crypto: testmgr - Remove nhpoly1305 tests
fscrypt: Drop obsolete recommendation to enable optimized NHPoly1305
Documentation/filesystems/fscrypt.rst | 5 -
arch/arm/crypto/Kconfig | 10 -
arch/arm/crypto/Makefile | 2 -
arch/arm/crypto/nhpoly1305-neon-glue.c | 80 -
arch/arm64/crypto/Kconfig | 10 -
arch/arm64/crypto/Makefile | 3 -
arch/arm64/crypto/nhpoly1305-neon-glue.c | 79 -
arch/x86/crypto/Kconfig | 20 -
arch/x86/crypto/Makefile | 5 -
arch/x86/crypto/nhpoly1305-avx2-glue.c | 81 -
arch/x86/crypto/nhpoly1305-sse2-glue.c | 80 -
crypto/Kconfig | 8 +-
crypto/Makefile | 1 -
crypto/adiantum.c | 442 +++---
crypto/nhpoly1305.c | 255 ---
crypto/testmgr.c | 10 +-
crypto/testmgr.h | 1372 -----------------
include/crypto/nh.h | 52 +
include/crypto/nhpoly1305.h | 74 -
lib/crypto/Kconfig | 13 +
lib/crypto/Makefile | 11 +
.../crypto => lib/crypto/arm}/nh-neon-core.S | 0
lib/crypto/arm/nh.h | 33 +
.../crypto/arm64}/nh-neon-core.S | 3 +-
lib/crypto/arm64/nh.h | 34 +
lib/crypto/nh.c | 82 +
lib/crypto/tests/Kconfig | 8 +
lib/crypto/tests/Makefile | 1 +
lib/crypto/tests/nh-testvecs.h | 298 ++++
lib/crypto/tests/nh_kunit.c | 43 +
.../crypto/x86/nh-avx2.S | 3 +-
.../crypto/x86/nh-sse2.S | 3 +-
lib/crypto/x86/nh.h | 45 +
scripts/crypto/gen-hash-testvecs.py | 40 +
34 files changed, 909 insertions(+), 2297 deletions(-)
delete mode 100644 arch/arm/crypto/nhpoly1305-neon-glue.c
delete mode 100644 arch/arm64/crypto/nhpoly1305-neon-glue.c
delete mode 100644 arch/x86/crypto/nhpoly1305-avx2-glue.c
delete mode 100644 arch/x86/crypto/nhpoly1305-sse2-glue.c
delete mode 100644 crypto/nhpoly1305.c
create mode 100644 include/crypto/nh.h
delete mode 100644 include/crypto/nhpoly1305.h
rename {arch/arm/crypto => lib/crypto/arm}/nh-neon-core.S (100%)
create mode 100644 lib/crypto/arm/nh.h
rename {arch/arm64/crypto => lib/crypto/arm64}/nh-neon-core.S (97%)
create mode 100644 lib/crypto/arm64/nh.h
create mode 100644 lib/crypto/nh.c
create mode 100644 lib/crypto/tests/nh-testvecs.h
create mode 100644 lib/crypto/tests/nh_kunit.c
rename arch/x86/crypto/nh-avx2-x86_64.S => lib/crypto/x86/nh-avx2.S (98%)
rename arch/x86/crypto/nh-sse2-x86_64.S => lib/crypto/x86/nh-sse2.S (97%)
create mode 100644 lib/crypto/x86/nh.hbase-commit: 0914d5848096af6496c7aa5e1ac051fcdb3f755b
Signature · 1 line
2.52.0
Eric Biggers
maintainerPATCH 1/12 lib/crypto: nh: Add NH library
Add support for the NH "almost-universal hash function" to lib/crypto/, specifically the variant of NH used in Adiantum.
This will replace the need for the "nhpoly1305" crypto_shash algorithm. All the implementations of "nhpoly1305" use architecture-optimized code only for the NH stage; they just use the generic C Poly1305 code for the Poly1305 stage. We can achieve the same result in a simpler way using an (architecture-optimized) nh() function combined with code in crypto/adiantum.c that passes the results to the Poly1305 library.
This commit begins this cleanup by adding the nh() function. The code is derived from crypto/nhpoly1305.c and include/crypto/nhpoly1305.h.
--- include/crypto/nh.h | 52 ++++++++++++++++++++++++++++ lib/crypto/Kconfig | 10 ++++++ lib/crypto/Makefile | 8 +++++ lib/crypto/nh.c | 82 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 152 insertions(+) create mode 100644 include/crypto/nh.h create mode 100644 lib/crypto/nh.c
include/crypto/nh.h new file +52 -0
@@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* +* NH hash function for Adiantum +*/ + +#ifndef _CRYPTO_NH_H +#define _CRYPTO_NH_H + +#include <linux/types.h> + +/* NH parameterization: */ + +/* Endianness: little */ +/* Word size: 32 bits (works well on NEON, SSE2, AVX2) */ + +/* Stride: 2 words (optimal on ARM32 NEON; works okay on other CPUs too) */ +#define NH_PAIR_STRIDE 2 +#define NH_MESSAGE_UNIT (NH_PAIR_STRIDE * 2 * sizeof(u32)) + +/* Num passes (Toeplitz iteration count): 4, to give ε = 2^{-128} */ +#define NH_NUM_PASSES 4 +#define NH_HASH_BYTES (NH_NUM_PASSES * sizeof(u64)) + +/* Max message size: 1024 bytes (32x compression factor) */ +#define NH_NUM_STRIDES 64 +#define NH_MESSAGE_WORDS (NH_PAIR_STRIDE * 2 * NH_NUM_STRIDES) +#define NH_MESSAGE_BYTES (NH_MESSAGE_WORDS * sizeof(u32)) +#define NH_KEY_WORDS (NH_MESSAGE_WORDS + \ + NH_PAIR_STRIDE * 2 * (NH_NUM_PASSES - 1)) +#define NH_KEY_BYTES (NH_KEY_WORDS * sizeof(u32)) + +/** +* nh() - NH hash function for Adiantum +* @key: The key. @message_len + 48 bytes of it are used. This is NH_KEY_BYTES +* if @message_len has its maximum length of NH_MESSAGE_BYTES. +* @message: The message +* @message_len: The message length in bytes. Must be a multiple of 16 +* (NH_MESSAGE_UNIT) and at most 1024 (NH_MESSAGE_BYTES). +* @hash: (output) The resulting hash value +* +* Note: the pseudocode for NH in the Adiantum paper iterates over 1024-byte +* segments of the message, computes a 32-byte hash for each, and returns all +* the hashes concatenated together. In contrast, this function just hashes one +* segment and returns one hash. It's the caller's responsibility to call this +* function for each 1024-byte segment and collect all the hashes. +* +* Context: Any context. +*/ +void nh (const u32 *key,const u8 *message,size_t message_len, +__le64 hash[NH_NUM_PASSES ]); + +#endif /* _CRYPTO_NH_H */
lib/crypto/Kconfig +10 -0
@@ -106,10 +106,20 @@ config CRYPTO_LIB_MLDSA select CRYPTO_LIB_SHA3 help The ML-DSA library functions. Select this if your module uses any of the functions from <crypto/mldsa.h>. +config CRYPTO_LIB_NH + tristate + help + Implementation of the NH almost-universal hash function, specifically + the variant of NH used in Adiantum. + +config CRYPTO_LIB_NH_ARCH + bool + depends on CRYPTO_LIB_NH && !UML + config CRYPTO_LIB_POLY1305 tristate help The Poly1305 library functions. Select this if your module uses any of the functions from <crypto/poly1305.h>.
lib/crypto/Makefile +8 -0
@@ -129,10 +129,18 @@ endif # CONFIG_CRYPTO_LIB_MD5_ARCH obj-$(CONFIG_CRYPTO_LIB_MLDSA) += libmldsa.o libmldsa-y := mldsa.o ################################################################################ +obj-$(CONFIG_CRYPTO_LIB_NH) += libnh.o +libnh-y := nh.o +ifeq ($(CONFIG_CRYPTO_LIB_NH_ARCH),y) +CFLAGS_nh.o += -I$(src)/$(SRCARCH) +endif + +################################################################################ + obj-$(CONFIG_CRYPTO_LIB_POLY1305) += libpoly1305.o libpoly1305-y := poly1305.o ifeq ($(CONFIG_ARCH_SUPPORTS_INT128),y) libpoly1305-$(CONFIG_CRYPTO_LIB_POLY1305_GENERIC) += poly1305-donna64.o else
lib/crypto/nh.c new file +82 -0
82 lines not on this page · raw message
Signature · 1 line
2.52.0
Eric Biggers
maintainerPATCH 2/12 lib/crypto: tests: Add KUnit tests for NH
In reply to Eric BiggersAdd some simple KUnit tests for the nh() function.
These replace the test coverage which will be lost by removing the nhpoly1305 crypto_shash.
Note that the NH code also continues to be tested indirectly as well, via the tests for the "adiantum(xchacha12,aes)" crypto_skcipher.
--- lib/crypto/tests/Kconfig | 8 + lib/crypto/tests/Makefile | 1 + lib/crypto/tests/nh-testvecs.h | 298 ++++++++++++++++++++++++++++ lib/crypto/tests/nh_kunit.c | 43 ++++ scripts/crypto/gen-hash-testvecs.py | 40 ++++ 5 files changed, 390 insertions(+) create mode 100644 lib/crypto/tests/nh-testvecs.h create mode 100644 lib/crypto/tests/nh_kunit.c
lib/crypto/tests/Kconfig +8 -0
@@ -45,10 +45,18 @@ config CRYPTO_LIB_MLDSA_KUNIT_TEST select CRYPTO_LIB_BENCHMARK_VISIBLE select CRYPTO_LIB_MLDSA help KUnit tests for the ML-DSA digital signature algorithm. +config CRYPTO_LIB_NH_KUNIT_TEST + tristate "KUnit tests for NH" if !KUNIT_ALL_TESTS + depends on KUNIT + default KUNIT_ALL_TESTS || CRYPTO_SELFTESTS + select CRYPTO_LIB_NH + help + KUnit tests for the NH almost-universal hash function. + config CRYPTO_LIB_POLY1305_KUNIT_TEST tristate "KUnit tests for Poly1305" if !KUNIT_ALL_TESTS depends on KUNIT default KUNIT_ALL_TESTS || CRYPTO_SELFTESTS select CRYPTO_LIB_BENCHMARK_VISIBLE
lib/crypto/tests/Makefile +1 -0
@@ -3,10 +3,11 @@ 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_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 obj-$(CONFIG_CRYPTO_LIB_SHA1_KUNIT_TEST) += sha1_kunit.o obj-$(CONFIG_CRYPTO_LIB_SHA256_KUNIT_TEST) += sha224_kunit.o sha256_kunit.o obj-$(CONFIG_CRYPTO_LIB_SHA512_KUNIT_TEST) += sha384_kunit.o sha512_kunit.o
lib/crypto/tests/nh-testvecs.h new file +298 -0
298 lines not on this page · raw message
lib/crypto/tests/nh_kunit.c new file +43 -0
43 lines not on this page · raw message
scripts/crypto/gen-hash-testvecs.py +40 -0
@@ -182,10 +182,48 @@ def gen_additional_blake2_testvecs(alg): hashes += h.digest() print_static_u8_array_definition( f'{alg}_keyed_testvec_consolidated[{alg_digest_size_const(alg)}]', compute_hash(alg, hashes)) +def nh_extract_int(bytestr, pos, length): + assert pos % 8 == 0 and length % 8 == 0 + return int.from_bytes(bytestr[pos//8 : pos//8 + length//8], byteorder='little') + +# The NH "almost-universal hash function" used in Adiantum. This is a +# straightforward translation of the pseudocode from Section 6.3 of the Adiantum +# paper (https://eprint.iacr.org/2018/720.pdf), except the outer loop is omitted +# because we assume len(msg) <= 1024. (The kernel's nh() function is only +# expected to handle up to 1024 bytes; it's just called repeatedly as needed.) +def nh(key, msg): + (w, s, r, u) = (32, 2, 4, 8192) + l = 8 * len(msg) + assert l <= u + assert l % (2*s*w) == 0 + h = bytes() + for i in range(0, 2*s*w*r, 2*s*w): + p = 0 + for j in range(0, l, 2*s*w): + for k in range(0, w*s, w): + a0 = nh_extract_int(key, i + j + k, w) + a1 = nh_extract_int(key, i + j + k + s*w, w) + b0 = nh_extract_int(msg, j + k, w) + b1 = nh_extract_int(msg, j + k + s*w, w) + p += ((a0 + b0) % 2**w) * ((a1 + b1) % 2**w) + h += (p % 2**64).to_bytes(8, byteorder='little') + return h + +def gen_nh_testvecs(): + NH_KEY_BYTES = 1072 + NH_MESSAGE_BYTES = 1024 + key = rand_bytes(NH_KEY_BYTES) + msg = rand_bytes(NH_MESSAGE_BYTES) + print_static_u8_array_definition('nh_test_key[NH_KEY_BYTES]', key) + print_static_u8_array_definition('nh_test_msg[NH_MESSAGE_BYTES]', msg) + for length in [16, 96, 256, 1024]: + print_static_u8_array_definition(f'nh_test_val{length}[NH_HASH_BYTES]', + nh(key, msg[:length])) + def gen_additional_poly1305_testvecs(): key = b'\xff' * POLY1305_KEY_SIZE data = b'' ctx = Poly1305(key) for _ in range(32):
@@ -215,10 +253,12 @@ alg = sys.argv[1] print('/* SPDX-License-Identifier: GPL-2.0-or-later */') print(f'/* This file was generated by: {sys.argv[0]} {" ".join(sys.argv[1:])} */') if alg.startswith('blake2'): gen_unkeyed_testvecs(alg) gen_additional_blake2_testvecs(alg) +elif alg == 'nh': + gen_nh_testvecs() elif alg == 'poly1305': gen_unkeyed_testvecs(alg) gen_additional_poly1305_testvecs() elif alg == 'polyval': gen_unkeyed_testvecs(alg)
Signature · 1 line
2.52.0
Re: [PATCH 02/12] lib/crypto: tests: Add KUnit tests for NH
Hi Eric,
Quoted 9 lines · Eric Biggers
Add some simple KUnit tests for the
nh()function.These replace the test coverage which will be lost by removing the nhpoly1305
crypto_shash.Note that the NH code also continues to be tested indirectly as well, via the tests for the "
adiantum(xchacha12,aes)"crypto_skcipher.Signed-off-by Eric Biggers <[email protected]>
Thanks for your patch, which is now commit 7246fe6cd64475d8 ("lib/crypto: tests: Add KUnit tests for NH") in v7.0-rc1.
lib/crypto/tests/Kconfig config CRYPTO_LIB_MLDSA_KUNIT_TEST · line 54
Quoted 13 lines
lib/crypto/tests/Kconfig +5
-0@@ -45,10 +45,18 @@ config CRYPTO_LIB_MLDSA_KUNIT_TEST select CRYPTO_LIB_BENCHMARK_VISIBLE select CRYPTO_LIB_MLDSA help KUnit tests for the ML-DSA digital signature algorithm. +config CRYPTO_LIB_NH_KUNIT_TEST + tristate "KUnit tests for NH" if !KUNIT_ALL_TESTS + depends on KUNIT + default KUNIT_ALL_TESTS || CRYPTO_SELFTESTS + select CRYPTO_LIB_NH
This select means that enabling KUNIT_ALL_TESTS also enables extra functionality, which may not be desirable in a production system. Fortunately CRYPTO_LIB_NH is tristate, so in the modular case the extra functionality is a module, too, and not part of the running system by default. Unfortunately CRYPTO_LIB_NH is invisible, so this cannot just be changed from "select" to "depends on".
lib/crypto/tests/Kconfig config CRYPTO_LIB_MLDSA_KUNIT_TEST · line 62
Quoted 8 lines
lib/crypto/tests/Kconfig +3
-0+ help + KUnit tests for the NH almost-universal hash function. + config CRYPTO_LIB_POLY1305_KUNIT_TEST tristate "KUnit tests for Poly1305" if !KUNIT_ALL_TESTS depends on KUNIT default KUNIT_ALL_TESTS || CRYPTO_SELFTESTS select CRYPTO_LIB_BENCHMARK_VISIBLE
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]
In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
Eric Biggers
maintainerRe: [PATCH 02/12] lib/crypto: tests: Add KUnit tests for NH
Quoted 24 lines · Geert Uytterhoeven
Hi Eric,
Quoted 9 lines · Eric Biggers
Add some simple KUnit tests for the
nh()function.These replace the test coverage which will be lost by removing the nhpoly1305
crypto_shash.Note that the NH code also continues to be tested indirectly as well, via the tests for the "
adiantum(xchacha12,aes)"crypto_skcipher.Signed-off-by Eric Biggers <[email protected]>Thanks for your patch, which is now commit
7246fe6cd64475d8("lib/crypto: tests: Add KUnit tests for NH") in v7.0-rc1.Quoted 8 lines
lib/crypto/tests/Kconfig +0
-0@@ -45,10 +45,18 @@ config CRYPTO_LIB_MLDSA_KUNIT_TEST select CRYPTO_LIB_BENCHMARK_VISIBLE select CRYPTO_LIB_MLDSA help KUnit tests for the ML-DSA digital signature algorithm.
Quoted 12 lines
lib/crypto/tests/Kconfig config CRYPTO_LIB_MLDSA_KUNIT_TEST · line 54
Quoted 5 lines
lib/crypto/tests/Kconfig +5
-0+config CRYPTO_LIB_NH_KUNIT_TEST + tristate "KUnit tests for NH" if !KUNIT_ALL_TESTS + depends on KUNIT + default KUNIT_ALL_TESTS || CRYPTO_SELFTESTS + select CRYPTO_LIB_NHThis select means that enabling
KUNIT_ALL_TESTSalso enables extra functionality, which may not be desirable in a production system. FortunatelyCRYPTO_LIB_NHis tristate, so in the modular case the extra functionality is a module, too, and not part of the running system by default. UnfortunatelyCRYPTO_LIB_NHis invisible, so this cannot just be changed from "select" to "depends on".
I'll probably be changing this, pending the result of the discussion on the similar thread about CRYPTO_LIB_MLDSA_KUNIT_TEST:
https://lore.kernel.org/linux-crypto/20260226180538.GC2251@sol/
- Eric
Eric Biggers
maintainerPATCH 3/12 lib/crypto: arm/nh: Migrate optimized code into library
In reply to Eric BiggersMigrate the arm32 NEON implementation of NH into lib/crypto/. This makes the nh() function be optimized on arm32 kernels.
Note: this temporarily makes the adiantum template not utilize the arm32 optimized NH code. This is resolved in a later commit that converts the adiantum template to use nh() instead of "nhpoly1305".
---
arch/arm/crypto/Kconfig | 10 ---
arch/arm/crypto/Makefile | 2 -
arch/arm/crypto/nhpoly1305-neon-glue.c | 80 -------------------
lib/crypto/Kconfig | 1 +
lib/crypto/Makefile | 1 +
.../crypto => lib/crypto/arm}/nh-neon-core.S | 0
lib/crypto/arm/nh.h | 33 ++++++++
7 files changed, 35 insertions(+), 92 deletions(-)
delete mode 100644 arch/arm/crypto/nhpoly1305-neon-glue.c
rename {arch/arm/crypto => lib/crypto/arm}/nh-neon-core.S (100%)
create mode 100644 lib/crypto/arm/nh.harch/arm/crypto/Kconfig +0 -10
@@ -21,20 +21,10 @@ config CRYPTO_GHASH_ARM_CE 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_NHPOLY1305_NEON - tristate "Hash functions: NHPoly1305 (NEON)" - depends on KERNEL_MODE_NEON - select CRYPTO_NHPOLY1305 - help - NHPoly1305 hash function (Adiantum) - - Architecture: arm using: - - NEON (Advanced SIMD) extensions - config CRYPTO_AES_ARM tristate "Ciphers: AES" select CRYPTO_ALGAPI select CRYPTO_AES help
arch/arm/crypto/Makefile +0 -2
@@ -3,15 +3,13 @@ # Arch-specific CryptoAPI modules. # obj-$(CONFIG_CRYPTO_AES_ARM) += aes-arm.o obj-$(CONFIG_CRYPTO_AES_ARM_BS) += aes-arm-bs.o -obj-$(CONFIG_CRYPTO_NHPOLY1305_NEON) += nhpoly1305-neon.o obj-$(CONFIG_CRYPTO_AES_ARM_CE) += aes-arm-ce.o obj-$(CONFIG_CRYPTO_GHASH_ARM_CE) += ghash-arm-ce.o aes-arm-y := aes-cipher-core.o aes-cipher-glue.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 -nhpoly1305-neon-y := nh-neon-core.o nhpoly1305-neon-glue.o
arch/arm/crypto/nhpoly1305-neon-glue.c deleted +0 -80
80 lines not on this page · raw message
lib/crypto/Kconfig +1 -0
@@ -115,10 +115,11 @@ config CRYPTO_LIB_NH the variant of NH used in Adiantum. config CRYPTO_LIB_NH_ARCH bool depends on CRYPTO_LIB_NH && !UML + default y if ARM && KERNEL_MODE_NEON config CRYPTO_LIB_POLY1305 tristate help The Poly1305 library functions. Select this if your module uses any
lib/crypto/Makefile +1 -0
@@ -133,10 +133,11 @@ libmldsa-y := mldsa.o obj-$(CONFIG_CRYPTO_LIB_NH) += libnh.o libnh-y := nh.o ifeq ($(CONFIG_CRYPTO_LIB_NH_ARCH),y) CFLAGS_nh.o += -I$(src)/$(SRCARCH) +libnh-$(CONFIG_ARM) += arm/nh-neon-core.o endif ################################################################################ obj-$(CONFIG_CRYPTO_LIB_POLY1305) += libpoly1305.o
lib/crypto/arm/nh-neon-core.S renamed from arch/arm/crypto/nh-neon-core.S +0 -0
lib/crypto/arm/nh.h new file +33 -0
@@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* +* ARM32 accelerated implementation of NH +* +* Copyright 2018 Google LLC +*/ + +#include <asm/neon.h> +#include <asm/simd.h> + +static __ro_after_init DEFINE_STATIC_KEY_FALSE (have_neon); + +asmlinkage void nh_neon(const u32 *key, const u8 *message, size_t message_len, +__le64 hash[NH_NUM_PASSES ]); + +static bool nh_arch (const u32 *key,const u8 *message,size_t message_len, +__le64 hash[NH_NUM_PASSES ]) +{ +if (static_branch_likely (&have_neon) && message_len >=64 && +may_use_simd ()) { + scoped_ksimd() +nh_neon (key, message, message_len, hash); +return true; + } +return false; +} + +#define nh_mod_init_arch nh_mod_init_arch +static void nh_mod_init_arch (void ) +{ +if (elf_hwcap &HWCAP_NEON ) +static_branch_enable (&have_neon); +}
Signature · 1 line
2.52.0
Eric Biggers
maintainerPATCH 4/12 lib/crypto: arm64/nh: Migrate optimized code into library
In reply to Eric BiggersMigrate the arm64 NEON implementation of NH into lib/crypto/. This makes the nh() function be optimized on arm64 kernels.
Note: this temporarily makes the adiantum template not utilize the arm64 optimized NH code. This is resolved in a later commit that converts the adiantum template to use nh() instead of "nhpoly1305".
---
arch/arm64/crypto/Kconfig | 10 ---
arch/arm64/crypto/Makefile | 3 -
arch/arm64/crypto/nhpoly1305-neon-glue.c | 79 -------------------
lib/crypto/Kconfig | 1 +
lib/crypto/Makefile | 1 +
.../crypto/arm64}/nh-neon-core.S | 3 +-
lib/crypto/arm64/nh.h | 34 ++++++++
7 files changed, 37 insertions(+), 94 deletions(-)
delete mode 100644 arch/arm64/crypto/nhpoly1305-neon-glue.c
rename {arch/arm64/crypto => lib/crypto/arm64}/nh-neon-core.S (97%)
create mode 100644 lib/crypto/arm64/nh.harch/arm64/crypto/Kconfig +0 -10
@@ -13,20 +13,10 @@ config CRYPTO_GHASH_ARM64_CE GCM GHASH function (NIST SP800-38D) Architecture: arm64 using: - ARMv8 Crypto Extensions -config CRYPTO_NHPOLY1305_NEON - tristate "Hash functions: NHPoly1305 (NEON)" - depends on KERNEL_MODE_NEON - select CRYPTO_NHPOLY1305 - help - NHPoly1305 hash function (Adiantum) - - Architecture: arm64 using: - - NEON (Advanced SIMD) extensions - config CRYPTO_SM3_NEON tristate "Hash functions: SM3 (NEON)" depends on KERNEL_MODE_NEON select CRYPTO_HASH select CRYPTO_LIB_SM3
arch/arm64/crypto/Makefile +0 -3
@@ -39,13 +39,10 @@ obj-$(CONFIG_CRYPTO_AES_ARM64_CE_BLK) += aes-ce-blk.o aes-ce-blk-y := aes-glue-ce.o aes-ce.o obj-$(CONFIG_CRYPTO_AES_ARM64_NEON_BLK) += aes-neon-blk.o aes-neon-blk-y := aes-glue-neon.o aes-neon.o -obj-$(CONFIG_CRYPTO_NHPOLY1305_NEON) += nhpoly1305-neon.o -nhpoly1305-neon-y := nh-neon-core.o nhpoly1305-neon-glue.o - obj-$(CONFIG_CRYPTO_AES_ARM64) += aes-arm64.o aes-arm64-y := aes-cipher-core.o aes-cipher-glue.o obj-$(CONFIG_CRYPTO_AES_ARM64_BS) += aes-neon-bs.o aes-neon-bs-y := aes-neonbs-core.o aes-neonbs-glue.o
arch/arm64/crypto/nhpoly1305-neon-glue.c deleted +0 -79
79 lines not on this page · raw message
lib/crypto/Kconfig +1 -0
@@ -116,10 +116,11 @@ config CRYPTO_LIB_NH config CRYPTO_LIB_NH_ARCH bool depends on CRYPTO_LIB_NH && !UML default y if ARM && KERNEL_MODE_NEON + default y if ARM64 && KERNEL_MODE_NEON config CRYPTO_LIB_POLY1305 tristate help The Poly1305 library functions. Select this if your module uses any
lib/crypto/Makefile +1 -0
@@ -134,10 +134,11 @@ libmldsa-y := mldsa.o obj-$(CONFIG_CRYPTO_LIB_NH) += libnh.o libnh-y := nh.o ifeq ($(CONFIG_CRYPTO_LIB_NH_ARCH),y) CFLAGS_nh.o += -I$(src)/$(SRCARCH) libnh-$(CONFIG_ARM) += arm/nh-neon-core.o +libnh-$(CONFIG_ARM64) += arm64/nh-neon-core.o endif ################################################################################ obj-$(CONFIG_CRYPTO_LIB_POLY1305) += libpoly1305.o
lib/crypto/arm64/nh-neon-core.S renamed from arch/arm64/crypto/nh-neon-core.S +1 -2
@@ -6,11 +6,10 @@ * * Author: Eric Biggers <[email protected]> */ #include <linux/linkage.h> -#include <linux/cfi_types.h> KEY .req x0 MESSAGE .req x1 MESSAGE_LEN .req x2 HASH .req x3
@@ -61,11 +60,11 @@ * void nh_neon(const u32 *key, const u8 *message, size_t message_len, * __le64 hash[NH_NUM_PASSES]) * * It's guaranteed that message_len % 16 == 0. */ -SYM_TYPED_FUNC_START(nh_neon) +SYM_FUNC_START(nh_neon) ld1 {K0.4s,K1.4s}, [KEY], #32 movi PASS0_SUMS.2d, #0 movi PASS1_SUMS.2d, #0 ld1 {K2.4s}, [KEY], #16
lib/crypto/arm64/nh.h new file +34 -0
@@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* +* ARM64 accelerated implementation of NH +* +* Copyright 2018 Google LLC +*/ + +#include <asm/hwcap.h> +#include <asm/simd.h> +#include <linux/cpufeature.h> + +static __ro_after_init DEFINE_STATIC_KEY_FALSE (have_neon); + +asmlinkage void nh_neon(const u32 *key, const u8 *message, size_t message_len, +__le64 hash[NH_NUM_PASSES ]); + +static bool nh_arch (const u32 *key,const u8 *message,size_t message_len, +__le64 hash[NH_NUM_PASSES ]) +{ +if (static_branch_likely (&have_neon) && message_len >=64 && +may_use_simd ()) { + scoped_ksimd() +nh_neon (key, message, message_len, hash); +return true; + } +return false; +} + +#define nh_mod_init_arch nh_mod_init_arch +static void nh_mod_init_arch (void ) +{ +if (cpu_have_named_feature (ASIMD )) +static_branch_enable (&have_neon); +}
Signature · 1 line
2.52.0
Eric Biggers
maintainerPATCH 5/12 lib/crypto: x86/nh: Migrate optimized code into library
In reply to Eric BiggersMigrate the x86_64 implementations of NH into lib/crypto/. This makes the nh() function be optimized on x86_64 kernels.
Note: this temporarily makes the adiantum template not utilize the x86_64 optimized NH code. This is resolved in a later commit that converts the adiantum template to use nh() instead of "nhpoly1305".
--- arch/x86/crypto/Kconfig | 20 ----- arch/x86/crypto/Makefile | 5 -- arch/x86/crypto/nhpoly1305-avx2-glue.c | 81 ------------------- arch/x86/crypto/nhpoly1305-sse2-glue.c | 80 ------------------ lib/crypto/Kconfig | 1 + lib/crypto/Makefile | 1 + .../crypto/x86/nh-avx2.S | 3 +- .../crypto/x86/nh-sse2.S | 3 +- lib/crypto/x86/nh.h | 45 +++++++++++ 9 files changed, 49 insertions(+), 190 deletions(-) delete mode 100644 arch/x86/crypto/nhpoly1305-avx2-glue.c delete mode 100644 arch/x86/crypto/nhpoly1305-sse2-glue.c rename arch/x86/crypto/nh-avx2-x86_64.S => lib/crypto/x86/nh-avx2.S (98%) rename arch/x86/crypto/nh-sse2-x86_64.S => lib/crypto/x86/nh-sse2.S (97%) create mode 100644 lib/crypto/x86/nh.h
arch/x86/crypto/Kconfig +0 -20
@@ -331,30 +331,10 @@ config CRYPTO_AEGIS128_AESNI_SSE2 Architecture: x86_64 using: - AES-NI (AES New Instructions) - SSE4.1 (Streaming SIMD Extensions 4.1) -config CRYPTO_NHPOLY1305_SSE2 - tristate "Hash functions: NHPoly1305 (SSE2)" - depends on 64BIT - select CRYPTO_NHPOLY1305 - help - NHPoly1305 hash function for Adiantum - - Architecture: x86_64 using: - - SSE2 (Streaming SIMD Extensions 2) - -config CRYPTO_NHPOLY1305_AVX2 - tristate "Hash functions: NHPoly1305 (AVX2)" - depends on 64BIT - select CRYPTO_NHPOLY1305 - help - NHPoly1305 hash function for Adiantum - - Architecture: x86_64 using: - - AVX2 (Advanced Vector Extensions 2) - config CRYPTO_SM3_AVX_X86_64 tristate "Hash functions: SM3 (AVX)" depends on 64BIT select CRYPTO_HASH select CRYPTO_LIB_SM3
arch/x86/crypto/Makefile +0 -5
@@ -51,15 +51,10 @@ aesni-intel-$(CONFIG_64BIT) += aes-ctr-avx-x86_64.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_NHPOLY1305_SSE2) += nhpoly1305-sse2.o -nhpoly1305-sse2-y := nh-sse2-x86_64.o nhpoly1305-sse2-glue.o -obj-$(CONFIG_CRYPTO_NHPOLY1305_AVX2) += nhpoly1305-avx2.o -nhpoly1305-avx2-y := nh-avx2-x86_64.o nhpoly1305-avx2-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/nhpoly1305-avx2-glue.c deleted +0 -81
81 lines not on this page · raw message
arch/x86/crypto/nhpoly1305-sse2-glue.c deleted +0 -80
80 lines not on this page · raw message
lib/crypto/Kconfig +1 -0
@@ -117,10 +117,11 @@ config CRYPTO_LIB_NH config CRYPTO_LIB_NH_ARCH bool depends on CRYPTO_LIB_NH && !UML default y if ARM && KERNEL_MODE_NEON default y if ARM64 && KERNEL_MODE_NEON + default y if X86_64 config CRYPTO_LIB_POLY1305 tristate help The Poly1305 library functions. Select this if your module uses any
lib/crypto/Makefile +1 -0
@@ -135,10 +135,11 @@ obj-$(CONFIG_CRYPTO_LIB_NH) += libnh.o libnh-y := nh.o ifeq ($(CONFIG_CRYPTO_LIB_NH_ARCH),y) CFLAGS_nh.o += -I$(src)/$(SRCARCH) libnh-$(CONFIG_ARM) += arm/nh-neon-core.o libnh-$(CONFIG_ARM64) += arm64/nh-neon-core.o +libnh-$(CONFIG_X86) += x86/nh-sse2.o x86/nh-avx2.o endif ################################################################################ obj-$(CONFIG_CRYPTO_LIB_POLY1305) += libpoly1305.o
lib/crypto/x86/nh-avx2.S renamed from arch/x86/crypto/nh-avx2-x86_64.S +1 -2
@@ -6,11 +6,10 @@ * * Author: Eric Biggers <[email protected]> */ #include <linux/linkage.h> -#include <linux/cfi_types.h> #define PASS0_SUMS %ymm0 #define PASS1_SUMS %ymm1 #define PASS2_SUMS %ymm2 #define PASS3_SUMS %ymm3
@@ -68,11 +67,11 @@ * void nh_avx2(const u32 *key, const u8 *message, size_t message_len, * __le64 hash[NH_NUM_PASSES]) * * It's guaranteed that message_len % 16 == 0. */ -SYM_TYPED_FUNC_START(nh_avx2) +SYM_FUNC_START(nh_avx2) vmovdqu 0x00(KEY), K0 vmovdqu 0x10(KEY), K1 add $0x20, KEY vpxor PASS0_SUMS, PASS0_SUMS, PASS0_SUMS
lib/crypto/x86/nh-sse2.S renamed from arch/x86/crypto/nh-sse2-x86_64.S +1 -2
@@ -6,11 +6,10 @@ * * Author: Eric Biggers <[email protected]> */ #include <linux/linkage.h> -#include <linux/cfi_types.h> #define PASS0_SUMS %xmm0 #define PASS1_SUMS %xmm1 #define PASS2_SUMS %xmm2 #define PASS3_SUMS %xmm3
@@ -70,11 +69,11 @@ * void nh_sse2(const u32 *key, const u8 *message, size_t message_len, * __le64 hash[NH_NUM_PASSES]) * * It's guaranteed that message_len % 16 == 0. */ -SYM_TYPED_FUNC_START(nh_sse2) +SYM_FUNC_START(nh_sse2) movdqu 0x00(KEY), K0 movdqu 0x10(KEY), K1 movdqu 0x20(KEY), K2 add $0x30, KEY
lib/crypto/x86/nh.h new file +45 -0
45 lines not on this page · raw message
Signature · 1 line
2.52.0
Eric Biggers
maintainerPATCH 6/12 crypto: adiantum - Convert to use NH library
In reply to Eric BiggersReimplement the Adiantum message hashing using the nh() library function, combined with some code which directly handles the Poly1305 stage. The latter code is derived from crypto/nhpoly1305.c.
This eliminates the dependency on the "nhpoly1305" crypto_shash algorithm, which existed only to fit Adiantum message hashing into the traditional Linux crypto API paradigm. Now that simple, architecture-optimized library functions are a well-established option too, we can switch to this simpler implementation.
Note: I've dropped the support for the optional third parameter of the adiantum template, which specified the nhpoly1305 implementation. We could keep accepting some strings in this parameter for backwards compatibility, but I don't think it's being used. I believe only "adiantum(xchacha12,aes)" and "adiantum(xchacha20,aes)" are used.
--- crypto/Kconfig | 2 +- crypto/adiantum.c | 295 +++++++++++++++++++++++++++++----------------- crypto/testmgr.c | 4 +- 3 files changed, 191 insertions(+), 110 deletions(-)
crypto/Kconfig +1 -1
@@ -599,13 +599,13 @@ endmenu menu "Length-preserving ciphers and modes" config CRYPTO_ADIANTUM tristate "Adiantum" select CRYPTO_CHACHA20 + select CRYPTO_LIB_NH select CRYPTO_LIB_POLY1305 select CRYPTO_LIB_POLY1305_GENERIC - select CRYPTO_NHPOLY1305 select CRYPTO_MANAGER help Adiantum tweakable, length-preserving encryption mode Designed for fast and secure disk encryption, especially on
crypto/adiantum.c +188 -107
562 lines not on this page · raw message
crypto/testmgr.c +2 -2
@@ -4059,18 +4059,18 @@ static int alg_test_null(const struct alg_test_desc *desc,/* Please keep this list sorted by algorithm name. */ static const struct alg_test_desc alg_test_descs[] = { { .alg ="adiantum(xchacha12,aes)" , - .generic_driver ="adiantum(xchacha12-lib,aes-generic,nhpoly1305-generic)" , + .generic_driver ="adiantum(xchacha12-lib,aes-generic)" , .test = alg_test_skcipher, .suite = { .cipher =__VECS (adiantum_xchacha12_aes_tv_template) }, }, { .alg ="adiantum(xchacha20,aes)" , - .generic_driver ="adiantum(xchacha20-lib,aes-generic,nhpoly1305-generic)" , + .generic_driver ="adiantum(xchacha20-lib,aes-generic)" , .test = alg_test_skcipher, .suite = { .cipher =__VECS (adiantum_xchacha20_aes_tv_template) }, }, {
Signature · 1 line
2.52.0
Eric Biggers
maintainerPATCH 7/12 crypto: adiantum - Use scatter_walk API instead of sg_miter
In reply to Eric BiggersMake adiantum_hash_message() use the scatter_walk API instead of sg_miter. scatter_walk is a bit simpler and also more efficient. For example, unlike sg_miter, scatter_walk doesn't require that the number of scatterlist entries be calculated up-front.
--- crypto/adiantum.c | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-)
crypto/adiantum.c +15 -18
@@ -367,30 +367,27 @@ static void nhpoly1305_final(struct nhpoly1305_ctx *ctx,* evaluated as a polynomial in GF(2^{130}-5), like in the Poly1305 MAC. Note * that the polynomial evaluation by itself would suffice to achieve the ε-∆U * property; NH is used for performance since it's much faster than Poly1305. */ static void adiantum_hash_message (struct skcipher_request *req, -struct scatterlist *sgl,unsigned int nents, -le128 *out) +struct scatterlist *sgl,le128 *out) {struct crypto_skcipher *tfm =crypto_skcipher_reqtfm (req);const struct adiantum_tfm_ctx *tctx =crypto_skcipher_ctx (tfm);struct adiantum_request_ctx *rctx =skcipher_request_ctx (req); -const unsigned int bulk_len = req->cryptlen -BLOCKCIPHER_BLOCK_SIZE ; -struct sg_mapping_iter miter; -unsigned int i, n; +unsigned int len = req->cryptlen -BLOCKCIPHER_BLOCK_SIZE ; +struct scatter_walk walk;nhpoly1305_init (&rctx->u.hash_ctx); +scatterwalk_start (&walk, sgl); +while (len) { +unsigned int n =scatterwalk_next (&walk, len); -sg_miter_start (&miter, sgl, nents,SG_MITER_FROM_SG |SG_MITER_ATOMIC ); -for (i =0 ; i < bulk_len; i += n) { -sg_miter_next (&miter); - n = min_t(unsigned int, miter.length, bulk_len - i); -nhpoly1305_update (&rctx->u.hash_ctx, tctx, miter.addr, n); +nhpoly1305_update (&rctx->u.hash_ctx, tctx, walk.addr, n); +scatterwalk_done_src (&walk, n); + len -= n; } -sg_miter_stop (&miter); -nhpoly1305_final (&rctx->u.hash_ctx, tctx, out); }/* Continue Adiantum encryption/decryption after the stream cipher step */ static int adiantum_finish (struct skcipher_request *req)
@@ -398,11 +395,10 @@ static int adiantum_finish(struct skcipher_request *req)struct crypto_skcipher *tfm =crypto_skcipher_reqtfm (req);const struct adiantum_tfm_ctx *tctx =crypto_skcipher_ctx (tfm);struct adiantum_request_ctx *rctx =skcipher_request_ctx (req);const unsigned int bulk_len = req->cryptlen -BLOCKCIPHER_BLOCK_SIZE ;struct scatterlist *dst = req->dst; -const unsigned int dst_nents =sg_nents (dst);le128 digest;/* If decrypting, decrypt C_M with the block cipher to get P_M */ if (!rctx->enc) crypto_cipher_decrypt_one(tctx->blockcipher, rctx->rbuf.bytes,
@@ -412,11 +408,12 @@ static int adiantum_finish(struct skcipher_request *req)* Second hash step * enc: C_R = C_M - H_{K_H}(T, C_L) * dec: P_R = P_M - H_{K_H}(T, P_L) */ le128_sub (&rctx->rbuf.bignum, &rctx->rbuf.bignum, &rctx->header_hash); -if (dst_nents ==1 && dst->offset + req->cryptlen <=PAGE_SIZE ) { +if (dst->length >= req->cryptlen && + dst->offset + req->cryptlen <=PAGE_SIZE ) {/* Fast path for single-page destination */ struct page *page =sg_page (dst);void *virt =kmap_local_page (page) + dst->offset;nhpoly1305_init (&rctx->u.hash_ctx);
@@ -426,11 +423,11 @@ static int adiantum_finish(struct skcipher_request *req)memcpy (virt + bulk_len, &rctx->rbuf.bignum,sizeof (le128));flush_dcache_page (page);kunmap_local (virt); }else {/* Slow path that works for any destination scatterlist */ -adiantum_hash_message (req, dst, dst_nents, &digest); +adiantum_hash_message (req, dst, &digest);le128_sub (&rctx->rbuf.bignum, &rctx->rbuf.bignum, &digest);scatterwalk_map_and_copy (&rctx->rbuf.bignum, dst, bulk_len,sizeof (le128),1 ); }return 0 ;
@@ -451,11 +448,10 @@ static int adiantum_crypt(struct skcipher_request *req, bool enc)struct crypto_skcipher *tfm =crypto_skcipher_reqtfm (req);const struct adiantum_tfm_ctx *tctx =crypto_skcipher_ctx (tfm);struct adiantum_request_ctx *rctx =skcipher_request_ctx (req);const unsigned int bulk_len = req->cryptlen -BLOCKCIPHER_BLOCK_SIZE ;struct scatterlist *src = req->src; -const unsigned int src_nents =sg_nents (src);unsigned int stream_len;le128 digest;if (req->cryptlen <BLOCKCIPHER_BLOCK_SIZE )return -EINVAL ;
@@ -466,22 +462,23 @@ static int adiantum_crypt(struct skcipher_request *req, bool enc)* First hash step * enc: P_M = P_R + H_{K_H}(T, P_L) * dec: C_M = C_R + H_{K_H}(T, C_L) */ adiantum_hash_header (req); -if (src_nents ==1 && src->offset + req->cryptlen <=PAGE_SIZE ) { +if (src->length >= req->cryptlen && + src->offset + req->cryptlen <=PAGE_SIZE ) {/* Fast path for single-page source */ void *virt =kmap_local_page (sg_page (src)) + src->offset;nhpoly1305_init (&rctx->u.hash_ctx);nhpoly1305_update (&rctx->u.hash_ctx, tctx, virt, bulk_len);nhpoly1305_final (&rctx->u.hash_ctx, tctx, &digest);memcpy (&rctx->rbuf.bignum, virt + bulk_len,sizeof (le128));kunmap_local (virt); }else {/* Slow path that works for any source scatterlist */ -adiantum_hash_message (req, src, src_nents, &digest); +adiantum_hash_message (req, src, &digest);scatterwalk_map_and_copy (&rctx->rbuf.bignum, src, bulk_len,sizeof (le128),0 ); }le128_add (&rctx->rbuf.bignum, &rctx->rbuf.bignum, &rctx->header_hash);le128_add (&rctx->rbuf.bignum, &rctx->rbuf.bignum, &digest);
Signature · 1 line
2.52.0
Eric Biggers
maintainerPATCH 8/12 crypto: adiantum - Use memcpy_{to,from}_sglist()
In reply to Eric BiggersCall the newer, easier-to-read functions memcpy_to_sglist() and memcpy_from_sglist() directly instead of calling scatterwalk_map_and_copy(). No change in behavior.
--- crypto/adiantum.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
crypto/adiantum.c +4 -4
@@ -425,12 +425,12 @@ static int adiantum_finish(struct skcipher_request *req)kunmap_local (virt); }else {/* Slow path that works for any destination scatterlist */ adiantum_hash_message (req, dst, &digest);le128_sub (&rctx->rbuf.bignum, &rctx->rbuf.bignum, &digest); -scatterwalk_map_and_copy (&rctx->rbuf.bignum, dst, - bulk_len,sizeof (le128),1 ); +memcpy_to_sglist (dst, bulk_len, &rctx->rbuf.bignum, +sizeof (le128)); }return 0 ; }static void adiantum_streamcipher_done (void *data,int err)
@@ -475,12 +475,12 @@ static int adiantum_crypt(struct skcipher_request *req, bool enc)memcpy (&rctx->rbuf.bignum, virt + bulk_len,sizeof (le128));kunmap_local (virt); }else {/* Slow path that works for any source scatterlist */ adiantum_hash_message (req, src, &digest); -scatterwalk_map_and_copy (&rctx->rbuf.bignum, src, - bulk_len,sizeof (le128),0 ); +memcpy_from_sglist (&rctx->rbuf.bignum, src, bulk_len, +sizeof (le128)); }le128_add (&rctx->rbuf.bignum, &rctx->rbuf.bignum, &rctx->header_hash);le128_add (&rctx->rbuf.bignum, &rctx->rbuf.bignum, &digest);/* If encrypting, encrypt P_M with the block cipher to get C_M */
Signature · 1 line
2.52.0
Re: [PATCH 08/12] crypto: adiantum - Use memcpy_{to,from}_sglist()
Quoted 8 lines · Eric Biggers
Call the newer, easier-to-read functions
memcpy_to_sglist()andmemcpy_from_sglist()directly instead of callingscatterwalk_map_and_copy(). No change in behavior.Signed-off-by Eric Biggers <[email protected]>--- crypto/adiantum.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
Signature · 3 lines
Email: Herbert Xu <[email protected]> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
Eric Biggers
maintainerPATCH 9/12 crypto: adiantum - Drop support for asynchronous xchacha ciphers
In reply to Eric BiggersThis feature isn't useful in practice. Simplify and streamline the code in the synchronous case, i.e. the case that actually matters, instead.
For example, by no longer having to support resuming the calculation after an asynchronous return of the xchacha cipher, we can just keep more of the state on the stack instead of in the request context.
--- crypto/adiantum.c | 174 +++++++++++++++++++--------------------------- 1 file changed, 70 insertions(+), 104 deletions(-)
crypto/adiantum.c +70 -104
@@ -81,33 +81,10 @@ struct nhpoly1305_ctx {__le64 nh_hash[NH_NUM_PASSES ]; };struct adiantum_request_ctx { - -/* -* Buffer for right-hand part of data, i.e. -* -* P_L => P_M => C_M => C_R when encrypting, or -* C_R => C_M => P_M => P_L when decrypting. -* -* Also used to build the IV for the stream cipher. -*/ -union { -u8 bytes[XCHACHA_IV_SIZE ]; -__le32 words[XCHACHA_IV_SIZE /sizeof (__le32)]; -le128 bignum;/* interpret as element of Z/(2^{128}Z) */ - } rbuf; - -bool enc;/* true if encrypting, false if decrypting */ - -/* -* The result of the Poly1305 ε-∆U hash function applied to -* (bulk length, tweak) -*/ -le128 header_hash; -/* * skcipher sub-request size is unknown at compile-time, so it needs to * go after the members with known sizes. */ union {
@@ -214,25 +191,24 @@ static inline void le128_sub(le128 *r, const le128 *v1, const le128 *v2) (x - y > x)); }/* * Apply the Poly1305 ε-∆U hash function to (bulk length, tweak) and save the -* result to rctx->header_hash. This is the calculation +* result to @out. This is the calculation * * H_T ← Poly1305_{K_T}(bin_{128}(|L|) || T) * * from the procedure in section 6.4 of the Adiantum paper. The resulting value * is reused in both the first and second hash steps. Specifically, it's added * to the result of an independently keyed ε-∆U hash function (for equal length * inputs only) taken over the left-hand part (the "bulk") of the message, to * give the overall Adiantum hash of the (tweak, left-hand part) pair. */ -static void adiantum_hash_header (struct skcipher_request *req) +static void adiantum_hash_header (struct skcipher_request *req,le128 *out) {struct crypto_skcipher *tfm =crypto_skcipher_reqtfm (req);const struct adiantum_tfm_ctx *tctx =crypto_skcipher_ctx (tfm); -struct adiantum_request_ctx *rctx =skcipher_request_ctx (req);const unsigned int bulk_len = req->cryptlen -BLOCKCIPHER_BLOCK_SIZE ;struct {__le64 message_bits;__le64 padding; } header = {
@@ -248,11 +224,11 @@ static void adiantum_hash_header(struct skcipher_request *req)BUILD_BUG_ON (TWEAK_SIZE %POLY1305_BLOCK_SIZE !=0 );poly1305_core_blocks (&state, &tctx->header_hash_key, req->iv,TWEAK_SIZE /POLY1305_BLOCK_SIZE ,1 ); -poly1305_core_emit (&state,NULL , &rctx->header_hash); +poly1305_core_emit (&state,NULL , out); }/* Pass the next NH hash value through Poly1305 */ static void process_nh_hash_value (struct nhpoly1305_ctx *ctx,const struct adiantum_tfm_ctx *key)
@@ -387,116 +363,73 @@ static void adiantum_hash_message(struct skcipher_request *req, len -= n; }nhpoly1305_final (&rctx->u.hash_ctx, tctx, out); } -/* Continue Adiantum encryption/decryption after the stream cipher step */ -static int adiantum_finish (struct skcipher_request *req) +static int adiantum_crypt (struct skcipher_request *req,bool enc) {struct crypto_skcipher *tfm =crypto_skcipher_reqtfm (req);const struct adiantum_tfm_ctx *tctx =crypto_skcipher_ctx (tfm);struct adiantum_request_ctx *rctx =skcipher_request_ctx (req);const unsigned int bulk_len = req->cryptlen -BLOCKCIPHER_BLOCK_SIZE ; -struct scatterlist *dst = req->dst; -le128 digest; - -/* If decrypting, decrypt C_M with the block cipher to get P_M */ -if (!rctx->enc) -crypto_cipher_decrypt_one (tctx->blockcipher, rctx->rbuf.bytes, - rctx->rbuf.bytes); - +struct scatterlist *src = req->src, *dst = req->dst;/* -* Second hash step -* enc: C_R = C_M - H_{K_H}(T, C_L) -* dec: P_R = P_M - H_{K_H}(T, P_L) +* Buffer for right-hand part of data, i.e. +* +* P_L => P_M => C_M => C_R when encrypting, or +* C_R => C_M => P_M => P_L when decrypting. +* +* Also used to build the IV for the stream cipher. */ -le128_sub (&rctx->rbuf.bignum, &rctx->rbuf.bignum, &rctx->header_hash); -if (dst->length >= req->cryptlen && - dst->offset + req->cryptlen <=PAGE_SIZE ) { -/* Fast path for single-page destination */ -struct page *page =sg_page (dst); -void *virt =kmap_local_page (page) + dst->offset; - -nhpoly1305_init (&rctx->u.hash_ctx); -nhpoly1305_update (&rctx->u.hash_ctx, tctx, virt, bulk_len); -nhpoly1305_final (&rctx->u.hash_ctx, tctx, &digest); -le128_sub (&rctx->rbuf.bignum, &rctx->rbuf.bignum, &digest); -memcpy (virt + bulk_len, &rctx->rbuf.bignum,sizeof (le128)); -flush_dcache_page (page); -kunmap_local (virt); - }else { -/* Slow path that works for any destination scatterlist */ -adiantum_hash_message (req, dst, &digest); -le128_sub (&rctx->rbuf.bignum, &rctx->rbuf.bignum, &digest); -memcpy_to_sglist (dst, bulk_len, &rctx->rbuf.bignum, -sizeof (le128)); - } -return 0 ; -} - -static void adiantum_streamcipher_done (void *data,int err) -{ -struct skcipher_request *req = data; - -if (!err) - err =adiantum_finish (req); - -skcipher_request_complete (req, err); -} - -static int adiantum_crypt (struct skcipher_request *req,bool enc) -{ -struct crypto_skcipher *tfm =crypto_skcipher_reqtfm (req); -const struct adiantum_tfm_ctx *tctx =crypto_skcipher_ctx (tfm); -struct adiantum_request_ctx *rctx =skcipher_request_ctx (req); -const unsigned int bulk_len = req->cryptlen -BLOCKCIPHER_BLOCK_SIZE ; -struct scatterlist *src = req->src; +union { +u8 bytes[XCHACHA_IV_SIZE ]; +__le32 words[XCHACHA_IV_SIZE /sizeof (__le32)]; +le128 bignum;/* interpret as element of Z/(2^{128}Z) */ + } rbuf; +le128 header_hash, msg_hash;unsigned int stream_len; -le128 digest; +int err;if (req->cryptlen <BLOCKCIPHER_BLOCK_SIZE )return -EINVAL ; - rctx->enc = enc; -/* * First hash step * enc: P_M = P_R + H_{K_H}(T, P_L) * dec: C_M = C_R + H_{K_H}(T, C_L) */ -adiantum_hash_header (req); +adiantum_hash_header (req, &header_hash);if (src->length >= req->cryptlen && src->offset + req->cryptlen <=PAGE_SIZE ) {/* Fast path for single-page source */ void *virt =kmap_local_page (sg_page (src)) + src->offset;nhpoly1305_init (&rctx->u.hash_ctx);nhpoly1305_update (&rctx->u.hash_ctx, tctx, virt, bulk_len); -nhpoly1305_final (&rctx->u.hash_ctx, tctx, &digest); -memcpy (&rctx->rbuf.bignum, virt + bulk_len,sizeof (le128)); +nhpoly1305_final (&rctx->u.hash_ctx, tctx, &msg_hash); +memcpy (&rbuf.bignum, virt + bulk_len,sizeof (le128));kunmap_local (virt); }else {/* Slow path that works for any source scatterlist */ -adiantum_hash_message (req, src, &digest); -memcpy_from_sglist (&rctx->rbuf.bignum, src, bulk_len, -sizeof (le128)); +adiantum_hash_message (req, src, &msg_hash); +memcpy_from_sglist (&rbuf.bignum, src, bulk_len,sizeof (le128)); } -le128_add (&rctx->rbuf.bignum, &rctx->rbuf.bignum, &rctx->header_hash); -le128_add (&rctx->rbuf.bignum, &rctx->rbuf.bignum, &digest); +le128_add (&rbuf.bignum, &rbuf.bignum, &header_hash); +le128_add (&rbuf.bignum, &rbuf.bignum, &msg_hash);/* If encrypting, encrypt P_M with the block cipher to get C_M */ if (enc) -crypto_cipher_encrypt_one (tctx->blockcipher, rctx->rbuf.bytes, - rctx->rbuf.bytes); +crypto_cipher_encrypt_one (tctx->blockcipher, rbuf.bytes, + rbuf.bytes);/* Initialize the rest of the XChaCha IV (first part is C_M) */ BUILD_BUG_ON (BLOCKCIPHER_BLOCK_SIZE !=16 );BUILD_BUG_ON (XCHACHA_IV_SIZE !=32 );/* nonce || stream position */ - rctx->rbuf.words[4 ] =cpu_to_le32 (1 ); - rctx->rbuf.words[5 ] =0 ; - rctx->rbuf.words[6 ] =0 ; - rctx->rbuf.words[7 ] =0 ; + rbuf.words[4 ] =cpu_to_le32 (1 ); + rbuf.words[5 ] =0 ; + rbuf.words[6 ] =0 ; + rbuf.words[7 ] =0 ;/* * XChaCha needs to be done on all the data except the last 16 bytes; * for disk encryption that usually means 4080 or 496 bytes. But ChaCha * implementations tend to be most efficient when passed a whole number
@@ -509,16 +442,48 @@ static int adiantum_crypt(struct skcipher_request *req, bool enc)if (round_up (stream_len,CHACHA_BLOCK_SIZE ) <= req->cryptlen) stream_len =round_up (stream_len,CHACHA_BLOCK_SIZE );skcipher_request_set_tfm (&rctx->u.streamcipher_req, tctx->streamcipher);skcipher_request_set_crypt (&rctx->u.streamcipher_req, req->src, - req->dst, stream_len, &rctx->rbuf); + req->dst, stream_len, &rbuf);skcipher_request_set_callback (&rctx->u.streamcipher_req, - req->base.flags, - adiantum_streamcipher_done, req); -return crypto_skcipher_encrypt (&rctx->u.streamcipher_req) ?: -adiantum_finish (req); + req->base.flags,NULL ,NULL ); + err =crypto_skcipher_encrypt (&rctx->u.streamcipher_req); +if (err) +return err; + +/* If decrypting, decrypt C_M with the block cipher to get P_M */ +if (!enc) +crypto_cipher_decrypt_one (tctx->blockcipher, rbuf.bytes, + rbuf.bytes); + +/* +* Second hash step +* enc: C_R = C_M - H_{K_H}(T, C_L) +* dec: P_R = P_M - H_{K_H}(T, P_L) +*/ +le128_sub (&rbuf.bignum, &rbuf.bignum, &header_hash); +if (dst->length >= req->cryptlen && + dst->offset + req->cryptlen <=PAGE_SIZE ) { +/* Fast path for single-page destination */ +struct page *page =sg_page (dst); +void *virt =kmap_local_page (page) + dst->offset; + +nhpoly1305_init (&rctx->u.hash_ctx); +nhpoly1305_update (&rctx->u.hash_ctx, tctx, virt, bulk_len); +nhpoly1305_final (&rctx->u.hash_ctx, tctx, &msg_hash); +le128_sub (&rbuf.bignum, &rbuf.bignum, &msg_hash); +memcpy (virt + bulk_len, &rbuf.bignum,sizeof (le128)); +flush_dcache_page (page); +kunmap_local (virt); + }else { +/* Slow path that works for any destination scatterlist */ +adiantum_hash_message (req, dst, &msg_hash); +le128_sub (&rbuf.bignum, &rbuf.bignum, &msg_hash); +memcpy_to_sglist (dst, bulk_len, &rbuf.bignum,sizeof (le128)); + } +return 0 ; }static int adiantum_encrypt (struct skcipher_request *req) {return adiantum_crypt (req, true);
@@ -622,11 +587,12 @@ static int adiantum_create(struct crypto_template *tmpl, struct rtattr **tb) ictx =skcipher_instance_ctx (inst);/* Stream cipher, e.g. "xchacha12" */ err =crypto_grab_skcipher (&ictx->streamcipher_spawn,skcipher_crypto_instance (inst), -crypto_attr_alg_name (tb[1 ]),0 , mask); +crypto_attr_alg_name (tb[1 ]),0 , + mask |CRYPTO_ALG_ASYNC /* sync only */ );if (err) goto err_free_inst; streamcipher_alg =crypto_spawn_skcipher_alg_common (&ictx->streamcipher_spawn);/* Block cipher, e.g. "aes" */
Signature · 1 line
2.52.0
Eric Biggers
maintainerPATCH 10/12 crypto: nhpoly1305 - Remove crypto_shash support
In reply to Eric BiggersRemove nhpoly1305 support from crypto_shash. It no longer has any user now that crypto/adiantum.c no longer uses it.
--- crypto/Kconfig | 6 - crypto/Makefile | 1 - crypto/nhpoly1305.c | 255 ------------------------------------ include/crypto/nhpoly1305.h | 74 ----------- 4 files changed, 336 deletions(-) delete mode 100644 crypto/nhpoly1305.c delete mode 100644 include/crypto/nhpoly1305.h
crypto/Kconfig +0 -6
@@ -757,16 +757,10 @@ config CRYPTO_XTS Use with aes-xts-plain, key size 256, 384 or 512 bits. This implementation currently can't handle a sectorsize which is not a multiple of 16 bytes. -config CRYPTO_NHPOLY1305 - tristate - select CRYPTO_HASH - select CRYPTO_LIB_POLY1305 - select CRYPTO_LIB_POLY1305_GENERIC - endmenu menu "AEAD (authenticated encryption with associated data) ciphers" config CRYPTO_AEGIS128
crypto/Makefile +0 -1
@@ -92,11 +92,10 @@ obj-$(CONFIG_CRYPTO_LRW) += lrw.o obj-$(CONFIG_CRYPTO_XTS) += xts.o obj-$(CONFIG_CRYPTO_CTR) += ctr.o obj-$(CONFIG_CRYPTO_XCTR) += xctr.o obj-$(CONFIG_CRYPTO_HCTR2) += hctr2.o obj-$(CONFIG_CRYPTO_ADIANTUM) += adiantum.o -obj-$(CONFIG_CRYPTO_NHPOLY1305) += nhpoly1305.o obj-$(CONFIG_CRYPTO_GCM) += gcm.o obj-$(CONFIG_CRYPTO_CCM) += ccm.o obj-$(CONFIG_CRYPTO_CHACHA20POLY1305) += chacha20poly1305.o obj-$(CONFIG_CRYPTO_AEGIS128) += aegis128.o aegis128-y := aegis128-core.o
crypto/nhpoly1305.c deleted +0 -255
255 lines not on this page · raw message
include/crypto/nhpoly1305.h deleted +0 -74
74 lines not on this page · raw message
Signature · 1 line
2.52.0
Re: [PATCH 10/12] crypto: nhpoly1305 - Remove crypto_shash support
Quoted 4 lines · Eric Biggers
Remove nhpoly1305 support from
crypto_shash. It no longer has any user now thatcrypto/adiantum.cno longer uses it.Signed-off-by Eric Biggers <[email protected]>
Quoted 8 lines
--- crypto/Kconfig | 6 - crypto/Makefile | 1 - crypto/nhpoly1305.c | 255 ------------------------------------ include/crypto/nhpoly1305.h | 74 ----------- 4 files changed, 336 deletions(-) delete mode 100644 crypto/nhpoly1305.c delete mode 100644 include/crypto/nhpoly1305.h
Thanks,
Signature · 3 lines
Email: Herbert Xu <[email protected]> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
Eric Biggers
maintainerPATCH 11/12 crypto: testmgr - Remove nhpoly1305 tests
In reply to Eric BiggersThese are no longer used, since nhpoly1305 support has been removed from the crypto_shash API.
--- crypto/testmgr.c | 6 - crypto/testmgr.h | 1372 ---------------------------------------------- 2 files changed, 1378 deletions(-)
crypto/testmgr.c +0 -6
@@ -5170,16 +5170,10 @@ static const struct alg_test_desc alg_test_descs[] = { .alg = "michael_mic", .test = alg_test_hash, .suite = { .hash = __VECS(michael_mic_tv_template) } - }, { - .alg = "nhpoly1305", - .test = alg_test_hash, - .suite = { - .hash = __VECS(nhpoly1305_tv_template) - } }, { .alg = "p1363(ecdsa-nist-p192)", .test = alg_test_null, }, { .alg = "p1363(ecdsa-nist-p256)",
crypto/testmgr.h +0 -1372
1,382 lines not on this page · raw message
Signature · 1 line
2.52.0
Re: [PATCH 11/12] crypto: testmgr - Remove nhpoly1305 tests
Quoted 8 lines · Eric Biggers
These are no longer used, since nhpoly1305 support has been removed from the
crypto_shashAPI.Signed-off-by Eric Biggers <[email protected]>--- crypto/testmgr.c | 6 - crypto/testmgr.h | 1372 ---------------------------------------------- 2 files changed, 1378 deletions(-)
Signature · 3 lines
Email: Herbert Xu <[email protected]> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
Eric Biggers
maintainerPATCH 12/12 fscrypt: Drop obsolete recommendation to enable optimized NHPoly1305
In reply to Eric BiggersCONFIG_CRYPTO_NHPOLY1305_NEON, CONFIG_CRYPTO_NHPOLY1305_SSE2, and CONFIG_CRYPTO_NHPOLY1305_AVX2 no longer exist. The equivalent optimizations are now just enabled automatically when Adiantum support is enabled. Update the fscrypt documentation accordingly.
--- Documentation/filesystems/fscrypt.rst | 5 ----- 1 file changed, 5 deletions(-)
Documentation/filesystems/fscrypt.rst +0 -5
@@ -453,15 +453,10 @@ API, but the filenames mode still does. - x86: CONFIG_CRYPTO_AES_NI_INTEL - Adiantum - Mandatory: - CONFIG_CRYPTO_ADIANTUM - - Recommended: - - arm32: CONFIG_CRYPTO_NHPOLY1305_NEON - - arm64: CONFIG_CRYPTO_NHPOLY1305_NEON - - x86: CONFIG_CRYPTO_NHPOLY1305_SSE2 - - x86: CONFIG_CRYPTO_NHPOLY1305_AVX2 - AES-128-CBC-ESSIV and AES-128-CBC-CTS: - Mandatory: - CONFIG_CRYPTO_ESSIV - CONFIG_CRYPTO_SHA256 or another SHA-256 implementation
Signature · 1 line
2.52.0
Quoted 16 lines · Eric Biggers
This series can also be retrieved from:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux.git nh-lib-v1
This series removes the nhpoly1305
crypto_shashalgorithm, which existed only to fit Adiantum hashing into the traditional Linux crypto API paradigm. It replaces it with annh()library function, combined with code in the "adiantum" template that handles the Poly1305 step.The result is simpler code. As usual, I've also fixed the issue where the architecture-optimized code was disabled by default.
I've also included some additional cleanups for the Adiantum code.
I'm planning to take this via libcrypto-next.
Quoted 13 lines
Eric Biggers (12):
lib/crypto: nh: Add NH library
lib/crypto: tests: Add KUnit tests for NH
lib/crypto: arm/nh: Migrate optimized code into library lib/crypto: arm64/nh: Migrate optimized code into library lib/crypto: x86/nh: Migrate optimized code into library
crypto: adiantum - Convert to use NH library
crypto: adiantum - Usescatter_walkAPI instead ofsg_miter
crypto: adiantum - Use memcpy_{to,from}_sglist()
crypto: adiantum - Drop support for asynchronous xchacha ciphers
crypto: nhpoly1305 - Removecrypto_shashsupport
crypto: testmgr - Remove nhpoly1305 tests
fscrypt: Drop obsolete recommendation to enable optimized NHPoly1305
Applied to https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux.git/log/?h=libcrypto-next
More reviews and acks would be appreciated!
- Eric