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
292impl ClientConfig {
293    /// Create a builder for a client configuration with
294    /// [the process-default `CryptoProvider`][CryptoProvider#using-the-per-process-default-cryptoprovider]
295    /// and safe protocol version defaults.
296    ///
297    /// For more information, see the [`ConfigBuilder`] documentation.
298    #[cfg(feature = "std")]
299    pub fn builder() -> ConfigBuilder<Self, WantsVerifier> {
300        Self::builder_with_protocol_versions(versions::DEFAULT_VERSIONS)
301    }
302
303    /// Create a builder for a client configuration with
304    /// [the process-default `CryptoProvider`][CryptoProvider#using-the-per-process-default-cryptoprovider]
305    /// and the provided protocol versions.
306    ///
307    /// Panics if
308    /// - the supported versions are not compatible with the provider (eg.
309    ///   the combination of ciphersuites supported by the provider and supported
310    ///   versions lead to zero cipher suites being usable),
311    /// - if a `CryptoProvider` cannot be resolved using a combination of
312    ///   the crate features and process default.
313    ///
314    /// For more information, see the [`ConfigBuilder`] documentation.
315    #[cfg(feature = "std")]
316    pub fn builder_with_protocol_versions(
317        versions: &[&'static versions::SupportedProtocolVersion],
318    ) -> ConfigBuilder<Self, WantsVerifier> {
319        // Safety assumptions:
320        // 1. that the provider has been installed (explicitly or implicitly)
321        // 2. that the process-level default provider is usable with the supplied protocol versions.
322        Self::builder_with_provider(
323            CryptoProvider::get_default_or_install_from_crate_features().clone(),
324        )
325        .with_protocol_versions(versions)
326        .unwrap()
327    }
328
329    /// Create a builder for a client configuration with a specific [`CryptoProvider`].
330    ///
331    /// This will use the provider's configured ciphersuites. You must additionally choose
332    /// which protocol versions to enable, using `with_protocol_versions` or
333    /// `with_safe_default_protocol_versions` and handling the `Result` in case a protocol
334    /// version is not supported by the provider's ciphersuites.
335    ///
336    /// For more information, see the [`ConfigBuilder`] documentation.
337    #[cfg(feature = "std")]
338    pub fn builder_with_provider(
339        provider: Arc<CryptoProvider>,
340    ) -> ConfigBuilder<Self, WantsVersions> {
341        ConfigBuilder {
342            state: WantsVersions {},
343            provider,
344            time_provider: Arc::new(DefaultTimeProvider),
345            side: PhantomData,
346        }
347    }
348    /// Create a builder for a client configuration with no default implementation details.
349    ///
350    /// This API must be used by `no_std` users.
351    ///
352    /// You must provide a specific [`TimeProvider`].
353    ///
354    /// You must provide a specific [`CryptoProvider`].
355    ///
356    /// This will use the provider's configured ciphersuites. You must additionally choose
357    /// which protocol versions to enable, using `with_protocol_versions` or
358    /// `with_safe_default_protocol_versions` and handling the `Result` in case a protocol
359    /// version is not supported by the provider's ciphersuites.
360    ///
361    /// For more information, see the [`ConfigBuilder`] documentation.
362    pub fn builder_with_details(
363        provider: Arc<CryptoProvider>,
364        time_provider: Arc<dyn TimeProvider>,
365    ) -> ConfigBuilder<Self, WantsVersions> {
366        ConfigBuilder {
367            state: WantsVersions {},
368            provider,
369            time_provider,
370            side: PhantomData,
371        }
372    }
373
374    /// Return true if connections made with this `ClientConfig` will
375    /// operate in FIPS mode.
376    ///
377    /// This is different from [`CryptoProvider::fips()`]: [`CryptoProvider::fips()`]
378    /// is concerned only with cryptography, whereas this _also_ covers TLS-level
379    /// configuration that NIST recommends, as well as ECH HPKE suites if applicable.
380    pub fn fips(&self) -> bool {
381        let mut is_fips = self.provider.fips();
382
383        #[cfg(feature = "tls12")]
384        {
385            is_fips = is_fips && self.require_ems
386        }
387
388        if let Some(ech_mode) = &self.ech_mode {
389            is_fips = is_fips && ech_mode.fips();
390        }
391
392        is_fips
393    }
394
395    /// Return the crypto provider used to construct this client configuration.
396    pub fn crypto_provider(&self) -> &Arc<CryptoProvider> {
397        &self.provider
398    }
399
400    /// Access configuration options whose use is dangerous and requires
401    /// extra care.
402    pub fn dangerous(&mut self) -> danger::DangerousClientConfig<'_> {
403        danger::DangerousClientConfig { cfg: self }
404    }
405
406    pub(super) fn needs_key_share(&self) -> bool {
407        self.supports_version(ProtocolVersion::TLSv1_3)
408    }
409
410    /// We support a given TLS version if it's quoted in the configured
411    /// versions *and* at least one ciphersuite for this version is
412    /// also configured.
413    pub(crate) fn supports_version(&self, v: ProtocolVersion) -> bool {
414        self.versions.contains(v)
415            && self
416                .provider
417                .cipher_suites
418                .iter()
419                .any(|cs| cs.version().version == v)
420    }
421
422    #[cfg(feature = "std")]
423    pub(crate) fn supports_protocol(&self, proto: Protocol) -> bool {
424        self.provider
425            .cipher_suites
426            .iter()
427            .any(|cs| cs.usable_for_protocol(proto))
428    }
429
430    pub(super) fn find_cipher_suite(&self, suite: CipherSuite) -> Option<SupportedCipherSuite> {
431        self.provider
432            .cipher_suites
433            .iter()
434            .copied()
435            .find(|&scs| scs.suite() == suite)
436    }
437
438    pub(super) fn find_kx_group(
439        &self,
440        group: NamedGroup,
441        version: ProtocolVersion,
442    ) -> Option<&'static dyn SupportedKxGroup> {
443        self.provider
444            .kx_groups
445            .iter()
446            .copied()
447            .find(|skxg| skxg.usable_for_version(version) && skxg.name() == group)
448    }
449
450    pub(super) fn current_time(&self) -> Result<UnixTime, Error> {
451        self.time_provider
452            .current_time()
453            .ok_or(Error::FailedToGetCurrentTime)
454    }
455}
456
457/// Configuration for how/when a client is allowed to resume a previous session.
458#[derive(Clone, Debug)]
459pub struct Resumption {
460    /// How we store session data or tickets. The default is to use an in-memory
461    /// [super::handy::ClientSessionMemoryCache].
462    pub(super) store: Arc<dyn ClientSessionStore>,
463
464    /// What mechanism is used for resuming a TLS 1.2 session.
465    pub(super) tls12_resumption: Tls12Resumption,
466}
467
468impl Resumption {
469    /// Create a new `Resumption` that stores data for the given number of sessions in memory.
470    ///
471    /// This is the default `Resumption` choice, and enables resuming a TLS 1.2 session with
472    /// a session id or RFC 5077 ticket.
473    #[cfg(feature = "std")]
474    pub fn in_memory_sessions(num: usize) -> Self {
475        Self {
476            store: Arc::new(super::handy::ClientSessionMemoryCache::new(num)),
477            tls12_resumption: Tls12Resumption::SessionIdOrTickets,
478        }
479    }
480
481    /// Use a custom [`ClientSessionStore`] implementation to store sessions.
482    ///
483    /// By default, enables resuming a TLS 1.2 session with a session id or RFC 5077 ticket.
484    pub fn store(store: Arc<dyn ClientSessionStore>) -> Self {
485        Self {
486            store,
487            tls12_resumption: Tls12Resumption::SessionIdOrTickets,
488        }
489    }
490
491    /// Disable all use of session resumption.
492    pub fn disabled() -> Self {
493        Self {
494            store: Arc::new(NoClientSessionStorage),
495            tls12_resumption: Tls12Resumption::Disabled,
496        }
497    }
498
499    /// Configure whether TLS 1.2 sessions may be resumed, and by what mechanism.
500    ///
501    /// This is meaningless if you've disabled resumption entirely, which is the case in `no-std`
502    /// contexts.
503    pub fn tls12_resumption(mut self, tls12: Tls12Resumption) -> Self {
504        self.tls12_resumption = tls12;
505        self
506    }
507}
508
509impl Default for Resumption {
510    /// Create an in-memory session store resumption with up to 256 server names, allowing
511    /// a TLS 1.2 session to resume with a session id or RFC 5077 ticket.
512    fn default() -> Self {
513        #[cfg(feature = "std")]
514        let ret = Self::in_memory_sessions(256);
515
516        #[cfg(not(feature = "std"))]
517        let ret = Self::disabled();
518
519        ret
520    }
521}
522
523/// What mechanisms to support for resuming a TLS 1.2 session.
524#[derive(Clone, Copy, Debug, PartialEq)]
525pub enum Tls12Resumption {
526    /// Disable 1.2 resumption.
527    Disabled,
528    /// Support 1.2 resumption using session ids only.
529    SessionIdOnly,
530    /// Support 1.2 resumption using session ids or RFC 5077 tickets.
531    ///
532    /// See[^1] for why you might like to disable RFC 5077 by instead choosing the `SessionIdOnly`
533    /// option. Note that TLS 1.3 tickets do not have those issues.
534    ///
535    /// [^1]: <https://words.filippo.io/we-need-to-talk-about-session-tickets/>
536    SessionIdOrTickets,
537}
538
539/// Container for unsafe APIs
540pub(super) mod danger {
541    use super::ClientConfig;
542    use super::verify::ServerCertVerifier;
543    use crate::sync::Arc;
544
545    /// Accessor for dangerous configuration options.
546    #[derive(Debug)]
547    pub struct DangerousClientConfig<'a> {
548        /// The underlying ClientConfig
549        pub cfg: &'a mut ClientConfig,
550    }
551
552    impl DangerousClientConfig<'_> {
553        /// Overrides the default `ServerCertVerifier` with something else.
554        pub fn set_certificate_verifier(&mut self, verifier: Arc<dyn ServerCertVerifier>) {
555            self.cfg.verifier = verifier;
556        }
557    }
558}
559
560#[derive(Debug, PartialEq)]
561enum EarlyDataState {
562    Disabled,
563    Ready,
564    Accepted,
565    AcceptedFinished,
566    Rejected,
567}
568
569#[derive(Debug)]
570pub(super) struct EarlyData {
571    state: EarlyDataState,
572    left: usize,
573}
574
575impl EarlyData {
576    fn new() -> Self {
577        Self {
578            left: 0,
579            state: EarlyDataState::Disabled,
580        }
581    }
582
583    pub(super) fn is_enabled(&self) -> bool {
584        matches!(self.state, EarlyDataState::Ready | EarlyDataState::Accepted)
585    }
586
587    #[cfg(feature = "std")]
588    fn is_accepted(&self) -> bool {
589        matches!(
590            self.state,
591            EarlyDataState::Accepted | EarlyDataState::AcceptedFinished
592        )
593    }
594
595    pub(super) fn enable(&mut self, max_data: usize) {
596        assert_eq!(self.state, EarlyDataState::Disabled);
597        self.state = EarlyDataState::Ready;
598        self.left = max_data;
599    }
600
601    pub(super) fn rejected(&mut self) {
602        trace!("EarlyData rejected");
603        self.state = EarlyDataState::Rejected;
604    }
605
606    pub(super) fn accepted(&mut self) {
607        trace!("EarlyData accepted");
608        assert_eq!(self.state, EarlyDataState::Ready);
609        self.state = EarlyDataState::Accepted;
610    }
611
612    pub(super) fn finished(&mut self) {
613        trace!("EarlyData finished");
614        self.state = match self.state {
615            EarlyDataState::Accepted => EarlyDataState::AcceptedFinished,
616            _ => panic!("bad EarlyData state"),
617        }
618    }
619
620    fn check_write_opt(&mut self, sz: usize) -> Option<usize> {
621        match self.state {
622            EarlyDataState::Disabled => unreachable!(),
623            EarlyDataState::Ready | EarlyDataState::Accepted => {
624                let take = if self.left < sz {
625                    mem::replace(&mut self.left, 0)
626                } else {
627                    self.left -= sz;
628                    sz
629                };
630
631                Some(take)
632            }
633            EarlyDataState::Rejected | EarlyDataState::AcceptedFinished => None,
634        }
635    }
636}
637
638#[cfg(feature = "std")]
639mod connection {
640    use alloc::vec::Vec;
641    use core::fmt;
642    use core::ops::{Deref, DerefMut};
643    use std::io;
644
645    use pki_types::ServerName;
646
647    use super::{ClientConnectionData, ClientExtensionsInput};
648    use crate::ClientConfig;
649    use crate::client::EchStatus;
650    use crate::common_state::Protocol;
651    use crate::conn::{ConnectionCommon, ConnectionCore};
652    use crate::error::Error;
653    use crate::suites::ExtractedSecrets;
654    use crate::sync::Arc;
655
656    /// Stub that implements io::Write and dispatches to `write_early_data`.
657    pub struct WriteEarlyData<'a> {
658        sess: &'a mut ClientConnection,
659    }
660
661    impl<'a> WriteEarlyData<'a> {
662        fn new(sess: &'a mut ClientConnection) -> Self {
663            WriteEarlyData { sess }
664        }
665
666        /// How many bytes you may send.  Writes will become short
667        /// once this reaches zero.
668        pub fn bytes_left(&self) -> usize {
669            self.sess
670                .inner
671                .core
672                .data
673                .early_data
674                .bytes_left()
675        }
676    }
677
678    impl io::Write for WriteEarlyData<'_> {
679        fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
680            self.sess.write_early_data(buf)
681        }
682
683        fn flush(&mut self) -> io::Result<()> {
684            Ok(())
685        }
686    }
687
688    impl super::EarlyData {
689        fn check_write(&mut self, sz: usize) -> io::Result<usize> {
690            self.check_write_opt(sz)
691                .ok_or_else(|| io::Error::from(io::ErrorKind::InvalidInput))
692        }
693
694        fn bytes_left(&self) -> usize {
695            self.left
696        }
697    }
698
699    /// This represents a single TLS client connection.
700    pub struct ClientConnection {
701        inner: ConnectionCommon<ClientConnectionData>,
702    }
703
704    impl fmt::Debug for ClientConnection {
705        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
706            f.debug_struct("ClientConnection")
707                .finish()
708        }
709    }
710
711    impl ClientConnection {
712        /// Make a new ClientConnection.  `config` controls how
713        /// we behave in the TLS protocol, `name` is the
714        /// name of the server we want to talk to.
715        pub fn new(config: Arc<ClientConfig>, name: ServerName<'static>) -> Result<Self, Error> {
716            Self::new_with_alpn(config.clone(), name, config.alpn_protocols.clone())
717        }
718
719        /// Make a new ClientConnection with custom ALPN protocols.
720        pub fn new_with_alpn(
721            config: Arc<ClientConfig>,
722            name: ServerName<'static>,
723            alpn_protocols: Vec<Vec<u8>>,
724        ) -> Result<Self, Error> {
725            Ok(Self {
726                inner: ConnectionCommon::from(ConnectionCore::for_client(
727                    config,
728                    name,
729                    ClientExtensionsInput::from_alpn(alpn_protocols),
730                    Protocol::Tcp,
731                )?),
732            })
733        }
734        /// Returns an `io::Write` implementer you can write bytes to
735        /// to send TLS1.3 early data (a.k.a. "0-RTT data") to the server.
736        ///
737        /// This returns None in many circumstances when the capability to
738        /// send early data is not available, including but not limited to:
739        ///
740        /// - The server hasn't been talked to previously.
741        /// - The server does not support resumption.
742        /// - The server does not support early data.
743        /// - The resumption data for the server has expired.
744        ///
745        /// The server specifies a maximum amount of early data.  You can
746        /// learn this limit through the returned object, and writes through
747        /// it will process only this many bytes.
748        ///
749        /// The server can choose not to accept any sent early data --
750        /// in this case the data is lost but the connection continues.  You
751        /// can tell this happened using `is_early_data_accepted`.
752        pub fn early_data(&mut self) -> Option<WriteEarlyData<'_>> {
753            if self
754                .inner
755                .core
756                .data
757                .early_data
758                .is_enabled()
759            {
760                Some(WriteEarlyData::new(self))
761            } else {
762                None
763            }
764        }
765
766        /// Returns True if the server signalled it will process early data.
767        ///
768        /// If you sent early data and this returns false at the end of the
769        /// handshake then the server will not process the data.  This
770        /// is not an error, but you may wish to resend the data.
771        pub fn is_early_data_accepted(&self) -> bool {
772            self.inner.core.is_early_data_accepted()
773        }
774
775        /// Extract secrets, so they can be used when configuring kTLS, for example.
776        /// Should be used with care as it exposes secret key material.
777        pub fn dangerous_extract_secrets(self) -> Result<ExtractedSecrets, Error> {
778            self.inner.dangerous_extract_secrets()
779        }
780
781        /// Return the connection's Encrypted Client Hello (ECH) status.
782        pub fn ech_status(&self) -> EchStatus {
783            self.inner.core.data.ech_status
784        }
785
786        /// Returns the number of TLS1.3 tickets that have been received.
787        pub fn tls13_tickets_received(&self) -> u32 {
788            self.inner.tls13_tickets_received
789        }
790
791        /// Return true if the connection was made with a `ClientConfig` that is FIPS compatible.
792        ///
793        /// This is different from [`crate::crypto::CryptoProvider::fips()`]:
794        /// it is concerned only with cryptography, whereas this _also_ covers TLS-level
795        /// configuration that NIST recommends, as well as ECH HPKE suites if applicable.
796        pub fn fips(&self) -> bool {
797            self.inner.core.common_state.fips
798        }
799
800        fn write_early_data(&mut self, data: &[u8]) -> io::Result<usize> {
801            self.inner
802                .core
803                .data
804                .early_data
805                .check_write(data.len())
806                .map(|sz| {
807                    self.inner
808                        .send_early_plaintext(&data[..sz])
809                })
810        }
811    }
812
813    impl Deref for ClientConnection {
814        type Target = ConnectionCommon<ClientConnectionData>;
815
816        fn deref(&self) -> &Self::Target {
817            &self.inner
818        }
819    }
820
821    impl DerefMut for ClientConnection {
822        fn deref_mut(&mut self) -> &mut Self::Target {
823            &mut self.inner
824        }
825    }
826
827    #[doc(hidden)]
828    impl<'a> TryFrom<&'a mut crate::Connection> for &'a mut ClientConnection {
829        type Error = ();
830
831        fn try_from(value: &'a mut crate::Connection) -> Result<Self, Self::Error> {
832            use crate::Connection::*;
833            match value {
834                Client(conn) => Ok(conn),
835                Server(_) => Err(()),
836            }
837        }
838    }
839
840    impl From<ClientConnection> for crate::Connection {
841        fn from(conn: ClientConnection) -> Self {
842            Self::Client(conn)
843        }
844    }
845}
846#[cfg(feature = "std")]
847pub use connection::{ClientConnection, WriteEarlyData};
848
849impl ConnectionCore<ClientConnectionData> {
850    pub(crate) fn for_client(
851        config: Arc<ClientConfig>,
852        name: ServerName<'static>,
853        extra_exts: ClientExtensionsInput<'static>,
854        proto: Protocol,
855    ) -> Result<Self, Error> {
856        let mut common_state = CommonState::new(Side::Client);
857        common_state.set_max_fragment_size(config.max_fragment_size)?;
858        common_state.protocol = proto;
859        common_state.enable_secret_extraction = config.enable_secret_extraction;
860        common_state.fips = config.fips();
861        let mut data = ClientConnectionData::new();
862
863        let mut cx = hs::ClientContext {
864            common: &mut common_state,
865            data: &mut data,
866            // `start_handshake` won't produce plaintext
867            sendable_plaintext: None,
868        };
869
870        let input = ClientHelloInput::new(name, &extra_exts, &mut cx, config)?;
871        let state = input.start_handshake(extra_exts, &mut cx)?;
872        Ok(Self::new(state, data, common_state))
873    }
874
875    #[cfg(feature = "std")]
876    pub(crate) fn is_early_data_accepted(&self) -> bool {
877        self.data.early_data.is_accepted()
878    }
879}
880
881/// Unbuffered version of `ClientConnection`
882///
883/// See the [`crate::unbuffered`] module docs for more details
884pub struct UnbufferedClientConnection {
885    inner: UnbufferedConnectionCommon<ClientConnectionData>,
886}
887
888impl UnbufferedClientConnection {
889    /// Make a new ClientConnection. `config` controls how we behave in the TLS protocol, `name` is
890    /// the name of the server we want to talk to.
891    pub fn new(config: Arc<ClientConfig>, name: ServerName<'static>) -> Result<Self, Error> {
892        Self::new_with_extensions(
893            config.clone(),
894            name,
895            ClientExtensionsInput::from_alpn(config.alpn_protocols.clone()),
896        )
897    }
898
899    /// Make a new UnbufferedClientConnection with custom ALPN protocols.
900    pub fn new_with_alpn(
901        config: Arc<ClientConfig>,
902        name: ServerName<'static>,
903        alpn_protocols: Vec<Vec<u8>>,
904    ) -> Result<Self, Error> {
905        Self::new_with_extensions(
906            config,
907            name,
908            ClientExtensionsInput::from_alpn(alpn_protocols),
909        )
910    }
911
912    fn new_with_extensions(
913        config: Arc<ClientConfig>,
914        name: ServerName<'static>,
915        extensions: ClientExtensionsInput<'static>,
916    ) -> Result<Self, Error> {
917        Ok(Self {
918            inner: UnbufferedConnectionCommon::from(ConnectionCore::for_client(
919                config,
920                name,
921                extensions,
922                Protocol::Tcp,
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    #[deprecated = "dangerous_extract_secrets() does not support session tickets or \
930                    key updates, use dangerous_into_kernel_connection() instead"]
931    pub fn dangerous_extract_secrets(self) -> Result<ExtractedSecrets, Error> {
932        self.inner.dangerous_extract_secrets()
933    }
934
935    /// Extract secrets and a [`KernelConnection`] object.
936    ///
937    /// This allows you use rustls to manage keys and then manage encryption and
938    /// decryption yourself (e.g. for kTLS).
939    ///
940    /// Should be used with care as it exposes secret key material.
941    ///
942    /// See the [`crate::kernel`] documentations for details on prerequisites
943    /// for calling this method.
944    pub fn dangerous_into_kernel_connection(
945        self,
946    ) -> Result<(ExtractedSecrets, KernelConnection<ClientConnectionData>), Error> {
947        self.inner
948            .core
949            .dangerous_into_kernel_connection()
950    }
951
952    /// Returns the number of TLS1.3 tickets that have been received.
953    pub fn tls13_tickets_received(&self) -> u32 {
954        self.inner.tls13_tickets_received
955    }
956}
957
958impl Deref for UnbufferedClientConnection {
959    type Target = UnbufferedConnectionCommon<ClientConnectionData>;
960
961    fn deref(&self) -> &Self::Target {
962        &self.inner
963    }
964}
965
966impl DerefMut for UnbufferedClientConnection {
967    fn deref_mut(&mut self) -> &mut Self::Target {
968        &mut self.inner
969    }
970}
971
972impl TransmitTlsData<'_, ClientConnectionData> {
973    /// returns an adapter that allows encrypting early (RTT-0) data before transmitting the
974    /// already encoded TLS data
975    ///
976    /// IF allowed by the protocol
977    pub fn may_encrypt_early_data(&mut self) -> Option<MayEncryptEarlyData<'_>> {
978        if self
979            .conn
980            .core
981            .data
982            .early_data
983            .is_enabled()
984        {
985            Some(MayEncryptEarlyData { conn: self.conn })
986        } else {
987            None
988        }
989    }
990}
991
992/// Allows encrypting early (RTT-0) data
993pub struct MayEncryptEarlyData<'c> {
994    conn: &'c mut UnbufferedConnectionCommon<ClientConnectionData>,
995}
996
997impl MayEncryptEarlyData<'_> {
998    /// Encrypts `application_data` into the `outgoing_tls` buffer
999    ///
1000    /// returns the number of bytes that were written into `outgoing_tls`, or an error if
1001    /// the provided buffer was too small. In the error case, `outgoing_tls` is not modified
1002    pub fn encrypt(
1003        &mut self,
1004        early_data: &[u8],
1005        outgoing_tls: &mut [u8],
1006    ) -> Result<usize, EarlyDataError> {
1007        let Some(allowed) = self
1008            .conn
1009            .core
1010            .data
1011            .early_data
1012            .check_write_opt(early_data.len())
1013        else {
1014            return Err(EarlyDataError::ExceededAllowedEarlyData);
1015        };
1016
1017        self.conn
1018            .core
1019            .common_state
1020            .write_plaintext(early_data[..allowed].into(), outgoing_tls)
1021            .map_err(|e| e.into())
1022    }
1023}
1024
1025/// Errors that may arise when encrypting early (RTT-0) data
1026#[derive(Debug)]
1027pub enum EarlyDataError {
1028    /// Cannot encrypt more early data due to imposed limits
1029    ExceededAllowedEarlyData,
1030    /// Encryption error
1031    Encrypt(EncryptError),
1032}
1033
1034impl From<EncryptError> for EarlyDataError {
1035    fn from(v: EncryptError) -> Self {
1036        Self::Encrypt(v)
1037    }
1038}
1039
1040impl fmt::Display for EarlyDataError {
1041    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1042        match self {
1043            Self::ExceededAllowedEarlyData => f.write_str("cannot send any more early data"),
1044            Self::Encrypt(e) => fmt::Display::fmt(e, f),
1045        }
1046    }
1047}
1048
1049#[cfg(feature = "std")]
1050impl std::error::Error for EarlyDataError {}
1051
1052/// State associated with a client connection.
1053#[derive(Debug)]
1054pub struct ClientConnectionData {
1055    pub(super) early_data: EarlyData,
1056    pub(super) ech_status: EchStatus,
1057}
1058
1059impl ClientConnectionData {
1060    fn new() -> Self {
1061        Self {
1062            early_data: EarlyData::new(),
1063            ech_status: EchStatus::NotOffered,
1064        }
1065    }
1066}
1067
1068impl crate::conn::SideData for ClientConnectionData {}