use crate::{
cert, name, signed_data, verify_cert, DnsNameRef, Error, SignatureAlgorithm, Time,
TlsClientTrustAnchors, TlsServerTrustAnchors,
};
#[cfg(feature = "alloc")]
use alloc::vec::Vec;
pub struct EndEntityCert<'a> {
inner: cert::Cert<'a>,
}
impl<'a> core::convert::TryFrom<&'a [u8]> for EndEntityCert<'a> {
type Error = Error;
fn try_from(cert_der: &'a [u8]) -> Result<Self, Self::Error> {
Ok(Self {
inner: cert::parse_cert(
untrusted::Input::from(cert_der),
cert::EndEntityOrCa::EndEntity,
)?,
})
}
}
impl<'a> EndEntityCert<'a> {
pub(super) fn inner(&self) -> &cert::Cert {
&self.inner
}
pub fn verify_is_valid_tls_server_cert(
&self,
supported_sig_algs: &[&SignatureAlgorithm],
&TlsServerTrustAnchors(trust_anchors): &TlsServerTrustAnchors,
intermediate_certs: &[&[u8]],
time: Time,
) -> Result<(), Error> {
verify_cert::build_chain(
verify_cert::EKU_SERVER_AUTH,
supported_sig_algs,
trust_anchors,
intermediate_certs,
&self.inner,
time,
0,
)
}
pub fn verify_is_valid_tls_client_cert(
&self,
supported_sig_algs: &[&SignatureAlgorithm],
&TlsClientTrustAnchors(trust_anchors): &TlsClientTrustAnchors,
intermediate_certs: &[&[u8]],
time: Time,
) -> Result<(), Error> {
verify_cert::build_chain(
verify_cert::EKU_CLIENT_AUTH,
supported_sig_algs,
trust_anchors,
intermediate_certs,
&self.inner,
time,
0,
)
}
pub fn verify_is_valid_for_dns_name(&self, dns_name: DnsNameRef) -> Result<(), Error> {
name::verify_cert_dns_name(&self, dns_name)
}
#[cfg(feature = "alloc")]
pub fn verify_is_valid_for_at_least_one_dns_name<'names, Names>(
&self,
dns_names: Names,
) -> Result<Vec<DnsNameRef<'names>>, Error>
where
Names: Iterator<Item = DnsNameRef<'names>>,
{
let result: Vec<DnsNameRef<'names>> = dns_names
.filter(|n| self.verify_is_valid_for_dns_name(*n).is_ok())
.collect();
if result.is_empty() {
return Err(Error::CertNotValidForName);
}
Ok(result)
}
pub fn verify_signature(
&self,
signature_alg: &SignatureAlgorithm,
msg: &[u8],
signature: &[u8],
) -> Result<(), Error> {
signed_data::verify_signature(
signature_alg,
self.inner.spki.value(),
untrusted::Input::from(msg),
untrusted::Input::from(signature),
)
}
}