rustls/server/
builder.rs

1use alloc::sync::Arc;
2use alloc::vec::Vec;
3use core::marker::PhantomData;
4
5use pki_types::{CertificateDer, PrivateKeyDer};
6
7use crate::builder::{ConfigBuilder, WantsVerifier};
8use crate::crypto::CryptoProvider;
9use crate::error::Error;
10use crate::server::{handy, ResolvesServerCert, ServerConfig};
11use crate::sign::CertifiedKey;
12use crate::time_provider::TimeProvider;
13use crate::verify::{ClientCertVerifier, NoClientAuth};
14use crate::{compress, versions, InconsistentKeys, NoKeyLog};
15
16impl ConfigBuilder<ServerConfig, WantsVerifier> {
17    /// Choose how to verify client certificates.
18    pub fn with_client_cert_verifier(
19        self,
20        client_cert_verifier: Arc<dyn ClientCertVerifier>,
21    ) -> ConfigBuilder<ServerConfig, WantsServerCert> {
22        ConfigBuilder {
23            state: WantsServerCert {
24                provider: self.state.provider,
25                versions: self.state.versions,
26                verifier: client_cert_verifier,
27                time_provider: self.state.time_provider,
28            },
29            side: PhantomData,
30        }
31    }
32
33    /// Disable client authentication.
34    pub fn with_no_client_auth(self) -> ConfigBuilder<ServerConfig, WantsServerCert> {
35        self.with_client_cert_verifier(Arc::new(NoClientAuth))
36    }
37}
38
39/// A config builder state where the caller must supply how to provide a server certificate to
40/// the connecting peer.
41///
42/// For more information, see the [`ConfigBuilder`] documentation.
43#[derive(Clone, Debug)]
44pub struct WantsServerCert {
45    provider: Arc<CryptoProvider>,
46    versions: versions::EnabledVersions,
47    verifier: Arc<dyn ClientCertVerifier>,
48    time_provider: Arc<dyn TimeProvider>,
49}
50
51impl ConfigBuilder<ServerConfig, WantsServerCert> {
52    /// Sets a single certificate chain and matching private key.  This
53    /// certificate and key is used for all subsequent connections,
54    /// irrespective of things like SNI hostname.
55    ///
56    /// Note that the end-entity certificate must have the
57    /// [Subject Alternative Name](https://tools.ietf.org/html/rfc6125#section-4.1)
58    /// extension to describe, e.g., the valid DNS name. The `commonName` field is
59    /// disregarded.
60    ///
61    /// `cert_chain` is a vector of DER-encoded certificates.
62    /// `key_der` is a DER-encoded private key as PKCS#1, PKCS#8, or SEC1. The
63    /// `aws-lc-rs` and `ring` [`CryptoProvider`]s support all three encodings,
64    /// but other `CryptoProviders` may not.
65    ///
66    /// This function fails if `key_der` is invalid, or if the
67    /// `SubjectPublicKeyInfo` from the private key does not match the public
68    /// key for the end-entity certificate from the `cert_chain`.
69    pub fn with_single_cert(
70        self,
71        cert_chain: Vec<CertificateDer<'static>>,
72        key_der: PrivateKeyDer<'static>,
73    ) -> Result<ServerConfig, Error> {
74        let private_key = self
75            .state
76            .provider
77            .key_provider
78            .load_private_key(key_der)?;
79
80        let certified_key = CertifiedKey::new(cert_chain, private_key);
81        match certified_key.keys_match() {
82            // Don't treat unknown consistency as an error
83            Ok(()) | Err(Error::InconsistentKeys(InconsistentKeys::Unknown)) => (),
84            Err(err) => return Err(err),
85        }
86
87        let resolver = handy::AlwaysResolvesChain::new(certified_key);
88        Ok(self.with_cert_resolver(Arc::new(resolver)))
89    }
90
91    /// Sets a single certificate chain, matching private key and optional OCSP
92    /// response.  This certificate and key is used for all
93    /// subsequent connections, irrespective of things like SNI hostname.
94    ///
95    /// `cert_chain` is a vector of DER-encoded certificates.
96    /// `key_der` is a DER-encoded private key as PKCS#1, PKCS#8, or SEC1. The
97    /// `aws-lc-rs` and `ring` [`CryptoProvider`]s support all three encodings,
98    /// but other `CryptoProviders` may not.
99    /// `ocsp` is a DER-encoded OCSP response.  Ignored if zero length.
100    ///
101    /// This function fails if `key_der` is invalid, or if the
102    /// `SubjectPublicKeyInfo` from the private key does not match the public
103    /// key for the end-entity certificate from the `cert_chain`.
104    pub fn with_single_cert_with_ocsp(
105        self,
106        cert_chain: Vec<CertificateDer<'static>>,
107        key_der: PrivateKeyDer<'static>,
108        ocsp: Vec<u8>,
109    ) -> Result<ServerConfig, Error> {
110        let private_key = self
111            .state
112            .provider
113            .key_provider
114            .load_private_key(key_der)?;
115
116        let certified_key = CertifiedKey::new(cert_chain, private_key);
117        match certified_key.keys_match() {
118            // Don't treat unknown consistency as an error
119            Ok(()) | Err(Error::InconsistentKeys(InconsistentKeys::Unknown)) => (),
120            Err(err) => return Err(err),
121        }
122
123        let resolver = handy::AlwaysResolvesChain::new_with_extras(certified_key, ocsp);
124        Ok(self.with_cert_resolver(Arc::new(resolver)))
125    }
126
127    /// Sets a custom [`ResolvesServerCert`].
128    pub fn with_cert_resolver(self, cert_resolver: Arc<dyn ResolvesServerCert>) -> ServerConfig {
129        ServerConfig {
130            provider: self.state.provider,
131            verifier: self.state.verifier,
132            cert_resolver,
133            ignore_client_order: false,
134            max_fragment_size: None,
135            #[cfg(feature = "std")]
136            session_storage: handy::ServerSessionMemoryCache::new(256),
137            #[cfg(not(feature = "std"))]
138            session_storage: Arc::new(handy::NoServerSessionStorage {}),
139            ticketer: Arc::new(handy::NeverProducesTickets {}),
140            alpn_protocols: Vec::new(),
141            versions: self.state.versions,
142            key_log: Arc::new(NoKeyLog {}),
143            enable_secret_extraction: false,
144            max_early_data_size: 0,
145            send_half_rtt_data: false,
146            send_tls13_tickets: 4,
147            #[cfg(feature = "tls12")]
148            require_ems: cfg!(feature = "fips"),
149            time_provider: self.state.time_provider,
150            cert_compressors: compress::default_cert_compressors().to_vec(),
151            cert_compression_cache: Arc::new(compress::CompressionCache::default()),
152            cert_decompressors: compress::default_cert_decompressors().to_vec(),
153        }
154    }
155}