1use alloc::boxed::Box;
2use alloc::vec::Vec;
3
4use super::ResolvesClientCert;
5use crate::log::{debug, trace};
6use crate::msgs::enums::ExtensionType;
7use crate::msgs::handshake::{CertificateChain, DistinguishedName, ProtocolName, ServerExtensions};
8use crate::sync::Arc;
9use crate::{CipherSuite, SignatureScheme, compress, sign};
10
11#[derive(Debug)]
12pub(super) struct ServerCertDetails<'a> {
13 pub(super) cert_chain: CertificateChain<'a>,
14 pub(super) ocsp_response: Vec<u8>,
15}
16
17impl<'a> ServerCertDetails<'a> {
18 pub(super) fn new(cert_chain: CertificateChain<'a>, ocsp_response: Vec<u8>) -> Self {
19 Self {
20 cert_chain,
21 ocsp_response,
22 }
23 }
24
25 pub(super) fn into_owned(self) -> ServerCertDetails<'static> {
26 let Self {
27 cert_chain,
28 ocsp_response,
29 } = self;
30 ServerCertDetails {
31 cert_chain: cert_chain.into_owned(),
32 ocsp_response,
33 }
34 }
35}
36
37pub(super) struct ClientHelloDetails {
38 pub(super) alpn_protocols: Vec<ProtocolName>,
39 pub(super) sent_extensions: Vec<ExtensionType>,
40 pub(super) extension_order_seed: u16,
41 pub(super) offered_cert_compression: bool,
42 pub(super) offered_cipher_suites: Vec<CipherSuite>,
43}
44
45impl ClientHelloDetails {
46 pub(super) fn new(alpn_protocols: Vec<ProtocolName>, extension_order_seed: u16) -> Self {
47 Self {
48 alpn_protocols,
49 sent_extensions: Vec::new(),
50 extension_order_seed,
51 offered_cert_compression: false,
52 offered_cipher_suites: Vec::new(),
53 }
54 }
55
56 pub(super) fn server_sent_unsolicited_extensions(
57 &self,
58 received_exts: &ServerExtensions<'_>,
59 allowed_unsolicited: &[ExtensionType],
60 ) -> bool {
61 let mut extensions = received_exts.collect_used();
62 extensions.extend(
63 received_exts
64 .unknown_extensions
65 .iter()
66 .map(|ext| ExtensionType::from(*ext)),
67 );
68 for ext_type in extensions {
69 if !self.sent_extensions.contains(&ext_type) && !allowed_unsolicited.contains(&ext_type)
70 {
71 trace!("Unsolicited extension {ext_type:?}");
72 return true;
73 }
74 }
75
76 false
77 }
78}
79
80pub(super) enum ClientAuthDetails {
81 Empty { auth_context_tls13: Option<Vec<u8>> },
83 Verify {
85 certkey: Arc<sign::CertifiedKey>,
86 signer: Box<dyn sign::Signer>,
87 auth_context_tls13: Option<Vec<u8>>,
88 compressor: Option<&'static dyn compress::CertCompressor>,
89 },
90}
91
92impl ClientAuthDetails {
93 pub(super) fn resolve(
94 resolver: &dyn ResolvesClientCert,
95 canames: Option<&[DistinguishedName]>,
96 sigschemes: &[SignatureScheme],
97 auth_context_tls13: Option<Vec<u8>>,
98 compressor: Option<&'static dyn compress::CertCompressor>,
99 ) -> Self {
100 let acceptable_issuers = canames
101 .unwrap_or_default()
102 .iter()
103 .map(|p| p.as_ref())
104 .collect::<Vec<&[u8]>>();
105
106 if let Some(certkey) = resolver.resolve(&acceptable_issuers, sigschemes) {
107 if let Some(signer) = certkey.key.choose_scheme(sigschemes) {
108 debug!("Attempting client auth");
109 return Self::Verify {
110 certkey,
111 signer,
112 auth_context_tls13,
113 compressor,
114 };
115 }
116 }
117
118 debug!("Client auth requested but no cert/sigscheme available");
119 Self::Empty { auth_context_tls13 }
120 }
121}