lib/crypto: Use size_t lengths for Poly1305 and ChaCha
Subsystems (4)
Eric Biggers
maintainercover lib/crypto: Use size_t lengths for Poly1305 and ChaCha
This series upgrades the Poly1305 and ChaCha functions to use size_t lengths, matching the rest of the crypto library.
It also fixes the (not currently reached) handling of lengths above S32_MAX bytes, and (not currently known to matter in practice) the assembly functions depending on unspecified high register bits.
This more comprehensively addresses the issues identified in
https://lore.kernel.org/r/[email protected]
This series is targeting libcrypto-next.
Eric Biggers (2):
lib/crypto: poly1305: Use size_t length
lib/crypto: chacha: Use size_t length
include/crypto/chacha.h | 6 ++-- include/crypto/internal/poly1305.h | 4 +-- include/crypto/poly1305.h | 4 +-- lib/crypto/arm/chacha-scalar-core.S | 2 +- lib/crypto/arm/chacha.h | 14 ++++----- lib/crypto/arm/poly1305.h | 8 +++--- lib/crypto/arm64/chacha.h | 10 +++---- lib/crypto/arm64/poly1305.h | 6 ++-- lib/crypto/chacha.c | 8 +++--- lib/crypto/mips/chacha.h | 5 ++-- lib/crypto/mips/poly1305.h | 2 +- lib/crypto/poly1305-donna32.c | 2 +- lib/crypto/poly1305-donna64.c | 2 +- lib/crypto/poly1305.c | 10 +++---- lib/crypto/powerpc/chacha-p10le-8x.S | 2 +- lib/crypto/powerpc/chacha.h | 10 +++---- lib/crypto/powerpc/poly1305-p10le_64.S | 23 ++++++++------- lib/crypto/powerpc/poly1305.h | 8 ++++-- lib/crypto/riscv/chacha.h | 6 ++-- lib/crypto/riscv/poly1305.h | 2 +- lib/crypto/s390/chacha.h | 2 +- lib/crypto/x86/chacha.h | 40 +++++++++++++------------- lib/crypto/x86/poly1305.h | 4 +-- 23 files changed, 91 insertions(+), 89 deletions(-)
base-commit: 40f47fa10a1d19c74f48a13d97b2eb19d5fb938d
Signature · 1 line
2.56.0
Eric Biggers
maintainerPATCH 1/2 lib/crypto: poly1305: Use size_t length
Upgrade the Poly1305 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 Poly1305 assembly functions actually already treated the length as size_t, despite it being declared as 32-bit on the 64-bit architectures arm64, mips64, ppc64, and riscv64:
- On arm64, this caused unspecified behavior due to the high 32 bits having an unspecified value in that architecture's ABI. 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.)
- On mips64 and riscv64, this caused incorrect behavior on lengths above S32_MAX, due to the sign extension done by those architectures' ABIs. Note that no current callers pass lengths over S32_MAX.
Also, the expression 'desc->buflen + nbytes >= POLY1305_BLOCK_SIZE' in poly1305_update() could overflow if nbytes was in [UINT_MAX - 14, UINT_MAX]. Note that again, no current callers pass lengths this large.
These issues date to the original introduction of the Poly1305 code. However, as noted above, they don't have any real-world impact currently; so this is an API robustness improvement only.
--- include/crypto/internal/poly1305.h | 4 ++-- include/crypto/poly1305.h | 4 ++-- lib/crypto/arm/poly1305.h | 8 ++++---- lib/crypto/arm64/poly1305.h | 6 +++--- lib/crypto/mips/poly1305.h | 2 +- lib/crypto/poly1305-donna32.c | 2 +- lib/crypto/poly1305-donna64.c | 2 +- lib/crypto/poly1305.c | 10 +++++----- lib/crypto/powerpc/poly1305-p10le_64.S | 23 ++++++++++++----------- lib/crypto/powerpc/poly1305.h | 8 +++++--- lib/crypto/riscv/poly1305.h | 2 +- lib/crypto/x86/poly1305.h | 4 ++-- 12 files changed, 39 insertions(+), 36 deletions(-)
include/crypto/internal/poly1305.h +2 -2
@@ -26,7 +26,7 @@ static inline void poly1305_core_init(struct poly1305_state *state)void poly1305_core_blocks (struct poly1305_state *state,const struct poly1305_core_key *key,const void *src, -unsigned int nblocks,u32 hibit); +size_t nblocks,u32 hibit);void poly1305_core_emit (const struct poly1305_state *state,const u32 nonce[4 ],void *dst);
@@ -39,7 +39,7 @@ poly1305_block_init_generic(struct poly1305_block_state *desc, }static inline void poly1305_blocks_generic (struct poly1305_block_state *state, -const u8 *src,unsigned int len, +const u8 *src,size_t len,u32 padbit) { poly1305_core_blocks(&state->h, &state->core_r, src,
include/crypto/poly1305.h +2 -2
@@ -60,8 +60,8 @@ struct poly1305_desc_ctx {void poly1305_init (struct poly1305_desc_ctx *desc, const u8 key[at_least POLY1305_KEY_SIZE]); -void poly1305_update (struct poly1305_desc_ctx *desc, -const u8 *src,unsigned int nbytes); +void poly1305_update (struct poly1305_desc_ctx *desc,const u8 *src, +size_t nbytes);void poly1305_final (struct poly1305_desc_ctx *desc,u8 *digest);#endif
lib/crypto/arm/poly1305.h +4 -4
@@ -14,9 +14,9 @@ asmlinkage void poly1305_block_init(struct poly1305_block_state *state,const u8 raw_key[POLY1305_BLOCK_SIZE ]); asmlinkage void poly1305_blocks_arm(struct poly1305_block_state *state, -const u8 *src,u32 len,u32 hibit); +const u8 *src,size_t len,u32 hibit); asmlinkage void poly1305_blocks_neon(struct poly1305_block_state *state, -const u8 *src,u32 len,u32 hibit); +const u8 *src,size_t len,u32 hibit); asmlinkage void poly1305_emit(const struct poly1305_state *state,u8 digest[POLY1305_DIGEST_SIZE ],const u32 nonce[4 ]);
@@ -24,12 +24,12 @@ asmlinkage void poly1305_emit(const struct poly1305_state *state,static __ro_after_init DEFINE_STATIC_KEY_FALSE (have_neon);static void poly1305_blocks (struct poly1305_block_state *state,const u8 *src, -unsigned int len,u32 padbit) +size_t len,u32 padbit) {if (IS_ENABLED (CONFIG_KERNEL_MODE_NEON ) &&static_branch_likely (&have_neon) &&likely (may_use_simd ())) { do { - unsigned int todo = min_t(unsigned int, len, SZ_4K); + size_t todo = min(len, SZ_4K); scoped_ksimd() poly1305_blocks_neon(state, src, todo, padbit);
lib/crypto/arm64/poly1305.h +3 -3
@@ -14,9 +14,9 @@ asmlinkage void poly1305_block_init(struct poly1305_block_state *state,const u8 raw_key[POLY1305_BLOCK_SIZE ]); asmlinkage void poly1305_blocks_arm64(struct poly1305_block_state *state, -const u8 *src,u32 len,u32 hibit); +const u8 *src,size_t len,u32 hibit); asmlinkage void poly1305_blocks_neon(struct poly1305_block_state *state, -const u8 *src,u32 len,u32 hibit); +const u8 *src,size_t len,u32 hibit); asmlinkage void poly1305_emit(const struct poly1305_state *state,u8 digest[POLY1305_DIGEST_SIZE ],const u32 nonce[4 ]);
@@ -24,7 +24,7 @@ asmlinkage void poly1305_emit(const struct poly1305_state *state,static __ro_after_init DEFINE_STATIC_KEY_FALSE (have_neon);static void poly1305_blocks (struct poly1305_block_state *state,const u8 *src, -unsigned int len,u32 padbit) +size_t len,u32 padbit) {if (static_branch_likely (&have_neon) &&likely (may_use_simd ())) {scoped_ksimd ()
lib/crypto/mips/poly1305.h +1 -1
@@ -8,7 +8,7 @@ asmlinkage void poly1305_block_init(struct poly1305_block_state *state,const u8 raw_key[POLY1305_BLOCK_SIZE ]); asmlinkage void poly1305_blocks(struct poly1305_block_state *state, -const u8 *src,u32 len,u32 hibit); +const u8 *src,size_t len,u32 hibit); asmlinkage void poly1305_emit(const struct poly1305_state *state,u8 digest[POLY1305_DIGEST_SIZE ],const u32 nonce[4 ]);
lib/crypto/poly1305-donna32.c +1 -1
@@ -31,7 +31,7 @@ EXPORT_SYMBOL(poly1305_core_setkey);void poly1305_core_blocks (struct poly1305_state *state,const struct poly1305_core_key *key,const void *src, -unsigned int nblocks,u32 hibit) +size_t nblocks,u32 hibit) {const u8 *input = src;u32 r0, r1, r2, r3, r4;
lib/crypto/poly1305-donna64.c +1 -1
@@ -32,7 +32,7 @@ EXPORT_SYMBOL(poly1305_core_setkey);void poly1305_core_blocks (struct poly1305_state *state,const struct poly1305_core_key *key,const void *src, -unsigned int nblocks,u32 hibit) +size_t nblocks,u32 hibit) {const u8 *input = src;u64 hibit64;
lib/crypto/poly1305.c +5 -5
@@ -34,14 +34,14 @@ void poly1305_init(struct poly1305_desc_ctx *desc, }EXPORT_SYMBOL (poly1305_init); -void poly1305_update (struct poly1305_desc_ctx *desc, -const u8 *src,unsigned int nbytes) +void poly1305_update (struct poly1305_desc_ctx *desc,const u8 *src, +size_t nbytes) { -if (desc->buflen + nbytes >=POLY1305_BLOCK_SIZE ) { -unsigned int bulk_len; +if (nbytes >=POLY1305_BLOCK_SIZE - desc->buflen) { +size_t bulk_len;if (desc->buflen) { -unsigned int l =POLY1305_BLOCK_SIZE - desc->buflen; +size_t l =POLY1305_BLOCK_SIZE - desc->buflen;memcpy (&desc->buf[desc->buflen], src, l); src += l;
lib/crypto/powerpc/poly1305-p10le_64.S +12 -11
@@ -46,11 +46,11 @@ # r4, r3, r2, r1, r0 ; # # -# poly1305_p10le_4blocks( uint8_t *k, uint32_t mlen, uint8_t *m) -# k = 32 bytes key -# r3 = k (r, s) -# r4 = mlen -# r5 = m +# void poly1305_p10le_4blocks(struct poly1305_block_state *state, const u8 *m, +# size_t mlen); +# r3 = state +# r4 = m +# r5 = mlen # #include <asm/ppc_asm.h> #include <asm/asm-offsets.h>
@@ -519,11 +519,11 @@ SYM_FUNC_END(do_mul) .endm # -# poly1305_p10le_4blocks( uint8_t *k, uint32_t mlen, uint8_t *m) -# k = 32 bytes key -# r3 = k (r, s) -# r4 = mlen -# r5 = m +# void poly1305_p10le_4blocks(struct poly1305_block_state *state, const u8 *m, +# size_t mlen); +# r3 = state +# r4 = m +# r5 = mlen # SYM_FUNC_START(poly1305_p10le_4blocks) .align 5
@@ -919,7 +919,8 @@ SYM_FUNC_END(Carry_reduction) # d2 = h0 * r0 # # -# unsigned int poly1305_test_64s(unisgned char *state, const byte *src, size_t len, highbit) +# void poly1305_64s(struct poly1305_block_state *state, const u8 *m, +# size_t mlen, int highbit); # - no highbit if final leftover block (highbit = 0) # SYM_FUNC_START(poly1305_64s)
lib/crypto/powerpc/poly1305.h +5 -3
@@ -10,8 +10,10 @@#include <linux/kernel.h> #include <linux/unaligned.h> -asmlinkage void poly1305_p10le_4blocks(struct poly1305_block_state *state, const u8 *m, u32 mlen); -asmlinkage void poly1305_64s(struct poly1305_block_state *state, const u8 *m, u32 mlen, int highbit); +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);
@@ -40,7 +42,7 @@ static void poly1305_block_init(struct poly1305_block_state *dctx, }static void poly1305_blocks (struct poly1305_block_state *state,const u8 *src, -unsigned int len,u32 padbit) +size_t len,u32 padbit) {if (!static_key_enabled (&have_p10))return poly1305_blocks_generic (state, src, len, padbit);
lib/crypto/riscv/poly1305.h +1 -1
@@ -8,7 +8,7 @@ asmlinkage void poly1305_block_init(struct poly1305_block_state *state,const u8 raw_key[POLY1305_BLOCK_SIZE ]); asmlinkage void poly1305_blocks(struct poly1305_block_state *state, -const u8 *src,u32 len,u32 hibit); +const u8 *src,size_t len,u32 hibit); asmlinkage void poly1305_emit(const struct poly1305_state *state,u8 digest[POLY1305_DIGEST_SIZE ],const u32 nonce[4 ]);
lib/crypto/x86/poly1305.h +2 -2
@@ -90,7 +90,7 @@ static void poly1305_block_init(struct poly1305_block_state *state, }static void poly1305_blocks (struct poly1305_block_state *state,const u8 *inp, -unsigned int len,u32 padbit) +size_t len,u32 padbit) {struct poly1305_arch_internal *ctx = container_of(&state->h.h, struct poly1305_arch_internal, h);
@@ -115,7 +115,7 @@ static void poly1305_blocks(struct poly1305_block_state *state, const u8 *inp, } do { - const unsigned int bytes = min(len, SZ_4K); + const size_t bytes = min(len, SZ_4K); kernel_fpu_begin(); if (static_branch_likely(&poly1305_use_avx512))
Signature · 1 line
2.56.0
Eric Biggers
maintainerPATCH 2/2 lib/crypto: chacha: Use size_t length
In reply to Eric BiggersUpgrade 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 ChaCha assembly functions actually already treated the length as size_t, despite it being declared as 32-bit on the 64-bit architectures 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.
--- include/crypto/chacha.h | 6 ++--- lib/crypto/arm/chacha-scalar-core.S | 2 +- lib/crypto/arm/chacha.h | 14 +++++----- lib/crypto/arm64/chacha.h | 10 +++---- lib/crypto/chacha.c | 8 +++--- lib/crypto/mips/chacha.h | 5 ++-- lib/crypto/powerpc/chacha-p10le-8x.S | 2 +- lib/crypto/powerpc/chacha.h | 10 +++---- lib/crypto/riscv/chacha.h | 6 ++--- lib/crypto/s390/chacha.h | 2 +- lib/crypto/x86/chacha.h | 40 ++++++++++++++-------------- 11 files changed, 52 insertions(+), 53 deletions(-)
include/crypto/chacha.h +3 -3
@@ -86,10 +86,10 @@ static inline void chacha_init(struct chacha_state *state, }void chacha_crypt (struct chacha_state *state,u8 *dst,const u8 *src, -unsigned int bytes,int nrounds); +size_t bytes,int nrounds); -static inline void chacha20_crypt (struct chacha_state *state, -u8 *dst,const u8 *src,unsigned int bytes) +static inline void chacha20_crypt (struct chacha_state *state,u8 *dst, +const u8 *src,size_t bytes) {chacha_crypt (state, dst, src, bytes,20 ); }
lib/crypto/arm/chacha-scalar-core.S +1 -1
@@ -366,7 +366,7 @@ .endm // _chacha /* - * void chacha_doarm(u8 *dst, const u8 *src, unsigned int bytes, + * void chacha_doarm(u8 *dst, const u8 *src, size_t bytes, * const struct chacha_state *state, int nrounds); */ ENTRY(chacha_doarm)
lib/crypto/arm/chacha.h +7 -7
@@ -17,14 +17,14 @@ asmlinkage void chacha_block_xor_neon(const struct chacha_state *state,u8 *dst,const u8 *src,int nrounds); asmlinkage void chacha_4block_xor_neon(const struct chacha_state *state, -u8 *dst,const u8 *src, -int nrounds,unsigned int nbytes); +u8 *dst,const u8 *src,int nrounds, +size_t nbytes); asmlinkage void hchacha_block_arm(const struct chacha_state *state,u32 out[HCHACHA_OUT_WORDS ],int nrounds); asmlinkage void hchacha_block_neon(const struct chacha_state *state,u32 out[HCHACHA_OUT_WORDS ],int nrounds); -asmlinkage void chacha_doarm(u8 *dst, const u8 *src, unsigned int bytes, +asmlinkage void chacha_doarm(u8 *dst, const u8 *src, size_t bytes,const struct chacha_state *state,int nrounds);static __ro_after_init DEFINE_STATIC_KEY_FALSE (use_neon);
@@ -35,12 +35,12 @@ static inline bool neon_usable(void) }static void chacha_doneon (struct chacha_state *state,u8 *dst,const u8 *src, -unsigned int bytes,int nrounds) +size_t bytes,int nrounds) {u8 buf[CHACHA_BLOCK_SIZE ];while (bytes >CHACHA_BLOCK_SIZE ) { -unsigned int l =min (bytes,CHACHA_BLOCK_SIZE *4U ); +size_t l =min (bytes,CHACHA_BLOCK_SIZE *4U );chacha_4block_xor_neon (state, dst, src, nrounds, l); bytes -= l;
@@ -73,7 +73,7 @@ static void hchacha_block_arch(const struct chacha_state *state, }static void chacha_crypt_arch (struct chacha_state *state,u8 *dst, -const u8 *src,unsigned int bytes,int nrounds) +const u8 *src,size_t bytes,int nrounds) {if (!IS_ENABLED (CONFIG_KERNEL_MODE_NEON ) || !neon_usable () || bytes <=CHACHA_BLOCK_SIZE ) {
@@ -83,7 +83,7 @@ static void chacha_crypt_arch(struct chacha_state *state, u8 *dst, } do { - unsigned int todo = min_t(unsigned int, bytes, SZ_4K); + size_t todo = min(bytes, SZ_4K); scoped_ksimd() chacha_doneon(state, dst, src, todo, nrounds);
lib/crypto/arm64/chacha.h +5 -5
@@ -28,18 +28,18 @@ asmlinkage void chacha_block_xor_neon(const struct chacha_state *state,u8 *dst,const u8 *src,int nrounds); asmlinkage void chacha_4block_xor_neon(const struct chacha_state *state, -u8 *dst,const u8 *src, -int nrounds,int bytes); +u8 *dst,const u8 *src,int nrounds, +size_t bytes); asmlinkage void hchacha_block_neon(const struct chacha_state *state,u32 out[HCHACHA_OUT_WORDS ],int nrounds);static __ro_after_init DEFINE_STATIC_KEY_FALSE (have_neon);static void chacha_doneon (struct chacha_state *state,u8 *dst,const u8 *src, -unsigned int bytes,int nrounds) +size_t bytes,int nrounds) {while (bytes) { -int l =min (bytes,CHACHA_BLOCK_SIZE *5 ); +size_t l =min (bytes,CHACHA_BLOCK_SIZE *5 );if (l <=CHACHA_BLOCK_SIZE ) {u8 buf[CHACHA_BLOCK_SIZE ];
@@ -70,7 +70,7 @@ static void hchacha_block_arch(const struct chacha_state *state, }static void chacha_crypt_arch (struct chacha_state *state,u8 *dst, -const u8 *src,unsigned int bytes,int nrounds) +const u8 *src,size_t bytes,int nrounds) {if (!static_branch_likely (&have_neon) || bytes <=CHACHA_BLOCK_SIZE || !crypto_simd_usable ())
lib/crypto/chacha.c +4 -4
@@ -11,9 +11,9 @@#include <linux/kernel.h> #include <linux/module.h> -static void __maybe_unused -chacha_crypt_generic (struct chacha_state *state,u8 *dst,const u8 *src, -unsigned int bytes,int nrounds) +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)) ;
@@ -39,7 +39,7 @@ chacha_crypt_generic(struct chacha_state *state, u8 *dst, const u8 *src,#endif void chacha_crypt (struct chacha_state *state,u8 *dst,const u8 *src, -unsigned int bytes,int nrounds) +size_t bytes,int nrounds) {chacha_crypt_arch (state, dst, src, bytes, nrounds); }
lib/crypto/mips/chacha.h +2 -3
@@ -7,8 +7,7 @@#include <linux/kernel.h> -asmlinkage void chacha_crypt_arch(struct chacha_state *state, -u8 *dst,const u8 *src, -unsigned int bytes,int nrounds); +asmlinkage void chacha_crypt_arch(struct chacha_state *state, u8 *dst, +const u8 *src,size_t bytes,int nrounds); asmlinkage void hchacha_block_arch(const struct chacha_state *state,u32 out[HCHACHA_OUT_WORDS ],int nrounds);
lib/crypto/powerpc/chacha-p10le-8x.S +1 -1
@@ -573,7 +573,7 @@ # # void chacha_p10le_8x(const struct chacha_state *state, u8 *dst, const u8 *src, -# unsigned int len, int nrounds); +# size_t len, int nrounds); # SYM_FUNC_START(chacha_p10le_8x) .align 5
lib/crypto/powerpc/chacha.h +5 -5
@@ -13,7 +13,7 @@#include <asm/switch_to.h> asmlinkage void chacha_p10le_8x(const struct chacha_state *state, u8 *dst, -const u8 *src,unsigned int len,int nrounds); +const u8 *src,size_t len,int nrounds);static __ro_after_init DEFINE_STATIC_KEY_FALSE (have_p10);
@@ -30,9 +30,9 @@ static void vsx_end(void) }static void chacha_p10_do_8x (struct chacha_state *state,u8 *dst,const u8 *src, -unsigned int bytes,int nrounds) +size_t bytes,int nrounds) { -unsigned int l = bytes & ~0x0FF ; +size_t l = bytes & ~0x0FF ;if (l >0 ) {chacha_p10le_8x (state, dst, src, l, nrounds);
@@ -49,14 +49,14 @@ static void chacha_p10_do_8x(struct chacha_state *state, u8 *dst, const u8 *src,#define hchacha_block_arch hchacha_block_generic/* not implemented yet */ static void chacha_crypt_arch (struct chacha_state *state,u8 *dst, -const u8 *src,unsigned int bytes,int nrounds) +const u8 *src,size_t bytes,int nrounds) {if (!static_branch_likely (&have_p10) || bytes <=CHACHA_BLOCK_SIZE || !crypto_simd_usable ())return chacha_crypt_generic (state, dst, src, bytes, nrounds); do { - unsigned int todo = min_t(unsigned int, bytes, SZ_4K); + size_t todo = min(bytes, SZ_4K); vsx_begin(); chacha_p10_do_8x(state, dst, src, todo, nrounds);
lib/crypto/riscv/chacha.h +3 -3
@@ -19,11 +19,11 @@ asmlinkage void chacha_zvkb(struct chacha_state *state, const u8 *in, u8 *out,#define hchacha_block_arch hchacha_block_generic/* not implemented yet */ static void chacha_crypt_arch (struct chacha_state *state,u8 *dst, -const u8 *src,unsigned int bytes,int nrounds) +const u8 *src,size_t bytes,int nrounds) {u8 block_buffer[CHACHA_BLOCK_SIZE ]; -unsigned int full_blocks = bytes /CHACHA_BLOCK_SIZE ; -unsigned int tail_bytes = bytes %CHACHA_BLOCK_SIZE ; +size_t full_blocks = bytes /CHACHA_BLOCK_SIZE ; +size_t tail_bytes = bytes %CHACHA_BLOCK_SIZE ;if (!static_branch_likely (&use_zvkb) || !crypto_simd_usable ())return chacha_crypt_generic (state, dst, src, bytes, nrounds);
lib/crypto/s390/chacha.h +1 -1
@@ -15,7 +15,7 @@#define hchacha_block_arch hchacha_block_generic/* not implemented yet */ static void chacha_crypt_arch (struct chacha_state *state,u8 *dst, -const u8 *src,unsigned int bytes,int nrounds) +const u8 *src,size_t bytes,int nrounds) {/* s390 chacha20 implementation has 20 rounds hard-coded, * it cannot handle a block of data or less, but otherwise
lib/crypto/x86/chacha.h +20 -20
@@ -11,46 +11,46 @@#include <linux/sizes.h> asmlinkage void chacha_block_xor_ssse3(const struct chacha_state *state, -u8 *dst,const u8 *src, -unsigned int len,int nrounds); +u8 *dst,const u8 *src,size_t len, +int nrounds); asmlinkage void chacha_4block_xor_ssse3(const struct chacha_state *state, -u8 *dst,const u8 *src, -unsigned int len,int nrounds); +u8 *dst,const u8 *src,size_t len, +int nrounds); asmlinkage void hchacha_block_ssse3(const struct chacha_state *state,u32 out[HCHACHA_OUT_WORDS ],int nrounds); asmlinkage void chacha_2block_xor_avx2(const struct chacha_state *state, -u8 *dst,const u8 *src, -unsigned int len,int nrounds); +u8 *dst,const u8 *src,size_t len, +int nrounds); asmlinkage void chacha_4block_xor_avx2(const struct chacha_state *state, -u8 *dst,const u8 *src, -unsigned int len,int nrounds); +u8 *dst,const u8 *src,size_t len, +int nrounds); asmlinkage void chacha_8block_xor_avx2(const struct chacha_state *state, -u8 *dst,const u8 *src, -unsigned int len,int nrounds); +u8 *dst,const u8 *src,size_t len, +int nrounds); asmlinkage void chacha_2block_xor_avx512vl(const struct chacha_state *state, -u8 *dst,const u8 *src, -unsigned int len,int nrounds); +u8 *dst,const u8 *src,size_t len, +int nrounds); asmlinkage void chacha_4block_xor_avx512vl(const struct chacha_state *state, -u8 *dst,const u8 *src, -unsigned int len,int nrounds); +u8 *dst,const u8 *src,size_t len, +int nrounds); asmlinkage void chacha_8block_xor_avx512vl(const struct chacha_state *state, -u8 *dst,const u8 *src, -unsigned int len,int nrounds); +u8 *dst,const u8 *src,size_t len, +int nrounds);static __ro_after_init DEFINE_STATIC_KEY_FALSE (chacha_use_simd);static __ro_after_init DEFINE_STATIC_KEY_FALSE (chacha_use_avx2);static __ro_after_init DEFINE_STATIC_KEY_FALSE (chacha_use_avx512vl); -static unsigned int chacha_advance (unsigned int len,unsigned int maxblocks) +static size_t chacha_advance (size_t len,size_t maxblocks) { len =min (len, maxblocks *CHACHA_BLOCK_SIZE );return round_up (len,CHACHA_BLOCK_SIZE ) /CHACHA_BLOCK_SIZE ; }static void chacha_dosimd (struct chacha_state *state,u8 *dst,const u8 *src, -unsigned int bytes,int nrounds) +size_t bytes,int nrounds) {if (static_branch_likely (&chacha_use_avx512vl)) {while (bytes >=CHACHA_BLOCK_SIZE *8 ) {
@@ -137,14 +137,14 @@ static void hchacha_block_arch(const struct chacha_state *state, }static void chacha_crypt_arch (struct chacha_state *state,u8 *dst, -const u8 *src,unsigned int bytes,int nrounds) +const u8 *src,size_t bytes,int nrounds) {if (!static_branch_likely (&chacha_use_simd) || bytes <=CHACHA_BLOCK_SIZE )return chacha_crypt_generic (state, dst, src, bytes, nrounds); do { - unsigned int todo = min_t(unsigned int, bytes, SZ_4K); + size_t todo = min(bytes, SZ_4K); kernel_fpu_begin(); chacha_dosimd(state, dst, src, todo, nrounds);
Signature · 1 line
2.56.0
Hi Eric,
Sorry for not replying to your question on v1. I was already reworking the series in that direction and should have told you.
Thanks for doing this. I tested your two patches with the lib/crypto KUnit tests in QEMU on x86_64, i386, arm, arm64, powerpc64le, riscv64, mips, mips64, s390x and UML, plus temporary tests with buffers over 2 GiB and 4 GiB. Everything passed, except for two things that fail the same way without your patches: the POWER10 Poly1305 interrupt context tests (I force-enabled that code, which depends on BROKEN), and two Poly1305 tests that crash under QEMU with AVX2 because of a QEMU bug.
One gap remains on 32-bit arm and MIPS: the ChaCha assembly there treats the length as signed, and size_t is 32 bits, so lengths of 2 GiB or more are still handled incorrectly. On a Cortex-A7, which always uses the scalar code, a 2 GiB + 4101 byte in-place chacha20_crypt() changed only one byte.
As a suggestion, I've sent two small fixes on top of your series:
- arm: use unsigned conditions in chacha-scalar-core.S, and DIV_ROUND_UP_POW2() for the block count, since DIV_ROUND_UP() wraps above 0xffffffc0.
- MIPS: the partial block code also relies on the sign of the remaining length, so a small C chacha_crypt_arch() passes the assembly at most 1 GiB at a time.
Feel free to fold them into your series or handle it differently.
Thanks,
Vladimir Kukharenko
Quoted 7 lines · Eric Biggers
This series upgrades the Poly1305 and ChaCha functions to use
size_tlengths, matching the rest of the crypto library.It also fixes the (not currently reached) handling of lengths above
S32_MAXbytes, and (not currently known to matter in practice) the assembly functions depending on unspecified high register bits.
Quoted 8 lines
This more comprehensively addresses the issues identified in
https://lore.kernel.org/r/[email protected]This series is targeting libcrypto-next.
Eric Biggers (2):
lib/crypto: poly1305: Usesize_tlength
lib/crypto: chacha: Usesize_tlength
Applied to https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux.git/log/?h=libcrypto-next
- Eric
This series was applied to riscv/linux.git (fixes) by Eric Biggers <[email protected]>:
Hello:
This series was applied to riscv/linux.git (fixes) by Eric Biggers <[email protected]>:
Quoted 8 lines · On Wed, 14 Oct 2026 17:26:02 +0200 you wrote:
This series upgrades the Poly1305 and ChaCha functions to use
size_tlengths, matching the rest of the crypto library.It also fixes the (not currently reached) handling of lengths above
S32_MAXbytes, and (not currently known to matter in practice) the assembly functions depending on unspecified high register bits.[...]
Here is the summary with links:
- [1/2] lib/crypto: poly1305: Use size_t length
https://git.kernel.org/riscv/c/0b58c136c2f9 - [2/2] lib/crypto: chacha: Use size_t length https://git.kernel.org/riscv/c/e42003dba6dd
You are awesome, thank you!
Signature · 2 lines
Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/patchwork/pwbot.html