Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
32 changes: 31 additions & 1 deletion rustls-platform-verifier/src/verification/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
use rustls::crypto::CryptoProvider;
use std::sync::Arc;

#[cfg(all(
any(unix, target_arch = "wasm32"),
not(target_os = "android"),
Expand Down Expand Up @@ -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<String>) -> rustls::Error {
rustls::Error::InvalidCertificate(rustls::CertificateError::Other(rustls::OtherError(
std::sync::Arc::from(Box::from(reason.into())),
Arc::from(Box::from(reason.into())),
)))
}

Expand All @@ -77,3 +80,30 @@ 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`] 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<CryptoProvider>) -> 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<CryptoProvider>) {
self.crypto_provider = crypto_provider.into();
}

fn get_provider(&self) -> &Arc<CryptoProvider> {
self.crypto_provider.get_or_init(|| {
CryptoProvider::get_default()
.expect("rustls default CryptoProvider not set")
.clone()
})
}
}
30 changes: 23 additions & 7 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,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<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 +61,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 +72,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 +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());
}
}

Expand Down Expand Up @@ -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))))
}
}

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