summaryrefslogtreecommitdiff
path: root/vendor/rustls/src/builder.rs
diff options
context:
space:
mode:
authormo khan <mo@mokhan.ca>2025-07-10 13:11:11 -0600
committermo khan <mo@mokhan.ca>2025-07-10 13:11:11 -0600
commit01959b16a21b22b5df5f16569c2a8e8f92beecef (patch)
tree32afa5d747c5466345c59ec52161a7cba3d6d755 /vendor/rustls/src/builder.rs
parentff30574117a996df332e23d1fb6f65259b316b5b (diff)
chore: vendor dependencies
Diffstat (limited to 'vendor/rustls/src/builder.rs')
-rw-r--r--vendor/rustls/src/builder.rs290
1 files changed, 290 insertions, 0 deletions
diff --git a/vendor/rustls/src/builder.rs b/vendor/rustls/src/builder.rs
new file mode 100644
index 00000000..f8ff6140
--- /dev/null
+++ b/vendor/rustls/src/builder.rs
@@ -0,0 +1,290 @@
+use alloc::format;
+use alloc::vec::Vec;
+use core::fmt;
+use core::marker::PhantomData;
+
+use crate::client::EchMode;
+use crate::crypto::CryptoProvider;
+use crate::error::Error;
+use crate::msgs::handshake::ALL_KEY_EXCHANGE_ALGORITHMS;
+use crate::sync::Arc;
+use crate::time_provider::TimeProvider;
+use crate::versions;
+#[cfg(doc)]
+use crate::{ClientConfig, ServerConfig};
+
+/// A [builder] for [`ServerConfig`] or [`ClientConfig`] values.
+///
+/// To get one of these, call [`ServerConfig::builder()`] or [`ClientConfig::builder()`].
+///
+/// To build a config, you must make at least two decisions (in order):
+///
+/// - How should this client or server verify certificates provided by its peer?
+/// - What certificates should this client or server present to its peer?
+///
+/// For settings besides these, see the fields of [`ServerConfig`] and [`ClientConfig`].
+///
+/// The usual choice for protocol primitives is to call
+/// [`ClientConfig::builder`]/[`ServerConfig::builder`]
+/// which will use rustls' default cryptographic provider and safe defaults for ciphersuites and
+/// supported protocol versions.
+///
+/// ```
+/// # #[cfg(feature = "aws_lc_rs")] {
+/// # rustls::crypto::aws_lc_rs::default_provider().install_default();
+/// use rustls::{ClientConfig, ServerConfig};
+/// ClientConfig::builder()
+/// // ...
+/// # ;
+///
+/// ServerConfig::builder()
+/// // ...
+/// # ;
+/// # }
+/// ```
+///
+/// You may also override the choice of protocol versions:
+///
+/// ```no_run
+/// # #[cfg(feature = "aws_lc_rs")] {
+/// # rustls::crypto::aws_lc_rs::default_provider().install_default();
+/// # use rustls::ServerConfig;
+/// ServerConfig::builder_with_protocol_versions(&[&rustls::version::TLS13])
+/// // ...
+/// # ;
+/// # }
+/// ```
+///
+/// Overriding the default cryptographic provider introduces a `Result` that must be unwrapped,
+/// because the config builder checks for consistency of the choices made. For instance, it's an error to
+/// configure only TLS 1.2 cipher suites while specifying that TLS 1.3 should be the only supported protocol
+/// version.
+///
+/// If you configure a smaller set of protocol primitives than the default, you may get a smaller binary,
+/// since the code for the unused ones can be optimized away at link time.
+///
+/// After choosing protocol primitives, you must choose (a) how to verify certificates and (b) what certificates
+/// (if any) to send to the peer. The methods to do this are specific to whether you're building a ClientConfig
+/// or a ServerConfig, as tracked by the [`ConfigSide`] type parameter on the various impls of ConfigBuilder.
+///
+/// # ClientConfig certificate configuration
+///
+/// For a client, _certificate verification_ must be configured either by calling one of:
+/// - [`ConfigBuilder::with_root_certificates`] or
+/// - [`ConfigBuilder::dangerous()`] and [`DangerousClientConfigBuilder::with_custom_certificate_verifier`]
+///
+/// Next, _certificate sending_ (also known as "client authentication", "mutual TLS", or "mTLS") must be configured
+/// or disabled using one of:
+/// - [`ConfigBuilder::with_no_client_auth`] - to not send client authentication (most common)
+/// - [`ConfigBuilder::with_client_auth_cert`] - to always send a specific certificate
+/// - [`ConfigBuilder::with_client_cert_resolver`] - to send a certificate chosen dynamically
+///
+/// For example:
+///
+/// ```
+/// # #[cfg(feature = "aws_lc_rs")] {
+/// # rustls::crypto::aws_lc_rs::default_provider().install_default();
+/// # use rustls::ClientConfig;
+/// # let root_certs = rustls::RootCertStore::empty();
+/// ClientConfig::builder()
+/// .with_root_certificates(root_certs)
+/// .with_no_client_auth();
+/// # }
+/// ```
+///
+/// # ServerConfig certificate configuration
+///
+/// For a server, _certificate verification_ must be configured by calling one of:
+/// - [`ConfigBuilder::with_no_client_auth`] - to not require client authentication (most common)
+/// - [`ConfigBuilder::with_client_cert_verifier`] - to use a custom verifier
+///
+/// Next, _certificate sending_ must be configured by calling one of:
+/// - [`ConfigBuilder::with_single_cert`] - to send a specific certificate
+/// - [`ConfigBuilder::with_single_cert_with_ocsp`] - to send a specific certificate, plus stapled OCSP
+/// - [`ConfigBuilder::with_cert_resolver`] - to send a certificate chosen dynamically
+///
+/// For example:
+///
+/// ```no_run
+/// # #[cfg(feature = "aws_lc_rs")] {
+/// # rustls::crypto::aws_lc_rs::default_provider().install_default();
+/// # use rustls::ServerConfig;
+/// # let certs = vec![];
+/// # let private_key = pki_types::PrivateKeyDer::from(
+/// # pki_types::PrivatePkcs8KeyDer::from(vec![])
+/// # );
+/// ServerConfig::builder()
+/// .with_no_client_auth()
+/// .with_single_cert(certs, private_key)
+/// .expect("bad certificate/key");
+/// # }
+/// ```
+///
+/// # Types
+///
+/// ConfigBuilder uses the [typestate] pattern to ensure at compile time that each required
+/// configuration item is provided exactly once. This is tracked in the `State` type parameter,
+/// which can have these values:
+///
+/// - [`WantsVersions`]
+/// - [`WantsVerifier`]
+/// - [`WantsClientCert`]
+/// - [`WantsServerCert`]
+///
+/// The other type parameter is `Side`, which is either `ServerConfig` or `ClientConfig`
+/// depending on whether the ConfigBuilder was built with [`ServerConfig::builder()`] or
+/// [`ClientConfig::builder()`].
+///
+/// You won't need to write out either of these type parameters explicitly. If you write a
+/// correct chain of configuration calls they will be used automatically. If you write an
+/// incorrect chain of configuration calls you will get an error message from the compiler
+/// mentioning some of these types.
+///
+/// Additionally, ServerConfig and ClientConfig carry a private field containing a
+/// [`CryptoProvider`], from [`ClientConfig::builder_with_provider()`] or
+/// [`ServerConfig::builder_with_provider()`]. This determines which cryptographic backend
+/// is used. The default is [the process-default provider](`CryptoProvider::get_default`).
+///
+/// [builder]: https://rust-unofficial.github.io/patterns/patterns/creational/builder.html
+/// [typestate]: http://cliffle.com/blog/rust-typestate/
+/// [`ServerConfig`]: crate::ServerConfig
+/// [`ServerConfig::builder`]: crate::ServerConfig::builder
+/// [`ClientConfig`]: crate::ClientConfig
+/// [`ClientConfig::builder()`]: crate::ClientConfig::builder()
+/// [`ServerConfig::builder()`]: crate::ServerConfig::builder()
+/// [`ClientConfig::builder_with_provider()`]: crate::ClientConfig::builder_with_provider()
+/// [`ServerConfig::builder_with_provider()`]: crate::ServerConfig::builder_with_provider()
+/// [`ConfigBuilder<ClientConfig, WantsVerifier>`]: struct.ConfigBuilder.html#impl-3
+/// [`ConfigBuilder<ServerConfig, WantsVerifier>`]: struct.ConfigBuilder.html#impl-6
+/// [`WantsClientCert`]: crate::client::WantsClientCert
+/// [`WantsServerCert`]: crate::server::WantsServerCert
+/// [`CryptoProvider::get_default`]: crate::crypto::CryptoProvider::get_default
+/// [`DangerousClientConfigBuilder::with_custom_certificate_verifier`]: crate::client::danger::DangerousClientConfigBuilder::with_custom_certificate_verifier
+#[derive(Clone)]
+pub struct ConfigBuilder<Side: ConfigSide, State> {
+ pub(crate) state: State,
+ pub(crate) provider: Arc<CryptoProvider>,
+ pub(crate) time_provider: Arc<dyn TimeProvider>,
+ pub(crate) side: PhantomData<Side>,
+}
+
+impl<Side: ConfigSide, State> ConfigBuilder<Side, State> {
+ /// Return the crypto provider used to construct this builder.
+ pub fn crypto_provider(&self) -> &Arc<CryptoProvider> {
+ &self.provider
+ }
+}
+
+impl<Side: ConfigSide, State: fmt::Debug> fmt::Debug for ConfigBuilder<Side, State> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let side_name = core::any::type_name::<Side>();
+ let (ty, _) = side_name
+ .split_once('<')
+ .unwrap_or((side_name, ""));
+ let (_, name) = ty.rsplit_once("::").unwrap_or(("", ty));
+
+ f.debug_struct(&format!("ConfigBuilder<{name}, _>",))
+ .field("state", &self.state)
+ .finish()
+ }
+}
+
+/// Config builder state where the caller must supply TLS protocol versions.
+///
+/// For more information, see the [`ConfigBuilder`] documentation.
+#[derive(Clone, Debug)]
+pub struct WantsVersions {}
+
+impl<S: ConfigSide> ConfigBuilder<S, WantsVersions> {
+ /// Accept the default protocol versions: both TLS1.2 and TLS1.3 are enabled.
+ pub fn with_safe_default_protocol_versions(
+ self,
+ ) -> Result<ConfigBuilder<S, WantsVerifier>, Error> {
+ self.with_protocol_versions(versions::DEFAULT_VERSIONS)
+ }
+
+ /// Use a specific set of protocol versions.
+ pub fn with_protocol_versions(
+ self,
+ versions: &[&'static versions::SupportedProtocolVersion],
+ ) -> Result<ConfigBuilder<S, WantsVerifier>, Error> {
+ let mut any_usable_suite = false;
+ for suite in &self.provider.cipher_suites {
+ if versions.contains(&suite.version()) {
+ any_usable_suite = true;
+ break;
+ }
+ }
+
+ if !any_usable_suite {
+ return Err(Error::General("no usable cipher suites configured".into()));
+ }
+
+ if self.provider.kx_groups.is_empty() {
+ return Err(Error::General("no kx groups configured".into()));
+ }
+
+ // verifying cipher suites have matching kx groups
+ let mut supported_kx_algos = Vec::with_capacity(ALL_KEY_EXCHANGE_ALGORITHMS.len());
+ for group in self.provider.kx_groups.iter() {
+ let kx = group.name().key_exchange_algorithm();
+ if !supported_kx_algos.contains(&kx) {
+ supported_kx_algos.push(kx);
+ }
+ // Small optimization. We don't need to go over other key exchange groups
+ // if we already cover all supported key exchange algorithms
+ if supported_kx_algos.len() == ALL_KEY_EXCHANGE_ALGORITHMS.len() {
+ break;
+ }
+ }
+
+ for cs in self.provider.cipher_suites.iter() {
+ let cs_kx = cs.key_exchange_algorithms();
+ if cs_kx
+ .iter()
+ .any(|kx| supported_kx_algos.contains(kx))
+ {
+ continue;
+ }
+ let suite_name = cs.common().suite;
+ return Err(Error::General(alloc::format!(
+ "Ciphersuite {suite_name:?} requires {cs_kx:?} key exchange, but no {cs_kx:?}-compatible \
+ key exchange groups were present in `CryptoProvider`'s `kx_groups` field",
+ )));
+ }
+
+ Ok(ConfigBuilder {
+ state: WantsVerifier {
+ versions: versions::EnabledVersions::new(versions),
+ client_ech_mode: None,
+ },
+ provider: self.provider,
+ time_provider: self.time_provider,
+ side: self.side,
+ })
+ }
+}
+
+/// Config builder state where the caller must supply a verifier.
+///
+/// For more information, see the [`ConfigBuilder`] documentation.
+#[derive(Clone, Debug)]
+pub struct WantsVerifier {
+ pub(crate) versions: versions::EnabledVersions,
+ pub(crate) client_ech_mode: Option<EchMode>,
+}
+
+/// Helper trait to abstract [`ConfigBuilder`] over building a [`ClientConfig`] or [`ServerConfig`].
+///
+/// [`ClientConfig`]: crate::ClientConfig
+/// [`ServerConfig`]: crate::ServerConfig
+pub trait ConfigSide: sealed::Sealed {}
+
+impl ConfigSide for crate::ClientConfig {}
+impl ConfigSide for crate::ServerConfig {}
+
+mod sealed {
+ pub trait Sealed {}
+ impl Sealed for crate::ClientConfig {}
+ impl Sealed for crate::ServerConfig {}
+}