Coverage Report

Created: 2026-09-14 06:47

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