rustls/client/
client_conn.rs

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