1use crate::{Error, ErrorCode, Result};
4use structured_asn1::memory::{Execution, Memory, OwnedVec, Work};
5use structured_asn1::{Element, Encoding, Oid, Parser, Reader, Span, Tag, universal};
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum Placement {
10 Signed,
12 Unsigned,
14}
15
16impl Placement {
17 fn field(self) -> &'static str {
18 match self {
19 Self::Signed => "signerInfo.signedAttrs",
20 Self::Unsigned => "signerInfo.unsignedAttrs",
21 }
22 }
23 fn tag(self) -> Tag {
24 Tag::context(
25 true,
26 match self {
27 Self::Signed => 0,
28 Self::Unsigned => 1,
29 },
30 )
31 }
32}
33
34#[derive(Debug)]
36pub struct Attribute<'a> {
37 kind: Oid<'a>,
38 values: OwnedVec<Element<'a>>,
39 element: Element<'a>,
40 parser: &'a Parser,
41 depth: u32,
42 encoding: Encoding,
43}
44
45impl<'a> Attribute<'a> {
46 fn read(parent: &Reader<'a>, element: &Element<'a>, field: &'static str) -> Result<Self> {
47 if element.tag() != Tag::constructed(universal::SEQUENCE) {
48 return Err(Error::schema(
49 ErrorCode::UnexpectedTag,
50 field,
51 element.span().start,
52 ));
53 }
54 let mut inside = parent
55 .enter(element)
56 .map_err(|error| Error::encoding(error, field))?;
57 let kind = inside
58 .read_oid()
59 .map_err(|error| Error::encoding(error, field))?;
60 let set = inside
61 .expect(Tag::constructed(universal::SET))
62 .map_err(|error| Error::encoding(error, field))?;
63 let mut members = inside
64 .enter(&set)
65 .map_err(|error| Error::encoding(error, field))?;
66 let execution = parent.execution();
67 let mut values = execution.vector();
68 let mut previous = None;
69 while let Some(value) = members
76 .next_element()
77 .map_err(|error| Error::encoding(error, field))?
78 {
79 if members.encoding().is_der() {
80 structured_pkix::der::conforms(&members, &value, field).map_err(Error::pkix)?;
81 if let Some(earlier) = previous
82 && !structured_pkix::der::set_ordered(&members, earlier, &value, field)
83 .map_err(Error::pkix)?
84 {
85 return Err(Error::schema(
86 ErrorCode::AttributeOrder,
87 field,
88 value.span().start,
89 ));
90 }
91 previous = Some(value.as_bytes());
92 }
93 values
94 .try_push(value)
95 .map_err(|reason| Error::resource(reason, field, value.span().start))?;
96 }
97 if !inside.is_empty() {
98 return Err(Error::schema(
99 ErrorCode::TrailingData,
100 field,
101 inside.offset(),
102 ));
103 }
104 Ok(Self {
105 kind,
106 values: values.into_owned(),
107 element: *element,
108 parser: members.parser(),
109 depth: members.depth(),
110 encoding: members.encoding(),
111 })
112 }
113
114 #[must_use]
116 pub fn kind(&self) -> Oid<'a> {
117 self.kind
118 }
119
120 #[must_use]
122 pub fn values(&self) -> &[Element<'a>] {
123 &self.values
124 }
125
126 #[must_use]
128 pub fn span(&self) -> Span {
129 self.element.span()
130 }
131
132 #[must_use]
134 pub fn as_bytes(&self) -> &'a [u8] {
135 self.element.as_bytes()
136 }
137
138 pub fn value_reader(
144 &self,
145 index: usize,
146 execution: &Memory,
147 field: &'static str,
148 ) -> Result<Option<Reader<'a>>> {
149 let Some(value) = self.selected_value(index, execution, field)? else {
150 return Ok(None);
151 };
152 debug_assert!(self.depth > 0);
153 self.parser
154 .read_nested_in(
155 value.as_bytes(),
156 value.span().start,
157 self.encoding,
158 self.depth - 1,
159 execution,
160 )
161 .map(Some)
162 .map_err(|error| Error::encoding(error, field))
163 }
164
165 pub fn value_reader_in<'query>(
169 &self,
170 index: usize,
171 parent: &Reader<'query>,
172 field: &'static str,
173 ) -> Result<Option<Reader<'query>>>
174 where
175 'a: 'query,
176 {
177 if !core::ptr::eq(self.parser, parent.parser()) {
178 return Err(Error::pkix(structured_pkix::Error::new(
179 structured_pkix::ErrorCode::ForeignReader,
180 field,
181 self.element.span().start,
182 )));
183 }
184 let Some(value) = self.selected_value(index, &parent.execution(), field)? else {
185 return Ok(None);
186 };
187 debug_assert!(self.depth > 0);
188 self.parser
189 .read_nested_query_in(
190 parent,
191 value.as_bytes(),
192 value.span().start,
193 self.encoding,
194 self.depth - 1,
195 )
196 .map(Some)
197 .map_err(|error| Error::encoding(error, field))
198 }
199
200 fn selected_value<W: Work>(
201 &self,
202 index: usize,
203 execution: &W,
204 field: &'static str,
205 ) -> Result<Option<Element<'a>>> {
206 execution
207 .charge_work(1)
208 .map_err(|reason| Error::resource(reason, field, self.element.span().start))?;
209 Ok(self.values.get(index).copied())
210 }
211
212 pub fn single(&self, field: &'static str) -> Result<&Element<'a>> {
214 match &*self.values {
215 [value] => Ok(value),
216 _ => Err(Error::schema(
217 ErrorCode::AttributeCardinality,
218 field,
219 self.element.span().start,
220 )),
221 }
222 }
223}
224
225#[derive(Debug)]
227pub struct Attributes<'a> {
228 items: OwnedVec<Attribute<'a>>,
229 element: Element<'a>,
230 placement: Placement,
231}
232
233impl<'a> Attributes<'a> {
234 pub fn read(parent: &Reader<'a>, element: &Element<'a>, placement: Placement) -> Result<Self> {
242 let reading = Self::read_inspection(parent, element, placement)?;
243 if let Some(fault) = reading.fault() {
244 return Err(fault);
245 }
246 Ok(reading)
247 }
248
249 pub fn read_inspection(
256 parent: &Reader<'a>,
257 element: &Element<'a>,
258 placement: Placement,
259 ) -> Result<Self> {
260 if element.tag() != placement.tag() {
261 return Err(Error::schema(
262 ErrorCode::UnexpectedTag,
263 placement.field(),
264 element.span().start,
265 ));
266 }
267 if placement == Placement::Signed {
268 let mut strict = parent
269 .reread(element, Encoding::Der)
270 .map_err(|error| Error::encoding(error, placement.field()))?;
271 let original = strict
272 .expect(placement.tag())
273 .map_err(|error| Error::encoding(error, placement.field()))?;
274 Self::read_set(&strict, &original, placement)
275 } else {
276 Self::read_set(parent, element, placement)
277 }
278 }
279
280 fn read_set(parent: &Reader<'a>, element: &Element<'a>, placement: Placement) -> Result<Self> {
281 let field = placement.field();
282 let mut inside = parent
283 .enter(element)
284 .map_err(|error| Error::encoding(error, field))?;
285 let execution = parent.execution();
286 let mut items = execution.vector();
287 let mut previous = None;
288 while let Some(member) = inside
289 .next_element()
290 .map_err(|error| Error::encoding(error, field))?
291 {
292 if inside.encoding().is_der() {
293 if let Some(earlier) = previous
294 && !structured_pkix::der::set_ordered(&inside, earlier, &member, field)
295 .map_err(Error::pkix)?
296 {
297 return Err(Error::schema(
298 ErrorCode::AttributeOrder,
299 field,
300 member.span().start,
301 ));
302 }
303 previous = Some(member.as_bytes());
304 }
305 let attribute = Attribute::read(&inside, &member, field)?;
306 items
307 .try_push(attribute)
308 .map_err(|reason| Error::resource(reason, field, member.span().start))?;
309 }
310 Ok(Self {
311 items: items.into_owned(),
312 element: *element,
313 placement,
314 })
315 }
316
317 #[must_use]
322 pub fn fault(&self) -> Option<Error> {
323 if self.items.is_empty() {
324 return Some(Error::schema(
325 ErrorCode::EmptyAttributes,
326 self.placement.field(),
327 self.element.span().start,
328 ));
329 }
330 None
331 }
332
333 #[must_use]
335 pub fn items(&self) -> &[Attribute<'a>] {
336 &self.items
337 }
338
339 #[must_use]
341 pub fn element(&self) -> &Element<'a> {
342 &self.element
343 }
344
345 pub fn all<'s>(&'s self, kind: Oid<'s>, execution: &Memory) -> Matching<'s, 'a> {
350 Matching {
351 attributes: self,
352 kind,
353 execution: execution.clone(),
354 next: 0,
355 stopped: false,
356 }
357 }
358
359 pub fn all_in<'s>(
361 &'s self,
362 kind: Oid<'s>,
363 parent: &'s Reader<'_>,
364 ) -> Matching<'s, 'a, Execution<'s>> {
365 Matching {
366 attributes: self,
367 kind,
368 execution: parent.execution(),
369 next: 0,
370 stopped: false,
371 }
372 }
373
374 pub fn unique_in<'s>(
379 &'s self,
380 kind: Oid<'s>,
381 parent: &'s Reader<'_>,
382 ) -> Result<Option<&'s Attribute<'a>>> {
383 let mut found = None;
384 for result in self.all_in(kind, parent) {
385 let attribute = result?;
386 if found.is_some() {
387 return Err(Error::schema(
388 ErrorCode::AttributeCardinality,
389 self.placement.field(),
390 attribute.span().start,
391 ));
392 }
393 found = Some(attribute);
394 }
395 Ok(found)
396 }
397
398 #[must_use]
403 pub fn signed_bytes(&self) -> Option<[&'a [u8]; 2]> {
404 if self.placement != Placement::Signed {
405 return None;
406 }
407 Some([&[0x31], &self.element.as_bytes()[1..]])
408 }
409}
410
411pub struct Matching<'s, 'a, W: Work = Memory> {
413 attributes: &'s Attributes<'a>,
414 kind: Oid<'s>,
415 execution: W,
416 next: usize,
417 stopped: bool,
418}
419
420impl<'s, 'a, W: Work> Iterator for Matching<'s, 'a, W> {
421 type Item = Result<&'s Attribute<'a>>;
422
423 fn next(&mut self) -> Option<Self::Item> {
424 self.attributes.next_matching(
425 self.kind,
426 &self.execution,
427 &mut self.next,
428 &mut self.stopped,
429 )
430 }
431}
432
433impl<'a> Attributes<'a> {
434 pub(crate) fn next_matching<'s>(
435 &'s self,
436 kind: Oid<'_>,
437 execution: &impl Work,
438 next: &mut usize,
439 stopped: &mut bool,
440 ) -> Option<Result<&'s Attribute<'a>>> {
441 if *stopped {
442 return None;
443 }
444 let field = self.placement.field();
445 loop {
446 if let Err(reason) = execution.charge_work(1) {
447 *stopped = true;
448 let at = self
449 .items
450 .get(*next)
451 .map_or(self.element.span().start, |attribute| {
452 attribute.span().start
453 });
454 return Some(Err(Error::resource(reason, field, at)));
455 }
456 let Some(attribute) = self.items.get(*next) else {
457 *stopped = true;
458 return None;
459 };
460 *next += 1;
461 if attribute.kind.as_bytes().len() != kind.as_bytes().len() {
462 continue;
463 }
464 if let Err(reason) = execution.charge_work(attribute.kind.as_bytes().len() as u64) {
465 *stopped = true;
466 return Some(Err(Error::resource(reason, field, attribute.span().start)));
467 }
468 if attribute.kind == kind {
469 return Some(Ok(attribute));
470 }
471 }
472 }
473}
474
475impl<W: Work> core::iter::FusedIterator for Matching<'_, '_, W> {}