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