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