mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-10-26 10:57:38 +08:00
Upgrade the ChaCha functions from 32-bit lengths to size_t. 'size_t' is the best practice for buffer lengths, and it's what the rest of the crypto library uses. Moreover, all the 64-bit ChaCha assembly functions actually already treated the length as 64-bit, despite it being declared as 32-bit in C on arm64, ppc64, and x86_64. For arm64 and x86_64, this caused unspecified behavior due to the high 32 bits of the corresponding register having an unspecified value in those architectures' ABIs. However, in practice these bits are always zero and no issue occurred. (ppc64 was fine too, since there the ABI zero-extends 32-bit arguments.) These issues date to the original introduction of the ChaCha code. However, as noted above, they don't have any real-world impact currently; so this is an API robustness improvement only. Reported-by: Vladimir Kukharenko <vladimir@genproof.com> Closes: https://lore.kernel.org/r/20261012-libcrypto-4gib-lengths-v1-0-ea566c129a2e@genproof.com Tested-by: Vladimir Kukharenko <vladimir@genproof.com> Link: https://patch.msgid.link/20261014152604.323310-3-ebiggers@kernel.org Signed-off-by: Eric Biggers <ebiggers@kernel.org>
71 lines
1.7 KiB
C
71 lines
1.7 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
/*
|
|
* The ChaCha stream cipher (RFC7539)
|
|
*
|
|
* Copyright (C) 2015 Martin Willi
|
|
*/
|
|
|
|
#include <crypto/chacha.h>
|
|
#include <crypto/utils.h>
|
|
#include <linux/export.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/module.h>
|
|
|
|
static void __maybe_unused chacha_crypt_generic(struct chacha_state *state,
|
|
u8 *dst, const u8 *src,
|
|
size_t bytes, int nrounds)
|
|
{
|
|
/* aligned to potentially speed up crypto_xor() */
|
|
u8 stream[CHACHA_BLOCK_SIZE] __aligned(sizeof(long));
|
|
|
|
while (bytes >= CHACHA_BLOCK_SIZE) {
|
|
chacha_block_generic(state, stream, nrounds);
|
|
crypto_xor_cpy(dst, src, stream, CHACHA_BLOCK_SIZE);
|
|
bytes -= CHACHA_BLOCK_SIZE;
|
|
dst += CHACHA_BLOCK_SIZE;
|
|
src += CHACHA_BLOCK_SIZE;
|
|
}
|
|
if (bytes) {
|
|
chacha_block_generic(state, stream, nrounds);
|
|
crypto_xor_cpy(dst, src, stream, bytes);
|
|
}
|
|
}
|
|
|
|
#ifdef CONFIG_CRYPTO_LIB_CHACHA_ARCH
|
|
#include "chacha.h" /* $(SRCARCH)/chacha.h */
|
|
#else
|
|
#define chacha_crypt_arch chacha_crypt_generic
|
|
#define hchacha_block_arch hchacha_block_generic
|
|
#endif
|
|
|
|
void chacha_crypt(struct chacha_state *state, u8 *dst, const u8 *src,
|
|
size_t bytes, int nrounds)
|
|
{
|
|
chacha_crypt_arch(state, dst, src, bytes, nrounds);
|
|
}
|
|
EXPORT_SYMBOL_GPL(chacha_crypt);
|
|
|
|
void hchacha_block(const struct chacha_state *state,
|
|
u32 out[HCHACHA_OUT_WORDS], int nrounds)
|
|
{
|
|
hchacha_block_arch(state, out, nrounds);
|
|
}
|
|
EXPORT_SYMBOL_GPL(hchacha_block);
|
|
|
|
#ifdef chacha_mod_init_arch
|
|
static int __init chacha_mod_init(void)
|
|
{
|
|
chacha_mod_init_arch();
|
|
return 0;
|
|
}
|
|
subsys_initcall(chacha_mod_init);
|
|
|
|
static void __exit chacha_mod_exit(void)
|
|
{
|
|
}
|
|
module_exit(chacha_mod_exit);
|
|
#endif
|
|
|
|
MODULE_DESCRIPTION("ChaCha stream cipher (RFC7539)");
|
|
MODULE_LICENSE("GPL");
|