#![doc(html_root_url = "https://briansmith.org/rustdoc/")]
#![cfg_attr(not(feature = "std"), no_std)]
#![allow(missing_debug_implementations)]
#![deny(unused_qualifications)]
#![forbid(
anonymous_parameters,
box_pointers,
missing_copy_implementations,
missing_docs,
trivial_casts,
trivial_numeric_casts,
unsafe_code,
unstable_features,
unused_extern_crates,
unused_import_braces,
unused_results,
variant_size_differences,
warnings
)]
#[cfg(all(test, not(feature = "std")))]
#[macro_use]
extern crate std;
#[macro_use]
mod der;
mod calendar;
mod cert;
mod error;
mod name;
mod signed_data;
mod time;
#[cfg(feature = "trust_anchor_util")]
pub mod trust_anchor_util;
mod verify_cert;
pub use error::Error;
pub use name::{DNSNameRef, InvalidDNSNameError};
#[cfg(feature = "std")]
pub use name::DNSName;
pub use signed_data::{
SignatureAlgorithm, ECDSA_P256_SHA256, ECDSA_P256_SHA384, ECDSA_P384_SHA256, ECDSA_P384_SHA384,
ED25519, RSA_PKCS1_2048_8192_SHA256, RSA_PKCS1_2048_8192_SHA384, RSA_PKCS1_2048_8192_SHA512,
RSA_PKCS1_3072_8192_SHA384, RSA_PSS_2048_8192_SHA256_LEGACY_KEY,
RSA_PSS_2048_8192_SHA384_LEGACY_KEY, RSA_PSS_2048_8192_SHA512_LEGACY_KEY,
};
pub use time::Time;
pub struct EndEntityCert<'a> {
inner: cert::Cert<'a>,
}
impl<'a> EndEntityCert<'a> {
pub fn from(cert_der: &'a [u8]) -> Result<Self, Error> {
Ok(Self {
inner: cert::parse_cert(
untrusted::Input::from(cert_der),
cert::EndEntityOrCA::EndEntity,
)?,
})
}
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 = "std")]
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),
)
}
}
#[derive(Debug)]
pub struct TrustAnchor<'a> {
pub subject: &'a [u8],
pub spki: &'a [u8],
pub name_constraints: Option<&'a [u8]>,
}
#[derive(Debug)]
pub struct TLSServerTrustAnchors<'a>(pub &'a [TrustAnchor<'a>]);
#[derive(Debug)]
pub struct TLSClientTrustAnchors<'a>(pub &'a [TrustAnchor<'a>]);