1use crate::content::{ContentInfo, Encapsulated};
4use crate::signer::{SignerInfo, required};
5use crate::{Error, ErrorCode, Result, oid};
6use structured_asn1::memory::{OwnedVec, Work};
7use structured_asn1::{Element, Encoding, Oid, Parser, Reader, Span, Tag, universal};
8use structured_pkix::{AlgorithmIdentifier, Certificate};
9
10#[derive(Debug, Clone, Copy)]
15pub enum CertificateChoice<'a> {
16 X509(usize),
18 Extended(Element<'a>),
20 AttributeV1(Element<'a>),
22 AttributeV2(Element<'a>),
24 Other(Element<'a>),
26}
27
28#[derive(Debug)]
31pub struct CertificateSet<'a> {
32 source: crate::signer::FieldsSource<'a>,
33 choices: OwnedVec<CertificateChoice<'a>>,
34 certificates: OwnedVec<Certificate<'a>>,
35}
36impl<'a> CertificateSet<'a> {
37 pub fn read(parent: &Reader<'a>, element: &Element<'a>, field: &'static str) -> Result<Self> {
39 let mut version = 1;
40 let (choices, certificates) = read_certificates(parent, element, &mut version, field)?;
41 Ok(Self {
42 source: crate::signer::FieldsSource::entered(parent, *element, field),
43 choices,
44 certificates,
45 })
46 }
47 #[must_use]
49 pub fn choices(&self) -> &[CertificateChoice<'a>] {
50 &self.choices
51 }
52 #[must_use]
54 pub fn certificates(&self) -> &[Certificate<'a>] {
55 &self.certificates
56 }
57 #[must_use]
59 pub fn fields_source(&self) -> crate::signer::FieldsSource<'a> {
60 self.source
61 }
62}
63
64#[derive(Debug)]
68pub struct RevocationSet<'a> {
69 source: crate::signer::FieldsSource<'a>,
70 values: OwnedVec<Element<'a>>,
71}
72impl<'a> RevocationSet<'a> {
73 pub fn read(parent: &Reader<'a>, element: &Element<'a>, field: &'static str) -> Result<Self> {
75 let mut version = 1;
76 let values = read_revocations(parent, element, &mut version, field)?;
77 Ok(Self {
78 source: crate::signer::FieldsSource::entered(parent, *element, field),
79 values,
80 })
81 }
82 #[must_use]
84 pub fn values(&self) -> &[Element<'a>] {
85 &self.values
86 }
87 #[must_use]
89 pub fn fields_source(&self) -> crate::signer::FieldsSource<'a> {
90 self.source
91 }
92}
93
94#[derive(Debug)]
97pub struct OtherRevocationInfo<'a> {
98 reader: Reader<'a>,
99 kind: Oid<'a>,
100 value: Element<'a>,
101}
102
103impl<'a> OtherRevocationInfo<'a> {
104 pub fn read(parent: &Reader<'a>, element: &Element<'a>) -> Result<Self> {
107 const FIELD: &str = "signedData.crls.other";
108 if element.tag() != Tag::context(true, 1) {
109 return Err(Error::schema(
110 ErrorCode::UnexpectedTag,
111 FIELD,
112 element.span().start,
113 ));
114 }
115 let (reader, kind, value) = other_fields(parent, element, FIELD)?;
116 Ok(Self {
117 reader,
118 kind,
119 value,
120 })
121 }
122
123 #[must_use]
125 pub fn kind(&self) -> Oid<'a> {
126 self.kind
127 }
128
129 #[must_use]
131 pub fn value(&self) -> Element<'a> {
132 self.value
133 }
134
135 pub fn ocsp(self) -> Result<Option<structured_pkix::ocsp::ResponseBytes<'a>>> {
141 const FIELD: &str = "signedData.crls.other";
142 self.reader
143 .charge(9)
144 .map_err(|error| Error::encoding(error, FIELD))?;
145 if self.kind != oid::OCSP_RESPONSE {
146 return Ok(None);
147 }
148 match structured_pkix::ocsp::Response::read_element(&self.reader, &self.value)
149 .map_err(Error::pkix)?
150 {
151 structured_pkix::ocsp::Response::Successful(response) => Ok(Some(response)),
152 structured_pkix::ocsp::Response::Failure { span, .. } => {
153 Err(Error::schema(ErrorCode::MalformedValue, FIELD, span.start))
154 }
155 }
156 }
157}
158
159#[derive(Debug)]
161pub struct SignedData<'a> {
162 parser: &'a Parser,
163 encoding: Encoding,
164 outer: u32,
165 version: u64,
166 required_version: u64,
167 algorithms: OwnedVec<AlgorithmIdentifier<'a>>,
168 content: Encapsulated<'a>,
169 choices: OwnedVec<CertificateChoice<'a>>,
170 certificates: OwnedVec<Certificate<'a>>,
171 certificate_field: Option<Span>,
172 revocations: OwnedVec<Element<'a>>,
173 revocation_field: Option<Span>,
174 signers: OwnedVec<SignerInfo<'a>>,
175 signer_set: Element<'a>,
176 faults: OwnedVec<Error>,
177 element: Element<'a>,
178}
179
180impl<'a> SignedData<'a> {
181 pub fn read(parser: &'a Parser, encoded: &'a [u8], base: u64) -> Result<Self> {
183 let mut root = parser
184 .read(encoded, base)
185 .map_err(|error| Error::encoding(error, "contentInfo"))?;
186 let (envelope, parent) = ContentInfo::read(&mut root)?;
187 parent
188 .execution()
189 .charge_work(envelope.kind().as_bytes().len() as u64)
190 .map_err(|reason| {
191 Error::resource(reason, "contentInfo.contentType", envelope.span().start)
192 })?;
193 if envelope.kind() != oid::SIGNED_DATA {
194 return Err(Error::schema(
195 ErrorCode::UnexpectedContentType,
196 "contentInfo.contentType",
197 envelope.span().start,
198 ));
199 }
200 Self::read_element(&parent, envelope.content())
201 }
202
203 pub fn read_element(parent: &Reader<'a>, element: &Element<'a>) -> Result<Self> {
205 const FIELD: &str = "signedData";
206 if element.tag() != Tag::constructed(universal::SEQUENCE) {
207 return Err(Error::schema(
208 ErrorCode::UnexpectedTag,
209 FIELD,
210 element.span().start,
211 ));
212 }
213 let mut inside = parent
214 .enter(element)
215 .map_err(|error| Error::encoding(error, FIELD))?;
216 let execution = parent.execution();
217 let (version, version_element) = read_version(&mut inside)?;
218 let set = required(&mut inside, "signedData.digestAlgorithms")?;
219 let algorithms = catalogue(
220 &inside,
221 &set,
222 Tag::constructed(universal::SET),
223 "signedData.digestAlgorithms",
224 |members, entry| {
225 structured_pkix::algorithm::read(members, entry, "signedData.digestAlgorithms")
226 .map_err(Error::pkix)
227 },
228 )?;
229 let content_element = required(&mut inside, "signedData.encapContentInfo")?;
230 let content = Encapsulated::read(&inside, &content_element)?;
231 execution
232 .charge_work(content.kind().as_bytes().len() as u64)
233 .map_err(|reason| {
234 Error::resource(
235 reason,
236 "signedData.encapContentInfo.eContentType",
237 content.span().start,
238 )
239 })?;
240 let mut required_version = if content.kind() == oid::DATA { 1 } else { 3 };
244 let mut choices = parent.memory().vector();
245 let mut certificates = parent.memory().vector();
246 let mut revocations = parent.memory().vector();
247 let mut certificate_field = None;
248 let mut revocation_field = None;
249 let mut next = required(&mut inside, "signedData.signerInfos")?;
250 if next.tag() == Tag::context(true, 0) {
251 certificate_field = Some(next.span());
252 (choices, certificates) = read_certificates(
253 &inside,
254 &next,
255 &mut required_version,
256 "signedData.certificates",
257 )?;
258 next = required(&mut inside, "signedData.signerInfos")?;
259 }
260 if next.tag() == Tag::context(true, 1) {
261 revocation_field = Some(next.span());
262 revocations =
263 read_revocations(&inside, &next, &mut required_version, "signedData.crls")?;
264 next = required(&mut inside, "signedData.signerInfos")?;
265 }
266 let signers = catalogue(
267 &inside,
268 &next,
269 Tag::constructed(universal::SET),
270 "signedData.signerInfos",
271 |members, entry| {
272 let signer = SignerInfo::read(members, entry)?;
273 if signer.version() == 3 {
274 required_version = required_version.max(3);
275 }
276 Ok(signer)
277 },
278 )?;
279 if !inside.is_empty() {
280 return Err(Error::schema(
281 ErrorCode::TrailingData,
282 FIELD,
283 inside.offset(),
284 ));
285 }
286 let faults = version_fault(&execution, version, required_version, &version_element)?;
287 Ok(Self {
288 parser: parent.parser(),
289 encoding: parent.encoding(),
290 outer: inside.depth(),
291 version,
292 required_version,
293 algorithms,
294 content,
295 choices,
296 certificates,
297 certificate_field,
298 revocations,
299 revocation_field,
300 signers,
301 signer_set: next,
302 faults,
303 element: *element,
304 })
305 }
306
307 #[must_use]
309 pub fn version(&self) -> u64 {
310 self.version
311 }
312 #[must_use]
315 pub fn fields_source(&self) -> crate::signer::FieldsSource<'a> {
316 crate::signer::FieldsSource {
317 parser: self.parser,
318 data: self.element.contents(),
319 base: self.element.contents_span().start,
320 encoding: self.encoding,
321 depth: self.outer,
322 field: "signedData",
323 }
324 }
325 #[must_use]
327 pub fn required_version(&self) -> u64 {
328 self.required_version
329 }
330 #[must_use]
336 pub fn digest_algorithms(&self) -> &[AlgorithmIdentifier<'a>] {
337 &self.algorithms
338 }
339 #[must_use]
342 pub fn signer_set_element(&self) -> Element<'a> {
343 self.signer_set
344 }
345 #[must_use]
347 pub fn content(&self) -> &Encapsulated<'a> {
348 &self.content
349 }
350 #[must_use]
354 pub fn encap_content_encoding(&self) -> &'a [u8] {
355 self.field_encoding(self.content.span())
356 }
357 #[must_use]
359 pub fn certificate_choices(&self) -> &[CertificateChoice<'a>] {
360 &self.choices
361 }
362 #[must_use]
364 pub fn certificates(&self) -> &[Certificate<'a>] {
365 &self.certificates
366 }
367 #[must_use]
369 pub fn certificate_field(&self) -> Option<Span> {
370 self.certificate_field
371 }
372 #[must_use]
375 pub fn certificate_encoding(&self) -> Option<&'a [u8]> {
376 self.certificate_field.map(|span| self.field_encoding(span))
377 }
378 pub fn certificate_choice_reader_in<'query>(
386 &self,
387 query: &Reader<'query>,
388 ordinal: usize,
389 ) -> Result<Option<Reader<'query>>>
390 where
391 'a: 'query,
392 {
393 const FIELD: &str = "signedData.certificates";
394 let at = self.certificate_field.unwrap_or(self.element.span()).start;
395 query
396 .execution()
397 .charge_work(1)
398 .map_err(|reason| Error::resource(reason, FIELD, at))?;
399 let entry = match self.choices.get(ordinal) {
400 Some(
401 CertificateChoice::Extended(entry)
402 | CertificateChoice::AttributeV1(entry)
403 | CertificateChoice::AttributeV2(entry)
404 | CertificateChoice::Other(entry),
405 ) => entry,
406 Some(CertificateChoice::X509(_)) | None => return Ok(None),
407 };
408 self.parser
409 .read_nested_query_in(
410 query,
411 entry.as_bytes(),
412 entry.span().start,
413 self.encoding,
414 self.outer,
415 )
416 .map(Some)
417 .map_err(|error| Error::encoding(error, FIELD))
418 }
419 #[must_use]
421 pub fn revocation_field(&self) -> Option<Span> {
422 self.revocation_field
423 }
424 #[must_use]
426 pub fn revocation_encoding(&self) -> Option<&'a [u8]> {
427 self.revocation_field.map(|span| self.field_encoding(span))
428 }
429 #[must_use]
431 pub fn revocations(&self) -> &[Element<'a>] {
432 &self.revocations
433 }
434 pub fn revocation_reader_in<'query>(
443 &self,
444 query: &Reader<'query>,
445 ordinal: usize,
446 ) -> Result<Option<Reader<'query>>>
447 where
448 'a: 'query,
449 {
450 const FIELD: &str = "signedData.crls";
451 let at = self.revocation_field.unwrap_or(self.element.span()).start;
452 query
453 .execution()
454 .charge_work(1)
455 .map_err(|reason| Error::resource(reason, FIELD, at))?;
456 let Some(entry) = self.revocations.get(ordinal) else {
457 return Ok(None);
458 };
459 self.parser
460 .read_nested_query_in(
461 query,
462 entry.as_bytes(),
463 entry.span().start,
464 self.encoding,
465 self.outer,
466 )
467 .map(Some)
468 .map_err(|error| Error::encoding(error, FIELD))
469 }
470 #[must_use]
472 pub fn signers(&self) -> &[SignerInfo<'a>] {
473 &self.signers
474 }
475 pub fn require_session(&self, parent: &Reader<'_>, field: &'static str) -> Result<()> {
477 if !core::ptr::eq(self.parser, parent.parser()) {
478 return Err(Error::pkix(structured_pkix::Error::new(
479 structured_pkix::ErrorCode::ForeignReader,
480 field,
481 self.element.span().start,
482 )));
483 }
484 Ok(())
485 }
486 pub fn require_signer(&self, signer: &SignerInfo<'_>, field: &'static str) -> Result<()> {
491 let storage = self.signers.as_ptr_range();
492 let address = core::ptr::from_ref(signer).cast::<SignerInfo<'a>>();
493 if !storage.contains(&address) {
494 return Err(Error::schema(
495 ErrorCode::InvalidLocation,
496 field,
497 signer.span().start,
498 ));
499 }
500 Ok(())
501 }
502 #[must_use]
504 pub fn faults(&self) -> &[Error] {
505 &self.faults
506 }
507 #[must_use]
509 pub fn span(&self) -> Span {
510 self.element.span()
511 }
512 #[must_use]
514 pub fn as_bytes(&self) -> &'a [u8] {
515 self.element.as_bytes()
516 }
517
518 fn field_encoding(&self, span: Span) -> &'a [u8] {
519 let start = usize::try_from(span.start - self.element.span().start)
522 .expect("original field starts inside SignedData");
523 let length = usize::try_from(span.length).expect("original field length fits SignedData");
524 &self.element.as_bytes()[start..start + length]
525 }
526}
527
528fn version_fault(
529 execution: &impl Work,
530 version: u64,
531 required: u64,
532 element: &Element<'_>,
533) -> Result<OwnedVec<Error>> {
534 let mut faults = execution.vector();
535 if version != required {
536 faults
537 .try_push(Error::schema(
538 ErrorCode::VersionMismatch,
539 "signedData.version",
540 element.span().start,
541 ))
542 .map_err(|reason| {
543 Error::resource(reason, "signedData.version", element.span().start)
544 })?;
545 }
546 Ok(faults.into_owned())
547}
548
549fn ordered<'a>(
550 parent: &Reader<'a>,
551 previous: &mut Option<&'a [u8]>,
552 element: &Element<'a>,
553 field: &'static str,
554) -> Result<()> {
555 if parent.encoding().is_der() {
556 if let Some(earlier) = *previous
557 && !structured_pkix::der::set_ordered(parent, earlier, element, field)
558 .map_err(Error::pkix)?
559 {
560 return Err(Error::schema(
561 ErrorCode::SetOrder,
562 field,
563 element.span().start,
564 ));
565 }
566 *previous = Some(element.as_bytes());
567 }
568 Ok(())
569}
570
571fn other_format(parent: &Reader<'_>, element: &Element<'_>, field: &'static str) -> Result<()> {
572 other_fields(parent, element, field).map(|_| ())
573}
574
575fn other_fields<'a>(
576 parent: &Reader<'a>,
577 element: &Element<'a>,
578 field: &'static str,
579) -> Result<(Reader<'a>, Oid<'a>, Element<'a>)> {
580 let mut inside = parent
581 .enter(element)
582 .map_err(|error| Error::encoding(error, field))?;
583 let kind = inside
584 .read_oid()
585 .map_err(|error| Error::encoding(error, field))?;
586 let value = required(&mut inside, field)?;
587 if !inside.is_empty() {
588 return Err(Error::schema(
589 ErrorCode::TrailingData,
590 field,
591 inside.offset(),
592 ));
593 }
594 Ok((inside, kind, value))
595}
596
597pub(crate) fn catalogue<'a, T>(
598 parent: &Reader<'a>,
599 set: &Element<'a>,
600 tag: Tag,
601 field: &'static str,
602 mut read: impl FnMut(&Reader<'a>, &Element<'a>) -> Result<T>,
603) -> Result<OwnedVec<T>> {
604 if set.tag() != tag {
605 return Err(Error::schema(
606 ErrorCode::UnexpectedTag,
607 field,
608 set.span().start,
609 ));
610 }
611 let mut members = parent
612 .enter(set)
613 .map_err(|error| Error::encoding(error, field))?;
614 let execution = parent.execution();
615 let mut values = execution.vector();
616 let mut previous = None;
617 while let Some(entry) = members
618 .next_element()
619 .map_err(|error| Error::encoding(error, field))?
620 {
621 ordered(&members, &mut previous, &entry, field)?;
622 values
623 .try_reserve(1)
624 .map_err(|reason| Error::resource(reason, field, entry.span().start))?;
625 let value = read(&members, &entry)?;
626 values
627 .try_push(value)
628 .map_err(|reason| Error::resource(reason, field, entry.span().start))?;
629 }
630 Ok(values.into_owned())
631}
632
633pub(crate) fn read_certificates<'a>(
634 parent: &Reader<'a>,
635 set: &Element<'a>,
636 version: &mut u64,
637 field: &'static str,
638) -> Result<(OwnedVec<CertificateChoice<'a>>, OwnedVec<Certificate<'a>>)> {
639 let execution = parent.execution();
640 let mut certificates = execution.vector();
641 let choices = catalogue(
642 parent,
643 set,
644 Tag::context(true, 0),
645 field,
646 |members, entry| {
647 Ok(match entry.tag() {
648 tag if tag == Tag::constructed(universal::SEQUENCE) => {
649 certificates
650 .try_reserve(1)
651 .map_err(|reason| Error::resource(reason, field, entry.span().start))?;
652 let certificate =
653 Certificate::read_element(members, entry).map_err(Error::pkix)?;
654 let index = certificates.len();
655 certificates
656 .try_push(certificate)
657 .map_err(|reason| Error::resource(reason, field, entry.span().start))?;
658 CertificateChoice::X509(index)
659 }
660 tag if tag == Tag::context(true, 0) => CertificateChoice::Extended(*entry),
661 tag if tag == Tag::context(true, 1) => {
662 *version = (*version).max(3);
663 CertificateChoice::AttributeV1(*entry)
664 }
665 tag if tag == Tag::context(true, 2) => {
666 *version = (*version).max(4);
667 CertificateChoice::AttributeV2(*entry)
668 }
669 tag if tag == Tag::context(true, 3) => {
670 other_format(members, entry, field)?;
671 *version = 5;
672 CertificateChoice::Other(*entry)
673 }
674 _ => {
675 return Err(Error::schema(
676 ErrorCode::UnexpectedTag,
677 field,
678 entry.span().start,
679 ));
680 }
681 })
682 },
683 )?;
684 Ok((choices, certificates.into_owned()))
685}
686
687fn read_version<'a>(inside: &mut Reader<'a>) -> Result<(u64, Element<'a>)> {
688 const FIELD: &str = "signedData.version";
689 let element = inside
690 .expect(Tag::primitive(universal::INTEGER))
691 .map_err(|error| Error::encoding(error, FIELD))?;
692 let version = inside
693 .integer(&element)
694 .map_err(|error| Error::encoding(error, FIELD))?
695 .as_u64()
696 .ok_or_else(|| Error::schema(ErrorCode::ValueTooLarge, FIELD, element.span().start))?;
697 Ok((version, element))
698}
699
700pub(crate) fn read_revocations<'a>(
701 parent: &Reader<'a>,
702 set: &Element<'a>,
703 version: &mut u64,
704 field: &'static str,
705) -> Result<OwnedVec<Element<'a>>> {
706 catalogue(
707 parent,
708 set,
709 Tag::context(true, 1),
710 field,
711 |members, entry| {
712 if entry.tag() == Tag::context(true, 1) {
713 other_format(members, entry, field)?;
714 *version = 5;
715 } else if entry.tag() != Tag::constructed(universal::SEQUENCE) {
716 return Err(Error::schema(
717 ErrorCode::UnexpectedTag,
718 field,
719 entry.span().start,
720 ));
721 }
722 Ok(*entry)
723 },
724 )
725}