1use crate::attribute::{Attributes, Placement};
4use crate::{Error, ErrorCode, Octets, Result};
5use structured_asn1::memory::{OwnedVec, Work};
6use structured_asn1::{Element, Encoding, Integer, Reader, ScopedReader, Span, Tag, universal};
7use structured_pkix::Name;
8use structured_pkix::algorithm::AlgorithmReading;
9
10#[derive(Debug)]
12pub enum SignerIdentifier<'a> {
13 IssuerAndSerial {
15 issuer: Name<'a>,
17 serial: Integer<'a>,
19 },
20 SubjectKeyIdentifier(Octets<'a>),
22}
23
24impl<'a> SignerIdentifier<'a> {
25 fn read(parent: &Reader<'a>, element: &Element<'a>) -> Result<Self> {
26 Self::read_as(parent, element, "signerInfo.sid")
27 }
28
29 pub(crate) fn read_as(
30 parent: &Reader<'a>,
31 element: &Element<'a>,
32 field: &'static str,
33 ) -> Result<Self> {
34 if element.tag() == Tag::context(false, 0) || element.tag() == Tag::context(true, 0) {
35 return Octets::read_identifier(parent, element, field).map(Self::SubjectKeyIdentifier);
36 }
37 if element.tag() != Tag::constructed(universal::SEQUENCE) {
38 return Err(Error::schema(
39 ErrorCode::UnexpectedTag,
40 field,
41 element.span().start,
42 ));
43 }
44 let mut inside = parent
45 .enter(element)
46 .map_err(|error| Error::encoding(error, field))?;
47 let name = inside
48 .expect(Tag::constructed(universal::SEQUENCE))
49 .map_err(|error| Error::encoding(error, field))?;
50 let issuer = structured_pkix::name::read(&inside, &name, field).map_err(Error::pkix)?;
51 let serial = inside
52 .read_integer()
53 .map_err(|error| Error::encoding(error, field))?;
54 if !inside.is_empty() {
55 return Err(Error::schema(
56 ErrorCode::TrailingData,
57 field,
58 inside.offset(),
59 ));
60 }
61 Ok(Self::IssuerAndSerial { issuer, serial })
62 }
63
64 #[must_use]
66 pub fn required_version(&self) -> u64 {
67 match self {
68 Self::IssuerAndSerial { .. } => 1,
69 Self::SubjectKeyIdentifier(_) => 3,
70 }
71 }
72}
73
74#[derive(Debug, Clone, Copy)]
78pub struct Fields<'d> {
79 pub(crate) parser: &'d structured_asn1::Parser,
80 pub(crate) depth: u32,
81 pub identity: [Element<'d>; 3],
83 pub signature: [Element<'d>; 2],
85}
86
87#[derive(Debug)]
89pub struct SignerInfo<'a> {
90 parser: &'a structured_asn1::Parser,
91 depth: u32,
92 fields: Fields<'a>,
93 version: u64,
94 sid: SignerIdentifier<'a>,
95 digest_algorithm: AlgorithmReading<'a>,
96 signed_attributes: Option<Attributes<'a>>,
97 signature_algorithm: AlgorithmReading<'a>,
98 signature: Octets<'a>,
99 signed_fields: &'a [u8],
100 unsigned_attributes: Option<Attributes<'a>>,
101 encoding: Encoding,
102 element: Element<'a>,
103 faults: OwnedVec<Error>,
104}
105
106impl<'a> SignerInfo<'a> {
107 #[must_use]
109 pub fn fields(&self) -> Fields<'a> {
110 self.fields
111 }
112 pub fn require_session(&self, parent: &Reader<'_>, field: &'static str) -> Result<()> {
115 if !self.digest_algorithm.same_session(parent) {
116 return Err(Error::pkix(structured_pkix::Error::new(
117 structured_pkix::ErrorCode::ForeignReader,
118 field,
119 self.span().start,
120 )));
121 }
122 Ok(())
123 }
124 pub fn read(parent: &Reader<'a>, element: &Element<'a>) -> Result<Self> {
135 const FIELD: &str = "signerInfo";
136 if element.tag() != Tag::constructed(universal::SEQUENCE) {
137 return Err(Error::schema(
138 ErrorCode::UnexpectedTag,
139 FIELD,
140 element.span().start,
141 ));
142 }
143 let mut inside = parent
144 .enter(element)
145 .map_err(|error| Error::encoding(error, FIELD))?;
146 let execution = parent.execution();
147 let mut faults = execution.vector();
148 let version_element = inside
149 .expect(Tag::primitive(universal::INTEGER))
150 .map_err(|error| Error::encoding(error, "signerInfo.version"))?;
151 let version = inside
152 .integer(&version_element)
153 .map_err(|error| Error::encoding(error, "signerInfo.version"))?
154 .as_u64()
155 .ok_or_else(|| {
156 Error::schema(
157 ErrorCode::ValueTooLarge,
158 "signerInfo.version",
159 version_element.span().start,
160 )
161 })?;
162 let named = required(&mut inside, "signerInfo.sid")?;
163 let sid = SignerIdentifier::read(&inside, &named)?;
164 if version != sid.required_version() {
165 faults
166 .try_push(Error::schema(
167 ErrorCode::VersionMismatch,
168 "signerInfo.version",
169 version_element.span().start,
170 ))
171 .map_err(|reason| {
172 Error::resource(reason, "signerInfo.version", version_element.span().start)
173 })?;
174 }
175 let digest = required(&mut inside, "signerInfo.digestAlgorithm")?;
176 let digest_algorithm =
177 read_algorithm(&inside, &digest, "signerInfo.digestAlgorithm", &mut faults)?;
178 let mut next = required(&mut inside, "signerInfo.signatureAlgorithm")?;
179 let signed_attributes = if next.tag() == Tag::context(true, 0) {
180 let attributes = read_attributes(&inside, &next, Placement::Signed, &mut faults)?;
181 next = required(&mut inside, "signerInfo.signatureAlgorithm")?;
182 Some(attributes)
183 } else {
184 None
185 };
186 let signature_algorithm_element = next;
187 let signature_algorithm =
188 read_algorithm(&inside, &next, "signerInfo.signatureAlgorithm", &mut faults)?;
189 let signature_element = required(&mut inside, "signerInfo.signature")?;
190 let signature = Octets::read(&inside, &signature_element, "signerInfo.signature")?;
191 let signed_fields = field_range(element, &version_element, &signature_element);
192 let unsigned_attributes = match inside
193 .next_element()
194 .map_err(|error| Error::encoding(error, "signerInfo.unsignedAttrs"))?
195 {
196 Some(attributes) => Some(read_attributes(
197 &inside,
198 &attributes,
199 Placement::Unsigned,
200 &mut faults,
201 )?),
202 None => None,
203 };
204 if !inside.is_empty() {
205 return Err(Error::schema(
206 ErrorCode::TrailingData,
207 FIELD,
208 inside.offset(),
209 ));
210 }
211 Ok(Self {
212 parser: parent.parser(),
213 depth: inside.depth(),
214 fields: Fields {
215 parser: parent.parser(),
216 depth: inside.depth(),
217 identity: [version_element, named, digest],
218 signature: [signature_algorithm_element, signature_element],
219 },
220 version,
221 sid,
222 digest_algorithm,
223 signed_attributes,
224 signature_algorithm,
225 signature,
226 signed_fields,
227 unsigned_attributes,
228 encoding: inside.encoding(),
229 element: *element,
230 faults: faults.into_owned(),
231 })
232 }
233
234 #[must_use]
236 pub fn version(&self) -> u64 {
237 self.version
238 }
239 #[must_use]
241 pub fn sid(&self) -> &SignerIdentifier<'a> {
242 &self.sid
243 }
244 #[must_use]
247 pub fn digest_algorithm(&self) -> &AlgorithmReading<'a> {
248 &self.digest_algorithm
249 }
250 #[must_use]
252 pub fn signed_attributes(&self) -> Option<&Attributes<'a>> {
253 self.signed_attributes.as_ref()
254 }
255 #[must_use]
258 pub fn signature_algorithm(&self) -> &AlgorithmReading<'a> {
259 &self.signature_algorithm
260 }
261 #[must_use]
263 pub fn signature(&self) -> &Octets<'a> {
264 &self.signature
265 }
266 #[must_use]
268 pub fn unsigned_attributes(&self) -> Option<&Attributes<'a>> {
269 self.unsigned_attributes.as_ref()
270 }
271
272 #[must_use]
275 pub fn signed_fields(&self) -> &'a [u8] {
276 self.signed_fields
277 }
278
279 pub fn countersignatures_in<'s>(
282 &'s self,
283 parent: &'s Reader<'a>,
284 ) -> crate::counter::Countersignatures<'s, 'a> {
285 crate::counter::Countersignatures::new(self, parent)
286 }
287 #[must_use]
289 pub fn encoding(&self) -> Encoding {
290 self.encoding
291 }
292 #[must_use]
294 pub fn span(&self) -> Span {
295 self.element.span()
296 }
297 #[must_use]
303 pub fn element(&self) -> &Element<'a> {
304 &self.element
305 }
306 #[must_use]
310 pub fn fields_source(&self) -> FieldsSource<'a> {
311 FieldsSource {
312 parser: self.parser,
313 data: self.element.contents(),
314 base: self.element.contents_span().start,
315 encoding: self.encoding,
316 depth: self.depth,
317 field: "signerInfo",
318 }
319 }
320 #[must_use]
322 pub fn as_bytes(&self) -> &'a [u8] {
323 self.element.as_bytes()
324 }
325 #[must_use]
331 pub fn faults(&self) -> &[Error] {
332 &self.faults
333 }
334
335 pub fn same_value(&self, other: &SignerInfo<'_>, parent: &Reader<'_>) -> Result<bool> {
346 if !self.same_fields(other, parent)? {
347 return Ok(false);
348 }
349 let comparison_error = |source| duplicate_comparison_error(source, other.span().start);
352 if !self
357 .digest_algorithm
358 .same_written_in(&other.digest_algorithm, parent)
359 .map_err(comparison_error)?
360 {
361 let (Some(left), Some(right)) = (
362 self.digest_algorithm.identifier(),
363 other.digest_algorithm.identifier(),
364 ) else {
365 return Ok(false);
368 };
369 if !left
370 .digest_matches_in(&right, parent)
371 .map_err(comparison_error)?
372 {
373 return Ok(false);
374 }
375 }
376 self.signature_algorithm
377 .same_written_in(&other.signature_algorithm, parent)
378 .map_err(comparison_error)
379 }
380
381 pub(crate) fn same_fields(&self, other: &SignerInfo<'_>, parent: &Reader<'_>) -> Result<bool> {
385 let field = "signedData.signerInfos";
386 let at = other.span().start;
387 self.require_session(parent, field)?;
388 other.require_session(parent, field)?;
389 parent
390 .execution()
391 .charge_work(1)
392 .map_err(|reason| Error::resource(reason, field, at))?;
393 if self.version != other.version {
394 return Ok(false);
395 }
396 let same_sid = match (&self.sid, &other.sid) {
397 (
398 SignerIdentifier::IssuerAndSerial { issuer, serial },
399 SignerIdentifier::IssuerAndSerial {
400 issuer: right,
401 serial: number,
402 },
403 ) => {
404 issuer
408 .matches_in(right, parent)
409 .map_err(|source| duplicate_comparison_error(source, at))?
410 && same_bytes(parent, serial.as_bytes(), number.as_bytes(), field, at)?
411 }
412 (
413 SignerIdentifier::SubjectKeyIdentifier(left),
414 SignerIdentifier::SubjectKeyIdentifier(right),
415 ) => left.same_value(right, parent, field, at)?,
416 _ => false,
417 };
418 if !same_sid {
419 return Ok(false);
420 }
421 for (left, right) in [
422 (&self.signed_attributes, &other.signed_attributes),
423 (&self.unsigned_attributes, &other.unsigned_attributes),
424 ] {
425 if !same_optional(
426 parent,
427 left.as_ref().map(|attrs| attrs.element().as_bytes()),
428 right.as_ref().map(|attrs| attrs.element().as_bytes()),
429 field,
430 at,
431 )? {
432 return Ok(false);
433 }
434 }
435 self.signature
436 .same_value(&other.signature, parent, field, at)
437 }
438}
439
440#[derive(Debug, Clone, Copy)]
444pub struct FieldsSource<'d> {
445 pub(crate) parser: &'d structured_asn1::Parser,
446 pub(crate) data: &'d [u8],
447 pub(crate) base: u64,
448 pub(crate) encoding: Encoding,
449 pub(crate) depth: u32,
450 pub(crate) field: &'static str,
451}
452impl<'d> FieldsSource<'d> {
453 pub(crate) fn entered(parent: &Reader<'d>, element: Element<'d>, field: &'static str) -> Self {
457 debug_assert!(element.tag().is_constructed());
458 Self {
459 parser: parent.parser(),
460 data: element.contents(),
461 base: element.contents_span().start,
462 encoding: parent.encoding(),
463 depth: parent.depth() + 1,
464 field,
465 }
466 }
467 pub fn reader_in<'operation, W: Work>(
470 &self,
471 work: &'operation W,
472 ) -> Result<structured_asn1::ScopedReader<'d, 'operation>>
473 where
474 'd: 'operation,
475 {
476 work.read_scoped_source(self.parser, self.data, self.base, self.encoding, self.depth)
477 .map_err(|cause| Error::encoding(cause, self.field))
478 }
479 pub fn query_in<'query>(&self, operation: &Reader<'query>) -> Result<Reader<'query>>
484 where
485 'd: 'query,
486 {
487 self.parser
488 .read_query_in(operation, self.data, self.base, self.encoding, self.depth)
489 .map_err(|cause| Error::encoding(cause, self.field))
490 }
491 #[must_use]
493 pub fn as_bytes(self) -> &'d [u8] {
494 self.data
495 }
496 #[must_use]
498 pub fn depth(self) -> u32 {
499 self.depth
500 }
501}
502
503fn read_attributes<'a, W: Work>(
504 parent: &Reader<'a>,
505 element: &Element<'a>,
506 placement: Placement,
507 faults: &mut OwnedVec<Error, W>,
508) -> Result<Attributes<'a>> {
509 let reading = Attributes::read_inspection(parent, element, placement)?;
510 if let Some(fault) = reading.fault() {
511 let field = fault.field();
512 let at = fault.offset();
513 faults
514 .try_push(fault)
515 .map_err(|reason| Error::resource(reason, field, at))?;
516 }
517 reading.inspect_registered(parent, faults)?;
518 Ok(reading)
519}
520
521fn read_algorithm<'a, W: Work>(
522 parent: &Reader<'a>,
523 element: &Element<'a>,
524 field: &'static str,
525 faults: &mut OwnedVec<Error, W>,
526) -> Result<AlgorithmReading<'a>> {
527 let reading =
533 structured_pkix::algorithm::read_inspection(parent, element, field).map_err(Error::pkix)?;
534 if let Some(fault) = reading.fault() {
535 faults
536 .try_push(Error::pkix(fault.clone()))
537 .map_err(|reason| Error::resource(reason, fault.field(), fault.offset()))?;
538 }
539 Ok(reading)
540}
541
542fn duplicate_comparison_error(source: structured_pkix::Error, at: u64) -> Error {
543 if source.is_resource() {
544 Error::pkix(structured_pkix::Error::new(
545 source.code(),
546 "signedData.signerInfos",
547 at,
548 ))
549 } else {
550 Error::pkix(source)
551 }
552}
553
554fn field_range<'a>(signer: &Element<'a>, first: &Element<'a>, last: &Element<'a>) -> &'a [u8] {
557 let origin = signer.span().start;
558 let start = first.span().start - origin;
559 let end = last.span().start + last.span().length - origin;
560 let bytes = signer.as_bytes();
561 let start = usize::try_from(start).expect("member offset fits the signer encoding");
563 let end = usize::try_from(end).expect("member end fits the signer encoding");
564 &bytes[start..end]
565}
566
567pub(crate) fn required<'a>(
568 reader: &mut ScopedReader<'a, '_>,
569 field: &'static str,
570) -> Result<Element<'a>> {
571 reader
572 .next_element()
573 .map_err(|error| Error::encoding(error, field))?
574 .ok_or_else(|| Error::schema(ErrorCode::MissingField, field, reader.offset()))
575}
576
577fn same_bytes(
578 parent: &Reader<'_>,
579 left: &[u8],
580 right: &[u8],
581 field: &'static str,
582 at: u64,
583) -> Result<bool> {
584 let execution = parent.execution();
585 execution
586 .charge_work(1)
587 .map_err(|reason| Error::resource(reason, field, at))?;
588 if left.len() != right.len() {
589 return Ok(false);
590 }
591 execution
592 .charge_work(left.len() as u64)
593 .map_err(|reason| Error::resource(reason, field, at))?;
594 Ok(left == right)
595}
596
597fn same_optional(
598 parent: &Reader<'_>,
599 left: Option<&[u8]>,
600 right: Option<&[u8]>,
601 field: &'static str,
602 at: u64,
603) -> Result<bool> {
604 parent
605 .execution()
606 .charge_work(1)
607 .map_err(|reason| Error::resource(reason, field, at))?;
608 match (left, right) {
609 (None, None) => Ok(true),
610 (Some(left), Some(right)) => same_bytes(parent, left, right, field, at),
611 _ => Ok(false),
612 }
613}