1use crate::anchors;
2use crate::error::TLSError;
3use crate::key;
4use crate::keylog::{KeyLog, NoKeyLog};
5#[cfg(feature = "logging")]
6use crate::log::trace;
7use crate::msgs::enums::CipherSuite;
8use crate::msgs::enums::SignatureScheme;
9use crate::msgs::enums::{AlertDescription, HandshakeType};
10use crate::msgs::enums::{ContentType, ProtocolVersion};
11use crate::msgs::handshake::CertificatePayload;
12use crate::msgs::handshake::ClientExtension;
13use crate::msgs::message::Message;
14use crate::session::{MiddleboxCCS, Session, SessionCommon};
15use crate::sign;
16use crate::suites::{SupportedCipherSuite, ALL_CIPHERSUITES};
17use crate::verify;
18
19use std::fmt;
20use std::io::{self, IoSlice};
21use std::mem;
22use std::sync::Arc;
23
24use sct;
25use webpki;
26
27#[macro_use]
28mod hs;
29mod common;
30pub mod handy;
31mod tls12;
32mod tls13;
33
34pub trait StoresClientSessions: Send + Sync {
46 fn put(&self, key: Vec<u8>, value: Vec<u8>) -> bool;
49
50 fn get(&self, key: &[u8]) -> Option<Vec<u8>>;
53}
54
55pub trait ResolvesClientCert: Send + Sync {
58 fn resolve(
70 &self,
71 acceptable_issuers: &[&[u8]],
72 sigschemes: &[SignatureScheme],
73 ) -> Option<sign::CertifiedKey>;
74
75 fn has_certs(&self) -> bool;
77}
78
79#[derive(Clone)]
85pub struct ClientConfig {
86 pub ciphersuites: Vec<&'static SupportedCipherSuite>,
88
89 pub root_store: anchors::RootCertStore,
91
92 pub alpn_protocols: Vec<Vec<u8>>,
95
96 pub session_persistence: Arc<dyn StoresClientSessions>,
98
99 pub mtu: Option<usize>,
101
102 pub client_auth_cert_resolver: Arc<dyn ResolvesClientCert>,
104
105 pub enable_tickets: bool,
111
112 pub versions: Vec<ProtocolVersion>,
115
116 pub ct_logs: Option<&'static [&'static sct::Log<'static>]>,
120
121 pub enable_sni: bool,
126
127 verifier: Arc<dyn verify::ServerCertVerifier>,
129
130 pub key_log: Arc<dyn KeyLog>,
133
134 pub enable_early_data: bool,
139}
140
141impl Default for ClientConfig {
142 fn default() -> Self {
143 Self::new()
144 }
145}
146
147impl ClientConfig {
148 pub fn new() -> ClientConfig {
154 ClientConfig::with_ciphersuites(&ALL_CIPHERSUITES)
155 }
156
157 pub fn with_ciphersuites(ciphersuites: &[&'static SupportedCipherSuite]) -> ClientConfig {
163 ClientConfig {
164 ciphersuites: ciphersuites.to_vec(),
165 root_store: anchors::RootCertStore::empty(),
166 alpn_protocols: Vec::new(),
167 session_persistence: handy::ClientSessionMemoryCache::new(32),
168 mtu: None,
169 client_auth_cert_resolver: Arc::new(handy::FailResolveClientCert {}),
170 enable_tickets: true,
171 versions: vec![ProtocolVersion::TLSv1_3, ProtocolVersion::TLSv1_2],
172 ct_logs: None,
173 enable_sni: true,
174 verifier: Arc::new(verify::WebPKIVerifier::new()),
175 key_log: Arc::new(NoKeyLog {}),
176 enable_early_data: false,
177 }
178 }
179
180 #[doc(hidden)]
181 pub fn supports_version(&self, v: ProtocolVersion) -> bool {
185 self.versions.contains(&v)
186 && self
187 .ciphersuites
188 .iter()
189 .any(|cs| cs.usable_for_version(v))
190 }
191
192 #[doc(hidden)]
193 pub fn get_verifier(&self) -> &dyn verify::ServerCertVerifier {
194 self.verifier.as_ref()
195 }
196
197 pub fn set_protocols(&mut self, protocols: &[Vec<u8>]) {
202 self.alpn_protocols.clear();
203 self.alpn_protocols
204 .extend_from_slice(protocols);
205 }
206
207 pub fn set_persistence(&mut self, persist: Arc<dyn StoresClientSessions>) {
209 self.session_persistence = persist;
210 }
211
212 pub fn set_mtu(&mut self, mtu: &Option<usize>) {
215 if let Some(x) = *mtu {
221 use crate::msgs::fragmenter;
222 debug_assert!(x > fragmenter::PACKET_OVERHEAD);
223 self.mtu = Some(x - fragmenter::PACKET_OVERHEAD);
224 } else {
225 self.mtu = None;
226 }
227 }
228
229 pub fn set_single_client_cert(
235 &mut self,
236 cert_chain: Vec<key::Certificate>,
237 key_der: key::PrivateKey,
238 ) -> Result<(), TLSError> {
239 let resolver = handy::AlwaysResolvesClientCert::new(cert_chain, &key_der)?;
240 self.client_auth_cert_resolver = Arc::new(resolver);
241 Ok(())
242 }
243
244 #[cfg(feature = "dangerous_configuration")]
247 pub fn dangerous(&mut self) -> danger::DangerousClientConfig {
248 danger::DangerousClientConfig { cfg: self }
249 }
250}
251
252#[cfg(feature = "dangerous_configuration")]
254pub mod danger {
255 use std::sync::Arc;
256
257 use super::verify::ServerCertVerifier;
258 use super::ClientConfig;
259
260 pub struct DangerousClientConfig<'a> {
262 pub cfg: &'a mut ClientConfig,
264 }
265
266 impl<'a> DangerousClientConfig<'a> {
267 pub fn set_certificate_verifier(&mut self, verifier: Arc<dyn ServerCertVerifier>) {
269 self.cfg.verifier = verifier;
270 }
271 }
272}
273
274#[derive(Debug, PartialEq)]
275enum EarlyDataState {
276 Disabled,
277 Ready,
278 Accepted,
279 AcceptedFinished,
280 Rejected,
281}
282
283pub struct EarlyData {
284 state: EarlyDataState,
285 left: usize,
286}
287
288impl EarlyData {
289 fn new() -> EarlyData {
290 EarlyData {
291 left: 0,
292 state: EarlyDataState::Disabled,
293 }
294 }
295
296 fn is_enabled(&self) -> bool {
297 match self.state {
298 EarlyDataState::Ready | EarlyDataState::Accepted => true,
299 _ => false,
300 }
301 }
302
303 fn is_accepted(&self) -> bool {
304 match self.state {
305 EarlyDataState::Accepted | EarlyDataState::AcceptedFinished => true,
306 _ => false,
307 }
308 }
309
310 fn enable(&mut self, max_data: usize) {
311 assert_eq!(self.state, EarlyDataState::Disabled);
312 self.state = EarlyDataState::Ready;
313 self.left = max_data;
314 }
315
316 fn rejected(&mut self) {
317 trace!("EarlyData rejected");
318 self.state = EarlyDataState::Rejected;
319 }
320
321 fn accepted(&mut self) {
322 trace!("EarlyData accepted");
323 assert_eq!(self.state, EarlyDataState::Ready);
324 self.state = EarlyDataState::Accepted;
325 }
326
327 fn finished(&mut self) {
328 trace!("EarlyData finished");
329 self.state = match self.state {
330 EarlyDataState::Accepted => EarlyDataState::AcceptedFinished,
331 _ => panic!("bad EarlyData state"),
332 }
333 }
334
335 fn check_write(&mut self, sz: usize) -> io::Result<usize> {
336 match self.state {
337 EarlyDataState::Disabled => unreachable!(),
338 EarlyDataState::Ready | EarlyDataState::Accepted => {
339 let take = if self.left < sz {
340 mem::replace(&mut self.left, 0)
341 } else {
342 self.left -= sz;
343 sz
344 };
345
346 Ok(take)
347 }
348 EarlyDataState::Rejected | EarlyDataState::AcceptedFinished => {
349 Err(io::Error::from(io::ErrorKind::InvalidInput))
350 }
351 }
352 }
353
354 fn bytes_left(&self) -> usize {
355 self.left
356 }
357}
358
359pub struct WriteEarlyData<'a> {
361 sess: &'a mut ClientSessionImpl,
362}
363
364impl<'a> WriteEarlyData<'a> {
365 fn new(sess: &'a mut ClientSessionImpl) -> WriteEarlyData<'a> {
366 WriteEarlyData { sess }
367 }
368
369 pub fn bytes_left(&self) -> usize {
372 self.sess.early_data.bytes_left()
373 }
374}
375
376impl<'a> io::Write for WriteEarlyData<'a> {
377 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
378 self.sess.write_early_data(buf)
379 }
380
381 fn flush(&mut self) -> io::Result<()> {
382 Ok(())
383 }
384}
385
386pub struct ClientSessionImpl {
387 pub config: Arc<ClientConfig>,
388 pub alpn_protocol: Option<Vec<u8>>,
389 pub common: SessionCommon,
390 pub error: Option<TLSError>,
391 pub state: Option<hs::NextState>,
392 pub server_cert_chain: CertificatePayload,
393 pub early_data: EarlyData,
394 pub resumption_ciphersuite: Option<&'static SupportedCipherSuite>,
395}
396
397impl fmt::Debug for ClientSessionImpl {
398 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
399 f.debug_struct("ClientSessionImpl")
400 .finish()
401 }
402}
403
404impl ClientSessionImpl {
405 pub fn new(config: &Arc<ClientConfig>) -> ClientSessionImpl {
406 ClientSessionImpl {
407 config: config.clone(),
408 alpn_protocol: None,
409 common: SessionCommon::new(config.mtu, true),
410 error: None,
411 state: None,
412 server_cert_chain: Vec::new(),
413 early_data: EarlyData::new(),
414 resumption_ciphersuite: None,
415 }
416 }
417
418 pub fn start_handshake(&mut self, hostname: webpki::DNSName, extra_exts: Vec<ClientExtension>) {
419 self.state = Some(hs::start_handshake(self, hostname, extra_exts));
420 }
421
422 pub fn get_cipher_suites(&self) -> Vec<CipherSuite> {
423 let mut ret = Vec::new();
424
425 for cs in &self.config.ciphersuites {
426 ret.push(cs.suite);
427 }
428
429 ret.push(CipherSuite::TLS_EMPTY_RENEGOTIATION_INFO_SCSV);
431
432 ret
433 }
434
435 pub fn find_cipher_suite(&self, suite: CipherSuite) -> Option<&'static SupportedCipherSuite> {
436 for scs in &self.config.ciphersuites {
437 if scs.suite == suite {
438 return Some(scs);
439 }
440 }
441
442 None
443 }
444
445 pub fn wants_read(&self) -> bool {
446 !self.common.has_readable_plaintext()
453 }
454
455 pub fn wants_write(&self) -> bool {
456 !self.common.sendable_tls.is_empty()
457 }
458
459 pub fn is_handshaking(&self) -> bool {
460 !self.common.traffic
461 }
462
463 pub fn set_buffer_limit(&mut self, len: usize) {
464 self.common.set_buffer_limit(len)
465 }
466
467 pub fn process_msg(&mut self, mut msg: Message) -> Result<(), TLSError> {
468 if let MiddleboxCCS::Drop = self.common.filter_tls13_ccs(&msg)? {
470 trace!("Dropping CCS");
471 return Ok(());
472 }
473
474 if self.common.record_layer.is_decrypting() {
476 let dm = self.common.decrypt_incoming(msg)?;
477 msg = dm;
478 }
479
480 if self
483 .common
484 .handshake_joiner
485 .want_message(&msg)
486 {
487 self.common
488 .handshake_joiner
489 .take_message(msg)
490 .ok_or_else(|| {
491 self.common
492 .send_fatal_alert(AlertDescription::DecodeError);
493 TLSError::CorruptMessagePayload(ContentType::Handshake)
494 })?;
495 return self.process_new_handshake_messages();
496 }
497
498 if !msg.decode_payload() {
500 return Err(TLSError::CorruptMessagePayload(msg.typ));
501 }
502
503 if msg.is_content_type(ContentType::Alert) {
505 return self.common.process_alert(msg);
506 }
507
508 self.process_main_protocol(msg)
509 }
510
511 pub fn process_new_handshake_messages(&mut self) -> Result<(), TLSError> {
512 while let Some(msg) = self
513 .common
514 .handshake_joiner
515 .frames
516 .pop_front()
517 {
518 self.process_main_protocol(msg)?;
519 }
520
521 Ok(())
522 }
523
524 fn reject_renegotiation_attempt(&mut self) -> Result<(), TLSError> {
525 self.common
526 .send_warning_alert(AlertDescription::NoRenegotiation);
527 Ok(())
528 }
529
530 fn queue_unexpected_alert(&mut self) {
531 self.common
532 .send_fatal_alert(AlertDescription::UnexpectedMessage);
533 }
534
535 fn maybe_send_unexpected_alert(&mut self, rc: hs::NextStateOrError) -> hs::NextStateOrError {
536 match rc {
537 Err(TLSError::InappropriateMessage { .. })
538 | Err(TLSError::InappropriateHandshakeMessage { .. }) => {
539 self.queue_unexpected_alert();
540 }
541 _ => {}
542 };
543 rc
544 }
545
546 fn process_main_protocol(&mut self, msg: Message) -> Result<(), TLSError> {
550 if msg.is_handshake_type(HandshakeType::HelloRequest)
553 && !self.common.is_tls13()
554 && !self.is_handshaking()
555 {
556 return self.reject_renegotiation_attempt();
557 }
558
559 let state = self.state.take().unwrap();
560 let maybe_next_state = state.handle(self, msg);
561 let next_state = self.maybe_send_unexpected_alert(maybe_next_state)?;
562 self.state = Some(next_state);
563
564 Ok(())
565 }
566
567 pub fn process_new_packets(&mut self) -> Result<(), TLSError> {
568 if let Some(ref err) = self.error {
569 return Err(err.clone());
570 }
571
572 if self.common.message_deframer.desynced {
573 return Err(TLSError::CorruptMessage);
574 }
575
576 while let Some(msg) = self
577 .common
578 .message_deframer
579 .frames
580 .pop_front()
581 {
582 match self.process_msg(msg) {
583 Ok(_) => {}
584 Err(err) => {
585 self.error = Some(err.clone());
586 return Err(err);
587 }
588 }
589 }
590
591 Ok(())
592 }
593
594 pub fn get_peer_certificates(&self) -> Option<Vec<key::Certificate>> {
595 if self.server_cert_chain.is_empty() {
596 return None;
597 }
598
599 Some(
600 self.server_cert_chain
601 .iter()
602 .cloned()
603 .collect(),
604 )
605 }
606
607 pub fn get_alpn_protocol(&self) -> Option<&[u8]> {
608 self.alpn_protocol
609 .as_ref()
610 .map(AsRef::as_ref)
611 }
612
613 pub fn get_protocol_version(&self) -> Option<ProtocolVersion> {
614 self.common.negotiated_version
615 }
616
617 pub fn get_negotiated_ciphersuite(&self) -> Option<&'static SupportedCipherSuite> {
618 self.common.get_suite()
619 }
620
621 pub fn write_early_data(&mut self, data: &[u8]) -> io::Result<usize> {
622 self.early_data
623 .check_write(data.len())
624 .and_then(|sz| {
625 Ok(self
626 .common
627 .send_early_plaintext(&data[..sz]))
628 })
629 }
630
631 fn export_keying_material(
632 &self,
633 output: &mut [u8],
634 label: &[u8],
635 context: Option<&[u8]>,
636 ) -> Result<(), TLSError> {
637 self.state
638 .as_ref()
639 .ok_or_else(|| TLSError::HandshakeNotComplete)
640 .and_then(|st| st.export_keying_material(output, label, context))
641 }
642
643 fn send_some_plaintext(&mut self, buf: &[u8]) -> usize {
644 let mut st = self.state.take();
645 st.as_mut()
646 .map(|st| st.perhaps_write_key_update(self));
647 self.state = st;
648
649 self.common.send_some_plaintext(buf)
650 }
651}
652
653#[derive(Debug)]
655pub struct ClientSession {
656 pub(crate) imp: ClientSessionImpl,
658}
659
660impl ClientSession {
661 pub fn new(config: &Arc<ClientConfig>, hostname: webpki::DNSNameRef) -> ClientSession {
665 let mut imp = ClientSessionImpl::new(config);
666 imp.start_handshake(hostname.into(), vec![]);
667 ClientSession { imp }
668 }
669
670 pub fn early_data(&mut self) -> Option<WriteEarlyData> {
689 if self.imp.early_data.is_enabled() {
690 Some(WriteEarlyData::new(&mut self.imp))
691 } else {
692 None
693 }
694 }
695
696 pub fn is_early_data_accepted(&self) -> bool {
702 self.imp.early_data.is_accepted()
703 }
704}
705
706impl Session for ClientSession {
707 fn read_tls(&mut self, rd: &mut dyn io::Read) -> io::Result<usize> {
708 self.imp.common.read_tls(rd)
709 }
710
711 fn write_tls(&mut self, wr: &mut dyn io::Write) -> io::Result<usize> {
713 self.imp.common.write_tls(wr)
714 }
715
716 fn process_new_packets(&mut self) -> Result<(), TLSError> {
717 self.imp.process_new_packets()
718 }
719
720 fn wants_read(&self) -> bool {
721 self.imp.wants_read()
722 }
723
724 fn wants_write(&self) -> bool {
725 self.imp.wants_write()
726 }
727
728 fn is_handshaking(&self) -> bool {
729 self.imp.is_handshaking()
730 }
731
732 fn set_buffer_limit(&mut self, len: usize) {
733 self.imp.set_buffer_limit(len)
734 }
735
736 fn send_close_notify(&mut self) {
737 self.imp.common.send_close_notify()
738 }
739
740 fn get_peer_certificates(&self) -> Option<Vec<key::Certificate>> {
741 self.imp.get_peer_certificates()
742 }
743
744 fn get_alpn_protocol(&self) -> Option<&[u8]> {
745 self.imp.get_alpn_protocol()
746 }
747
748 fn get_protocol_version(&self) -> Option<ProtocolVersion> {
749 self.imp.get_protocol_version()
750 }
751
752 fn export_keying_material(
753 &self,
754 output: &mut [u8],
755 label: &[u8],
756 context: Option<&[u8]>,
757 ) -> Result<(), TLSError> {
758 self.imp
759 .export_keying_material(output, label, context)
760 }
761
762 fn get_negotiated_ciphersuite(&self) -> Option<&'static SupportedCipherSuite> {
763 self.imp
764 .get_negotiated_ciphersuite()
765 .or(self.imp.resumption_ciphersuite)
766 }
767}
768
769impl io::Read for ClientSession {
770 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
783 self.imp.common.read(buf)
784 }
785}
786
787impl io::Write for ClientSession {
788 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
799 Ok(self.imp.send_some_plaintext(buf))
800 }
801
802 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
803 let mut sz = 0;
804 for buf in bufs {
805 sz += self.imp.send_some_plaintext(buf);
806 }
807 Ok(sz)
808 }
809
810 fn flush(&mut self) -> io::Result<()> {
811 self.imp.common.flush_plaintext();
812 Ok(())
813 }
814}