use yasna::{construct_der, models::ObjectIdentifier, DERWriter};
use crate::pkcs10::Extension;
pub(crate) trait WcceExtension {
const EXTENSION_OID: &'static [u64];
const CRITICAL: bool;
fn value(&self, writer: DERWriter);
}
impl<T> Extension for T
where
T: WcceExtension,
{
fn oid(&self) -> &[u64] {
Self::EXTENSION_OID
}
fn critical(&self) -> bool {
Self::CRITICAL
}
fn value(&self) -> Vec<u8> {
construct_der(|writer| {
self.value(writer);
})
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct CertificateTemplate<'a> {
pub template_oid: &'a [u64],
pub major_version: Option<u32>,
pub minor_version: Option<u32>,
}
impl WcceExtension for CertificateTemplate<'_> {
const EXTENSION_OID: &'static [u64] = &[1, 3, 6, 1, 4, 1, 311, 21, 7];
const CRITICAL: bool = false;
fn value(&self, writer: DERWriter) {
writer.write_sequence(|writer| {
writer
.next()
.write_oid(&ObjectIdentifier::from_slice(self.template_oid));
if let Some(major) = self.major_version {
writer.next().write_u32(major);
}
if let Some(minor) = self.minor_version {
writer.next().write_u32(minor);
}
});
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ApplicationCertPolicies<'a, T>
where
T: AsRef<[u64]>,
{
pub policies: &'a [T],
}
impl<T> WcceExtension for ApplicationCertPolicies<'_, T>
where
T: AsRef<[u64]>,
{
const EXTENSION_OID: &'static [u64] = &[1, 3, 6, 1, 4, 1, 311, 21, 10];
const CRITICAL: bool = false;
fn value(&self, writer: DERWriter) {
writer.write_sequence(|writer| {
for policy in self.policies {
writer.next().write_sequence(|writer| {
writer
.next()
.write_oid(&ObjectIdentifier::from_slice(policy.as_ref()));
});
}
});
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_certificate_template_der() {
let expected = [0x30, 0x4, 0x6, 0x2, 0x2A, 0x3].to_vec();
let actual = <CertificateTemplate as Extension>::value(&CertificateTemplate {
template_oid: &[1, 2, 3],
major_version: None,
minor_version: None,
});
assert_eq!(expected, actual);
let expected = [
0x30, 0x0a, 0x06, 0x02, 0x2a, 0x03, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00,
]
.to_vec();
let actual = <CertificateTemplate as Extension>::value(&CertificateTemplate {
template_oid: &[1, 2, 3],
major_version: Some(0),
minor_version: Some(0),
});
assert_eq!(expected, actual);
}
#[test]
fn test_application_cert_policies_der() {
let policies: &[&[u64]] = &[];
let acp = ApplicationCertPolicies { policies };
let expected = [0x30, 0x00].to_vec();
let actual = <ApplicationCertPolicies<_> as Extension>::value(&acp);
assert_eq!(expected, actual);
}
}