Skip to main content

structured_cms/timestamp/
tsa.rs

1//! Original explicit TSA names using the common `GeneralName` semantics.
2
3use super::record;
4use crate::{Error, ErrorCode, Result};
5use structured_asn1::memory::{OwnedVec, Work};
6use structured_asn1::{Element, Reader, Span};
7use structured_pkix::general_name::{self, GeneralName};
8
9const FIELD: &str = "tstInfo.tsa";
10
11/// Present TSA wrapper and its readable name, or explicitly unreadable contents.
12/// An unreadable present wrapper is distinct from an absent optional field.
13#[derive(Debug)]
14pub struct TsaReading<'a> {
15    wrapper: Element<'a>,
16    element: Option<Element<'a>>,
17    name: Option<GeneralName<'a>>,
18}
19
20impl<'a> TsaReading<'a> {
21    pub(super) fn read<W: Work>(
22        parent: &Reader<'a>,
23        wrapper: &Element<'a>,
24        faults: &mut OwnedVec<Error, W>,
25    ) -> Result<Self> {
26        let mut inside = parent
27            .enter(wrapper)
28            .map_err(|error| Error::encoding(error, FIELD))?;
29        let first = match inside
30            .next_element()
31            .map_err(|error| Error::encoding(error, FIELD))
32        {
33            Ok(Some(first)) => first,
34            Ok(None) => {
35                record(
36                    faults,
37                    Error::schema(ErrorCode::MissingField, FIELD, wrapper.span().start),
38                )?;
39                return Ok(Self {
40                    wrapper: *wrapper,
41                    element: None,
42                    name: None,
43                });
44            }
45            Err(error) => {
46                record(faults, error)?;
47                return Ok(Self {
48                    wrapper: *wrapper,
49                    element: None,
50                    name: None,
51                });
52            }
53        };
54        let reading = match general_name::read(&inside, &first, FIELD).map_err(Error::pkix) {
55            Ok(name) => Ok(name),
56            Err(error) if error.is_terminal() => return Err(error),
57            Err(error) => Err(error),
58        };
59        let mut duplicate = None;
60        while let Some(extra) = inside
61            .next_element()
62            .map_err(|error| Error::encoding(error, FIELD))?
63        {
64            let at = extra.span().start;
65            inside
66                .execution()
67                .charge_work(1 + first.as_bytes().len().min(extra.as_bytes().len()) as u64)
68                .map_err(|reason| Error::resource(reason, FIELD, at))?;
69            if first.as_bytes() != extra.as_bytes() && !same_name(&inside, &reading, &extra)? {
70                return Err(Error::schema(ErrorCode::TrailingData, FIELD, at));
71            }
72            duplicate.get_or_insert(at);
73        }
74        if let Some(at) = duplicate {
75            record(faults, Error::schema(ErrorCode::DuplicateField, FIELD, at))?;
76        }
77        let name = match reading {
78            Ok(name) => Some(name),
79            Err(error) => {
80                record(faults, error)?;
81                None
82            }
83        };
84        Ok(Self {
85            wrapper: *wrapper,
86            element: Some(first),
87            name,
88        })
89    }
90
91    /// Whole original explicit \[0\] wrapper range.
92    #[must_use]
93    pub fn span(&self) -> Span {
94        self.wrapper.span()
95    }
96    /// First original encoded name, absent if its header was unreadable/missing.
97    #[must_use]
98    pub fn element(&self) -> Option<&Element<'a>> {
99        self.element.as_ref()
100    }
101    /// Common decoded name; None means present-but-unreadable, never absence.
102    #[must_use]
103    pub fn name(&self) -> Option<&GeneralName<'a>> {
104        self.name.as_ref()
105    }
106}
107
108fn same_name(
109    parent: &Reader<'_>,
110    first: &Result<GeneralName<'_>>,
111    extra: &Element<'_>,
112) -> Result<bool> {
113    let Ok(first) = first else {
114        return Ok(false);
115    };
116    let other = match general_name::read(parent, extra, FIELD).map_err(Error::pkix) {
117        Ok(other) => other,
118        Err(error) if error.is_terminal() => return Err(error),
119        Err(_) => return Ok(false),
120    };
121    general_name::matches(parent, first, &other, extra.span().start, FIELD).map_err(Error::pkix)
122}