Skip to content

Commit

Permalink
feat: add Verifier::set_provider and Verifier::with_provider
Browse files Browse the repository at this point in the history
  • Loading branch information
jbr committed Apr 9, 2024
1 parent b6f6334 commit 864067f
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 50 deletions.
23 changes: 8 additions & 15 deletions rustls-platform-verifier/src/verification/android.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Vec<u8>>,
default_provider: OnceCell<Arc<CryptoProvider>>,
pub(super) crypto_provider: OnceCell<Arc<CryptoProvider>>,
}

impl Default for Verifier {
Expand All @@ -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(),
}
}

Expand All @@ -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<'_>,
Expand Down
25 changes: 9 additions & 16 deletions rustls-platform-verifier/src/verification/apple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Vec<u8>>,
default_provider: OnceCell<Arc<CryptoProvider>>,
pub(super) crypto_provider: OnceCell<Arc<CryptoProvider>>,
}

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(),
}
}

Expand All @@ -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<'_>,
Expand Down
33 changes: 33 additions & 0 deletions rustls-platform-verifier/src/verification/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,36 @@ fn invalid_certificate(reason: impl Into<String>) -> 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<rustls::crypto::CryptoProvider>,
) -> 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<rustls::crypto::CryptoProvider>,
) {
self.crypto_provider = crypto_provider.into();
}

fn get_provider(&self) -> &std::sync::Arc<rustls::crypto::CryptoProvider> {
self.crypto_provider.get_or_init(|| {
rustls::crypto::CryptoProvider::get_default()
.expect("rustls default CryptoProvider not set")
.clone()
})
}
}
22 changes: 18 additions & 4 deletions rustls-platform-verifier/src/verification/others.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand All @@ -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<Vec<u8>>,

pub(super) crypto_provider: OnceCell<Arc<CryptoProvider>>,
}

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(),
}
}

Expand All @@ -53,6 +62,7 @@ impl Verifier {
extra_roots: roots.into_iter().collect::<Vec<_>>().into(),
#[cfg(any(test, feature = "ffi-testing", feature = "dbg"))]
test_only_root_ca_override: None,
crypto_provider: OnceCell::new(),
}
}

Expand All @@ -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(),
}
}

Expand All @@ -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());
}
}

Expand Down
23 changes: 8 additions & 15 deletions rustls-platform-verifier/src/verification/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Vec<u8>>,
default_provider: OnceCell<Arc<CryptoProvider>>,
pub(super) crypto_provider: OnceCell<Arc<CryptoProvider>>,
}

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(),
}
}

Expand All @@ -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.
Expand Down

0 comments on commit 864067f

Please sign in to comment.