1 | use alloc::boxed::Box; |
2 | use alloc::string::ToString; |
3 | use alloc::vec; |
4 | use alloc::vec::Vec; |
5 | |
6 | pub(super) use client_hello::CompleteClientHelloHandling; |
7 | use pki_types::UnixTime; |
8 | use subtle::ConstantTimeEq; |
9 | |
10 | use super::common::ActiveCertifiedKey; |
11 | use super::hs::{self, ServerContext}; |
12 | use super::server_conn::{ProducesTickets, ServerConfig, ServerConnectionData}; |
13 | use crate::check::inappropriate_message; |
14 | use crate::common_state::{CommonState, HandshakeFlightTls12, HandshakeKind, Side, State}; |
15 | use crate::conn::ConnectionRandoms; |
16 | use crate::crypto::ActiveKeyExchange; |
17 | use crate::enums::{AlertDescription, ContentType, HandshakeType, ProtocolVersion}; |
18 | use crate::error::{Error, PeerIncompatible, PeerMisbehaved}; |
19 | use crate::hash_hs::HandshakeHash; |
20 | use crate::log::{debug, trace}; |
21 | use crate::msgs::base::Payload; |
22 | use crate::msgs::ccs::ChangeCipherSpecPayload; |
23 | use crate::msgs::codec::Codec; |
24 | use crate::msgs::handshake::{ |
25 | CertificateChain, ClientKeyExchangeParams, HandshakeMessagePayload, HandshakePayload, |
26 | NewSessionTicketPayload, SessionId, |
27 | }; |
28 | use crate::msgs::message::{Message, MessagePayload}; |
29 | use crate::msgs::persist; |
30 | use crate::suites::PartiallyExtractedSecrets; |
31 | use crate::sync::Arc; |
32 | use crate::tls12::{self, ConnectionSecrets, Tls12CipherSuite}; |
33 | use crate::verify; |
34 | |
35 | mod client_hello { |
36 | use pki_types::CertificateDer; |
37 | |
38 | use super::*; |
39 | use crate::common_state::KxState; |
40 | use crate::crypto::SupportedKxGroup; |
41 | use crate::enums::SignatureScheme; |
42 | use crate::msgs::enums::{ClientCertificateType, Compression, ECPointFormat}; |
43 | use crate::msgs::handshake::{ |
44 | CertificateRequestPayload, CertificateStatus, ClientExtension, ClientHelloPayload, |
45 | ClientSessionTicket, Random, ServerExtension, ServerHelloPayload, ServerKeyExchange, |
46 | ServerKeyExchangeParams, ServerKeyExchangePayload, |
47 | }; |
48 | use crate::sign; |
49 | use crate::verify::DigitallySignedStruct; |
50 | |
51 | pub(in crate::server) struct CompleteClientHelloHandling { |
52 | pub(in crate::server) config: Arc<ServerConfig>, |
53 | pub(in crate::server) transcript: HandshakeHash, |
54 | pub(in crate::server) session_id: SessionId, |
55 | pub(in crate::server) suite: &'static Tls12CipherSuite, |
56 | pub(in crate::server) using_ems: bool, |
57 | pub(in crate::server) randoms: ConnectionRandoms, |
58 | pub(in crate::server) send_ticket: bool, |
59 | pub(in crate::server) extra_exts: Vec<ServerExtension>, |
60 | } |
61 | |
62 | impl CompleteClientHelloHandling { |
63 | pub(in crate::server) fn handle_client_hello( |
64 | mut self, |
65 | cx: &mut ServerContext<'_>, |
66 | server_key: ActiveCertifiedKey<'_>, |
67 | chm: &Message<'_>, |
68 | client_hello: &ClientHelloPayload, |
69 | selected_kxg: &'static dyn SupportedKxGroup, |
70 | sigschemes_ext: Vec<SignatureScheme>, |
71 | tls13_enabled: bool, |
72 | ) -> hs::NextStateOrError<'static> { |
73 | // -- TLS1.2 only from hereon in -- |
74 | self.transcript.add_message(chm); |
75 | |
76 | if client_hello.ems_support_offered() { |
77 | self.using_ems = true; |
78 | } else if self.config.require_ems { |
79 | return Err(cx.common.send_fatal_alert( |
80 | AlertDescription::HandshakeFailure, |
81 | PeerIncompatible::ExtendedMasterSecretExtensionRequired, |
82 | )); |
83 | } |
84 | |
85 | // "RFC 4492 specified that if this extension is missing, |
86 | // it means that only the uncompressed point format is |
87 | // supported" |
88 | // - <https://datatracker.ietf.org/doc/html/rfc8422#section-5.1.2> |
89 | let ecpoints_ext = client_hello |
90 | .ecpoints_extension() |
91 | .unwrap_or(&[ECPointFormat::Uncompressed]); |
92 | |
93 | trace!("ecpoints {:?}" , ecpoints_ext); |
94 | |
95 | if !ecpoints_ext.contains(&ECPointFormat::Uncompressed) { |
96 | return Err(cx.common.send_fatal_alert( |
97 | AlertDescription::IllegalParameter, |
98 | PeerIncompatible::UncompressedEcPointsRequired, |
99 | )); |
100 | } |
101 | |
102 | // -- If TLS1.3 is enabled, signal the downgrade in the server random |
103 | if tls13_enabled { |
104 | self.randoms.server[24..].copy_from_slice(&tls12::DOWNGRADE_SENTINEL); |
105 | } |
106 | |
107 | // -- Check for resumption -- |
108 | // We can do this either by (in order of preference): |
109 | // 1. receiving a ticket that decrypts |
110 | // 2. receiving a sessionid that is in our cache |
111 | // |
112 | // If we receive a ticket, the sessionid won't be in our |
113 | // cache, so don't check. |
114 | // |
115 | // If either works, we end up with a ServerConnectionValue |
116 | // which is passed to start_resumption and concludes |
117 | // our handling of the ClientHello. |
118 | // |
119 | let mut ticket_received = false; |
120 | let resume_data = client_hello |
121 | .ticket_extension() |
122 | .and_then(|ticket_ext| match ticket_ext { |
123 | ClientExtension::SessionTicket(ClientSessionTicket::Offer(ticket)) => { |
124 | Some(ticket) |
125 | } |
126 | _ => None, |
127 | }) |
128 | .and_then(|ticket| { |
129 | ticket_received = true; |
130 | debug!("Ticket received" ); |
131 | let data = self |
132 | .config |
133 | .ticketer |
134 | .decrypt(ticket.bytes()); |
135 | if data.is_none() { |
136 | debug!("Ticket didn't decrypt" ); |
137 | } |
138 | data |
139 | }) |
140 | .or_else(|| { |
141 | // Perhaps resume? If we received a ticket, the sessionid |
142 | // does not correspond to a real session. |
143 | if client_hello.session_id.is_empty() || ticket_received { |
144 | return None; |
145 | } |
146 | |
147 | self.config |
148 | .session_storage |
149 | .get(client_hello.session_id.as_ref()) |
150 | }) |
151 | .and_then(|x| persist::ServerSessionValue::read_bytes(&x).ok()) |
152 | .filter(|resumedata| { |
153 | hs::can_resume(self.suite.into(), &cx.data.sni, self.using_ems, resumedata) |
154 | }); |
155 | |
156 | if let Some(data) = resume_data { |
157 | return self.start_resumption(cx, client_hello, &client_hello.session_id, data); |
158 | } |
159 | |
160 | // Now we have chosen a ciphersuite, we can make kx decisions. |
161 | let sigschemes = self |
162 | .suite |
163 | .resolve_sig_schemes(&sigschemes_ext); |
164 | |
165 | if sigschemes.is_empty() { |
166 | return Err(cx.common.send_fatal_alert( |
167 | AlertDescription::HandshakeFailure, |
168 | PeerIncompatible::NoSignatureSchemesInCommon, |
169 | )); |
170 | } |
171 | |
172 | let ecpoint = ECPointFormat::SUPPORTED |
173 | .iter() |
174 | .find(|format| ecpoints_ext.contains(format)) |
175 | .cloned() |
176 | .ok_or_else(|| { |
177 | cx.common.send_fatal_alert( |
178 | AlertDescription::HandshakeFailure, |
179 | PeerIncompatible::NoEcPointFormatsInCommon, |
180 | ) |
181 | })?; |
182 | |
183 | debug_assert_eq!(ecpoint, ECPointFormat::Uncompressed); |
184 | |
185 | let mut ocsp_response = server_key.get_ocsp(); |
186 | |
187 | // If we're not offered a ticket or a potential session ID, allocate a session ID. |
188 | if !self.config.session_storage.can_cache() { |
189 | self.session_id = SessionId::empty(); |
190 | } else if self.session_id.is_empty() && !ticket_received { |
191 | self.session_id = SessionId::random(self.config.provider.secure_random)?; |
192 | } |
193 | |
194 | cx.common.kx_state = KxState::Start(selected_kxg); |
195 | cx.common.handshake_kind = Some(HandshakeKind::Full); |
196 | |
197 | let mut flight = HandshakeFlightTls12::new(&mut self.transcript); |
198 | |
199 | self.send_ticket = emit_server_hello( |
200 | &mut flight, |
201 | &self.config, |
202 | cx, |
203 | self.session_id, |
204 | self.suite, |
205 | self.using_ems, |
206 | &mut ocsp_response, |
207 | client_hello, |
208 | None, |
209 | &self.randoms, |
210 | self.extra_exts, |
211 | )?; |
212 | emit_certificate(&mut flight, server_key.get_cert()); |
213 | if let Some(ocsp_response) = ocsp_response { |
214 | emit_cert_status(&mut flight, ocsp_response); |
215 | } |
216 | let server_kx = emit_server_kx( |
217 | &mut flight, |
218 | sigschemes, |
219 | selected_kxg, |
220 | server_key.get_key(), |
221 | &self.randoms, |
222 | )?; |
223 | let doing_client_auth = emit_certificate_req(&mut flight, &self.config)?; |
224 | emit_server_hello_done(&mut flight); |
225 | |
226 | flight.finish(cx.common); |
227 | |
228 | if doing_client_auth { |
229 | Ok(Box::new(ExpectCertificate { |
230 | config: self.config, |
231 | transcript: self.transcript, |
232 | randoms: self.randoms, |
233 | session_id: self.session_id, |
234 | suite: self.suite, |
235 | using_ems: self.using_ems, |
236 | server_kx, |
237 | send_ticket: self.send_ticket, |
238 | })) |
239 | } else { |
240 | Ok(Box::new(ExpectClientKx { |
241 | config: self.config, |
242 | transcript: self.transcript, |
243 | randoms: self.randoms, |
244 | session_id: self.session_id, |
245 | suite: self.suite, |
246 | using_ems: self.using_ems, |
247 | server_kx, |
248 | client_cert: None, |
249 | send_ticket: self.send_ticket, |
250 | })) |
251 | } |
252 | } |
253 | |
254 | fn start_resumption( |
255 | mut self, |
256 | cx: &mut ServerContext<'_>, |
257 | client_hello: &ClientHelloPayload, |
258 | id: &SessionId, |
259 | resumedata: persist::ServerSessionValue, |
260 | ) -> hs::NextStateOrError<'static> { |
261 | debug!("Resuming connection" ); |
262 | |
263 | if resumedata.extended_ms && !self.using_ems { |
264 | return Err(cx.common.send_fatal_alert( |
265 | AlertDescription::IllegalParameter, |
266 | PeerMisbehaved::ResumptionAttemptedWithVariedEms, |
267 | )); |
268 | } |
269 | |
270 | self.session_id = *id; |
271 | let mut flight = HandshakeFlightTls12::new(&mut self.transcript); |
272 | self.send_ticket = emit_server_hello( |
273 | &mut flight, |
274 | &self.config, |
275 | cx, |
276 | self.session_id, |
277 | self.suite, |
278 | self.using_ems, |
279 | &mut None, |
280 | client_hello, |
281 | Some(&resumedata), |
282 | &self.randoms, |
283 | self.extra_exts, |
284 | )?; |
285 | flight.finish(cx.common); |
286 | |
287 | let secrets = ConnectionSecrets::new_resume( |
288 | self.randoms, |
289 | self.suite, |
290 | &resumedata.master_secret.0, |
291 | ); |
292 | self.config.key_log.log( |
293 | "CLIENT_RANDOM" , |
294 | &secrets.randoms.client, |
295 | &secrets.master_secret, |
296 | ); |
297 | cx.common |
298 | .start_encryption_tls12(&secrets, Side::Server); |
299 | cx.common.peer_certificates = resumedata.client_cert_chain; |
300 | cx.common.handshake_kind = Some(HandshakeKind::Resumed); |
301 | |
302 | if self.send_ticket { |
303 | let now = self.config.current_time()?; |
304 | |
305 | emit_ticket( |
306 | &secrets, |
307 | &mut self.transcript, |
308 | self.using_ems, |
309 | cx, |
310 | &*self.config.ticketer, |
311 | now, |
312 | )?; |
313 | } |
314 | emit_ccs(cx.common); |
315 | cx.common |
316 | .record_layer |
317 | .start_encrypting(); |
318 | emit_finished(&secrets, &mut self.transcript, cx.common); |
319 | |
320 | Ok(Box::new(ExpectCcs { |
321 | config: self.config, |
322 | secrets, |
323 | transcript: self.transcript, |
324 | session_id: self.session_id, |
325 | using_ems: self.using_ems, |
326 | resuming: true, |
327 | send_ticket: self.send_ticket, |
328 | })) |
329 | } |
330 | } |
331 | |
332 | fn emit_server_hello( |
333 | flight: &mut HandshakeFlightTls12<'_>, |
334 | config: &ServerConfig, |
335 | cx: &mut ServerContext<'_>, |
336 | session_id: SessionId, |
337 | suite: &'static Tls12CipherSuite, |
338 | using_ems: bool, |
339 | ocsp_response: &mut Option<&[u8]>, |
340 | hello: &ClientHelloPayload, |
341 | resumedata: Option<&persist::ServerSessionValue>, |
342 | randoms: &ConnectionRandoms, |
343 | extra_exts: Vec<ServerExtension>, |
344 | ) -> Result<bool, Error> { |
345 | let mut ep = hs::ExtensionProcessing::new(); |
346 | ep.process_common(config, cx, ocsp_response, hello, resumedata, extra_exts)?; |
347 | ep.process_tls12(config, hello, using_ems); |
348 | |
349 | let sh = HandshakeMessagePayload { |
350 | typ: HandshakeType::ServerHello, |
351 | payload: HandshakePayload::ServerHello(ServerHelloPayload { |
352 | legacy_version: ProtocolVersion::TLSv1_2, |
353 | random: Random::from(randoms.server), |
354 | session_id, |
355 | cipher_suite: suite.common.suite, |
356 | compression_method: Compression::Null, |
357 | extensions: ep.exts, |
358 | }), |
359 | }; |
360 | trace!("sending server hello {:?}" , sh); |
361 | flight.add(sh); |
362 | |
363 | Ok(ep.send_ticket) |
364 | } |
365 | |
366 | fn emit_certificate( |
367 | flight: &mut HandshakeFlightTls12<'_>, |
368 | cert_chain: &[CertificateDer<'static>], |
369 | ) { |
370 | flight.add(HandshakeMessagePayload { |
371 | typ: HandshakeType::Certificate, |
372 | payload: HandshakePayload::Certificate(CertificateChain(cert_chain.to_vec())), |
373 | }); |
374 | } |
375 | |
376 | fn emit_cert_status(flight: &mut HandshakeFlightTls12<'_>, ocsp: &[u8]) { |
377 | flight.add(HandshakeMessagePayload { |
378 | typ: HandshakeType::CertificateStatus, |
379 | payload: HandshakePayload::CertificateStatus(CertificateStatus::new(ocsp)), |
380 | }); |
381 | } |
382 | |
383 | fn emit_server_kx( |
384 | flight: &mut HandshakeFlightTls12<'_>, |
385 | sigschemes: Vec<SignatureScheme>, |
386 | selected_group: &'static dyn SupportedKxGroup, |
387 | signing_key: &dyn sign::SigningKey, |
388 | randoms: &ConnectionRandoms, |
389 | ) -> Result<Box<dyn ActiveKeyExchange>, Error> { |
390 | let kx = selected_group.start()?; |
391 | let kx_params = ServerKeyExchangeParams::new(&*kx); |
392 | |
393 | let mut msg = Vec::new(); |
394 | msg.extend(randoms.client); |
395 | msg.extend(randoms.server); |
396 | kx_params.encode(&mut msg); |
397 | |
398 | let signer = signing_key |
399 | .choose_scheme(&sigschemes) |
400 | .ok_or_else(|| Error::General("incompatible signing key" .to_string()))?; |
401 | let sigscheme = signer.scheme(); |
402 | let sig = signer.sign(&msg)?; |
403 | |
404 | let skx = ServerKeyExchangePayload::from(ServerKeyExchange { |
405 | params: kx_params, |
406 | dss: DigitallySignedStruct::new(sigscheme, sig), |
407 | }); |
408 | |
409 | flight.add(HandshakeMessagePayload { |
410 | typ: HandshakeType::ServerKeyExchange, |
411 | payload: HandshakePayload::ServerKeyExchange(skx), |
412 | }); |
413 | Ok(kx) |
414 | } |
415 | |
416 | fn emit_certificate_req( |
417 | flight: &mut HandshakeFlightTls12<'_>, |
418 | config: &ServerConfig, |
419 | ) -> Result<bool, Error> { |
420 | let client_auth = &config.verifier; |
421 | |
422 | if !client_auth.offer_client_auth() { |
423 | return Ok(false); |
424 | } |
425 | |
426 | let verify_schemes = client_auth.supported_verify_schemes(); |
427 | |
428 | let names = config |
429 | .verifier |
430 | .root_hint_subjects() |
431 | .to_vec(); |
432 | |
433 | let cr = CertificateRequestPayload { |
434 | certtypes: vec![ |
435 | ClientCertificateType::RSASign, |
436 | ClientCertificateType::ECDSASign, |
437 | ], |
438 | sigschemes: verify_schemes, |
439 | canames: names, |
440 | }; |
441 | |
442 | let creq = HandshakeMessagePayload { |
443 | typ: HandshakeType::CertificateRequest, |
444 | payload: HandshakePayload::CertificateRequest(cr), |
445 | }; |
446 | |
447 | trace!("Sending CertificateRequest {:?}" , creq); |
448 | flight.add(creq); |
449 | Ok(true) |
450 | } |
451 | |
452 | fn emit_server_hello_done(flight: &mut HandshakeFlightTls12<'_>) { |
453 | flight.add(HandshakeMessagePayload { |
454 | typ: HandshakeType::ServerHelloDone, |
455 | payload: HandshakePayload::ServerHelloDone, |
456 | }); |
457 | } |
458 | } |
459 | |
460 | // --- Process client's Certificate for client auth --- |
461 | struct ExpectCertificate { |
462 | config: Arc<ServerConfig>, |
463 | transcript: HandshakeHash, |
464 | randoms: ConnectionRandoms, |
465 | session_id: SessionId, |
466 | suite: &'static Tls12CipherSuite, |
467 | using_ems: bool, |
468 | server_kx: Box<dyn ActiveKeyExchange>, |
469 | send_ticket: bool, |
470 | } |
471 | |
472 | impl State<ServerConnectionData> for ExpectCertificate { |
473 | fn handle<'m>( |
474 | mut self: Box<Self>, |
475 | cx: &mut ServerContext<'_>, |
476 | m: Message<'m>, |
477 | ) -> hs::NextStateOrError<'m> |
478 | where |
479 | Self: 'm, |
480 | { |
481 | self.transcript.add_message(&m); |
482 | let cert_chain = require_handshake_msg_move!( |
483 | m, |
484 | HandshakeType::Certificate, |
485 | HandshakePayload::Certificate |
486 | )?; |
487 | |
488 | // If we can't determine if the auth is mandatory, abort |
489 | let mandatory = self |
490 | .config |
491 | .verifier |
492 | .client_auth_mandatory(); |
493 | |
494 | trace!("certs {:?}" , cert_chain); |
495 | |
496 | let client_cert = match cert_chain.split_first() { |
497 | None if mandatory => { |
498 | return Err(cx.common.send_fatal_alert( |
499 | AlertDescription::CertificateRequired, |
500 | Error::NoCertificatesPresented, |
501 | )); |
502 | } |
503 | None => { |
504 | debug!("client auth requested but no certificate supplied" ); |
505 | self.transcript.abandon_client_auth(); |
506 | None |
507 | } |
508 | Some((end_entity, intermediates)) => { |
509 | let now = self.config.current_time()?; |
510 | |
511 | self.config |
512 | .verifier |
513 | .verify_client_cert(end_entity, intermediates, now) |
514 | .map_err(|err| { |
515 | cx.common |
516 | .send_cert_verify_error_alert(err) |
517 | })?; |
518 | |
519 | Some(cert_chain) |
520 | } |
521 | }; |
522 | |
523 | Ok(Box::new(ExpectClientKx { |
524 | config: self.config, |
525 | transcript: self.transcript, |
526 | randoms: self.randoms, |
527 | session_id: self.session_id, |
528 | suite: self.suite, |
529 | using_ems: self.using_ems, |
530 | server_kx: self.server_kx, |
531 | client_cert, |
532 | send_ticket: self.send_ticket, |
533 | })) |
534 | } |
535 | |
536 | fn into_owned(self: Box<Self>) -> hs::NextState<'static> { |
537 | self |
538 | } |
539 | } |
540 | |
541 | // --- Process client's KeyExchange --- |
542 | struct ExpectClientKx<'a> { |
543 | config: Arc<ServerConfig>, |
544 | transcript: HandshakeHash, |
545 | randoms: ConnectionRandoms, |
546 | session_id: SessionId, |
547 | suite: &'static Tls12CipherSuite, |
548 | using_ems: bool, |
549 | server_kx: Box<dyn ActiveKeyExchange>, |
550 | client_cert: Option<CertificateChain<'a>>, |
551 | send_ticket: bool, |
552 | } |
553 | |
554 | impl State<ServerConnectionData> for ExpectClientKx<'_> { |
555 | fn handle<'m>( |
556 | mut self: Box<Self>, |
557 | cx: &mut ServerContext<'_>, |
558 | m: Message<'m>, |
559 | ) -> hs::NextStateOrError<'m> |
560 | where |
561 | Self: 'm, |
562 | { |
563 | let client_kx = require_handshake_msg!( |
564 | m, |
565 | HandshakeType::ClientKeyExchange, |
566 | HandshakePayload::ClientKeyExchange |
567 | )?; |
568 | self.transcript.add_message(&m); |
569 | let ems_seed = self |
570 | .using_ems |
571 | .then(|| self.transcript.current_hash()); |
572 | |
573 | // Complete key agreement, and set up encryption with the |
574 | // resulting premaster secret. |
575 | let peer_kx_params = tls12::decode_kx_params::<ClientKeyExchangeParams>( |
576 | self.suite.kx, |
577 | cx.common, |
578 | client_kx.bytes(), |
579 | )?; |
580 | let secrets = ConnectionSecrets::from_key_exchange( |
581 | self.server_kx, |
582 | peer_kx_params.pub_key(), |
583 | ems_seed, |
584 | self.randoms, |
585 | self.suite, |
586 | ) |
587 | .map_err(|err| { |
588 | cx.common |
589 | .send_fatal_alert(AlertDescription::IllegalParameter, err) |
590 | })?; |
591 | cx.common.kx_state.complete(); |
592 | |
593 | self.config.key_log.log( |
594 | "CLIENT_RANDOM" , |
595 | &secrets.randoms.client, |
596 | &secrets.master_secret, |
597 | ); |
598 | cx.common |
599 | .start_encryption_tls12(&secrets, Side::Server); |
600 | |
601 | match self.client_cert { |
602 | Some(client_cert) => Ok(Box::new(ExpectCertificateVerify { |
603 | config: self.config, |
604 | secrets, |
605 | transcript: self.transcript, |
606 | session_id: self.session_id, |
607 | using_ems: self.using_ems, |
608 | client_cert, |
609 | send_ticket: self.send_ticket, |
610 | })), |
611 | _ => Ok(Box::new(ExpectCcs { |
612 | config: self.config, |
613 | secrets, |
614 | transcript: self.transcript, |
615 | session_id: self.session_id, |
616 | using_ems: self.using_ems, |
617 | resuming: false, |
618 | send_ticket: self.send_ticket, |
619 | })), |
620 | } |
621 | } |
622 | |
623 | fn into_owned(self: Box<Self>) -> hs::NextState<'static> { |
624 | Box::new(ExpectClientKx { |
625 | config: self.config, |
626 | transcript: self.transcript, |
627 | randoms: self.randoms, |
628 | session_id: self.session_id, |
629 | suite: self.suite, |
630 | using_ems: self.using_ems, |
631 | server_kx: self.server_kx, |
632 | client_cert: self |
633 | .client_cert |
634 | .map(|cert| cert.into_owned()), |
635 | send_ticket: self.send_ticket, |
636 | }) |
637 | } |
638 | } |
639 | |
640 | // --- Process client's certificate proof --- |
641 | struct ExpectCertificateVerify<'a> { |
642 | config: Arc<ServerConfig>, |
643 | secrets: ConnectionSecrets, |
644 | transcript: HandshakeHash, |
645 | session_id: SessionId, |
646 | using_ems: bool, |
647 | client_cert: CertificateChain<'a>, |
648 | send_ticket: bool, |
649 | } |
650 | |
651 | impl State<ServerConnectionData> for ExpectCertificateVerify<'_> { |
652 | fn handle<'m>( |
653 | mut self: Box<Self>, |
654 | cx: &mut ServerContext<'_>, |
655 | m: Message<'m>, |
656 | ) -> hs::NextStateOrError<'m> |
657 | where |
658 | Self: 'm, |
659 | { |
660 | let rc = { |
661 | let sig = require_handshake_msg!( |
662 | m, |
663 | HandshakeType::CertificateVerify, |
664 | HandshakePayload::CertificateVerify |
665 | )?; |
666 | |
667 | match self.transcript.take_handshake_buf() { |
668 | Some(msgs) => { |
669 | let certs = &self.client_cert; |
670 | self.config |
671 | .verifier |
672 | .verify_tls12_signature(&msgs, &certs[0], sig) |
673 | } |
674 | None => { |
675 | // This should be unreachable; the handshake buffer was initialized with |
676 | // client authentication if the verifier wants to offer it. |
677 | // `transcript.abandon_client_auth()` can extract it, but its only caller in |
678 | // this flow will also set `ExpectClientKx::client_cert` to `None`, making it |
679 | // impossible to reach this state. |
680 | return Err(cx.common.send_fatal_alert( |
681 | AlertDescription::AccessDenied, |
682 | Error::General("client authentication not set up" .into()), |
683 | )); |
684 | } |
685 | } |
686 | }; |
687 | |
688 | if let Err(e) = rc { |
689 | return Err(cx |
690 | .common |
691 | .send_cert_verify_error_alert(e)); |
692 | } |
693 | |
694 | trace!("client CertificateVerify OK" ); |
695 | cx.common.peer_certificates = Some(self.client_cert.into_owned()); |
696 | |
697 | self.transcript.add_message(&m); |
698 | Ok(Box::new(ExpectCcs { |
699 | config: self.config, |
700 | secrets: self.secrets, |
701 | transcript: self.transcript, |
702 | session_id: self.session_id, |
703 | using_ems: self.using_ems, |
704 | resuming: false, |
705 | send_ticket: self.send_ticket, |
706 | })) |
707 | } |
708 | |
709 | fn into_owned(self: Box<Self>) -> hs::NextState<'static> { |
710 | Box::new(ExpectCertificateVerify { |
711 | config: self.config, |
712 | secrets: self.secrets, |
713 | transcript: self.transcript, |
714 | session_id: self.session_id, |
715 | using_ems: self.using_ems, |
716 | client_cert: self.client_cert.into_owned(), |
717 | send_ticket: self.send_ticket, |
718 | }) |
719 | } |
720 | } |
721 | |
722 | // --- Process client's ChangeCipherSpec --- |
723 | struct ExpectCcs { |
724 | config: Arc<ServerConfig>, |
725 | secrets: ConnectionSecrets, |
726 | transcript: HandshakeHash, |
727 | session_id: SessionId, |
728 | using_ems: bool, |
729 | resuming: bool, |
730 | send_ticket: bool, |
731 | } |
732 | |
733 | impl State<ServerConnectionData> for ExpectCcs { |
734 | fn handle<'m>( |
735 | self: Box<Self>, |
736 | cx: &mut ServerContext<'_>, |
737 | m: Message<'m>, |
738 | ) -> hs::NextStateOrError<'m> |
739 | where |
740 | Self: 'm, |
741 | { |
742 | match m.payload { |
743 | MessagePayload::ChangeCipherSpec(..) => {} |
744 | payload => { |
745 | return Err(inappropriate_message( |
746 | &payload, |
747 | &[ContentType::ChangeCipherSpec], |
748 | )); |
749 | } |
750 | } |
751 | |
752 | // CCS should not be received interleaved with fragmented handshake-level |
753 | // message. |
754 | cx.common.check_aligned_handshake()?; |
755 | |
756 | cx.common |
757 | .record_layer |
758 | .start_decrypting(); |
759 | Ok(Box::new(ExpectFinished { |
760 | config: self.config, |
761 | secrets: self.secrets, |
762 | transcript: self.transcript, |
763 | session_id: self.session_id, |
764 | using_ems: self.using_ems, |
765 | resuming: self.resuming, |
766 | send_ticket: self.send_ticket, |
767 | })) |
768 | } |
769 | |
770 | fn into_owned(self: Box<Self>) -> hs::NextState<'static> { |
771 | self |
772 | } |
773 | } |
774 | |
775 | // --- Process client's Finished --- |
776 | fn get_server_connection_value_tls12( |
777 | secrets: &ConnectionSecrets, |
778 | using_ems: bool, |
779 | cx: &ServerContext<'_>, |
780 | time_now: UnixTime, |
781 | ) -> persist::ServerSessionValue { |
782 | let version: ProtocolVersion = ProtocolVersion::TLSv1_2; |
783 | |
784 | let mut v: ServerSessionValue = persist::ServerSessionValue::new( |
785 | cx.data.sni.as_ref(), |
786 | v:version, |
787 | cs:secrets.suite().common.suite, |
788 | ms:secrets.master_secret(), |
789 | client_cert_chain:cx.common.peer_certificates.clone(), |
790 | alpn:cx.common.alpn_protocol.clone(), |
791 | application_data:cx.data.resumption_data.clone(), |
792 | creation_time:time_now, |
793 | age_obfuscation_offset:0, |
794 | ); |
795 | |
796 | if using_ems { |
797 | v.set_extended_ms_used(); |
798 | } |
799 | |
800 | v |
801 | } |
802 | |
803 | fn emit_ticket( |
804 | secrets: &ConnectionSecrets, |
805 | transcript: &mut HandshakeHash, |
806 | using_ems: bool, |
807 | cx: &mut ServerContext<'_>, |
808 | ticketer: &dyn ProducesTickets, |
809 | now: UnixTime, |
810 | ) -> Result<(), Error> { |
811 | let plain = get_server_connection_value_tls12(secrets, using_ems, cx, now).get_encoding(); |
812 | |
813 | // If we can't produce a ticket for some reason, we can't |
814 | // report an error. Send an empty one. |
815 | let ticket = ticketer |
816 | .encrypt(&plain) |
817 | .unwrap_or_default(); |
818 | let ticket_lifetime = ticketer.lifetime(); |
819 | |
820 | let m = Message { |
821 | version: ProtocolVersion::TLSv1_2, |
822 | payload: MessagePayload::handshake(HandshakeMessagePayload { |
823 | typ: HandshakeType::NewSessionTicket, |
824 | payload: HandshakePayload::NewSessionTicket(NewSessionTicketPayload::new( |
825 | ticket_lifetime, |
826 | ticket, |
827 | )), |
828 | }), |
829 | }; |
830 | |
831 | transcript.add_message(&m); |
832 | cx.common.send_msg(m, false); |
833 | Ok(()) |
834 | } |
835 | |
836 | fn emit_ccs(common: &mut CommonState) { |
837 | let m: Message<'_> = Message { |
838 | version: ProtocolVersion::TLSv1_2, |
839 | payload: MessagePayload::ChangeCipherSpec(ChangeCipherSpecPayload {}), |
840 | }; |
841 | |
842 | common.send_msg(m, must_encrypt:false); |
843 | } |
844 | |
845 | fn emit_finished( |
846 | secrets: &ConnectionSecrets, |
847 | transcript: &mut HandshakeHash, |
848 | common: &mut CommonState, |
849 | ) { |
850 | let vh: Output = transcript.current_hash(); |
851 | let verify_data: Vec = secrets.server_verify_data(&vh); |
852 | let verify_data_payload: Payload<'static> = Payload::new(bytes:verify_data); |
853 | |
854 | let f: Message<'_> = Message { |
855 | version: ProtocolVersion::TLSv1_2, |
856 | payload: MessagePayload::handshake(parsed:HandshakeMessagePayload { |
857 | typ: HandshakeType::Finished, |
858 | payload: HandshakePayload::Finished(verify_data_payload), |
859 | }), |
860 | }; |
861 | |
862 | transcript.add_message(&f); |
863 | common.send_msg(m:f, must_encrypt:true); |
864 | } |
865 | |
866 | struct ExpectFinished { |
867 | config: Arc<ServerConfig>, |
868 | secrets: ConnectionSecrets, |
869 | transcript: HandshakeHash, |
870 | session_id: SessionId, |
871 | using_ems: bool, |
872 | resuming: bool, |
873 | send_ticket: bool, |
874 | } |
875 | |
876 | impl State<ServerConnectionData> for ExpectFinished { |
877 | fn handle<'m>( |
878 | mut self: Box<Self>, |
879 | cx: &mut ServerContext<'_>, |
880 | m: Message<'m>, |
881 | ) -> hs::NextStateOrError<'m> |
882 | where |
883 | Self: 'm, |
884 | { |
885 | let finished = |
886 | require_handshake_msg!(m, HandshakeType::Finished, HandshakePayload::Finished)?; |
887 | |
888 | cx.common.check_aligned_handshake()?; |
889 | |
890 | let vh = self.transcript.current_hash(); |
891 | let expect_verify_data = self.secrets.client_verify_data(&vh); |
892 | |
893 | let _fin_verified = |
894 | match ConstantTimeEq::ct_eq(&expect_verify_data[..], finished.bytes()).into() { |
895 | true => verify::FinishedMessageVerified::assertion(), |
896 | false => { |
897 | return Err(cx |
898 | .common |
899 | .send_fatal_alert(AlertDescription::DecryptError, Error::DecryptError)); |
900 | } |
901 | }; |
902 | |
903 | // Save connection, perhaps |
904 | if !self.resuming && !self.session_id.is_empty() { |
905 | let now = self.config.current_time()?; |
906 | |
907 | let value = get_server_connection_value_tls12(&self.secrets, self.using_ems, cx, now); |
908 | |
909 | let worked = self |
910 | .config |
911 | .session_storage |
912 | .put(self.session_id.as_ref().to_vec(), value.get_encoding()); |
913 | if worked { |
914 | debug!("Session saved" ); |
915 | } else { |
916 | debug!("Session not saved" ); |
917 | } |
918 | } |
919 | |
920 | // Send our CCS and Finished. |
921 | self.transcript.add_message(&m); |
922 | if !self.resuming { |
923 | if self.send_ticket { |
924 | let now = self.config.current_time()?; |
925 | emit_ticket( |
926 | &self.secrets, |
927 | &mut self.transcript, |
928 | self.using_ems, |
929 | cx, |
930 | &*self.config.ticketer, |
931 | now, |
932 | )?; |
933 | } |
934 | emit_ccs(cx.common); |
935 | cx.common |
936 | .record_layer |
937 | .start_encrypting(); |
938 | emit_finished(&self.secrets, &mut self.transcript, cx.common); |
939 | } |
940 | |
941 | cx.common |
942 | .start_traffic(&mut cx.sendable_plaintext); |
943 | Ok(Box::new(ExpectTraffic { |
944 | secrets: self.secrets, |
945 | _fin_verified, |
946 | })) |
947 | } |
948 | |
949 | fn into_owned(self: Box<Self>) -> hs::NextState<'static> { |
950 | self |
951 | } |
952 | } |
953 | |
954 | // --- Process traffic --- |
955 | struct ExpectTraffic { |
956 | secrets: ConnectionSecrets, |
957 | _fin_verified: verify::FinishedMessageVerified, |
958 | } |
959 | |
960 | impl ExpectTraffic {} |
961 | |
962 | impl State<ServerConnectionData> for ExpectTraffic { |
963 | fn handle<'m>( |
964 | self: Box<Self>, |
965 | cx: &mut ServerContext<'_>, |
966 | m: Message<'m>, |
967 | ) -> hs::NextStateOrError<'m> |
968 | where |
969 | Self: 'm, |
970 | { |
971 | match m.payload { |
972 | MessagePayload::ApplicationData(payload) => cx |
973 | .common |
974 | .take_received_plaintext(payload), |
975 | payload => { |
976 | return Err(inappropriate_message( |
977 | &payload, |
978 | &[ContentType::ApplicationData], |
979 | )); |
980 | } |
981 | } |
982 | Ok(self) |
983 | } |
984 | |
985 | fn export_keying_material( |
986 | &self, |
987 | output: &mut [u8], |
988 | label: &[u8], |
989 | context: Option<&[u8]>, |
990 | ) -> Result<(), Error> { |
991 | self.secrets |
992 | .export_keying_material(output, label, context); |
993 | Ok(()) |
994 | } |
995 | |
996 | fn extract_secrets(&self) -> Result<PartiallyExtractedSecrets, Error> { |
997 | self.secrets |
998 | .extract_secrets(Side::Server) |
999 | } |
1000 | |
1001 | fn into_owned(self: Box<Self>) -> hs::NextState<'static> { |
1002 | self |
1003 | } |
1004 | } |
1005 | |