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(&inside, &next, &mut required_version)?;
186 next = required(&mut inside, "signedData.signerInfos")?;
187 }
188 if next.tag() == Tag::context(true, 1) {
189 revocation_field = Some(next.span());
190 revocations = read_revocations(&inside, &next, &mut required_version)?;
191 next = required(&mut inside, "signedData.signerInfos")?;
192 }
193 let signers = catalogue(
194 &inside,
195 &next,
196 Tag::constructed(universal::SET),
197 "signedData.signerInfos",
198 |members, entry| {
199 let signer = SignerInfo::read(members, entry)?;
200 if signer.version() == 3 {
201 required_version = required_version.max(3);
202 }
203 Ok(signer)
204 },
205 )?;
206 if !inside.is_empty() {
207 return Err(Error::schema(
208 ErrorCode::TrailingData,
209 FIELD,
210 inside.offset(),
211 ));
212 }
213 let faults = version_fault(&execution, version, required_version, &version_element)?;
214 Ok(Self {
215 parser: parent.parser(),
216 encoding: parent.encoding(),
217 outer: inside.depth(),
218 version,
219 required_version,
220 algorithms,
221 content,
222 choices,
223 certificates,
224 certificate_field,
225 revocations,
226 revocation_field,
227 signers,
228 faults,
229 element: *element,
230 })
231 }
232
233 #[must_use]
235 pub fn version(&self) -> u64 {
236 self.version
237 }
238 #[must_use]
240 pub fn required_version(&self) -> u64 {
241 self.required_version
242 }
243 #[must_use]
249 pub fn digest_algorithms(&self) -> &[AlgorithmIdentifier<'a>] {
250 &self.algorithms
251 }
252 #[must_use]
254 pub fn content(&self) -> &Encapsulated<'a> {
255 &self.content
256 }
257 #[must_use]
259 pub fn certificate_choices(&self) -> &[CertificateChoice<'a>] {
260 &self.choices
261 }
262 #[must_use]
264 pub fn certificates(&self) -> &[Certificate<'a>] {
265 &self.certificates
266 }
267 #[must_use]
269 pub fn certificate_field(&self) -> Option<Span> {
270 self.certificate_field
271 }
272 pub fn certificate_choice_reader_in<'query>(
280 &self,
281 query: &Reader<'query>,
282 ordinal: usize,
283 ) -> Result<Option<Reader<'query>>>
284 where
285 'a: 'query,
286 {
287 const FIELD: &str = "signedData.certificates";
288 let at = self.certificate_field.unwrap_or(self.element.span()).start;
289 query
290 .execution()
291 .charge_work(1)
292 .map_err(|reason| Error::resource(reason, FIELD, at))?;
293 let entry = match self.choices.get(ordinal) {
294 Some(
295 CertificateChoice::Extended(entry)
296 | CertificateChoice::AttributeV1(entry)
297 | CertificateChoice::AttributeV2(entry)
298 | CertificateChoice::Other(entry),
299 ) => entry,
300 Some(CertificateChoice::X509(_)) | None => return Ok(None),
301 };
302 self.parser
303 .read_nested_query_in(
304 query,
305 entry.as_bytes(),
306 entry.span().start,
307 self.encoding,
308 self.outer,
309 )
310 .map(Some)
311 .map_err(|error| Error::encoding(error, FIELD))
312 }
313 #[must_use]
315 pub fn revocation_field(&self) -> Option<Span> {
316 self.revocation_field
317 }
318 #[must_use]
320 pub fn revocations(&self) -> &[Element<'a>] {
321 &self.revocations
322 }
323 pub fn revocation_reader_in<'query>(
332 &self,
333 query: &Reader<'query>,
334 ordinal: usize,
335 ) -> Result<Option<Reader<'query>>>
336 where
337 'a: 'query,
338 {
339 const FIELD: &str = "signedData.crls";
340 let at = self.revocation_field.unwrap_or(self.element.span()).start;
341 query
342 .execution()
343 .charge_work(1)
344 .map_err(|reason| Error::resource(reason, FIELD, at))?;
345 let Some(entry) = self.revocations.get(ordinal) else {
346 return Ok(None);
347 };
348 self.parser
349 .read_nested_query_in(
350 query,
351 entry.as_bytes(),
352 entry.span().start,
353 self.encoding,
354 self.outer,
355 )
356 .map(Some)
357 .map_err(|error| Error::encoding(error, FIELD))
358 }
359 #[must_use]
361 pub fn signers(&self) -> &[SignerInfo<'a>] {
362 &self.signers
363 }
364 pub fn require_session(&self, parent: &Reader<'_>, field: &'static str) -> Result<()> {
366 if !core::ptr::eq(self.parser, parent.parser()) {
367 return Err(Error::pkix(structured_pkix::Error::new(
368 structured_pkix::ErrorCode::ForeignReader,
369 field,
370 self.element.span().start,
371 )));
372 }
373 Ok(())
374 }
375 pub fn require_signer(&self, signer: &SignerInfo<'_>, field: &'static str) -> Result<()> {
380 let storage = self.signers.as_ptr_range();
381 let address = core::ptr::from_ref(signer).cast::<SignerInfo<'a>>();
382 if !storage.contains(&address) {
383 return Err(Error::schema(
384 ErrorCode::InvalidLocation,
385 field,
386 signer.span().start,
387 ));
388 }
389 Ok(())
390 }
391 #[must_use]
393 pub fn faults(&self) -> &[Error] {
394 &self.faults
395 }
396 #[must_use]
398 pub fn span(&self) -> Span {
399 self.element.span()
400 }
401 #[must_use]
403 pub fn as_bytes(&self) -> &'a [u8] {
404 self.element.as_bytes()
405 }
406}
407
408fn version_fault(
409 execution: &impl Work,
410 version: u64,
411 required: u64,
412 element: &Element<'_>,
413) -> Result<OwnedVec<Error>> {
414 let mut faults = execution.vector();
415 if version != required {
416 faults
417 .try_push(Error::schema(
418 ErrorCode::VersionMismatch,
419 "signedData.version",
420 element.span().start,
421 ))
422 .map_err(|reason| {
423 Error::resource(reason, "signedData.version", element.span().start)
424 })?;
425 }
426 Ok(faults.into_owned())
427}
428
429fn ordered<'a>(
430 parent: &Reader<'a>,
431 previous: &mut Option<&'a [u8]>,
432 element: &Element<'a>,
433 field: &'static str,
434) -> Result<()> {
435 if parent.encoding().is_der() {
436 if let Some(earlier) = *previous
437 && !structured_pkix::der::set_ordered(parent, earlier, element, field)
438 .map_err(Error::pkix)?
439 {
440 return Err(Error::schema(
441 ErrorCode::SetOrder,
442 field,
443 element.span().start,
444 ));
445 }
446 *previous = Some(element.as_bytes());
447 }
448 Ok(())
449}
450
451fn other_format(parent: &Reader<'_>, element: &Element<'_>, field: &'static str) -> Result<()> {
452 other_fields(parent, element, field).map(|_| ())
453}
454
455fn other_fields<'a>(
456 parent: &Reader<'a>,
457 element: &Element<'a>,
458 field: &'static str,
459) -> Result<(Reader<'a>, Oid<'a>, Element<'a>)> {
460 let mut inside = parent
461 .enter(element)
462 .map_err(|error| Error::encoding(error, field))?;
463 let kind = inside
464 .read_oid()
465 .map_err(|error| Error::encoding(error, field))?;
466 let value = required(&mut inside, field)?;
467 if !inside.is_empty() {
468 return Err(Error::schema(
469 ErrorCode::TrailingData,
470 field,
471 inside.offset(),
472 ));
473 }
474 Ok((inside, kind, value))
475}
476
477fn catalogue<'a, T>(
478 parent: &Reader<'a>,
479 set: &Element<'a>,
480 tag: Tag,
481 field: &'static str,
482 mut read: impl FnMut(&Reader<'a>, &Element<'a>) -> Result<T>,
483) -> Result<OwnedVec<T>> {
484 if set.tag() != tag {
485 return Err(Error::schema(
486 ErrorCode::UnexpectedTag,
487 field,
488 set.span().start,
489 ));
490 }
491 let mut members = parent
492 .enter(set)
493 .map_err(|error| Error::encoding(error, field))?;
494 let execution = parent.execution();
495 let mut values = execution.vector();
496 let mut previous = None;
497 while let Some(entry) = members
498 .next_element()
499 .map_err(|error| Error::encoding(error, field))?
500 {
501 ordered(&members, &mut previous, &entry, field)?;
502 values
503 .try_reserve(1)
504 .map_err(|reason| Error::resource(reason, field, entry.span().start))?;
505 let value = read(&members, &entry)?;
506 values
507 .try_push(value)
508 .map_err(|reason| Error::resource(reason, field, entry.span().start))?;
509 }
510 Ok(values.into_owned())
511}
512
513fn read_certificates<'a>(
514 parent: &Reader<'a>,
515 set: &Element<'a>,
516 version: &mut u64,
517) -> Result<(OwnedVec<CertificateChoice<'a>>, OwnedVec<Certificate<'a>>)> {
518 const FIELD: &str = "signedData.certificates";
519 let execution = parent.execution();
520 let mut certificates = execution.vector();
521 let choices = catalogue(
522 parent,
523 set,
524 Tag::context(true, 0),
525 FIELD,
526 |members, entry| {
527 Ok(match entry.tag() {
528 tag if tag == Tag::constructed(universal::SEQUENCE) => {
529 certificates
530 .try_reserve(1)
531 .map_err(|reason| Error::resource(reason, FIELD, entry.span().start))?;
532 let certificate =
533 Certificate::read_element(members, entry).map_err(Error::pkix)?;
534 let index = certificates.len();
535 certificates
536 .try_push(certificate)
537 .map_err(|reason| Error::resource(reason, FIELD, entry.span().start))?;
538 CertificateChoice::X509(index)
539 }
540 tag if tag == Tag::context(true, 0) => CertificateChoice::Extended(*entry),
541 tag if tag == Tag::context(true, 1) => {
542 *version = (*version).max(3);
543 CertificateChoice::AttributeV1(*entry)
544 }
545 tag if tag == Tag::context(true, 2) => {
546 *version = (*version).max(4);
547 CertificateChoice::AttributeV2(*entry)
548 }
549 tag if tag == Tag::context(true, 3) => {
550 other_format(members, entry, FIELD)?;
551 *version = 5;
552 CertificateChoice::Other(*entry)
553 }
554 _ => {
555 return Err(Error::schema(
556 ErrorCode::UnexpectedTag,
557 FIELD,
558 entry.span().start,
559 ));
560 }
561 })
562 },
563 )?;
564 Ok((choices, certificates.into_owned()))
565}
566
567fn read_version<'a>(inside: &mut Reader<'a>) -> Result<(u64, Element<'a>)> {
568 const FIELD: &str = "signedData.version";
569 let element = inside
570 .expect(Tag::primitive(universal::INTEGER))
571 .map_err(|error| Error::encoding(error, FIELD))?;
572 let version = inside
573 .integer(&element)
574 .map_err(|error| Error::encoding(error, FIELD))?
575 .as_u64()
576 .ok_or_else(|| Error::schema(ErrorCode::ValueTooLarge, FIELD, element.span().start))?;
577 Ok((version, element))
578}
579
580fn read_revocations<'a>(
581 parent: &Reader<'a>,
582 set: &Element<'a>,
583 version: &mut u64,
584) -> Result<OwnedVec<Element<'a>>> {
585 const FIELD: &str = "signedData.crls";
586 catalogue(
587 parent,
588 set,
589 Tag::context(true, 1),
590 FIELD,
591 |members, entry| {
592 if entry.tag() == Tag::context(true, 1) {
593 other_format(members, entry, FIELD)?;
594 *version = 5;
595 } else if entry.tag() != Tag::constructed(universal::SEQUENCE) {
596 return Err(Error::schema(
597 ErrorCode::UnexpectedTag,
598 FIELD,
599 entry.span().start,
600 ));
601 }
602 Ok(*entry)
603 },
604 )
605}