Crypto library fixes for v7.4-rc2

- Disable the MIPS64 Octeon optimized SHA-1, SHA-256, and SHA-512 code
   on little-endian kernels, since it doesn't work correctly on them
 
 - Remove the PowerPC optimized Poly1305 code. It's already been marked
   as BROKEN for over a year due to not working in softirq context, but
   it turns out some of the Poly1305 math is incorrect too
 
 - A few robustness improvements for the ML-DSA code
 -----BEGIN PGP SIGNATURE-----
 
 iIoEABYIADIWIQSacvsUNc7UX4ntmEPzXCl4vpKOKwUCaujLJxQcZWJpZ2dlcnNA
 a2VybmVsLm9yZwAKCRDzXCl4vpKOKxd5AP9gCKliD6T4RAmnUtM0Jzys24ezmsl2
 NZuA7BDT3rvD9wEAjSyxFeMrWCxJmAx4yKzXVNJcZC9gRc2e/0OP39Mplwg=
 =tcgp
 -----END PGP SIGNATURE-----

Merge tag 'libcrypto-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux

Pull crypto library fixes from Eric Biggers:

 - Disable the MIPS64 Octeon optimized SHA-1, SHA-256, and SHA-512 code
   on little-endian kernels, since it doesn't work correctly on them

 - Remove the PowerPC optimized Poly1305 code. It's already been marked
   as BROKEN for over a year due to not working in softirq context, but
   it turns out some of the Poly1305 math is incorrect too

 - A few robustness improvements for the ML-DSA code

* tag 'libcrypto-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux:
  lib/crypto: mldsa: Add __must_check to mldsa_verify()
  lib/crypto: mldsa: Explicitly check that 'alg' is a valid value
  lib/crypto: mldsa: Check pk_len before doing pointer arithmetic
  lib/crypto: powerpc/poly1305: Remove BROKEN implementation
  lib/crypto: mips: Disable Octeon SHA code on little-endian kernels
This commit is contained in:
Linus Torvalds 2026-11-02 16:04:49 -08:00
commit b2e7a7bbc1
7 changed files with 28 additions and 1168 deletions

View File

@ -48,11 +48,13 @@ enum mldsa_alg {
* Return:
* * 0 if the signature is valid
* * -EBADMSG if the signature and/or public key is malformed
* * -EINVAL if @alg is not a valid value
* * -EKEYREJECTED if the signature is invalid but otherwise well-formed
* * -ENOMEM if out of memory so the validity of the signature is unknown
*/
int mldsa_verify(enum mldsa_alg alg, const u8 *sig, size_t sig_len,
const u8 *msg, size_t msg_len, const u8 *pk, size_t pk_len);
int __must_check mldsa_verify(enum mldsa_alg alg, const u8 *sig, size_t sig_len,
const u8 *msg, size_t msg_len, const u8 *pk,
size_t pk_len);
#if IS_ENABLED(CONFIG_CRYPTO_LIB_MLDSA_KUNIT_TEST)
/* Internal function, exposed only for unit testing */

View File

@ -197,8 +197,6 @@ config CRYPTO_LIB_POLY1305_ARCH
default y if ARM
default y if ARM64
default y if MIPS
# The PPC64 code needs to be fixed to work in softirq context.
default y if PPC64 && CPU_LITTLE_ENDIAN && VSX && BROKEN
default y if RISCV
default y if X86_64
@ -209,9 +207,7 @@ config CRYPTO_LIB_POLY1305_ARCH
config CRYPTO_LIB_POLY1305_GENERIC
bool
depends on CRYPTO_LIB_POLY1305
# Enable if there's no arch impl or the arch impl requires the generic
# impl as a fallback. (Or if selected explicitly.)
default y if !CRYPTO_LIB_POLY1305_ARCH || PPC64
default y if !CRYPTO_LIB_POLY1305_ARCH
config CRYPTO_LIB_POLY1305_RSIZE
int
@ -237,7 +233,7 @@ config CRYPTO_LIB_SHA1_ARCH
depends on CRYPTO_LIB_SHA1 && !UML
default y if ARM
default y if ARM64
default y if MIPS && CPU_CAVIUM_OCTEON
default y if MIPS && CPU_CAVIUM_OCTEON && CPU_BIG_ENDIAN
default y if PPC
default y if S390
default y if SPARC64
@ -255,7 +251,7 @@ config CRYPTO_LIB_SHA256_ARCH
depends on CRYPTO_LIB_SHA256 && !UML
default y if ARM && !CPU_V7M
default y if ARM64
default y if MIPS && CPU_CAVIUM_OCTEON
default y if MIPS && CPU_CAVIUM_OCTEON && CPU_BIG_ENDIAN
default y if PPC && SPE
default y if RISCV && 64BIT && TOOLCHAIN_HAS_VECTOR_CRYPTO && \
RISCV_EFFICIENT_VECTOR_UNALIGNED_ACCESS
@ -275,7 +271,7 @@ config CRYPTO_LIB_SHA512_ARCH
depends on CRYPTO_LIB_SHA512 && !UML
default y if ARM && !CPU_V7M
default y if ARM64
default y if MIPS && CPU_CAVIUM_OCTEON
default y if MIPS && CPU_CAVIUM_OCTEON && CPU_BIG_ENDIAN
default y if RISCV && 64BIT && TOOLCHAIN_HAS_VECTOR_CRYPTO && \
RISCV_EFFICIENT_VECTOR_UNALIGNED_ACCESS
default y if S390

View File

@ -256,8 +256,6 @@ $(obj)/mips/poly1305-core.S: $(src)/mips/poly1305-mips.pl FORCE
targets += mips/poly1305-core.S
endif
libpoly1305-$(CONFIG_PPC) += powerpc/poly1305-p10le_64.o
ifeq ($(CONFIG_RISCV),y)
libpoly1305-y += riscv/poly1305-core.o
poly1305-perlasm-flavour-$(CONFIG_32BIT) := 32

View File

@ -306,7 +306,7 @@ static const u8 *decode_t1_elem(struct mldsa_ring_elem *out,
* Reference: FIPS 204 Algorithm 27, sigDecode.
*
* This also validates that the coefficients of z are in range, corresponding
* the infinity norm check at the end of Algorithm 8, ML-DSA.Verify_internal.
* to the infinity norm check at the end of Algorithm 8, ML-DSA.Verify_internal.
*
* Finally, this also converts z to NTT form.
*/
@ -528,15 +528,21 @@ static size_t encode_w1(u8 out[MAX_W1_ENCODED_LEN],
int mldsa_verify(enum mldsa_alg alg, const u8 *sig, size_t sig_len,
const u8 *msg, size_t msg_len, const u8 *pk, size_t pk_len)
{
const struct mldsa_parameter_set *params = &mldsa_parameter_sets[alg];
const int k = params->k, l = params->l;
const struct mldsa_parameter_set *params;
int k, l;
/* For now this just does pure ML-DSA with an empty context string. */
static const u8 msg_prefix[2] = { /* dom_sep= */ 0, /* ctx_len= */ 0 };
const u8 *ctilde; /* The signer's commitment hash */
const u8 *t1_encoded = &pk[RHO_LEN]; /* Next encoded element of t_1 */
const u8 *t1_encoded; /* Next encoded element of t_1 */
u8 *h; /* The signer's hint vector, length k * N */
size_t w1_enc_len;
if (alg != MLDSA44 && alg != MLDSA65 && alg != MLDSA87)
return -EINVAL;
params = &mldsa_parameter_sets[alg];
k = params->k;
l = params->l;
/* Validate the public key and signature lengths. */
if (pk_len != params->pk_len || sig_len != params->sig_len)
return -EBADMSG;
@ -587,6 +593,7 @@ int mldsa_verify(enum mldsa_alg alg, const u8 *sig, size_t sig_len,
* The computation is the same for each of the k rows. Just do each row
* before moving on to the next, resulting in only one loop over k.
*/
t1_encoded = &pk[RHO_LEN];
for (int i = 0; i < k; i++) {
/*
* tmp = NTT(A) * NTT(z) * 2^-32

File diff suppressed because it is too large Load Diff

View File

@ -1,76 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Poly1305 authenticator algorithm, RFC7539.
*
* Copyright 2023- IBM Corp. All rights reserved.
*/
#include <asm/switch_to.h>
#include <linux/cpufeature.h>
#include <linux/jump_label.h>
#include <linux/kernel.h>
#include <linux/unaligned.h>
asmlinkage void poly1305_p10le_4blocks(struct poly1305_block_state *state,
const u8 *m, size_t mlen);
asmlinkage void poly1305_64s(struct poly1305_block_state *state, const u8 *m,
size_t mlen, int highbit);
asmlinkage void poly1305_emit_64(const struct poly1305_state *state, const u32 nonce[4], u8 digest[POLY1305_DIGEST_SIZE]);
static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_p10);
static void vsx_begin(void)
{
preempt_disable();
enable_kernel_vsx();
}
static void vsx_end(void)
{
disable_kernel_vsx();
preempt_enable();
}
static void poly1305_block_init(struct poly1305_block_state *dctx,
const u8 raw_key[POLY1305_BLOCK_SIZE])
{
if (!static_key_enabled(&have_p10))
return poly1305_block_init_generic(dctx, raw_key);
dctx->h = (struct poly1305_state){};
dctx->core_r.key.r64[0] = get_unaligned_le64(raw_key + 0);
dctx->core_r.key.r64[1] = get_unaligned_le64(raw_key + 8);
}
static void poly1305_blocks(struct poly1305_block_state *state, const u8 *src,
size_t len, u32 padbit)
{
if (!static_key_enabled(&have_p10))
return poly1305_blocks_generic(state, src, len, padbit);
vsx_begin();
if (len >= POLY1305_BLOCK_SIZE * 4) {
poly1305_p10le_4blocks(state, src, len);
src += len - (len % (POLY1305_BLOCK_SIZE * 4));
len %= POLY1305_BLOCK_SIZE * 4;
}
while (len >= POLY1305_BLOCK_SIZE) {
poly1305_64s(state, src, POLY1305_BLOCK_SIZE, padbit);
len -= POLY1305_BLOCK_SIZE;
src += POLY1305_BLOCK_SIZE;
}
vsx_end();
}
static void poly1305_emit(const struct poly1305_state *state,
u8 digest[POLY1305_DIGEST_SIZE], const u32 nonce[4])
{
if (!static_key_enabled(&have_p10))
return poly1305_emit_generic(state, digest, nonce);
poly1305_emit_64(state, nonce, digest);
}
#define poly1305_mod_init_arch poly1305_mod_init_arch
static void poly1305_mod_init_arch(void)
{
if (cpu_has_feature(CPU_FTR_ARCH_31))
static_branch_enable(&have_p10);
}

View File

@ -372,6 +372,14 @@ static void test_mldsa_use_hint(struct kunit *test)
}
}
static void test_mldsa_invalid_alg(struct kunit *test)
{
KUNIT_ASSERT_EQ(test, -EINVAL,
mldsa_verify(MLDSA44 - 1, NULL, 0, NULL, 0, NULL, 0));
KUNIT_ASSERT_EQ(test, -EINVAL,
mldsa_verify(MLDSA87 + 1, NULL, 0, NULL, 0, NULL, 0));
}
static void benchmark_mldsa(struct kunit *test,
const struct mldsa_testvector *tv)
{
@ -414,6 +422,7 @@ static struct kunit_case mldsa_kunit_cases[] = {
KUNIT_CASE(test_mldsa65),
KUNIT_CASE(test_mldsa87),
KUNIT_CASE(test_mldsa_use_hint),
KUNIT_CASE(test_mldsa_invalid_alg),
KUNIT_CASE(benchmark_mldsa44),
KUNIT_CASE(benchmark_mldsa65),
KUNIT_CASE(benchmark_mldsa87),