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