Skip to content

Commit 8459ab3

Browse files
committed
fixes pyca#11450 -- warn on legacy provider load
enable disabling the legacy provider entirely
1 parent f1f7648 commit 8459ab3

File tree

6 files changed

+38
-29
lines changed

6 files changed

+38
-29
lines changed

Diff for: .github/workflows/ci.yml

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ jobs:
3636
- {VERSION: "3.12", NOXSESSION: "tests-ssh", OPENSSL: {TYPE: "openssl", VERSION: "3.2.4"}}
3737
- {VERSION: "3.12", NOXSESSION: "tests-ssh", OPENSSL: {TYPE: "openssl", VERSION: "3.3.3"}}
3838
- {VERSION: "3.12", NOXSESSION: "tests", OPENSSL: {TYPE: "openssl", VERSION: "3.2.4", CONFIG_FLAGS: "no-engine no-rc2 no-srtp no-ct no-psk"}}
39+
- {VERSION: "3.12", NOXSESSION: "tests", OPENSSL: {TYPE: "openssl", VERSION: "3.2.4", CONFIG_FLAGS: "no-legacy", NO_LEGACY: "0"}}
3940
- {VERSION: "3.12", NOXSESSION: "tests", OPENSSL: {TYPE: "openssl", VERSION: "3.2.4", CONFIG_FLAGS: "no-legacy", NO_LEGACY: "1"}}
4041
- {VERSION: "3.12", NOXSESSION: "tests", NOXARGS: "--enable-fips=1", OPENSSL: {TYPE: "openssl", CONFIG_FLAGS: "enable-fips", VERSION: "3.1.8"}}
4142
- {VERSION: "3.12", NOXSESSION: "tests", NOXARGS: "--enable-fips=1", OPENSSL: {TYPE: "openssl", CONFIG_FLAGS: "enable-fips", VERSION: "3.2.4"}}

Diff for: CHANGELOG.rst

+7
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,13 @@ Changelog
3535
:meth:`VerifiedClient.subject <cryptography.x509.verification.VerifiedClient.subjects>`
3636
property can now be `None` since a custom extension policy may allow certificates
3737
without a Subject Alternative Name extension.
38+
* Changed the behavior when the OpenSSL 3 legacy provider fails to load.
39+
Instead of raising an exception, a warning is now emitted. The
40+
``CRYPTOGRAPHY_OPENSSL_NO_LEGACY`` environment variable can still be used to
41+
disable the legacy provider at runtime.
42+
* Added support for the ``CRYPTOGRAPHY_BUILD_OPENSSL_NO_LEGACY`` environment
43+
variable during build time, which prevents the library from ever attempting
44+
to load the legacy provider.
3845

3946
.. _v44-0-2:
4047

Diff for: docs/openssl.rst

+6
Original file line numberDiff line numberDiff line change
@@ -41,5 +41,11 @@ disable the legacy provider in OpenSSL 3.x. This will disable legacy
4141
cryptographic algorithms, including ``Blowfish``, ``CAST5``, ``SEED``,
4242
``ARC4``, and ``RC2`` (which is used by some encrypted serialization formats).
4343

44+
Additionally, the ``CRYPTOGRAPHY_BUILD_OPENSSL_NO_LEGACY`` environment variable
45+
can be set during the build process to prevent the library from ever attempting
46+
to load the legacy provider.
47+
48+
If loading the legacy provider is not disabled and the legacy provider fails to
49+
load, a warning is emitted.
4450

4551
.. _`OpenSSL`: https://www.openssl.org/

Diff for: src/rust/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,4 @@ name = "cryptography_rust"
3333
crate-type = ["cdylib"]
3434

3535
[lints.rust]
36-
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(CRYPTOGRAPHY_OPENSSL_300_OR_GREATER)', 'cfg(CRYPTOGRAPHY_OPENSSL_309_OR_GREATER)', 'cfg(CRYPTOGRAPHY_OPENSSL_320_OR_GREATER)', 'cfg(CRYPTOGRAPHY_OPENSSL_330_OR_GREATER)', 'cfg(CRYPTOGRAPHY_OPENSSL_350_OR_GREATER)', 'cfg(CRYPTOGRAPHY_IS_LIBRESSL)', 'cfg(CRYPTOGRAPHY_IS_BORINGSSL)', 'cfg(CRYPTOGRAPHY_OSSLCONF, values("OPENSSL_NO_IDEA", "OPENSSL_NO_CAST", "OPENSSL_NO_BF", "OPENSSL_NO_CAMELLIA", "OPENSSL_NO_SEED", "OPENSSL_NO_SM4"))'] }
36+
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(CRYPTOGRAPHY_OPENSSL_300_OR_GREATER)', 'cfg(CRYPTOGRAPHY_OPENSSL_309_OR_GREATER)', 'cfg(CRYPTOGRAPHY_OPENSSL_320_OR_GREATER)', 'cfg(CRYPTOGRAPHY_OPENSSL_330_OR_GREATER)', 'cfg(CRYPTOGRAPHY_OPENSSL_350_OR_GREATER)', 'cfg(CRYPTOGRAPHY_IS_LIBRESSL)', 'cfg(CRYPTOGRAPHY_IS_BORINGSSL)', 'cfg(CRYPTOGRAPHY_BUILD_OPENSSL_NO_LEGACY)', 'cfg(CRYPTOGRAPHY_OSSLCONF, values("OPENSSL_NO_IDEA", "OPENSSL_NO_CAST", "OPENSSL_NO_BF", "OPENSSL_NO_CAMELLIA", "OPENSSL_NO_SEED", "OPENSSL_NO_SM4"))'] }

Diff for: src/rust/build.rs

+5
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ fn main() {
3434
println!("cargo:rustc-cfg=CRYPTOGRAPHY_IS_BORINGSSL");
3535
}
3636

37+
if env::var("CRYPTOGRAPHY_BUILD_OPENSSL_NO_LEGACY").map_or(false, |v| !v.is_empty() && v != "0")
38+
{
39+
println!("cargo:rustc-cfg=CRYPTOGRAPHY_BUILD_OPENSSL_NO_LEGACY");
40+
}
41+
3742
if let Ok(vars) = env::var("DEP_OPENSSL_CONF") {
3843
for var in vars.split(',') {
3944
println!("cargo:rustc-cfg=CRYPTOGRAPHY_OSSLCONF=\"{var}\"");

Diff for: src/rust/src/lib.rs

+18-28
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@ use std::env;
1212
use openssl::provider;
1313

1414
#[cfg(CRYPTOGRAPHY_OPENSSL_300_OR_GREATER)]
15-
use crate::error::CryptographyResult;
15+
use pyo3::PyTypeInfo;
1616

17+
#[cfg(CRYPTOGRAPHY_OPENSSL_300_OR_GREATER)]
18+
use crate::error::CryptographyResult;
1719
mod asn1;
1820
mod backend;
1921
mod buf;
@@ -53,19 +55,27 @@ fn is_fips_enabled() -> bool {
5355
}
5456

5557
#[cfg(CRYPTOGRAPHY_OPENSSL_300_OR_GREATER)]
56-
fn _initialize_providers() -> CryptographyResult<LoadedProviders> {
58+
fn _initialize_providers(py: pyo3::Python<'_>) -> CryptographyResult<LoadedProviders> {
5759
// As of OpenSSL 3.0.0 we must register a legacy cipher provider
5860
// to get RC2 (needed for junk asymmetric private key
5961
// serialization), RC4, Blowfish, IDEA, SEED, etc. These things
6062
// are ugly legacy, but we aren't going to get rid of them
6163
// any time soon.
62-
let load_legacy = env::var("CRYPTOGRAPHY_OPENSSL_NO_LEGACY")
63-
.map(|v| v.is_empty() || v == "0")
64-
.unwrap_or(true);
64+
65+
let load_legacy = !cfg!(CRYPTOGRAPHY_BUILD_OPENSSL_NO_LEGACY)
66+
&& !env::var("CRYPTOGRAPHY_OPENSSL_NO_LEGACY").map_or(false, |v| !v.is_empty() && v != "0");
67+
6568
let legacy = if load_legacy {
6669
let legacy_result = provider::Provider::load(None, "legacy");
67-
_legacy_provider_error(legacy_result.is_ok())?;
68-
Some(legacy_result?)
70+
if legacy_result.is_err() {
71+
let message = crate::utils::cstr_from_literal!("OpenSSL 3's legacy provider failed to load. Legacy algorithms will not be available. If you need those algorithms, check your OpenSSL configuration.");
72+
let warning_cls = pyo3::exceptions::PyWarning::type_object(py).into_any();
73+
pyo3::PyErr::warn(py, &warning_cls, message, 1)?;
74+
75+
None
76+
} else {
77+
Some(legacy_result?)
78+
}
6979
} else {
7080
None
7181
};
@@ -77,15 +87,6 @@ fn _initialize_providers() -> CryptographyResult<LoadedProviders> {
7787
})
7888
}
7989

80-
fn _legacy_provider_error(success: bool) -> pyo3::PyResult<()> {
81-
if !success {
82-
return Err(pyo3::exceptions::PyRuntimeError::new_err(
83-
"OpenSSL 3.0's legacy provider failed to load. This is a fatal error by default, but cryptography supports running without legacy algorithms by setting the environment variable CRYPTOGRAPHY_OPENSSL_NO_LEGACY. If you did not expect this error, you have likely made a mistake with your OpenSSL configuration."
84-
));
85-
}
86-
Ok(())
87-
}
88-
8990
#[cfg(CRYPTOGRAPHY_OPENSSL_300_OR_GREATER)]
9091
#[pyo3::pyfunction]
9192
fn enable_fips(providers: &mut LoadedProviders) -> CryptographyResult<()> {
@@ -224,7 +225,7 @@ mod _rust {
224225

225226
cfg_if::cfg_if! {
226227
if #[cfg(CRYPTOGRAPHY_OPENSSL_300_OR_GREATER)] {
227-
let providers = super::super::_initialize_providers()?;
228+
let providers = super::super::_initialize_providers(openssl_mod.py())?;
228229
if providers.legacy.is_some() {
229230
openssl_mod.add("_legacy_provider_loaded", true)?;
230231
} else {
@@ -262,14 +263,3 @@ mod _rust {
262263
Ok(())
263264
}
264265
}
265-
266-
#[cfg(test)]
267-
mod tests {
268-
use super::_legacy_provider_error;
269-
270-
#[test]
271-
fn test_legacy_provider_error() {
272-
assert!(_legacy_provider_error(true).is_ok());
273-
assert!(_legacy_provider_error(false).is_err());
274-
}
275-
}

0 commit comments

Comments
 (0)