use pki_types::{CertificateDer, TrustAnchor};
use crate::cert::{Cert, lenient_certificate_serial_number};
use crate::der;
use crate::error::{DerTypeId, Error};
pub fn anchor_from_trusted_cert<'a>(
cert: &'a CertificateDer<'a>,
) -> Result<TrustAnchor<'a>, Error> {
let cert_der = untrusted::Input::from(cert.as_ref());
match Cert::from_der(cert_der) {
Ok(cert) => Ok(TrustAnchor::from(cert)),
Err(Error::UnsupportedCertVersion) => {
extract_trust_anchor_from_v1_cert_der(cert_der).or(Err(Error::BadDer))
}
Err(err) => Err(err),
}
}
fn extract_trust_anchor_from_v1_cert_der(
cert_der: untrusted::Input<'_>,
) -> Result<TrustAnchor<'_>, Error> {
cert_der.read_all(Error::BadDer, |cert_der| {
der::nested(
cert_der,
der::Tag::Sequence,
Error::TrailingData(DerTypeId::TrustAnchorV1),
|cert_der| {
let anchor = der::nested(
cert_der,
der::Tag::Sequence,
Error::TrailingData(DerTypeId::TrustAnchorV1TbsCertificate),
|tbs| {
lenient_certificate_serial_number(tbs)?;
skip(tbs, der::Tag::Sequence)?; skip(tbs, der::Tag::Sequence)?; skip(tbs, der::Tag::Sequence)?; let subject = der::expect_tag(tbs, der::Tag::Sequence)?;
let spki = der::expect_tag(tbs, der::Tag::Sequence)?;
Ok(TrustAnchor {
subject: subject.as_slice_less_safe().into(),
subject_public_key_info: spki.as_slice_less_safe().into(),
name_constraints: None,
})
},
);
skip(cert_der, der::Tag::Sequence)?;
skip(cert_der, der::Tag::BitString)?;
anchor
},
)
})
}
impl<'a> From<Cert<'a>> for TrustAnchor<'a> {
fn from(cert: Cert<'a>) -> Self {
Self {
subject: cert.subject.as_slice_less_safe().into(),
subject_public_key_info: cert.spki.as_slice_less_safe().into(),
name_constraints: cert
.name_constraints
.map(|nc| nc.as_slice_less_safe().into()),
}
}
}
fn skip(input: &mut untrusted::Reader<'_>, tag: der::Tag) -> Result<(), Error> {
der::expect_tag(input, tag).map(|_| ())
}