rustls/client/
common.rs

1use super::ResolvesClientCert;
2#[cfg(feature = "logging")]
3use crate::log::{debug, trace};
4use crate::msgs::enums::ExtensionType;
5use crate::msgs::handshake::{CertificatePayload, DistinguishedName};
6use crate::msgs::handshake::{Sct, ServerExtension};
7use crate::{sign, SignatureScheme};
8
9use std::sync::Arc;
10
11#[derive(Debug)]
12pub(super) struct ServerCertDetails {
13    pub(super) cert_chain: CertificatePayload,
14    pub(super) ocsp_response: Vec<u8>,
15    pub(super) scts: Option<Vec<Sct>>,
16}
17
18impl ServerCertDetails {
19    pub(super) fn new(
20        cert_chain: CertificatePayload,
21        ocsp_response: Vec<u8>,
22        scts: Option<Vec<Sct>>,
23    ) -> Self {
24        Self {
25            cert_chain,
26            ocsp_response,
27            scts,
28        }
29    }
30
31    pub(super) fn scts(&self) -> impl Iterator<Item = &[u8]> {
32        self.scts
33            .as_deref()
34            .unwrap_or(&[])
35            .iter()
36            .map(|payload| payload.as_ref())
37    }
38}
39
40pub(super) struct ClientHelloDetails {
41    pub(super) sent_extensions: Vec<ExtensionType>,
42}
43
44impl ClientHelloDetails {
45    pub(super) fn new() -> Self {
46        Self {
47            sent_extensions: Vec::new(),
48        }
49    }
50
51    pub(super) fn server_may_send_sct_list(&self) -> bool {
52        self.sent_extensions
53            .contains(&ExtensionType::SCT)
54    }
55
56    pub(super) fn server_sent_unsolicited_extensions(
57        &self,
58        received_exts: &[ServerExtension],
59        allowed_unsolicited: &[ExtensionType],
60    ) -> bool {
61        for ext in received_exts {
62            let ext_type = ext.get_type();
63            if !self.sent_extensions.contains(&ext_type) && !allowed_unsolicited.contains(&ext_type)
64            {
65                trace!("Unsolicited extension {:?}", ext_type);
66                return true;
67            }
68        }
69
70        false
71    }
72}
73
74pub(super) enum ClientAuthDetails {
75    /// Send an empty `Certificate` and no `CertificateVerify`.
76    Empty { auth_context_tls13: Option<Vec<u8>> },
77    /// Send a non-empty `Certificate` and a `CertificateVerify`.
78    Verify {
79        certkey: Arc<sign::CertifiedKey>,
80        signer: Box<dyn sign::Signer>,
81        auth_context_tls13: Option<Vec<u8>>,
82    },
83}
84
85impl ClientAuthDetails {
86    pub(super) fn resolve(
87        resolver: &dyn ResolvesClientCert,
88        canames: Option<&[DistinguishedName]>,
89        sigschemes: &[SignatureScheme],
90        auth_context_tls13: Option<Vec<u8>>,
91    ) -> Self {
92        let acceptable_issuers = canames
93            .unwrap_or_default()
94            .iter()
95            .map(|p| p.as_ref())
96            .collect::<Vec<&[u8]>>();
97
98        if let Some(certkey) = resolver.resolve(&acceptable_issuers, sigschemes) {
99            if let Some(signer) = certkey.key.choose_scheme(sigschemes) {
100                debug!("Attempting client auth");
101                return Self::Verify {
102                    certkey,
103                    signer,
104                    auth_context_tls13,
105                };
106            }
107        }
108
109        debug!("Client auth requested but no cert/sigscheme available");
110        Self::Empty { auth_context_tls13 }
111    }
112}