This is an adaptation of the corresponding Linux commit:
| commit 6fd70bc8bc01a578c7728b7bd1cb5689c62cc5b7 (HEAD)
| Author: Jérémy Jean <[email protected]>
| AuthorDate: Sat Sep 26 20:43:26 2026 +0000
|
| crypto: ecc - Handle exceptional points in Shamir multiplication
|
| Shamir multiplication mishandles equal points, opposite points and the
| point at infinity. This rejects valid ECDSA signatures and can accept
| invalid digest/signature tuples when the public key is G or -G. The
| kernel incorrectly rejects 16 valid signatures from Wycheproof.
|
| Handle doubling, cancellation and the point at infinity in precomputation
| and accumulation. Add regression tests for P-256 ECDSA and 256/512-bit
| EC-RDSA. The valid vectors are Wycheproof P1363 secp256r1/SHA-256 cases
| 60 and 210 converted to X9.62, two constructed ECDSA signatures for
| Q = +/-G with k = 2, and six constructed EC-RDSA signatures for Q = G,
| -G and -2G. Also add two invalid P-256 digest/signature tuples for
| Q = +/-G that must return -EKEYREJECTED.
|
| Fixes: 0d7a78643f69 ("crypto: ecrdsa - add EC-RDSA (GOST 34.10)
algorithm")
| Cc: [email protected]
| Assisted-by: LLM
| Signed-off-by: Jérémy Jean <[email protected]>
| Reviewed-by: Ignat Korchagin <[email protected]>
| Reviewed-by: Stefan Berger <[email protected]>
| Signed-off-by: Herbert Xu <[email protected]>
barebox has no testmgr, so only the crypto/ecc.c hunks are ported.
Fixes: d2cc4152f483 ("Add elliptic curve cryptography (ECC) helper functions")
Signed-off-by: Ahmad Fatoum <[email protected]>
---
crypto/ecc.c | 35 ++++++++++++++++++++++++++++++++---
1 file changed, 32 insertions(+), 3 deletions(-)
diff --git a/crypto/ecc.c b/crypto/ecc.c
index 01cb1ae88ead..00ffd18cbf52 100644
--- a/crypto/ecc.c
+++ b/crypto/ecc.c
@@ -1,4 +1,4 @@
-// SPDX-Comment: Origin-URL:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/crypto/ecc.c?id=9deef9c5b8fcc702e69252bef46735d8b0d1f70c
+// SPDX-Comment: Origin-URL:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/crypto/ecc.c?id=6fd70bc8bc01a578c7728b7bd1cb5689c62cc5b7
/*
* Copyright (c) 2013, 2014 Kenneth MacKay. All rights reserved.
* Copyright (c) 2019 Vitaly Chikunov <[email protected]>
@@ -1411,9 +1411,22 @@ static void ecc_point_add(const struct ecc_point *result,
vli_set(result->x, q->x, ndigits);
vli_set(result->y, q->y, ndigits);
vli_mod_sub(z, result->x, p->x, curve->p, ndigits);
+ if (vli_is_zero(z, ndigits)) {
+ if (vli_cmp(p->y, q->y, ndigits)) {
+ /* P + (-P) is the point at infinity. */
+ vli_clear(result->x, ndigits);
+ vli_clear(result->y, ndigits);
+ return;
+ }
+ /* The co-Z addition formula does not handle P == Q. */
+ z[0] = 1;
+ ecc_point_double_jacobian(result->x, result->y, z, curve);
+ goto out;
+ }
vli_set(px, p->x, ndigits);
vli_set(py, p->y, ndigits);
xycz_add(px, py, result->x, result->y, curve);
+out:
vli_mod_inv(z, z, curve->p, ndigits);
apply_z(result->x, result->y, z, curve);
}
@@ -1455,22 +1468,38 @@ void ecc_point_mult_shamir(const struct ecc_point
*result,
vli_set(rx, point->x, ndigits);
vli_set(ry, point->y, ndigits);
vli_clear(z + 1, ndigits - 1);
- z[0] = 1;
+ z[0] = !ecc_point_is_zero(point);
for (--i; i >= 0; i--) {
ecc_point_double_jacobian(rx, ry, z, curve);
idx = !!vli_test_bit(u1, i);
idx |= (!!vli_test_bit(u2, i)) << 1;
point = points[idx];
- if (point) {
+ if (point && !ecc_point_is_zero(point)) {
u64 tx[ECC_MAX_DIGITS];
u64 ty[ECC_MAX_DIGITS];
u64 tz[ECC_MAX_DIGITS];
+ if (vli_is_zero(z, ndigits)) {
+ /* Adding to infinity starts a new accumulator.
*/
+ vli_set(rx, point->x, ndigits);
+ vli_set(ry, point->y, ndigits);
+ z[0] = 1;
+ continue;
+ }
vli_set(tx, point->x, ndigits);
vli_set(ty, point->y, ndigits);
apply_z(tx, ty, z, curve);
vli_mod_sub(tz, rx, tx, curve->p, ndigits);
+ if (vli_is_zero(tz, ndigits)) {
+ if (!vli_cmp(ry, ty, ndigits))
+ ecc_point_double_jacobian(rx, ry, z,
+ curve);
+ else
+ /* Adding opposite points yields
infinity. */
+ vli_clear(z, ndigits);
+ continue;
+ }
xycz_add(tx, ty, rx, ry, curve);
vli_mod_mult_fast(z, z, tz, curve);
}
--
2.47.3