use crate::der::Tag;
use crate::signed_data::SignedData;
use crate::x509::{remember_extension, set_extension_once, Extension};
use crate::{der, public_values_eq, Error};
pub enum EndEntityOrCa<'a> {
EndEntity,
Ca(&'a Cert<'a>),
}
pub struct Cert<'a> {
pub(crate) ee_or_ca: EndEntityOrCa<'a>,
pub(crate) serial: untrusted::Input<'a>,
pub(crate) signed_data: SignedData<'a>,
pub(crate) issuer: untrusted::Input<'a>,
pub(crate) validity: untrusted::Input<'a>,
pub(crate) subject: untrusted::Input<'a>,
pub(crate) spki: der::Value<'a>,
pub(crate) basic_constraints: Option<untrusted::Input<'a>>,
pub(crate) key_usage: Option<untrusted::Input<'a>>,
pub(crate) eku: Option<untrusted::Input<'a>>,
pub(crate) name_constraints: Option<untrusted::Input<'a>>,
pub(crate) subject_alt_name: Option<untrusted::Input<'a>>,
}
impl<'a> Cert<'a> {
pub(crate) fn from_der(
cert_der: untrusted::Input<'a>,
ee_or_ca: EndEntityOrCa<'a>,
) -> Result<Self, Error> {
let (tbs, signed_data) = cert_der.read_all(Error::BadDer, |cert_der| {
der::nested(cert_der, der::Tag::Sequence, Error::BadDer, |der| {
SignedData::from_der(der, der::TWO_BYTE_DER_SIZE)
})
})?;
tbs.read_all(Error::BadDer, |tbs| {
version3(tbs)?;
let serial = lenient_certificate_serial_number(tbs)?;
let signature = der::expect_tag_and_get_value(tbs, der::Tag::Sequence)?;
if !public_values_eq(signature, signed_data.algorithm) {
return Err(Error::SignatureAlgorithmMismatch);
}
let issuer = der::expect_tag_and_get_value(tbs, der::Tag::Sequence)?;
let validity = der::expect_tag_and_get_value(tbs, der::Tag::Sequence)?;
let subject = der::expect_tag_and_get_value(tbs, der::Tag::Sequence)?;
let spki = der::expect_tag(tbs, der::Tag::Sequence)?;
let mut cert = Cert {
ee_or_ca,
signed_data,
serial,
issuer,
validity,
subject,
spki,
basic_constraints: None,
key_usage: None,
eku: None,
name_constraints: None,
subject_alt_name: None,
};
if !tbs.at_end() {
der::nested(
tbs,
der::Tag::ContextSpecificConstructed3,
Error::MalformedExtensions,
|tagged| {
der::nested_of_mut(
tagged,
der::Tag::Sequence,
der::Tag::Sequence,
Error::BadDer,
|extension| {
remember_cert_extension(&mut cert, &Extension::parse(extension)?)
},
)
},
)?;
}
Ok(cert)
})
}
pub fn serial(&self) -> &[u8] {
self.serial.as_slice_less_safe()
}
pub fn issuer(&self) -> &[u8] {
self.issuer.as_slice_less_safe()
}
pub fn subject(&self) -> &[u8] {
self.subject.as_slice_less_safe()
}
pub fn end_entity_or_ca(&self) -> &EndEntityOrCa {
&self.ee_or_ca
}
}
fn version3(input: &mut untrusted::Reader) -> Result<(), Error> {
der::nested(
input,
der::Tag::ContextSpecificConstructed0,
Error::UnsupportedCertVersion,
|input| {
let version = der::small_nonnegative_integer(input)?;
if version != 2 {
return Err(Error::UnsupportedCertVersion);
}
Ok(())
},
)
}
pub(crate) fn lenient_certificate_serial_number<'a>(
input: &mut untrusted::Reader<'a>,
) -> Result<untrusted::Input<'a>, Error> {
der::expect_tag_and_get_value(input, Tag::Integer)
}
fn remember_cert_extension<'a>(
cert: &mut Cert<'a>,
extension: &Extension<'a>,
) -> Result<(), Error> {
remember_extension(extension, |id| {
let out = match id {
15 => &mut cert.key_usage,
17 => &mut cert.subject_alt_name,
19 => &mut cert.basic_constraints,
30 => &mut cert.name_constraints,
37 => &mut cert.eku,
_ => return extension.unsupported(),
};
set_extension_once(out, || {
extension.value.read_all(Error::BadDer, |value| match id {
15 => Ok(value.read_bytes_to_end()),
_ => der::expect_tag_and_get_value(value, Tag::Sequence),
})
})
})
}
#[cfg(test)]
mod tests {
use crate::cert::{Cert, EndEntityOrCa};
#[test]
fn test_serial_read() {
let ee = include_bytes!("../tests/misc/serial_neg_ee.der");
let cert = Cert::from_der(untrusted::Input::from(ee), EndEntityOrCa::EndEntity)
.expect("failed to parse certificate");
assert_eq!(cert.serial.as_slice_less_safe(), &[255, 33, 82, 65, 17]);
let ee = include_bytes!("../tests/misc/serial_large_positive.der");
let cert = Cert::from_der(untrusted::Input::from(ee), EndEntityOrCa::EndEntity)
.expect("failed to parse certificate");
assert_eq!(
cert.serial.as_slice_less_safe(),
&[
0, 230, 9, 254, 122, 234, 0, 104, 140, 224, 36, 180, 237, 32, 27, 31, 239, 82, 180,
68, 209
]
)
}
}