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 key_share = KeyShareEntry::new(key_share.group(), key_share.pub_key());
308        exts.push(ClientExtension::KeyShare(vec![key_share]));
309    }
310
311    if let Some(cookie) = retryreq.and_then(HelloRetryRequest::cookie) {
312        exts.push(ClientExtension::Cookie(cookie.clone()));
313    }
314
315    if support_tls13 {
316        // We could support PSK_KE here too. Such connections don't
317        // have forward secrecy, and are similar to TLS1.2 resumption.
318        let psk_modes = vec![PSKKeyExchangeMode::PSK_DHE_KE];
319        exts.push(ClientExtension::PresharedKeyModes(psk_modes));
320    }
321
322    if !config.alpn_protocols.is_empty() {
323        exts.push(ClientExtension::Protocols(Vec::from_slices(
324            &config
325                .alpn_protocols
326                .iter()
327                .map(|proto| &proto[..])
328                .collect::<Vec<_>>(),
329        )));
330    }
331
332    input.hello.offered_cert_compression = if support_tls13 && !config.cert_decompressors.is_empty()
333    {
334        exts.push(ClientExtension::CertificateCompressionAlgorithms(
335            config
336                .cert_decompressors
337                .iter()
338                .map(|dec| dec.algorithm())
339                .collect(),
340        ));
341        true
342    } else {
343        false
344    };
345
346    if config
347        .client_auth_cert_resolver
348        .only_raw_public_keys()
349    {
350        exts.push(ClientExtension::ClientCertTypes(vec![
351            CertificateType::RawPublicKey,
352        ]));
353    }
354
355    if config
356        .verifier
357        .requires_raw_public_keys()
358    {
359        exts.push(ClientExtension::ServerCertTypes(vec![
360            CertificateType::RawPublicKey,
361        ]));
362    }
363
364    // Extra extensions must be placed before the PSK extension
365    exts.extend(extra_exts.iter().cloned());
366
367    // If this is a second client hello we're constructing in response to an HRR, and
368    // we've rejected ECH or sent GREASE ECH, then we need to carry forward the
369    // exact same ECH extension we used in the first hello.
370    if matches!(cx.data.ech_status, EchStatus::Rejected | EchStatus::Grease) & retryreq.is_some() {
371        if let Some(prev_ech_ext) = input.prev_ech_ext.take() {
372            exts.push(prev_ech_ext);
373        }
374    }
375
376    // Do we have a SessionID or ticket cached for this host?
377    let tls13_session = prepare_resumption(&input.resuming, &mut exts, suite, cx, config);
378
379    // Extensions MAY be randomized
380    // but they also need to keep the same order as the previous ClientHello
381    exts.sort_by_cached_key(|new_ext| {
382        match (&cx.data.ech_status, new_ext) {
383            // When not offering ECH/GREASE, the PSK extension is always last.
384            (EchStatus::NotOffered, ClientExtension::PresharedKey(..)) => return u32::MAX,
385            // When ECH or GREASE are in-play, the ECH extension is always last.
386            (_, ClientExtension::EncryptedClientHello(_)) => return u32::MAX,
387            // ... and the PSK extension should be second-to-last.
388            (_, ClientExtension::PresharedKey(..)) => return u32::MAX - 1,
389            _ => {}
390        };
391
392        let seed = (input.hello.extension_order_seed as u32) << 16
393            | (u16::from(new_ext.ext_type()) as u32);
394        match low_quality_integer_hash(seed) {
395            u32::MAX => 0,
396            key => key,
397        }
398    });
399
400    let mut cipher_suites: Vec<_> = config
401        .provider
402        .cipher_suites
403        .iter()
404        .filter_map(|cs| match cs.usable_for_protocol(cx.common.protocol) {
405            true => Some(cs.suite()),
406            false => None,
407        })
408        .collect();
409    // We don't do renegotiation at all, in fact.
410    cipher_suites.push(CipherSuite::TLS_EMPTY_RENEGOTIATION_INFO_SCSV);
411
412    let mut chp_payload = ClientHelloPayload {
413        client_version: ProtocolVersion::TLSv1_2,
414        random: input.random,
415        session_id: input.session_id,
416        cipher_suites,
417        compression_methods: vec![Compression::Null],
418        extensions: exts,
419    };
420
421    let ech_grease_ext = config
422        .ech_mode
423        .as_ref()
424        .and_then(|mode| match mode {
425            EchMode::Grease(cfg) => Some(cfg.grease_ext(
426                config.provider.secure_random,
427                input.server_name.clone(),
428                &chp_payload,
429            )),
430            _ => None,
431        });
432
433    match (cx.data.ech_status, &mut ech_state) {
434        // If we haven't offered ECH, or have offered ECH but got a non-rejecting HRR, then
435        // we need to replace the client hello payload with an ECH client hello payload.
436        (EchStatus::NotOffered | EchStatus::Offered, Some(ech_state)) => {
437            // Replace the client hello payload with an ECH client hello payload.
438            chp_payload = ech_state.ech_hello(chp_payload, retryreq, &tls13_session)?;
439            cx.data.ech_status = EchStatus::Offered;
440            // Store the ECH extension in case we need to carry it forward in a subsequent hello.
441            input.prev_ech_ext = chp_payload.extensions.last().cloned();
442        }
443        // If we haven't offered ECH, and have no ECH state, then consider whether to use GREASE
444        // ECH.
445        (EchStatus::NotOffered, None) => {
446            if let Some(grease_ext) = ech_grease_ext {
447                // Add the GREASE ECH extension.
448                let grease_ext = grease_ext?;
449                chp_payload
450                    .extensions
451                    .push(grease_ext.clone());
452                cx.data.ech_status = EchStatus::Grease;
453                // Store the GREASE ECH extension in case we need to carry it forward in a
454                // subsequent hello.
455                input.prev_ech_ext = Some(grease_ext);
456            }
457        }
458        _ => {}
459    }
460
461    // Note what extensions we sent.
462    input.hello.sent_extensions = chp_payload
463        .extensions
464        .iter()
465        .map(ClientExtension::ext_type)
466        .collect();
467
468    let mut chp = HandshakeMessagePayload {
469        typ: HandshakeType::ClientHello,
470        payload: HandshakePayload::ClientHello(chp_payload),
471    };
472
473    let early_key_schedule = match (ech_state.as_mut(), tls13_session) {
474        // If we're performing ECH and resuming, then the PSK binder will have been dealt with
475        // separately, and we need to take the early_data_key_schedule computed for the inner hello.
476        (Some(ech_state), Some(tls13_session)) => ech_state
477            .early_data_key_schedule
478            .take()
479            .map(|schedule| (tls13_session.suite(), schedule)),
480
481        // When we're not doing ECH and resuming, then the PSK binder need to be filled in as
482        // normal.
483        (_, Some(tls13_session)) => Some((
484            tls13_session.suite(),
485            tls13::fill_in_psk_binder(&tls13_session, &transcript_buffer, &mut chp),
486        )),
487
488        // No early key schedule in other cases.
489        _ => None,
490    };
491
492    let ch = Message {
493        version: match retryreq {
494            // <https://datatracker.ietf.org/doc/html/rfc8446#section-5.1>:
495            // "This value MUST be set to 0x0303 for all records generated
496            //  by a TLS 1.3 implementation ..."
497            Some(_) => ProtocolVersion::TLSv1_2,
498            // "... other than an initial ClientHello (i.e., one not
499            // generated after a HelloRetryRequest), where it MAY also be
500            // 0x0301 for compatibility purposes"
501            //
502            // (retryreq == None means we're in the "initial ClientHello" case)
503            None => ProtocolVersion::TLSv1_0,
504        },
505        payload: MessagePayload::handshake(chp),
506    };
507
508    if retryreq.is_some() {
509        // send dummy CCS to fool middleboxes prior
510        // to second client hello
511        tls13::emit_fake_ccs(&mut input.sent_tls13_fake_ccs, cx.common);
512    }
513
514    trace!("Sending ClientHello {:#?}", ch);
515
516    transcript_buffer.add_message(&ch);
517    cx.common.send_msg(ch, false);
518
519    // Calculate the hash of ClientHello and use it to derive EarlyTrafficSecret
520    let early_key_schedule = early_key_schedule.map(|(resuming_suite, schedule)| {
521        if !cx.data.early_data.is_enabled() {
522            return schedule;
523        }
524
525        let (transcript_buffer, random) = match &ech_state {
526            // When using ECH the early data key schedule is derived based on the inner
527            // hello transcript and random.
528            Some(ech_state) => (
529                &ech_state.inner_hello_transcript,
530                &ech_state.inner_hello_random.0,
531            ),
532            None => (&transcript_buffer, &input.random.0),
533        };
534
535        tls13::derive_early_traffic_secret(
536            &*config.key_log,
537            cx,
538            resuming_suite,
539            &schedule,
540            &mut input.sent_tls13_fake_ccs,
541            transcript_buffer,
542            random,
543        );
544        schedule
545    });
546
547    let next = ExpectServerHello {
548        input,
549        transcript_buffer,
550        early_key_schedule,
551        offered_key_share: key_share,
552        suite,
553        ech_state,
554    };
555
556    Ok(if support_tls13 && retryreq.is_none() {
557        Box::new(ExpectServerHelloOrHelloRetryRequest { next, extra_exts })
558    } else {
559        Box::new(next)
560    })
561}
562
563/// Prepare resumption with the session state retrieved from storage.
564///
565/// This function will push onto `exts` to
566///
567/// (a) request a new ticket if we don't have one,
568/// (b) send our TLS 1.2 ticket after retrieving an 1.2 session,
569/// (c) send a request for 1.3 early data if allowed and
570/// (d) send a 1.3 preshared key if we have one.
571///
572/// For resumption to work, the currently negotiated cipher suite (if available) must be
573/// able to resume from the resuming session's cipher suite.
574///
575/// If 1.3 resumption can continue, returns the 1.3 session value for further processing.
576fn prepare_resumption<'a>(
577    resuming: &'a Option<persist::Retrieved<ClientSessionValue>>,
578    exts: &mut Vec<ClientExtension>,
579    suite: Option<SupportedCipherSuite>,
580    cx: &mut ClientContext<'_>,
581    config: &ClientConfig,
582) -> Option<persist::Retrieved<&'a persist::Tls13ClientSessionValue>> {
583    // Check whether we're resuming with a non-empty ticket.
584    let resuming = match resuming {
585        Some(resuming) if !resuming.ticket().is_empty() => resuming,
586        _ => {
587            if config.supports_version(ProtocolVersion::TLSv1_3)
588                || config.resumption.tls12_resumption == Tls12Resumption::SessionIdOrTickets
589            {
590                // If we don't have a ticket, request one.
591                exts.push(ClientExtension::SessionTicket(ClientSessionTicket::Request));
592            }
593            return None;
594        }
595    };
596
597    let tls13 = match resuming.map(|csv| csv.tls13()) {
598        Some(tls13) => tls13,
599        None => {
600            // TLS 1.2; send the ticket if we have support this protocol version
601            if config.supports_version(ProtocolVersion::TLSv1_2)
602                && config.resumption.tls12_resumption == Tls12Resumption::SessionIdOrTickets
603            {
604                exts.push(ClientExtension::SessionTicket(ClientSessionTicket::Offer(
605                    Payload::new(resuming.ticket()),
606                )));
607            }
608            return None; // TLS 1.2, so nothing to return here
609        }
610    };
611
612    if !config.supports_version(ProtocolVersion::TLSv1_3) {
613        return None;
614    }
615
616    // If the server selected TLS 1.2, we can't resume.
617    let suite = match suite {
618        Some(SupportedCipherSuite::Tls13(suite)) => Some(suite),
619        #[cfg(feature = "tls12")]
620        Some(SupportedCipherSuite::Tls12(_)) => return None,
621        None => None,
622    };
623
624    // If the selected cipher suite can't select from the session's, we can't resume.
625    if let Some(suite) = suite {
626        suite.can_resume_from(tls13.suite())?;
627    }
628
629    tls13::prepare_resumption(config, cx, &tls13, exts, suite.is_some());
630    Some(tls13)
631}
632
633pub(super) fn process_alpn_protocol(
634    common: &mut CommonState,
635    config: &ClientConfig,
636    proto: Option<&[u8]>,
637) -> Result<(), Error> {
638    common.alpn_protocol = proto.map(ToOwned::to_owned);
639
640    if let Some(alpn_protocol) = &common.alpn_protocol {
641        if !config
642            .alpn_protocols
643            .contains(alpn_protocol)
644        {
645            return Err(common.send_fatal_alert(
646                AlertDescription::IllegalParameter,
647                PeerMisbehaved::SelectedUnofferedApplicationProtocol,
648            ));
649        }
650    }
651
652    // RFC 9001 says: "While ALPN only specifies that servers use this alert, QUIC clients MUST
653    // use error 0x0178 to terminate a connection when ALPN negotiation fails." We judge that
654    // the user intended to use ALPN (rather than some out-of-band protocol negotiation
655    // mechanism) if and only if any ALPN protocols were configured. This defends against badly-behaved
656    // servers which accept a connection that requires an application-layer protocol they do not
657    // understand.
658    if common.is_quic() && common.alpn_protocol.is_none() && !config.alpn_protocols.is_empty() {
659        return Err(common.send_fatal_alert(
660            AlertDescription::NoApplicationProtocol,
661            Error::NoApplicationProtocol,
662        ));
663    }
664
665    debug!(
666        "ALPN protocol is {:?}",
667        common
668            .alpn_protocol
669            .as_ref()
670            .map(|v| bs_debug::BsDebug(v))
671    );
672    Ok(())
673}
674
675pub(super) fn process_server_cert_type_extension(
676    common: &mut CommonState,
677    config: &ClientConfig,
678    server_cert_extension: Option<&CertificateType>,
679) -> Result<(), Error> {
680    let requires_server_rpk = config
681        .verifier
682        .requires_raw_public_keys();
683    let server_offers_rpk = matches!(server_cert_extension, Some(CertificateType::RawPublicKey));
684
685    let raw_key_negotation_params = RawKeyNegotiationParams {
686        peer_supports_raw_key: server_offers_rpk,
687        local_expects_raw_key: requires_server_rpk,
688        extension_type: ExtensionType::ServerCertificateType,
689    };
690    match raw_key_negotation_params.validate_raw_key_negotiation() {
691        RawKeyNegotationResult::Err(err) => {
692            Err(common.send_fatal_alert(AlertDescription::HandshakeFailure, err))
693        }
694        _ => Ok(()),
695    }
696}
697
698pub(super) fn process_client_cert_type_extension(
699    common: &mut CommonState,
700    config: &ClientConfig,
701    client_cert_extension: Option<&CertificateType>,
702) -> Result<(), Error> {
703    let requires_client_rpk = config
704        .client_auth_cert_resolver
705        .only_raw_public_keys();
706    let server_allows_rpk = matches!(client_cert_extension, Some(CertificateType::RawPublicKey));
707
708    let raw_key_negotation_params = RawKeyNegotiationParams {
709        peer_supports_raw_key: server_allows_rpk,
710        local_expects_raw_key: requires_client_rpk,
711        extension_type: ExtensionType::ClientCertificateType,
712    };
713    match raw_key_negotation_params.validate_raw_key_negotiation() {
714        RawKeyNegotationResult::Err(err) => {
715            Err(common.send_fatal_alert(AlertDescription::HandshakeFailure, err))
716        }
717        _ => Ok(()),
718    }
719}
720
721impl State<ClientConnectionData> for ExpectServerHello {
722    fn handle<'m>(
723        mut self: Box<Self>,
724        cx: &mut ClientContext<'_>,
725        m: Message<'m>,
726    ) -> NextStateOrError<'m>
727    where
728        Self: 'm,
729    {
730        let server_hello =
731            require_handshake_msg!(m, HandshakeType::ServerHello, HandshakePayload::ServerHello)?;
732        trace!("We got ServerHello {:#?}", server_hello);
733
734        use crate::ProtocolVersion::{TLSv1_2, TLSv1_3};
735        let config = &self.input.config;
736        let tls13_supported = config.supports_version(TLSv1_3);
737
738        let server_version = if server_hello.legacy_version == TLSv1_2 {
739            server_hello
740                .supported_versions()
741                .unwrap_or(server_hello.legacy_version)
742        } else {
743            server_hello.legacy_version
744        };
745
746        let version = match server_version {
747            TLSv1_3 if tls13_supported => TLSv1_3,
748            TLSv1_2 if config.supports_version(TLSv1_2) => {
749                if cx.data.early_data.is_enabled() && cx.common.early_traffic {
750                    // The client must fail with a dedicated error code if the server
751                    // responds with TLS 1.2 when offering 0-RTT.
752                    return Err(PeerMisbehaved::OfferedEarlyDataWithOldProtocolVersion.into());
753                }
754
755                if server_hello
756                    .supported_versions()
757                    .is_some()
758                {
759                    return Err({
760                        cx.common.send_fatal_alert(
761                            AlertDescription::IllegalParameter,
762                            PeerMisbehaved::SelectedTls12UsingTls13VersionExtension,
763                        )
764                    });
765                }
766
767                TLSv1_2
768            }
769            _ => {
770                let reason = match server_version {
771                    TLSv1_2 | TLSv1_3 => PeerIncompatible::ServerTlsVersionIsDisabledByOurConfig,
772                    _ => PeerIncompatible::ServerDoesNotSupportTls12Or13,
773                };
774                return Err(cx
775                    .common
776                    .send_fatal_alert(AlertDescription::ProtocolVersion, reason));
777            }
778        };
779
780        if server_hello.compression_method != Compression::Null {
781            return Err({
782                cx.common.send_fatal_alert(
783                    AlertDescription::IllegalParameter,
784                    PeerMisbehaved::SelectedUnofferedCompression,
785                )
786            });
787        }
788
789        if server_hello.has_duplicate_extension() {
790            return Err(cx.common.send_fatal_alert(
791                AlertDescription::DecodeError,
792                PeerMisbehaved::DuplicateServerHelloExtensions,
793            ));
794        }
795
796        let allowed_unsolicited = [ExtensionType::RenegotiationInfo];
797        if self
798            .input
799            .hello
800            .server_sent_unsolicited_extensions(&server_hello.extensions, &allowed_unsolicited)
801        {
802            return Err(cx.common.send_fatal_alert(
803                AlertDescription::UnsupportedExtension,
804                PeerMisbehaved::UnsolicitedServerHelloExtension,
805            ));
806        }
807
808        cx.common.negotiated_version = Some(version);
809
810        // Extract ALPN protocol
811        if !cx.common.is_tls13() {
812            process_alpn_protocol(cx.common, config, server_hello.alpn_protocol())?;
813        }
814
815        // If ECPointFormats extension is supplied by the server, it must contain
816        // Uncompressed.  But it's allowed to be omitted.
817        if let Some(point_fmts) = server_hello.ecpoints_extension() {
818            if !point_fmts.contains(&ECPointFormat::Uncompressed) {
819                return Err(cx.common.send_fatal_alert(
820                    AlertDescription::HandshakeFailure,
821                    PeerMisbehaved::ServerHelloMustOfferUncompressedEcPoints,
822                ));
823            }
824        }
825
826        let suite = config
827            .find_cipher_suite(server_hello.cipher_suite)
828            .ok_or_else(|| {
829                cx.common.send_fatal_alert(
830                    AlertDescription::HandshakeFailure,
831                    PeerMisbehaved::SelectedUnofferedCipherSuite,
832                )
833            })?;
834
835        if version != suite.version().version {
836            return Err({
837                cx.common.send_fatal_alert(
838                    AlertDescription::IllegalParameter,
839                    PeerMisbehaved::SelectedUnusableCipherSuiteForVersion,
840                )
841            });
842        }
843
844        match self.suite {
845            Some(prev_suite) if prev_suite != suite => {
846                return Err({
847                    cx.common.send_fatal_alert(
848                        AlertDescription::IllegalParameter,
849                        PeerMisbehaved::SelectedDifferentCipherSuiteAfterRetry,
850                    )
851                });
852            }
853            _ => {
854                debug!("Using ciphersuite {:?}", suite);
855                self.suite = Some(suite);
856                cx.common.suite = Some(suite);
857            }
858        }
859
860        // Start our handshake hash, and input the server-hello.
861        let mut transcript = self
862            .transcript_buffer
863            .start_hash(suite.hash_provider());
864        transcript.add_message(&m);
865
866        let randoms = ConnectionRandoms::new(self.input.random, server_hello.random);
867        // For TLS1.3, start message encryption using
868        // handshake_traffic_secret.
869        match suite {
870            SupportedCipherSuite::Tls13(suite) => {
871                #[allow(clippy::bind_instead_of_map)]
872                let resuming_session = self
873                    .input
874                    .resuming
875                    .and_then(|resuming| match resuming.value {
876                        ClientSessionValue::Tls13(inner) => Some(inner),
877                        #[cfg(feature = "tls12")]
878                        ClientSessionValue::Tls12(_) => None,
879                    });
880
881                tls13::handle_server_hello(
882                    self.input.config,
883                    cx,
884                    server_hello,
885                    resuming_session,
886                    self.input.server_name,
887                    randoms,
888                    suite,
889                    transcript,
890                    self.early_key_schedule,
891                    self.input.hello,
892                    // We always send a key share when TLS 1.3 is enabled.
893                    self.offered_key_share.unwrap(),
894                    self.input.sent_tls13_fake_ccs,
895                    &m,
896                    self.ech_state,
897                )
898            }
899            #[cfg(feature = "tls12")]
900            SupportedCipherSuite::Tls12(suite) => {
901                let resuming_session = self
902                    .input
903                    .resuming
904                    .and_then(|resuming| match resuming.value {
905                        ClientSessionValue::Tls12(inner) => Some(inner),
906                        ClientSessionValue::Tls13(_) => None,
907                    });
908
909                tls12::CompleteServerHelloHandling {
910                    config: self.input.config,
911                    resuming_session,
912                    server_name: self.input.server_name,
913                    randoms,
914                    using_ems: self.input.using_ems,
915                    transcript,
916                }
917                .handle_server_hello(cx, suite, server_hello, tls13_supported)
918            }
919        }
920    }
921
922    fn into_owned(self: Box<Self>) -> NextState<'static> {
923        self
924    }
925}
926
927impl ExpectServerHelloOrHelloRetryRequest {
928    fn into_expect_server_hello(self) -> NextState<'static> {
929        Box::new(self.next)
930    }
931
932    fn handle_hello_retry_request(
933        mut self,
934        cx: &mut ClientContext<'_>,
935        m: Message<'_>,
936    ) -> NextStateOrError<'static> {
937        let hrr = require_handshake_msg!(
938            m,
939            HandshakeType::HelloRetryRequest,
940            HandshakePayload::HelloRetryRequest
941        )?;
942        trace!("Got HRR {:?}", hrr);
943
944        cx.common.check_aligned_handshake()?;
945
946        let cookie = hrr.cookie();
947        let req_group = hrr.requested_key_share_group();
948
949        // We always send a key share when TLS 1.3 is enabled.
950        let offered_key_share = self.next.offered_key_share.unwrap();
951
952        // A retry request is illegal if it contains no cookie and asks for
953        // retry of a group we already sent.
954        if cookie.is_none() && req_group == Some(offered_key_share.group()) {
955            return Err({
956                cx.common.send_fatal_alert(
957                    AlertDescription::IllegalParameter,
958                    PeerMisbehaved::IllegalHelloRetryRequestWithOfferedGroup,
959                )
960            });
961        }
962
963        // Or has an empty cookie.
964        if let Some(cookie) = cookie {
965            if cookie.0.is_empty() {
966                return Err({
967                    cx.common.send_fatal_alert(
968                        AlertDescription::IllegalParameter,
969                        PeerMisbehaved::IllegalHelloRetryRequestWithEmptyCookie,
970                    )
971                });
972            }
973        }
974
975        // Or has something unrecognised
976        if hrr.has_unknown_extension() {
977            return Err(cx.common.send_fatal_alert(
978                AlertDescription::UnsupportedExtension,
979                PeerIncompatible::ServerSentHelloRetryRequestWithUnknownExtension,
980            ));
981        }
982
983        // Or has the same extensions more than once
984        if hrr.has_duplicate_extension() {
985            return Err({
986                cx.common.send_fatal_alert(
987                    AlertDescription::IllegalParameter,
988                    PeerMisbehaved::DuplicateHelloRetryRequestExtensions,
989                )
990            });
991        }
992
993        // Or asks us to change nothing.
994        if cookie.is_none() && req_group.is_none() {
995            return Err({
996                cx.common.send_fatal_alert(
997                    AlertDescription::IllegalParameter,
998                    PeerMisbehaved::IllegalHelloRetryRequestWithNoChanges,
999                )
1000            });
1001        }
1002
1003        // Or does not echo the session_id from our ClientHello:
1004        //
1005        // > the HelloRetryRequest has the same format as a ServerHello message,
1006        // > and the legacy_version, legacy_session_id_echo, cipher_suite, and
1007        // > legacy_compression_method fields have the same meaning
1008        // <https://www.rfc-editor.org/rfc/rfc8446#section-4.1.4>
1009        //
1010        // and
1011        //
1012        // > A client which receives a legacy_session_id_echo field that does not
1013        // > match what it sent in the ClientHello MUST abort the handshake with an
1014        // > "illegal_parameter" alert.
1015        // <https://www.rfc-editor.org/rfc/rfc8446#section-4.1.3>
1016        if hrr.session_id != self.next.input.session_id {
1017            return Err({
1018                cx.common.send_fatal_alert(
1019                    AlertDescription::IllegalParameter,
1020                    PeerMisbehaved::IllegalHelloRetryRequestWithWrongSessionId,
1021                )
1022            });
1023        }
1024
1025        // Or asks us to talk a protocol we didn't offer, or doesn't support HRR at all.
1026        match hrr.supported_versions() {
1027            Some(ProtocolVersion::TLSv1_3) => {
1028                cx.common.negotiated_version = Some(ProtocolVersion::TLSv1_3);
1029            }
1030            _ => {
1031                return Err({
1032                    cx.common.send_fatal_alert(
1033                        AlertDescription::IllegalParameter,
1034                        PeerMisbehaved::IllegalHelloRetryRequestWithUnsupportedVersion,
1035                    )
1036                });
1037            }
1038        }
1039
1040        // Or asks us to use a ciphersuite we didn't offer.
1041        let config = &self.next.input.config;
1042        let cs = match config.find_cipher_suite(hrr.cipher_suite) {
1043            Some(cs) => cs,
1044            None => {
1045                return Err({
1046                    cx.common.send_fatal_alert(
1047                        AlertDescription::IllegalParameter,
1048                        PeerMisbehaved::IllegalHelloRetryRequestWithUnofferedCipherSuite,
1049                    )
1050                });
1051            }
1052        };
1053
1054        // Or offers ECH related extensions when we didn't offer ECH.
1055        if cx.data.ech_status == EchStatus::NotOffered && hrr.ech().is_some() {
1056            return Err({
1057                cx.common.send_fatal_alert(
1058                    AlertDescription::UnsupportedExtension,
1059                    PeerMisbehaved::IllegalHelloRetryRequestWithInvalidEch,
1060                )
1061            });
1062        }
1063
1064        // HRR selects the ciphersuite.
1065        cx.common.suite = Some(cs);
1066        cx.common.handshake_kind = Some(HandshakeKind::FullWithHelloRetryRequest);
1067
1068        // If we offered ECH, we need to confirm that the server accepted it.
1069        match (self.next.ech_state.as_ref(), cs.tls13()) {
1070            (Some(ech_state), Some(tls13_cs)) => {
1071                if !ech_state.confirm_hrr_acceptance(hrr, tls13_cs, cx.common)? {
1072                    // If the server did not confirm, then note the new ECH status but
1073                    // continue the handshake. We will abort with an ECH required error
1074                    // at the end.
1075                    cx.data.ech_status = EchStatus::Rejected;
1076                }
1077            }
1078            (Some(_), None) => {
1079                unreachable!("ECH state should only be set when TLS 1.3 was negotiated")
1080            }
1081            _ => {}
1082        };
1083
1084        // This is the draft19 change where the transcript became a tree
1085        let transcript = self
1086            .next
1087            .transcript_buffer
1088            .start_hash(cs.hash_provider());
1089        let mut transcript_buffer = transcript.into_hrr_buffer();
1090        transcript_buffer.add_message(&m);
1091
1092        // If we offered ECH and the server accepted, we also need to update the separate
1093        // ECH transcript with the hello retry request message.
1094        if let Some(ech_state) = self.next.ech_state.as_mut() {
1095            ech_state.transcript_hrr_update(cs.hash_provider(), &m);
1096        }
1097
1098        // Early data is not allowed after HelloRetryrequest
1099        if cx.data.early_data.is_enabled() {
1100            cx.data.early_data.rejected();
1101        }
1102
1103        let key_share = match req_group {
1104            Some(group) if group != offered_key_share.group() => {
1105                let skxg = match config.find_kx_group(group, ProtocolVersion::TLSv1_3) {
1106                    Some(skxg) => skxg,
1107                    None => {
1108                        return Err(cx.common.send_fatal_alert(
1109                            AlertDescription::IllegalParameter,
1110                            PeerMisbehaved::IllegalHelloRetryRequestWithUnofferedNamedGroup,
1111                        ));
1112                    }
1113                };
1114
1115                cx.common.kx_state = KxState::Start(skxg);
1116                skxg.start()?
1117            }
1118            _ => offered_key_share,
1119        };
1120
1121        emit_client_hello_for_retry(
1122            transcript_buffer,
1123            Some(hrr),
1124            Some(key_share),
1125            self.extra_exts,
1126            Some(cs),
1127            self.next.input,
1128            cx,
1129            self.next.ech_state,
1130        )
1131    }
1132}
1133
1134impl State<ClientConnectionData> for ExpectServerHelloOrHelloRetryRequest {
1135    fn handle<'m>(
1136        self: Box<Self>,
1137        cx: &mut ClientContext<'_>,
1138        m: Message<'m>,
1139    ) -> NextStateOrError<'m>
1140    where
1141        Self: 'm,
1142    {
1143        match m.payload {
1144            MessagePayload::Handshake {
1145                parsed:
1146                    HandshakeMessagePayload {
1147                        payload: HandshakePayload::ServerHello(..),
1148                        ..
1149                    },
1150                ..
1151            } => self
1152                .into_expect_server_hello()
1153                .handle(cx, m),
1154            MessagePayload::Handshake {
1155                parsed:
1156                    HandshakeMessagePayload {
1157                        payload: HandshakePayload::HelloRetryRequest(..),
1158                        ..
1159                    },
1160                ..
1161            } => self.handle_hello_retry_request(cx, m),
1162            payload => Err(inappropriate_handshake_message(
1163                &payload,
1164                &[ContentType::Handshake],
1165                &[HandshakeType::ServerHello, HandshakeType::HelloRetryRequest],
1166            )),
1167        }
1168    }
1169
1170    fn into_owned(self: Box<Self>) -> NextState<'static> {
1171        self
1172    }
1173}
1174
1175enum ClientSessionValue {
1176    Tls13(persist::Tls13ClientSessionValue),
1177    #[cfg(feature = "tls12")]
1178    Tls12(persist::Tls12ClientSessionValue),
1179}
1180
1181impl ClientSessionValue {
1182    fn common(&self) -> &persist::ClientSessionCommon {
1183        match self {
1184            Self::Tls13(inner) => &inner.common,
1185            #[cfg(feature = "tls12")]
1186            Self::Tls12(inner) => &inner.common,
1187        }
1188    }
1189
1190    fn tls13(&self) -> Option<&persist::Tls13ClientSessionValue> {
1191        match self {
1192            Self::Tls13(v) => Some(v),
1193            #[cfg(feature = "tls12")]
1194            Self::Tls12(_) => None,
1195        }
1196    }
1197}
1198
1199impl Deref for ClientSessionValue {
1200    type Target = persist::ClientSessionCommon;
1201
1202    fn deref(&self) -> &Self::Target {
1203        self.common()
1204    }
1205}
1206
1207fn low_quality_integer_hash(mut x: u32) -> u32 {
1208    x = x
1209        .wrapping_add(0x7ed55d16)
1210        .wrapping_add(x << 12);
1211    x = (x ^ 0xc761c23c) ^ (x >> 19);
1212    x = x
1213        .wrapping_add(0x165667b1)
1214        .wrapping_add(x << 5);
1215    x = x.wrapping_add(0xd3a2646c) ^ (x << 9);
1216    x = x
1217        .wrapping_add(0xfd7046c5)
1218        .wrapping_add(x << 3);
1219    x = (x ^ 0xb55a4f09) ^ (x >> 16);
1220    x
1221}