Coverage Report

Created: 2026-01-25 06:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/rustls-0.23.36/src/client/builder.rs
Line
Count
Source
1
use alloc::vec::Vec;
2
use core::marker::PhantomData;
3
4
use pki_types::{CertificateDer, PrivateKeyDer};
5
6
use super::client_conn::Resumption;
7
use crate::builder::{ConfigBuilder, WantsVerifier};
8
use crate::client::{ClientConfig, EchMode, ResolvesClientCert, handy};
9
use crate::error::Error;
10
use crate::key_log::NoKeyLog;
11
use crate::sign::{CertifiedKey, SingleCertAndKey};
12
use crate::sync::Arc;
13
use crate::versions::TLS13;
14
use crate::webpki::{self, WebPkiServerVerifier};
15
use crate::{WantsVersions, compress, verify, versions};
16
17
impl ConfigBuilder<ClientConfig, WantsVersions> {
18
    /// Enable Encrypted Client Hello (ECH) in the given mode.
19
    ///
20
    /// This implicitly selects TLS 1.3 as the only supported protocol version to meet the
21
    /// requirement to support ECH.
22
    ///
23
    /// The `ClientConfig` that will be produced by this builder will be specific to the provided
24
    /// [`crate::client::EchConfig`] and may not be appropriate for all connections made by the program.
25
    /// In this case the configuration should only be shared by connections intended for domains
26
    /// that offer the provided [`crate::client::EchConfig`] in their DNS zone.
27
0
    pub fn with_ech(
28
0
        self,
29
0
        mode: EchMode,
30
0
    ) -> Result<ConfigBuilder<ClientConfig, WantsVerifier>, Error> {
31
0
        let mut res = self.with_protocol_versions(&[&TLS13][..])?;
32
0
        res.state.client_ech_mode = Some(mode);
33
0
        Ok(res)
34
0
    }
35
}
36
37
impl ConfigBuilder<ClientConfig, WantsVerifier> {
38
    /// Choose how to verify server certificates.
39
    ///
40
    /// Using this function does not configure revocation.  If you wish to
41
    /// configure revocation, instead use:
42
    ///
43
    /// ```diff
44
    /// - .with_root_certificates(root_store)
45
    /// + .with_webpki_verifier(
46
    /// +   WebPkiServerVerifier::builder_with_provider(root_store, crypto_provider)
47
    /// +   .with_crls(...)
48
    /// +   .build()?
49
    /// + )
50
    /// ```
51
0
    pub fn with_root_certificates(
52
0
        self,
53
0
        root_store: impl Into<Arc<webpki::RootCertStore>>,
54
0
    ) -> ConfigBuilder<ClientConfig, WantsClientCert> {
55
0
        let algorithms = self
56
0
            .provider
57
0
            .signature_verification_algorithms;
58
0
        self.with_webpki_verifier(
59
0
            WebPkiServerVerifier::new_without_revocation(root_store, algorithms).into(),
60
        )
61
0
    }
Unexecuted instantiation: <rustls::builder::ConfigBuilder<rustls::client::client_conn::ClientConfig, rustls::builder::WantsVerifier>>::with_root_certificates::<rustls::webpki::anchors::RootCertStore>
Unexecuted instantiation: <rustls::builder::ConfigBuilder<rustls::client::client_conn::ClientConfig, rustls::builder::WantsVerifier>>::with_root_certificates::<_>
62
63
    /// Choose how to verify server certificates using a webpki verifier.
64
    ///
65
    /// See [`webpki::WebPkiServerVerifier::builder`] and
66
    /// [`webpki::WebPkiServerVerifier::builder_with_provider`] for more information.
67
0
    pub fn with_webpki_verifier(
68
0
        self,
69
0
        verifier: Arc<WebPkiServerVerifier>,
70
0
    ) -> ConfigBuilder<ClientConfig, WantsClientCert> {
71
0
        ConfigBuilder {
72
0
            state: WantsClientCert {
73
0
                versions: self.state.versions,
74
0
                verifier,
75
0
                client_ech_mode: self.state.client_ech_mode,
76
0
            },
77
0
            provider: self.provider,
78
0
            time_provider: self.time_provider,
79
0
            side: PhantomData,
80
0
        }
81
0
    }
82
83
    /// Access configuration options whose use is dangerous and requires
84
    /// extra care.
85
0
    pub fn dangerous(self) -> danger::DangerousClientConfigBuilder {
86
0
        danger::DangerousClientConfigBuilder { cfg: self }
87
0
    }
88
}
89
90
/// Container for unsafe APIs
91
pub(super) mod danger {
92
    use core::marker::PhantomData;
93
94
    use crate::client::WantsClientCert;
95
    use crate::sync::Arc;
96
    use crate::{ClientConfig, ConfigBuilder, WantsVerifier, verify};
97
98
    /// Accessor for dangerous configuration options.
99
    #[derive(Debug)]
100
    pub struct DangerousClientConfigBuilder {
101
        /// The underlying ClientConfigBuilder
102
        pub cfg: ConfigBuilder<ClientConfig, WantsVerifier>,
103
    }
104
105
    impl DangerousClientConfigBuilder {
106
        /// Set a custom certificate verifier.
107
0
        pub fn with_custom_certificate_verifier(
108
0
            self,
109
0
            verifier: Arc<dyn verify::ServerCertVerifier>,
110
0
        ) -> ConfigBuilder<ClientConfig, WantsClientCert> {
111
0
            ConfigBuilder {
112
0
                state: WantsClientCert {
113
0
                    versions: self.cfg.state.versions,
114
0
                    verifier,
115
0
                    client_ech_mode: self.cfg.state.client_ech_mode,
116
0
                },
117
0
                provider: self.cfg.provider,
118
0
                time_provider: self.cfg.time_provider,
119
0
                side: PhantomData,
120
0
            }
121
0
        }
122
    }
123
}
124
125
/// A config builder state where the caller needs to supply whether and how to provide a client
126
/// certificate.
127
///
128
/// For more information, see the [`ConfigBuilder`] documentation.
129
#[derive(Clone)]
130
pub struct WantsClientCert {
131
    versions: versions::EnabledVersions,
132
    verifier: Arc<dyn verify::ServerCertVerifier>,
133
    client_ech_mode: Option<EchMode>,
134
}
135
136
impl ConfigBuilder<ClientConfig, WantsClientCert> {
137
    /// Sets a single certificate chain and matching private key for use
138
    /// in client authentication.
139
    ///
140
    /// `cert_chain` is a vector of DER-encoded certificates.
141
    /// `key_der` is a DER-encoded private key as PKCS#1, PKCS#8, or SEC1. The
142
    /// `aws-lc-rs` and `ring` [`CryptoProvider`][crate::CryptoProvider]s support
143
    /// all three encodings, but other `CryptoProviders` may not.
144
    ///
145
    /// This function fails if `key_der` is invalid.
146
0
    pub fn with_client_auth_cert(
147
0
        self,
148
0
        cert_chain: Vec<CertificateDer<'static>>,
149
0
        key_der: PrivateKeyDer<'static>,
150
0
    ) -> Result<ClientConfig, Error> {
151
0
        let certified_key = CertifiedKey::from_der(cert_chain, key_der, &self.provider)?;
152
0
        Ok(self.with_client_cert_resolver(Arc::new(SingleCertAndKey::from(certified_key))))
153
0
    }
154
155
    /// Do not support client auth.
156
0
    pub fn with_no_client_auth(self) -> ClientConfig {
157
0
        self.with_client_cert_resolver(Arc::new(handy::FailResolveClientCert {}))
158
0
    }
159
160
    /// Sets a custom [`ResolvesClientCert`].
161
0
    pub fn with_client_cert_resolver(
162
0
        self,
163
0
        client_auth_cert_resolver: Arc<dyn ResolvesClientCert>,
164
0
    ) -> ClientConfig {
165
0
        ClientConfig {
166
0
            provider: self.provider,
167
0
            alpn_protocols: Vec::new(),
168
0
            resumption: Resumption::default(),
169
0
            max_fragment_size: None,
170
0
            client_auth_cert_resolver,
171
0
            versions: self.state.versions,
172
0
            enable_sni: true,
173
0
            verifier: self.state.verifier,
174
0
            key_log: Arc::new(NoKeyLog {}),
175
0
            enable_secret_extraction: false,
176
0
            enable_early_data: false,
177
0
            #[cfg(feature = "tls12")]
178
0
            require_ems: cfg!(feature = "fips"),
179
0
            time_provider: self.time_provider,
180
0
            cert_compressors: compress::default_cert_compressors().to_vec(),
181
0
            cert_compression_cache: Arc::new(compress::CompressionCache::default()),
182
0
            cert_decompressors: compress::default_cert_decompressors().to_vec(),
183
0
            ech_mode: self.state.client_ech_mode,
184
0
        }
185
0
    }
186
}