rustls/client/
hs.rs

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