Skip to content

Commit e21b63b

Browse files
committed
Remove old impl of registery
1 parent f9d6000 commit e21b63b

File tree

7 files changed

+71
-178
lines changed

7 files changed

+71
-178
lines changed

src/cryptography/hazmat/backends/openssl/backend.py

Lines changed: 2 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66

77
import collections
88
import contextlib
9-
import itertools
109
import typing
1110

1211
from cryptography import utils, x509
@@ -33,27 +32,9 @@
3332
)
3433
from cryptography.hazmat.primitives.ciphers.algorithms import (
3534
AES,
36-
AES128,
37-
AES256,
38-
ARC4,
39-
SM4,
40-
Camellia,
41-
ChaCha20,
42-
TripleDES,
43-
_BlowfishInternal,
44-
_CAST5Internal,
45-
_IDEAInternal,
46-
_SEEDInternal,
4735
)
4836
from cryptography.hazmat.primitives.ciphers.modes import (
4937
CBC,
50-
CFB,
51-
CFB8,
52-
CTR,
53-
ECB,
54-
GCM,
55-
OFB,
56-
XTS,
5738
Mode,
5839
)
5940
from cryptography.hazmat.primitives.serialization.pkcs12 import (
@@ -69,7 +50,7 @@
6950

7051
# Not actually supported, just used as a marker for some serialization tests.
7152
class _RC2:
72-
pass
53+
key_size = 128
7354

7455

7556
class Backend:
@@ -132,7 +113,6 @@ def __init__(self) -> None:
132113
tuple[type[CipherAlgorithm], type[Mode]],
133114
typing.Callable,
134115
] = {}
135-
self._register_default_ciphers()
136116
self._dh_types = [self._lib.EVP_PKEY_DH]
137117
if self._lib.Cryptography_HAS_EVP_PKEY_DHX:
138118
self._dh_types.append(self._lib.EVP_PKEY_DHX)
@@ -220,93 +200,7 @@ def cipher_supported(self, cipher: CipherAlgorithm, mode: Mode) -> bool:
220200
if not isinstance(cipher, self._fips_ciphers):
221201
return False
222202

223-
try:
224-
adapter = self._cipher_registry[type(cipher), type(mode)]
225-
except KeyError:
226-
return False
227-
evp_cipher = adapter(self, cipher, mode)
228-
return self._ffi.NULL != evp_cipher
229-
230-
def register_cipher_adapter(self, cipher_cls, mode_cls, adapter) -> None:
231-
if (cipher_cls, mode_cls) in self._cipher_registry:
232-
raise ValueError(
233-
f"Duplicate registration for: {cipher_cls} {mode_cls}."
234-
)
235-
self._cipher_registry[cipher_cls, mode_cls] = adapter
236-
237-
def _register_default_ciphers(self) -> None:
238-
for cipher_cls in [AES, AES128, AES256]:
239-
for mode_cls in [CBC, CTR, ECB, OFB, CFB, CFB8, GCM]:
240-
self.register_cipher_adapter(
241-
cipher_cls,
242-
mode_cls,
243-
GetCipherByName(
244-
"{cipher.name}-{cipher.key_size}-{mode.name}"
245-
),
246-
)
247-
for mode_cls in [CBC, CTR, ECB, OFB, CFB]:
248-
self.register_cipher_adapter(
249-
Camellia,
250-
mode_cls,
251-
GetCipherByName("{cipher.name}-{cipher.key_size}-{mode.name}"),
252-
)
253-
for mode_cls in [CBC, CFB, CFB8, OFB]:
254-
self.register_cipher_adapter(
255-
TripleDES, mode_cls, GetCipherByName("des-ede3-{mode.name}")
256-
)
257-
self.register_cipher_adapter(
258-
TripleDES, ECB, GetCipherByName("des-ede3")
259-
)
260-
# ChaCha20 uses the Long Name "chacha20" in OpenSSL, but in LibreSSL
261-
# it uses "chacha"
262-
self.register_cipher_adapter(
263-
ChaCha20,
264-
type(None),
265-
GetCipherByName(
266-
"chacha" if self._lib.CRYPTOGRAPHY_IS_LIBRESSL else "chacha20"
267-
),
268-
)
269-
self.register_cipher_adapter(AES, XTS, _get_xts_cipher)
270-
for mode_cls in [ECB, CBC, OFB, CFB, CTR]:
271-
self.register_cipher_adapter(
272-
SM4, mode_cls, GetCipherByName("sm4-{mode.name}")
273-
)
274-
# Don't register legacy ciphers if they're unavailable. Hypothetically
275-
# this wouldn't be necessary because we test availability by seeing if
276-
# we get an EVP_CIPHER * in the _CipherContext __init__, but OpenSSL 3
277-
# will return a valid pointer even though the cipher is unavailable.
278-
if (
279-
self._binding._legacy_provider_loaded
280-
or not self._lib.CRYPTOGRAPHY_OPENSSL_300_OR_GREATER
281-
):
282-
for mode_cls in [CBC, CFB, OFB, ECB]:
283-
self.register_cipher_adapter(
284-
_BlowfishInternal,
285-
mode_cls,
286-
GetCipherByName("bf-{mode.name}"),
287-
)
288-
for mode_cls in [CBC, CFB, OFB, ECB]:
289-
self.register_cipher_adapter(
290-
_SEEDInternal,
291-
mode_cls,
292-
GetCipherByName("seed-{mode.name}"),
293-
)
294-
for cipher_cls, mode_cls in itertools.product(
295-
[_CAST5Internal, _IDEAInternal],
296-
[CBC, OFB, CFB, ECB],
297-
):
298-
self.register_cipher_adapter(
299-
cipher_cls,
300-
mode_cls,
301-
GetCipherByName("{cipher.name}-{mode.name}"),
302-
)
303-
self.register_cipher_adapter(
304-
ARC4, type(None), GetCipherByName("rc4")
305-
)
306-
# We don't actually support RC2, this is just used by some tests.
307-
self.register_cipher_adapter(
308-
_RC2, type(None), GetCipherByName("rc2")
309-
)
203+
return rust_openssl.ciphers.cipher_supported(cipher, mode)
310204

311205
def pbkdf2_hmac_supported(self, algorithm: hashes.HashAlgorithm) -> bool:
312206
return self.hmac_supported(algorithm)
@@ -1108,34 +1002,4 @@ def _load_pkcs7_certificates(self, p7) -> list[x509.Certificate]:
11081002
return certs
11091003

11101004

1111-
class GetCipherByName:
1112-
def __init__(self, fmt: str):
1113-
self._fmt = fmt
1114-
1115-
def __call__(self, backend: Backend, cipher: CipherAlgorithm, mode: Mode):
1116-
cipher_name = self._fmt.format(cipher=cipher, mode=mode).lower()
1117-
evp_cipher = backend._lib.EVP_get_cipherbyname(
1118-
cipher_name.encode("ascii")
1119-
)
1120-
1121-
# try EVP_CIPHER_fetch if present
1122-
if (
1123-
evp_cipher == backend._ffi.NULL
1124-
and backend._lib.Cryptography_HAS_300_EVP_CIPHER
1125-
):
1126-
evp_cipher = backend._lib.EVP_CIPHER_fetch(
1127-
backend._ffi.NULL,
1128-
cipher_name.encode("ascii"),
1129-
backend._ffi.NULL,
1130-
)
1131-
1132-
backend._consume_errors()
1133-
return evp_cipher
1134-
1135-
1136-
def _get_xts_cipher(backend: Backend, cipher: AES, mode):
1137-
cipher_name = f"aes-{cipher.key_size // 2}-xts"
1138-
return backend._lib.EVP_get_cipherbyname(cipher_name.encode("ascii"))
1139-
1140-
11411005
backend = Backend()

src/cryptography/hazmat/bindings/_rust/openssl/ciphers.pyi

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ def create_decryption_ctx(
2323
def create_decryption_ctx(
2424
algorithm: ciphers.CipherAlgorithm, mode: modes.Mode
2525
) -> ciphers.CipherContext: ...
26+
def cipher_supported(
27+
algorithm: ciphers.CipherAlgorithm, mode: modes.Mode
28+
) -> bool: ...
2629
def _advance(
2730
ctx: ciphers.AEADEncryptionContext | ciphers.AEADDecryptionContext, n: int
2831
) -> None: ...

src/rust/src/backend/cipher_registry.rs

Lines changed: 45 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ fn get_cipher_registry(
112112
let seed = types::SEED.get(py)?;
113113
let arc4 = types::ARC4.get(py)?;
114114
let chacha20 = types::CHACHA20.get(py)?;
115+
let rc2 = types::RC2.get(py)?;
115116

116117
let cbc = types::CBC.get(py)?;
117118
let cfb = types::CFB.get(py)?;
@@ -223,42 +224,53 @@ fn get_cipher_registry(
223224
m.add(sm4, ecb, Some(128), Cipher::sm4_ecb())?;
224225
}
225226

226-
#[cfg(not(CRYPTOGRAPHY_OSSLCONF = "OPENSSL_NO_SEED"))]
227-
{
228-
m.add(seed, cbc, Some(128), Cipher::seed_cbc())?;
229-
m.add(seed, cfb, Some(128), Cipher::seed_cfb128())?;
230-
m.add(seed, ofb, Some(128), Cipher::seed_ofb())?;
231-
m.add(seed, ecb, Some(128), Cipher::seed_ecb())?;
232-
}
233-
234-
#[cfg(not(CRYPTOGRAPHY_OSSLCONF = "OPENSSL_NO_BF"))]
235-
{
236-
m.add(blowfish, cbc, None, Cipher::bf_cbc())?;
237-
m.add(blowfish, cfb, None, Cipher::bf_cfb64())?;
238-
m.add(blowfish, ofb, None, Cipher::bf_ofb())?;
239-
m.add(blowfish, ecb, None, Cipher::bf_ecb())?;
240-
}
241-
242-
#[cfg(not(CRYPTOGRAPHY_OSSLCONF = "OPENSSL_NO_CAST"))]
243-
{
244-
m.add(cast5, cbc, None, Cipher::cast5_cbc())?;
245-
m.add(cast5, ecb, None, Cipher::cast5_ecb())?;
246-
m.add(cast5, ofb, None, Cipher::cast5_ofb())?;
247-
m.add(cast5, cfb, None, Cipher::cast5_cfb64())?;
248-
}
249-
250-
#[cfg(not(CRYPTOGRAPHY_OSSLCONF = "OPENSSL_NO_IDEA"))]
251-
{
252-
m.add(idea, cbc, Some(128), Cipher::idea_cbc())?;
253-
m.add(idea, ecb, Some(128), Cipher::idea_ecb())?;
254-
m.add(idea, ofb, Some(128), Cipher::idea_ofb())?;
255-
m.add(idea, cfb, Some(128), Cipher::idea_cfb64())?;
256-
}
257-
258227
#[cfg(not(CRYPTOGRAPHY_IS_BORINGSSL))]
259228
m.add(chacha20, none_type, None, Cipher::chacha20())?;
260229

261-
m.add(arc4, none_type, None, Cipher::rc4())?;
230+
// Don't register legacy ciphers if they're unavailable. In theory
231+
// this should't be necessary but OpenSSL 3 will return an EVP_CIPHER
232+
// even when the cipher is unavailable.
233+
if cfg!(not(CRYPTOGRAPHY_OPENSSL_300_OR_GREATER))
234+
|| types::LEGACY_PROVIDER_LOADED.get(py)?.is_true()?
235+
{
236+
#[cfg(not(CRYPTOGRAPHY_OSSLCONF = "OPENSSL_NO_BF"))]
237+
{
238+
m.add(blowfish, cbc, None, Cipher::bf_cbc())?;
239+
m.add(blowfish, cfb, None, Cipher::bf_cfb64())?;
240+
m.add(blowfish, ofb, None, Cipher::bf_ofb())?;
241+
m.add(blowfish, ecb, None, Cipher::bf_ecb())?;
242+
}
243+
#[cfg(not(CRYPTOGRAPHY_OSSLCONF = "OPENSSL_NO_SEED"))]
244+
{
245+
m.add(seed, cbc, Some(128), Cipher::seed_cbc())?;
246+
m.add(seed, cfb, Some(128), Cipher::seed_cfb128())?;
247+
m.add(seed, ofb, Some(128), Cipher::seed_ofb())?;
248+
m.add(seed, ecb, Some(128), Cipher::seed_ecb())?;
249+
}
250+
251+
#[cfg(not(CRYPTOGRAPHY_OSSLCONF = "OPENSSL_NO_CAST"))]
252+
{
253+
m.add(cast5, cbc, None, Cipher::cast5_cbc())?;
254+
m.add(cast5, ecb, None, Cipher::cast5_ecb())?;
255+
m.add(cast5, ofb, None, Cipher::cast5_ofb())?;
256+
m.add(cast5, cfb, None, Cipher::cast5_cfb64())?;
257+
}
258+
259+
#[cfg(not(CRYPTOGRAPHY_OSSLCONF = "OPENSSL_NO_IDEA"))]
260+
{
261+
m.add(idea, cbc, Some(128), Cipher::idea_cbc())?;
262+
m.add(idea, ecb, Some(128), Cipher::idea_ecb())?;
263+
m.add(idea, ofb, Some(128), Cipher::idea_ofb())?;
264+
m.add(idea, cfb, Some(128), Cipher::idea_cfb64())?;
265+
}
266+
267+
m.add(arc4, none_type, None, Cipher::rc4())?;
268+
269+
// We don't actually support RC2, this is just used by some tests.
270+
if let Some(rc2_cbc) = Cipher::from_nid(openssl::nid::Nid::RC2_CBC) {
271+
m.add(rc2, cbc, None, rc2_cbc)?;
272+
}
273+
}
262274

263275
Ok(m.build())
264276
})

src/rust/src/backend/ciphers.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,15 @@ fn create_decryption_ctx(
510510
}
511511
}
512512

513+
#[pyo3::prelude::pyfunction]
514+
fn cipher_supported(
515+
py: pyo3::Python<'_>,
516+
algorithm: &pyo3::PyAny,
517+
mode: &pyo3::PyAny,
518+
) -> CryptographyResult<bool> {
519+
Ok(cipher_registry::get_cipher(py, algorithm, mode.get_type())?.is_some())
520+
}
521+
513522
#[pyo3::prelude::pyfunction]
514523
fn _advance(ctx: &pyo3::PyAny, n: u64) {
515524
if let Ok(c) = ctx.downcast::<pyo3::PyCell<PyAEADEncryptionContext>>() {
@@ -532,6 +541,7 @@ pub(crate) fn create_module(py: pyo3::Python<'_>) -> pyo3::PyResult<&pyo3::prelu
532541
let m = pyo3::prelude::PyModule::new(py, "ciphers")?;
533542
m.add_function(pyo3::wrap_pyfunction!(create_encryption_ctx, m)?)?;
534543
m.add_function(pyo3::wrap_pyfunction!(create_decryption_ctx, m)?)?;
544+
m.add_function(pyo3::wrap_pyfunction!(cipher_supported, m)?)?;
535545

536546
m.add_function(pyo3::wrap_pyfunction!(_advance, m)?)?;
537547
m.add_function(pyo3::wrap_pyfunction!(_advance_aad, m)?)?;

src/rust/src/types.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,8 @@ pub static ARC4: LazyPyImport = LazyPyImport::new(
542542
"cryptography.hazmat.primitives.ciphers.algorithms",
543543
&["ARC4"],
544544
);
545+
pub static RC2: LazyPyImport =
546+
LazyPyImport::new("cryptography.hazmat.backends.openssl.backend", &["_RC2"]);
545547

546548
pub static MODE_WITH_INITIALIZATION_VECTOR: LazyPyImport = LazyPyImport::new(
547549
"cryptography.hazmat.primitives.ciphers.modes",
@@ -576,6 +578,11 @@ pub static GCM: LazyPyImport =
576578
pub static XTS: LazyPyImport =
577579
LazyPyImport::new("cryptography.hazmat.primitives.ciphers.modes", &["XTS"]);
578580

581+
pub static LEGACY_PROVIDER_LOADED: LazyPyImport = LazyPyImport::new(
582+
"cryptography.hazmat.bindings.openssl.binding",
583+
&["Binding", "_legacy_provider_loaded"],
584+
);
585+
579586
#[cfg(test)]
580587
mod tests {
581588
use super::LazyPyImport;

tests/hazmat/backends/test_openssl.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@
1313
from cryptography.hazmat.backends.openssl.backend import backend
1414
from cryptography.hazmat.primitives import hashes, serialization
1515
from cryptography.hazmat.primitives.asymmetric import padding
16-
from cryptography.hazmat.primitives.ciphers.algorithms import AES
17-
from cryptography.hazmat.primitives.ciphers.modes import CBC
1816

1917
from ...doubles import (
2018
DummyAsymmetricPadding,
@@ -92,10 +90,6 @@ def test_supports_cipher(self):
9290
is False
9391
)
9492

95-
def test_register_duplicate_cipher_adapter(self):
96-
with pytest.raises(ValueError):
97-
backend.register_cipher_adapter(AES, CBC, None)
98-
9993
def test_openssl_assert(self):
10094
backend.openssl_assert(True)
10195
with pytest.raises(InternalError):

tests/hazmat/primitives/test_pkcs12.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
ed25519,
2020
rsa,
2121
)
22+
from cryptography.hazmat.primitives.ciphers import modes
2223
from cryptography.hazmat.primitives.serialization import (
2324
Encoding,
2425
PublicFormat,
@@ -94,7 +95,9 @@ def test_load_pkcs12_ec_keys(self, filename, password, backend):
9495
],
9596
)
9697
@pytest.mark.supported(
97-
only_if=lambda backend: backend.cipher_supported(_RC2(), None),
98+
only_if=lambda backend: backend.cipher_supported(
99+
_RC2(), modes.CBC(initialization_vector=b"\x00" * 16)
100+
),
98101
skip_message="Does not support RC2",
99102
)
100103
def test_load_pkcs12_ec_keys_rc2(self, filename, password, backend):

0 commit comments

Comments
 (0)