diff --git a/rustls-platform-verifier/src/verification/android.rs b/rustls-platform-verifier/src/verification/android.rs index fc0f0c25..66c3cb5f 100644 --- a/rustls-platform-verifier/src/verification/android.rs +++ b/rustls-platform-verifier/src/verification/android.rs @@ -47,7 +47,7 @@ pub struct Verifier { /// Testing only: The root CA certificate to trust. #[cfg(any(test, feature = "ffi-testing"))] test_only_root_ca_override: Option>, - default_provider: OnceCell>, + pub(super) crypto_provider: OnceCell>, } impl Default for Verifier { @@ -71,13 +71,16 @@ impl Drop for Verifier { impl Verifier { /// Creates a new instance of a TLS certificate verifier that utilizes the - /// Android certificate facilities. The rustls default [`CryptoProvider`] - /// must be set before the verifier can be used. + /// Android certificate facilities. + /// + /// A [`CryptoProvider`] must be set with + /// [`set_provider`][Verifier::set_provider]/[`with_provider`][Verifier::with_provider] or + /// [`CryptoProvider::install_default`] before the verifier can be used. pub fn new() -> Self { Self { #[cfg(any(test, feature = "ffi-testing"))] test_only_root_ca_override: None, - default_provider: OnceCell::new(), + crypto_provider: OnceCell::new(), } } @@ -86,20 +89,10 @@ impl Verifier { pub(crate) fn new_with_fake_root(root: &[u8]) -> Self { Self { test_only_root_ca_override: Some(root.into()), - default_provider: OnceCell::new(), + crypto_provider: OnceCell::new(), } } - fn get_provider(&self) -> &CryptoProvider { - self.default_provider - .get_or_init(|| { - rustls::crypto::CryptoProvider::get_default() - .expect("rustls default CryptoProvider not set") - .clone() - }) - .as_ref() - } - fn verify_certificate( &self, end_entity: &pki_types::CertificateDer<'_>, diff --git a/rustls-platform-verifier/src/verification/apple.rs b/rustls-platform-verifier/src/verification/apple.rs index cff3f561..40de6eb8 100644 --- a/rustls-platform-verifier/src/verification/apple.rs +++ b/rustls-platform-verifier/src/verification/apple.rs @@ -46,18 +46,21 @@ pub struct Verifier { /// Testing only: The root CA certificate to trust. #[cfg(any(test, feature = "ffi-testing", feature = "dbg"))] test_only_root_ca_override: Option>, - default_provider: OnceCell>, + pub(super) crypto_provider: OnceCell>, } impl Verifier { - /// Creates a new instance of a TLS certificate verifier that utilizes the - /// macOS certificate facilities. The rustls default [`CryptoProvider`] - /// must be set before the verifier can be used. + /// Creates a new instance of a TLS certificate verifier that utilizes the macOS certificate + /// facilities. + /// + /// A [`CryptoProvider`] must be set with + /// [`set_provider`][Verifier::set_provider]/[`with_provider`][Verifier::with_provider] or + /// [`CryptoProvider::install_default`] before the verifier can be used. pub fn new() -> Self { Self { #[cfg(any(test, feature = "ffi-testing", feature = "dbg"))] test_only_root_ca_override: None, - default_provider: OnceCell::new(), + crypto_provider: OnceCell::new(), } } @@ -66,20 +69,10 @@ impl Verifier { pub(crate) fn new_with_fake_root(root: &[u8]) -> Self { Self { test_only_root_ca_override: Some(root.into()), - default_provider: OnceCell::new(), + crypto_provider: OnceCell::new(), } } - fn get_provider(&self) -> &CryptoProvider { - self.default_provider - .get_or_init(|| { - rustls::crypto::CryptoProvider::get_default() - .expect("rustls default CryptoProvider not set") - .clone() - }) - .as_ref() - } - fn verify_certificate( &self, end_entity: &pki_types::CertificateDer<'_>, diff --git a/rustls-platform-verifier/src/verification/mod.rs b/rustls-platform-verifier/src/verification/mod.rs index 7c0751d0..f8ad6d70 100644 --- a/rustls-platform-verifier/src/verification/mod.rs +++ b/rustls-platform-verifier/src/verification/mod.rs @@ -1,3 +1,6 @@ +use rustls::crypto::CryptoProvider; +use std::sync::Arc; + #[cfg(all( any(unix, target_arch = "wasm32"), not(target_os = "android"), @@ -64,7 +67,7 @@ fn log_server_cert(_end_entity: &rustls::pki_types::CertificateDer<'_>) { #[cfg(any(windows, target_os = "macos", target_os = "ios"))] fn invalid_certificate(reason: impl Into) -> rustls::Error { rustls::Error::InvalidCertificate(rustls::CertificateError::Other(rustls::OtherError( - std::sync::Arc::from(Box::from(reason.into())), + Arc::from(Box::from(reason.into())), ))) } @@ -77,3 +80,30 @@ fn invalid_certificate(reason: impl Into) -> rustls::Error { /// - id-kp-serverAuth // TODO: Chromium also allows for `OID_ANY_EKU` on Android. pub const ALLOWED_EKUS: &[&str] = &["1.3.6.1.5.5.7.3.1"]; + +impl Verifier { + /// Chainable setter to configure the [`CryptoProvider`] for this `Verifier`. + /// + /// This will be used instead of the rustls processs-default `CryptoProvider`, even if one has + /// been installed. + pub fn with_provider(mut self, crypto_provider: Arc) -> Self { + self.set_provider(crypto_provider); + self + } + + /// Configures the [`CryptoProvider`] for this `Verifier`. + /// + /// This will be used instead of the rustls processs-default `CryptoProvider`, even if one has + /// been installed. + pub fn set_provider(&mut self, crypto_provider: Arc) { + self.crypto_provider = crypto_provider.into(); + } + + fn get_provider(&self) -> &Arc { + self.crypto_provider.get_or_init(|| { + CryptoProvider::get_default() + .expect("rustls default CryptoProvider not set") + .clone() + }) + } +} diff --git a/rustls-platform-verifier/src/verification/others.rs b/rustls-platform-verifier/src/verification/others.rs index 0a9b123c..ec88df07 100644 --- a/rustls-platform-verifier/src/verification/others.rs +++ b/rustls-platform-verifier/src/verification/others.rs @@ -4,7 +4,8 @@ use rustls::client::danger::{HandshakeSignatureValid, ServerCertVerified, Server use rustls::client::WebPkiServerVerifier; use rustls::pki_types; use rustls::{ - CertificateError, DigitallySignedStruct, Error as TlsError, OtherError, SignatureScheme, + crypto::CryptoProvider, CertificateError, DigitallySignedStruct, Error as TlsError, OtherError, + SignatureScheme, }; use std::fmt::Debug; use std::sync::{Arc, Mutex}; @@ -28,17 +29,24 @@ pub struct Verifier { /// Testing only: an additional root CA certificate to trust. #[cfg(any(test, feature = "ffi-testing", feature = "dbg"))] test_only_root_ca_override: Option>, + + pub(super) crypto_provider: OnceCell>, } impl Verifier { /// Creates a new verifier whose certificate validation is provided by /// WebPKI, using root certificates provided by the platform. + /// + /// A [`CryptoProvider`] must be set with + /// [`set_provider`][Verifier::set_provider]/[`with_provider`][Verifier::with_provider] or + /// [`CryptoProvider::install_default`] before the verifier can be used. pub fn new() -> Self { Self { inner: OnceCell::new(), extra_roots: Vec::new().into(), #[cfg(any(test, feature = "ffi-testing", feature = "dbg"))] test_only_root_ca_override: None, + crypto_provider: OnceCell::new(), } } @@ -53,6 +61,7 @@ impl Verifier { extra_roots: roots.into_iter().collect::>().into(), #[cfg(any(test, feature = "ffi-testing", feature = "dbg"))] test_only_root_ca_override: None, + crypto_provider: OnceCell::new(), } } @@ -63,6 +72,7 @@ impl Verifier { inner: OnceCell::new(), extra_roots: Vec::new().into(), test_only_root_ca_override: Some(root.into()), + crypto_provider: OnceCell::new(), } } @@ -85,9 +95,12 @@ impl Verifier { if (added != 1) || (ignored != 0) { panic!("Failed to insert fake, test-only root trust anchor"); } - return Ok(WebPkiServerVerifier::builder(root_store.into()) - .build() - .unwrap()); + return Ok(WebPkiServerVerifier::builder_with_provider( + root_store.into(), + Arc::clone(self.get_provider()), + ) + .build() + .unwrap()); } } @@ -143,9 +156,12 @@ impl Verifier { })); }; - WebPkiServerVerifier::builder(root_store.into()) - .build() - .map_err(|e| TlsError::Other(OtherError(Arc::new(e)))) + WebPkiServerVerifier::builder_with_provider( + root_store.into(), + Arc::clone(self.get_provider()), + ) + .build() + .map_err(|e| TlsError::Other(OtherError(Arc::new(e)))) } } diff --git a/rustls-platform-verifier/src/verification/windows.rs b/rustls-platform-verifier/src/verification/windows.rs index 2480fb6d..19d5ff9a 100644 --- a/rustls-platform-verifier/src/verification/windows.rs +++ b/rustls-platform-verifier/src/verification/windows.rs @@ -421,18 +421,21 @@ pub struct Verifier { /// Testing only: The root CA certificate to trust. #[cfg(any(test, feature = "ffi-testing", feature = "dbg"))] test_only_root_ca_override: Option>, - default_provider: OnceCell>, + pub(super) crypto_provider: OnceCell>, } impl Verifier { /// Creates a new instance of a TLS certificate verifier that utilizes the - /// Windows certificate facilities. The rustls default [`CryptoProvider`] - /// must be set before the verifier can be used. + /// Windows certificate facilities. + /// + /// A [`CryptoProvider`] must be set with + /// [`set_provider`][Verifier::set_provider]/[`with_provider`][Verifier::with_provider] or + /// [`CryptoProvider::install_default`] before the verifier can be used. pub fn new() -> Self { Self { #[cfg(any(test, feature = "ffi-testing", feature = "dbg"))] test_only_root_ca_override: None, - default_provider: OnceCell::new(), + crypto_provider: OnceCell::new(), } } @@ -441,20 +444,10 @@ impl Verifier { pub(crate) fn new_with_fake_root(root: &[u8]) -> Self { Self { test_only_root_ca_override: Some(root.into()), - default_provider: OnceCell::new(), + crypto_provider: OnceCell::new(), } } - fn get_provider(&self) -> &CryptoProvider { - self.default_provider - .get_or_init(|| { - rustls::crypto::CryptoProvider::get_default() - .expect("rustls default CryptoProvider not set") - .clone() - }) - .as_ref() - } - /// Verifies a certificate and its chain for the specified `server`. /// /// Return `Ok(())` if the certificate was valid.