* [PATCH 6.12,6.6,6.1,5.15,5.10] lib/crypto: arm64: Fix lost Poly1305 carry when resuming NEON state
@ 2026-10-29 20:20 Eric Biggers
0 siblings, 0 replies; only message in thread
From: Eric Biggers @ 2026-10-29 20:20 UTC (permalink / raw)
To: stable
Cc: linux-crypto, Jérémy Jean, Jason A. Donenfeld,
Eric Biggers
From: Jérémy Jean <Jeremy.Jean@oss.cyber.gouv.fr>
commit 24f07e8c07a0c0dd275331cbb41c79a78741eef9 upstream.
When poly1305_blocks_neon() resumes from a base 2^26 accumulator and the
next update contains an odd number of full 16-byte blocks, it processes
one leading block through poly1305_mult() so that the remaining NEON
work has an even block count. That requires converting the accumulator
to the base 2^64 form used by poly1305_mult(). The final ADC of that
conversion stores the carry into d2, but the following accumulation and
poly1305_mult() use h2. If the conversion carries across bit 128, the
carry is dropped and the emitted tag is wrong.
This was introduced by Cryptogams commit 03dc4adf91c8
("arm/poly1305-armv*.pl: optimize branches."), which removed the
reduction that consumed d2 shortly before Linux imported the code.
OpenSSL's copy did not take that change.
The carry is possible because the NEON code stores the accumulator [h0,
h1, h2, h3, h4] in a lazily reduced, redundant base 2^26 form: its final
carry chain leaves h0, h2, h3 < 2^26, but h1 and h4 may slightly exceed
2^26 - 1. For example, the reachable state
h0 = 4
h1 = 2^26
h2 = 2^26 - 1
h3 = 2^26 - 1
h4 = 2^24 - 1
represents 4 + 2^26*2^26 + (2^26-1)*2^52 + (2^26-1)*2^78 +
(2^24-1)*2^104 = 2^128 + 4, despite the bit representing the 2^128 term
(bit 24 of h4) not being set; the extra comes from the h1 limb being
above the normal base 2^26 range. When this value is converted into the
non-redundant base 2^64 form, a carry into the new 2^128 bit (in bit 0
of h2) is necessary to preserve the value.
Given the above bounds, a carry into bit 128 happens exactly when
h1 >= 2^26, h2 = h3 = 2^26 - 1, and h4 mod 2^24 = 2^24 - 1.
Store the carry into h2, matching the other base 2^26 to base 2^64
conversions in poly1305_blocks() and poly1305_emit().
This bug causes an incorrect tag to be emitted. However, this is
unlikely to happen in practice where Poly1305 is used with a random key,
since the random key tends to distribute the accumulator values
throughout their valid range. There isn't an obvious way for an
attacker without knowledge of the r_key to cause [h0, h1, h2, h3, h4] to
land on the precise values where this bug occurs.
[EB: Rewrote the commit message to more clearly describe the bug and
its impact, and simplified explanation about why there's a carry bit.]
Fixes: f569ca164751 ("crypto: arm64/poly1305 - incorporate OpenSSL/CRYPTOGAMS NEON implementation")
Cc: stable@vger.kernel.org
Assisted-by: LLM
Reviewed-by: Jason A. Donenfeld <Jason@zx2c4.com>
Signed-off-by: Jérémy Jean <Jeremy.Jean@oss.cyber.gouv.fr>
Link: https://patch.msgid.link/20261009125354.315476-2-ebiggers@kernel.org
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
arch/arm64/crypto/poly1305-armv8.pl | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/crypto/poly1305-armv8.pl b/arch/arm64/crypto/poly1305-armv8.pl
index 22c9069c06505..e69419b0ca01e 100644
--- a/arch/arm64/crypto/poly1305-armv8.pl
+++ b/arch/arm64/crypto/poly1305-armv8.pl
@@ -372,7 +372,7 @@ poly1305_blocks_neon:
adc $h1,$h1,xzr
lsr $h2,x14,#24
adds $h1,$h1,x14,lsl#40
- adc $d2,$h2,xzr // can be partially reduced...
+ adc $h2,$h2,xzr // preserve carry into top limb
ldp $d0,$d1,[$inp],#16 // load input
sub $len,$len,#16
base-commit: 85d82e0d7c2dfd3e75d34f35b7ebbf41f45c9c4e
--
2.56.0
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2026-10-29 20:21 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-29 20:20 [PATCH 6.12,6.6,6.1,5.15,5.10] lib/crypto: arm64: Fix lost Poly1305 carry when resuming NEON state Eric Biggers
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.