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