1 Commits

Author SHA256 Message Date
841d179f2b CVE-2026-26007: Subgroup Attack Due to Missing Subgroup Validation for SECT Curves (bsc#1258074)
* added CVE-2026-26007.patch
2026-02-17 14:57:40 +01:00
3 changed files with 207 additions and 1 deletions

197
CVE-2026-26007.patch Normal file
View File

@@ -0,0 +1,197 @@
From 0eebb9dbb6343d9bc1d91e5a2482ed4e054a6d8c Mon Sep 17 00:00:00 2001
From: Paul Kehrer <paul.l.kehrer@gmail.com>
Date: Tue, 10 Feb 2026 12:32:06 -0600
Subject: [PATCH] EC check key on cofactor > 1 (#14287)
* Refactor EC public key construction to share more code (#14285)
* Run an EC check key if cofactor > 1
This only applies to the binary curves (ed25519 is cofactor 8 and
ed448 is cofactor 4 but we use a different code path for eddsa)
* deprecate SECT curves
* add a test
* more tests
* code review
* simplify
* update with CVE and credit
---------
Co-authored-by: Alex Gaynor <alex.gaynor@gmail.com>
---
CHANGELOG.rst | 15 +++++++
.../hazmat/primitives/asymmetric/ec.py | 23 +++++++++++
src/cryptography/utils.py | 1 +
src/rust/src/backend/ec.rs | 41 +++++++++++++------
tests/hazmat/primitives/test_ec.py | 37 +++++++++++++++++
5 files changed, 104 insertions(+), 13 deletions(-)
Index: cryptography-44.0.3/src/cryptography/hazmat/primitives/asymmetric/ec.py
===================================================================
--- cryptography-44.0.3.orig/src/cryptography/hazmat/primitives/asymmetric/ec.py
+++ cryptography-44.0.3/src/cryptography/hazmat/primitives/asymmetric/ec.py
@@ -401,3 +401,26 @@ def get_curve_for_oid(oid: ObjectIdentif
"The provided object identifier has no matching elliptic "
"curve class"
)
+
+
+_SECT_CURVES: tuple[type[EllipticCurve], ...] = (
+ SECT163K1,
+ SECT163R2,
+ SECT233K1,
+ SECT233R1,
+ SECT283K1,
+ SECT283R1,
+ SECT409K1,
+ SECT409R1,
+ SECT571K1,
+ SECT571R1,
+)
+
+for _curve_cls in _SECT_CURVES:
+ utils.deprecated(
+ _curve_cls,
+ __name__,
+ f"{_curve_cls.__name__} will be removed in the next release.",
+ utils.DeprecatedIn46,
+ name=_curve_cls.__name__,
+ )
Index: cryptography-44.0.3/src/cryptography/utils.py
===================================================================
--- cryptography-44.0.3.orig/src/cryptography/utils.py
+++ cryptography-44.0.3/src/cryptography/utils.py
@@ -26,6 +26,7 @@ DeprecatedIn40 = CryptographyDeprecation
DeprecatedIn41 = CryptographyDeprecationWarning
DeprecatedIn42 = CryptographyDeprecationWarning
DeprecatedIn43 = CryptographyDeprecationWarning
+DeprecatedIn46 = CryptographyDeprecationWarning
def _check_bytes(name: str, value: bytes) -> None:
Index: cryptography-44.0.3/src/rust/src/backend/ec.rs
===================================================================
--- cryptography-44.0.3.orig/src/rust/src/backend/ec.rs
+++ cryptography-44.0.3/src/rust/src/backend/ec.rs
@@ -149,12 +149,10 @@ pub(crate) fn public_key_from_pkey(
) -> CryptographyResult<ECPublicKey> {
let ec = pkey.ec_key()?;
let curve = py_curve_from_curve(py, ec.group())?;
- check_key_infinity(&ec)?;
- Ok(ECPublicKey {
- pkey: pkey.to_owned(),
- curve: curve.into(),
- })
+
+ ECPublicKey::new(pkey.to_owned(), curve.into())
}
+
#[pyo3::pyfunction]
#[pyo3(signature = (curve, backend=None))]
fn generate_private_key(
@@ -212,10 +210,7 @@ fn from_public_bytes(
let ec = openssl::ec::EcKey::from_public_key(&curve, &point)?;
let pkey = openssl::pkey::PKey::from_ec_key(ec)?;
- Ok(ECPublicKey {
- pkey,
- curve: py_curve.into(),
- })
+ ECPublicKey::new(pkey, py_curve.into())
}
#[pyo3::pymethods]
@@ -377,6 +372,29 @@ impl ECPrivateKey {
}
}
+impl ECPublicKey {
+ fn new(
+ pkey: openssl::pkey::PKey<openssl::pkey::Public>,
+ curve: pyo3::Py<pyo3::PyAny>,
+ ) -> CryptographyResult<ECPublicKey> {
+ let ec = pkey.ec_key()?;
+ check_key_infinity(&ec)?;
+ let mut bn_ctx = openssl::bn::BigNumContext::new()?;
+ let mut cofactor = openssl::bn::BigNum::new()?;
+ ec.group().cofactor(&mut cofactor, &mut bn_ctx)?;
+ let one = openssl::bn::BigNum::from_u32(1)?;
+ if cofactor != one {
+ ec.check_key().map_err(|_| {
+ pyo3::exceptions::PyValueError::new_err(
+ "Invalid EC key (key out of range, infinity, etc.)",
+ )
+ })?;
+ }
+
+ Ok(ECPublicKey { pkey, curve })
+ }
+}
+
#[pyo3::pymethods]
impl ECPublicKey {
#[getter]
@@ -617,10 +635,7 @@ impl EllipticCurvePublicNumbers {
let pkey = openssl::pkey::PKey::from_ec_key(public_key)?;
- Ok(ECPublicKey {
- pkey,
- curve: self.curve.clone_ref(py),
- })
+ ECPublicKey::new(pkey, self.curve.clone_ref(py))
}
fn __eq__(
Index: cryptography-44.0.3/tests/hazmat/primitives/test_ec.py
===================================================================
--- cryptography-44.0.3.orig/tests/hazmat/primitives/test_ec.py
+++ cryptography-44.0.3/tests/hazmat/primitives/test_ec.py
@@ -1457,3 +1457,40 @@ class TestECDH:
with pytest.raises(ValueError):
key.exchange(ec.ECDH(), public_key)
+
+
+def test_invalid_sect_public_keys(backend):
+ _skip_curve_unsupported(backend, ec.SECT571K1())
+ public_numbers = ec.EllipticCurvePublicNumbers(1, 1, ec.SECT571K1())
+ with pytest.raises(ValueError):
+ public_numbers.public_key()
+
+ point = binascii.unhexlify(
+ b"0400000000000000000000000000000000000000000000000000000000000000000"
+ b"0000000000000000000000000000000000000000000000000000000000000000000"
+ b"0000000000010000000000000000000000000000000000000000000000000000000"
+ b"0000000000000000000000000000000000000000000000000000000000000000000"
+ b"0000000000000000000001"
+ )
+ with pytest.raises(ValueError):
+ ec.EllipticCurvePublicKey.from_encoded_point(ec.SECT571K1(), point)
+
+ der = binascii.unhexlify(
+ b"3081a7301006072a8648ce3d020106052b810400260381920004000000000000000"
+ b"0000000000000000000000000000000000000000000000000000000000000000000"
+ b"0000000000000000000000000000000000000000000000000000000000000100000"
+ b"0000000000000000000000000000000000000000000000000000000000000000000"
+ b"0000000000000000000000000000000000000000000000000000000000000000000"
+ b"00001"
+ )
+ with pytest.raises(ValueError):
+ serialization.load_der_public_key(der)
+
+ pem = textwrap.dedent("""-----BEGIN PUBLIC KEY-----
+ MIGnMBAGByqGSM49AgEGBSuBBAAmA4GSAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE=
+ -----END PUBLIC KEY-----""").encode()
+ with pytest.raises(ValueError):
+ serialization.load_pem_public_key(pem)

View File

@@ -1,3 +1,10 @@
-------------------------------------------------------------------
Tue Feb 17 13:32:54 UTC 2026 - Nico Krapp <nico.krapp@suse.com>
- CVE-2026-26007: Subgroup Attack Due to Missing Subgroup
Validation for SECT Curves (bsc#1258074)
* added CVE-2026-26007.patch
-------------------------------------------------------------------
Wed May 7 15:45:10 UTC 2025 - Nico Krapp <nico.krapp@suse.com>

View File

@@ -40,7 +40,9 @@ Source2: vendor.tar.zst
Source4: python-cryptography.keyring
# PATCH-FEATURE-OPENSUSE no-pytest_benchmark.patch mcepl@suse.com
# We don't need no benchmarking and coverage measurement
Patch4: no-pytest_benchmark.patch
Patch1: no-pytest_benchmark.patch
# PATCH-FIX-UPSTREAM CVE-2026-26007.patch bsc#1258074
Patch2: CVE-2026-26007.patch
BuildRequires: %{python_module cffi >= 1.12}
BuildRequires: %{python_module devel}
BuildRequires: %{python_module exceptiongroup}