Skip to main content

rustls/client/
common.rs

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    /// Send an empty `Certificate` and no `CertificateVerify`.
82    Empty { auth_context_tls13: Option<Vec<u8>> },
83    /// Send a non-empty `Certificate` and a `CertificateVerify`.
84    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}