1 | use crate::check::{inappropriate_handshake_message, inappropriate_message}; |
2 | use crate::common_state::{CommonState, Side, State}; |
3 | use crate::conn::ConnectionRandoms; |
4 | use crate::enums::ProtocolVersion; |
5 | use crate::enums::{AlertDescription, ContentType, HandshakeType}; |
6 | use crate::error::{Error, InvalidMessage, PeerMisbehaved}; |
7 | use crate::hash_hs::HandshakeHash; |
8 | #[cfg (feature = "logging" )] |
9 | use crate::log::{debug, trace, warn}; |
10 | use crate::msgs::base::{Payload, PayloadU8}; |
11 | use crate::msgs::ccs::ChangeCipherSpecPayload; |
12 | use crate::msgs::codec::Codec; |
13 | use crate::msgs::handshake::{ |
14 | CertificateChain, HandshakeMessagePayload, HandshakePayload, NewSessionTicketPayload, |
15 | ServerEcdhParams, SessionId, |
16 | }; |
17 | use crate::msgs::message::{Message, MessagePayload}; |
18 | use crate::msgs::persist; |
19 | use crate::sign::Signer; |
20 | use crate::suites::{PartiallyExtractedSecrets, SupportedCipherSuite}; |
21 | use crate::tls12::{self, ConnectionSecrets, Tls12CipherSuite}; |
22 | use crate::verify::{self, DigitallySignedStruct}; |
23 | |
24 | use super::client_conn::ClientConnectionData; |
25 | use super::hs::ClientContext; |
26 | use crate::client::common::ClientAuthDetails; |
27 | use crate::client::common::ServerCertDetails; |
28 | use crate::client::{hs, ClientConfig}; |
29 | |
30 | use pki_types::{ServerName, UnixTime}; |
31 | use subtle::ConstantTimeEq; |
32 | |
33 | use alloc::borrow::ToOwned; |
34 | use alloc::boxed::Box; |
35 | use alloc::sync::Arc; |
36 | use alloc::vec; |
37 | use alloc::vec::Vec; |
38 | |
39 | pub(super) use server_hello::CompleteServerHelloHandling; |
40 | |
41 | mod server_hello { |
42 | use crate::msgs::enums::ExtensionType; |
43 | use crate::msgs::handshake::HasServerExtensions; |
44 | use crate::msgs::handshake::ServerHelloPayload; |
45 | |
46 | use super::*; |
47 | |
48 | pub(in crate::client) struct CompleteServerHelloHandling { |
49 | pub(in crate::client) config: Arc<ClientConfig>, |
50 | pub(in crate::client) resuming_session: Option<persist::Tls12ClientSessionValue>, |
51 | pub(in crate::client) server_name: ServerName<'static>, |
52 | pub(in crate::client) randoms: ConnectionRandoms, |
53 | pub(in crate::client) using_ems: bool, |
54 | pub(in crate::client) transcript: HandshakeHash, |
55 | } |
56 | |
57 | impl CompleteServerHelloHandling { |
58 | pub(in crate::client) fn handle_server_hello( |
59 | mut self, |
60 | cx: &mut ClientContext, |
61 | suite: &'static Tls12CipherSuite, |
62 | server_hello: &ServerHelloPayload, |
63 | tls13_supported: bool, |
64 | ) -> hs::NextStateOrError { |
65 | self.randoms |
66 | .server |
67 | .clone_from_slice(&server_hello.random.0[..]); |
68 | |
69 | // Look for TLS1.3 downgrade signal in server random |
70 | // both the server random and TLS12_DOWNGRADE_SENTINEL are |
71 | // public values and don't require constant time comparison |
72 | let has_downgrade_marker = self.randoms.server[24..] == tls12::DOWNGRADE_SENTINEL; |
73 | if tls13_supported && has_downgrade_marker { |
74 | return Err({ |
75 | cx.common.send_fatal_alert( |
76 | AlertDescription::IllegalParameter, |
77 | PeerMisbehaved::AttemptedDowngradeToTls12WhenTls13IsSupported, |
78 | ) |
79 | }); |
80 | } |
81 | |
82 | // Doing EMS? |
83 | self.using_ems = server_hello.ems_support_acked(); |
84 | |
85 | // Might the server send a ticket? |
86 | let must_issue_new_ticket = if server_hello |
87 | .find_extension(ExtensionType::SessionTicket) |
88 | .is_some() |
89 | { |
90 | debug!("Server supports tickets" ); |
91 | true |
92 | } else { |
93 | false |
94 | }; |
95 | |
96 | // Might the server send a CertificateStatus between Certificate and |
97 | // ServerKeyExchange? |
98 | let may_send_cert_status = server_hello |
99 | .find_extension(ExtensionType::StatusRequest) |
100 | .is_some(); |
101 | if may_send_cert_status { |
102 | debug!("Server may staple OCSP response" ); |
103 | } |
104 | |
105 | // See if we're successfully resuming. |
106 | if let Some(resuming) = self.resuming_session { |
107 | if resuming.session_id == server_hello.session_id { |
108 | debug!("Server agreed to resume" ); |
109 | |
110 | // Is the server telling lies about the ciphersuite? |
111 | if resuming.suite() != suite { |
112 | return Err(PeerMisbehaved::ResumptionOfferedWithVariedCipherSuite.into()); |
113 | } |
114 | |
115 | // And about EMS support? |
116 | if resuming.extended_ms() != self.using_ems { |
117 | return Err(PeerMisbehaved::ResumptionOfferedWithVariedEms.into()); |
118 | } |
119 | |
120 | let secrets = |
121 | ConnectionSecrets::new_resume(self.randoms, suite, resuming.secret()); |
122 | self.config.key_log.log( |
123 | "CLIENT_RANDOM" , |
124 | &secrets.randoms.client, |
125 | &secrets.master_secret, |
126 | ); |
127 | cx.common |
128 | .start_encryption_tls12(&secrets, Side::Client); |
129 | |
130 | // Since we're resuming, we verified the certificate and |
131 | // proof of possession in the prior session. |
132 | cx.common.peer_certificates = Some(resuming.server_cert_chain().clone()); |
133 | let cert_verified = verify::ServerCertVerified::assertion(); |
134 | let sig_verified = verify::HandshakeSignatureValid::assertion(); |
135 | |
136 | return if must_issue_new_ticket { |
137 | Ok(Box::new(ExpectNewTicket { |
138 | config: self.config, |
139 | secrets, |
140 | resuming_session: Some(resuming), |
141 | session_id: server_hello.session_id, |
142 | server_name: self.server_name, |
143 | using_ems: self.using_ems, |
144 | transcript: self.transcript, |
145 | resuming: true, |
146 | cert_verified, |
147 | sig_verified, |
148 | })) |
149 | } else { |
150 | Ok(Box::new(ExpectCcs { |
151 | config: self.config, |
152 | secrets, |
153 | resuming_session: Some(resuming), |
154 | session_id: server_hello.session_id, |
155 | server_name: self.server_name, |
156 | using_ems: self.using_ems, |
157 | transcript: self.transcript, |
158 | ticket: None, |
159 | resuming: true, |
160 | cert_verified, |
161 | sig_verified, |
162 | })) |
163 | }; |
164 | } |
165 | } |
166 | |
167 | Ok(Box::new(ExpectCertificate { |
168 | config: self.config, |
169 | resuming_session: None, |
170 | session_id: server_hello.session_id, |
171 | server_name: self.server_name, |
172 | randoms: self.randoms, |
173 | using_ems: self.using_ems, |
174 | transcript: self.transcript, |
175 | suite, |
176 | may_send_cert_status, |
177 | must_issue_new_ticket, |
178 | })) |
179 | } |
180 | } |
181 | } |
182 | |
183 | struct ExpectCertificate { |
184 | config: Arc<ClientConfig>, |
185 | resuming_session: Option<persist::Tls12ClientSessionValue>, |
186 | session_id: SessionId, |
187 | server_name: ServerName<'static>, |
188 | randoms: ConnectionRandoms, |
189 | using_ems: bool, |
190 | transcript: HandshakeHash, |
191 | pub(super) suite: &'static Tls12CipherSuite, |
192 | may_send_cert_status: bool, |
193 | must_issue_new_ticket: bool, |
194 | } |
195 | |
196 | impl State<ClientConnectionData> for ExpectCertificate { |
197 | fn handle( |
198 | mut self: Box<Self>, |
199 | _cx: &mut ClientContext<'_>, |
200 | m: Message, |
201 | ) -> hs::NextStateOrError { |
202 | self.transcript.add_message(&m); |
203 | let server_cert_chain = require_handshake_msg_move!( |
204 | m, |
205 | HandshakeType::Certificate, |
206 | HandshakePayload::Certificate |
207 | )?; |
208 | |
209 | if self.may_send_cert_status { |
210 | Ok(Box::new(ExpectCertificateStatusOrServerKx { |
211 | config: self.config, |
212 | resuming_session: self.resuming_session, |
213 | session_id: self.session_id, |
214 | server_name: self.server_name, |
215 | randoms: self.randoms, |
216 | using_ems: self.using_ems, |
217 | transcript: self.transcript, |
218 | suite: self.suite, |
219 | server_cert_chain, |
220 | must_issue_new_ticket: self.must_issue_new_ticket, |
221 | })) |
222 | } else { |
223 | let server_cert = ServerCertDetails::new(server_cert_chain, vec![]); |
224 | |
225 | Ok(Box::new(ExpectServerKx { |
226 | config: self.config, |
227 | resuming_session: self.resuming_session, |
228 | session_id: self.session_id, |
229 | server_name: self.server_name, |
230 | randoms: self.randoms, |
231 | using_ems: self.using_ems, |
232 | transcript: self.transcript, |
233 | suite: self.suite, |
234 | server_cert, |
235 | must_issue_new_ticket: self.must_issue_new_ticket, |
236 | })) |
237 | } |
238 | } |
239 | } |
240 | |
241 | struct ExpectCertificateStatusOrServerKx { |
242 | config: Arc<ClientConfig>, |
243 | resuming_session: Option<persist::Tls12ClientSessionValue>, |
244 | session_id: SessionId, |
245 | server_name: ServerName<'static>, |
246 | randoms: ConnectionRandoms, |
247 | using_ems: bool, |
248 | transcript: HandshakeHash, |
249 | suite: &'static Tls12CipherSuite, |
250 | server_cert_chain: CertificateChain, |
251 | must_issue_new_ticket: bool, |
252 | } |
253 | |
254 | impl State<ClientConnectionData> for ExpectCertificateStatusOrServerKx { |
255 | fn handle(self: Box<Self>, cx: &mut ClientContext<'_>, m: Message) -> hs::NextStateOrError { |
256 | match m.payload { |
257 | MessagePayload::Handshake { |
258 | parsed: |
259 | HandshakeMessagePayload { |
260 | payload: HandshakePayload::ServerKeyExchange(..), |
261 | .. |
262 | }, |
263 | .. |
264 | } => Box::new(ExpectServerKx { |
265 | config: self.config, |
266 | resuming_session: self.resuming_session, |
267 | session_id: self.session_id, |
268 | server_name: self.server_name, |
269 | randoms: self.randoms, |
270 | using_ems: self.using_ems, |
271 | transcript: self.transcript, |
272 | suite: self.suite, |
273 | server_cert: ServerCertDetails::new(self.server_cert_chain, vec![]), |
274 | must_issue_new_ticket: self.must_issue_new_ticket, |
275 | }) |
276 | .handle(cx, m), |
277 | MessagePayload::Handshake { |
278 | parsed: |
279 | HandshakeMessagePayload { |
280 | payload: HandshakePayload::CertificateStatus(..), |
281 | .. |
282 | }, |
283 | .. |
284 | } => Box::new(ExpectCertificateStatus { |
285 | config: self.config, |
286 | resuming_session: self.resuming_session, |
287 | session_id: self.session_id, |
288 | server_name: self.server_name, |
289 | randoms: self.randoms, |
290 | using_ems: self.using_ems, |
291 | transcript: self.transcript, |
292 | suite: self.suite, |
293 | server_cert_chain: self.server_cert_chain, |
294 | must_issue_new_ticket: self.must_issue_new_ticket, |
295 | }) |
296 | .handle(cx, m), |
297 | payload => Err(inappropriate_handshake_message( |
298 | &payload, |
299 | &[ContentType::Handshake], |
300 | &[ |
301 | HandshakeType::ServerKeyExchange, |
302 | HandshakeType::CertificateStatus, |
303 | ], |
304 | )), |
305 | } |
306 | } |
307 | } |
308 | |
309 | struct ExpectCertificateStatus { |
310 | config: Arc<ClientConfig>, |
311 | resuming_session: Option<persist::Tls12ClientSessionValue>, |
312 | session_id: SessionId, |
313 | server_name: ServerName<'static>, |
314 | randoms: ConnectionRandoms, |
315 | using_ems: bool, |
316 | transcript: HandshakeHash, |
317 | suite: &'static Tls12CipherSuite, |
318 | server_cert_chain: CertificateChain, |
319 | must_issue_new_ticket: bool, |
320 | } |
321 | |
322 | impl State<ClientConnectionData> for ExpectCertificateStatus { |
323 | fn handle( |
324 | mut self: Box<Self>, |
325 | _cx: &mut ClientContext<'_>, |
326 | m: Message, |
327 | ) -> hs::NextStateOrError { |
328 | self.transcript.add_message(&m); |
329 | let server_cert_ocsp_response = require_handshake_msg_move!( |
330 | m, |
331 | HandshakeType::CertificateStatus, |
332 | HandshakePayload::CertificateStatus |
333 | )? |
334 | .into_inner(); |
335 | |
336 | trace!( |
337 | "Server stapled OCSP response is {:?}" , |
338 | &server_cert_ocsp_response |
339 | ); |
340 | |
341 | let server_cert = ServerCertDetails::new(self.server_cert_chain, server_cert_ocsp_response); |
342 | |
343 | Ok(Box::new(ExpectServerKx { |
344 | config: self.config, |
345 | resuming_session: self.resuming_session, |
346 | session_id: self.session_id, |
347 | server_name: self.server_name, |
348 | randoms: self.randoms, |
349 | using_ems: self.using_ems, |
350 | transcript: self.transcript, |
351 | suite: self.suite, |
352 | server_cert, |
353 | must_issue_new_ticket: self.must_issue_new_ticket, |
354 | })) |
355 | } |
356 | } |
357 | |
358 | struct ExpectServerKx { |
359 | config: Arc<ClientConfig>, |
360 | resuming_session: Option<persist::Tls12ClientSessionValue>, |
361 | session_id: SessionId, |
362 | server_name: ServerName<'static>, |
363 | randoms: ConnectionRandoms, |
364 | using_ems: bool, |
365 | transcript: HandshakeHash, |
366 | suite: &'static Tls12CipherSuite, |
367 | server_cert: ServerCertDetails, |
368 | must_issue_new_ticket: bool, |
369 | } |
370 | |
371 | impl State<ClientConnectionData> for ExpectServerKx { |
372 | fn handle(mut self: Box<Self>, cx: &mut ClientContext<'_>, m: Message) -> hs::NextStateOrError { |
373 | let opaque_kx = require_handshake_msg!( |
374 | m, |
375 | HandshakeType::ServerKeyExchange, |
376 | HandshakePayload::ServerKeyExchange |
377 | )?; |
378 | self.transcript.add_message(&m); |
379 | |
380 | let ecdhe = opaque_kx |
381 | .unwrap_given_kxa(self.suite.kx) |
382 | .ok_or_else(|| { |
383 | cx.common.send_fatal_alert( |
384 | AlertDescription::DecodeError, |
385 | InvalidMessage::MissingKeyExchange, |
386 | ) |
387 | })?; |
388 | |
389 | // Save the signature and signed parameters for later verification. |
390 | let mut kx_params = Vec::new(); |
391 | ecdhe.params.encode(&mut kx_params); |
392 | let server_kx = ServerKxDetails::new(kx_params, ecdhe.dss); |
393 | |
394 | #[cfg_attr (not(feature = "logging" ), allow(unused_variables))] |
395 | { |
396 | debug!("ECDHE curve is {:?}" , ecdhe.params.curve_params); |
397 | } |
398 | |
399 | Ok(Box::new(ExpectServerDoneOrCertReq { |
400 | config: self.config, |
401 | resuming_session: self.resuming_session, |
402 | session_id: self.session_id, |
403 | server_name: self.server_name, |
404 | randoms: self.randoms, |
405 | using_ems: self.using_ems, |
406 | transcript: self.transcript, |
407 | suite: self.suite, |
408 | server_cert: self.server_cert, |
409 | server_kx, |
410 | must_issue_new_ticket: self.must_issue_new_ticket, |
411 | })) |
412 | } |
413 | } |
414 | |
415 | fn emit_certificate( |
416 | transcript: &mut HandshakeHash, |
417 | cert_chain: CertificateChain, |
418 | common: &mut CommonState, |
419 | ) { |
420 | let cert: Message = Message { |
421 | version: ProtocolVersion::TLSv1_2, |
422 | payload: MessagePayload::handshake(parsed:HandshakeMessagePayload { |
423 | typ: HandshakeType::Certificate, |
424 | payload: HandshakePayload::Certificate(cert_chain), |
425 | }), |
426 | }; |
427 | |
428 | transcript.add_message(&cert); |
429 | common.send_msg(m:cert, must_encrypt:false); |
430 | } |
431 | |
432 | fn emit_clientkx(transcript: &mut HandshakeHash, common: &mut CommonState, pub_key: &[u8]) { |
433 | let mut buf: Vec = Vec::new(); |
434 | let ecpoint: PayloadU8 = PayloadU8::new(bytes:Vec::from(pub_key)); |
435 | ecpoint.encode(&mut buf); |
436 | let pubkey: Payload = Payload::new(bytes:buf); |
437 | |
438 | let ckx: Message = Message { |
439 | version: ProtocolVersion::TLSv1_2, |
440 | payload: MessagePayload::handshake(parsed:HandshakeMessagePayload { |
441 | typ: HandshakeType::ClientKeyExchange, |
442 | payload: HandshakePayload::ClientKeyExchange(pubkey), |
443 | }), |
444 | }; |
445 | |
446 | transcript.add_message(&ckx); |
447 | common.send_msg(m:ckx, must_encrypt:false); |
448 | } |
449 | |
450 | fn emit_certverify( |
451 | transcript: &mut HandshakeHash, |
452 | signer: &dyn Signer, |
453 | common: &mut CommonState, |
454 | ) -> Result<(), Error> { |
455 | let message: Vec = transcript |
456 | .take_handshake_buf() |
457 | .ok_or_else(|| Error::General("Expected transcript" .to_owned()))?; |
458 | |
459 | let scheme: SignatureScheme = signer.scheme(); |
460 | let sig: Vec = signer.sign(&message)?; |
461 | let body: DigitallySignedStruct = DigitallySignedStruct::new(scheme, sig); |
462 | |
463 | let m: Message = Message { |
464 | version: ProtocolVersion::TLSv1_2, |
465 | payload: MessagePayload::handshake(parsed:HandshakeMessagePayload { |
466 | typ: HandshakeType::CertificateVerify, |
467 | payload: HandshakePayload::CertificateVerify(body), |
468 | }), |
469 | }; |
470 | |
471 | transcript.add_message(&m); |
472 | common.send_msg(m, must_encrypt:false); |
473 | Ok(()) |
474 | } |
475 | |
476 | fn emit_ccs(common: &mut CommonState) { |
477 | let ccs: Message = Message { |
478 | version: ProtocolVersion::TLSv1_2, |
479 | payload: MessagePayload::ChangeCipherSpec(ChangeCipherSpecPayload {}), |
480 | }; |
481 | |
482 | common.send_msg(m:ccs, must_encrypt:false); |
483 | } |
484 | |
485 | fn emit_finished( |
486 | secrets: &ConnectionSecrets, |
487 | transcript: &mut HandshakeHash, |
488 | common: &mut CommonState, |
489 | ) { |
490 | let vh: Output = transcript.get_current_hash(); |
491 | let verify_data: Vec = secrets.client_verify_data(&vh); |
492 | let verify_data_payload: Payload = Payload::new(bytes:verify_data); |
493 | |
494 | let f: Message = Message { |
495 | version: ProtocolVersion::TLSv1_2, |
496 | payload: MessagePayload::handshake(parsed:HandshakeMessagePayload { |
497 | typ: HandshakeType::Finished, |
498 | payload: HandshakePayload::Finished(verify_data_payload), |
499 | }), |
500 | }; |
501 | |
502 | transcript.add_message(&f); |
503 | common.send_msg(m:f, must_encrypt:true); |
504 | } |
505 | |
506 | struct ServerKxDetails { |
507 | kx_params: Vec<u8>, |
508 | kx_sig: DigitallySignedStruct, |
509 | } |
510 | |
511 | impl ServerKxDetails { |
512 | fn new(params: Vec<u8>, sig: DigitallySignedStruct) -> Self { |
513 | Self { |
514 | kx_params: params, |
515 | kx_sig: sig, |
516 | } |
517 | } |
518 | } |
519 | |
520 | // --- Either a CertificateRequest, or a ServerHelloDone. --- |
521 | // Existence of the CertificateRequest tells us the server is asking for |
522 | // client auth. Otherwise we go straight to ServerHelloDone. |
523 | struct ExpectServerDoneOrCertReq { |
524 | config: Arc<ClientConfig>, |
525 | resuming_session: Option<persist::Tls12ClientSessionValue>, |
526 | session_id: SessionId, |
527 | server_name: ServerName<'static>, |
528 | randoms: ConnectionRandoms, |
529 | using_ems: bool, |
530 | transcript: HandshakeHash, |
531 | suite: &'static Tls12CipherSuite, |
532 | server_cert: ServerCertDetails, |
533 | server_kx: ServerKxDetails, |
534 | must_issue_new_ticket: bool, |
535 | } |
536 | |
537 | impl State<ClientConnectionData> for ExpectServerDoneOrCertReq { |
538 | fn handle(mut self: Box<Self>, cx: &mut ClientContext<'_>, m: Message) -> hs::NextStateOrError { |
539 | if matches!( |
540 | m.payload, |
541 | MessagePayload::Handshake { |
542 | parsed: HandshakeMessagePayload { |
543 | payload: HandshakePayload::CertificateRequest(_), |
544 | .. |
545 | }, |
546 | .. |
547 | } |
548 | ) { |
549 | Box::new(ExpectCertificateRequest { |
550 | config: self.config, |
551 | resuming_session: self.resuming_session, |
552 | session_id: self.session_id, |
553 | server_name: self.server_name, |
554 | randoms: self.randoms, |
555 | using_ems: self.using_ems, |
556 | transcript: self.transcript, |
557 | suite: self.suite, |
558 | server_cert: self.server_cert, |
559 | server_kx: self.server_kx, |
560 | must_issue_new_ticket: self.must_issue_new_ticket, |
561 | }) |
562 | .handle(cx, m) |
563 | } else { |
564 | self.transcript.abandon_client_auth(); |
565 | |
566 | Box::new(ExpectServerDone { |
567 | config: self.config, |
568 | resuming_session: self.resuming_session, |
569 | session_id: self.session_id, |
570 | server_name: self.server_name, |
571 | randoms: self.randoms, |
572 | using_ems: self.using_ems, |
573 | transcript: self.transcript, |
574 | suite: self.suite, |
575 | server_cert: self.server_cert, |
576 | server_kx: self.server_kx, |
577 | client_auth: None, |
578 | must_issue_new_ticket: self.must_issue_new_ticket, |
579 | }) |
580 | .handle(cx, m) |
581 | } |
582 | } |
583 | } |
584 | |
585 | struct ExpectCertificateRequest { |
586 | config: Arc<ClientConfig>, |
587 | resuming_session: Option<persist::Tls12ClientSessionValue>, |
588 | session_id: SessionId, |
589 | server_name: ServerName<'static>, |
590 | randoms: ConnectionRandoms, |
591 | using_ems: bool, |
592 | transcript: HandshakeHash, |
593 | suite: &'static Tls12CipherSuite, |
594 | server_cert: ServerCertDetails, |
595 | server_kx: ServerKxDetails, |
596 | must_issue_new_ticket: bool, |
597 | } |
598 | |
599 | impl State<ClientConnectionData> for ExpectCertificateRequest { |
600 | fn handle( |
601 | mut self: Box<Self>, |
602 | _cx: &mut ClientContext<'_>, |
603 | m: Message, |
604 | ) -> hs::NextStateOrError { |
605 | let certreq = require_handshake_msg!( |
606 | m, |
607 | HandshakeType::CertificateRequest, |
608 | HandshakePayload::CertificateRequest |
609 | )?; |
610 | self.transcript.add_message(&m); |
611 | debug!("Got CertificateRequest {:?}" , certreq); |
612 | |
613 | // The RFC jovially describes the design here as 'somewhat complicated' |
614 | // and 'somewhat underspecified'. So thanks for that. |
615 | // |
616 | // We ignore certreq.certtypes as a result, since the information it contains |
617 | // is entirely duplicated in certreq.sigschemes. |
618 | |
619 | const NO_CONTEXT: Option<Vec<u8>> = None; // TLS 1.2 doesn't use a context. |
620 | let client_auth = ClientAuthDetails::resolve( |
621 | self.config |
622 | .client_auth_cert_resolver |
623 | .as_ref(), |
624 | Some(&certreq.canames), |
625 | &certreq.sigschemes, |
626 | NO_CONTEXT, |
627 | ); |
628 | |
629 | Ok(Box::new(ExpectServerDone { |
630 | config: self.config, |
631 | resuming_session: self.resuming_session, |
632 | session_id: self.session_id, |
633 | server_name: self.server_name, |
634 | randoms: self.randoms, |
635 | using_ems: self.using_ems, |
636 | transcript: self.transcript, |
637 | suite: self.suite, |
638 | server_cert: self.server_cert, |
639 | server_kx: self.server_kx, |
640 | client_auth: Some(client_auth), |
641 | must_issue_new_ticket: self.must_issue_new_ticket, |
642 | })) |
643 | } |
644 | } |
645 | |
646 | struct ExpectServerDone { |
647 | config: Arc<ClientConfig>, |
648 | resuming_session: Option<persist::Tls12ClientSessionValue>, |
649 | session_id: SessionId, |
650 | server_name: ServerName<'static>, |
651 | randoms: ConnectionRandoms, |
652 | using_ems: bool, |
653 | transcript: HandshakeHash, |
654 | suite: &'static Tls12CipherSuite, |
655 | server_cert: ServerCertDetails, |
656 | server_kx: ServerKxDetails, |
657 | client_auth: Option<ClientAuthDetails>, |
658 | must_issue_new_ticket: bool, |
659 | } |
660 | |
661 | impl State<ClientConnectionData> for ExpectServerDone { |
662 | fn handle(self: Box<Self>, cx: &mut ClientContext<'_>, m: Message) -> hs::NextStateOrError { |
663 | match m.payload { |
664 | MessagePayload::Handshake { |
665 | parsed: |
666 | HandshakeMessagePayload { |
667 | payload: HandshakePayload::ServerHelloDone, |
668 | .. |
669 | }, |
670 | .. |
671 | } => {} |
672 | payload => { |
673 | return Err(inappropriate_handshake_message( |
674 | &payload, |
675 | &[ContentType::Handshake], |
676 | &[HandshakeType::ServerHelloDone], |
677 | )); |
678 | } |
679 | } |
680 | |
681 | let mut st = *self; |
682 | st.transcript.add_message(&m); |
683 | |
684 | cx.common.check_aligned_handshake()?; |
685 | |
686 | trace!("Server cert is {:?}" , st.server_cert.cert_chain); |
687 | debug!("Server DNS name is {:?}" , st.server_name); |
688 | |
689 | let suite = st.suite; |
690 | |
691 | // 1. Verify the cert chain. |
692 | // 2. Verify any SCTs provided with the certificate. |
693 | // 3. Verify that the top certificate signed their kx. |
694 | // 4. If doing client auth, send our Certificate. |
695 | // 5. Complete the key exchange: |
696 | // a) generate our kx pair |
697 | // b) emit a ClientKeyExchange containing it |
698 | // c) if doing client auth, emit a CertificateVerify |
699 | // d) emit a CCS |
700 | // e) derive the shared keys, and start encryption |
701 | // 6. emit a Finished, our first encrypted message under the new keys. |
702 | |
703 | // 1. |
704 | let (end_entity, intermediates) = st |
705 | .server_cert |
706 | .cert_chain |
707 | .split_first() |
708 | .ok_or(Error::NoCertificatesPresented)?; |
709 | let cert_verified = st |
710 | .config |
711 | .verifier |
712 | .verify_server_cert( |
713 | end_entity, |
714 | intermediates, |
715 | &st.server_name, |
716 | &st.server_cert.ocsp_response, |
717 | UnixTime::now(), |
718 | ) |
719 | .map_err(|err| { |
720 | cx.common |
721 | .send_cert_verify_error_alert(err) |
722 | })?; |
723 | |
724 | // 3. |
725 | // Build up the contents of the signed message. |
726 | // It's ClientHello.random || ServerHello.random || ServerKeyExchange.params |
727 | let sig_verified = { |
728 | let mut message = Vec::new(); |
729 | message.extend_from_slice(&st.randoms.client); |
730 | message.extend_from_slice(&st.randoms.server); |
731 | message.extend_from_slice(&st.server_kx.kx_params); |
732 | |
733 | // Check the signature is compatible with the ciphersuite. |
734 | let sig = &st.server_kx.kx_sig; |
735 | if !SupportedCipherSuite::from(suite).usable_for_signature_algorithm(sig.scheme.sign()) |
736 | { |
737 | warn!( |
738 | "peer signed kx with wrong algorithm (got {:?} expect {:?})" , |
739 | sig.scheme.sign(), |
740 | suite.sign |
741 | ); |
742 | return Err(PeerMisbehaved::SignedKxWithWrongAlgorithm.into()); |
743 | } |
744 | |
745 | st.config |
746 | .verifier |
747 | .verify_tls12_signature(&message, &st.server_cert.cert_chain[0], sig) |
748 | .map_err(|err| { |
749 | cx.common |
750 | .send_cert_verify_error_alert(err) |
751 | })? |
752 | }; |
753 | cx.common.peer_certificates = Some(st.server_cert.cert_chain); |
754 | |
755 | // 4. |
756 | if let Some(client_auth) = &st.client_auth { |
757 | let certs = match client_auth { |
758 | ClientAuthDetails::Empty { .. } => CertificateChain::default(), |
759 | ClientAuthDetails::Verify { certkey, .. } => CertificateChain(certkey.cert.clone()), |
760 | }; |
761 | emit_certificate(&mut st.transcript, certs, cx.common); |
762 | } |
763 | |
764 | // 5a. |
765 | let ecdh_params = |
766 | tls12::decode_ecdh_params::<ServerEcdhParams>(cx.common, &st.server_kx.kx_params)?; |
767 | let named_group = ecdh_params.curve_params.named_group; |
768 | let skxg = match st.config.find_kx_group(named_group) { |
769 | Some(skxg) => skxg, |
770 | None => { |
771 | return Err(PeerMisbehaved::SelectedUnofferedKxGroup.into()); |
772 | } |
773 | }; |
774 | let kx = skxg |
775 | .start() |
776 | .map_err(|_| Error::FailedToGetRandomBytes)?; |
777 | |
778 | // 5b. |
779 | let mut transcript = st.transcript; |
780 | emit_clientkx(&mut transcript, cx.common, kx.pub_key()); |
781 | // Note: EMS handshake hash only runs up to ClientKeyExchange. |
782 | let ems_seed = st |
783 | .using_ems |
784 | .then(|| transcript.get_current_hash()); |
785 | |
786 | // 5c. |
787 | if let Some(ClientAuthDetails::Verify { signer, .. }) = &st.client_auth { |
788 | emit_certverify(&mut transcript, signer.as_ref(), cx.common)?; |
789 | } |
790 | |
791 | // 5d. |
792 | emit_ccs(cx.common); |
793 | |
794 | // 5e. Now commit secrets. |
795 | let secrets = ConnectionSecrets::from_key_exchange( |
796 | kx, |
797 | &ecdh_params.public.0, |
798 | ems_seed, |
799 | st.randoms, |
800 | suite, |
801 | )?; |
802 | |
803 | st.config.key_log.log( |
804 | "CLIENT_RANDOM" , |
805 | &secrets.randoms.client, |
806 | &secrets.master_secret, |
807 | ); |
808 | cx.common |
809 | .start_encryption_tls12(&secrets, Side::Client); |
810 | cx.common |
811 | .record_layer |
812 | .start_encrypting(); |
813 | |
814 | // 6. |
815 | emit_finished(&secrets, &mut transcript, cx.common); |
816 | |
817 | if st.must_issue_new_ticket { |
818 | Ok(Box::new(ExpectNewTicket { |
819 | config: st.config, |
820 | secrets, |
821 | resuming_session: st.resuming_session, |
822 | session_id: st.session_id, |
823 | server_name: st.server_name, |
824 | using_ems: st.using_ems, |
825 | transcript, |
826 | resuming: false, |
827 | cert_verified, |
828 | sig_verified, |
829 | })) |
830 | } else { |
831 | Ok(Box::new(ExpectCcs { |
832 | config: st.config, |
833 | secrets, |
834 | resuming_session: st.resuming_session, |
835 | session_id: st.session_id, |
836 | server_name: st.server_name, |
837 | using_ems: st.using_ems, |
838 | transcript, |
839 | ticket: None, |
840 | resuming: false, |
841 | cert_verified, |
842 | sig_verified, |
843 | })) |
844 | } |
845 | } |
846 | } |
847 | |
848 | struct ExpectNewTicket { |
849 | config: Arc<ClientConfig>, |
850 | secrets: ConnectionSecrets, |
851 | resuming_session: Option<persist::Tls12ClientSessionValue>, |
852 | session_id: SessionId, |
853 | server_name: ServerName<'static>, |
854 | using_ems: bool, |
855 | transcript: HandshakeHash, |
856 | resuming: bool, |
857 | cert_verified: verify::ServerCertVerified, |
858 | sig_verified: verify::HandshakeSignatureValid, |
859 | } |
860 | |
861 | impl State<ClientConnectionData> for ExpectNewTicket { |
862 | fn handle( |
863 | mut self: Box<Self>, |
864 | _cx: &mut ClientContext<'_>, |
865 | m: Message, |
866 | ) -> hs::NextStateOrError { |
867 | self.transcript.add_message(&m); |
868 | |
869 | let nst = require_handshake_msg_move!( |
870 | m, |
871 | HandshakeType::NewSessionTicket, |
872 | HandshakePayload::NewSessionTicket |
873 | )?; |
874 | |
875 | Ok(Box::new(ExpectCcs { |
876 | config: self.config, |
877 | secrets: self.secrets, |
878 | resuming_session: self.resuming_session, |
879 | session_id: self.session_id, |
880 | server_name: self.server_name, |
881 | using_ems: self.using_ems, |
882 | transcript: self.transcript, |
883 | ticket: Some(nst), |
884 | resuming: self.resuming, |
885 | cert_verified: self.cert_verified, |
886 | sig_verified: self.sig_verified, |
887 | })) |
888 | } |
889 | } |
890 | |
891 | // -- Waiting for their CCS -- |
892 | struct ExpectCcs { |
893 | config: Arc<ClientConfig>, |
894 | secrets: ConnectionSecrets, |
895 | resuming_session: Option<persist::Tls12ClientSessionValue>, |
896 | session_id: SessionId, |
897 | server_name: ServerName<'static>, |
898 | using_ems: bool, |
899 | transcript: HandshakeHash, |
900 | ticket: Option<NewSessionTicketPayload>, |
901 | resuming: bool, |
902 | cert_verified: verify::ServerCertVerified, |
903 | sig_verified: verify::HandshakeSignatureValid, |
904 | } |
905 | |
906 | impl State<ClientConnectionData> for ExpectCcs { |
907 | fn handle(self: Box<Self>, cx: &mut ClientContext<'_>, m: Message) -> hs::NextStateOrError { |
908 | match m.payload { |
909 | MessagePayload::ChangeCipherSpec(..) => {} |
910 | payload => { |
911 | return Err(inappropriate_message( |
912 | &payload, |
913 | &[ContentType::ChangeCipherSpec], |
914 | )); |
915 | } |
916 | } |
917 | // CCS should not be received interleaved with fragmented handshake-level |
918 | // message. |
919 | cx.common.check_aligned_handshake()?; |
920 | |
921 | // Note: msgs layer validates trivial contents of CCS. |
922 | cx.common |
923 | .record_layer |
924 | .start_decrypting(); |
925 | |
926 | Ok(Box::new(ExpectFinished { |
927 | config: self.config, |
928 | secrets: self.secrets, |
929 | resuming_session: self.resuming_session, |
930 | session_id: self.session_id, |
931 | server_name: self.server_name, |
932 | using_ems: self.using_ems, |
933 | transcript: self.transcript, |
934 | ticket: self.ticket, |
935 | resuming: self.resuming, |
936 | cert_verified: self.cert_verified, |
937 | sig_verified: self.sig_verified, |
938 | })) |
939 | } |
940 | } |
941 | |
942 | struct ExpectFinished { |
943 | config: Arc<ClientConfig>, |
944 | resuming_session: Option<persist::Tls12ClientSessionValue>, |
945 | session_id: SessionId, |
946 | server_name: ServerName<'static>, |
947 | using_ems: bool, |
948 | transcript: HandshakeHash, |
949 | ticket: Option<NewSessionTicketPayload>, |
950 | secrets: ConnectionSecrets, |
951 | resuming: bool, |
952 | cert_verified: verify::ServerCertVerified, |
953 | sig_verified: verify::HandshakeSignatureValid, |
954 | } |
955 | |
956 | impl ExpectFinished { |
957 | // -- Waiting for their finished -- |
958 | fn save_session(&mut self, cx: &ClientContext<'_>) { |
959 | // Save a ticket. If we got a new ticket, save that. Otherwise, save the |
960 | // original ticket again. |
961 | let (mut ticket, lifetime) = match self.ticket.take() { |
962 | Some(nst) => (nst.ticket.0, nst.lifetime_hint), |
963 | None => (Vec::new(), 0), |
964 | }; |
965 | |
966 | if ticket.is_empty() { |
967 | if let Some(resuming_session) = &mut self.resuming_session { |
968 | ticket = resuming_session.take_ticket(); |
969 | } |
970 | } |
971 | |
972 | if self.session_id.is_empty() && ticket.is_empty() { |
973 | debug!("Session not saved: server didn't allocate id or ticket" ); |
974 | return; |
975 | } |
976 | |
977 | let session_value = persist::Tls12ClientSessionValue::new( |
978 | self.secrets.suite(), |
979 | self.session_id, |
980 | ticket, |
981 | self.secrets.master_secret(), |
982 | cx.common |
983 | .peer_certificates |
984 | .clone() |
985 | .unwrap_or_default(), |
986 | UnixTime::now(), |
987 | lifetime, |
988 | self.using_ems, |
989 | ); |
990 | |
991 | self.config |
992 | .resumption |
993 | .store |
994 | .set_tls12_session(self.server_name.clone(), session_value); |
995 | } |
996 | } |
997 | |
998 | impl State<ClientConnectionData> for ExpectFinished { |
999 | fn handle(self: Box<Self>, cx: &mut ClientContext<'_>, m: Message) -> hs::NextStateOrError { |
1000 | let mut st = *self; |
1001 | let finished = |
1002 | require_handshake_msg!(m, HandshakeType::Finished, HandshakePayload::Finished)?; |
1003 | |
1004 | cx.common.check_aligned_handshake()?; |
1005 | |
1006 | // Work out what verify_data we expect. |
1007 | let vh = st.transcript.get_current_hash(); |
1008 | let expect_verify_data = st.secrets.server_verify_data(&vh); |
1009 | |
1010 | // Constant-time verification of this is relatively unimportant: they only |
1011 | // get one chance. But it can't hurt. |
1012 | let _fin_verified = match ConstantTimeEq::ct_eq(&expect_verify_data[..], &finished.0).into() |
1013 | { |
1014 | true => verify::FinishedMessageVerified::assertion(), |
1015 | false => { |
1016 | return Err(cx |
1017 | .common |
1018 | .send_fatal_alert(AlertDescription::DecryptError, Error::DecryptError)); |
1019 | } |
1020 | }; |
1021 | |
1022 | // Hash this message too. |
1023 | st.transcript.add_message(&m); |
1024 | |
1025 | st.save_session(cx); |
1026 | |
1027 | if st.resuming { |
1028 | emit_ccs(cx.common); |
1029 | cx.common |
1030 | .record_layer |
1031 | .start_encrypting(); |
1032 | emit_finished(&st.secrets, &mut st.transcript, cx.common); |
1033 | } |
1034 | |
1035 | cx.common.start_traffic(); |
1036 | Ok(Box::new(ExpectTraffic { |
1037 | secrets: st.secrets, |
1038 | _cert_verified: st.cert_verified, |
1039 | _sig_verified: st.sig_verified, |
1040 | _fin_verified, |
1041 | })) |
1042 | } |
1043 | |
1044 | // we could not decrypt the encrypted handshake message with session resumption |
1045 | // this might mean that the ticket was invalid for some reason, so we remove it |
1046 | // from the store to restart a session from scratch |
1047 | fn handle_decrypt_error(&self) { |
1048 | if self.resuming { |
1049 | self.config |
1050 | .resumption |
1051 | .store |
1052 | .remove_tls12_session(&self.server_name); |
1053 | } |
1054 | } |
1055 | } |
1056 | |
1057 | // -- Traffic transit state -- |
1058 | struct ExpectTraffic { |
1059 | secrets: ConnectionSecrets, |
1060 | _cert_verified: verify::ServerCertVerified, |
1061 | _sig_verified: verify::HandshakeSignatureValid, |
1062 | _fin_verified: verify::FinishedMessageVerified, |
1063 | } |
1064 | |
1065 | impl State<ClientConnectionData> for ExpectTraffic { |
1066 | fn handle(self: Box<Self>, cx: &mut ClientContext<'_>, m: Message) -> hs::NextStateOrError { |
1067 | match m.payload { |
1068 | MessagePayload::ApplicationData(payload) => cx |
1069 | .common |
1070 | .take_received_plaintext(payload), |
1071 | payload => { |
1072 | return Err(inappropriate_message( |
1073 | &payload, |
1074 | &[ContentType::ApplicationData], |
1075 | )); |
1076 | } |
1077 | } |
1078 | Ok(self) |
1079 | } |
1080 | |
1081 | fn export_keying_material( |
1082 | &self, |
1083 | output: &mut [u8], |
1084 | label: &[u8], |
1085 | context: Option<&[u8]>, |
1086 | ) -> Result<(), Error> { |
1087 | self.secrets |
1088 | .export_keying_material(output, label, context); |
1089 | Ok(()) |
1090 | } |
1091 | |
1092 | fn extract_secrets(&self) -> Result<PartiallyExtractedSecrets, Error> { |
1093 | self.secrets |
1094 | .extract_secrets(Side::Client) |
1095 | } |
1096 | } |
1097 | |