x509_signature/
sequence.rs

1//! An iterator over ASN.1 SEQUENCE structures
2
3use super::{der, Error};
4
5/// An iterator over X.509 extensions.
6///
7/// Errors are detected lazily.
8#[derive(Debug, Copy, Clone)]
9pub struct ExtensionIterator<'a>(pub(crate) SequenceIterator<'a>);
10
11/// An iterator over X.509 sequences.
12///
13/// Errors are detected lazily.
14#[derive(Debug, Copy, Clone)]
15pub struct SequenceIterator<'a> {
16    inner: untrusted::Input<'a>,
17}
18
19impl<'a> SequenceIterator<'a> {
20    /// Read X.509 extensions from an [`untrusted::Reader`].
21    pub fn read(input: &mut untrusted::Reader<'a>) -> Self {
22        Self {
23            inner: input.read_bytes_to_end(),
24        }
25    }
26
27    /// Iterate over the X.509 sequences. The callback is expected to read the
28    /// provided [`untrusted::Reader`] to the end; if it does not, or if the
29    /// DER isn’t a sequence of sequences, `Err(error)` will be returned.
30    pub fn iterate<
31        E: Copy + core::fmt::Debug,
32        T: FnMut(&mut untrusted::Reader<'a>) -> Result<(), E>,
33    >(
34        &self, error: E, cb: &mut T,
35    ) -> Result<(), E> {
36        self.inner.read_all(error, |input| {
37            while !input.at_end() {
38                der::nested(input, der::Tag::Sequence, error, &mut *cb)?
39            }
40            Ok(())
41        })
42    }
43}
44
45impl<'a> ExtensionIterator<'a> {
46    /// Iterate over the X.509 extensions.
47    pub fn iterate<T: FnMut(&'a [u8], bool, untrusted::Input<'a>) -> Result<(), Error>>(
48        &self, cb: &mut T,
49    ) -> Result<(), Error> {
50        self.0.iterate(Error::BadDER, &mut |input| {
51            let oid =
52                der::expect_tag_and_get_value(input, der::Tag::OID).map_err(|_| Error::BadDER)?;
53            let mut critical = false;
54            if input.peek(der::Tag::Boolean as _) {
55                critical = match input
56                    .read_bytes(3)
57                    .map_err(|_| Error::BadDER)?
58                    .as_slice_less_safe()
59                {
60                    b"\x01\x01\xFF" => true,
61                    b"\x01\x01\0" => false,
62                    _ => return Err(Error::BadDER),
63                }
64            }
65            let value = der::expect_tag_and_get_value(input, der::Tag::OctetString)
66                .map_err(|_| Error::BadDER)?;
67            cb(oid.as_slice_less_safe(), critical, value)
68        })
69    }
70}