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) -> Result<(), Error> {
594    common.alpn_protocol = selected.map(ToOwned::to_owned);
595
596    if let Some(alpn_protocol) = &common.alpn_protocol {
597        if !offered_protocols.contains(alpn_protocol) {
598            return Err(common.send_fatal_alert(
599                AlertDescription::IllegalParameter,
600                PeerMisbehaved::SelectedUnofferedApplicationProtocol,
601            ));
602        }
603    }
604
605    // RFC 9001 says: "While ALPN only specifies that servers use this alert, QUIC clients MUST
606    // use error 0x0178 to terminate a connection when ALPN negotiation fails." We judge that
607    // the user intended to use ALPN (rather than some out-of-band protocol negotiation
608    // mechanism) if and only if any ALPN protocols were configured. This defends against badly-behaved
609    // servers which accept a connection that requires an application-layer protocol they do not
610    // understand.
611    if common.is_quic() && common.alpn_protocol.is_none() && !offered_protocols.is_empty() {
612        return Err(common.send_fatal_alert(
613            AlertDescription::NoApplicationProtocol,
614            Error::NoApplicationProtocol,
615        ));
616    }
617
618    debug!(
619        "ALPN protocol is {:?}",
620        common
621            .alpn_protocol
622            .as_ref()
623            .map(|v| bs_debug::BsDebug(v.as_ref()))
624    );
625    Ok(())
626}
627
628pub(super) fn process_server_cert_type_extension(
629    common: &mut CommonState,
630    config: &ClientConfig,
631    server_cert_extension: Option<&CertificateType>,
632) -> Result<Option<(ExtensionType, CertificateType)>, Error> {
633    process_cert_type_extension(
634        common,
635        config
636            .verifier
637            .requires_raw_public_keys(),
638        server_cert_extension.copied(),
639        ExtensionType::ServerCertificateType,
640    )
641}
642
643pub(super) fn process_client_cert_type_extension(
644    common: &mut CommonState,
645    config: &ClientConfig,
646    client_cert_extension: Option<&CertificateType>,
647) -> Result<Option<(ExtensionType, CertificateType)>, Error> {
648    process_cert_type_extension(
649        common,
650        config
651            .client_auth_cert_resolver
652            .only_raw_public_keys(),
653        client_cert_extension.copied(),
654        ExtensionType::ClientCertificateType,
655    )
656}
657
658impl State<ClientConnectionData> for ExpectServerHello {
659    fn handle<'m>(
660        mut self: Box<Self>,
661        cx: &mut ClientContext<'_>,
662        m: Message<'m>,
663    ) -> NextStateOrError<'m>
664    where
665        Self: 'm,
666    {
667        let server_hello =
668            require_handshake_msg!(m, HandshakeType::ServerHello, HandshakePayload::ServerHello)?;
669        trace!("We got ServerHello {server_hello:#?}");
670
671        use crate::ProtocolVersion::{TLSv1_2, TLSv1_3};
672        let config = &self.input.config;
673        let tls13_supported = config.supports_version(TLSv1_3);
674
675        let server_version = if server_hello.legacy_version == TLSv1_2 {
676            server_hello
677                .selected_version
678                .unwrap_or(server_hello.legacy_version)
679        } else {
680            server_hello.legacy_version
681        };
682
683        let version = match server_version {
684            TLSv1_3 if tls13_supported => TLSv1_3,
685            TLSv1_2 if config.supports_version(TLSv1_2) => {
686                if cx.data.early_data.is_enabled() && cx.common.early_traffic {
687                    // The client must fail with a dedicated error code if the server
688                    // responds with TLS 1.2 when offering 0-RTT.
689                    return Err(PeerMisbehaved::OfferedEarlyDataWithOldProtocolVersion.into());
690                }
691
692                if server_hello.selected_version.is_some() {
693                    return Err({
694                        cx.common.send_fatal_alert(
695                            AlertDescription::IllegalParameter,
696                            PeerMisbehaved::SelectedTls12UsingTls13VersionExtension,
697                        )
698                    });
699                }
700
701                TLSv1_2
702            }
703            _ => {
704                let reason = match server_version {
705                    TLSv1_2 | TLSv1_3 => PeerIncompatible::ServerTlsVersionIsDisabledByOurConfig,
706                    _ => PeerIncompatible::ServerDoesNotSupportTls12Or13,
707                };
708                return Err(cx
709                    .common
710                    .send_fatal_alert(AlertDescription::ProtocolVersion, reason));
711            }
712        };
713
714        if server_hello.compression_method != Compression::Null {
715            return Err({
716                cx.common.send_fatal_alert(
717                    AlertDescription::IllegalParameter,
718                    PeerMisbehaved::SelectedUnofferedCompression,
719                )
720            });
721        }
722
723        let allowed_unsolicited = [ExtensionType::RenegotiationInfo];
724        if self
725            .input
726            .hello
727            .server_sent_unsolicited_extensions(server_hello, &allowed_unsolicited)
728        {
729            return Err(cx.common.send_fatal_alert(
730                AlertDescription::UnsupportedExtension,
731                PeerMisbehaved::UnsolicitedServerHelloExtension,
732            ));
733        }
734
735        cx.common.negotiated_version = Some(version);
736
737        // Extract ALPN protocol
738        if !cx.common.is_tls13() {
739            process_alpn_protocol(
740                cx.common,
741                &self.input.hello.alpn_protocols,
742                server_hello
743                    .selected_protocol
744                    .as_ref()
745                    .map(|s| s.as_ref()),
746            )?;
747        }
748
749        // If ECPointFormats extension is supplied by the server, it must contain
750        // Uncompressed.  But it's allowed to be omitted.
751        if let Some(point_fmts) = &server_hello.ec_point_formats {
752            if !point_fmts.uncompressed {
753                return Err(cx.common.send_fatal_alert(
754                    AlertDescription::HandshakeFailure,
755                    PeerMisbehaved::ServerHelloMustOfferUncompressedEcPoints,
756                ));
757            }
758        }
759
760        let suite = config
761            .find_cipher_suite(server_hello.cipher_suite)
762            .ok_or_else(|| {
763                cx.common.send_fatal_alert(
764                    AlertDescription::HandshakeFailure,
765                    PeerMisbehaved::SelectedUnofferedCipherSuite,
766                )
767            })?;
768
769        if version != suite.version().version {
770            return Err({
771                cx.common.send_fatal_alert(
772                    AlertDescription::IllegalParameter,
773                    PeerMisbehaved::SelectedUnusableCipherSuiteForVersion,
774                )
775            });
776        }
777
778        match self.suite {
779            Some(prev_suite) if prev_suite != suite => {
780                return Err({
781                    cx.common.send_fatal_alert(
782                        AlertDescription::IllegalParameter,
783                        PeerMisbehaved::SelectedDifferentCipherSuiteAfterRetry,
784                    )
785                });
786            }
787            _ => {
788                debug!("Using ciphersuite {suite:?}");
789                self.suite = Some(suite);
790                cx.common.suite = Some(suite);
791            }
792        }
793
794        // Start our handshake hash, and input the server-hello.
795        let mut transcript = self
796            .transcript_buffer
797            .start_hash(suite.hash_provider());
798        transcript.add_message(&m);
799
800        let randoms = ConnectionRandoms::new(self.input.random, server_hello.random);
801        // For TLS1.3, start message encryption using
802        // handshake_traffic_secret.
803        match suite {
804            SupportedCipherSuite::Tls13(suite) => {
805                tls13::handle_server_hello(
806                    cx,
807                    server_hello,
808                    randoms,
809                    suite,
810                    transcript,
811                    self.early_data_key_schedule,
812                    // We always send a key share when TLS 1.3 is enabled.
813                    self.offered_key_share.unwrap(),
814                    &m,
815                    self.ech_state,
816                    self.input,
817                )
818            }
819            #[cfg(feature = "tls12")]
820            SupportedCipherSuite::Tls12(suite) => tls12::CompleteServerHelloHandling {
821                randoms,
822                transcript,
823                input: self.input,
824            }
825            .handle_server_hello(cx, suite, server_hello, tls13_supported),
826        }
827    }
828
829    fn into_owned(self: Box<Self>) -> NextState<'static> {
830        self
831    }
832}
833
834impl ExpectServerHelloOrHelloRetryRequest {
835    fn into_expect_server_hello(self) -> NextState<'static> {
836        Box::new(self.next)
837    }
838
839    fn handle_hello_retry_request(
840        mut self,
841        cx: &mut ClientContext<'_>,
842        m: Message<'_>,
843    ) -> NextStateOrError<'static> {
844        let hrr = require_handshake_msg!(
845            m,
846            HandshakeType::HelloRetryRequest,
847            HandshakePayload::HelloRetryRequest
848        )?;
849        trace!("Got HRR {hrr:?}");
850
851        cx.common.check_aligned_handshake()?;
852
853        // We always send a key share when TLS 1.3 is enabled.
854        let offered_key_share = self.next.offered_key_share.unwrap();
855
856        // A retry request is illegal if it contains no cookie and asks for
857        // retry of a group we already sent.
858        let config = &self.next.input.config;
859
860        if let (None, Some(req_group)) = (&hrr.cookie, hrr.key_share) {
861            let offered_hybrid = offered_key_share
862                .hybrid_component()
863                .and_then(|(group_name, _)| {
864                    config.find_kx_group(group_name, ProtocolVersion::TLSv1_3)
865                })
866                .map(|skxg| skxg.name());
867
868            if req_group == offered_key_share.group() || Some(req_group) == offered_hybrid {
869                return Err({
870                    cx.common.send_fatal_alert(
871                        AlertDescription::IllegalParameter,
872                        PeerMisbehaved::IllegalHelloRetryRequestWithOfferedGroup,
873                    )
874                });
875            }
876        }
877
878        // Or has an empty cookie.
879        if let Some(cookie) = &hrr.cookie {
880            if cookie.0.is_empty() {
881                return Err({
882                    cx.common.send_fatal_alert(
883                        AlertDescription::IllegalParameter,
884                        PeerMisbehaved::IllegalHelloRetryRequestWithEmptyCookie,
885                    )
886                });
887            }
888        }
889
890        // Or asks us to change nothing.
891        if hrr.cookie.is_none() && hrr.key_share.is_none() {
892            return Err({
893                cx.common.send_fatal_alert(
894                    AlertDescription::IllegalParameter,
895                    PeerMisbehaved::IllegalHelloRetryRequestWithNoChanges,
896                )
897            });
898        }
899
900        // Or does not echo the session_id from our ClientHello:
901        //
902        // > the HelloRetryRequest has the same format as a ServerHello message,
903        // > and the legacy_version, legacy_session_id_echo, cipher_suite, and
904        // > legacy_compression_method fields have the same meaning
905        // <https://www.rfc-editor.org/rfc/rfc8446#section-4.1.4>
906        //
907        // and
908        //
909        // > A client which receives a legacy_session_id_echo field that does not
910        // > match what it sent in the ClientHello MUST abort the handshake with an
911        // > "illegal_parameter" alert.
912        // <https://www.rfc-editor.org/rfc/rfc8446#section-4.1.3>
913        if hrr.session_id != self.next.input.session_id {
914            return Err({
915                cx.common.send_fatal_alert(
916                    AlertDescription::IllegalParameter,
917                    PeerMisbehaved::IllegalHelloRetryRequestWithWrongSessionId,
918                )
919            });
920        }
921
922        // Or asks us to talk a protocol we didn't offer, or doesn't support HRR at all.
923        match hrr.supported_versions {
924            Some(ProtocolVersion::TLSv1_3) => {
925                cx.common.negotiated_version = Some(ProtocolVersion::TLSv1_3);
926            }
927            _ => {
928                return Err({
929                    cx.common.send_fatal_alert(
930                        AlertDescription::IllegalParameter,
931                        PeerMisbehaved::IllegalHelloRetryRequestWithUnsupportedVersion,
932                    )
933                });
934            }
935        }
936
937        // Or asks us to use a ciphersuite we didn't offer.
938        let Some(cs) = config.find_cipher_suite(hrr.cipher_suite) else {
939            return Err({
940                cx.common.send_fatal_alert(
941                    AlertDescription::IllegalParameter,
942                    PeerMisbehaved::IllegalHelloRetryRequestWithUnofferedCipherSuite,
943                )
944            });
945        };
946
947        // Or offers ECH related extensions when we didn't offer ECH.
948        if cx.data.ech_status == EchStatus::NotOffered && hrr.encrypted_client_hello.is_some() {
949            return Err({
950                cx.common.send_fatal_alert(
951                    AlertDescription::UnsupportedExtension,
952                    PeerMisbehaved::IllegalHelloRetryRequestWithInvalidEch,
953                )
954            });
955        }
956
957        // HRR selects the ciphersuite.
958        cx.common.suite = Some(cs);
959        cx.common.handshake_kind = Some(HandshakeKind::FullWithHelloRetryRequest);
960
961        // If we offered ECH, we need to confirm that the server accepted it.
962        match (self.next.ech_state.as_ref(), cs.tls13()) {
963            (Some(ech_state), Some(tls13_cs)) => {
964                if !ech_state.confirm_hrr_acceptance(hrr, tls13_cs, cx.common)? {
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                    cx.data.ech_status = EchStatus::Rejected;
969                }
970            }
971            (Some(_), None) => {
972                unreachable!("ECH state should only be set when TLS 1.3 was negotiated")
973            }
974            _ => {}
975        };
976
977        // This is the draft19 change where the transcript became a tree
978        let transcript = self
979            .next
980            .transcript_buffer
981            .start_hash(cs.hash_provider());
982        let mut transcript_buffer = transcript.into_hrr_buffer();
983        transcript_buffer.add_message(&m);
984
985        // If we offered ECH and the server accepted, we also need to update the separate
986        // ECH transcript with the hello retry request message.
987        if let Some(ech_state) = self.next.ech_state.as_mut() {
988            ech_state.transcript_hrr_update(cs.hash_provider(), &m);
989        }
990
991        // Early data is not allowed after HelloRetryrequest
992        if cx.data.early_data.is_enabled() {
993            cx.data.early_data.rejected();
994        }
995
996        let key_share = match hrr.key_share {
997            Some(group) if group != offered_key_share.group() => {
998                let Some(skxg) = config.find_kx_group(group, ProtocolVersion::TLSv1_3) else {
999                    return Err(cx.common.send_fatal_alert(
1000                        AlertDescription::IllegalParameter,
1001                        PeerMisbehaved::IllegalHelloRetryRequestWithUnofferedNamedGroup,
1002                    ));
1003                };
1004
1005                cx.common.kx_state = KxState::Start(skxg);
1006                skxg.start()?
1007            }
1008            _ => offered_key_share,
1009        };
1010
1011        emit_client_hello_for_retry(
1012            transcript_buffer,
1013            Some(hrr),
1014            Some(key_share),
1015            self.extra_exts,
1016            Some(cs),
1017            self.next.input,
1018            cx,
1019            self.next.ech_state,
1020        )
1021    }
1022}
1023
1024impl State<ClientConnectionData> for ExpectServerHelloOrHelloRetryRequest {
1025    fn handle<'m>(
1026        self: Box<Self>,
1027        cx: &mut ClientContext<'_>,
1028        m: Message<'m>,
1029    ) -> NextStateOrError<'m>
1030    where
1031        Self: 'm,
1032    {
1033        match m.payload {
1034            MessagePayload::Handshake {
1035                parsed: HandshakeMessagePayload(HandshakePayload::ServerHello(..)),
1036                ..
1037            } => self
1038                .into_expect_server_hello()
1039                .handle(cx, m),
1040            MessagePayload::Handshake {
1041                parsed: HandshakeMessagePayload(HandshakePayload::HelloRetryRequest(..)),
1042                ..
1043            } => self.handle_hello_retry_request(cx, m),
1044            payload => Err(inappropriate_handshake_message(
1045                &payload,
1046                &[ContentType::Handshake],
1047                &[HandshakeType::ServerHello, HandshakeType::HelloRetryRequest],
1048            )),
1049        }
1050    }
1051
1052    fn into_owned(self: Box<Self>) -> NextState<'static> {
1053        self
1054    }
1055}
1056
1057fn process_cert_type_extension(
1058    common: &mut CommonState,
1059    client_expects: bool,
1060    server_negotiated: Option<CertificateType>,
1061    extension_type: ExtensionType,
1062) -> Result<Option<(ExtensionType, CertificateType)>, Error> {
1063    match (client_expects, server_negotiated) {
1064        (true, Some(CertificateType::RawPublicKey)) => {
1065            Ok(Some((extension_type, CertificateType::RawPublicKey)))
1066        }
1067        (true, _) => Err(common.send_fatal_alert(
1068            AlertDescription::HandshakeFailure,
1069            Error::PeerIncompatible(PeerIncompatible::IncorrectCertificateTypeExtension),
1070        )),
1071        (_, Some(CertificateType::RawPublicKey)) => {
1072            unreachable!("Caught by `PeerMisbehaved::UnsolicitedEncryptedExtension`")
1073        }
1074        (_, _) => Ok(None),
1075    }
1076}
1077
1078pub(super) enum ClientSessionValue {
1079    Tls13(persist::Tls13ClientSessionValue),
1080    #[cfg(feature = "tls12")]
1081    Tls12(persist::Tls12ClientSessionValue),
1082}
1083
1084impl ClientSessionValue {
1085    fn retrieve(
1086        server_name: &ServerName<'static>,
1087        config: &ClientConfig,
1088        cx: &mut ClientContext<'_>,
1089    ) -> Option<persist::Retrieved<Self>> {
1090        let found = config
1091            .resumption
1092            .store
1093            .take_tls13_ticket(server_name)
1094            .map(ClientSessionValue::Tls13)
1095            .or_else(|| {
1096                #[cfg(feature = "tls12")]
1097                {
1098                    config
1099                        .resumption
1100                        .store
1101                        .tls12_session(server_name)
1102                        .map(ClientSessionValue::Tls12)
1103                }
1104
1105                #[cfg(not(feature = "tls12"))]
1106                None
1107            })
1108            .and_then(|resuming| {
1109                resuming.compatible_config(&config.verifier, &config.client_auth_cert_resolver)
1110            })
1111            .and_then(|resuming| {
1112                let now = config
1113                    .current_time()
1114                    .map_err(|_err| debug!("Could not get current time: {_err}"))
1115                    .ok()?;
1116
1117                let retrieved = persist::Retrieved::new(resuming, now);
1118                match retrieved.has_expired() {
1119                    false => Some(retrieved),
1120                    true => None,
1121                }
1122            })
1123            .or_else(|| {
1124                debug!("No cached session for {server_name:?}");
1125                None
1126            });
1127
1128        if let Some(resuming) = &found {
1129            if cx.common.is_quic() {
1130                cx.common.quic.params = resuming
1131                    .tls13()
1132                    .map(|v| v.quic_params());
1133            }
1134        }
1135
1136        found
1137    }
1138
1139    fn common(&self) -> &persist::ClientSessionCommon {
1140        match self {
1141            Self::Tls13(inner) => &inner.common,
1142            #[cfg(feature = "tls12")]
1143            Self::Tls12(inner) => &inner.common,
1144        }
1145    }
1146
1147    fn tls13(&self) -> Option<&persist::Tls13ClientSessionValue> {
1148        match self {
1149            Self::Tls13(v) => Some(v),
1150            #[cfg(feature = "tls12")]
1151            Self::Tls12(_) => None,
1152        }
1153    }
1154
1155    fn compatible_config(
1156        self,
1157        server_cert_verifier: &Arc<dyn ServerCertVerifier>,
1158        client_creds: &Arc<dyn ResolvesClientCert>,
1159    ) -> Option<Self> {
1160        match &self {
1161            Self::Tls13(v) => v
1162                .compatible_config(server_cert_verifier, client_creds)
1163                .then_some(self),
1164            #[cfg(feature = "tls12")]
1165            Self::Tls12(v) => v
1166                .compatible_config(server_cert_verifier, client_creds)
1167                .then_some(self),
1168        }
1169    }
1170}
1171
1172impl Deref for ClientSessionValue {
1173    type Target = persist::ClientSessionCommon;
1174
1175    fn deref(&self) -> &Self::Target {
1176        self.common()
1177    }
1178}