structured_cms/attribute_certificate/
clearance.rs1use super::{end, sequence, tag};
9use crate::attribute::Attribute;
10use crate::signer::required;
11use crate::{Error, ErrorCode, Result};
12use structured_asn1::memory::{OwnedVec, Work};
13use structured_asn1::{BitString, Element, Encoding, Oid, Parser, ScopedReader, Tag, universal};
14
15const FIELD: &str = "attributeCertificate.clearance";
16pub const IDENTIFIER: Oid<'static> = Oid::from_bytes(&[85, 4, 55]);
18pub const LEGACY_IDENTIFIER: Oid<'static> = Oid::from_bytes(&[85, 1, 5, 55]);
20
21#[derive(Debug, Clone, Copy, PartialEq, Eq)]
23pub enum Syntax {
24 Current,
26 Legacy,
28}
29
30#[derive(Debug, Clone, Copy)]
32pub struct SecurityCategory<'a> {
33 parser: &'a Parser,
34 depth: u32,
35 pub element: Element<'a>,
37 pub kind: Oid<'a>,
39 pub kind_element: Element<'a>,
41 pub wrapper: Element<'a>,
43 pub value: Element<'a>,
45}
46
47impl<'a> SecurityCategory<'a> {
48 pub fn value_reader<'operation, W: Work>(
53 &self,
54 work: &'operation W,
55 ) -> Result<ScopedReader<'a, 'operation>>
56 where
57 'a: 'operation,
58 {
59 work.read_scoped_source(
60 self.parser,
61 self.value.as_bytes(),
62 self.value.span().start,
63 Encoding::Der,
64 self.depth,
65 )
66 .map_err(|e| Error::encoding(e, FIELD))
67 }
68}
69
70#[derive(Debug)]
73pub struct Clearance<'a> {
74 pub element: Element<'a>,
76 pub syntax: Syntax,
78 pub policy: Oid<'a>,
80 pub policy_element: Element<'a>,
82 pub classes: Option<BitString<'a>>,
84 pub classes_element: Option<Element<'a>>,
86 pub categories_element: Option<Element<'a>>,
88 pub categories: OwnedVec<SecurityCategory<'a>>,
90}
91
92impl<'a> Clearance<'a> {
93 pub fn read(parent: &mut ScopedReader<'a, '_>) -> Result<Self> {
95 let element = required(parent, FIELD)?;
96 let result = Self::read_element(parent, &element)?;
97 end(parent, FIELD)?;
98 Ok(result)
99 }
100
101 pub fn read_element(parent: &ScopedReader<'a, '_>, element: &Element<'a>) -> Result<Self> {
103 let mut der = parent
104 .reread(element, Encoding::Der)
105 .map_err(|e| Error::encoding(e, FIELD))?;
106 let element = required(&mut der, FIELD)?;
107 tag(&element, sequence(), FIELD)?;
108 end(&der, FIELD)?;
109 let mut inside = der.enter(&element).map_err(|e| Error::encoding(e, FIELD))?;
110 let policy_element = required(&mut inside, FIELD)?;
111 let syntax = if policy_element.tag() == Tag::context(false, 0) {
112 Syntax::Legacy
113 } else {
114 tag(&policy_element, Tag::primitive(universal::OID), FIELD)?;
115 Syntax::Current
116 };
117 let policy = inside
118 .oid(&policy_element)
119 .map_err(|e| Error::encoding(e, FIELD))?;
120 let class_tag = match syntax {
121 Syntax::Current => Tag::primitive(universal::BIT_STRING),
122 Syntax::Legacy => Tag::context(false, 1),
123 };
124 let set_tag = match syntax {
125 Syntax::Current => Tag::constructed(universal::SET),
126 Syntax::Legacy => Tag::context(true, 2),
127 };
128 let mut next = inside
129 .next_element()
130 .map_err(|e| Error::encoding(e, FIELD))?;
131 let classes_element = super::optional(&mut inside, &mut next, class_tag, FIELD)?;
132 let classes = classes_element
133 .map(|encoded| {
134 let bits = inside
135 .bit_string(&encoded)
136 .map_err(|e| Error::encoding(e, FIELD))?;
137 if !bits.is_empty() && !bits.bit(bits.len() - 1) {
140 return Err(Error::schema(
141 ErrorCode::MalformedValue,
142 FIELD,
143 encoded.span().start,
144 ));
145 }
146 if bits.len() == 2 && bits.as_bytes() == [0x40] {
149 return Err(Error::schema(
150 ErrorCode::DefaultWritten,
151 FIELD,
152 encoded.span().start,
153 ));
154 }
155 Ok(bits)
156 })
157 .transpose()?;
158 let categories_element = next;
159 let execution = inside.execution();
160 let mut categories = execution.vector();
161 if let Some(set) = categories_element {
162 tag(&set, set_tag, FIELD)?;
163 let mut entries = inside.enter(&set).map_err(|e| Error::encoding(e, FIELD))?;
164 let mut previous = None;
165 while let Some(entry) = entries
166 .next_element()
167 .map_err(|e| Error::encoding(e, FIELD))?
168 {
169 if let Some(before) = previous
170 && !structured_pkix::der::set_ordered(&entries, before, &entry, FIELD)
171 .map_err(Error::pkix)?
172 {
173 return Err(Error::schema(
174 ErrorCode::SetOrder,
175 FIELD,
176 entry.span().start,
177 ));
178 }
179 categories
180 .try_reserve(1)
181 .map_err(|e| Error::resource(e, FIELD, entry.span().start))?;
182 categories
183 .try_push(category(&entries, &entry)?)
184 .map_err(|e| Error::resource(e, FIELD, entry.span().start))?;
185 previous = Some(entry.as_bytes());
186 }
187 }
188 end(&inside, FIELD)?;
189 Ok(Self {
190 element,
191 syntax,
192 policy,
193 policy_element,
194 classes,
195 classes_element,
196 categories_element,
197 categories: categories.into_owned(),
198 })
199 }
200
201 pub fn read_attribute<W: Work>(attribute: &Attribute<'a>, work: &W) -> Result<OwnedVec<Self>> {
204 let execution = attribute.query_in(work);
205 execution
206 .charge_work(8)
207 .map_err(|e| Error::resource(e, FIELD, attribute.span().start))?;
208 let current = attribute.kind() == IDENTIFIER;
209 if !current && attribute.kind() != LEGACY_IDENTIFIER {
210 return Err(Error::schema(
211 ErrorCode::UnexpectedContentType,
212 FIELD,
213 attribute.span().start,
214 ));
215 }
216 if attribute.values().is_empty() {
217 return Err(Error::schema(
218 ErrorCode::AttributeCardinality,
219 FIELD,
220 attribute.span().start,
221 ));
222 }
223 let mut result = execution.vector();
224 result
225 .try_reserve_exact(attribute.values().len())
226 .map_err(|e| Error::resource(e, FIELD, attribute.span().start))?;
227 for index in 0..attribute.values().len() {
228 let mut reader = attribute
229 .value_reader_scoped(index, &execution, FIELD)?
230 .ok_or_else(|| {
231 Error::schema(
232 ErrorCode::AttributeCardinality,
233 FIELD,
234 attribute.span().start,
235 )
236 })?;
237 let value = Self::read(&mut reader)?;
238 if current && value.syntax == Syntax::Legacy {
239 return Err(Error::schema(
240 ErrorCode::AttributeSyntax,
241 FIELD,
242 value.policy_element.span().start,
243 ));
244 }
245 result
246 .try_push(value)
247 .map_err(|e| Error::resource(e, FIELD, reader.offset()))?;
248 }
249 Ok(result.into_owned())
250 }
251
252 #[must_use]
255 pub fn has_class(&self, position: u64) -> bool {
256 match self.classes {
257 Some(bits) => bits.bit(position),
258 None => position == 1,
259 }
260 }
261}
262
263fn category<'a>(
264 parent: &ScopedReader<'a, '_>,
265 element: &Element<'a>,
266) -> Result<SecurityCategory<'a>> {
267 tag(element, sequence(), FIELD)?;
268 let mut inside = parent
269 .enter(element)
270 .map_err(|e| Error::encoding(e, FIELD))?;
271 let kind_element = required(&mut inside, FIELD)?;
272 tag(&kind_element, Tag::context(false, 0), FIELD)?;
273 let kind = inside
274 .oid(&kind_element)
275 .map_err(|e| Error::encoding(e, FIELD))?;
276 let wrapper = required(&mut inside, FIELD)?;
277 tag(&wrapper, Tag::context(true, 1), FIELD)?;
278 end(&inside, FIELD)?;
279 let mut nested = inside
280 .enter(&wrapper)
281 .map_err(|e| Error::encoding(e, FIELD))?;
282 let value = required(&mut nested, FIELD)?;
283 end(&nested, FIELD)?;
284 structured_pkix::der::conforms(&nested, &value, FIELD).map_err(Error::pkix)?;
285 Ok(SecurityCategory {
286 parser: parent.parser(),
287 depth: nested.depth(),
288 element: *element,
289 kind,
290 kind_element,
291 wrapper,
292 value,
293 })
294}