Skip to main content

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