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 OtherRevocationInfo<'a> {
32 reader: Reader<'a>,
33 kind: Oid<'a>,
34 value: Element<'a>,
35}
36
37impl<'a> OtherRevocationInfo<'a> {
38 pub fn read(parent: &Reader<'a>, element: &Element<'a>) -> Result<Self> {
41 const FIELD: &str = "signedData.crls.other";
42 if element.tag() != Tag::context(true, 1) {
43 return Err(Error::schema(
44 ErrorCode::UnexpectedTag,
45 FIELD,
46 element.span().start,
47 ));
48 }
49 let (reader, kind, value) = other_fields(parent, element, FIELD)?;
50 Ok(Self {
51 reader,
52 kind,
53 value,
54 })
55 }
56
57 #[must_use]
59 pub fn kind(&self) -> Oid<'a> {
60 self.kind
61 }
62
63 #[must_use]
65 pub fn value(&self) -> Element<'a> {
66 self.value
67 }
68
69 pub fn ocsp(self) -> Result<Option<structured_pkix::ocsp::ResponseBytes<'a>>> {
75 const FIELD: &str = "signedData.crls.other";
76 self.reader
77 .charge(9)
78 .map_err(|error| Error::encoding(error, FIELD))?;
79 if self.kind != oid::OCSP_RESPONSE {
80 return Ok(None);
81 }
82 match structured_pkix::ocsp::Response::read_element(&self.reader, &self.value)
83 .map_err(Error::pkix)?
84 {
85 structured_pkix::ocsp::Response::Successful(response) => Ok(Some(response)),
86 structured_pkix::ocsp::Response::Failure { span, .. } => {
87 Err(Error::schema(ErrorCode::MalformedValue, FIELD, span.start))
88 }
89 }
90 }
91}
92
93#[derive(Debug)]
95pub struct SignedData<'a> {
96 parser: &'a Parser,
97 encoding: Encoding,
98 outer: u32,
99 version: u64,
100 required_version: u64,
101 algorithms: OwnedVec<AlgorithmIdentifier<'a>>,
102 content: Encapsulated<'a>,
103 choices: OwnedVec<CertificateChoice<'a>>,
104 certificates: OwnedVec<Certificate<'a>>,
105 certificate_field: Option<Span>,
106 revocations: OwnedVec<Element<'a>>,
107 revocation_field: Option<Span>,
108 signers: OwnedVec<SignerInfo<'a>>,
109 faults: OwnedVec<Error>,
110 element: Element<'a>,
111}
112
113impl<'a> SignedData<'a> {
114 pub fn read(parser: &'a Parser, encoded: &'a [u8], base: u64) -> Result<Self> {
116 let mut root = parser
117 .read(encoded, base)
118 .map_err(|error| Error::encoding(error, "contentInfo"))?;
119 let (envelope, parent) = ContentInfo::read(&mut root)?;
120 parent
121 .execution()
122 .charge_work(envelope.kind().as_bytes().len() as u64)
123 .map_err(|reason| {
124 Error::resource(reason, "contentInfo.contentType", envelope.span().start)
125 })?;
126 if envelope.kind() != oid::SIGNED_DATA {
127 return Err(Error::schema(
128 ErrorCode::UnexpectedContentType,
129 "contentInfo.contentType",
130 envelope.span().start,
131 ));
132 }
133 Self::read_element(&parent, envelope.content())
134 }
135
136 pub fn read_element(parent: &Reader<'a>, element: &Element<'a>) -> Result<Self> {
138 const FIELD: &str = "signedData";
139 if element.tag() != Tag::constructed(universal::SEQUENCE) {
140 return Err(Error::schema(
141 ErrorCode::UnexpectedTag,
142 FIELD,
143 element.span().start,
144 ));
145 }
146 let mut inside = parent
147 .enter(element)
148 .map_err(|error| Error::encoding(error, FIELD))?;
149 let execution = parent.execution();
150 let (version, version_element) = read_version(&mut inside)?;
151 let set = required(&mut inside, "signedData.digestAlgorithms")?;
152 let algorithms = catalogue(
153 &inside,
154 &set,
155 Tag::constructed(universal::SET),
156 "signedData.digestAlgorithms",
157 |members, entry| {
158 structured_pkix::algorithm::read(members, entry, "signedData.digestAlgorithms")
159 .map_err(Error::pkix)
160 },
161 )?;
162 let content_element = required(&mut inside, "signedData.encapContentInfo")?;
163 let content = Encapsulated::read(&inside, &content_element)?;
164 execution
165 .charge_work(content.kind().as_bytes().len() as u64)
166 .map_err(|reason| {
167 Error::resource(
168 reason,
169 "signedData.encapContentInfo.eContentType",
170 content.span().start,
171 )
172 })?;
173 let mut required_version = if content.kind() == oid::DATA { 1 } else { 3 };
177 let mut choices = parent.memory().vector();
178 let mut certificates = parent.memory().vector();
179 let mut revocations = parent.memory().vector();
180 let mut certificate_field = None;
181 let mut revocation_field = None;
182 let mut next = required(&mut inside, "signedData.signerInfos")?;
183 if next.tag() == Tag::context(true, 0) {
184 certificate_field = Some(next.span());
185 (choices, certificates) = read_certificates(
186 &inside,
187 &next,
188 &mut required_version,
189 "signedData.certificates",
190 )?;
191 next = required(&mut inside, "signedData.signerInfos")?;
192 }
193 if next.tag() == Tag::context(true, 1) {
194 revocation_field = Some(next.span());
195 revocations =
196 read_revocations(&inside, &next, &mut required_version, "signedData.crls")?;
197 next = required(&mut inside, "signedData.signerInfos")?;
198 }
199 let signers = catalogue(
200 &inside,
201 &next,
202 Tag::constructed(universal::SET),
203 "signedData.signerInfos",
204 |members, entry| {
205 let signer = SignerInfo::read(members, entry)?;
206 if signer.version() == 3 {
207 required_version = required_version.max(3);
208 }
209 Ok(signer)
210 },
211 )?;
212 if !inside.is_empty() {
213 return Err(Error::schema(
214 ErrorCode::TrailingData,
215 FIELD,
216 inside.offset(),
217 ));
218 }
219 let faults = version_fault(&execution, version, required_version, &version_element)?;
220 Ok(Self {
221 parser: parent.parser(),
222 encoding: parent.encoding(),
223 outer: inside.depth(),
224 version,
225 required_version,
226 algorithms,
227 content,
228 choices,
229 certificates,
230 certificate_field,
231 revocations,
232 revocation_field,
233 signers,
234 faults,
235 element: *element,
236 })
237 }
238
239 #[must_use]
241 pub fn version(&self) -> u64 {
242 self.version
243 }
244 #[must_use]
246 pub fn required_version(&self) -> u64 {
247 self.required_version
248 }
249 #[must_use]
255 pub fn digest_algorithms(&self) -> &[AlgorithmIdentifier<'a>] {
256 &self.algorithms
257 }
258 #[must_use]
260 pub fn content(&self) -> &Encapsulated<'a> {
261 &self.content
262 }
263 #[must_use]
267 pub fn encap_content_encoding(&self) -> &'a [u8] {
268 self.field_encoding(self.content.span())
269 }
270 #[must_use]
272 pub fn certificate_choices(&self) -> &[CertificateChoice<'a>] {
273 &self.choices
274 }
275 #[must_use]
277 pub fn certificates(&self) -> &[Certificate<'a>] {
278 &self.certificates
279 }
280 #[must_use]
282 pub fn certificate_field(&self) -> Option<Span> {
283 self.certificate_field
284 }
285 #[must_use]
288 pub fn certificate_encoding(&self) -> Option<&'a [u8]> {
289 self.certificate_field.map(|span| self.field_encoding(span))
290 }
291 pub fn certificate_choice_reader_in<'query>(
299 &self,
300 query: &Reader<'query>,
301 ordinal: usize,
302 ) -> Result<Option<Reader<'query>>>
303 where
304 'a: 'query,
305 {
306 const FIELD: &str = "signedData.certificates";
307 let at = self.certificate_field.unwrap_or(self.element.span()).start;
308 query
309 .execution()
310 .charge_work(1)
311 .map_err(|reason| Error::resource(reason, FIELD, at))?;
312 let entry = match self.choices.get(ordinal) {
313 Some(
314 CertificateChoice::Extended(entry)
315 | CertificateChoice::AttributeV1(entry)
316 | CertificateChoice::AttributeV2(entry)
317 | CertificateChoice::Other(entry),
318 ) => entry,
319 Some(CertificateChoice::X509(_)) | None => return Ok(None),
320 };
321 self.parser
322 .read_nested_query_in(
323 query,
324 entry.as_bytes(),
325 entry.span().start,
326 self.encoding,
327 self.outer,
328 )
329 .map(Some)
330 .map_err(|error| Error::encoding(error, FIELD))
331 }
332 #[must_use]
334 pub fn revocation_field(&self) -> Option<Span> {
335 self.revocation_field
336 }
337 #[must_use]
339 pub fn revocation_encoding(&self) -> Option<&'a [u8]> {
340 self.revocation_field.map(|span| self.field_encoding(span))
341 }
342 #[must_use]
344 pub fn revocations(&self) -> &[Element<'a>] {
345 &self.revocations
346 }
347 pub fn revocation_reader_in<'query>(
356 &self,
357 query: &Reader<'query>,
358 ordinal: usize,
359 ) -> Result<Option<Reader<'query>>>
360 where
361 'a: 'query,
362 {
363 const FIELD: &str = "signedData.crls";
364 let at = self.revocation_field.unwrap_or(self.element.span()).start;
365 query
366 .execution()
367 .charge_work(1)
368 .map_err(|reason| Error::resource(reason, FIELD, at))?;
369 let Some(entry) = self.revocations.get(ordinal) else {
370 return Ok(None);
371 };
372 self.parser
373 .read_nested_query_in(
374 query,
375 entry.as_bytes(),
376 entry.span().start,
377 self.encoding,
378 self.outer,
379 )
380 .map(Some)
381 .map_err(|error| Error::encoding(error, FIELD))
382 }
383 #[must_use]
385 pub fn signers(&self) -> &[SignerInfo<'a>] {
386 &self.signers
387 }
388 pub fn require_session(&self, parent: &Reader<'_>, field: &'static str) -> Result<()> {
390 if !core::ptr::eq(self.parser, parent.parser()) {
391 return Err(Error::pkix(structured_pkix::Error::new(
392 structured_pkix::ErrorCode::ForeignReader,
393 field,
394 self.element.span().start,
395 )));
396 }
397 Ok(())
398 }
399 pub fn require_signer(&self, signer: &SignerInfo<'_>, field: &'static str) -> Result<()> {
404 let storage = self.signers.as_ptr_range();
405 let address = core::ptr::from_ref(signer).cast::<SignerInfo<'a>>();
406 if !storage.contains(&address) {
407 return Err(Error::schema(
408 ErrorCode::InvalidLocation,
409 field,
410 signer.span().start,
411 ));
412 }
413 Ok(())
414 }
415 #[must_use]
417 pub fn faults(&self) -> &[Error] {
418 &self.faults
419 }
420 #[must_use]
422 pub fn span(&self) -> Span {
423 self.element.span()
424 }
425 #[must_use]
427 pub fn as_bytes(&self) -> &'a [u8] {
428 self.element.as_bytes()
429 }
430
431 fn field_encoding(&self, span: Span) -> &'a [u8] {
432 let start = usize::try_from(span.start - self.element.span().start)
435 .expect("original field starts inside SignedData");
436 let length = usize::try_from(span.length).expect("original field length fits SignedData");
437 &self.element.as_bytes()[start..start + length]
438 }
439}
440
441fn version_fault(
442 execution: &impl Work,
443 version: u64,
444 required: u64,
445 element: &Element<'_>,
446) -> Result<OwnedVec<Error>> {
447 let mut faults = execution.vector();
448 if version != required {
449 faults
450 .try_push(Error::schema(
451 ErrorCode::VersionMismatch,
452 "signedData.version",
453 element.span().start,
454 ))
455 .map_err(|reason| {
456 Error::resource(reason, "signedData.version", element.span().start)
457 })?;
458 }
459 Ok(faults.into_owned())
460}
461
462fn ordered<'a>(
463 parent: &Reader<'a>,
464 previous: &mut Option<&'a [u8]>,
465 element: &Element<'a>,
466 field: &'static str,
467) -> Result<()> {
468 if parent.encoding().is_der() {
469 if let Some(earlier) = *previous
470 && !structured_pkix::der::set_ordered(parent, earlier, element, field)
471 .map_err(Error::pkix)?
472 {
473 return Err(Error::schema(
474 ErrorCode::SetOrder,
475 field,
476 element.span().start,
477 ));
478 }
479 *previous = Some(element.as_bytes());
480 }
481 Ok(())
482}
483
484fn other_format(parent: &Reader<'_>, element: &Element<'_>, field: &'static str) -> Result<()> {
485 other_fields(parent, element, field).map(|_| ())
486}
487
488fn other_fields<'a>(
489 parent: &Reader<'a>,
490 element: &Element<'a>,
491 field: &'static str,
492) -> Result<(Reader<'a>, Oid<'a>, Element<'a>)> {
493 let mut inside = parent
494 .enter(element)
495 .map_err(|error| Error::encoding(error, field))?;
496 let kind = inside
497 .read_oid()
498 .map_err(|error| Error::encoding(error, field))?;
499 let value = required(&mut inside, field)?;
500 if !inside.is_empty() {
501 return Err(Error::schema(
502 ErrorCode::TrailingData,
503 field,
504 inside.offset(),
505 ));
506 }
507 Ok((inside, kind, value))
508}
509
510pub(crate) fn catalogue<'a, T>(
511 parent: &Reader<'a>,
512 set: &Element<'a>,
513 tag: Tag,
514 field: &'static str,
515 mut read: impl FnMut(&Reader<'a>, &Element<'a>) -> Result<T>,
516) -> Result<OwnedVec<T>> {
517 if set.tag() != tag {
518 return Err(Error::schema(
519 ErrorCode::UnexpectedTag,
520 field,
521 set.span().start,
522 ));
523 }
524 let mut members = parent
525 .enter(set)
526 .map_err(|error| Error::encoding(error, field))?;
527 let execution = parent.execution();
528 let mut values = execution.vector();
529 let mut previous = None;
530 while let Some(entry) = members
531 .next_element()
532 .map_err(|error| Error::encoding(error, field))?
533 {
534 ordered(&members, &mut previous, &entry, field)?;
535 values
536 .try_reserve(1)
537 .map_err(|reason| Error::resource(reason, field, entry.span().start))?;
538 let value = read(&members, &entry)?;
539 values
540 .try_push(value)
541 .map_err(|reason| Error::resource(reason, field, entry.span().start))?;
542 }
543 Ok(values.into_owned())
544}
545
546pub(crate) fn read_certificates<'a>(
547 parent: &Reader<'a>,
548 set: &Element<'a>,
549 version: &mut u64,
550 field: &'static str,
551) -> Result<(OwnedVec<CertificateChoice<'a>>, OwnedVec<Certificate<'a>>)> {
552 let execution = parent.execution();
553 let mut certificates = execution.vector();
554 let choices = catalogue(
555 parent,
556 set,
557 Tag::context(true, 0),
558 field,
559 |members, entry| {
560 Ok(match entry.tag() {
561 tag if tag == Tag::constructed(universal::SEQUENCE) => {
562 certificates
563 .try_reserve(1)
564 .map_err(|reason| Error::resource(reason, field, entry.span().start))?;
565 let certificate =
566 Certificate::read_element(members, entry).map_err(Error::pkix)?;
567 let index = certificates.len();
568 certificates
569 .try_push(certificate)
570 .map_err(|reason| Error::resource(reason, field, entry.span().start))?;
571 CertificateChoice::X509(index)
572 }
573 tag if tag == Tag::context(true, 0) => CertificateChoice::Extended(*entry),
574 tag if tag == Tag::context(true, 1) => {
575 *version = (*version).max(3);
576 CertificateChoice::AttributeV1(*entry)
577 }
578 tag if tag == Tag::context(true, 2) => {
579 *version = (*version).max(4);
580 CertificateChoice::AttributeV2(*entry)
581 }
582 tag if tag == Tag::context(true, 3) => {
583 other_format(members, entry, field)?;
584 *version = 5;
585 CertificateChoice::Other(*entry)
586 }
587 _ => {
588 return Err(Error::schema(
589 ErrorCode::UnexpectedTag,
590 field,
591 entry.span().start,
592 ));
593 }
594 })
595 },
596 )?;
597 Ok((choices, certificates.into_owned()))
598}
599
600fn read_version<'a>(inside: &mut Reader<'a>) -> Result<(u64, Element<'a>)> {
601 const FIELD: &str = "signedData.version";
602 let element = inside
603 .expect(Tag::primitive(universal::INTEGER))
604 .map_err(|error| Error::encoding(error, FIELD))?;
605 let version = inside
606 .integer(&element)
607 .map_err(|error| Error::encoding(error, FIELD))?
608 .as_u64()
609 .ok_or_else(|| Error::schema(ErrorCode::ValueTooLarge, FIELD, element.span().start))?;
610 Ok((version, element))
611}
612
613pub(crate) fn read_revocations<'a>(
614 parent: &Reader<'a>,
615 set: &Element<'a>,
616 version: &mut u64,
617 field: &'static str,
618) -> Result<OwnedVec<Element<'a>>> {
619 catalogue(
620 parent,
621 set,
622 Tag::context(true, 1),
623 field,
624 |members, entry| {
625 if entry.tag() == Tag::context(true, 1) {
626 other_format(members, entry, field)?;
627 *version = 5;
628 } else if entry.tag() != Tag::constructed(universal::SEQUENCE) {
629 return Err(Error::schema(
630 ErrorCode::UnexpectedTag,
631 field,
632 entry.span().start,
633 ));
634 }
635 Ok(*entry)
636 },
637 )
638}