1use crate::{der, Error};
16
17pub(crate) struct Extension<'a> {
18 pub(crate) critical: bool,
19 pub(crate) id: untrusted::Input<'a>,
20 pub(crate) value: untrusted::Input<'a>,
21}
22
23impl<'a> Extension<'a> {
24 pub(crate) fn parse(der: &mut untrusted::Reader<'a>) -> Result<Extension<'a>, Error> {
25 let id = der::expect_tag_and_get_value(der, der::Tag::OID)?;
26 let critical = der::optional_boolean(der)?;
27 let value = der::expect_tag_and_get_value(der, der::Tag::OctetString)?;
28 Ok(Extension {
29 id,
30 critical,
31 value,
32 })
33 }
34
35 pub(crate) fn unsupported(&self) -> Result<(), Error> {
36 match self.critical {
37 true => Err(Error::UnsupportedCriticalExtension),
38 false => Ok(()),
39 }
40 }
41}
42
43pub(crate) fn set_extension_once<T>(
44 destination: &mut Option<T>,
45 parser: impl Fn() -> Result<T, Error>,
46) -> Result<(), Error> {
47 match destination {
48 Some(..) => Err(Error::ExtensionValueInvalid),
51 None => {
52 *destination = Some(parser()?);
53 Ok(())
54 }
55 }
56}
57
58pub(crate) fn remember_extension(
59 extension: &Extension,
60 mut handler: impl FnMut(u8) -> Result<(), Error>,
61) -> Result<(), Error> {
62 static ID_CE: [u8; 2] = oid![2, 5, 29];
65
66 if extension.id.len() != ID_CE.len() + 1
67 || !extension.id.as_slice_less_safe().starts_with(&ID_CE)
68 {
69 return extension.unsupported();
70 }
71
72 let last_octet = *extension.id.as_slice_less_safe().last().unwrap();
74 handler(last_octet)
75}