use alloc::boxed::Box;
use alloc::sync::Arc;
use alloc::vec::Vec;
use super::ResolvesClientCert;
use crate::log::{debug, trace};
use crate::msgs::enums::ExtensionType;
use crate::msgs::handshake::{CertificateChain, DistinguishedName, ServerExtension};
use crate::{compress, sign, SignatureScheme};
#[derive(Debug)]
pub(super) struct ServerCertDetails<'a> {
pub(super) cert_chain: CertificateChain<'a>,
pub(super) ocsp_response: Vec<u8>,
}
impl<'a> ServerCertDetails<'a> {
pub(super) fn new(cert_chain: CertificateChain<'a>, ocsp_response: Vec<u8>) -> Self {
Self {
cert_chain,
ocsp_response,
}
}
pub(super) fn into_owned(self) -> ServerCertDetails<'static> {
let Self {
cert_chain,
ocsp_response,
} = self;
ServerCertDetails {
cert_chain: cert_chain.into_owned(),
ocsp_response,
}
}
}
pub(super) struct ClientHelloDetails {
pub(super) sent_extensions: Vec<ExtensionType>,
pub(super) extension_order_seed: u16,
pub(super) offered_cert_compression: bool,
}
impl ClientHelloDetails {
pub(super) fn new(extension_order_seed: u16) -> Self {
Self {
sent_extensions: Vec::new(),
extension_order_seed,
offered_cert_compression: false,
}
}
pub(super) fn server_sent_unsolicited_extensions(
&self,
received_exts: &[ServerExtension],
allowed_unsolicited: &[ExtensionType],
) -> bool {
for ext in received_exts {
let ext_type = ext.ext_type();
if !self.sent_extensions.contains(&ext_type) && !allowed_unsolicited.contains(&ext_type)
{
trace!("Unsolicited extension {:?}", ext_type);
return true;
}
}
false
}
}
pub(super) enum ClientAuthDetails {
Empty { auth_context_tls13: Option<Vec<u8>> },
Verify {
certkey: Arc<sign::CertifiedKey>,
signer: Box<dyn sign::Signer>,
auth_context_tls13: Option<Vec<u8>>,
compressor: Option<&'static dyn compress::CertCompressor>,
},
}
impl ClientAuthDetails {
pub(super) fn resolve(
resolver: &dyn ResolvesClientCert,
canames: Option<&[DistinguishedName]>,
sigschemes: &[SignatureScheme],
auth_context_tls13: Option<Vec<u8>>,
compressor: Option<&'static dyn compress::CertCompressor>,
) -> Self {
let acceptable_issuers = canames
.unwrap_or_default()
.iter()
.map(|p| p.as_ref())
.collect::<Vec<&[u8]>>();
if let Some(certkey) = resolver.resolve(&acceptable_issuers, sigschemes) {
if let Some(signer) = certkey.key.choose_scheme(sigschemes) {
debug!("Attempting client auth");
return Self::Verify {
certkey,
signer,
auth_context_tls13,
compressor,
};
}
}
debug!("Client auth requested but no cert/sigscheme available");
Self::Empty { auth_context_tls13 }
}
}