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