use alloc::string::{String, ToString};
use alloc::vec::Vec;
use anyhow::{anyhow, bail, Context, Result};
use crate::config::{ParsedCert, X509Codec};
pub struct X509CertBackend;
pub struct X509CertParsed {
cert: x509_cert::Certificate,
}
impl X509Codec for X509CertBackend {
type Parsed<'a> = X509CertParsed;
fn from_der<'a>(cert_der: &'a [u8]) -> Result<Self::Parsed<'a>> {
let cert: x509_cert::Certificate =
der::Decode::from_der(cert_der).context("Failed to decode certificate")?;
Ok(X509CertParsed { cert })
}
}
impl ParsedCert for X509CertParsed {
fn issuer_dn(&self) -> Result<String> {
Ok(self.cert.tbs_certificate.issuer.to_string())
}
fn extension(&self, oid: &[u8]) -> Result<Option<Vec<u8>>> {
let oid = const_oid::ObjectIdentifier::from_bytes(oid)
.map_err(|_| anyhow!("Invalid OID encoding"))?;
let mut iter = self
.cert
.tbs_certificate
.extensions
.as_deref()
.unwrap_or(&[])
.iter()
.filter(|e| e.extn_id == oid)
.map(|e| e.extn_value.clone());
let extension = match iter.next() {
Some(ext) => ext,
None => return Ok(None),
};
if iter.next().is_some() {
bail!("extension {} appears more than once", oid);
}
Ok(Some(extension.into_bytes()))
}
}