From: Eric Biggers <ebiggers@kernel.org>
To: linux-crypto@vger.kernel.org
Cc: "Ard Biesheuvel" <ardb@kernel.org>,
"Jason A . Donenfeld" <Jason@zx2c4.com>,
"Herbert Xu" <herbert@gondor.apana.org.au>,
linux-arm-kernel@lists.infradead.org,
"Jérémy Jean" <Jeremy.Jean@oss.cyber.gouv.fr>,
stable@vger.kernel.org, "Eric Biggers" <ebiggers@kernel.org>
Subject: [PATCH v3 1/2] lib/crypto: arm64: Fix lost Poly1305 carry when resuming NEON state
Date: Fri, 9 Oct 2026 14:53:53 +0200 [thread overview]
Message-ID: <20261009125354.315476-2-ebiggers@kernel.org> (raw)
In-Reply-To: <20261009125354.315476-1-ebiggers@kernel.org>
From: Jérémy Jean <Jeremy.Jean@oss.cyber.gouv.fr>
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 2^128 + 4, so the conversion must produce the base 2^64 limbs
h0 = 4, h1 = 0, h2 = 1. The low 64-bit word sums to 2^64 + 4 and the
middle 64-bit word (including the carry from the low word) sums to 2^64,
so both carry out. However, the carry out of the middle word goes to
d2, leaving h2 = 0 and the value 4 instead of 2^128 + 4.
Given the above bounds, a carry across 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.
Fixes: f569ca164751 ("crypto: arm64/poly1305 - incorporate OpenSSL/CRYPTOGAMS NEON implementation")
Cc: stable@vger.kernel.org
Assisted-by: LLM
Signed-off-by: Jérémy Jean <Jeremy.Jean@oss.cyber.gouv.fr>
[EB: Rewrote the commit message to more clearly describe the bug and
its impact, and removed a lot of pointless LLM-generated text.]
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
lib/crypto/arm64/poly1305-armv8.pl | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/crypto/arm64/poly1305-armv8.pl b/lib/crypto/arm64/poly1305-armv8.pl
index f1930c6b55ce..234398ff6b60 100644
--- a/lib/crypto/arm64/poly1305-armv8.pl
+++ b/lib/crypto/arm64/poly1305-armv8.pl
@@ -375,7 +375,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
--
2.56.0
next prev parent reply other threads:[~2026-10-09 12:54 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-09 12:53 [PATCH v3 0/2] lib/crypto: arm64: Fix Poly1305 NEON resume carry loss Eric Biggers
2026-10-09 12:53 ` Eric Biggers [this message]
2026-10-09 16:13 ` [PATCH v3 1/2] lib/crypto: arm64: Fix lost Poly1305 carry when resuming NEON state Eric Biggers
2026-10-09 16:15 ` Jason A. Donenfeld
2026-10-09 12:53 ` [PATCH v3 2/2] lib/crypto: tests: Add Poly1305 split-update carry regression test Eric Biggers
2026-10-09 16:19 ` Jason A. Donenfeld
2026-10-09 17:25 ` [PATCH v3 0/2] lib/crypto: arm64: Fix Poly1305 NEON resume carry loss Eric Biggers
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261009125354.315476-2-ebiggers@kernel.org \
--to=ebiggers@kernel.org \
--cc=Jason@zx2c4.com \
--cc=Jeremy.Jean@oss.cyber.gouv.fr \
--cc=ardb@kernel.org \
--cc=herbert@gondor.apana.org.au \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-crypto@vger.kernel.org \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox