/rust/registry/src/index.crates.io-1949cf8c6b5b557f/rustls-0.23.35/src/client/tls12.rs
Line | Count | Source |
1 | | use alloc::borrow::ToOwned; |
2 | | use alloc::boxed::Box; |
3 | | use alloc::vec; |
4 | | use alloc::vec::Vec; |
5 | | |
6 | | use pki_types::ServerName; |
7 | | pub(super) use server_hello::CompleteServerHelloHandling; |
8 | | use subtle::ConstantTimeEq; |
9 | | |
10 | | use super::client_conn::ClientConnectionData; |
11 | | use super::hs::ClientContext; |
12 | | use crate::ConnectionTrafficSecrets; |
13 | | use crate::check::{inappropriate_handshake_message, inappropriate_message}; |
14 | | use crate::client::common::{ClientAuthDetails, ServerCertDetails}; |
15 | | use crate::client::{ClientConfig, hs}; |
16 | | use crate::common_state::{CommonState, HandshakeKind, KxState, Side, State}; |
17 | | use crate::conn::ConnectionRandoms; |
18 | | use crate::conn::kernel::{Direction, KernelContext, KernelState}; |
19 | | use crate::crypto::KeyExchangeAlgorithm; |
20 | | use crate::enums::{AlertDescription, ContentType, HandshakeType, ProtocolVersion}; |
21 | | use crate::error::{Error, InvalidMessage, PeerIncompatible, PeerMisbehaved}; |
22 | | use crate::hash_hs::HandshakeHash; |
23 | | use crate::log::{debug, trace, warn}; |
24 | | use crate::msgs::base::{Payload, PayloadU8, PayloadU16}; |
25 | | use crate::msgs::ccs::ChangeCipherSpecPayload; |
26 | | use crate::msgs::handshake::{ |
27 | | CertificateChain, ClientDhParams, ClientEcdhParams, ClientKeyExchangeParams, |
28 | | HandshakeMessagePayload, HandshakePayload, NewSessionTicketPayload, |
29 | | NewSessionTicketPayloadTls13, ServerKeyExchangeParams, SessionId, |
30 | | }; |
31 | | use crate::msgs::message::{Message, MessagePayload}; |
32 | | use crate::msgs::persist; |
33 | | use crate::sign::Signer; |
34 | | use crate::suites::{PartiallyExtractedSecrets, SupportedCipherSuite}; |
35 | | use crate::sync::Arc; |
36 | | use crate::tls12::{self, ConnectionSecrets, Tls12CipherSuite}; |
37 | | use crate::verify::{self, DigitallySignedStruct}; |
38 | | |
39 | | mod server_hello { |
40 | | use super::*; |
41 | | use crate::client::hs::{ClientHelloInput, ClientSessionValue}; |
42 | | use crate::msgs::handshake::ServerHelloPayload; |
43 | | |
44 | | pub(in crate::client) struct CompleteServerHelloHandling { |
45 | | pub(in crate::client) randoms: ConnectionRandoms, |
46 | | pub(in crate::client) transcript: HandshakeHash, |
47 | | pub(in crate::client) input: ClientHelloInput, |
48 | | } |
49 | | |
50 | | impl CompleteServerHelloHandling { |
51 | 0 | pub(in crate::client) fn handle_server_hello( |
52 | 0 | mut self, |
53 | 0 | cx: &mut ClientContext<'_>, |
54 | 0 | suite: &'static Tls12CipherSuite, |
55 | 0 | server_hello: &ServerHelloPayload, |
56 | 0 | tls13_supported: bool, |
57 | 0 | ) -> hs::NextStateOrError<'static> { |
58 | 0 | self.randoms |
59 | 0 | .server |
60 | 0 | .clone_from_slice(&server_hello.random.0[..]); |
61 | | |
62 | | // Look for TLS1.3 downgrade signal in server random |
63 | | // both the server random and TLS12_DOWNGRADE_SENTINEL are |
64 | | // public values and don't require constant time comparison |
65 | 0 | let has_downgrade_marker = self.randoms.server[24..] == tls12::DOWNGRADE_SENTINEL; |
66 | 0 | if tls13_supported && has_downgrade_marker { |
67 | 0 | return Err({ |
68 | 0 | cx.common.send_fatal_alert( |
69 | 0 | AlertDescription::IllegalParameter, |
70 | 0 | PeerMisbehaved::AttemptedDowngradeToTls12WhenTls13IsSupported, |
71 | 0 | ) |
72 | 0 | }); |
73 | 0 | } |
74 | | |
75 | | // If we didn't have an input session to resume, and we sent a session ID, |
76 | | // that implies we sent a TLS 1.3 legacy_session_id for compatibility purposes. |
77 | | // In this instance since we're now continuing a TLS 1.2 handshake the server |
78 | | // should not have echoed it back: it's a randomly generated session ID it couldn't |
79 | | // have known. |
80 | 0 | if self.input.resuming.is_none() |
81 | 0 | && !self.input.session_id.is_empty() |
82 | 0 | && self.input.session_id == server_hello.session_id |
83 | | { |
84 | 0 | return Err({ |
85 | 0 | cx.common.send_fatal_alert( |
86 | 0 | AlertDescription::IllegalParameter, |
87 | 0 | PeerMisbehaved::ServerEchoedCompatibilitySessionId, |
88 | 0 | ) |
89 | 0 | }); |
90 | 0 | } |
91 | | |
92 | | let ClientHelloInput { |
93 | 0 | config, |
94 | 0 | server_name, |
95 | | .. |
96 | 0 | } = self.input; |
97 | | |
98 | 0 | let resuming_session = self |
99 | 0 | .input |
100 | 0 | .resuming |
101 | 0 | .and_then(|resuming| match resuming.value { |
102 | 0 | ClientSessionValue::Tls12(inner) => Some(inner), |
103 | 0 | ClientSessionValue::Tls13(_) => None, |
104 | 0 | }); |
105 | | |
106 | | // Doing EMS? |
107 | 0 | let using_ems = server_hello |
108 | 0 | .extended_master_secret_ack |
109 | 0 | .is_some(); |
110 | 0 | if config.require_ems && !using_ems { |
111 | 0 | return Err({ |
112 | 0 | cx.common.send_fatal_alert( |
113 | 0 | AlertDescription::HandshakeFailure, |
114 | 0 | PeerIncompatible::ExtendedMasterSecretExtensionRequired, |
115 | 0 | ) |
116 | 0 | }); |
117 | 0 | } |
118 | | |
119 | | // Might the server send a ticket? |
120 | 0 | let must_issue_new_ticket = if server_hello |
121 | 0 | .session_ticket_ack |
122 | 0 | .is_some() |
123 | | { |
124 | 0 | debug!("Server supports tickets"); |
125 | 0 | true |
126 | | } else { |
127 | 0 | false |
128 | | }; |
129 | | |
130 | | // Might the server send a CertificateStatus between Certificate and |
131 | | // ServerKeyExchange? |
132 | 0 | let may_send_cert_status = server_hello |
133 | 0 | .certificate_status_request_ack |
134 | 0 | .is_some(); |
135 | 0 | if may_send_cert_status { |
136 | 0 | debug!("Server may staple OCSP response"); |
137 | 0 | } |
138 | | |
139 | | // See if we're successfully resuming. |
140 | 0 | if let Some(resuming) = resuming_session { |
141 | 0 | if resuming.session_id == server_hello.session_id { |
142 | 0 | debug!("Server agreed to resume"); |
143 | | |
144 | | // Is the server telling lies about the ciphersuite? |
145 | 0 | if resuming.suite() != suite { |
146 | 0 | return Err(PeerMisbehaved::ResumptionOfferedWithVariedCipherSuite.into()); |
147 | 0 | } |
148 | | |
149 | | // And about EMS support? |
150 | 0 | if resuming.extended_ms() != using_ems { |
151 | 0 | return Err(PeerMisbehaved::ResumptionOfferedWithVariedEms.into()); |
152 | 0 | } |
153 | | |
154 | 0 | let secrets = |
155 | 0 | ConnectionSecrets::new_resume(self.randoms, suite, resuming.secret()); |
156 | 0 | config.key_log.log( |
157 | 0 | "CLIENT_RANDOM", |
158 | 0 | &secrets.randoms.client, |
159 | 0 | &secrets.master_secret, |
160 | 0 | ); |
161 | 0 | cx.common |
162 | 0 | .start_encryption_tls12(&secrets, Side::Client); |
163 | | |
164 | | // Since we're resuming, we verified the certificate and |
165 | | // proof of possession in the prior session. |
166 | 0 | cx.common.peer_certificates = Some( |
167 | 0 | resuming |
168 | 0 | .server_cert_chain() |
169 | 0 | .clone() |
170 | 0 | .into_owned(), |
171 | 0 | ); |
172 | 0 | cx.common.handshake_kind = Some(HandshakeKind::Resumed); |
173 | 0 | let cert_verified = verify::ServerCertVerified::assertion(); |
174 | 0 | let sig_verified = verify::HandshakeSignatureValid::assertion(); |
175 | | |
176 | 0 | return if must_issue_new_ticket { |
177 | 0 | Ok(Box::new(ExpectNewTicket { |
178 | 0 | config, |
179 | 0 | secrets, |
180 | 0 | resuming_session: Some(resuming), |
181 | 0 | session_id: server_hello.session_id, |
182 | 0 | server_name, |
183 | 0 | using_ems, |
184 | 0 | transcript: self.transcript, |
185 | 0 | resuming: true, |
186 | 0 | cert_verified, |
187 | 0 | sig_verified, |
188 | 0 | })) |
189 | | } else { |
190 | 0 | Ok(Box::new(ExpectCcs { |
191 | 0 | config, |
192 | 0 | secrets, |
193 | 0 | resuming_session: Some(resuming), |
194 | 0 | session_id: server_hello.session_id, |
195 | 0 | server_name, |
196 | 0 | using_ems, |
197 | 0 | transcript: self.transcript, |
198 | 0 | ticket: None, |
199 | 0 | resuming: true, |
200 | 0 | cert_verified, |
201 | 0 | sig_verified, |
202 | 0 | })) |
203 | | }; |
204 | 0 | } |
205 | 0 | } |
206 | | |
207 | 0 | cx.common.handshake_kind = Some(HandshakeKind::Full); |
208 | 0 | Ok(Box::new(ExpectCertificate { |
209 | 0 | config, |
210 | 0 | resuming_session: None, |
211 | 0 | session_id: server_hello.session_id, |
212 | 0 | server_name, |
213 | 0 | randoms: self.randoms, |
214 | 0 | using_ems, |
215 | 0 | transcript: self.transcript, |
216 | 0 | suite, |
217 | 0 | may_send_cert_status, |
218 | 0 | must_issue_new_ticket, |
219 | 0 | })) |
220 | 0 | } |
221 | | } |
222 | | } |
223 | | |
224 | | struct ExpectCertificate { |
225 | | config: Arc<ClientConfig>, |
226 | | resuming_session: Option<persist::Tls12ClientSessionValue>, |
227 | | session_id: SessionId, |
228 | | server_name: ServerName<'static>, |
229 | | randoms: ConnectionRandoms, |
230 | | using_ems: bool, |
231 | | transcript: HandshakeHash, |
232 | | pub(super) suite: &'static Tls12CipherSuite, |
233 | | may_send_cert_status: bool, |
234 | | must_issue_new_ticket: bool, |
235 | | } |
236 | | |
237 | | impl State<ClientConnectionData> for ExpectCertificate { |
238 | 0 | fn handle<'m>( |
239 | 0 | mut self: Box<Self>, |
240 | 0 | _cx: &mut ClientContext<'_>, |
241 | 0 | m: Message<'m>, |
242 | 0 | ) -> hs::NextStateOrError<'m> |
243 | 0 | where |
244 | 0 | Self: 'm, |
245 | | { |
246 | 0 | self.transcript.add_message(&m); |
247 | 0 | let server_cert_chain = require_handshake_msg_move!( |
248 | | m, |
249 | | HandshakeType::Certificate, |
250 | | HandshakePayload::Certificate |
251 | 0 | )?; |
252 | | |
253 | 0 | if self.may_send_cert_status { |
254 | 0 | Ok(Box::new(ExpectCertificateStatusOrServerKx { |
255 | 0 | config: self.config, |
256 | 0 | resuming_session: self.resuming_session, |
257 | 0 | session_id: self.session_id, |
258 | 0 | server_name: self.server_name, |
259 | 0 | randoms: self.randoms, |
260 | 0 | using_ems: self.using_ems, |
261 | 0 | transcript: self.transcript, |
262 | 0 | suite: self.suite, |
263 | 0 | server_cert_chain, |
264 | 0 | must_issue_new_ticket: self.must_issue_new_ticket, |
265 | 0 | })) |
266 | | } else { |
267 | 0 | let server_cert = ServerCertDetails::new(server_cert_chain, vec![]); |
268 | | |
269 | 0 | Ok(Box::new(ExpectServerKx { |
270 | 0 | config: self.config, |
271 | 0 | resuming_session: self.resuming_session, |
272 | 0 | session_id: self.session_id, |
273 | 0 | server_name: self.server_name, |
274 | 0 | randoms: self.randoms, |
275 | 0 | using_ems: self.using_ems, |
276 | 0 | transcript: self.transcript, |
277 | 0 | suite: self.suite, |
278 | 0 | server_cert, |
279 | 0 | must_issue_new_ticket: self.must_issue_new_ticket, |
280 | 0 | })) |
281 | | } |
282 | 0 | } |
283 | | |
284 | 0 | fn into_owned(self: Box<Self>) -> hs::NextState<'static> { |
285 | 0 | self |
286 | 0 | } |
287 | | } |
288 | | |
289 | | struct ExpectCertificateStatusOrServerKx<'m> { |
290 | | config: Arc<ClientConfig>, |
291 | | resuming_session: Option<persist::Tls12ClientSessionValue>, |
292 | | session_id: SessionId, |
293 | | server_name: ServerName<'static>, |
294 | | randoms: ConnectionRandoms, |
295 | | using_ems: bool, |
296 | | transcript: HandshakeHash, |
297 | | suite: &'static Tls12CipherSuite, |
298 | | server_cert_chain: CertificateChain<'m>, |
299 | | must_issue_new_ticket: bool, |
300 | | } |
301 | | |
302 | | impl State<ClientConnectionData> for ExpectCertificateStatusOrServerKx<'_> { |
303 | 0 | fn handle<'m>( |
304 | 0 | self: Box<Self>, |
305 | 0 | cx: &mut ClientContext<'_>, |
306 | 0 | m: Message<'m>, |
307 | 0 | ) -> hs::NextStateOrError<'m> |
308 | 0 | where |
309 | 0 | Self: 'm, |
310 | | { |
311 | 0 | match m.payload { |
312 | | MessagePayload::Handshake { |
313 | | parsed: HandshakeMessagePayload(HandshakePayload::ServerKeyExchange(..)), |
314 | | .. |
315 | 0 | } => Box::new(ExpectServerKx { |
316 | 0 | config: self.config, |
317 | 0 | resuming_session: self.resuming_session, |
318 | 0 | session_id: self.session_id, |
319 | 0 | server_name: self.server_name, |
320 | 0 | randoms: self.randoms, |
321 | 0 | using_ems: self.using_ems, |
322 | 0 | transcript: self.transcript, |
323 | 0 | suite: self.suite, |
324 | 0 | server_cert: ServerCertDetails::new(self.server_cert_chain, vec![]), |
325 | 0 | must_issue_new_ticket: self.must_issue_new_ticket, |
326 | 0 | }) |
327 | 0 | .handle(cx, m), |
328 | | MessagePayload::Handshake { |
329 | | parsed: HandshakeMessagePayload(HandshakePayload::CertificateStatus(..)), |
330 | | .. |
331 | 0 | } => Box::new(ExpectCertificateStatus { |
332 | 0 | config: self.config, |
333 | 0 | resuming_session: self.resuming_session, |
334 | 0 | session_id: self.session_id, |
335 | 0 | server_name: self.server_name, |
336 | 0 | randoms: self.randoms, |
337 | 0 | using_ems: self.using_ems, |
338 | 0 | transcript: self.transcript, |
339 | 0 | suite: self.suite, |
340 | 0 | server_cert_chain: self.server_cert_chain, |
341 | 0 | must_issue_new_ticket: self.must_issue_new_ticket, |
342 | 0 | }) |
343 | 0 | .handle(cx, m), |
344 | 0 | payload => Err(inappropriate_handshake_message( |
345 | 0 | &payload, |
346 | 0 | &[ContentType::Handshake], |
347 | 0 | &[ |
348 | 0 | HandshakeType::ServerKeyExchange, |
349 | 0 | HandshakeType::CertificateStatus, |
350 | 0 | ], |
351 | 0 | )), |
352 | | } |
353 | 0 | } |
354 | | |
355 | 0 | fn into_owned(self: Box<Self>) -> hs::NextState<'static> { |
356 | 0 | Box::new(ExpectCertificateStatusOrServerKx { |
357 | 0 | config: self.config, |
358 | 0 | resuming_session: self.resuming_session, |
359 | 0 | session_id: self.session_id, |
360 | 0 | server_name: self.server_name, |
361 | 0 | randoms: self.randoms, |
362 | 0 | using_ems: self.using_ems, |
363 | 0 | transcript: self.transcript, |
364 | 0 | suite: self.suite, |
365 | 0 | server_cert_chain: self.server_cert_chain.into_owned(), |
366 | 0 | must_issue_new_ticket: self.must_issue_new_ticket, |
367 | 0 | }) |
368 | 0 | } |
369 | | } |
370 | | |
371 | | struct ExpectCertificateStatus<'a> { |
372 | | config: Arc<ClientConfig>, |
373 | | resuming_session: Option<persist::Tls12ClientSessionValue>, |
374 | | session_id: SessionId, |
375 | | server_name: ServerName<'static>, |
376 | | randoms: ConnectionRandoms, |
377 | | using_ems: bool, |
378 | | transcript: HandshakeHash, |
379 | | suite: &'static Tls12CipherSuite, |
380 | | server_cert_chain: CertificateChain<'a>, |
381 | | must_issue_new_ticket: bool, |
382 | | } |
383 | | |
384 | | impl State<ClientConnectionData> for ExpectCertificateStatus<'_> { |
385 | 0 | fn handle<'m>( |
386 | 0 | mut self: Box<Self>, |
387 | 0 | _cx: &mut ClientContext<'_>, |
388 | 0 | m: Message<'m>, |
389 | 0 | ) -> hs::NextStateOrError<'m> |
390 | 0 | where |
391 | 0 | Self: 'm, |
392 | | { |
393 | 0 | self.transcript.add_message(&m); |
394 | 0 | let server_cert_ocsp_response = require_handshake_msg_move!( |
395 | | m, |
396 | | HandshakeType::CertificateStatus, |
397 | | HandshakePayload::CertificateStatus |
398 | 0 | )? |
399 | 0 | .into_inner(); |
400 | | |
401 | 0 | trace!( |
402 | | "Server stapled OCSP response is {:?}", |
403 | | &server_cert_ocsp_response |
404 | | ); |
405 | | |
406 | 0 | let server_cert = ServerCertDetails::new(self.server_cert_chain, server_cert_ocsp_response); |
407 | | |
408 | 0 | Ok(Box::new(ExpectServerKx { |
409 | 0 | config: self.config, |
410 | 0 | resuming_session: self.resuming_session, |
411 | 0 | session_id: self.session_id, |
412 | 0 | server_name: self.server_name, |
413 | 0 | randoms: self.randoms, |
414 | 0 | using_ems: self.using_ems, |
415 | 0 | transcript: self.transcript, |
416 | 0 | suite: self.suite, |
417 | 0 | server_cert, |
418 | 0 | must_issue_new_ticket: self.must_issue_new_ticket, |
419 | 0 | })) |
420 | 0 | } |
421 | | |
422 | 0 | fn into_owned(self: Box<Self>) -> hs::NextState<'static> { |
423 | 0 | Box::new(ExpectCertificateStatus { |
424 | 0 | config: self.config, |
425 | 0 | resuming_session: self.resuming_session, |
426 | 0 | session_id: self.session_id, |
427 | 0 | server_name: self.server_name, |
428 | 0 | randoms: self.randoms, |
429 | 0 | using_ems: self.using_ems, |
430 | 0 | transcript: self.transcript, |
431 | 0 | suite: self.suite, |
432 | 0 | server_cert_chain: self.server_cert_chain.into_owned(), |
433 | 0 | must_issue_new_ticket: self.must_issue_new_ticket, |
434 | 0 | }) |
435 | 0 | } |
436 | | } |
437 | | |
438 | | struct ExpectServerKx<'a> { |
439 | | config: Arc<ClientConfig>, |
440 | | resuming_session: Option<persist::Tls12ClientSessionValue>, |
441 | | session_id: SessionId, |
442 | | server_name: ServerName<'static>, |
443 | | randoms: ConnectionRandoms, |
444 | | using_ems: bool, |
445 | | transcript: HandshakeHash, |
446 | | suite: &'static Tls12CipherSuite, |
447 | | server_cert: ServerCertDetails<'a>, |
448 | | must_issue_new_ticket: bool, |
449 | | } |
450 | | |
451 | | impl State<ClientConnectionData> for ExpectServerKx<'_> { |
452 | 0 | fn handle<'m>( |
453 | 0 | mut self: Box<Self>, |
454 | 0 | cx: &mut ClientContext<'_>, |
455 | 0 | m: Message<'m>, |
456 | 0 | ) -> hs::NextStateOrError<'m> |
457 | 0 | where |
458 | 0 | Self: 'm, |
459 | | { |
460 | 0 | let opaque_kx = require_handshake_msg!( |
461 | | m, |
462 | | HandshakeType::ServerKeyExchange, |
463 | | HandshakePayload::ServerKeyExchange |
464 | 0 | )?; |
465 | 0 | self.transcript.add_message(&m); |
466 | | |
467 | 0 | let kx = opaque_kx |
468 | 0 | .unwrap_given_kxa(self.suite.kx) |
469 | 0 | .ok_or_else(|| { |
470 | 0 | cx.common.send_fatal_alert( |
471 | 0 | AlertDescription::DecodeError, |
472 | 0 | InvalidMessage::MissingKeyExchange, |
473 | | ) |
474 | 0 | })?; |
475 | | |
476 | | // Save the signature and signed parameters for later verification. |
477 | 0 | let mut kx_params = Vec::new(); |
478 | 0 | kx.params.encode(&mut kx_params); |
479 | 0 | let server_kx = ServerKxDetails::new(kx_params, kx.dss); |
480 | | |
481 | | #[cfg_attr(not(feature = "logging"), allow(unused_variables))] |
482 | | { |
483 | 0 | match &kx.params { |
484 | 0 | ServerKeyExchangeParams::Ecdh(ecdhe) => { |
485 | 0 | debug!("ECDHE curve is {:?}", ecdhe.curve_params) |
486 | | } |
487 | 0 | ServerKeyExchangeParams::Dh(dhe) => { |
488 | 0 | debug!("DHE params are p = {:?}, g = {:?}", dhe.dh_p, dhe.dh_g) |
489 | | } |
490 | | } |
491 | | } |
492 | | |
493 | 0 | Ok(Box::new(ExpectServerDoneOrCertReq { |
494 | 0 | config: self.config, |
495 | 0 | resuming_session: self.resuming_session, |
496 | 0 | session_id: self.session_id, |
497 | 0 | server_name: self.server_name, |
498 | 0 | randoms: self.randoms, |
499 | 0 | using_ems: self.using_ems, |
500 | 0 | transcript: self.transcript, |
501 | 0 | suite: self.suite, |
502 | 0 | server_cert: self.server_cert, |
503 | 0 | server_kx, |
504 | 0 | must_issue_new_ticket: self.must_issue_new_ticket, |
505 | 0 | })) |
506 | 0 | } |
507 | | |
508 | 0 | fn into_owned(self: Box<Self>) -> hs::NextState<'static> { |
509 | 0 | Box::new(ExpectServerKx { |
510 | 0 | config: self.config, |
511 | 0 | resuming_session: self.resuming_session, |
512 | 0 | session_id: self.session_id, |
513 | 0 | server_name: self.server_name, |
514 | 0 | randoms: self.randoms, |
515 | 0 | using_ems: self.using_ems, |
516 | 0 | transcript: self.transcript, |
517 | 0 | suite: self.suite, |
518 | 0 | server_cert: self.server_cert.into_owned(), |
519 | 0 | must_issue_new_ticket: self.must_issue_new_ticket, |
520 | 0 | }) |
521 | 0 | } |
522 | | } |
523 | | |
524 | 0 | fn emit_certificate( |
525 | 0 | transcript: &mut HandshakeHash, |
526 | 0 | cert_chain: CertificateChain<'static>, |
527 | 0 | common: &mut CommonState, |
528 | 0 | ) { |
529 | 0 | let cert = Message { |
530 | 0 | version: ProtocolVersion::TLSv1_2, |
531 | 0 | payload: MessagePayload::handshake(HandshakeMessagePayload(HandshakePayload::Certificate( |
532 | 0 | cert_chain, |
533 | 0 | ))), |
534 | 0 | }; |
535 | | |
536 | 0 | transcript.add_message(&cert); |
537 | 0 | common.send_msg(cert, false); |
538 | 0 | } |
539 | | |
540 | 0 | fn emit_client_kx( |
541 | 0 | transcript: &mut HandshakeHash, |
542 | 0 | kxa: KeyExchangeAlgorithm, |
543 | 0 | common: &mut CommonState, |
544 | 0 | pub_key: &[u8], |
545 | 0 | ) { |
546 | 0 | let mut buf = Vec::new(); |
547 | 0 | match kxa { |
548 | 0 | KeyExchangeAlgorithm::ECDHE => ClientKeyExchangeParams::Ecdh(ClientEcdhParams { |
549 | 0 | public: PayloadU8::new(pub_key.to_vec()), |
550 | 0 | }), |
551 | 0 | KeyExchangeAlgorithm::DHE => ClientKeyExchangeParams::Dh(ClientDhParams { |
552 | 0 | public: PayloadU16::new(pub_key.to_vec()), |
553 | 0 | }), |
554 | | } |
555 | 0 | .encode(&mut buf); |
556 | 0 | let pubkey = Payload::new(buf); |
557 | | |
558 | 0 | let ckx = Message { |
559 | 0 | version: ProtocolVersion::TLSv1_2, |
560 | 0 | payload: MessagePayload::handshake(HandshakeMessagePayload( |
561 | 0 | HandshakePayload::ClientKeyExchange(pubkey), |
562 | 0 | )), |
563 | 0 | }; |
564 | | |
565 | 0 | transcript.add_message(&ckx); |
566 | 0 | common.send_msg(ckx, false); |
567 | 0 | } |
568 | | |
569 | 0 | fn emit_certverify( |
570 | 0 | transcript: &mut HandshakeHash, |
571 | 0 | signer: &dyn Signer, |
572 | 0 | common: &mut CommonState, |
573 | 0 | ) -> Result<(), Error> { |
574 | 0 | let message = transcript |
575 | 0 | .take_handshake_buf() |
576 | 0 | .ok_or_else(|| Error::General("Expected transcript".to_owned()))?; |
577 | | |
578 | 0 | let scheme = signer.scheme(); |
579 | 0 | let sig = signer.sign(&message)?; |
580 | 0 | let body = DigitallySignedStruct::new(scheme, sig); |
581 | | |
582 | 0 | let m = Message { |
583 | 0 | version: ProtocolVersion::TLSv1_2, |
584 | 0 | payload: MessagePayload::handshake(HandshakeMessagePayload( |
585 | 0 | HandshakePayload::CertificateVerify(body), |
586 | 0 | )), |
587 | 0 | }; |
588 | | |
589 | 0 | transcript.add_message(&m); |
590 | 0 | common.send_msg(m, false); |
591 | 0 | Ok(()) |
592 | 0 | } |
593 | | |
594 | 0 | fn emit_ccs(common: &mut CommonState) { |
595 | 0 | let ccs = Message { |
596 | 0 | version: ProtocolVersion::TLSv1_2, |
597 | 0 | payload: MessagePayload::ChangeCipherSpec(ChangeCipherSpecPayload {}), |
598 | 0 | }; |
599 | | |
600 | 0 | common.send_msg(ccs, false); |
601 | 0 | } |
602 | | |
603 | 0 | fn emit_finished( |
604 | 0 | secrets: &ConnectionSecrets, |
605 | 0 | transcript: &mut HandshakeHash, |
606 | 0 | common: &mut CommonState, |
607 | 0 | ) { |
608 | 0 | let vh = transcript.current_hash(); |
609 | 0 | let verify_data = secrets.client_verify_data(&vh); |
610 | 0 | let verify_data_payload = Payload::new(verify_data); |
611 | | |
612 | 0 | let f = Message { |
613 | 0 | version: ProtocolVersion::TLSv1_2, |
614 | 0 | payload: MessagePayload::handshake(HandshakeMessagePayload(HandshakePayload::Finished( |
615 | 0 | verify_data_payload, |
616 | 0 | ))), |
617 | 0 | }; |
618 | | |
619 | 0 | transcript.add_message(&f); |
620 | 0 | common.send_msg(f, true); |
621 | 0 | } |
622 | | |
623 | | struct ServerKxDetails { |
624 | | kx_params: Vec<u8>, |
625 | | kx_sig: DigitallySignedStruct, |
626 | | } |
627 | | |
628 | | impl ServerKxDetails { |
629 | 0 | fn new(params: Vec<u8>, sig: DigitallySignedStruct) -> Self { |
630 | 0 | Self { |
631 | 0 | kx_params: params, |
632 | 0 | kx_sig: sig, |
633 | 0 | } |
634 | 0 | } |
635 | | } |
636 | | |
637 | | // --- Either a CertificateRequest, or a ServerHelloDone. --- |
638 | | // Existence of the CertificateRequest tells us the server is asking for |
639 | | // client auth. Otherwise we go straight to ServerHelloDone. |
640 | | struct ExpectServerDoneOrCertReq<'a> { |
641 | | config: Arc<ClientConfig>, |
642 | | resuming_session: Option<persist::Tls12ClientSessionValue>, |
643 | | session_id: SessionId, |
644 | | server_name: ServerName<'static>, |
645 | | randoms: ConnectionRandoms, |
646 | | using_ems: bool, |
647 | | transcript: HandshakeHash, |
648 | | suite: &'static Tls12CipherSuite, |
649 | | server_cert: ServerCertDetails<'a>, |
650 | | server_kx: ServerKxDetails, |
651 | | must_issue_new_ticket: bool, |
652 | | } |
653 | | |
654 | | impl State<ClientConnectionData> for ExpectServerDoneOrCertReq<'_> { |
655 | 0 | fn handle<'m>( |
656 | 0 | mut self: Box<Self>, |
657 | 0 | cx: &mut ClientContext<'_>, |
658 | 0 | m: Message<'m>, |
659 | 0 | ) -> hs::NextStateOrError<'m> |
660 | 0 | where |
661 | 0 | Self: 'm, |
662 | | { |
663 | 0 | if matches!( |
664 | 0 | m.payload, |
665 | | MessagePayload::Handshake { |
666 | | parsed: HandshakeMessagePayload(HandshakePayload::CertificateRequest(_)), |
667 | | .. |
668 | | } |
669 | | ) { |
670 | 0 | Box::new(ExpectCertificateRequest { |
671 | 0 | config: self.config, |
672 | 0 | resuming_session: self.resuming_session, |
673 | 0 | session_id: self.session_id, |
674 | 0 | server_name: self.server_name, |
675 | 0 | randoms: self.randoms, |
676 | 0 | using_ems: self.using_ems, |
677 | 0 | transcript: self.transcript, |
678 | 0 | suite: self.suite, |
679 | 0 | server_cert: self.server_cert, |
680 | 0 | server_kx: self.server_kx, |
681 | 0 | must_issue_new_ticket: self.must_issue_new_ticket, |
682 | 0 | }) |
683 | 0 | .handle(cx, m) |
684 | | } else { |
685 | 0 | self.transcript.abandon_client_auth(); |
686 | | |
687 | 0 | Box::new(ExpectServerDone { |
688 | 0 | config: self.config, |
689 | 0 | resuming_session: self.resuming_session, |
690 | 0 | session_id: self.session_id, |
691 | 0 | server_name: self.server_name, |
692 | 0 | randoms: self.randoms, |
693 | 0 | using_ems: self.using_ems, |
694 | 0 | transcript: self.transcript, |
695 | 0 | suite: self.suite, |
696 | 0 | server_cert: self.server_cert, |
697 | 0 | server_kx: self.server_kx, |
698 | 0 | client_auth: None, |
699 | 0 | must_issue_new_ticket: self.must_issue_new_ticket, |
700 | 0 | }) |
701 | 0 | .handle(cx, m) |
702 | | } |
703 | 0 | } |
704 | | |
705 | 0 | fn into_owned(self: Box<Self>) -> hs::NextState<'static> { |
706 | 0 | Box::new(ExpectServerDoneOrCertReq { |
707 | 0 | config: self.config, |
708 | 0 | resuming_session: self.resuming_session, |
709 | 0 | session_id: self.session_id, |
710 | 0 | server_name: self.server_name, |
711 | 0 | randoms: self.randoms, |
712 | 0 | using_ems: self.using_ems, |
713 | 0 | transcript: self.transcript, |
714 | 0 | suite: self.suite, |
715 | 0 | server_cert: self.server_cert.into_owned(), |
716 | 0 | server_kx: self.server_kx, |
717 | 0 | must_issue_new_ticket: self.must_issue_new_ticket, |
718 | 0 | }) |
719 | 0 | } |
720 | | } |
721 | | |
722 | | struct ExpectCertificateRequest<'a> { |
723 | | config: Arc<ClientConfig>, |
724 | | resuming_session: Option<persist::Tls12ClientSessionValue>, |
725 | | session_id: SessionId, |
726 | | server_name: ServerName<'static>, |
727 | | randoms: ConnectionRandoms, |
728 | | using_ems: bool, |
729 | | transcript: HandshakeHash, |
730 | | suite: &'static Tls12CipherSuite, |
731 | | server_cert: ServerCertDetails<'a>, |
732 | | server_kx: ServerKxDetails, |
733 | | must_issue_new_ticket: bool, |
734 | | } |
735 | | |
736 | | impl State<ClientConnectionData> for ExpectCertificateRequest<'_> { |
737 | 0 | fn handle<'m>( |
738 | 0 | mut self: Box<Self>, |
739 | 0 | _cx: &mut ClientContext<'_>, |
740 | 0 | m: Message<'m>, |
741 | 0 | ) -> hs::NextStateOrError<'m> |
742 | 0 | where |
743 | 0 | Self: 'm, |
744 | | { |
745 | 0 | let certreq = require_handshake_msg!( |
746 | | m, |
747 | | HandshakeType::CertificateRequest, |
748 | | HandshakePayload::CertificateRequest |
749 | 0 | )?; |
750 | 0 | self.transcript.add_message(&m); |
751 | 0 | debug!("Got CertificateRequest {certreq:?}"); |
752 | | |
753 | | // The RFC jovially describes the design here as 'somewhat complicated' |
754 | | // and 'somewhat underspecified'. So thanks for that. |
755 | | // |
756 | | // We ignore certreq.certtypes as a result, since the information it contains |
757 | | // is entirely duplicated in certreq.sigschemes. |
758 | | |
759 | | const NO_CONTEXT: Option<Vec<u8>> = None; // TLS 1.2 doesn't use a context. |
760 | 0 | let no_compression = None; // or compression |
761 | 0 | let client_auth = ClientAuthDetails::resolve( |
762 | 0 | self.config |
763 | 0 | .client_auth_cert_resolver |
764 | 0 | .as_ref(), |
765 | 0 | Some(&certreq.canames), |
766 | 0 | &certreq.sigschemes, |
767 | 0 | NO_CONTEXT, |
768 | 0 | no_compression, |
769 | | ); |
770 | | |
771 | 0 | Ok(Box::new(ExpectServerDone { |
772 | 0 | config: self.config, |
773 | 0 | resuming_session: self.resuming_session, |
774 | 0 | session_id: self.session_id, |
775 | 0 | server_name: self.server_name, |
776 | 0 | randoms: self.randoms, |
777 | 0 | using_ems: self.using_ems, |
778 | 0 | transcript: self.transcript, |
779 | 0 | suite: self.suite, |
780 | 0 | server_cert: self.server_cert, |
781 | 0 | server_kx: self.server_kx, |
782 | 0 | client_auth: Some(client_auth), |
783 | 0 | must_issue_new_ticket: self.must_issue_new_ticket, |
784 | 0 | })) |
785 | 0 | } |
786 | | |
787 | 0 | fn into_owned(self: Box<Self>) -> hs::NextState<'static> { |
788 | 0 | Box::new(ExpectCertificateRequest { |
789 | 0 | config: self.config, |
790 | 0 | resuming_session: self.resuming_session, |
791 | 0 | session_id: self.session_id, |
792 | 0 | server_name: self.server_name, |
793 | 0 | randoms: self.randoms, |
794 | 0 | using_ems: self.using_ems, |
795 | 0 | transcript: self.transcript, |
796 | 0 | suite: self.suite, |
797 | 0 | server_cert: self.server_cert.into_owned(), |
798 | 0 | server_kx: self.server_kx, |
799 | 0 | must_issue_new_ticket: self.must_issue_new_ticket, |
800 | 0 | }) |
801 | 0 | } |
802 | | } |
803 | | |
804 | | struct ExpectServerDone<'a> { |
805 | | config: Arc<ClientConfig>, |
806 | | resuming_session: Option<persist::Tls12ClientSessionValue>, |
807 | | session_id: SessionId, |
808 | | server_name: ServerName<'static>, |
809 | | randoms: ConnectionRandoms, |
810 | | using_ems: bool, |
811 | | transcript: HandshakeHash, |
812 | | suite: &'static Tls12CipherSuite, |
813 | | server_cert: ServerCertDetails<'a>, |
814 | | server_kx: ServerKxDetails, |
815 | | client_auth: Option<ClientAuthDetails>, |
816 | | must_issue_new_ticket: bool, |
817 | | } |
818 | | |
819 | | impl State<ClientConnectionData> for ExpectServerDone<'_> { |
820 | 0 | fn handle<'m>( |
821 | 0 | self: Box<Self>, |
822 | 0 | cx: &mut ClientContext<'_>, |
823 | 0 | m: Message<'m>, |
824 | 0 | ) -> hs::NextStateOrError<'m> |
825 | 0 | where |
826 | 0 | Self: 'm, |
827 | | { |
828 | 0 | match m.payload { |
829 | | MessagePayload::Handshake { |
830 | | parsed: HandshakeMessagePayload(HandshakePayload::ServerHelloDone), |
831 | | .. |
832 | 0 | } => {} |
833 | 0 | payload => { |
834 | 0 | return Err(inappropriate_handshake_message( |
835 | 0 | &payload, |
836 | 0 | &[ContentType::Handshake], |
837 | 0 | &[HandshakeType::ServerHelloDone], |
838 | 0 | )); |
839 | | } |
840 | | } |
841 | | |
842 | 0 | let mut st = *self; |
843 | 0 | st.transcript.add_message(&m); |
844 | | |
845 | 0 | cx.common.check_aligned_handshake()?; |
846 | | |
847 | 0 | trace!("Server cert is {:?}", st.server_cert.cert_chain); |
848 | 0 | debug!("Server DNS name is {:?}", st.server_name); |
849 | | |
850 | 0 | let suite = st.suite; |
851 | | |
852 | | // 1. Verify the cert chain. |
853 | | // 2. Verify that the top certificate signed their kx. |
854 | | // 3. If doing client auth, send our Certificate. |
855 | | // 4. Complete the key exchange: |
856 | | // a) generate our kx pair |
857 | | // b) emit a ClientKeyExchange containing it |
858 | | // c) if doing client auth, emit a CertificateVerify |
859 | | // d) derive the shared keys |
860 | | // e) emit a CCS |
861 | | // f) use the derived keys to start encryption |
862 | | // 5. emit a Finished, our first encrypted message under the new keys. |
863 | | |
864 | | // 1. |
865 | 0 | let (end_entity, intermediates) = st |
866 | 0 | .server_cert |
867 | 0 | .cert_chain |
868 | 0 | .split_first() |
869 | 0 | .ok_or(Error::NoCertificatesPresented)?; |
870 | | |
871 | 0 | let now = st.config.current_time()?; |
872 | | |
873 | 0 | let cert_verified = st |
874 | 0 | .config |
875 | 0 | .verifier |
876 | 0 | .verify_server_cert( |
877 | 0 | end_entity, |
878 | 0 | intermediates, |
879 | 0 | &st.server_name, |
880 | 0 | &st.server_cert.ocsp_response, |
881 | 0 | now, |
882 | 0 | ) |
883 | 0 | .map_err(|err| { |
884 | 0 | cx.common |
885 | 0 | .send_cert_verify_error_alert(err) |
886 | 0 | })?; |
887 | | |
888 | | // 2. |
889 | | // Build up the contents of the signed message. |
890 | | // It's ClientHello.random || ServerHello.random || ServerKeyExchange.params |
891 | 0 | let sig_verified = { |
892 | 0 | let mut message = Vec::new(); |
893 | 0 | message.extend_from_slice(&st.randoms.client); |
894 | 0 | message.extend_from_slice(&st.randoms.server); |
895 | 0 | message.extend_from_slice(&st.server_kx.kx_params); |
896 | | |
897 | | // Check the signature is compatible with the ciphersuite. |
898 | 0 | let sig = &st.server_kx.kx_sig; |
899 | 0 | if !SupportedCipherSuite::from(suite) |
900 | 0 | .usable_for_signature_algorithm(sig.scheme.algorithm()) |
901 | | { |
902 | 0 | warn!( |
903 | | "peer signed kx with wrong algorithm (got {:?} expect {:?})", |
904 | | sig.scheme.algorithm(), |
905 | | suite.sign |
906 | | ); |
907 | 0 | return Err(PeerMisbehaved::SignedKxWithWrongAlgorithm.into()); |
908 | 0 | } |
909 | | |
910 | 0 | st.config |
911 | 0 | .verifier |
912 | 0 | .verify_tls12_signature(&message, end_entity, sig) |
913 | 0 | .map_err(|err| { |
914 | 0 | cx.common |
915 | 0 | .send_cert_verify_error_alert(err) |
916 | 0 | })? |
917 | | }; |
918 | 0 | cx.common.peer_certificates = Some(st.server_cert.cert_chain.into_owned()); |
919 | | |
920 | | // 3. |
921 | 0 | if let Some(client_auth) = &st.client_auth { |
922 | 0 | let certs = match client_auth { |
923 | 0 | ClientAuthDetails::Empty { .. } => CertificateChain::default(), |
924 | 0 | ClientAuthDetails::Verify { certkey, .. } => CertificateChain(certkey.cert.clone()), |
925 | | }; |
926 | 0 | emit_certificate(&mut st.transcript, certs, cx.common); |
927 | 0 | } |
928 | | |
929 | | // 4a. |
930 | 0 | let kx_params = tls12::decode_kx_params::<ServerKeyExchangeParams>( |
931 | 0 | st.suite.kx, |
932 | 0 | cx.common, |
933 | 0 | &st.server_kx.kx_params, |
934 | 0 | )?; |
935 | 0 | let maybe_skxg = match &kx_params { |
936 | 0 | ServerKeyExchangeParams::Ecdh(ecdh) => st |
937 | 0 | .config |
938 | 0 | .find_kx_group(ecdh.curve_params.named_group, ProtocolVersion::TLSv1_2), |
939 | 0 | ServerKeyExchangeParams::Dh(dh) => { |
940 | 0 | let ffdhe_group = dh.as_ffdhe_group(); |
941 | | |
942 | 0 | st.config |
943 | 0 | .provider |
944 | 0 | .kx_groups |
945 | 0 | .iter() |
946 | 0 | .find(|kxg| kxg.ffdhe_group() == Some(ffdhe_group)) |
947 | 0 | .copied() |
948 | | } |
949 | | }; |
950 | 0 | let Some(skxg) = maybe_skxg else { |
951 | 0 | return Err(cx.common.send_fatal_alert( |
952 | 0 | AlertDescription::IllegalParameter, |
953 | 0 | PeerMisbehaved::SelectedUnofferedKxGroup, |
954 | 0 | )); |
955 | | }; |
956 | 0 | cx.common.kx_state = KxState::Start(skxg); |
957 | 0 | let kx = skxg.start()?; |
958 | | |
959 | | // 4b. |
960 | 0 | let mut transcript = st.transcript; |
961 | 0 | emit_client_kx(&mut transcript, st.suite.kx, cx.common, kx.pub_key()); |
962 | | // Note: EMS handshake hash only runs up to ClientKeyExchange. |
963 | 0 | let ems_seed = st |
964 | 0 | .using_ems |
965 | 0 | .then(|| transcript.current_hash()); |
966 | | |
967 | | // 4c. |
968 | 0 | if let Some(ClientAuthDetails::Verify { signer, .. }) = &st.client_auth { |
969 | 0 | emit_certverify(&mut transcript, signer.as_ref(), cx.common)?; |
970 | 0 | } |
971 | | |
972 | | // 4d. Derive secrets. |
973 | | // An alert at this point will be sent in plaintext. That must happen |
974 | | // prior to the CCS, or else the peer will try to decrypt it. |
975 | 0 | let secrets = ConnectionSecrets::from_key_exchange( |
976 | 0 | kx, |
977 | 0 | kx_params.pub_key(), |
978 | 0 | ems_seed, |
979 | 0 | st.randoms, |
980 | 0 | suite, |
981 | | ) |
982 | 0 | .map_err(|err| { |
983 | 0 | cx.common |
984 | 0 | .send_fatal_alert(AlertDescription::IllegalParameter, err) |
985 | 0 | })?; |
986 | 0 | cx.common.kx_state.complete(); |
987 | | |
988 | | // 4e. CCS. We are definitely going to switch on encryption. |
989 | 0 | emit_ccs(cx.common); |
990 | | |
991 | | // 4f. Now commit secrets. |
992 | 0 | st.config.key_log.log( |
993 | 0 | "CLIENT_RANDOM", |
994 | 0 | &secrets.randoms.client, |
995 | 0 | &secrets.master_secret, |
996 | 0 | ); |
997 | 0 | cx.common |
998 | 0 | .start_encryption_tls12(&secrets, Side::Client); |
999 | 0 | cx.common |
1000 | 0 | .record_layer |
1001 | 0 | .start_encrypting(); |
1002 | | |
1003 | | // 5. |
1004 | 0 | emit_finished(&secrets, &mut transcript, cx.common); |
1005 | | |
1006 | 0 | if st.must_issue_new_ticket { |
1007 | 0 | Ok(Box::new(ExpectNewTicket { |
1008 | 0 | config: st.config, |
1009 | 0 | secrets, |
1010 | 0 | resuming_session: st.resuming_session, |
1011 | 0 | session_id: st.session_id, |
1012 | 0 | server_name: st.server_name, |
1013 | 0 | using_ems: st.using_ems, |
1014 | 0 | transcript, |
1015 | 0 | resuming: false, |
1016 | 0 | cert_verified, |
1017 | 0 | sig_verified, |
1018 | 0 | })) |
1019 | | } else { |
1020 | 0 | Ok(Box::new(ExpectCcs { |
1021 | 0 | config: st.config, |
1022 | 0 | secrets, |
1023 | 0 | resuming_session: st.resuming_session, |
1024 | 0 | session_id: st.session_id, |
1025 | 0 | server_name: st.server_name, |
1026 | 0 | using_ems: st.using_ems, |
1027 | 0 | transcript, |
1028 | 0 | ticket: None, |
1029 | 0 | resuming: false, |
1030 | 0 | cert_verified, |
1031 | 0 | sig_verified, |
1032 | 0 | })) |
1033 | | } |
1034 | 0 | } |
1035 | | |
1036 | 0 | fn into_owned(self: Box<Self>) -> hs::NextState<'static> { |
1037 | 0 | Box::new(ExpectServerDone { |
1038 | 0 | config: self.config, |
1039 | 0 | resuming_session: self.resuming_session, |
1040 | 0 | session_id: self.session_id, |
1041 | 0 | server_name: self.server_name, |
1042 | 0 | randoms: self.randoms, |
1043 | 0 | using_ems: self.using_ems, |
1044 | 0 | transcript: self.transcript, |
1045 | 0 | suite: self.suite, |
1046 | 0 | server_cert: self.server_cert.into_owned(), |
1047 | 0 | server_kx: self.server_kx, |
1048 | 0 | client_auth: self.client_auth, |
1049 | 0 | must_issue_new_ticket: self.must_issue_new_ticket, |
1050 | 0 | }) |
1051 | 0 | } |
1052 | | } |
1053 | | |
1054 | | struct ExpectNewTicket { |
1055 | | config: Arc<ClientConfig>, |
1056 | | secrets: ConnectionSecrets, |
1057 | | resuming_session: Option<persist::Tls12ClientSessionValue>, |
1058 | | session_id: SessionId, |
1059 | | server_name: ServerName<'static>, |
1060 | | using_ems: bool, |
1061 | | transcript: HandshakeHash, |
1062 | | resuming: bool, |
1063 | | cert_verified: verify::ServerCertVerified, |
1064 | | sig_verified: verify::HandshakeSignatureValid, |
1065 | | } |
1066 | | |
1067 | | impl State<ClientConnectionData> for ExpectNewTicket { |
1068 | 0 | fn handle<'m>( |
1069 | 0 | mut self: Box<Self>, |
1070 | 0 | _cx: &mut ClientContext<'_>, |
1071 | 0 | m: Message<'m>, |
1072 | 0 | ) -> hs::NextStateOrError<'m> |
1073 | 0 | where |
1074 | 0 | Self: 'm, |
1075 | | { |
1076 | 0 | self.transcript.add_message(&m); |
1077 | | |
1078 | 0 | let nst = require_handshake_msg_move!( |
1079 | | m, |
1080 | | HandshakeType::NewSessionTicket, |
1081 | | HandshakePayload::NewSessionTicket |
1082 | 0 | )?; |
1083 | | |
1084 | 0 | Ok(Box::new(ExpectCcs { |
1085 | 0 | config: self.config, |
1086 | 0 | secrets: self.secrets, |
1087 | 0 | resuming_session: self.resuming_session, |
1088 | 0 | session_id: self.session_id, |
1089 | 0 | server_name: self.server_name, |
1090 | 0 | using_ems: self.using_ems, |
1091 | 0 | transcript: self.transcript, |
1092 | 0 | ticket: Some(nst), |
1093 | 0 | resuming: self.resuming, |
1094 | 0 | cert_verified: self.cert_verified, |
1095 | 0 | sig_verified: self.sig_verified, |
1096 | 0 | })) |
1097 | 0 | } |
1098 | | |
1099 | 0 | fn into_owned(self: Box<Self>) -> hs::NextState<'static> { |
1100 | 0 | self |
1101 | 0 | } |
1102 | | } |
1103 | | |
1104 | | // -- Waiting for their CCS -- |
1105 | | struct ExpectCcs { |
1106 | | config: Arc<ClientConfig>, |
1107 | | secrets: ConnectionSecrets, |
1108 | | resuming_session: Option<persist::Tls12ClientSessionValue>, |
1109 | | session_id: SessionId, |
1110 | | server_name: ServerName<'static>, |
1111 | | using_ems: bool, |
1112 | | transcript: HandshakeHash, |
1113 | | ticket: Option<NewSessionTicketPayload>, |
1114 | | resuming: bool, |
1115 | | cert_verified: verify::ServerCertVerified, |
1116 | | sig_verified: verify::HandshakeSignatureValid, |
1117 | | } |
1118 | | |
1119 | | impl State<ClientConnectionData> for ExpectCcs { |
1120 | 0 | fn handle<'m>( |
1121 | 0 | self: Box<Self>, |
1122 | 0 | cx: &mut ClientContext<'_>, |
1123 | 0 | m: Message<'m>, |
1124 | 0 | ) -> hs::NextStateOrError<'m> |
1125 | 0 | where |
1126 | 0 | Self: 'm, |
1127 | | { |
1128 | 0 | match m.payload { |
1129 | 0 | MessagePayload::ChangeCipherSpec(..) => {} |
1130 | 0 | payload => { |
1131 | 0 | return Err(inappropriate_message( |
1132 | 0 | &payload, |
1133 | 0 | &[ContentType::ChangeCipherSpec], |
1134 | 0 | )); |
1135 | | } |
1136 | | } |
1137 | | // CCS should not be received interleaved with fragmented handshake-level |
1138 | | // message. |
1139 | 0 | cx.common.check_aligned_handshake()?; |
1140 | | |
1141 | | // Note: msgs layer validates trivial contents of CCS. |
1142 | 0 | cx.common |
1143 | 0 | .record_layer |
1144 | 0 | .start_decrypting(); |
1145 | | |
1146 | 0 | Ok(Box::new(ExpectFinished { |
1147 | 0 | config: self.config, |
1148 | 0 | secrets: self.secrets, |
1149 | 0 | resuming_session: self.resuming_session, |
1150 | 0 | session_id: self.session_id, |
1151 | 0 | server_name: self.server_name, |
1152 | 0 | using_ems: self.using_ems, |
1153 | 0 | transcript: self.transcript, |
1154 | 0 | ticket: self.ticket, |
1155 | 0 | resuming: self.resuming, |
1156 | 0 | cert_verified: self.cert_verified, |
1157 | 0 | sig_verified: self.sig_verified, |
1158 | 0 | })) |
1159 | 0 | } |
1160 | | |
1161 | 0 | fn into_owned(self: Box<Self>) -> hs::NextState<'static> { |
1162 | 0 | self |
1163 | 0 | } |
1164 | | } |
1165 | | |
1166 | | struct ExpectFinished { |
1167 | | config: Arc<ClientConfig>, |
1168 | | resuming_session: Option<persist::Tls12ClientSessionValue>, |
1169 | | session_id: SessionId, |
1170 | | server_name: ServerName<'static>, |
1171 | | using_ems: bool, |
1172 | | transcript: HandshakeHash, |
1173 | | ticket: Option<NewSessionTicketPayload>, |
1174 | | secrets: ConnectionSecrets, |
1175 | | resuming: bool, |
1176 | | cert_verified: verify::ServerCertVerified, |
1177 | | sig_verified: verify::HandshakeSignatureValid, |
1178 | | } |
1179 | | |
1180 | | impl ExpectFinished { |
1181 | | // -- Waiting for their finished -- |
1182 | 0 | fn save_session(&mut self, cx: &ClientContext<'_>) { |
1183 | | // Save a ticket. If we got a new ticket, save that. Otherwise, save the |
1184 | | // original ticket again. |
1185 | 0 | let (mut ticket, lifetime) = match self.ticket.take() { |
1186 | 0 | Some(nst) => (nst.ticket, nst.lifetime_hint), |
1187 | 0 | None => (Arc::new(PayloadU16::empty()), 0), |
1188 | | }; |
1189 | | |
1190 | 0 | if ticket.0.is_empty() { |
1191 | 0 | if let Some(resuming_session) = &mut self.resuming_session { |
1192 | 0 | ticket = resuming_session.ticket(); |
1193 | 0 | } |
1194 | 0 | } |
1195 | | |
1196 | 0 | if self.session_id.is_empty() && ticket.0.is_empty() { |
1197 | 0 | debug!("Session not saved: server didn't allocate id or ticket"); |
1198 | 0 | return; |
1199 | 0 | } |
1200 | | |
1201 | 0 | let Ok(now) = self.config.current_time() else { |
1202 | 0 | debug!("Could not get current time"); |
1203 | 0 | return; |
1204 | | }; |
1205 | | |
1206 | 0 | let session_value = persist::Tls12ClientSessionValue::new( |
1207 | 0 | self.secrets.suite(), |
1208 | 0 | self.session_id, |
1209 | 0 | ticket, |
1210 | 0 | self.secrets.master_secret(), |
1211 | 0 | cx.common |
1212 | 0 | .peer_certificates |
1213 | 0 | .clone() |
1214 | 0 | .unwrap_or_default(), |
1215 | 0 | &self.config.verifier, |
1216 | 0 | &self.config.client_auth_cert_resolver, |
1217 | 0 | now, |
1218 | 0 | lifetime, |
1219 | 0 | self.using_ems, |
1220 | | ); |
1221 | | |
1222 | 0 | self.config |
1223 | 0 | .resumption |
1224 | 0 | .store |
1225 | 0 | .set_tls12_session(self.server_name.clone(), session_value); |
1226 | 0 | } |
1227 | | } |
1228 | | |
1229 | | impl State<ClientConnectionData> for ExpectFinished { |
1230 | 0 | fn handle<'m>( |
1231 | 0 | self: Box<Self>, |
1232 | 0 | cx: &mut ClientContext<'_>, |
1233 | 0 | m: Message<'m>, |
1234 | 0 | ) -> hs::NextStateOrError<'m> |
1235 | 0 | where |
1236 | 0 | Self: 'm, |
1237 | | { |
1238 | 0 | let mut st = *self; |
1239 | 0 | let finished = |
1240 | 0 | require_handshake_msg!(m, HandshakeType::Finished, HandshakePayload::Finished)?; |
1241 | | |
1242 | 0 | cx.common.check_aligned_handshake()?; |
1243 | | |
1244 | | // Work out what verify_data we expect. |
1245 | 0 | let vh = st.transcript.current_hash(); |
1246 | 0 | let expect_verify_data = st.secrets.server_verify_data(&vh); |
1247 | | |
1248 | | // Constant-time verification of this is relatively unimportant: they only |
1249 | | // get one chance. But it can't hurt. |
1250 | 0 | let _fin_verified = |
1251 | 0 | match ConstantTimeEq::ct_eq(&expect_verify_data[..], finished.bytes()).into() { |
1252 | 0 | true => verify::FinishedMessageVerified::assertion(), |
1253 | | false => { |
1254 | 0 | return Err(cx |
1255 | 0 | .common |
1256 | 0 | .send_fatal_alert(AlertDescription::DecryptError, Error::DecryptError)); |
1257 | | } |
1258 | | }; |
1259 | | |
1260 | | // Hash this message too. |
1261 | 0 | st.transcript.add_message(&m); |
1262 | | |
1263 | 0 | st.save_session(cx); |
1264 | | |
1265 | 0 | if st.resuming { |
1266 | 0 | emit_ccs(cx.common); |
1267 | 0 | cx.common |
1268 | 0 | .record_layer |
1269 | 0 | .start_encrypting(); |
1270 | 0 | emit_finished(&st.secrets, &mut st.transcript, cx.common); |
1271 | 0 | } |
1272 | | |
1273 | 0 | cx.common |
1274 | 0 | .start_traffic(&mut cx.sendable_plaintext); |
1275 | 0 | Ok(Box::new(ExpectTraffic { |
1276 | 0 | secrets: st.secrets, |
1277 | 0 | _cert_verified: st.cert_verified, |
1278 | 0 | _sig_verified: st.sig_verified, |
1279 | 0 | _fin_verified, |
1280 | 0 | })) |
1281 | 0 | } |
1282 | | |
1283 | | // we could not decrypt the encrypted handshake message with session resumption |
1284 | | // this might mean that the ticket was invalid for some reason, so we remove it |
1285 | | // from the store to restart a session from scratch |
1286 | 0 | fn handle_decrypt_error(&self) { |
1287 | 0 | if self.resuming { |
1288 | 0 | self.config |
1289 | 0 | .resumption |
1290 | 0 | .store |
1291 | 0 | .remove_tls12_session(&self.server_name); |
1292 | 0 | } |
1293 | 0 | } |
1294 | | |
1295 | 0 | fn into_owned(self: Box<Self>) -> hs::NextState<'static> { |
1296 | 0 | self |
1297 | 0 | } |
1298 | | } |
1299 | | |
1300 | | // -- Traffic transit state -- |
1301 | | struct ExpectTraffic { |
1302 | | secrets: ConnectionSecrets, |
1303 | | _cert_verified: verify::ServerCertVerified, |
1304 | | _sig_verified: verify::HandshakeSignatureValid, |
1305 | | _fin_verified: verify::FinishedMessageVerified, |
1306 | | } |
1307 | | |
1308 | | impl State<ClientConnectionData> for ExpectTraffic { |
1309 | 0 | fn handle<'m>( |
1310 | 0 | self: Box<Self>, |
1311 | 0 | cx: &mut ClientContext<'_>, |
1312 | 0 | m: Message<'m>, |
1313 | 0 | ) -> hs::NextStateOrError<'m> |
1314 | 0 | where |
1315 | 0 | Self: 'm, |
1316 | | { |
1317 | 0 | match m.payload { |
1318 | 0 | MessagePayload::ApplicationData(payload) => cx |
1319 | 0 | .common |
1320 | 0 | .take_received_plaintext(payload), |
1321 | 0 | payload => { |
1322 | 0 | return Err(inappropriate_message( |
1323 | 0 | &payload, |
1324 | 0 | &[ContentType::ApplicationData], |
1325 | 0 | )); |
1326 | | } |
1327 | | } |
1328 | 0 | Ok(self) |
1329 | 0 | } |
1330 | | |
1331 | 0 | fn export_keying_material( |
1332 | 0 | &self, |
1333 | 0 | output: &mut [u8], |
1334 | 0 | label: &[u8], |
1335 | 0 | context: Option<&[u8]>, |
1336 | 0 | ) -> Result<(), Error> { |
1337 | 0 | self.secrets |
1338 | 0 | .export_keying_material(output, label, context); |
1339 | 0 | Ok(()) |
1340 | 0 | } |
1341 | | |
1342 | 0 | fn extract_secrets(&self) -> Result<PartiallyExtractedSecrets, Error> { |
1343 | 0 | self.secrets |
1344 | 0 | .extract_secrets(Side::Client) |
1345 | 0 | } |
1346 | | |
1347 | 0 | fn into_external_state(self: Box<Self>) -> Result<Box<dyn KernelState + 'static>, Error> { |
1348 | 0 | Ok(self) |
1349 | 0 | } |
1350 | | |
1351 | 0 | fn into_owned(self: Box<Self>) -> hs::NextState<'static> { |
1352 | 0 | self |
1353 | 0 | } |
1354 | | } |
1355 | | |
1356 | | impl KernelState for ExpectTraffic { |
1357 | 0 | fn update_secrets(&mut self, _: Direction) -> Result<ConnectionTrafficSecrets, Error> { |
1358 | 0 | Err(Error::General( |
1359 | 0 | "TLS 1.2 connections do not support traffic secret updates".into(), |
1360 | 0 | )) |
1361 | 0 | } |
1362 | | |
1363 | 0 | fn handle_new_session_ticket( |
1364 | 0 | &mut self, |
1365 | 0 | _cx: &mut KernelContext<'_>, |
1366 | 0 | _message: &NewSessionTicketPayloadTls13, |
1367 | 0 | ) -> Result<(), Error> { |
1368 | 0 | Err(Error::General( |
1369 | 0 | "TLS 1.2 session tickets may not be sent once the handshake has completed".into(), |
1370 | 0 | )) |
1371 | 0 | } |
1372 | | } |