1use alloc::boxed::Box;
2use alloc::sync::Arc;
3use alloc::vec::Vec;
4
5use super::ResolvesClientCert;
6use crate::log::{debug, trace};
7use crate::msgs::enums::ExtensionType;
8use crate::msgs::handshake::{CertificateChain, DistinguishedName, ServerExtension};
9use crate::{compress, sign, SignatureScheme};
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) sent_extensions: Vec<ExtensionType>,
39 pub(super) extension_order_seed: u16,
40 pub(super) offered_cert_compression: bool,
41}
42
43impl ClientHelloDetails {
44 pub(super) fn new(extension_order_seed: u16) -> Self {
45 Self {
46 sent_extensions: Vec::new(),
47 extension_order_seed,
48 offered_cert_compression: false,
49 }
50 }
51
52 pub(super) fn server_sent_unsolicited_extensions(
53 &self,
54 received_exts: &[ServerExtension],
55 allowed_unsolicited: &[ExtensionType],
56 ) -> bool {
57 for ext in received_exts {
58 let ext_type = ext.ext_type();
59 if !self.sent_extensions.contains(&ext_type) && !allowed_unsolicited.contains(&ext_type)
60 {
61 trace!("Unsolicited extension {:?}", ext_type);
62 return true;
63 }
64 }
65
66 false
67 }
68}
69
70pub(super) enum ClientAuthDetails {
71 Empty { auth_context_tls13: Option<Vec<u8>> },
73 Verify {
75 certkey: Arc<sign::CertifiedKey>,
76 signer: Box<dyn sign::Signer>,
77 auth_context_tls13: Option<Vec<u8>>,
78 compressor: Option<&'static dyn compress::CertCompressor>,
79 },
80}
81
82impl ClientAuthDetails {
83 pub(super) fn resolve(
84 resolver: &dyn ResolvesClientCert,
85 canames: Option<&[DistinguishedName]>,
86 sigschemes: &[SignatureScheme],
87 auth_context_tls13: Option<Vec<u8>>,
88 compressor: Option<&'static dyn compress::CertCompressor>,
89 ) -> Self {
90 let acceptable_issuers = canames
91 .unwrap_or_default()
92 .iter()
93 .map(|p| p.as_ref())
94 .collect::<Vec<&[u8]>>();
95
96 if let Some(certkey) = resolver.resolve(&acceptable_issuers, sigschemes) {
97 if let Some(signer) = certkey.key.choose_scheme(sigschemes) {
98 debug!("Attempting client auth");
99 return Self::Verify {
100 certkey,
101 signer,
102 auth_context_tls13,
103 compressor,
104 };
105 }
106 }
107
108 debug!("Client auth requested but no cert/sigscheme available");
109 Self::Empty { auth_context_tls13 }
110 }
111}