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