1use alloc::vec::Vec;
2
3use crate::compress;
4use crate::crypto::{SelectedCredential, SignatureScheme};
5use crate::enums::CertificateType;
6use crate::log::{debug, trace};
7use crate::msgs::enums::ExtensionType;
8use crate::msgs::handshake::{CertificateChain, ProtocolName, ServerExtensions};
9pub use crate::msgs::persist::{Tls12ClientSessionValue, Tls13ClientSessionValue};
10use crate::verify::DistinguishedName;
11pub use crate::webpki::{
12 ServerVerifierBuilder, VerifierBuilderError, WebPkiServerVerifier,
13 verify_identity_signed_by_trust_anchor, verify_server_name,
14};
15
16mod config;
17pub use config::{
18 ClientConfig, ClientCredentialResolver, ClientSessionKey, ClientSessionStore,
19 CredentialRequest, Resumption, Tls12Resumption, WantsClientCert,
20};
21
22mod connection;
23#[cfg(feature = "std")]
24pub use connection::{ClientConnection, WriteEarlyData};
25pub use connection::{
26 ClientConnectionData, EarlyDataError, MayEncryptEarlyData, UnbufferedClientConnection,
27};
28
29mod ech;
30pub use ech::{EchConfig, EchGreaseConfig, EchMode, EchStatus};
31
32mod handy;
33#[cfg(any(feature = "std", feature = "hashbrown"))]
34pub use handy::ClientSessionMemoryCache;
35
36mod hs;
37pub(crate) use hs::ClientHandler;
38
39mod tls12;
40pub(crate) use tls12::TLS12_HANDLER;
41
42mod tls13;
43pub(crate) use tls13::TLS13_HANDLER;
44
45pub mod danger {
47 pub use super::config::danger::{DangerousClientConfig, DangerousClientConfigBuilder};
48 pub use crate::verify::{
49 HandshakeSignatureValid, PeerVerified, ServerIdentity, ServerVerifier,
50 SignatureVerificationInput,
51 };
52}
53
54#[cfg(test)]
55mod test;
56
57#[derive(Debug)]
58struct ServerCertDetails {
59 cert_chain: CertificateChain<'static>,
60 ocsp_response: Vec<u8>,
61}
62
63impl ServerCertDetails {
64 fn new(cert_chain: CertificateChain<'static>, ocsp_response: Vec<u8>) -> Self {
65 Self {
66 cert_chain,
67 ocsp_response,
68 }
69 }
70}
71
72struct ClientHelloDetails {
73 alpn_protocols: Vec<ProtocolName>,
74 sent_extensions: Vec<ExtensionType>,
75 extension_order_seed: u16,
76 offered_cert_compression: bool,
77}
78
79impl ClientHelloDetails {
80 fn new(alpn_protocols: Vec<ProtocolName>, extension_order_seed: u16) -> Self {
81 Self {
82 alpn_protocols,
83 sent_extensions: Vec::new(),
84 extension_order_seed,
85 offered_cert_compression: false,
86 }
87 }
88
89 fn server_sent_unsolicited_extensions(
90 &self,
91 received_exts: &ServerExtensions<'_>,
92 allowed_unsolicited: &[ExtensionType],
93 ) -> bool {
94 let mut extensions = received_exts.collect_used();
95 extensions.extend(
96 received_exts
97 .unknown_extensions
98 .iter()
99 .map(|ext| ExtensionType::from(*ext)),
100 );
101 for ext_type in extensions {
102 if !self.sent_extensions.contains(&ext_type) && !allowed_unsolicited.contains(&ext_type)
103 {
104 trace!("Unsolicited extension {ext_type:?}");
105 return true;
106 }
107 }
108
109 false
110 }
111}
112
113enum ClientAuthDetails {
114 Empty { auth_context_tls13: Option<Vec<u8>> },
116 Verify {
118 credentials: SelectedCredential,
119 auth_context_tls13: Option<Vec<u8>>,
120 compressor: Option<&'static dyn compress::CertCompressor>,
121 },
122}
123
124impl ClientAuthDetails {
125 fn resolve(
126 negotiated_type: CertificateType,
127 resolver: &dyn ClientCredentialResolver,
128 root_hint_subjects: Option<&[DistinguishedName]>,
129 signature_schemes: &[SignatureScheme],
130 auth_context_tls13: Option<Vec<u8>>,
131 compressor: Option<&'static dyn compress::CertCompressor>,
132 ) -> Self {
133 let server_hello = CredentialRequest {
134 negotiated_type,
135 signature_schemes,
136 root_hint_subjects: root_hint_subjects.unwrap_or_default(),
137 };
138
139 if let Some(credentials) = resolver.resolve(&server_hello) {
140 debug!("Attempting client auth");
141 return Self::Verify {
142 credentials,
143 auth_context_tls13,
144 compressor,
145 };
146 }
147
148 debug!("Client auth requested but no cert/sigscheme available");
149 Self::Empty { auth_context_tls13 }
150 }
151}