clia_rustls_mod/client/
client_conn.rs

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