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