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