Skip to main content

rustls/client/
client_conn.rs

1use alloc::vec::Vec;
2use core::marker::PhantomData;
3use core::ops::{Deref, DerefMut};
4use core::{fmt, mem};
5
6use pki_types::{ServerName, UnixTime};
7
8use super::handy::NoClientSessionStorage;
9use super::hs::{self, ClientHelloInput};
10#[cfg(feature = "std")]
11use crate::WantsVerifier;
12use crate::builder::ConfigBuilder;
13use crate::client::{EchMode, EchStatus};
14use crate::common_state::{CommonState, Protocol, Side};
15use crate::conn::{ConnectionCore, UnbufferedConnectionCommon};
16use crate::crypto::{CryptoProvider, SupportedKxGroup};
17use crate::enums::{CipherSuite, ProtocolVersion, SignatureScheme};
18use crate::error::Error;
19use crate::kernel::KernelConnection;
20use crate::log::trace;
21use crate::msgs::enums::NamedGroup;
22use crate::msgs::handshake::ClientExtensionsInput;
23use crate::msgs::persist;
24use crate::suites::{ExtractedSecrets, SupportedCipherSuite};
25use crate::sync::Arc;
26#[cfg(feature = "std")]
27use crate::time_provider::DefaultTimeProvider;
28use crate::time_provider::TimeProvider;
29use crate::unbuffered::{EncryptError, TransmitTlsData};
30#[cfg(doc)]
31use crate::{DistinguishedName, crypto};
32use crate::{KeyLog, WantsVersions, compress, sign, verify, versions};
33
34/// A trait for the ability to store client session data, so that sessions
35/// can be resumed in future connections.
36///
37/// Generally all data in this interface should be treated as
38/// **highly sensitive**, containing enough key material to break all security
39/// of the corresponding session.
40///
41/// `set_`, `insert_`, `remove_` and `take_` operations are mutating; this isn't
42/// expressed in the type system to allow implementations freedom in
43/// how to achieve interior mutability.  `Mutex` is a common choice.
44pub trait ClientSessionStore: fmt::Debug + Send + Sync {
45    /// Remember what `NamedGroup` the given server chose.
46    fn set_kx_hint(&self, server_name: ServerName<'static>, group: NamedGroup);
47
48    /// This should return the value most recently passed to `set_kx_hint`
49    /// for the given `server_name`.
50    ///
51    /// If `None` is returned, the caller chooses the first configured group,
52    /// and an extra round trip might happen if that choice is unsatisfactory
53    /// to the server.
54    fn kx_hint(&self, server_name: &ServerName<'_>) -> Option<NamedGroup>;
55
56    /// Remember a TLS1.2 session.
57    ///
58    /// At most one of these can be remembered at a time, per `server_name`.
59    fn set_tls12_session(
60        &self,
61        server_name: ServerName<'static>,
62        value: persist::Tls12ClientSessionValue,
63    );
64
65    /// Get the most recently saved TLS1.2 session for `server_name` provided to `set_tls12_session`.
66    fn tls12_session(
67        &self,
68        server_name: &ServerName<'_>,
69    ) -> Option<persist::Tls12ClientSessionValue>;
70
71    /// Remove and forget any saved TLS1.2 session for `server_name`.
72    fn remove_tls12_session(&self, server_name: &ServerName<'static>);
73
74    /// Remember a TLS1.3 ticket that might be retrieved later from `take_tls13_ticket`, allowing
75    /// resumption of this session.
76    ///
77    /// This can be called multiple times for a given session, allowing multiple independent tickets
78    /// to be valid at once.  The number of times this is called is controlled by the server, so
79    /// implementations of this trait should apply a reasonable bound of how many items are stored
80    /// simultaneously.
81    fn insert_tls13_ticket(
82        &self,
83        server_name: ServerName<'static>,
84        value: persist::Tls13ClientSessionValue,
85    );
86
87    /// Return a TLS1.3 ticket previously provided to `add_tls13_ticket`.
88    ///
89    /// Implementations of this trait must return each value provided to `add_tls13_ticket` _at most once_.
90    fn take_tls13_ticket(
91        &self,
92        server_name: &ServerName<'static>,
93    ) -> Option<persist::Tls13ClientSessionValue>;
94}
95
96/// A trait for the ability to choose a certificate chain and
97/// private key for the purposes of client authentication.
98pub trait ResolvesClientCert: fmt::Debug + Send + Sync {
99    /// Resolve a client certificate chain/private key to use as the client's
100    /// identity.
101    ///
102    /// `root_hint_subjects` is an optional list of certificate authority
103    /// subject distinguished names that the client can use to help
104    /// decide on a client certificate the server is likely to accept. If
105    /// the list is empty, the client should send whatever certificate it
106    /// has. The hints are expected to be DER-encoded X.500 distinguished names,
107    /// per [RFC 5280 A.1]. See [`DistinguishedName`] for more information
108    /// on decoding with external crates like `x509-parser`.
109    ///
110    /// `sigschemes` is the list of the [`SignatureScheme`]s the server
111    /// supports.
112    ///
113    /// Return `None` to continue the handshake without any client
114    /// authentication.  The server may reject the handshake later
115    /// if it requires authentication.
116    ///
117    /// [RFC 5280 A.1]: https://www.rfc-editor.org/rfc/rfc5280#appendix-A.1
118    fn resolve(
119        &self,
120        root_hint_subjects: &[&[u8]],
121        sigschemes: &[SignatureScheme],
122    ) -> Option<Arc<sign::CertifiedKey>>;
123
124    /// Return true if the client only supports raw public keys.
125    ///
126    /// See [RFC 7250](https://www.rfc-editor.org/rfc/rfc7250).
127    fn only_raw_public_keys(&self) -> bool {
128        false
129    }
130
131    /// Return true if any certificates at all are available.
132    fn has_certs(&self) -> bool;
133}
134
135/// Common configuration for (typically) all connections made by a program.
136///
137/// Making one of these is cheap, though one of the inputs may be expensive: gathering trust roots
138/// from the operating system to add to the [`RootCertStore`] passed to `with_root_certificates()`
139/// (the rustls-native-certs crate is often used for this) may take on the order of a few hundred
140/// milliseconds.
141///
142/// These must be created via the [`ClientConfig::builder()`] or [`ClientConfig::builder_with_provider()`]
143/// function.
144///
145/// Note that using [`ConfigBuilder<ClientConfig, WantsVersions>::with_ech()`] will produce a common
146/// configuration specific to the provided [`crate::client::EchConfig`] that may not be appropriate
147/// for all connections made by the program. In this case the configuration should only be shared
148/// by connections intended for domains that offer the provided [`crate::client::EchConfig`] in
149/// their DNS zone.
150///
151/// # Defaults
152///
153/// * [`ClientConfig::max_fragment_size`]: the default is `None` (meaning 16kB).
154/// * [`ClientConfig::resumption`]: supports resumption with up to 256 server names, using session
155///   ids or tickets, with a max of eight tickets per server.
156/// * [`ClientConfig::alpn_protocols`]: the default is empty -- no ALPN protocol is negotiated.
157/// * [`ClientConfig::key_log`]: key material is not logged.
158/// * [`ClientConfig::cert_decompressors`]: depends on the crate features, see [`compress::default_cert_decompressors()`].
159/// * [`ClientConfig::cert_compressors`]: depends on the crate features, see [`compress::default_cert_compressors()`].
160/// * [`ClientConfig::cert_compression_cache`]: caches the most recently used 4 compressions
161///
162/// [`RootCertStore`]: crate::RootCertStore
163#[derive(Clone, Debug)]
164pub struct ClientConfig {
165    /// Which ALPN protocols we include in our client hello.
166    /// If empty, no ALPN extension is sent.
167    pub alpn_protocols: Vec<Vec<u8>>,
168
169    /// Whether to check the selected ALPN was offered.
170    ///
171    /// The default is true.
172    pub check_selected_alpn: bool,
173
174    /// How and when the client can resume a previous session.
175    ///
176    /// # Sharing `resumption` between `ClientConfig`s
177    /// In a program using many `ClientConfig`s it may improve resumption rates
178    /// (which has a significant impact on connection performance) if those
179    /// configs share a single `Resumption`.
180    ///
181    /// However, resumption is only allowed between two `ClientConfig`s if their
182    /// `client_auth_cert_resolver` (ie, potential client authentication credentials)
183    /// and `verifier` (ie, server certificate verification settings) are
184    /// the same (according to `Arc::ptr_eq`).
185    ///
186    /// To illustrate, imagine two `ClientConfig`s `A` and `B`.  `A` fully validates
187    /// the server certificate, `B` does not.  If `A` and `B` shared a resumption store,
188    /// it would be possible for a session originated by `B` to be inserted into the
189    /// store, and then resumed by `A`.  This would give a false impression to the user
190    /// of `A` that the server certificate is fully validated.
191    pub resumption: Resumption,
192
193    /// The maximum size of plaintext input to be emitted in a single TLS record.
194    /// A value of None is equivalent to the [TLS maximum] of 16 kB.
195    ///
196    /// rustls enforces an arbitrary minimum of 32 bytes for this field.
197    /// Out of range values are reported as errors from [ClientConnection::new].
198    ///
199    /// Setting this value to a little less than the TCP MSS may improve latency
200    /// for stream-y workloads.
201    ///
202    /// [TLS maximum]: https://datatracker.ietf.org/doc/html/rfc8446#section-5.1
203    /// [ClientConnection::new]: crate::client::ClientConnection::new
204    pub max_fragment_size: Option<usize>,
205
206    /// How to decide what client auth certificate/keys to use.
207    pub client_auth_cert_resolver: Arc<dyn ResolvesClientCert>,
208
209    /// Whether to send the Server Name Indication (SNI) extension
210    /// during the client handshake.
211    ///
212    /// The default is true.
213    pub enable_sni: bool,
214
215    /// How to output key material for debugging.  The default
216    /// does nothing.
217    pub key_log: Arc<dyn KeyLog>,
218
219    /// Allows traffic secrets to be extracted after the handshake,
220    /// e.g. for kTLS setup.
221    pub enable_secret_extraction: bool,
222
223    /// Whether to send data on the first flight ("early data") in
224    /// TLS 1.3 handshakes.
225    ///
226    /// The default is false.
227    pub enable_early_data: bool,
228
229    /// If set to `true`, requires the server to support the extended
230    /// master secret extraction method defined in [RFC 7627].
231    ///
232    /// The default is `true` if the configured [`CryptoProvider`] is
233    /// FIPS-compliant (i.e., [`CryptoProvider::fips()`] returns `true`),
234    /// `false` otherwise.
235    ///
236    /// It must be set to `true` to meet FIPS requirement mentioned in section
237    /// **D.Q Transition of the TLS 1.2 KDF to Support the Extended Master
238    /// Secret** from [FIPS 140-3 IG.pdf].
239    ///
240    /// [RFC 7627]: https://datatracker.ietf.org/doc/html/rfc7627
241    /// [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
242    #[cfg(feature = "tls12")]
243    pub require_ems: bool,
244
245    /// Provides the current system time
246    pub time_provider: Arc<dyn TimeProvider>,
247
248    /// Source of randomness and other crypto.
249    pub(super) provider: Arc<CryptoProvider>,
250
251    /// Supported versions, in no particular order.  The default
252    /// is all supported versions.
253    pub(super) versions: versions::EnabledVersions,
254
255    /// How to verify the server certificate chain.
256    pub(super) verifier: Arc<dyn verify::ServerCertVerifier>,
257
258    /// How to decompress the server's certificate chain.
259    ///
260    /// If this is non-empty, the [RFC8779] certificate compression
261    /// extension is offered, and any compressed certificates are
262    /// transparently decompressed during the handshake.
263    ///
264    /// This only applies to TLS1.3 connections.  It is ignored for
265    /// TLS1.2 connections.
266    ///
267    /// [RFC8779]: https://datatracker.ietf.org/doc/rfc8879/
268    pub cert_decompressors: Vec<&'static dyn compress::CertDecompressor>,
269
270    /// How to compress the client's certificate chain.
271    ///
272    /// If a server supports this extension, and advertises support
273    /// for one of the compression algorithms included here, the
274    /// client certificate will be compressed according to [RFC8779].
275    ///
276    /// This only applies to TLS1.3 connections.  It is ignored for
277    /// TLS1.2 connections.
278    ///
279    /// [RFC8779]: https://datatracker.ietf.org/doc/rfc8879/
280    pub cert_compressors: Vec<&'static dyn compress::CertCompressor>,
281
282    /// Caching for compressed certificates.
283    ///
284    /// This is optional: [`compress::CompressionCache::Disabled`] gives
285    /// a cache that does no caching.
286    pub cert_compression_cache: Arc<compress::CompressionCache>,
287
288    /// How to offer Encrypted Client Hello (ECH). The default is to not offer ECH.
289    pub(super) ech_mode: Option<EchMode>,
290
291    /// Request a specific number of TLS 1.3 session tickets via [RFC 9149].
292    ///
293    /// Set to `None` to disable sending the extension (the default).
294    ///
295    /// [RFC 9149]: https://datatracker.ietf.org/doc/html/rfc9149
296    pub send_ticket_request: Option<TicketRequest>,
297}
298
299/// Desired session ticket counts for the RFC 9149 `ticket_request` extension.
300#[derive(Clone, Copy, Debug, PartialEq)]
301pub struct TicketRequest {
302    /// Tickets desired when the server negotiates a new connection.
303    pub new_session_count: u8,
304    /// Tickets desired when the server resumes using a presented ticket.
305    pub resumption_count: u8,
306}
307
308impl ClientConfig {
309    /// Create a builder for a client configuration with
310    /// [the process-default `CryptoProvider`][CryptoProvider#using-the-per-process-default-cryptoprovider]
311    /// and safe protocol version defaults.
312    ///
313    /// For more information, see the [`ConfigBuilder`] documentation.
314    #[cfg(feature = "std")]
315    pub fn builder() -> ConfigBuilder<Self, WantsVerifier> {
316        Self::builder_with_protocol_versions(versions::DEFAULT_VERSIONS)
317    }
318
319    /// Create a builder for a client configuration with
320    /// [the process-default `CryptoProvider`][CryptoProvider#using-the-per-process-default-cryptoprovider]
321    /// and the provided protocol versions.
322    ///
323    /// Panics if
324    /// - the supported versions are not compatible with the provider (eg.
325    ///   the combination of ciphersuites supported by the provider and supported
326    ///   versions lead to zero cipher suites being usable),
327    /// - if a `CryptoProvider` cannot be resolved using a combination of
328    ///   the crate features and process default.
329    ///
330    /// For more information, see the [`ConfigBuilder`] documentation.
331    #[cfg(feature = "std")]
332    pub fn builder_with_protocol_versions(
333        versions: &[&'static versions::SupportedProtocolVersion],
334    ) -> ConfigBuilder<Self, WantsVerifier> {
335        // Safety assumptions:
336        // 1. that the provider has been installed (explicitly or implicitly)
337        // 2. that the process-level default provider is usable with the supplied protocol versions.
338        Self::builder_with_provider(
339            CryptoProvider::get_default_or_install_from_crate_features().clone(),
340        )
341        .with_protocol_versions(versions)
342        .unwrap()
343    }
344
345    /// Create a builder for a client configuration with a specific [`CryptoProvider`].
346    ///
347    /// This will use the provider's configured ciphersuites. You must additionally choose
348    /// which protocol versions to enable, using `with_protocol_versions` or
349    /// `with_safe_default_protocol_versions` and handling the `Result` in case a protocol
350    /// version is not supported by the provider's ciphersuites.
351    ///
352    /// For more information, see the [`ConfigBuilder`] documentation.
353    #[cfg(feature = "std")]
354    pub fn builder_with_provider(
355        provider: Arc<CryptoProvider>,
356    ) -> ConfigBuilder<Self, WantsVersions> {
357        ConfigBuilder {
358            state: WantsVersions {},
359            provider,
360            time_provider: Arc::new(DefaultTimeProvider),
361            side: PhantomData,
362        }
363    }
364    /// Create a builder for a client configuration with no default implementation details.
365    ///
366    /// This API must be used by `no_std` users.
367    ///
368    /// You must provide a specific [`TimeProvider`].
369    ///
370    /// You must provide a specific [`CryptoProvider`].
371    ///
372    /// This will use the provider's configured ciphersuites. You must additionally choose
373    /// which protocol versions to enable, using `with_protocol_versions` or
374    /// `with_safe_default_protocol_versions` and handling the `Result` in case a protocol
375    /// version is not supported by the provider's ciphersuites.
376    ///
377    /// For more information, see the [`ConfigBuilder`] documentation.
378    pub fn builder_with_details(
379        provider: Arc<CryptoProvider>,
380        time_provider: Arc<dyn TimeProvider>,
381    ) -> ConfigBuilder<Self, WantsVersions> {
382        ConfigBuilder {
383            state: WantsVersions {},
384            provider,
385            time_provider,
386            side: PhantomData,
387        }
388    }
389
390    /// Return true if connections made with this `ClientConfig` will
391    /// operate in FIPS mode.
392    ///
393    /// This is different from [`CryptoProvider::fips()`]: [`CryptoProvider::fips()`]
394    /// is concerned only with cryptography, whereas this _also_ covers TLS-level
395    /// configuration that NIST recommends, as well as ECH HPKE suites if applicable.
396    pub fn fips(&self) -> bool {
397        let mut is_fips = self.provider.fips();
398
399        #[cfg(feature = "tls12")]
400        {
401            is_fips = is_fips && self.require_ems
402        }
403
404        if let Some(ech_mode) = &self.ech_mode {
405            is_fips = is_fips && ech_mode.fips();
406        }
407
408        is_fips
409    }
410
411    /// Return the crypto provider used to construct this client configuration.
412    pub fn crypto_provider(&self) -> &Arc<CryptoProvider> {
413        &self.provider
414    }
415
416    /// Access configuration options whose use is dangerous and requires
417    /// extra care.
418    pub fn dangerous(&mut self) -> danger::DangerousClientConfig<'_> {
419        danger::DangerousClientConfig { cfg: self }
420    }
421
422    pub(super) fn needs_key_share(&self) -> bool {
423        self.supports_version(ProtocolVersion::TLSv1_3, Protocol::Tcp)
424    }
425
426    /// We support a given TLS version if it's quoted in the configured
427    /// versions *and* at least one ciphersuite for this version is
428    /// also configured.
429    pub(crate) fn supports_version(&self, v: ProtocolVersion, protocol: Protocol) -> bool {
430        self.versions.contains(v)
431            && self
432                .provider
433                .cipher_suites
434                .iter()
435                .any(|cs| cs.version().version == v)
436            && protocol.supports_version(v)
437    }
438
439    #[cfg(feature = "std")]
440    pub(crate) fn supports_protocol(&self, proto: Protocol) -> bool {
441        self.provider
442            .cipher_suites
443            .iter()
444            .any(|cs| cs.usable_for_protocol(proto))
445    }
446
447    pub(super) fn find_cipher_suite(
448        &self,
449        suite: CipherSuite,
450        protocol: Protocol,
451    ) -> Option<SupportedCipherSuite> {
452        self.provider
453            .cipher_suites
454            .iter()
455            .copied()
456            .find(|&scs| scs.suite() == suite && scs.usable_for_protocol(protocol))
457    }
458
459    pub(super) fn find_kx_group(
460        &self,
461        group: NamedGroup,
462        version: ProtocolVersion,
463    ) -> Option<&'static dyn SupportedKxGroup> {
464        self.provider
465            .kx_groups
466            .iter()
467            .copied()
468            .find(|skxg| skxg.usable_for_version(version) && skxg.name() == group)
469    }
470
471    pub(super) fn current_time(&self) -> Result<UnixTime, Error> {
472        self.time_provider
473            .current_time()
474            .ok_or(Error::FailedToGetCurrentTime)
475    }
476}
477
478/// Configuration for how/when a client is allowed to resume a previous session.
479#[derive(Clone, Debug)]
480pub struct Resumption {
481    /// How we store session data or tickets. The default is to use an in-memory
482    /// [super::handy::ClientSessionMemoryCache].
483    pub(super) store: Arc<dyn ClientSessionStore>,
484
485    /// What mechanism is used for resuming a TLS 1.2 session.
486    pub(super) tls12_resumption: Tls12Resumption,
487}
488
489impl Resumption {
490    /// Create a new `Resumption` that stores data for the given number of sessions in memory.
491    ///
492    /// This is the default `Resumption` choice, and enables resuming a TLS 1.2 session with
493    /// a session id or RFC 5077 ticket.
494    #[cfg(feature = "std")]
495    pub fn in_memory_sessions(num: usize) -> Self {
496        Self {
497            store: Arc::new(super::handy::ClientSessionMemoryCache::new(num)),
498            tls12_resumption: Tls12Resumption::SessionIdOrTickets,
499        }
500    }
501
502    /// Use a custom [`ClientSessionStore`] implementation to store sessions.
503    ///
504    /// By default, enables resuming a TLS 1.2 session with a session id or RFC 5077 ticket.
505    pub fn store(store: Arc<dyn ClientSessionStore>) -> Self {
506        Self {
507            store,
508            tls12_resumption: Tls12Resumption::SessionIdOrTickets,
509        }
510    }
511
512    /// Disable all use of session resumption.
513    pub fn disabled() -> Self {
514        Self {
515            store: Arc::new(NoClientSessionStorage),
516            tls12_resumption: Tls12Resumption::Disabled,
517        }
518    }
519
520    /// Configure whether TLS 1.2 sessions may be resumed, and by what mechanism.
521    ///
522    /// This is meaningless if you've disabled resumption entirely, which is the case in `no-std`
523    /// contexts.
524    pub fn tls12_resumption(mut self, tls12: Tls12Resumption) -> Self {
525        self.tls12_resumption = tls12;
526        self
527    }
528}
529
530impl Default for Resumption {
531    /// Create an in-memory session store resumption with up to 256 server names, allowing
532    /// a TLS 1.2 session to resume with a session id or RFC 5077 ticket.
533    fn default() -> Self {
534        #[cfg(feature = "std")]
535        let ret = Self::in_memory_sessions(256);
536
537        #[cfg(not(feature = "std"))]
538        let ret = Self::disabled();
539
540        ret
541    }
542}
543
544/// What mechanisms to support for resuming a TLS 1.2 session.
545#[derive(Clone, Copy, Debug, PartialEq)]
546pub enum Tls12Resumption {
547    /// Disable 1.2 resumption.
548    Disabled,
549    /// Support 1.2 resumption using session ids only.
550    SessionIdOnly,
551    /// Support 1.2 resumption using session ids or RFC 5077 tickets.
552    ///
553    /// See[^1] for why you might like to disable RFC 5077 by instead choosing the `SessionIdOnly`
554    /// option. Note that TLS 1.3 tickets do not have those issues.
555    ///
556    /// [^1]: <https://words.filippo.io/we-need-to-talk-about-session-tickets/>
557    SessionIdOrTickets,
558}
559
560/// Container for unsafe APIs
561pub(super) mod danger {
562    use super::ClientConfig;
563    use super::verify::ServerCertVerifier;
564    use crate::sync::Arc;
565
566    /// Accessor for dangerous configuration options.
567    #[derive(Debug)]
568    pub struct DangerousClientConfig<'a> {
569        /// The underlying ClientConfig
570        pub cfg: &'a mut ClientConfig,
571    }
572
573    impl DangerousClientConfig<'_> {
574        /// Overrides the default `ServerCertVerifier` with something else.
575        pub fn set_certificate_verifier(&mut self, verifier: Arc<dyn ServerCertVerifier>) {
576            self.cfg.verifier = verifier;
577        }
578    }
579}
580
581#[derive(Debug, PartialEq)]
582enum EarlyDataState {
583    Disabled,
584    Ready,
585    Accepted,
586    AcceptedFinished,
587    Rejected,
588}
589
590#[derive(Debug)]
591pub(super) struct EarlyData {
592    state: EarlyDataState,
593    left: usize,
594}
595
596impl EarlyData {
597    fn new() -> Self {
598        Self {
599            left: 0,
600            state: EarlyDataState::Disabled,
601        }
602    }
603
604    pub(super) fn is_enabled(&self) -> bool {
605        matches!(self.state, EarlyDataState::Ready | EarlyDataState::Accepted)
606    }
607
608    #[cfg(feature = "std")]
609    fn is_accepted(&self) -> bool {
610        matches!(
611            self.state,
612            EarlyDataState::Accepted | EarlyDataState::AcceptedFinished
613        )
614    }
615
616    pub(super) fn enable(&mut self, max_data: usize) {
617        assert_eq!(self.state, EarlyDataState::Disabled);
618        self.state = EarlyDataState::Ready;
619        self.left = max_data;
620    }
621
622    pub(super) fn rejected(&mut self) {
623        trace!("EarlyData rejected");
624        self.state = EarlyDataState::Rejected;
625    }
626
627    pub(super) fn accepted(&mut self) {
628        trace!("EarlyData accepted");
629        assert_eq!(self.state, EarlyDataState::Ready);
630        self.state = EarlyDataState::Accepted;
631    }
632
633    pub(super) fn finished(&mut self) {
634        trace!("EarlyData finished");
635        self.state = match self.state {
636            EarlyDataState::Accepted => EarlyDataState::AcceptedFinished,
637            _ => panic!("bad EarlyData state"),
638        }
639    }
640
641    fn check_write_opt(&mut self, sz: usize) -> Option<usize> {
642        match self.state {
643            EarlyDataState::Disabled => unreachable!(),
644            EarlyDataState::Ready | EarlyDataState::Accepted => {
645                let take = if self.left < sz {
646                    mem::replace(&mut self.left, 0)
647                } else {
648                    self.left -= sz;
649                    sz
650                };
651
652                Some(take)
653            }
654            EarlyDataState::Rejected | EarlyDataState::AcceptedFinished => None,
655        }
656    }
657}
658
659#[cfg(feature = "std")]
660mod connection {
661    use alloc::vec::Vec;
662    use core::fmt;
663    use core::ops::{Deref, DerefMut};
664    use std::io;
665
666    use pki_types::ServerName;
667
668    use super::{ClientConnectionData, ClientExtensionsInput};
669    use crate::ClientConfig;
670    use crate::client::EchStatus;
671    use crate::common_state::Protocol;
672    use crate::conn::{ConnectionCommon, ConnectionCore};
673    use crate::error::Error;
674    use crate::suites::ExtractedSecrets;
675    use crate::sync::Arc;
676
677    /// Stub that implements io::Write and dispatches to `write_early_data`.
678    pub struct WriteEarlyData<'a> {
679        sess: &'a mut ClientConnection,
680    }
681
682    impl<'a> WriteEarlyData<'a> {
683        fn new(sess: &'a mut ClientConnection) -> Self {
684            WriteEarlyData { sess }
685        }
686
687        /// How many bytes you may send.  Writes will become short
688        /// once this reaches zero.
689        pub fn bytes_left(&self) -> usize {
690            self.sess
691                .inner
692                .core
693                .data
694                .early_data
695                .bytes_left()
696        }
697    }
698
699    impl io::Write for WriteEarlyData<'_> {
700        fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
701            self.sess.write_early_data(buf)
702        }
703
704        fn flush(&mut self) -> io::Result<()> {
705            Ok(())
706        }
707    }
708
709    impl super::EarlyData {
710        fn check_write(&mut self, sz: usize) -> io::Result<usize> {
711            self.check_write_opt(sz)
712                .ok_or_else(|| io::Error::from(io::ErrorKind::InvalidInput))
713        }
714
715        fn bytes_left(&self) -> usize {
716            self.left
717        }
718    }
719
720    /// This represents a single TLS client connection.
721    pub struct ClientConnection {
722        inner: ConnectionCommon<ClientConnectionData>,
723    }
724
725    impl fmt::Debug for ClientConnection {
726        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
727            f.debug_struct("ClientConnection")
728                .finish()
729        }
730    }
731
732    impl ClientConnection {
733        /// Make a new ClientConnection.  `config` controls how
734        /// we behave in the TLS protocol, `name` is the
735        /// name of the server we want to talk to.
736        pub fn new(config: Arc<ClientConfig>, name: ServerName<'static>) -> Result<Self, Error> {
737            Self::new_with_alpn(config.clone(), name, config.alpn_protocols.clone())
738        }
739
740        /// Make a new ClientConnection with custom ALPN protocols.
741        pub fn new_with_alpn(
742            config: Arc<ClientConfig>,
743            name: ServerName<'static>,
744            alpn_protocols: Vec<Vec<u8>>,
745        ) -> Result<Self, Error> {
746            Ok(Self {
747                inner: ConnectionCommon::from(ConnectionCore::for_client(
748                    config,
749                    name,
750                    ClientExtensionsInput::from_alpn(alpn_protocols),
751                    Protocol::Tcp,
752                )?),
753            })
754        }
755        /// Returns an `io::Write` implementer you can write bytes to
756        /// to send TLS1.3 early data (a.k.a. "0-RTT data") to the server.
757        ///
758        /// This returns None in many circumstances when the capability to
759        /// send early data is not available, including but not limited to:
760        ///
761        /// - The server hasn't been talked to previously.
762        /// - The server does not support resumption.
763        /// - The server does not support early data.
764        /// - The resumption data for the server has expired.
765        ///
766        /// The server specifies a maximum amount of early data.  You can
767        /// learn this limit through the returned object, and writes through
768        /// it will process only this many bytes.
769        ///
770        /// The server can choose not to accept any sent early data --
771        /// in this case the data is lost but the connection continues.  You
772        /// can tell this happened using `is_early_data_accepted`.
773        pub fn early_data(&mut self) -> Option<WriteEarlyData<'_>> {
774            if self
775                .inner
776                .core
777                .data
778                .early_data
779                .is_enabled()
780            {
781                Some(WriteEarlyData::new(self))
782            } else {
783                None
784            }
785        }
786
787        /// Returns True if the server signalled it will process early data.
788        ///
789        /// If you sent early data and this returns false at the end of the
790        /// handshake then the server will not process the data.  This
791        /// is not an error, but you may wish to resend the data.
792        pub fn is_early_data_accepted(&self) -> bool {
793            self.inner.core.is_early_data_accepted()
794        }
795
796        /// Extract secrets, so they can be used when configuring kTLS, for example.
797        /// Should be used with care as it exposes secret key material.
798        pub fn dangerous_extract_secrets(self) -> Result<ExtractedSecrets, Error> {
799            self.inner.dangerous_extract_secrets()
800        }
801
802        /// Return the connection's Encrypted Client Hello (ECH) status.
803        pub fn ech_status(&self) -> EchStatus {
804            self.inner.core.data.ech_status
805        }
806
807        /// Returns the number of TLS1.3 tickets that have been received.
808        pub fn tls13_tickets_received(&self) -> u32 {
809            self.inner.tls13_tickets_received
810        }
811
812        /// Return true if the connection was made with a `ClientConfig` that is FIPS compatible.
813        ///
814        /// This is different from [`crate::crypto::CryptoProvider::fips()`]:
815        /// it is concerned only with cryptography, whereas this _also_ covers TLS-level
816        /// configuration that NIST recommends, as well as ECH HPKE suites if applicable.
817        pub fn fips(&self) -> bool {
818            self.inner.core.common_state.fips
819        }
820
821        fn write_early_data(&mut self, data: &[u8]) -> io::Result<usize> {
822            self.inner
823                .core
824                .data
825                .early_data
826                .check_write(data.len())
827                .map(|sz| {
828                    self.inner
829                        .send_early_plaintext(&data[..sz])
830                })
831        }
832    }
833
834    impl Deref for ClientConnection {
835        type Target = ConnectionCommon<ClientConnectionData>;
836
837        fn deref(&self) -> &Self::Target {
838            &self.inner
839        }
840    }
841
842    impl DerefMut for ClientConnection {
843        fn deref_mut(&mut self) -> &mut Self::Target {
844            &mut self.inner
845        }
846    }
847
848    #[doc(hidden)]
849    impl<'a> TryFrom<&'a mut crate::Connection> for &'a mut ClientConnection {
850        type Error = ();
851
852        fn try_from(value: &'a mut crate::Connection) -> Result<Self, Self::Error> {
853            use crate::Connection::*;
854            match value {
855                Client(conn) => Ok(conn),
856                Server(_) => Err(()),
857            }
858        }
859    }
860
861    impl From<ClientConnection> for crate::Connection {
862        fn from(conn: ClientConnection) -> Self {
863            Self::Client(conn)
864        }
865    }
866}
867#[cfg(feature = "std")]
868pub use connection::{ClientConnection, WriteEarlyData};
869
870impl ConnectionCore<ClientConnectionData> {
871    pub(crate) fn for_client(
872        config: Arc<ClientConfig>,
873        name: ServerName<'static>,
874        extra_exts: ClientExtensionsInput<'static>,
875        proto: Protocol,
876    ) -> Result<Self, Error> {
877        let mut common_state = CommonState::new(Side::Client);
878        common_state.set_max_fragment_size(config.max_fragment_size)?;
879        common_state.protocol = proto;
880        common_state.enable_secret_extraction = config.enable_secret_extraction;
881        common_state.fips = config.fips();
882        let mut data = ClientConnectionData::new();
883
884        let mut cx = hs::ClientContext {
885            common: &mut common_state,
886            data: &mut data,
887            // `start_handshake` won't produce plaintext
888            sendable_plaintext: None,
889        };
890
891        let input = ClientHelloInput::new(name, &extra_exts, &mut cx, config)?;
892        let state = input.start_handshake(extra_exts, &mut cx)?;
893        Ok(Self::new(state, data, common_state))
894    }
895
896    #[cfg(feature = "std")]
897    pub(crate) fn is_early_data_accepted(&self) -> bool {
898        self.data.early_data.is_accepted()
899    }
900}
901
902/// Unbuffered version of `ClientConnection`
903///
904/// See the [`crate::unbuffered`] module docs for more details
905pub struct UnbufferedClientConnection {
906    inner: UnbufferedConnectionCommon<ClientConnectionData>,
907}
908
909impl UnbufferedClientConnection {
910    /// Make a new ClientConnection. `config` controls how we behave in the TLS protocol, `name` is
911    /// the name of the server we want to talk to.
912    pub fn new(config: Arc<ClientConfig>, name: ServerName<'static>) -> Result<Self, Error> {
913        Self::new_with_extensions(
914            config.clone(),
915            name,
916            ClientExtensionsInput::from_alpn(config.alpn_protocols.clone()),
917        )
918    }
919
920    /// Make a new UnbufferedClientConnection with custom ALPN protocols.
921    pub fn new_with_alpn(
922        config: Arc<ClientConfig>,
923        name: ServerName<'static>,
924        alpn_protocols: Vec<Vec<u8>>,
925    ) -> Result<Self, Error> {
926        Self::new_with_extensions(
927            config,
928            name,
929            ClientExtensionsInput::from_alpn(alpn_protocols),
930        )
931    }
932
933    fn new_with_extensions(
934        config: Arc<ClientConfig>,
935        name: ServerName<'static>,
936        extensions: ClientExtensionsInput<'static>,
937    ) -> Result<Self, Error> {
938        Ok(Self {
939            inner: UnbufferedConnectionCommon::from(ConnectionCore::for_client(
940                config,
941                name,
942                extensions,
943                Protocol::Tcp,
944            )?),
945        })
946    }
947
948    /// Extract secrets, so they can be used when configuring kTLS, for example.
949    /// Should be used with care as it exposes secret key material.
950    #[deprecated = "dangerous_extract_secrets() does not support session tickets or \
951                    key updates, use dangerous_into_kernel_connection() instead"]
952    pub fn dangerous_extract_secrets(self) -> Result<ExtractedSecrets, Error> {
953        self.inner.dangerous_extract_secrets()
954    }
955
956    /// Extract secrets and a [`KernelConnection`] object.
957    ///
958    /// This allows you use rustls to manage keys and then manage encryption and
959    /// decryption yourself (e.g. for kTLS).
960    ///
961    /// Should be used with care as it exposes secret key material.
962    ///
963    /// See the [`crate::kernel`] documentations for details on prerequisites
964    /// for calling this method.
965    pub fn dangerous_into_kernel_connection(
966        self,
967    ) -> Result<(ExtractedSecrets, KernelConnection<ClientConnectionData>), Error> {
968        self.inner
969            .core
970            .dangerous_into_kernel_connection()
971    }
972
973    /// Returns the number of TLS1.3 tickets that have been received.
974    pub fn tls13_tickets_received(&self) -> u32 {
975        self.inner.tls13_tickets_received
976    }
977}
978
979impl Deref for UnbufferedClientConnection {
980    type Target = UnbufferedConnectionCommon<ClientConnectionData>;
981
982    fn deref(&self) -> &Self::Target {
983        &self.inner
984    }
985}
986
987impl DerefMut for UnbufferedClientConnection {
988    fn deref_mut(&mut self) -> &mut Self::Target {
989        &mut self.inner
990    }
991}
992
993impl TransmitTlsData<'_, ClientConnectionData> {
994    /// returns an adapter that allows encrypting early (RTT-0) data before transmitting the
995    /// already encoded TLS data
996    ///
997    /// IF allowed by the protocol
998    pub fn may_encrypt_early_data(&mut self) -> Option<MayEncryptEarlyData<'_>> {
999        if self
1000            .conn
1001            .core
1002            .data
1003            .early_data
1004            .is_enabled()
1005        {
1006            Some(MayEncryptEarlyData { conn: self.conn })
1007        } else {
1008            None
1009        }
1010    }
1011}
1012
1013/// Allows encrypting early (RTT-0) data
1014pub struct MayEncryptEarlyData<'c> {
1015    conn: &'c mut UnbufferedConnectionCommon<ClientConnectionData>,
1016}
1017
1018impl MayEncryptEarlyData<'_> {
1019    /// Encrypts `application_data` into the `outgoing_tls` buffer
1020    ///
1021    /// returns the number of bytes that were written into `outgoing_tls`, or an error if
1022    /// the provided buffer was too small. In the error case, `outgoing_tls` is not modified
1023    pub fn encrypt(
1024        &mut self,
1025        early_data: &[u8],
1026        outgoing_tls: &mut [u8],
1027    ) -> Result<usize, EarlyDataError> {
1028        let Some(allowed) = self
1029            .conn
1030            .core
1031            .data
1032            .early_data
1033            .check_write_opt(early_data.len())
1034        else {
1035            return Err(EarlyDataError::ExceededAllowedEarlyData);
1036        };
1037
1038        self.conn
1039            .core
1040            .common_state
1041            .write_plaintext(early_data[..allowed].into(), outgoing_tls)
1042            .map_err(|e| e.into())
1043    }
1044}
1045
1046/// Errors that may arise when encrypting early (RTT-0) data
1047#[derive(Debug)]
1048pub enum EarlyDataError {
1049    /// Cannot encrypt more early data due to imposed limits
1050    ExceededAllowedEarlyData,
1051    /// Encryption error
1052    Encrypt(EncryptError),
1053}
1054
1055impl From<EncryptError> for EarlyDataError {
1056    fn from(v: EncryptError) -> Self {
1057        Self::Encrypt(v)
1058    }
1059}
1060
1061impl fmt::Display for EarlyDataError {
1062    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1063        match self {
1064            Self::ExceededAllowedEarlyData => f.write_str("cannot send any more early data"),
1065            Self::Encrypt(e) => fmt::Display::fmt(e, f),
1066        }
1067    }
1068}
1069
1070#[cfg(feature = "std")]
1071impl std::error::Error for EarlyDataError {}
1072
1073/// State associated with a client connection.
1074#[derive(Debug)]
1075pub struct ClientConnectionData {
1076    pub(super) early_data: EarlyData,
1077    pub(super) ech_status: EchStatus,
1078}
1079
1080impl ClientConnectionData {
1081    fn new() -> Self {
1082        Self {
1083            early_data: EarlyData::new(),
1084            ech_status: EchStatus::NotOffered,
1085        }
1086    }
1087}
1088
1089impl crate::conn::SideData for ClientConnectionData {}