rustls/client/
hs.rs

1use alloc::borrow::ToOwned;
2use alloc::boxed::Box;
3use alloc::vec;
4use alloc::vec::Vec;
5use core::ops::Deref;
6
7use pki_types::ServerName;
8
9#[cfg(feature = "tls12")]
10use super::tls12;
11use super::{ResolvesClientCert, Tls12Resumption};
12use crate::SupportedCipherSuite;
13#[cfg(feature = "logging")]
14use crate::bs_debug;
15use crate::check::inappropriate_handshake_message;
16use crate::client::client_conn::ClientConnectionData;
17use crate::client::common::ClientHelloDetails;
18use crate::client::ech::EchState;
19use crate::client::{ClientConfig, EchMode, EchStatus, tls13};
20use crate::common_state::{CommonState, HandshakeKind, KxState, State};
21use crate::conn::ConnectionRandoms;
22use crate::crypto::{ActiveKeyExchange, KeyExchangeAlgorithm};
23use crate::enums::{
24    AlertDescription, CertificateType, CipherSuite, ContentType, HandshakeType, ProtocolVersion,
25};
26use crate::error::{Error, PeerIncompatible, PeerMisbehaved};
27use crate::hash_hs::HandshakeHashBuffer;
28use crate::log::{debug, trace};
29use crate::msgs::base::Payload;
30use crate::msgs::enums::{Compression, ExtensionType};
31use crate::msgs::handshake::{
32    CertificateStatusRequest, ClientExtensions, ClientExtensionsInput, ClientHelloPayload,
33    ClientSessionTicket, EncryptedClientHello, HandshakeMessagePayload, HandshakePayload,
34    HelloRetryRequest, KeyShareEntry, ProtocolName, PskKeyExchangeModes, Random, ServerNamePayload,
35    SessionId, SupportedEcPointFormats, SupportedProtocolVersions, TransportParameters,
36};
37use crate::msgs::message::{Message, MessagePayload};
38use crate::msgs::persist;
39use crate::sync::Arc;
40use crate::tls13::key_schedule::KeyScheduleEarly;
41use crate::verify::ServerCertVerifier;
42
43pub(super) type NextState<'a> = Box<dyn State<ClientConnectionData> + 'a>;
44pub(super) type NextStateOrError<'a> = Result<NextState<'a>, Error>;
45pub(super) type ClientContext<'a> = crate::common_state::Context<'a, ClientConnectionData>;
46
47struct ExpectServerHello {
48    input: ClientHelloInput,
49    transcript_buffer: HandshakeHashBuffer,
50    // The key schedule for sending early data.
51    //
52    // If the server accepts the PSK used for early data then
53    // this is used to compute the rest of the key schedule.
54    // Otherwise, it is thrown away.
55    //
56    // If this is `None` then we do not support early data.
57    early_data_key_schedule: Option<KeyScheduleEarly>,
58    offered_key_share: Option<Box<dyn ActiveKeyExchange>>,
59    suite: Option<SupportedCipherSuite>,
60    ech_state: Option<EchState>,
61}
62
63struct ExpectServerHelloOrHelloRetryRequest {
64    next: ExpectServerHello,
65    extra_exts: ClientExtensionsInput<'static>,
66}
67
68pub(super) struct ClientHelloInput {
69    pub(super) config: Arc<ClientConfig>,
70    pub(super) resuming: Option<persist::Retrieved<ClientSessionValue>>,
71    pub(super) random: Random,
72    pub(super) sent_tls13_fake_ccs: bool,
73    pub(super) hello: ClientHelloDetails,
74    pub(super) session_id: SessionId,
75    pub(super) server_name: ServerName<'static>,
76    pub(super) prev_ech_ext: Option<EncryptedClientHello>,
77}
78
79impl ClientHelloInput {
80    pub(super) fn new(
81        server_name: ServerName<'static>,
82        extra_exts: &ClientExtensionsInput<'_>,
83        cx: &mut ClientContext<'_>,
84        config: Arc<ClientConfig>,
85    ) -> Result<Self, Error> {
86        let mut resuming = ClientSessionValue::retrieve(&server_name, &config, cx);
87        let session_id = match &mut resuming {
88            Some(_resuming) => {
89                debug!("Resuming session");
90                match &mut _resuming.value {
91                    #[cfg(feature = "tls12")]
92                    ClientSessionValue::Tls12(inner) => {
93                        // If we have a ticket, we use the sessionid as a signal that
94                        // we're  doing an abbreviated handshake.  See section 3.4 in
95                        // RFC5077.
96                        if !inner.ticket().0.is_empty() {
97                            inner.session_id = SessionId::random(config.provider.secure_random)?;
98                        }
99                        Some(inner.session_id)
100                    }
101                    _ => None,
102                }
103            }
104            _ => {
105                debug!("Not resuming any session");
106                None
107            }
108        };
109
110        // https://tools.ietf.org/html/rfc8446#appendix-D.4
111        // https://tools.ietf.org/html/draft-ietf-quic-tls-34#section-8.4
112        let session_id = match session_id {
113            Some(session_id) => session_id,
114            None if cx.common.is_quic() => SessionId::empty(),
115            None if !config.supports_version(ProtocolVersion::TLSv1_3) => SessionId::empty(),
116            None => SessionId::random(config.provider.secure_random)?,
117        };
118
119        let hello = ClientHelloDetails::new(
120            extra_exts
121                .protocols
122                .clone()
123                .unwrap_or_default(),
124            crate::rand::random_u16(config.provider.secure_random)?,
125        );
126
127        Ok(Self {
128            resuming,
129            random: Random::new(config.provider.secure_random)?,
130            sent_tls13_fake_ccs: false,
131            hello,
132            session_id,
133            server_name,
134            prev_ech_ext: None,
135            config,
136        })
137    }
138
139    pub(super) fn start_handshake(
140        self,
141        extra_exts: ClientExtensionsInput<'static>,
142        cx: &mut ClientContext<'_>,
143    ) -> NextStateOrError<'static> {
144        let mut transcript_buffer = HandshakeHashBuffer::new();
145        if self
146            .config
147            .client_auth_cert_resolver
148            .has_certs()
149        {
150            transcript_buffer.set_client_auth_enabled();
151        }
152
153        let key_share = if self.config.needs_key_share() {
154            Some(tls13::initial_key_share(
155                &self.config,
156                &self.server_name,
157                &mut cx.common.kx_state,
158            )?)
159        } else {
160            None
161        };
162
163        let ech_state = match self.config.ech_mode.as_ref() {
164            Some(EchMode::Enable(ech_config)) => {
165                Some(ech_config.state(self.server_name.clone(), &self.config)?)
166            }
167            _ => None,
168        };
169
170        emit_client_hello_for_retry(
171            transcript_buffer,
172            None,
173            key_share,
174            extra_exts,
175            None,
176            self,
177            cx,
178            ech_state,
179        )
180    }
181}
182
183/// Emits the initial ClientHello or a ClientHello in response to
184/// a HelloRetryRequest.
185///
186/// `retryreq` and `suite` are `None` if this is the initial
187/// ClientHello.
188fn emit_client_hello_for_retry(
189    mut transcript_buffer: HandshakeHashBuffer,
190    retryreq: Option<&HelloRetryRequest>,
191    key_share: Option<Box<dyn ActiveKeyExchange>>,
192    extra_exts: ClientExtensionsInput<'static>,
193    suite: Option<SupportedCipherSuite>,
194    mut input: ClientHelloInput,
195    cx: &mut ClientContext<'_>,
196    mut ech_state: Option<EchState>,
197) -> NextStateOrError<'static> {
198    let config = &input.config;
199    // Defense in depth: the ECH state should be None if ECH is disabled based on config
200    // builder semantics.
201    let forbids_tls12 = cx.common.is_quic() || ech_state.is_some();
202
203    let supported_versions = SupportedProtocolVersions {
204        tls12: config.supports_version(ProtocolVersion::TLSv1_2) && !forbids_tls12,
205        tls13: config.supports_version(ProtocolVersion::TLSv1_3),
206    };
207
208    // should be unreachable thanks to config builder
209    assert!(supported_versions.any(|_| true));
210
211    let mut exts = Box::new(ClientExtensions {
212        // offer groups which are usable for any offered version
213        named_groups: Some(
214            config
215                .provider
216                .kx_groups
217                .iter()
218                .filter(|skxg| supported_versions.any(|v| skxg.usable_for_version(v)))
219                .map(|skxg| skxg.name())
220                .collect(),
221        ),
222        supported_versions: Some(supported_versions),
223        signature_schemes: Some(
224            config
225                .verifier
226                .supported_verify_schemes(),
227        ),
228        extended_master_secret_request: Some(()),
229        certificate_status_request: Some(CertificateStatusRequest::build_ocsp()),
230        protocols: extra_exts.protocols.clone(),
231        ..Default::default()
232    });
233
234    match extra_exts.transport_parameters.clone() {
235        Some(TransportParameters::Quic(v)) => exts.transport_parameters = Some(v),
236        Some(TransportParameters::QuicDraft(v)) => exts.transport_parameters_draft = Some(v),
237        None => {}
238    };
239
240    if supported_versions.tls13 {
241        if let Some(cas_extension) = config.verifier.root_hint_subjects() {
242            exts.certificate_authority_names = Some(cas_extension.to_owned());
243        }
244    }
245
246    // Send the ECPointFormat extension only if we are proposing ECDHE
247    if config
248        .provider
249        .kx_groups
250        .iter()
251        .any(|skxg| skxg.name().key_exchange_algorithm() == KeyExchangeAlgorithm::ECDHE)
252    {
253        exts.ec_point_formats = Some(SupportedEcPointFormats::default());
254    }
255
256    exts.server_name = match (ech_state.as_ref(), config.enable_sni) {
257        // If we have ECH state we have a "cover name" to send in the outer hello
258        // as the SNI domain name. This happens unconditionally so we ignore the
259        // `enable_sni` value. That will be used later to decide what to do for
260        // the protected inner hello's SNI.
261        (Some(ech_state), _) => Some(ServerNamePayload::from(&ech_state.outer_name)),
262
263        // If we have no ECH state, and SNI is enabled, try to use the input server_name
264        // for the SNI domain name.
265        (None, true) => match &input.server_name {
266            ServerName::DnsName(dns_name) => Some(ServerNamePayload::from(dns_name)),
267            _ => None,
268        },
269
270        // If we have no ECH state, and SNI is not enabled, there's nothing to do.
271        (None, false) => None,
272    };
273
274    if let Some(key_share) = &key_share {
275        debug_assert!(supported_versions.tls13);
276        let mut shares = vec![KeyShareEntry::new(key_share.group(), key_share.pub_key())];
277
278        if !retryreq
279            .map(|rr| rr.key_share.is_some())
280            .unwrap_or_default()
281        {
282            // Only for the initial client hello, or a HRR that does not specify a kx group,
283            // see if we can send a second KeyShare for "free".  We only do this if the same
284            // algorithm is also supported separately by our provider for this version
285            // (`find_kx_group` looks that up).
286            if let Some((component_group, component_share)) =
287                key_share
288                    .hybrid_component()
289                    .filter(|(group, _)| {
290                        config
291                            .find_kx_group(*group, ProtocolVersion::TLSv1_3)
292                            .is_some()
293                    })
294            {
295                shares.push(KeyShareEntry::new(component_group, component_share));
296            }
297        }
298
299        exts.key_shares = Some(shares);
300    }
301
302    if let Some(cookie) = retryreq.and_then(|hrr| hrr.cookie.as_ref()) {
303        exts.cookie = Some(cookie.clone());
304    }
305
306    if supported_versions.tls13 {
307        // We could support PSK_KE here too. Such connections don't
308        // have forward secrecy, and are similar to TLS1.2 resumption.
309        exts.preshared_key_modes = Some(PskKeyExchangeModes {
310            psk: false,
311            psk_dhe: true,
312        });
313    }
314
315    input.hello.offered_cert_compression =
316        if supported_versions.tls13 && !config.cert_decompressors.is_empty() {
317            exts.certificate_compression_algorithms = Some(
318                config
319                    .cert_decompressors
320                    .iter()
321                    .map(|dec| dec.algorithm())
322                    .collect(),
323            );
324            true
325        } else {
326            false
327        };
328
329    if config
330        .client_auth_cert_resolver
331        .only_raw_public_keys()
332    {
333        exts.client_certificate_types = Some(vec![CertificateType::RawPublicKey]);
334    }
335
336    if config
337        .verifier
338        .requires_raw_public_keys()
339    {
340        exts.server_certificate_types = Some(vec![CertificateType::RawPublicKey]);
341    }
342
343    // If this is a second client hello we're constructing in response to an HRR, and
344    // we've rejected ECH or sent GREASE ECH, then we need to carry forward the
345    // exact same ECH extension we used in the first hello.
346    if matches!(cx.data.ech_status, EchStatus::Rejected | EchStatus::Grease) & retryreq.is_some() {
347        if let Some(prev_ech_ext) = input.prev_ech_ext.take() {
348            exts.encrypted_client_hello = Some(prev_ech_ext);
349        }
350    }
351
352    // Do we have a SessionID or ticket cached for this host?
353    let tls13_session = prepare_resumption(&input.resuming, &mut exts, suite, cx, config);
354
355    // Extensions MAY be randomized
356    // but they also need to keep the same order as the previous ClientHello
357    exts.order_seed = input.hello.extension_order_seed;
358
359    let mut cipher_suites: Vec<_> = config
360        .provider
361        .cipher_suites
362        .iter()
363        .filter_map(|cs| match cs.usable_for_protocol(cx.common.protocol) {
364            true => Some(cs.suite()),
365            false => None,
366        })
367        .collect();
368
369    if supported_versions.tls12 {
370        // We don't do renegotiation at all, in fact.
371        cipher_suites.push(CipherSuite::TLS_EMPTY_RENEGOTIATION_INFO_SCSV);
372    }
373
374    let mut chp_payload = ClientHelloPayload {
375        client_version: ProtocolVersion::TLSv1_2,
376        random: input.random,
377        session_id: input.session_id,
378        cipher_suites,
379        compression_methods: vec![Compression::Null],
380        extensions: exts,
381    };
382
383    let ech_grease_ext = config
384        .ech_mode
385        .as_ref()
386        .and_then(|mode| match mode {
387            EchMode::Grease(cfg) => Some(cfg.grease_ext(
388                config.provider.secure_random,
389                input.server_name.clone(),
390                &chp_payload,
391            )),
392            _ => None,
393        });
394
395    match (cx.data.ech_status, &mut ech_state) {
396        // If we haven't offered ECH, or have offered ECH but got a non-rejecting HRR, then
397        // we need to replace the client hello payload with an ECH client hello payload.
398        (EchStatus::NotOffered | EchStatus::Offered, Some(ech_state)) => {
399            // Replace the client hello payload with an ECH client hello payload.
400            chp_payload = ech_state.ech_hello(chp_payload, retryreq, &tls13_session)?;
401            cx.data.ech_status = EchStatus::Offered;
402            // Store the ECH extension in case we need to carry it forward in a subsequent hello.
403            input.prev_ech_ext = chp_payload
404                .encrypted_client_hello
405                .clone();
406        }
407        // If we haven't offered ECH, and have no ECH state, then consider whether to use GREASE
408        // ECH.
409        (EchStatus::NotOffered, None) => {
410            if let Some(grease_ext) = ech_grease_ext {
411                // Add the GREASE ECH extension.
412                let grease_ext = grease_ext?;
413                chp_payload.encrypted_client_hello = Some(grease_ext.clone());
414                cx.data.ech_status = EchStatus::Grease;
415                // Store the GREASE ECH extension in case we need to carry it forward in a
416                // subsequent hello.
417                input.prev_ech_ext = Some(grease_ext);
418            }
419        }
420        _ => {}
421    }
422
423    // Note what extensions we sent.
424    input.hello.sent_extensions = chp_payload.collect_used();
425
426    let mut chp = HandshakeMessagePayload(HandshakePayload::ClientHello(chp_payload));
427
428    let tls13_early_data_key_schedule = match (ech_state.as_mut(), tls13_session) {
429        // If we're performing ECH and resuming, then the PSK binder will have been dealt with
430        // separately, and we need to take the early_data_key_schedule computed for the inner hello.
431        (Some(ech_state), Some(tls13_session)) => ech_state
432            .early_data_key_schedule
433            .take()
434            .map(|schedule| (tls13_session.suite(), schedule)),
435
436        // When we're not doing ECH and resuming, then the PSK binder need to be filled in as
437        // normal.
438        (_, Some(tls13_session)) => Some((
439            tls13_session.suite(),
440            tls13::fill_in_psk_binder(&tls13_session, &transcript_buffer, &mut chp),
441        )),
442
443        // No early key schedule in other cases.
444        _ => None,
445    };
446
447    let ch = Message {
448        version: match retryreq {
449            // <https://datatracker.ietf.org/doc/html/rfc8446#section-5.1>:
450            // "This value MUST be set to 0x0303 for all records generated
451            //  by a TLS 1.3 implementation ..."
452            Some(_) => ProtocolVersion::TLSv1_2,
453            // "... other than an initial ClientHello (i.e., one not
454            // generated after a HelloRetryRequest), where it MAY also be
455            // 0x0301 for compatibility purposes"
456            //
457            // (retryreq == None means we're in the "initial ClientHello" case)
458            None => ProtocolVersion::TLSv1_0,
459        },
460        payload: MessagePayload::handshake(chp),
461    };
462
463    if retryreq.is_some() {
464        // send dummy CCS to fool middleboxes prior
465        // to second client hello
466        tls13::emit_fake_ccs(&mut input.sent_tls13_fake_ccs, cx.common);
467    }
468
469    trace!("Sending ClientHello {ch:#?}");
470
471    transcript_buffer.add_message(&ch);
472    cx.common.send_msg(ch, false);
473
474    // Calculate the hash of ClientHello and use it to derive EarlyTrafficSecret
475    let early_data_key_schedule =
476        tls13_early_data_key_schedule.map(|(resuming_suite, schedule)| {
477            if !cx.data.early_data.is_enabled() {
478                return schedule;
479            }
480
481            let (transcript_buffer, random) = match &ech_state {
482                // When using ECH the early data key schedule is derived based on the inner
483                // hello transcript and random.
484                Some(ech_state) => (
485                    &ech_state.inner_hello_transcript,
486                    &ech_state.inner_hello_random.0,
487                ),
488                None => (&transcript_buffer, &input.random.0),
489            };
490
491            tls13::derive_early_traffic_secret(
492                &*config.key_log,
493                cx,
494                resuming_suite.common.hash_provider,
495                &schedule,
496                &mut input.sent_tls13_fake_ccs,
497                transcript_buffer,
498                random,
499            );
500            schedule
501        });
502
503    let next = ExpectServerHello {
504        input,
505        transcript_buffer,
506        early_data_key_schedule,
507        offered_key_share: key_share,
508        suite,
509        ech_state,
510    };
511
512    Ok(if supported_versions.tls13 && retryreq.is_none() {
513        Box::new(ExpectServerHelloOrHelloRetryRequest {
514            next,
515            extra_exts: extra_exts.into_owned(),
516        })
517    } else {
518        Box::new(next)
519    })
520}
521
522/// Prepares `exts` and `cx` with TLS 1.2 or TLS 1.3 session
523/// resumption.
524///
525/// - `suite` is `None` if this is the initial ClientHello, or
526///   `Some` if we're retrying in response to
527///   a HelloRetryRequest.
528///
529/// This function will push onto `exts` to
530///
531/// (a) request a new ticket if we don't have one,
532/// (b) send our TLS 1.2 ticket after retrieving an 1.2 session,
533/// (c) send a request for 1.3 early data if allowed and
534/// (d) send a 1.3 preshared key if we have one.
535///
536/// It returns the TLS 1.3 PSKs, if any, for further processing.
537fn prepare_resumption<'a>(
538    resuming: &'a Option<persist::Retrieved<ClientSessionValue>>,
539    exts: &mut ClientExtensions<'_>,
540    suite: Option<SupportedCipherSuite>,
541    cx: &mut ClientContext<'_>,
542    config: &ClientConfig,
543) -> Option<persist::Retrieved<&'a persist::Tls13ClientSessionValue>> {
544    // Check whether we're resuming with a non-empty ticket.
545    let resuming = match resuming {
546        Some(resuming) if !resuming.ticket().is_empty() => resuming,
547        _ => {
548            if config.supports_version(ProtocolVersion::TLSv1_2)
549                && config.resumption.tls12_resumption == Tls12Resumption::SessionIdOrTickets
550            {
551                // If we don't have a ticket, request one.
552                exts.session_ticket = Some(ClientSessionTicket::Request);
553            }
554            return None;
555        }
556    };
557
558    let Some(tls13) = resuming.map(|csv| csv.tls13()) else {
559        // TLS 1.2; send the ticket if we have support this protocol version
560        if config.supports_version(ProtocolVersion::TLSv1_2)
561            && config.resumption.tls12_resumption == Tls12Resumption::SessionIdOrTickets
562        {
563            exts.session_ticket = Some(ClientSessionTicket::Offer(Payload::new(resuming.ticket())));
564        }
565        return None; // TLS 1.2, so nothing to return here
566    };
567
568    if !config.supports_version(ProtocolVersion::TLSv1_3) {
569        return None;
570    }
571
572    // If the server selected TLS 1.2, we can't resume.
573    let suite = match suite {
574        Some(SupportedCipherSuite::Tls13(suite)) => Some(suite),
575        #[cfg(feature = "tls12")]
576        Some(SupportedCipherSuite::Tls12(_)) => return None,
577        None => None,
578    };
579
580    // If the selected cipher suite can't select from the session's, we can't resume.
581    if let Some(suite) = suite {
582        suite.can_resume_from(tls13.suite())?;
583    }
584
585    tls13::prepare_resumption(config, cx, &tls13, exts, suite.is_some());
586    Some(tls13)
587}
588
589pub(super) fn process_alpn_protocol(
590    common: &mut CommonState,
591    offered_protocols: &[ProtocolName],
592    selected: Option<&ProtocolName>,
593    check_selected_offered: bool,
594) -> Result<(), Error> {
595    common.alpn_protocol = selected.map(ToOwned::to_owned);
596
597    if let Some(alpn_protocol) = &common.alpn_protocol {
598        if check_selected_offered && !offered_protocols.contains(alpn_protocol) {
599            return Err(common.send_fatal_alert(
600                AlertDescription::IllegalParameter,
601                PeerMisbehaved::SelectedUnofferedApplicationProtocol,
602            ));
603        }
604    }
605
606    // RFC 9001 says: "While ALPN only specifies that servers use this alert, QUIC clients MUST
607    // use error 0x0178 to terminate a connection when ALPN negotiation fails." We judge that
608    // the user intended to use ALPN (rather than some out-of-band protocol negotiation
609    // mechanism) if and only if any ALPN protocols were configured. This defends against badly-behaved
610    // servers which accept a connection that requires an application-layer protocol they do not
611    // understand.
612    if common.is_quic() && common.alpn_protocol.is_none() && !offered_protocols.is_empty() {
613        return Err(common.send_fatal_alert(
614            AlertDescription::NoApplicationProtocol,
615            Error::NoApplicationProtocol,
616        ));
617    }
618
619    debug!(
620        "ALPN protocol is {:?}",
621        common
622            .alpn_protocol
623            .as_ref()
624            .map(|v| bs_debug::BsDebug(v.as_ref()))
625    );
626    Ok(())
627}
628
629pub(super) fn process_server_cert_type_extension(
630    common: &mut CommonState,
631    config: &ClientConfig,
632    server_cert_extension: Option<&CertificateType>,
633) -> Result<Option<(ExtensionType, CertificateType)>, Error> {
634    process_cert_type_extension(
635        common,
636        config
637            .verifier
638            .requires_raw_public_keys(),
639        server_cert_extension.copied(),
640        ExtensionType::ServerCertificateType,
641    )
642}
643
644pub(super) fn process_client_cert_type_extension(
645    common: &mut CommonState,
646    config: &ClientConfig,
647    client_cert_extension: Option<&CertificateType>,
648) -> Result<Option<(ExtensionType, CertificateType)>, Error> {
649    process_cert_type_extension(
650        common,
651        config
652            .client_auth_cert_resolver
653            .only_raw_public_keys(),
654        client_cert_extension.copied(),
655        ExtensionType::ClientCertificateType,
656    )
657}
658
659impl State<ClientConnectionData> for ExpectServerHello {
660    fn handle<'m>(
661        mut self: Box<Self>,
662        cx: &mut ClientContext<'_>,
663        m: Message<'m>,
664    ) -> NextStateOrError<'m>
665    where
666        Self: 'm,
667    {
668        let server_hello =
669            require_handshake_msg!(m, HandshakeType::ServerHello, HandshakePayload::ServerHello)?;
670        trace!("We got ServerHello {server_hello:#?}");
671
672        use crate::ProtocolVersion::{TLSv1_2, TLSv1_3};
673        let config = &self.input.config;
674        let tls13_supported = config.supports_version(TLSv1_3);
675
676        let server_version = if server_hello.legacy_version == TLSv1_2 {
677            server_hello
678                .selected_version
679                .unwrap_or(server_hello.legacy_version)
680        } else {
681            server_hello.legacy_version
682        };
683
684        let version = match server_version {
685            TLSv1_3 if tls13_supported => TLSv1_3,
686            TLSv1_2 if config.supports_version(TLSv1_2) => {
687                if cx.data.early_data.is_enabled() && cx.common.early_traffic {
688                    // The client must fail with a dedicated error code if the server
689                    // responds with TLS 1.2 when offering 0-RTT.
690                    return Err(PeerMisbehaved::OfferedEarlyDataWithOldProtocolVersion.into());
691                }
692
693                if server_hello.selected_version.is_some() {
694                    return Err({
695                        cx.common.send_fatal_alert(
696                            AlertDescription::IllegalParameter,
697                            PeerMisbehaved::SelectedTls12UsingTls13VersionExtension,
698                        )
699                    });
700                }
701
702                TLSv1_2
703            }
704            _ => {
705                let reason = match server_version {
706                    TLSv1_2 | TLSv1_3 => PeerIncompatible::ServerTlsVersionIsDisabledByOurConfig,
707                    _ => PeerIncompatible::ServerDoesNotSupportTls12Or13,
708                };
709                return Err(cx
710                    .common
711                    .send_fatal_alert(AlertDescription::ProtocolVersion, reason));
712            }
713        };
714
715        if server_hello.compression_method != Compression::Null {
716            return Err({
717                cx.common.send_fatal_alert(
718                    AlertDescription::IllegalParameter,
719                    PeerMisbehaved::SelectedUnofferedCompression,
720                )
721            });
722        }
723
724        let allowed_unsolicited = [ExtensionType::RenegotiationInfo];
725        if self
726            .input
727            .hello
728            .server_sent_unsolicited_extensions(server_hello, &allowed_unsolicited)
729        {
730            return Err(cx.common.send_fatal_alert(
731                AlertDescription::UnsupportedExtension,
732                PeerMisbehaved::UnsolicitedServerHelloExtension,
733            ));
734        }
735
736        cx.common.negotiated_version = Some(version);
737
738        // Extract ALPN protocol
739        if !cx.common.is_tls13() {
740            process_alpn_protocol(
741                cx.common,
742                &self.input.hello.alpn_protocols,
743                server_hello
744                    .selected_protocol
745                    .as_ref()
746                    .map(|s| s.as_ref()),
747                self.input.config.check_selected_alpn,
748            )?;
749        }
750
751        // If ECPointFormats extension is supplied by the server, it must contain
752        // Uncompressed.  But it's allowed to be omitted.
753        if let Some(point_fmts) = &server_hello.ec_point_formats {
754            if !point_fmts.uncompressed {
755                return Err(cx.common.send_fatal_alert(
756                    AlertDescription::HandshakeFailure,
757                    PeerMisbehaved::ServerHelloMustOfferUncompressedEcPoints,
758                ));
759            }
760        }
761
762        let suite = config
763            .find_cipher_suite(server_hello.cipher_suite)
764            .ok_or_else(|| {
765                cx.common.send_fatal_alert(
766                    AlertDescription::HandshakeFailure,
767                    PeerMisbehaved::SelectedUnofferedCipherSuite,
768                )
769            })?;
770
771        if version != suite.version().version {
772            return Err({
773                cx.common.send_fatal_alert(
774                    AlertDescription::IllegalParameter,
775                    PeerMisbehaved::SelectedUnusableCipherSuiteForVersion,
776                )
777            });
778        }
779
780        match self.suite {
781            Some(prev_suite) if prev_suite != suite => {
782                return Err({
783                    cx.common.send_fatal_alert(
784                        AlertDescription::IllegalParameter,
785                        PeerMisbehaved::SelectedDifferentCipherSuiteAfterRetry,
786                    )
787                });
788            }
789            _ => {
790                debug!("Using ciphersuite {suite:?}");
791                self.suite = Some(suite);
792                cx.common.suite = Some(suite);
793            }
794        }
795
796        // Start our handshake hash, and input the server-hello.
797        let mut transcript = self
798            .transcript_buffer
799            .start_hash(suite.hash_provider());
800        transcript.add_message(&m);
801
802        let randoms = ConnectionRandoms::new(self.input.random, server_hello.random);
803        // For TLS1.3, start message encryption using
804        // handshake_traffic_secret.
805        match suite {
806            SupportedCipherSuite::Tls13(suite) => {
807                tls13::handle_server_hello(
808                    cx,
809                    server_hello,
810                    randoms,
811                    suite,
812                    transcript,
813                    self.early_data_key_schedule,
814                    // We always send a key share when TLS 1.3 is enabled.
815                    self.offered_key_share.unwrap(),
816                    &m,
817                    self.ech_state,
818                    self.input,
819                )
820            }
821            #[cfg(feature = "tls12")]
822            SupportedCipherSuite::Tls12(suite) => tls12::CompleteServerHelloHandling {
823                randoms,
824                transcript,
825                input: self.input,
826            }
827            .handle_server_hello(cx, suite, server_hello, tls13_supported),
828        }
829    }
830
831    fn into_owned(self: Box<Self>) -> NextState<'static> {
832        self
833    }
834}
835
836impl ExpectServerHelloOrHelloRetryRequest {
837    fn into_expect_server_hello(self) -> NextState<'static> {
838        Box::new(self.next)
839    }
840
841    fn handle_hello_retry_request(
842        mut self,
843        cx: &mut ClientContext<'_>,
844        m: Message<'_>,
845    ) -> NextStateOrError<'static> {
846        let hrr = require_handshake_msg!(
847            m,
848            HandshakeType::HelloRetryRequest,
849            HandshakePayload::HelloRetryRequest
850        )?;
851        trace!("Got HRR {hrr:?}");
852
853        cx.common.check_aligned_handshake()?;
854
855        // We always send a key share when TLS 1.3 is enabled.
856        let offered_key_share = self.next.offered_key_share.unwrap();
857
858        // A retry request is illegal if it contains no cookie and asks for
859        // retry of a group we already sent.
860        let config = &self.next.input.config;
861
862        if let (None, Some(req_group)) = (&hrr.cookie, hrr.key_share) {
863            let offered_hybrid = offered_key_share
864                .hybrid_component()
865                .and_then(|(group_name, _)| {
866                    config.find_kx_group(group_name, ProtocolVersion::TLSv1_3)
867                })
868                .map(|skxg| skxg.name());
869
870            if req_group == offered_key_share.group() || Some(req_group) == offered_hybrid {
871                return Err({
872                    cx.common.send_fatal_alert(
873                        AlertDescription::IllegalParameter,
874                        PeerMisbehaved::IllegalHelloRetryRequestWithOfferedGroup,
875                    )
876                });
877            }
878        }
879
880        // Or has an empty cookie.
881        if let Some(cookie) = &hrr.cookie {
882            if cookie.0.is_empty() {
883                return Err({
884                    cx.common.send_fatal_alert(
885                        AlertDescription::IllegalParameter,
886                        PeerMisbehaved::IllegalHelloRetryRequestWithEmptyCookie,
887                    )
888                });
889            }
890        }
891
892        // Or asks us to change nothing.
893        if hrr.cookie.is_none() && hrr.key_share.is_none() {
894            return Err({
895                cx.common.send_fatal_alert(
896                    AlertDescription::IllegalParameter,
897                    PeerMisbehaved::IllegalHelloRetryRequestWithNoChanges,
898                )
899            });
900        }
901
902        // Or does not echo the session_id from our ClientHello:
903        //
904        // > the HelloRetryRequest has the same format as a ServerHello message,
905        // > and the legacy_version, legacy_session_id_echo, cipher_suite, and
906        // > legacy_compression_method fields have the same meaning
907        // <https://www.rfc-editor.org/rfc/rfc8446#section-4.1.4>
908        //
909        // and
910        //
911        // > A client which receives a legacy_session_id_echo field that does not
912        // > match what it sent in the ClientHello MUST abort the handshake with an
913        // > "illegal_parameter" alert.
914        // <https://www.rfc-editor.org/rfc/rfc8446#section-4.1.3>
915        if hrr.session_id != self.next.input.session_id {
916            return Err({
917                cx.common.send_fatal_alert(
918                    AlertDescription::IllegalParameter,
919                    PeerMisbehaved::IllegalHelloRetryRequestWithWrongSessionId,
920                )
921            });
922        }
923
924        // Or asks us to talk a protocol we didn't offer, or doesn't support HRR at all.
925        match hrr.supported_versions {
926            Some(ProtocolVersion::TLSv1_3) => {
927                cx.common.negotiated_version = Some(ProtocolVersion::TLSv1_3);
928            }
929            _ => {
930                return Err({
931                    cx.common.send_fatal_alert(
932                        AlertDescription::IllegalParameter,
933                        PeerMisbehaved::IllegalHelloRetryRequestWithUnsupportedVersion,
934                    )
935                });
936            }
937        }
938
939        // Or asks us to use a ciphersuite we didn't offer.
940        let Some(cs) = config.find_cipher_suite(hrr.cipher_suite) else {
941            return Err({
942                cx.common.send_fatal_alert(
943                    AlertDescription::IllegalParameter,
944                    PeerMisbehaved::IllegalHelloRetryRequestWithUnofferedCipherSuite,
945                )
946            });
947        };
948
949        // Or offers ECH related extensions when we didn't offer ECH.
950        if cx.data.ech_status == EchStatus::NotOffered && hrr.encrypted_client_hello.is_some() {
951            return Err({
952                cx.common.send_fatal_alert(
953                    AlertDescription::UnsupportedExtension,
954                    PeerMisbehaved::IllegalHelloRetryRequestWithInvalidEch,
955                )
956            });
957        }
958
959        // HRR selects the ciphersuite.
960        cx.common.suite = Some(cs);
961        cx.common.handshake_kind = Some(HandshakeKind::FullWithHelloRetryRequest);
962
963        // If we offered ECH, we need to confirm that the server accepted it.
964        match (self.next.ech_state.as_ref(), cs.tls13()) {
965            // If the server did not confirm, then note the new ECH status but
966            // continue the handshake. We will abort with an ECH required error
967            // at the end.
968            (Some(ech_state), Some(tls13_cs))
969                if !ech_state.confirm_hrr_acceptance(hrr, tls13_cs, cx.common)? =>
970            {
971                cx.data.ech_status = EchStatus::Rejected
972            }
973            (Some(_), None) => {
974                unreachable!("ECH state should only be set when TLS 1.3 was negotiated")
975            }
976            _ => {}
977        };
978
979        // This is the draft19 change where the transcript became a tree
980        let transcript = self
981            .next
982            .transcript_buffer
983            .start_hash(cs.hash_provider());
984        let mut transcript_buffer = transcript.into_hrr_buffer();
985        transcript_buffer.add_message(&m);
986
987        // If we offered ECH and the server accepted, we also need to update the separate
988        // ECH transcript with the hello retry request message.
989        if let Some(ech_state) = self.next.ech_state.as_mut() {
990            ech_state.transcript_hrr_update(cs.hash_provider(), &m);
991        }
992
993        // Early data is not allowed after HelloRetryrequest
994        if cx.data.early_data.is_enabled() {
995            cx.data.early_data.rejected();
996        }
997
998        let key_share = match hrr.key_share {
999            Some(group) if group != offered_key_share.group() => {
1000                let Some(skxg) = config.find_kx_group(group, ProtocolVersion::TLSv1_3) else {
1001                    return Err(cx.common.send_fatal_alert(
1002                        AlertDescription::IllegalParameter,
1003                        PeerMisbehaved::IllegalHelloRetryRequestWithUnofferedNamedGroup,
1004                    ));
1005                };
1006
1007                cx.common.kx_state = KxState::Start(skxg);
1008                skxg.start()?
1009            }
1010            _ => offered_key_share,
1011        };
1012
1013        emit_client_hello_for_retry(
1014            transcript_buffer,
1015            Some(hrr),
1016            Some(key_share),
1017            self.extra_exts,
1018            Some(cs),
1019            self.next.input,
1020            cx,
1021            self.next.ech_state,
1022        )
1023    }
1024}
1025
1026impl State<ClientConnectionData> for ExpectServerHelloOrHelloRetryRequest {
1027    fn handle<'m>(
1028        self: Box<Self>,
1029        cx: &mut ClientContext<'_>,
1030        m: Message<'m>,
1031    ) -> NextStateOrError<'m>
1032    where
1033        Self: 'm,
1034    {
1035        match m.payload {
1036            MessagePayload::Handshake {
1037                parsed: HandshakeMessagePayload(HandshakePayload::ServerHello(..)),
1038                ..
1039            } => self
1040                .into_expect_server_hello()
1041                .handle(cx, m),
1042            MessagePayload::Handshake {
1043                parsed: HandshakeMessagePayload(HandshakePayload::HelloRetryRequest(..)),
1044                ..
1045            } => self.handle_hello_retry_request(cx, m),
1046            payload => Err(inappropriate_handshake_message(
1047                &payload,
1048                &[ContentType::Handshake],
1049                &[HandshakeType::ServerHello, HandshakeType::HelloRetryRequest],
1050            )),
1051        }
1052    }
1053
1054    fn into_owned(self: Box<Self>) -> NextState<'static> {
1055        self
1056    }
1057}
1058
1059fn process_cert_type_extension(
1060    common: &mut CommonState,
1061    client_expects: bool,
1062    server_negotiated: Option<CertificateType>,
1063    extension_type: ExtensionType,
1064) -> Result<Option<(ExtensionType, CertificateType)>, Error> {
1065    match (client_expects, server_negotiated) {
1066        (true, Some(CertificateType::RawPublicKey)) => {
1067            Ok(Some((extension_type, CertificateType::RawPublicKey)))
1068        }
1069        (true, _) => Err(common.send_fatal_alert(
1070            AlertDescription::HandshakeFailure,
1071            Error::PeerIncompatible(PeerIncompatible::IncorrectCertificateTypeExtension),
1072        )),
1073        (_, Some(CertificateType::RawPublicKey)) => {
1074            unreachable!("Caught by `PeerMisbehaved::UnsolicitedEncryptedExtension`")
1075        }
1076        (_, _) => Ok(None),
1077    }
1078}
1079
1080pub(super) enum ClientSessionValue {
1081    Tls13(persist::Tls13ClientSessionValue),
1082    #[cfg(feature = "tls12")]
1083    Tls12(persist::Tls12ClientSessionValue),
1084}
1085
1086impl ClientSessionValue {
1087    fn retrieve(
1088        server_name: &ServerName<'static>,
1089        config: &ClientConfig,
1090        cx: &mut ClientContext<'_>,
1091    ) -> Option<persist::Retrieved<Self>> {
1092        let found = config
1093            .resumption
1094            .store
1095            .take_tls13_ticket(server_name)
1096            .map(ClientSessionValue::Tls13)
1097            .or_else(|| {
1098                #[cfg(feature = "tls12")]
1099                {
1100                    config
1101                        .resumption
1102                        .store
1103                        .tls12_session(server_name)
1104                        .map(ClientSessionValue::Tls12)
1105                }
1106
1107                #[cfg(not(feature = "tls12"))]
1108                None
1109            })
1110            .and_then(|resuming| {
1111                resuming.compatible_config(&config.verifier, &config.client_auth_cert_resolver)
1112            })
1113            .and_then(|resuming| {
1114                let now = config
1115                    .current_time()
1116                    .map_err(|_err| debug!("Could not get current time: {_err}"))
1117                    .ok()?;
1118
1119                let retrieved = persist::Retrieved::new(resuming, now);
1120                match retrieved.has_expired() {
1121                    false => Some(retrieved),
1122                    true => None,
1123                }
1124            })
1125            .or_else(|| {
1126                debug!("No cached session for {server_name:?}");
1127                None
1128            });
1129
1130        if let Some(resuming) = &found {
1131            if cx.common.is_quic() {
1132                cx.common.quic.params = resuming
1133                    .tls13()
1134                    .map(|v| v.quic_params());
1135            }
1136        }
1137
1138        found
1139    }
1140
1141    fn common(&self) -> &persist::ClientSessionCommon {
1142        match self {
1143            Self::Tls13(inner) => &inner.common,
1144            #[cfg(feature = "tls12")]
1145            Self::Tls12(inner) => &inner.common,
1146        }
1147    }
1148
1149    fn tls13(&self) -> Option<&persist::Tls13ClientSessionValue> {
1150        match self {
1151            Self::Tls13(v) => Some(v),
1152            #[cfg(feature = "tls12")]
1153            Self::Tls12(_) => None,
1154        }
1155    }
1156
1157    fn compatible_config(
1158        self,
1159        server_cert_verifier: &Arc<dyn ServerCertVerifier>,
1160        client_creds: &Arc<dyn ResolvesClientCert>,
1161    ) -> Option<Self> {
1162        match &self {
1163            Self::Tls13(v) => v
1164                .compatible_config(server_cert_verifier, client_creds)
1165                .then_some(self),
1166            #[cfg(feature = "tls12")]
1167            Self::Tls12(v) => v
1168                .compatible_config(server_cert_verifier, client_creds)
1169                .then_some(self),
1170        }
1171    }
1172}
1173
1174impl Deref for ClientSessionValue {
1175    type Target = persist::ClientSessionCommon;
1176
1177    fn deref(&self) -> &Self::Target {
1178        self.common()
1179    }
1180}