| 1 | use alloc::boxed::Box; |
| 2 | use alloc::vec::Vec; |
| 3 | use core::fmt; |
| 4 | use core::fmt::{Debug, Formatter}; |
| 5 | use core::marker::PhantomData; |
| 6 | use core::ops::{Deref, DerefMut}; |
| 7 | #[cfg (feature = "std" )] |
| 8 | use std::io; |
| 9 | |
| 10 | use pki_types::{DnsName, UnixTime}; |
| 11 | |
| 12 | use super::hs; |
| 13 | #[cfg (feature = "std" )] |
| 14 | use crate::WantsVerifier; |
| 15 | use crate::builder::ConfigBuilder; |
| 16 | use crate::common_state::{CommonState, Side}; |
| 17 | #[cfg (feature = "std" )] |
| 18 | use crate::common_state::{Protocol, State}; |
| 19 | use crate::conn::{ConnectionCommon, ConnectionCore, UnbufferedConnectionCommon}; |
| 20 | #[cfg (doc)] |
| 21 | use crate::crypto; |
| 22 | use crate::crypto::CryptoProvider; |
| 23 | use crate::enums::{CipherSuite, ProtocolVersion, SignatureScheme}; |
| 24 | use crate::error::Error; |
| 25 | use crate::log::trace; |
| 26 | use crate::msgs::base::Payload; |
| 27 | use crate::msgs::enums::CertificateType; |
| 28 | use crate::msgs::handshake::{ClientHelloPayload, ProtocolName, ServerExtension}; |
| 29 | use crate::msgs::message::Message; |
| 30 | use crate::suites::ExtractedSecrets; |
| 31 | use crate::sync::Arc; |
| 32 | #[cfg (feature = "std" )] |
| 33 | use crate::time_provider::DefaultTimeProvider; |
| 34 | use crate::time_provider::TimeProvider; |
| 35 | use crate::vecbuf::ChunkVecBuffer; |
| 36 | use crate::{DistinguishedName, KeyLog, WantsVersions, compress, sign, verify, versions}; |
| 37 | |
| 38 | /// A trait for the ability to store server session data. |
| 39 | /// |
| 40 | /// The keys and values are opaque. |
| 41 | /// |
| 42 | /// Inserted keys are randomly chosen by the library and have |
| 43 | /// no internal structure (in other words, you may rely on all |
| 44 | /// bits being uniformly random). Queried keys are untrusted data. |
| 45 | /// |
| 46 | /// Both the keys and values should be treated as |
| 47 | /// **highly sensitive data**, containing enough key material |
| 48 | /// to break all security of the corresponding sessions. |
| 49 | /// |
| 50 | /// Implementations can be lossy (in other words, forgetting |
| 51 | /// key/value pairs) without any negative security consequences. |
| 52 | /// |
| 53 | /// However, note that `take` **must** reliably delete a returned |
| 54 | /// value. If it does not, there may be security consequences. |
| 55 | /// |
| 56 | /// `put` and `take` are mutating operations; this isn't expressed |
| 57 | /// in the type system to allow implementations freedom in |
| 58 | /// how to achieve interior mutability. `Mutex` is a common |
| 59 | /// choice. |
| 60 | pub trait StoresServerSessions: Debug + Send + Sync { |
| 61 | /// Store session secrets encoded in `value` against `key`, |
| 62 | /// overwrites any existing value against `key`. Returns `true` |
| 63 | /// if the value was stored. |
| 64 | fn put(&self, key: Vec<u8>, value: Vec<u8>) -> bool; |
| 65 | |
| 66 | /// Find a value with the given `key`. Return it, or None |
| 67 | /// if it doesn't exist. |
| 68 | fn get(&self, key: &[u8]) -> Option<Vec<u8>>; |
| 69 | |
| 70 | /// Find a value with the given `key`. Return it and delete it; |
| 71 | /// or None if it doesn't exist. |
| 72 | fn take(&self, key: &[u8]) -> Option<Vec<u8>>; |
| 73 | |
| 74 | /// Whether the store can cache another session. This is used to indicate to clients |
| 75 | /// whether their session can be resumed; the implementation is not required to remember |
| 76 | /// a session even if it returns `true` here. |
| 77 | fn can_cache(&self) -> bool; |
| 78 | } |
| 79 | |
| 80 | /// A trait for the ability to encrypt and decrypt tickets. |
| 81 | pub trait ProducesTickets: Debug + Send + Sync { |
| 82 | /// Returns true if this implementation will encrypt/decrypt |
| 83 | /// tickets. Should return false if this is a dummy |
| 84 | /// implementation: the server will not send the SessionTicket |
| 85 | /// extension and will not call the other functions. |
| 86 | fn enabled(&self) -> bool; |
| 87 | |
| 88 | /// Returns the lifetime in seconds of tickets produced now. |
| 89 | /// The lifetime is provided as a hint to clients that the |
| 90 | /// ticket will not be useful after the given time. |
| 91 | /// |
| 92 | /// This lifetime must be implemented by key rolling and |
| 93 | /// erasure, *not* by storing a lifetime in the ticket. |
| 94 | /// |
| 95 | /// The objective is to limit damage to forward secrecy caused |
| 96 | /// by tickets, not just limiting their lifetime. |
| 97 | fn lifetime(&self) -> u32; |
| 98 | |
| 99 | /// Encrypt and authenticate `plain`, returning the resulting |
| 100 | /// ticket. Return None if `plain` cannot be encrypted for |
| 101 | /// some reason: an empty ticket will be sent and the connection |
| 102 | /// will continue. |
| 103 | fn encrypt(&self, plain: &[u8]) -> Option<Vec<u8>>; |
| 104 | |
| 105 | /// Decrypt `cipher`, validating its authenticity protection |
| 106 | /// and recovering the plaintext. `cipher` is fully attacker |
| 107 | /// controlled, so this decryption must be side-channel free, |
| 108 | /// panic-proof, and otherwise bullet-proof. If the decryption |
| 109 | /// fails, return None. |
| 110 | fn decrypt(&self, cipher: &[u8]) -> Option<Vec<u8>>; |
| 111 | } |
| 112 | |
| 113 | /// How to choose a certificate chain and signing key for use |
| 114 | /// in server authentication. |
| 115 | /// |
| 116 | /// This is suitable when selecting a certificate does not require |
| 117 | /// I/O or when the application is using blocking I/O anyhow. |
| 118 | /// |
| 119 | /// For applications that use async I/O and need to do I/O to choose |
| 120 | /// a certificate (for instance, fetching a certificate from a data store), |
| 121 | /// the [`Acceptor`] interface is more suitable. |
| 122 | pub trait ResolvesServerCert: Debug + Send + Sync { |
| 123 | /// Choose a certificate chain and matching key given simplified |
| 124 | /// ClientHello information. |
| 125 | /// |
| 126 | /// Return `None` to abort the handshake. |
| 127 | fn resolve(&self, client_hello: ClientHello<'_>) -> Option<Arc<sign::CertifiedKey>>; |
| 128 | |
| 129 | /// Return true when the server only supports raw public keys. |
| 130 | fn only_raw_public_keys(&self) -> bool { |
| 131 | false |
| 132 | } |
| 133 | } |
| 134 | |
| 135 | /// A struct representing the received Client Hello |
| 136 | #[derive (Debug)] |
| 137 | pub struct ClientHello<'a> { |
| 138 | pub(super) server_name: &'a Option<DnsName<'a>>, |
| 139 | pub(super) signature_schemes: &'a [SignatureScheme], |
| 140 | pub(super) alpn: Option<&'a Vec<ProtocolName>>, |
| 141 | pub(super) server_cert_types: Option<&'a [CertificateType]>, |
| 142 | pub(super) client_cert_types: Option<&'a [CertificateType]>, |
| 143 | pub(super) cipher_suites: &'a [CipherSuite], |
| 144 | /// The [certificate_authorities] extension, if it was sent by the client. |
| 145 | /// |
| 146 | /// [certificate_authorities]: https://datatracker.ietf.org/doc/html/rfc8446#section-4.2.4 |
| 147 | pub(super) certificate_authorities: Option<&'a [DistinguishedName]>, |
| 148 | } |
| 149 | |
| 150 | impl<'a> ClientHello<'a> { |
| 151 | /// Get the server name indicator. |
| 152 | /// |
| 153 | /// Returns `None` if the client did not supply a SNI. |
| 154 | pub fn server_name(&self) -> Option<&str> { |
| 155 | self.server_name |
| 156 | .as_ref() |
| 157 | .map(<DnsName<'_> as AsRef<str>>::as_ref) |
| 158 | } |
| 159 | |
| 160 | /// Get the compatible signature schemes. |
| 161 | /// |
| 162 | /// Returns standard-specified default if the client omitted this extension. |
| 163 | pub fn signature_schemes(&self) -> &[SignatureScheme] { |
| 164 | self.signature_schemes |
| 165 | } |
| 166 | |
| 167 | /// Get the ALPN protocol identifiers submitted by the client. |
| 168 | /// |
| 169 | /// Returns `None` if the client did not include an ALPN extension. |
| 170 | /// |
| 171 | /// Application Layer Protocol Negotiation (ALPN) is a TLS extension that lets a client |
| 172 | /// submit a set of identifiers that each a represent an application-layer protocol. |
| 173 | /// The server will then pick its preferred protocol from the set submitted by the client. |
| 174 | /// Each identifier is represented as a byte array, although common values are often ASCII-encoded. |
| 175 | /// See the official RFC-7301 specifications at <https://datatracker.ietf.org/doc/html/rfc7301> |
| 176 | /// for more information on ALPN. |
| 177 | /// |
| 178 | /// For example, a HTTP client might specify "http/1.1" and/or "h2". Other well-known values |
| 179 | /// are listed in the at IANA registry at |
| 180 | /// <https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids>. |
| 181 | /// |
| 182 | /// The server can specify supported ALPN protocols by setting [`ServerConfig::alpn_protocols`]. |
| 183 | /// During the handshake, the server will select the first protocol configured that the client supports. |
| 184 | pub fn alpn(&self) -> Option<impl Iterator<Item = &'a [u8]>> { |
| 185 | self.alpn.map(|protocols| { |
| 186 | protocols |
| 187 | .iter() |
| 188 | .map(|proto| proto.as_ref()) |
| 189 | }) |
| 190 | } |
| 191 | |
| 192 | /// Get cipher suites. |
| 193 | pub fn cipher_suites(&self) -> &[CipherSuite] { |
| 194 | self.cipher_suites |
| 195 | } |
| 196 | |
| 197 | /// Get the server certificate types offered in the ClientHello. |
| 198 | /// |
| 199 | /// Returns `None` if the client did not include a certificate type extension. |
| 200 | pub fn server_cert_types(&self) -> Option<&'a [CertificateType]> { |
| 201 | self.server_cert_types |
| 202 | } |
| 203 | |
| 204 | /// Get the client certificate types offered in the ClientHello. |
| 205 | /// |
| 206 | /// Returns `None` if the client did not include a certificate type extension. |
| 207 | pub fn client_cert_types(&self) -> Option<&'a [CertificateType]> { |
| 208 | self.client_cert_types |
| 209 | } |
| 210 | |
| 211 | /// Get the [certificate_authorities] extension sent by the client. |
| 212 | /// |
| 213 | /// Returns `None` if the client did not send this extension. |
| 214 | /// |
| 215 | /// [certificate_authorities]: https://datatracker.ietf.org/doc/html/rfc8446#section-4.2.4 |
| 216 | pub fn certificate_authorities(&self) -> Option<&'a [DistinguishedName]> { |
| 217 | self.certificate_authorities |
| 218 | } |
| 219 | } |
| 220 | |
| 221 | /// Common configuration for a set of server sessions. |
| 222 | /// |
| 223 | /// Making one of these is cheap, though one of the inputs may be expensive: gathering trust roots |
| 224 | /// from the operating system to add to the [`RootCertStore`] passed to a `ClientCertVerifier` |
| 225 | /// builder may take on the order of a few hundred milliseconds. |
| 226 | /// |
| 227 | /// These must be created via the [`ServerConfig::builder()`] or [`ServerConfig::builder_with_provider()`] |
| 228 | /// function. |
| 229 | /// |
| 230 | /// # Defaults |
| 231 | /// |
| 232 | /// * [`ServerConfig::max_fragment_size`]: the default is `None` (meaning 16kB). |
| 233 | /// * [`ServerConfig::session_storage`]: if the `std` feature is enabled, the default stores 256 |
| 234 | /// sessions in memory. If the `std` feature is not enabled, the default is to not store any |
| 235 | /// sessions. In a no-std context, by enabling the `hashbrown` feature you may provide your |
| 236 | /// own `session_storage` using [`ServerSessionMemoryCache`] and a `crate::lock::MakeMutex` |
| 237 | /// implementation. |
| 238 | /// * [`ServerConfig::alpn_protocols`]: the default is empty -- no ALPN protocol is negotiated. |
| 239 | /// * [`ServerConfig::key_log`]: key material is not logged. |
| 240 | /// * [`ServerConfig::send_tls13_tickets`]: 2 tickets are sent. |
| 241 | /// * [`ServerConfig::cert_compressors`]: depends on the crate features, see [`compress::default_cert_compressors()`]. |
| 242 | /// * [`ServerConfig::cert_compression_cache`]: caches the most recently used 4 compressions |
| 243 | /// * [`ServerConfig::cert_decompressors`]: depends on the crate features, see [`compress::default_cert_decompressors()`]. |
| 244 | /// |
| 245 | /// # Sharing resumption storage between `ServerConfig`s |
| 246 | /// |
| 247 | /// In a program using many `ServerConfig`s it may improve resumption rates |
| 248 | /// (which has a significant impact on connection performance) if those |
| 249 | /// configs share [`ServerConfig::session_storage`] or [`ServerConfig::ticketer`]. |
| 250 | /// |
| 251 | /// However, caution is needed: other fields influence the security of a session |
| 252 | /// and resumption between them can be surprising. If sharing |
| 253 | /// [`ServerConfig::session_storage`] or [`ServerConfig::ticketer`] between two |
| 254 | /// `ServerConfig`s, you should also evaluate the following fields and ensure |
| 255 | /// they are equivalent: |
| 256 | /// |
| 257 | /// * `ServerConfig::verifier` -- client authentication requirements, |
| 258 | /// * [`ServerConfig::cert_resolver`] -- server identities. |
| 259 | /// |
| 260 | /// To illustrate, imagine two `ServerConfig`s `A` and `B`. `A` requires |
| 261 | /// client authentication, `B` does not. If `A` and `B` shared a resumption store, |
| 262 | /// it would be possible for a session originated by `B` (that is, an unauthenticated client) |
| 263 | /// to be inserted into the store, and then resumed by `A`. This would give a false |
| 264 | /// impression to the user of `A` that the client was authenticated. This is possible |
| 265 | /// whether the resumption is performed statefully (via [`ServerConfig::session_storage`]) |
| 266 | /// or statelessly (via [`ServerConfig::ticketer`]). |
| 267 | /// |
| 268 | /// _Unlike_ `ClientConfig`, rustls does not enforce any policy here. |
| 269 | /// |
| 270 | /// [`RootCertStore`]: crate::RootCertStore |
| 271 | /// [`ServerSessionMemoryCache`]: crate::server::handy::ServerSessionMemoryCache |
| 272 | #[derive (Clone, Debug)] |
| 273 | pub struct ServerConfig { |
| 274 | /// Source of randomness and other crypto. |
| 275 | pub(super) provider: Arc<CryptoProvider>, |
| 276 | |
| 277 | /// Ignore the client's ciphersuite order. Instead, |
| 278 | /// choose the top ciphersuite in the server list |
| 279 | /// which is supported by the client. |
| 280 | pub ignore_client_order: bool, |
| 281 | |
| 282 | /// The maximum size of plaintext input to be emitted in a single TLS record. |
| 283 | /// A value of None is equivalent to the [TLS maximum] of 16 kB. |
| 284 | /// |
| 285 | /// rustls enforces an arbitrary minimum of 32 bytes for this field. |
| 286 | /// Out of range values are reported as errors from [ServerConnection::new]. |
| 287 | /// |
| 288 | /// Setting this value to a little less than the TCP MSS may improve latency |
| 289 | /// for stream-y workloads. |
| 290 | /// |
| 291 | /// [TLS maximum]: https://datatracker.ietf.org/doc/html/rfc8446#section-5.1 |
| 292 | /// [ServerConnection::new]: crate::server::ServerConnection::new |
| 293 | pub max_fragment_size: Option<usize>, |
| 294 | |
| 295 | /// How to store client sessions. |
| 296 | /// |
| 297 | /// See [ServerConfig#sharing-resumption-storage-between-serverconfigs] |
| 298 | /// for a warning related to this field. |
| 299 | pub session_storage: Arc<dyn StoresServerSessions>, |
| 300 | |
| 301 | /// How to produce tickets. |
| 302 | /// |
| 303 | /// See [ServerConfig#sharing-resumption-storage-between-serverconfigs] |
| 304 | /// for a warning related to this field. |
| 305 | pub ticketer: Arc<dyn ProducesTickets>, |
| 306 | |
| 307 | /// How to choose a server cert and key. This is usually set by |
| 308 | /// [ConfigBuilder::with_single_cert] or [ConfigBuilder::with_cert_resolver]. |
| 309 | /// For async applications, see also [Acceptor]. |
| 310 | pub cert_resolver: Arc<dyn ResolvesServerCert>, |
| 311 | |
| 312 | /// Protocol names we support, most preferred first. |
| 313 | /// If empty we don't do ALPN at all. |
| 314 | pub alpn_protocols: Vec<Vec<u8>>, |
| 315 | |
| 316 | /// Supported protocol versions, in no particular order. |
| 317 | /// The default is all supported versions. |
| 318 | pub(super) versions: versions::EnabledVersions, |
| 319 | |
| 320 | /// How to verify client certificates. |
| 321 | pub(super) verifier: Arc<dyn verify::ClientCertVerifier>, |
| 322 | |
| 323 | /// How to output key material for debugging. The default |
| 324 | /// does nothing. |
| 325 | pub key_log: Arc<dyn KeyLog>, |
| 326 | |
| 327 | /// Allows traffic secrets to be extracted after the handshake, |
| 328 | /// e.g. for kTLS setup. |
| 329 | pub enable_secret_extraction: bool, |
| 330 | |
| 331 | /// Amount of early data to accept for sessions created by |
| 332 | /// this config. Specify 0 to disable early data. The |
| 333 | /// default is 0. |
| 334 | /// |
| 335 | /// Read the early data via [`ServerConnection::early_data`]. |
| 336 | /// |
| 337 | /// The units for this are _both_ plaintext bytes, _and_ ciphertext |
| 338 | /// bytes, depending on whether the server accepts a client's early_data |
| 339 | /// or not. It is therefore recommended to include some slop in |
| 340 | /// this value to account for the unknown amount of ciphertext |
| 341 | /// expansion in the latter case. |
| 342 | pub max_early_data_size: u32, |
| 343 | |
| 344 | /// Whether the server should send "0.5RTT" data. This means the server |
| 345 | /// sends data after its first flight of handshake messages, without |
| 346 | /// waiting for the client to complete the handshake. |
| 347 | /// |
| 348 | /// This can improve TTFB latency for either server-speaks-first protocols, |
| 349 | /// or client-speaks-first protocols when paired with "0RTT" data. This |
| 350 | /// comes at the cost of a subtle weakening of the normal handshake |
| 351 | /// integrity guarantees that TLS provides. Note that the initial |
| 352 | /// `ClientHello` is indirectly authenticated because it is included |
| 353 | /// in the transcript used to derive the keys used to encrypt the data. |
| 354 | /// |
| 355 | /// This only applies to TLS1.3 connections. TLS1.2 connections cannot |
| 356 | /// do this optimisation and this setting is ignored for them. It is |
| 357 | /// also ignored for TLS1.3 connections that even attempt client |
| 358 | /// authentication. |
| 359 | /// |
| 360 | /// This defaults to false. This means the first application data |
| 361 | /// sent by the server comes after receiving and validating the client's |
| 362 | /// handshake up to the `Finished` message. This is the safest option. |
| 363 | pub send_half_rtt_data: bool, |
| 364 | |
| 365 | /// How many TLS1.3 tickets to send immediately after a successful |
| 366 | /// handshake. |
| 367 | /// |
| 368 | /// Because TLS1.3 tickets are single-use, this allows |
| 369 | /// a client to perform multiple resumptions. |
| 370 | /// |
| 371 | /// The default is 2. |
| 372 | /// |
| 373 | /// If this is 0, no tickets are sent and clients will not be able to |
| 374 | /// do any resumption. |
| 375 | pub send_tls13_tickets: usize, |
| 376 | |
| 377 | /// If set to `true`, requires the client to support the extended |
| 378 | /// master secret extraction method defined in [RFC 7627]. |
| 379 | /// |
| 380 | /// The default is `true` if the "fips" crate feature is enabled, |
| 381 | /// `false` otherwise. |
| 382 | /// |
| 383 | /// It must be set to `true` to meet FIPS requirement mentioned in section |
| 384 | /// **D.Q Transition of the TLS 1.2 KDF to Support the Extended Master |
| 385 | /// Secret** from [FIPS 140-3 IG.pdf]. |
| 386 | /// |
| 387 | /// [RFC 7627]: https://datatracker.ietf.org/doc/html/rfc7627 |
| 388 | /// [FIPS 140-3 IG.pdf]: https://csrc.nist.gov/csrc/media/Projects/cryptographic-module-validation-program/documents/fips%20140-3/FIPS%20140-3%20IG.pdf |
| 389 | #[cfg (feature = "tls12" )] |
| 390 | pub require_ems: bool, |
| 391 | |
| 392 | /// Provides the current system time |
| 393 | pub time_provider: Arc<dyn TimeProvider>, |
| 394 | |
| 395 | /// How to compress the server's certificate chain. |
| 396 | /// |
| 397 | /// If a client supports this extension, and advertises support |
| 398 | /// for one of the compression algorithms included here, the |
| 399 | /// server certificate will be compressed according to [RFC8779]. |
| 400 | /// |
| 401 | /// This only applies to TLS1.3 connections. It is ignored for |
| 402 | /// TLS1.2 connections. |
| 403 | /// |
| 404 | /// [RFC8779]: https://datatracker.ietf.org/doc/rfc8879/ |
| 405 | pub cert_compressors: Vec<&'static dyn compress::CertCompressor>, |
| 406 | |
| 407 | /// Caching for compressed certificates. |
| 408 | /// |
| 409 | /// This is optional: [`compress::CompressionCache::Disabled`] gives |
| 410 | /// a cache that does no caching. |
| 411 | pub cert_compression_cache: Arc<compress::CompressionCache>, |
| 412 | |
| 413 | /// How to decompress the clients's certificate chain. |
| 414 | /// |
| 415 | /// If this is non-empty, the [RFC8779] certificate compression |
| 416 | /// extension is offered when requesting client authentication, |
| 417 | /// and any compressed certificates are transparently decompressed |
| 418 | /// during the handshake. |
| 419 | /// |
| 420 | /// This only applies to TLS1.3 connections. It is ignored for |
| 421 | /// TLS1.2 connections. |
| 422 | /// |
| 423 | /// [RFC8779]: https://datatracker.ietf.org/doc/rfc8879/ |
| 424 | pub cert_decompressors: Vec<&'static dyn compress::CertDecompressor>, |
| 425 | } |
| 426 | |
| 427 | impl ServerConfig { |
| 428 | /// Create a builder for a server configuration with |
| 429 | /// [the process-default `CryptoProvider`][CryptoProvider#using-the-per-process-default-cryptoprovider] |
| 430 | /// and safe protocol version defaults. |
| 431 | /// |
| 432 | /// For more information, see the [`ConfigBuilder`] documentation. |
| 433 | #[cfg (feature = "std" )] |
| 434 | pub fn builder() -> ConfigBuilder<Self, WantsVerifier> { |
| 435 | Self::builder_with_protocol_versions(versions::DEFAULT_VERSIONS) |
| 436 | } |
| 437 | |
| 438 | /// Create a builder for a server configuration with |
| 439 | /// [the process-default `CryptoProvider`][CryptoProvider#using-the-per-process-default-cryptoprovider] |
| 440 | /// and the provided protocol versions. |
| 441 | /// |
| 442 | /// Panics if |
| 443 | /// - the supported versions are not compatible with the provider (eg. |
| 444 | /// the combination of ciphersuites supported by the provider and supported |
| 445 | /// versions lead to zero cipher suites being usable), |
| 446 | /// - if a `CryptoProvider` cannot be resolved using a combination of |
| 447 | /// the crate features and process default. |
| 448 | /// |
| 449 | /// For more information, see the [`ConfigBuilder`] documentation. |
| 450 | #[cfg (feature = "std" )] |
| 451 | pub fn builder_with_protocol_versions( |
| 452 | versions: &[&'static versions::SupportedProtocolVersion], |
| 453 | ) -> ConfigBuilder<Self, WantsVerifier> { |
| 454 | // Safety assumptions: |
| 455 | // 1. that the provider has been installed (explicitly or implicitly) |
| 456 | // 2. that the process-level default provider is usable with the supplied protocol versions. |
| 457 | Self::builder_with_provider(Arc::clone( |
| 458 | CryptoProvider::get_default_or_install_from_crate_features(), |
| 459 | )) |
| 460 | .with_protocol_versions(versions) |
| 461 | .unwrap() |
| 462 | } |
| 463 | |
| 464 | /// Create a builder for a server configuration with a specific [`CryptoProvider`]. |
| 465 | /// |
| 466 | /// This will use the provider's configured ciphersuites. You must additionally choose |
| 467 | /// which protocol versions to enable, using `with_protocol_versions` or |
| 468 | /// `with_safe_default_protocol_versions` and handling the `Result` in case a protocol |
| 469 | /// version is not supported by the provider's ciphersuites. |
| 470 | /// |
| 471 | /// For more information, see the [`ConfigBuilder`] documentation. |
| 472 | #[cfg (feature = "std" )] |
| 473 | pub fn builder_with_provider( |
| 474 | provider: Arc<CryptoProvider>, |
| 475 | ) -> ConfigBuilder<Self, WantsVersions> { |
| 476 | ConfigBuilder { |
| 477 | state: WantsVersions {}, |
| 478 | provider, |
| 479 | time_provider: Arc::new(DefaultTimeProvider), |
| 480 | side: PhantomData, |
| 481 | } |
| 482 | } |
| 483 | |
| 484 | /// Create a builder for a server configuration with no default implementation details. |
| 485 | /// |
| 486 | /// This API must be used by `no_std` users. |
| 487 | /// |
| 488 | /// You must provide a specific [`TimeProvider`]. |
| 489 | /// |
| 490 | /// You must provide a specific [`CryptoProvider`]. |
| 491 | /// |
| 492 | /// This will use the provider's configured ciphersuites. You must additionally choose |
| 493 | /// which protocol versions to enable, using `with_protocol_versions` or |
| 494 | /// `with_safe_default_protocol_versions` and handling the `Result` in case a protocol |
| 495 | /// version is not supported by the provider's ciphersuites. |
| 496 | /// |
| 497 | /// For more information, see the [`ConfigBuilder`] documentation. |
| 498 | pub fn builder_with_details( |
| 499 | provider: Arc<CryptoProvider>, |
| 500 | time_provider: Arc<dyn TimeProvider>, |
| 501 | ) -> ConfigBuilder<Self, WantsVersions> { |
| 502 | ConfigBuilder { |
| 503 | state: WantsVersions {}, |
| 504 | provider, |
| 505 | time_provider, |
| 506 | side: PhantomData, |
| 507 | } |
| 508 | } |
| 509 | |
| 510 | /// Return `true` if connections made with this `ServerConfig` will |
| 511 | /// operate in FIPS mode. |
| 512 | /// |
| 513 | /// This is different from [`CryptoProvider::fips()`]: [`CryptoProvider::fips()`] |
| 514 | /// is concerned only with cryptography, whereas this _also_ covers TLS-level |
| 515 | /// configuration that NIST recommends. |
| 516 | pub fn fips(&self) -> bool { |
| 517 | #[cfg (feature = "tls12" )] |
| 518 | { |
| 519 | self.provider.fips() && self.require_ems |
| 520 | } |
| 521 | |
| 522 | #[cfg (not(feature = "tls12" ))] |
| 523 | { |
| 524 | self.provider.fips() |
| 525 | } |
| 526 | } |
| 527 | |
| 528 | /// Return the crypto provider used to construct this client configuration. |
| 529 | pub fn crypto_provider(&self) -> &Arc<CryptoProvider> { |
| 530 | &self.provider |
| 531 | } |
| 532 | |
| 533 | /// We support a given TLS version if it's quoted in the configured |
| 534 | /// versions *and* at least one ciphersuite for this version is |
| 535 | /// also configured. |
| 536 | pub(crate) fn supports_version(&self, v: ProtocolVersion) -> bool { |
| 537 | self.versions.contains(v) |
| 538 | && self |
| 539 | .provider |
| 540 | .cipher_suites |
| 541 | .iter() |
| 542 | .any(|cs| cs.version().version == v) |
| 543 | } |
| 544 | |
| 545 | #[cfg (feature = "std" )] |
| 546 | pub(crate) fn supports_protocol(&self, proto: Protocol) -> bool { |
| 547 | self.provider |
| 548 | .cipher_suites |
| 549 | .iter() |
| 550 | .any(|cs| cs.usable_for_protocol(proto)) |
| 551 | } |
| 552 | |
| 553 | pub(super) fn current_time(&self) -> Result<UnixTime, Error> { |
| 554 | self.time_provider |
| 555 | .current_time() |
| 556 | .ok_or(Error::FailedToGetCurrentTime) |
| 557 | } |
| 558 | } |
| 559 | |
| 560 | #[cfg (feature = "std" )] |
| 561 | mod connection { |
| 562 | use alloc::boxed::Box; |
| 563 | use alloc::vec::Vec; |
| 564 | use core::fmt; |
| 565 | use core::fmt::{Debug, Formatter}; |
| 566 | use core::ops::{Deref, DerefMut}; |
| 567 | use std::io; |
| 568 | |
| 569 | use super::{Accepted, Accepting, EarlyDataState, ServerConfig, ServerConnectionData}; |
| 570 | use crate::common_state::{CommonState, Context, Side}; |
| 571 | use crate::conn::{ConnectionCommon, ConnectionCore}; |
| 572 | use crate::error::Error; |
| 573 | use crate::server::hs; |
| 574 | use crate::suites::ExtractedSecrets; |
| 575 | use crate::sync::Arc; |
| 576 | use crate::vecbuf::ChunkVecBuffer; |
| 577 | |
| 578 | /// Allows reading of early data in resumed TLS1.3 connections. |
| 579 | /// |
| 580 | /// "Early data" is also known as "0-RTT data". |
| 581 | /// |
| 582 | /// This structure implements [`std::io::Read`]. |
| 583 | pub struct ReadEarlyData<'a> { |
| 584 | early_data: &'a mut EarlyDataState, |
| 585 | } |
| 586 | |
| 587 | impl<'a> ReadEarlyData<'a> { |
| 588 | fn new(early_data: &'a mut EarlyDataState) -> Self { |
| 589 | ReadEarlyData { early_data } |
| 590 | } |
| 591 | } |
| 592 | |
| 593 | impl io::Read for ReadEarlyData<'_> { |
| 594 | fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { |
| 595 | self.early_data.read(buf) |
| 596 | } |
| 597 | |
| 598 | #[cfg (read_buf)] |
| 599 | fn read_buf(&mut self, cursor: core::io::BorrowedCursor<'_>) -> io::Result<()> { |
| 600 | self.early_data.read_buf(cursor) |
| 601 | } |
| 602 | } |
| 603 | |
| 604 | /// This represents a single TLS server connection. |
| 605 | /// |
| 606 | /// Send TLS-protected data to the peer using the `io::Write` trait implementation. |
| 607 | /// Read data from the peer using the `io::Read` trait implementation. |
| 608 | pub struct ServerConnection { |
| 609 | pub(super) inner: ConnectionCommon<ServerConnectionData>, |
| 610 | } |
| 611 | |
| 612 | impl ServerConnection { |
| 613 | /// Make a new ServerConnection. `config` controls how |
| 614 | /// we behave in the TLS protocol. |
| 615 | pub fn new(config: Arc<ServerConfig>) -> Result<Self, Error> { |
| 616 | Ok(Self { |
| 617 | inner: ConnectionCommon::from(ConnectionCore::for_server(config, Vec::new())?), |
| 618 | }) |
| 619 | } |
| 620 | |
| 621 | /// Retrieves the server name, if any, used to select the certificate and |
| 622 | /// private key. |
| 623 | /// |
| 624 | /// This returns `None` until some time after the client's server name indication |
| 625 | /// (SNI) extension value is processed during the handshake. It will never be |
| 626 | /// `None` when the connection is ready to send or process application data, |
| 627 | /// unless the client does not support SNI. |
| 628 | /// |
| 629 | /// This is useful for application protocols that need to enforce that the |
| 630 | /// server name matches an application layer protocol hostname. For |
| 631 | /// example, HTTP/1.1 servers commonly expect the `Host:` header field of |
| 632 | /// every request on a connection to match the hostname in the SNI extension |
| 633 | /// when the client provides the SNI extension. |
| 634 | /// |
| 635 | /// The server name is also used to match sessions during session resumption. |
| 636 | pub fn server_name(&self) -> Option<&str> { |
| 637 | self.inner.core.get_sni_str() |
| 638 | } |
| 639 | |
| 640 | /// Application-controlled portion of the resumption ticket supplied by the client, if any. |
| 641 | /// |
| 642 | /// Recovered from the prior session's `set_resumption_data`. Integrity is guaranteed by rustls. |
| 643 | /// |
| 644 | /// Returns `Some` if and only if a valid resumption ticket has been received from the client. |
| 645 | pub fn received_resumption_data(&self) -> Option<&[u8]> { |
| 646 | self.inner |
| 647 | .core |
| 648 | .data |
| 649 | .received_resumption_data |
| 650 | .as_ref() |
| 651 | .map(|x| &x[..]) |
| 652 | } |
| 653 | |
| 654 | /// Set the resumption data to embed in future resumption tickets supplied to the client. |
| 655 | /// |
| 656 | /// Defaults to the empty byte string. Must be less than 2^15 bytes to allow room for other |
| 657 | /// data. Should be called while `is_handshaking` returns true to ensure all transmitted |
| 658 | /// resumption tickets are affected. |
| 659 | /// |
| 660 | /// Integrity will be assured by rustls, but the data will be visible to the client. If secrecy |
| 661 | /// from the client is desired, encrypt the data separately. |
| 662 | pub fn set_resumption_data(&mut self, data: &[u8]) { |
| 663 | assert!(data.len() < 2usize.pow(15)); |
| 664 | self.inner.core.data.resumption_data = data.into(); |
| 665 | } |
| 666 | |
| 667 | /// Explicitly discard early data, notifying the client |
| 668 | /// |
| 669 | /// Useful if invariants encoded in `received_resumption_data()` cannot be respected. |
| 670 | /// |
| 671 | /// Must be called while `is_handshaking` is true. |
| 672 | pub fn reject_early_data(&mut self) { |
| 673 | self.inner.core.reject_early_data() |
| 674 | } |
| 675 | |
| 676 | /// Returns an `io::Read` implementer you can read bytes from that are |
| 677 | /// received from a client as TLS1.3 0RTT/"early" data, during the handshake. |
| 678 | /// |
| 679 | /// This returns `None` in many circumstances, such as : |
| 680 | /// |
| 681 | /// - Early data is disabled if [`ServerConfig::max_early_data_size`] is zero (the default). |
| 682 | /// - The session negotiated with the client is not TLS1.3. |
| 683 | /// - The client just doesn't support early data. |
| 684 | /// - The connection doesn't resume an existing session. |
| 685 | /// - The client hasn't sent a full ClientHello yet. |
| 686 | pub fn early_data(&mut self) -> Option<ReadEarlyData<'_>> { |
| 687 | let data = &mut self.inner.core.data; |
| 688 | if data.early_data.was_accepted() { |
| 689 | Some(ReadEarlyData::new(&mut data.early_data)) |
| 690 | } else { |
| 691 | None |
| 692 | } |
| 693 | } |
| 694 | |
| 695 | /// Return true if the connection was made with a `ServerConfig` that is FIPS compatible. |
| 696 | /// |
| 697 | /// This is different from [`crate::crypto::CryptoProvider::fips()`]: |
| 698 | /// it is concerned only with cryptography, whereas this _also_ covers TLS-level |
| 699 | /// configuration that NIST recommends, as well as ECH HPKE suites if applicable. |
| 700 | pub fn fips(&self) -> bool { |
| 701 | self.inner.core.common_state.fips |
| 702 | } |
| 703 | |
| 704 | /// Extract secrets, so they can be used when configuring kTLS, for example. |
| 705 | /// Should be used with care as it exposes secret key material. |
| 706 | pub fn dangerous_extract_secrets(self) -> Result<ExtractedSecrets, Error> { |
| 707 | self.inner.dangerous_extract_secrets() |
| 708 | } |
| 709 | } |
| 710 | |
| 711 | impl Debug for ServerConnection { |
| 712 | fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { |
| 713 | f.debug_struct("ServerConnection" ) |
| 714 | .finish() |
| 715 | } |
| 716 | } |
| 717 | |
| 718 | impl Deref for ServerConnection { |
| 719 | type Target = ConnectionCommon<ServerConnectionData>; |
| 720 | |
| 721 | fn deref(&self) -> &Self::Target { |
| 722 | &self.inner |
| 723 | } |
| 724 | } |
| 725 | |
| 726 | impl DerefMut for ServerConnection { |
| 727 | fn deref_mut(&mut self) -> &mut Self::Target { |
| 728 | &mut self.inner |
| 729 | } |
| 730 | } |
| 731 | |
| 732 | impl From<ServerConnection> for crate::Connection { |
| 733 | fn from(conn: ServerConnection) -> Self { |
| 734 | Self::Server(conn) |
| 735 | } |
| 736 | } |
| 737 | |
| 738 | /// Handle a server-side connection before configuration is available. |
| 739 | /// |
| 740 | /// `Acceptor` allows the caller to choose a [`ServerConfig`] after reading |
| 741 | /// the [`super::ClientHello`] of an incoming connection. This is useful for servers |
| 742 | /// that choose different certificates or cipher suites based on the |
| 743 | /// characteristics of the `ClientHello`. In particular it is useful for |
| 744 | /// servers that need to do some I/O to load a certificate and its private key |
| 745 | /// and don't want to use the blocking interface provided by |
| 746 | /// [`super::ResolvesServerCert`]. |
| 747 | /// |
| 748 | /// Create an Acceptor with [`Acceptor::default()`]. |
| 749 | /// |
| 750 | /// # Example |
| 751 | /// |
| 752 | /// ```no_run |
| 753 | /// # #[cfg (feature = "aws_lc_rs" )] { |
| 754 | /// # fn choose_server_config( |
| 755 | /// # _: rustls::server::ClientHello, |
| 756 | /// # ) -> std::sync::Arc<rustls::ServerConfig> { |
| 757 | /// # unimplemented!(); |
| 758 | /// # } |
| 759 | /// # #[allow (unused_variables)] |
| 760 | /// # fn main() { |
| 761 | /// use rustls::server::{Acceptor, ServerConfig}; |
| 762 | /// let listener = std::net::TcpListener::bind("127.0.0.1:0" ).unwrap(); |
| 763 | /// for stream in listener.incoming() { |
| 764 | /// let mut stream = stream.unwrap(); |
| 765 | /// let mut acceptor = Acceptor::default(); |
| 766 | /// let accepted = loop { |
| 767 | /// acceptor.read_tls(&mut stream).unwrap(); |
| 768 | /// if let Some(accepted) = acceptor.accept().unwrap() { |
| 769 | /// break accepted; |
| 770 | /// } |
| 771 | /// }; |
| 772 | /// |
| 773 | /// // For some user-defined choose_server_config: |
| 774 | /// let config = choose_server_config(accepted.client_hello()); |
| 775 | /// let conn = accepted |
| 776 | /// .into_connection(config) |
| 777 | /// .unwrap(); |
| 778 | /// |
| 779 | /// // Proceed with handling the ServerConnection. |
| 780 | /// } |
| 781 | /// # } |
| 782 | /// # } |
| 783 | /// ``` |
| 784 | pub struct Acceptor { |
| 785 | inner: Option<ConnectionCommon<ServerConnectionData>>, |
| 786 | } |
| 787 | |
| 788 | impl Default for Acceptor { |
| 789 | /// Return an empty Acceptor, ready to receive bytes from a new client connection. |
| 790 | fn default() -> Self { |
| 791 | Self { |
| 792 | inner: Some( |
| 793 | ConnectionCore::new( |
| 794 | Box::new(Accepting), |
| 795 | ServerConnectionData::default(), |
| 796 | CommonState::new(Side::Server), |
| 797 | ) |
| 798 | .into(), |
| 799 | ), |
| 800 | } |
| 801 | } |
| 802 | } |
| 803 | |
| 804 | impl Acceptor { |
| 805 | /// Read TLS content from `rd`. |
| 806 | /// |
| 807 | /// Returns an error if this `Acceptor` has already yielded an [`Accepted`]. For more details, |
| 808 | /// refer to [`Connection::read_tls()`]. |
| 809 | /// |
| 810 | /// [`Connection::read_tls()`]: crate::Connection::read_tls |
| 811 | pub fn read_tls(&mut self, rd: &mut dyn io::Read) -> Result<usize, io::Error> { |
| 812 | match &mut self.inner { |
| 813 | Some(conn) => conn.read_tls(rd), |
| 814 | None => Err(io::Error::new( |
| 815 | io::ErrorKind::Other, |
| 816 | "acceptor cannot read after successful acceptance" , |
| 817 | )), |
| 818 | } |
| 819 | } |
| 820 | |
| 821 | /// Check if a `ClientHello` message has been received. |
| 822 | /// |
| 823 | /// Returns `Ok(None)` if the complete `ClientHello` has not yet been received. |
| 824 | /// Do more I/O and then call this function again. |
| 825 | /// |
| 826 | /// Returns `Ok(Some(accepted))` if the connection has been accepted. Call |
| 827 | /// `accepted.into_connection()` to continue. Do not call this function again. |
| 828 | /// |
| 829 | /// Returns `Err((err, alert))` if an error occurred. If an alert is returned, the |
| 830 | /// application should call `alert.write()` to send the alert to the client. It should |
| 831 | /// not call `accept()` again. |
| 832 | pub fn accept(&mut self) -> Result<Option<Accepted>, (Error, AcceptedAlert)> { |
| 833 | let Some(mut connection) = self.inner.take() else { |
| 834 | return Err(( |
| 835 | Error::General("Acceptor polled after completion" .into()), |
| 836 | AcceptedAlert::empty(), |
| 837 | )); |
| 838 | }; |
| 839 | |
| 840 | let message = match connection.first_handshake_message() { |
| 841 | Ok(Some(msg)) => msg, |
| 842 | Ok(None) => { |
| 843 | self.inner = Some(connection); |
| 844 | return Ok(None); |
| 845 | } |
| 846 | Err(err) => return Err((err, AcceptedAlert::from(connection))), |
| 847 | }; |
| 848 | |
| 849 | let mut cx = Context::from(&mut connection); |
| 850 | let sig_schemes = match hs::process_client_hello(&message, false, &mut cx) { |
| 851 | Ok((_, sig_schemes)) => sig_schemes, |
| 852 | Err(err) => { |
| 853 | return Err((err, AcceptedAlert::from(connection))); |
| 854 | } |
| 855 | }; |
| 856 | |
| 857 | Ok(Some(Accepted { |
| 858 | connection, |
| 859 | message, |
| 860 | sig_schemes, |
| 861 | })) |
| 862 | } |
| 863 | } |
| 864 | |
| 865 | /// Represents a TLS alert resulting from handling the client's `ClientHello` message. |
| 866 | /// |
| 867 | /// When [`Acceptor::accept()`] returns an error, it yields an `AcceptedAlert` such that the |
| 868 | /// application can communicate failure to the client via [`AcceptedAlert::write()`]. |
| 869 | pub struct AcceptedAlert(ChunkVecBuffer); |
| 870 | |
| 871 | impl AcceptedAlert { |
| 872 | pub(super) fn empty() -> Self { |
| 873 | Self(ChunkVecBuffer::new(None)) |
| 874 | } |
| 875 | |
| 876 | /// Send the alert to the client. |
| 877 | /// |
| 878 | /// To account for short writes this function should be called repeatedly until it |
| 879 | /// returns `Ok(0)` or an error. |
| 880 | pub fn write(&mut self, wr: &mut dyn io::Write) -> Result<usize, io::Error> { |
| 881 | self.0.write_to(wr) |
| 882 | } |
| 883 | |
| 884 | /// Send the alert to the client. |
| 885 | /// |
| 886 | /// This function will invoke the writer until the buffer is empty. |
| 887 | pub fn write_all(&mut self, wr: &mut dyn io::Write) -> Result<(), io::Error> { |
| 888 | while self.write(wr)? != 0 {} |
| 889 | Ok(()) |
| 890 | } |
| 891 | } |
| 892 | |
| 893 | impl From<ConnectionCommon<ServerConnectionData>> for AcceptedAlert { |
| 894 | fn from(conn: ConnectionCommon<ServerConnectionData>) -> Self { |
| 895 | Self(conn.core.common_state.sendable_tls) |
| 896 | } |
| 897 | } |
| 898 | |
| 899 | impl Debug for AcceptedAlert { |
| 900 | fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { |
| 901 | f.debug_struct("AcceptedAlert" ).finish() |
| 902 | } |
| 903 | } |
| 904 | } |
| 905 | |
| 906 | #[cfg (feature = "std" )] |
| 907 | pub use connection::{AcceptedAlert, Acceptor, ReadEarlyData, ServerConnection}; |
| 908 | |
| 909 | /// Unbuffered version of `ServerConnection` |
| 910 | /// |
| 911 | /// See the [`crate::unbuffered`] module docs for more details |
| 912 | pub struct UnbufferedServerConnection { |
| 913 | inner: UnbufferedConnectionCommon<ServerConnectionData>, |
| 914 | } |
| 915 | |
| 916 | impl UnbufferedServerConnection { |
| 917 | /// Make a new ServerConnection. `config` controls how we behave in the TLS protocol. |
| 918 | pub fn new(config: Arc<ServerConfig>) -> Result<Self, Error> { |
| 919 | Ok(Self { |
| 920 | inner: UnbufferedConnectionCommon::from(ConnectionCore::for_server( |
| 921 | config, |
| 922 | extra_exts:Vec::new(), |
| 923 | )?), |
| 924 | }) |
| 925 | } |
| 926 | |
| 927 | /// Extract secrets, so they can be used when configuring kTLS, for example. |
| 928 | /// Should be used with care as it exposes secret key material. |
| 929 | pub fn dangerous_extract_secrets(self) -> Result<ExtractedSecrets, Error> { |
| 930 | self.inner.dangerous_extract_secrets() |
| 931 | } |
| 932 | } |
| 933 | |
| 934 | impl Deref for UnbufferedServerConnection { |
| 935 | type Target = UnbufferedConnectionCommon<ServerConnectionData>; |
| 936 | |
| 937 | fn deref(&self) -> &Self::Target { |
| 938 | &self.inner |
| 939 | } |
| 940 | } |
| 941 | |
| 942 | impl DerefMut for UnbufferedServerConnection { |
| 943 | fn deref_mut(&mut self) -> &mut Self::Target { |
| 944 | &mut self.inner |
| 945 | } |
| 946 | } |
| 947 | |
| 948 | impl UnbufferedConnectionCommon<ServerConnectionData> { |
| 949 | pub(crate) fn pop_early_data(&mut self) -> Option<Vec<u8>> { |
| 950 | self.core.data.early_data.pop() |
| 951 | } |
| 952 | |
| 953 | pub(crate) fn peek_early_data(&self) -> Option<&[u8]> { |
| 954 | self.core.data.early_data.peek() |
| 955 | } |
| 956 | } |
| 957 | |
| 958 | /// Represents a `ClientHello` message received through the [`Acceptor`]. |
| 959 | /// |
| 960 | /// Contains the state required to resume the connection through [`Accepted::into_connection()`]. |
| 961 | pub struct Accepted { |
| 962 | connection: ConnectionCommon<ServerConnectionData>, |
| 963 | message: Message<'static>, |
| 964 | sig_schemes: Vec<SignatureScheme>, |
| 965 | } |
| 966 | |
| 967 | impl Accepted { |
| 968 | /// Get the [`ClientHello`] for this connection. |
| 969 | pub fn client_hello(&self) -> ClientHello<'_> { |
| 970 | let payload = Self::client_hello_payload(&self.message); |
| 971 | let ch = ClientHello { |
| 972 | server_name: &self.connection.core.data.sni, |
| 973 | signature_schemes: &self.sig_schemes, |
| 974 | alpn: payload.alpn_extension(), |
| 975 | server_cert_types: payload.server_certificate_extension(), |
| 976 | client_cert_types: payload.client_certificate_extension(), |
| 977 | cipher_suites: &payload.cipher_suites, |
| 978 | certificate_authorities: payload.certificate_authorities_extension(), |
| 979 | }; |
| 980 | |
| 981 | trace!("Accepted::client_hello(): {ch:#?}" ); |
| 982 | ch |
| 983 | } |
| 984 | |
| 985 | /// Convert the [`Accepted`] into a [`ServerConnection`]. |
| 986 | /// |
| 987 | /// Takes the state returned from [`Acceptor::accept()`] as well as the [`ServerConfig`] and |
| 988 | /// [`sign::CertifiedKey`] that should be used for the session. Returns an error if |
| 989 | /// configuration-dependent validation of the received `ClientHello` message fails. |
| 990 | #[cfg (feature = "std" )] |
| 991 | pub fn into_connection( |
| 992 | mut self, |
| 993 | config: Arc<ServerConfig>, |
| 994 | ) -> Result<ServerConnection, (Error, AcceptedAlert)> { |
| 995 | if let Err(err) = self |
| 996 | .connection |
| 997 | .set_max_fragment_size(config.max_fragment_size) |
| 998 | { |
| 999 | // We have a connection here, but it won't contain an alert since the error |
| 1000 | // is with the fragment size configured in the `ServerConfig`. |
| 1001 | return Err((err, AcceptedAlert::empty())); |
| 1002 | } |
| 1003 | |
| 1004 | self.connection.enable_secret_extraction = config.enable_secret_extraction; |
| 1005 | |
| 1006 | let state = hs::ExpectClientHello::new(config, Vec::new()); |
| 1007 | let mut cx = hs::ServerContext::from(&mut self.connection); |
| 1008 | |
| 1009 | let ch = Self::client_hello_payload(&self.message); |
| 1010 | let new = match state.with_certified_key(self.sig_schemes, ch, &self.message, &mut cx) { |
| 1011 | Ok(new) => new, |
| 1012 | Err(err) => return Err((err, AcceptedAlert::from(self.connection))), |
| 1013 | }; |
| 1014 | |
| 1015 | self.connection.replace_state(new); |
| 1016 | Ok(ServerConnection { |
| 1017 | inner: self.connection, |
| 1018 | }) |
| 1019 | } |
| 1020 | |
| 1021 | fn client_hello_payload<'a>(message: &'a Message<'_>) -> &'a ClientHelloPayload { |
| 1022 | match &message.payload { |
| 1023 | crate::msgs::message::MessagePayload::Handshake { parsed, .. } => match &parsed.payload |
| 1024 | { |
| 1025 | crate::msgs::handshake::HandshakePayload::ClientHello(ch) => ch, |
| 1026 | _ => unreachable!(), |
| 1027 | }, |
| 1028 | _ => unreachable!(), |
| 1029 | } |
| 1030 | } |
| 1031 | } |
| 1032 | |
| 1033 | impl Debug for Accepted { |
| 1034 | fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { |
| 1035 | f.debug_struct(name:"Accepted" ).finish() |
| 1036 | } |
| 1037 | } |
| 1038 | |
| 1039 | #[cfg (feature = "std" )] |
| 1040 | struct Accepting; |
| 1041 | |
| 1042 | #[cfg (feature = "std" )] |
| 1043 | impl State<ServerConnectionData> for Accepting { |
| 1044 | fn handle<'m>( |
| 1045 | self: Box<Self>, |
| 1046 | _cx: &mut hs::ServerContext<'_>, |
| 1047 | _m: Message<'m>, |
| 1048 | ) -> Result<Box<dyn State<ServerConnectionData> + 'm>, Error> |
| 1049 | where |
| 1050 | Self: 'm, |
| 1051 | { |
| 1052 | Err(Error::General("unreachable state" .into())) |
| 1053 | } |
| 1054 | |
| 1055 | fn into_owned(self: Box<Self>) -> hs::NextState<'static> { |
| 1056 | self |
| 1057 | } |
| 1058 | } |
| 1059 | |
| 1060 | pub(super) enum EarlyDataState { |
| 1061 | New, |
| 1062 | Accepted { |
| 1063 | received: ChunkVecBuffer, |
| 1064 | left: usize, |
| 1065 | }, |
| 1066 | Rejected, |
| 1067 | } |
| 1068 | |
| 1069 | impl Default for EarlyDataState { |
| 1070 | fn default() -> Self { |
| 1071 | Self::New |
| 1072 | } |
| 1073 | } |
| 1074 | |
| 1075 | impl EarlyDataState { |
| 1076 | pub(super) fn reject(&mut self) { |
| 1077 | *self = Self::Rejected; |
| 1078 | } |
| 1079 | |
| 1080 | pub(super) fn accept(&mut self, max_size: usize) { |
| 1081 | *self = Self::Accepted { |
| 1082 | received: ChunkVecBuffer::new(Some(max_size)), |
| 1083 | left: max_size, |
| 1084 | }; |
| 1085 | } |
| 1086 | |
| 1087 | #[cfg (feature = "std" )] |
| 1088 | fn was_accepted(&self) -> bool { |
| 1089 | matches!(self, Self::Accepted { .. }) |
| 1090 | } |
| 1091 | |
| 1092 | pub(super) fn was_rejected(&self) -> bool { |
| 1093 | matches!(self, Self::Rejected) |
| 1094 | } |
| 1095 | |
| 1096 | fn peek(&self) -> Option<&[u8]> { |
| 1097 | match self { |
| 1098 | Self::Accepted { received, .. } => received.peek(), |
| 1099 | _ => None, |
| 1100 | } |
| 1101 | } |
| 1102 | |
| 1103 | fn pop(&mut self) -> Option<Vec<u8>> { |
| 1104 | match self { |
| 1105 | Self::Accepted { received, .. } => received.pop(), |
| 1106 | _ => None, |
| 1107 | } |
| 1108 | } |
| 1109 | |
| 1110 | #[cfg (feature = "std" )] |
| 1111 | fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { |
| 1112 | match self { |
| 1113 | Self::Accepted { received, .. } => received.read(buf), |
| 1114 | _ => Err(io::Error::from(io::ErrorKind::BrokenPipe)), |
| 1115 | } |
| 1116 | } |
| 1117 | |
| 1118 | #[cfg (read_buf)] |
| 1119 | fn read_buf(&mut self, cursor: core::io::BorrowedCursor<'_>) -> io::Result<()> { |
| 1120 | match self { |
| 1121 | Self::Accepted { received, .. } => received.read_buf(cursor), |
| 1122 | _ => Err(io::Error::from(io::ErrorKind::BrokenPipe)), |
| 1123 | } |
| 1124 | } |
| 1125 | |
| 1126 | pub(super) fn take_received_plaintext(&mut self, bytes: Payload<'_>) -> bool { |
| 1127 | let available = bytes.bytes().len(); |
| 1128 | let Self::Accepted { received, left } = self else { |
| 1129 | return false; |
| 1130 | }; |
| 1131 | |
| 1132 | if received.apply_limit(available) != available || available > *left { |
| 1133 | return false; |
| 1134 | } |
| 1135 | |
| 1136 | received.append(bytes.into_vec()); |
| 1137 | *left -= available; |
| 1138 | true |
| 1139 | } |
| 1140 | } |
| 1141 | |
| 1142 | impl Debug for EarlyDataState { |
| 1143 | fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { |
| 1144 | match self { |
| 1145 | Self::New => write!(f, "EarlyDataState::New" ), |
| 1146 | Self::Accepted { received: &ChunkVecBuffer, left: &usize } => write!( |
| 1147 | f, |
| 1148 | "EarlyDataState::Accepted {{ received: {}, left: {} }}" , |
| 1149 | received.len(), |
| 1150 | left |
| 1151 | ), |
| 1152 | Self::Rejected => write!(f, "EarlyDataState::Rejected" ), |
| 1153 | } |
| 1154 | } |
| 1155 | } |
| 1156 | |
| 1157 | impl ConnectionCore<ServerConnectionData> { |
| 1158 | pub(crate) fn for_server( |
| 1159 | config: Arc<ServerConfig>, |
| 1160 | extra_exts: Vec<ServerExtension>, |
| 1161 | ) -> Result<Self, Error> { |
| 1162 | let mut common = CommonState::new(Side::Server); |
| 1163 | common.set_max_fragment_size(config.max_fragment_size)?; |
| 1164 | common.enable_secret_extraction = config.enable_secret_extraction; |
| 1165 | common.fips = config.fips(); |
| 1166 | Ok(Self::new( |
| 1167 | Box::new(hs::ExpectClientHello::new(config, extra_exts)), |
| 1168 | ServerConnectionData::default(), |
| 1169 | common, |
| 1170 | )) |
| 1171 | } |
| 1172 | |
| 1173 | #[cfg (feature = "std" )] |
| 1174 | pub(crate) fn reject_early_data(&mut self) { |
| 1175 | assert!( |
| 1176 | self.common_state.is_handshaking(), |
| 1177 | "cannot retroactively reject early data" |
| 1178 | ); |
| 1179 | self.data.early_data.reject(); |
| 1180 | } |
| 1181 | |
| 1182 | #[cfg (feature = "std" )] |
| 1183 | pub(crate) fn get_sni_str(&self) -> Option<&str> { |
| 1184 | self.data.get_sni_str() |
| 1185 | } |
| 1186 | } |
| 1187 | |
| 1188 | /// State associated with a server connection. |
| 1189 | #[derive (Default, Debug)] |
| 1190 | pub struct ServerConnectionData { |
| 1191 | pub(super) sni: Option<DnsName<'static>>, |
| 1192 | pub(super) received_resumption_data: Option<Vec<u8>>, |
| 1193 | pub(super) resumption_data: Vec<u8>, |
| 1194 | pub(super) early_data: EarlyDataState, |
| 1195 | } |
| 1196 | |
| 1197 | impl ServerConnectionData { |
| 1198 | #[cfg (feature = "std" )] |
| 1199 | pub(super) fn get_sni_str(&self) -> Option<&str> { |
| 1200 | self.sni.as_ref().map(AsRef::as_ref) |
| 1201 | } |
| 1202 | } |
| 1203 | |
| 1204 | impl crate::conn::SideData for ServerConnectionData {} |
| 1205 | |
| 1206 | #[cfg (feature = "std" )] |
| 1207 | #[cfg (test)] |
| 1208 | mod tests { |
| 1209 | use std::format; |
| 1210 | |
| 1211 | use super::*; |
| 1212 | |
| 1213 | // these branches not reachable externally, unless something else goes wrong. |
| 1214 | #[test ] |
| 1215 | fn test_read_in_new_state() { |
| 1216 | assert_eq!( |
| 1217 | format!("{:?}" , EarlyDataState::default().read(&mut [0u8; 5])), |
| 1218 | "Err(Kind(BrokenPipe))" |
| 1219 | ); |
| 1220 | } |
| 1221 | |
| 1222 | #[cfg (read_buf)] |
| 1223 | #[test ] |
| 1224 | fn test_read_buf_in_new_state() { |
| 1225 | use core::io::BorrowedBuf; |
| 1226 | |
| 1227 | let mut buf = [0u8; 5]; |
| 1228 | let mut buf: BorrowedBuf<'_> = buf.as_mut_slice().into(); |
| 1229 | assert_eq!( |
| 1230 | format!("{:?}" , EarlyDataState::default().read_buf(buf.unfilled())), |
| 1231 | "Err(Kind(BrokenPipe))" |
| 1232 | ); |
| 1233 | } |
| 1234 | } |
| 1235 | |