mod identity;
mod parser;
mod store;
#[cfg(feature = "boring")]
use boring::x509::X509;
#[cfg(all(feature = "rustls-tls", not(feature = "boring")))]
use rustls_pki_types::CertificateDer;
pub use self::{
identity::Identity,
store::{CertStore, CertStoreBuilder},
};
use crate::Error;
pub enum CertificateInput<'c> {
Raw(&'c [u8]),
Parsed(Certificate),
}
impl<'a> CertificateInput<'a> {
pub(crate) fn with_parser<F>(self, parser: F) -> crate::Result<Certificate>
where
F: Fn(&'a [u8]) -> crate::Result<Certificate>,
{
match self {
CertificateInput::Raw(data) => parser(data),
CertificateInput::Parsed(cert) => Ok(cert),
}
}
}
impl From<Certificate> for CertificateInput<'_> {
fn from(cert: Certificate) -> Self {
CertificateInput::Parsed(cert)
}
}
impl<'c, T: AsRef<[u8]> + ?Sized + 'c> From<&'c T> for CertificateInput<'c> {
fn from(value: &'c T) -> CertificateInput<'c> {
CertificateInput::Raw(value.as_ref())
}
}
#[cfg(feature = "boring")]
#[derive(Clone)]
pub struct Certificate(X509);
#[cfg(all(feature = "rustls-tls", not(feature = "boring")))]
#[derive(Clone, Debug)]
pub struct Certificate(pub(crate) CertificateDer<'static>);
#[cfg(not(any(feature = "boring", feature = "rustls-tls")))]
#[derive(Clone, Debug)]
pub struct Certificate;
impl Certificate {
#[inline]
pub fn from_der<C: AsRef<[u8]>>(cert: C) -> crate::Result<Self> {
#[cfg(feature = "boring")]
{
X509::from_der(cert.as_ref()).map(Self).map_err(Error::tls)
}
#[cfg(all(feature = "rustls-tls", not(feature = "boring")))]
{
Ok(Self(CertificateDer::from(cert.as_ref().to_vec())))
}
#[cfg(not(any(feature = "boring", feature = "rustls-tls")))]
{
let _ = cert;
Err(Error::tls("TLS not supported"))
}
}
#[inline]
pub fn from_pem<C: AsRef<[u8]>>(cert: C) -> crate::Result<Self> {
#[cfg(feature = "boring")]
{
X509::from_pem(cert.as_ref()).map(Self).map_err(Error::tls)
}
#[cfg(all(feature = "rustls-tls", not(feature = "boring")))]
{
use std::io::Cursor;
let mut reader = Cursor::new(cert.as_ref());
let certs = rustls_pemfile::certs(&mut reader)
.collect::<Result<Vec<_>, _>>()
.map_err(|e| Error::tls(Box::new(e)))?;
certs
.into_iter()
.next()
.map(Self)
.ok_or_else(|| Error::tls("No certificate found in PEM"))
}
#[cfg(not(any(feature = "boring", feature = "rustls-tls")))]
{
let _ = cert;
Err(Error::tls("TLS not supported"))
}
}
#[inline]
pub fn stack_from_pem<C: AsRef<[u8]>>(cert: C) -> crate::Result<Vec<Self>> {
#[cfg(feature = "boring")]
{
let certs = X509::stack_from_pem(cert.as_ref()).map_err(Error::tls)?;
Ok(certs.into_iter().map(Self).collect())
}
#[cfg(all(feature = "rustls-tls", not(feature = "boring")))]
{
use std::io::Cursor;
let mut reader = Cursor::new(cert.as_ref());
let certs = rustls_pemfile::certs(&mut reader)
.collect::<Result<Vec<_>, _>>()
.map_err(|e| Error::tls(Box::new(e)))?;
Ok(certs.into_iter().map(Self).collect())
}
#[cfg(not(any(feature = "boring", feature = "rustls-tls")))]
{
let _ = cert;
Err(Error::tls("TLS not supported"))
}
}
}