rustls/client/
builder.rs

1use crate::builder::{ConfigBuilder, WantsVerifier};
2use crate::client::handy;
3use crate::client::{ClientConfig, ResolvesClientCert};
4use crate::crypto::CryptoProvider;
5use crate::error::Error;
6use crate::key_log::NoKeyLog;
7use crate::msgs::handshake::CertificateChain;
8use crate::webpki::{self, WebPkiServerVerifier};
9use crate::{verify, versions};
10
11use super::client_conn::Resumption;
12
13use pki_types::{CertificateDer, PrivateKeyDer};
14
15use alloc::sync::Arc;
16use alloc::vec::Vec;
17use core::marker::PhantomData;
18
19impl ConfigBuilder<ClientConfig, WantsVerifier> {
20    /// Choose how to verify server certificates.
21    ///
22    /// Using this function does not configure revocation.  If you wish to
23    /// configure revocation, instead use:
24    ///
25    /// ```diff
26    /// - .with_root_certificates(root_store)
27    /// + .with_webpki_verifier(
28    /// +   WebPkiServerVerifier::builder_with_provider(root_store, crypto_provider)
29    /// +   .with_crls(...)
30    /// +   .build()?
31    /// + )
32    /// ```
33    pub fn with_root_certificates(
34        self,
35        root_store: impl Into<Arc<webpki::RootCertStore>>,
36    ) -> ConfigBuilder<ClientConfig, WantsClientCert> {
37        let algorithms = self
38            .state
39            .provider
40            .signature_verification_algorithms;
41        self.with_webpki_verifier(
42            WebPkiServerVerifier::new_without_revocation(root_store, algorithms).into(),
43        )
44    }
45
46    /// Choose how to verify server certificates using a webpki verifier.
47    ///
48    /// See [`webpki::WebPkiServerVerifier::builder`] and
49    /// [`webpki::WebPkiServerVerifier::builder_with_provider`] for more information.
50    pub fn with_webpki_verifier(
51        self,
52        verifier: Arc<WebPkiServerVerifier>,
53    ) -> ConfigBuilder<ClientConfig, WantsClientCert> {
54        ConfigBuilder {
55            state: WantsClientCert {
56                provider: self.state.provider,
57                versions: self.state.versions,
58                verifier,
59            },
60            side: PhantomData,
61        }
62    }
63
64    /// Access configuration options whose use is dangerous and requires
65    /// extra care.
66    pub fn dangerous(self) -> danger::DangerousClientConfigBuilder {
67        danger::DangerousClientConfigBuilder { cfg: self }
68    }
69}
70
71/// Container for unsafe APIs
72pub(super) mod danger {
73    use alloc::sync::Arc;
74    use core::marker::PhantomData;
75
76    use crate::client::WantsClientCert;
77    use crate::{verify, ClientConfig, ConfigBuilder, WantsVerifier};
78
79    /// Accessor for dangerous configuration options.
80    #[derive(Debug)]
81    pub struct DangerousClientConfigBuilder {
82        /// The underlying ClientConfigBuilder
83        pub cfg: ConfigBuilder<ClientConfig, WantsVerifier>,
84    }
85
86    impl DangerousClientConfigBuilder {
87        /// Set a custom certificate verifier.
88        pub fn with_custom_certificate_verifier(
89            self,
90            verifier: Arc<dyn verify::ServerCertVerifier>,
91        ) -> ConfigBuilder<ClientConfig, WantsClientCert> {
92            ConfigBuilder {
93                state: WantsClientCert {
94                    provider: self.cfg.state.provider,
95                    versions: self.cfg.state.versions,
96                    verifier,
97                },
98                side: PhantomData,
99            }
100        }
101    }
102}
103
104/// A config builder state where the caller needs to supply whether and how to provide a client
105/// certificate.
106///
107/// For more information, see the [`ConfigBuilder`] documentation.
108#[derive(Clone)]
109pub struct WantsClientCert {
110    provider: Arc<CryptoProvider>,
111    versions: versions::EnabledVersions,
112    verifier: Arc<dyn verify::ServerCertVerifier>,
113}
114
115impl ConfigBuilder<ClientConfig, WantsClientCert> {
116    /// Sets a single certificate chain and matching private key for use
117    /// in client authentication.
118    ///
119    /// `cert_chain` is a vector of DER-encoded certificates.
120    /// `key_der` is a DER-encoded private key as PKCS#1, PKCS#8, or SEC1. The
121    /// `aws-lc-rs` and `ring` [`CryptoProvider`]s support all three encodings,
122    /// but other `CryptoProviders` may not.
123    ///
124    /// This function fails if `key_der` is invalid.
125    pub fn with_client_auth_cert(
126        self,
127        cert_chain: Vec<CertificateDer<'static>>,
128        key_der: PrivateKeyDer<'static>,
129    ) -> Result<ClientConfig, Error> {
130        let private_key = self
131            .state
132            .provider
133            .key_provider
134            .load_private_key(key_der)?;
135        let resolver =
136            handy::AlwaysResolvesClientCert::new(private_key, CertificateChain(cert_chain))?;
137        Ok(self.with_client_cert_resolver(Arc::new(resolver)))
138    }
139
140    /// Do not support client auth.
141    pub fn with_no_client_auth(self) -> ClientConfig {
142        self.with_client_cert_resolver(Arc::new(handy::FailResolveClientCert {}))
143    }
144
145    /// Sets a custom [`ResolvesClientCert`].
146    pub fn with_client_cert_resolver(
147        self,
148        client_auth_cert_resolver: Arc<dyn ResolvesClientCert>,
149    ) -> ClientConfig {
150        ClientConfig {
151            provider: self.state.provider,
152            alpn_protocols: Vec::new(),
153            resumption: Resumption::default(),
154            max_fragment_size: None,
155            client_auth_cert_resolver,
156            versions: self.state.versions,
157            enable_sni: true,
158            verifier: self.state.verifier,
159            key_log: Arc::new(NoKeyLog {}),
160            enable_secret_extraction: false,
161            enable_early_data: false,
162        }
163    }
164}