rustls/client/
common.rs

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