From 864067f1c0a7d07ae5581eb385e3764c089b866c Mon Sep 17 00:00:00 2001 From: Jacob Rothstein Date: Mon, 8 Apr 2024 17:09:10 -0700 Subject: [PATCH] feat: add Verifier::set_provider and Verifier::with_provider --- .../src/verification/android.rs | 23 +++++-------- .../src/verification/apple.rs | 25 +++++--------- .../src/verification/mod.rs | 33 +++++++++++++++++++ .../src/verification/others.rs | 22 ++++++++++--- .../src/verification/windows.rs | 23 +++++-------- 5 files changed, 76 insertions(+), 50 deletions(-) diff --git a/rustls-platform-verifier/src/verification/android.rs b/rustls-platform-verifier/src/verification/android.rs index fc0f0c2..66c3cb5 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 cff3f56..40de6eb 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 7c0751d..504f465 100644 --- a/rustls-platform-verifier/src/verification/mod.rs +++ b/rustls-platform-verifier/src/verification/mod.rs @@ -77,3 +77,36 @@ 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`][rustls::crypto::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: std::sync::Arc, + ) -> Self { + self.set_provider(crypto_provider); + self + } + + /// Configures the [`CryptoProvider`][rustls::crypto::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: std::sync::Arc, + ) { + self.crypto_provider = crypto_provider.into(); + } + + fn get_provider(&self) -> &std::sync::Arc { + self.crypto_provider.get_or_init(|| { + rustls::crypto::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 0a9b123..4e5ba1c 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,25 @@ 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 +62,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 +73,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 +96,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()); } } diff --git a/rustls-platform-verifier/src/verification/windows.rs b/rustls-platform-verifier/src/verification/windows.rs index 2480fb6..19d5ff9 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.