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 const FIELD: &str = "signerInfo.sid";
27 if element.tag() == Tag::context(false, 0) || element.tag() == Tag::context(true, 0) {
28 return Octets::read_identifier(parent, element, FIELD).map(Self::SubjectKeyIdentifier);
29 }
30 if element.tag() != Tag::constructed(universal::SEQUENCE) {
31 return Err(Error::schema(
32 ErrorCode::UnexpectedTag,
33 FIELD,
34 element.span().start,
35 ));
36 }
37 let mut inside = parent
38 .enter(element)
39 .map_err(|error| Error::encoding(error, FIELD))?;
40 let name = inside
41 .expect(Tag::constructed(universal::SEQUENCE))
42 .map_err(|error| Error::encoding(error, FIELD))?;
43 let issuer = structured_pkix::name::read(&inside, &name, FIELD).map_err(Error::pkix)?;
44 let serial = inside
45 .read_integer()
46 .map_err(|error| Error::encoding(error, FIELD))?;
47 if !inside.is_empty() {
48 return Err(Error::schema(
49 ErrorCode::TrailingData,
50 FIELD,
51 inside.offset(),
52 ));
53 }
54 Ok(Self::IssuerAndSerial { issuer, serial })
55 }
56
57 #[must_use]
59 pub fn required_version(&self) -> u64 {
60 match self {
61 Self::IssuerAndSerial { .. } => 1,
62 Self::SubjectKeyIdentifier(_) => 3,
63 }
64 }
65}
66
67#[derive(Debug)]
69pub struct SignerInfo<'a> {
70 version: u64,
71 sid: SignerIdentifier<'a>,
72 digest_algorithm: AlgorithmReading<'a>,
73 signed_attributes: Option<Attributes<'a>>,
74 signature_algorithm: AlgorithmReading<'a>,
75 signature: Octets<'a>,
76 signed_fields: &'a [u8],
77 unsigned_attributes: Option<Attributes<'a>>,
78 encoding: Encoding,
79 element: Element<'a>,
80 faults: OwnedVec<Error>,
81}
82
83impl<'a> SignerInfo<'a> {
84 pub fn require_session(&self, parent: &Reader<'_>, field: &'static str) -> Result<()> {
87 if !self.digest_algorithm.same_session(parent) {
88 return Err(Error::pkix(structured_pkix::Error::new(
89 structured_pkix::ErrorCode::ForeignReader,
90 field,
91 self.span().start,
92 )));
93 }
94 Ok(())
95 }
96 pub fn read(parent: &Reader<'a>, element: &Element<'a>) -> Result<Self> {
107 const FIELD: &str = "signerInfo";
108 if element.tag() != Tag::constructed(universal::SEQUENCE) {
109 return Err(Error::schema(
110 ErrorCode::UnexpectedTag,
111 FIELD,
112 element.span().start,
113 ));
114 }
115 let mut inside = parent
116 .enter(element)
117 .map_err(|error| Error::encoding(error, FIELD))?;
118 let execution = parent.execution();
119 let mut faults = execution.vector();
120 let version_element = inside
121 .expect(Tag::primitive(universal::INTEGER))
122 .map_err(|error| Error::encoding(error, "signerInfo.version"))?;
123 let version = inside
124 .integer(&version_element)
125 .map_err(|error| Error::encoding(error, "signerInfo.version"))?
126 .as_u64()
127 .ok_or_else(|| {
128 Error::schema(
129 ErrorCode::ValueTooLarge,
130 "signerInfo.version",
131 version_element.span().start,
132 )
133 })?;
134 let named = required(&mut inside, "signerInfo.sid")?;
135 let sid = SignerIdentifier::read(&inside, &named)?;
136 if version != sid.required_version() {
137 faults
138 .try_push(Error::schema(
139 ErrorCode::VersionMismatch,
140 "signerInfo.version",
141 version_element.span().start,
142 ))
143 .map_err(|reason| {
144 Error::resource(reason, "signerInfo.version", version_element.span().start)
145 })?;
146 }
147 let digest = required(&mut inside, "signerInfo.digestAlgorithm")?;
148 let digest_algorithm =
149 read_algorithm(&inside, &digest, "signerInfo.digestAlgorithm", &mut faults)?;
150 let mut next = required(&mut inside, "signerInfo.signatureAlgorithm")?;
151 let signed_attributes = if next.tag() == Tag::context(true, 0) {
152 let attributes = read_attributes(&inside, &next, Placement::Signed, &mut faults)?;
153 next = required(&mut inside, "signerInfo.signatureAlgorithm")?;
154 Some(attributes)
155 } else {
156 None
157 };
158 let signature_algorithm =
159 read_algorithm(&inside, &next, "signerInfo.signatureAlgorithm", &mut faults)?;
160 let signature_element = required(&mut inside, "signerInfo.signature")?;
161 let signature = Octets::read(&inside, &signature_element, "signerInfo.signature")?;
162 let signed_fields = field_range(element, &version_element, &signature_element);
163 let unsigned_attributes = match inside
164 .next_element()
165 .map_err(|error| Error::encoding(error, "signerInfo.unsignedAttrs"))?
166 {
167 Some(attributes) => Some(read_attributes(
168 &inside,
169 &attributes,
170 Placement::Unsigned,
171 &mut faults,
172 )?),
173 None => None,
174 };
175 if !inside.is_empty() {
176 return Err(Error::schema(
177 ErrorCode::TrailingData,
178 FIELD,
179 inside.offset(),
180 ));
181 }
182 Ok(Self {
183 version,
184 sid,
185 digest_algorithm,
186 signed_attributes,
187 signature_algorithm,
188 signature,
189 signed_fields,
190 unsigned_attributes,
191 encoding: inside.encoding(),
192 element: *element,
193 faults: faults.into_owned(),
194 })
195 }
196
197 #[must_use]
199 pub fn version(&self) -> u64 {
200 self.version
201 }
202 #[must_use]
204 pub fn sid(&self) -> &SignerIdentifier<'a> {
205 &self.sid
206 }
207 #[must_use]
210 pub fn digest_algorithm(&self) -> &AlgorithmReading<'a> {
211 &self.digest_algorithm
212 }
213 #[must_use]
215 pub fn signed_attributes(&self) -> Option<&Attributes<'a>> {
216 self.signed_attributes.as_ref()
217 }
218 #[must_use]
221 pub fn signature_algorithm(&self) -> &AlgorithmReading<'a> {
222 &self.signature_algorithm
223 }
224 #[must_use]
226 pub fn signature(&self) -> &Octets<'a> {
227 &self.signature
228 }
229 #[must_use]
231 pub fn unsigned_attributes(&self) -> Option<&Attributes<'a>> {
232 self.unsigned_attributes.as_ref()
233 }
234
235 #[must_use]
238 pub fn signed_fields(&self) -> &'a [u8] {
239 self.signed_fields
240 }
241
242 pub fn countersignatures_in<'s>(
245 &'s self,
246 parent: &'s Reader<'a>,
247 ) -> crate::counter::Countersignatures<'s, 'a> {
248 crate::counter::Countersignatures::new(self, parent)
249 }
250 #[must_use]
252 pub fn encoding(&self) -> Encoding {
253 self.encoding
254 }
255 #[must_use]
257 pub fn span(&self) -> Span {
258 self.element.span()
259 }
260 #[must_use]
266 pub fn element(&self) -> &Element<'a> {
267 &self.element
268 }
269 #[must_use]
271 pub fn as_bytes(&self) -> &'a [u8] {
272 self.element.as_bytes()
273 }
274 #[must_use]
280 pub fn faults(&self) -> &[Error] {
281 &self.faults
282 }
283
284 pub fn same_value(&self, other: &SignerInfo<'_>, parent: &Reader<'_>) -> Result<bool> {
295 if !self.same_fields(other, parent)? {
296 return Ok(false);
297 }
298 let comparison_error = |source| duplicate_comparison_error(source, other.span().start);
301 if !self
306 .digest_algorithm
307 .same_written_in(&other.digest_algorithm, parent)
308 .map_err(comparison_error)?
309 {
310 let (Some(left), Some(right)) = (
311 self.digest_algorithm.identifier(),
312 other.digest_algorithm.identifier(),
313 ) else {
314 return Ok(false);
317 };
318 if !left
319 .digest_matches_in(&right, parent)
320 .map_err(comparison_error)?
321 {
322 return Ok(false);
323 }
324 }
325 self.signature_algorithm
326 .same_written_in(&other.signature_algorithm, parent)
327 .map_err(comparison_error)
328 }
329
330 pub(crate) fn same_fields(&self, other: &SignerInfo<'_>, parent: &Reader<'_>) -> Result<bool> {
334 let field = "signedData.signerInfos";
335 let at = other.span().start;
336 self.require_session(parent, field)?;
337 other.require_session(parent, field)?;
338 parent
339 .execution()
340 .charge_work(1)
341 .map_err(|reason| Error::resource(reason, field, at))?;
342 if self.version != other.version {
343 return Ok(false);
344 }
345 let same_sid = match (&self.sid, &other.sid) {
346 (
347 SignerIdentifier::IssuerAndSerial { issuer, serial },
348 SignerIdentifier::IssuerAndSerial {
349 issuer: right,
350 serial: number,
351 },
352 ) => {
353 issuer
357 .matches_in(right, parent)
358 .map_err(|source| duplicate_comparison_error(source, at))?
359 && same_bytes(parent, serial.as_bytes(), number.as_bytes(), field, at)?
360 }
361 (
362 SignerIdentifier::SubjectKeyIdentifier(left),
363 SignerIdentifier::SubjectKeyIdentifier(right),
364 ) => left.same_value(right, parent, field, at)?,
365 _ => false,
366 };
367 if !same_sid {
368 return Ok(false);
369 }
370 for (left, right) in [
371 (&self.signed_attributes, &other.signed_attributes),
372 (&self.unsigned_attributes, &other.unsigned_attributes),
373 ] {
374 if !same_optional(
375 parent,
376 left.as_ref().map(|attrs| attrs.element().as_bytes()),
377 right.as_ref().map(|attrs| attrs.element().as_bytes()),
378 field,
379 at,
380 )? {
381 return Ok(false);
382 }
383 }
384 self.signature
385 .same_value(&other.signature, parent, field, at)
386 }
387}
388
389fn read_attributes<'a, W: Work>(
390 parent: &Reader<'a>,
391 element: &Element<'a>,
392 placement: Placement,
393 faults: &mut OwnedVec<Error, W>,
394) -> Result<Attributes<'a>> {
395 let reading = Attributes::read_inspection(parent, element, placement)?;
396 if let Some(fault) = reading.fault() {
397 let field = fault.field();
398 let at = fault.offset();
399 faults
400 .try_push(fault)
401 .map_err(|reason| Error::resource(reason, field, at))?;
402 }
403 reading.inspect_registered(parent, faults)?;
404 Ok(reading)
405}
406
407fn read_algorithm<'a, W: Work>(
408 parent: &Reader<'a>,
409 element: &Element<'a>,
410 field: &'static str,
411 faults: &mut OwnedVec<Error, W>,
412) -> Result<AlgorithmReading<'a>> {
413 let reading =
419 structured_pkix::algorithm::read_inspection(parent, element, field).map_err(Error::pkix)?;
420 if let Some(fault) = reading.fault() {
421 faults
422 .try_push(Error::pkix(fault.clone()))
423 .map_err(|reason| Error::resource(reason, fault.field(), fault.offset()))?;
424 }
425 Ok(reading)
426}
427
428fn duplicate_comparison_error(source: structured_pkix::Error, at: u64) -> Error {
429 if source.is_resource() {
430 Error::pkix(structured_pkix::Error::new(
431 source.code(),
432 "signedData.signerInfos",
433 at,
434 ))
435 } else {
436 Error::pkix(source)
437 }
438}
439
440fn field_range<'a>(signer: &Element<'a>, first: &Element<'a>, last: &Element<'a>) -> &'a [u8] {
443 let origin = signer.span().start;
444 let start = first.span().start - origin;
445 let end = last.span().start + last.span().length - origin;
446 let bytes = signer.as_bytes();
447 let start = usize::try_from(start).expect("member offset fits the signer encoding");
449 let end = usize::try_from(end).expect("member end fits the signer encoding");
450 &bytes[start..end]
451}
452
453pub(crate) fn required<'a>(
454 reader: &mut ScopedReader<'a, '_>,
455 field: &'static str,
456) -> Result<Element<'a>> {
457 reader
458 .next_element()
459 .map_err(|error| Error::encoding(error, field))?
460 .ok_or_else(|| Error::schema(ErrorCode::MissingField, field, reader.offset()))
461}
462
463fn same_bytes(
464 parent: &Reader<'_>,
465 left: &[u8],
466 right: &[u8],
467 field: &'static str,
468 at: u64,
469) -> Result<bool> {
470 let execution = parent.execution();
471 execution
472 .charge_work(1)
473 .map_err(|reason| Error::resource(reason, field, at))?;
474 if left.len() != right.len() {
475 return Ok(false);
476 }
477 execution
478 .charge_work(left.len() as u64)
479 .map_err(|reason| Error::resource(reason, field, at))?;
480 Ok(left == right)
481}
482
483fn same_optional(
484 parent: &Reader<'_>,
485 left: Option<&[u8]>,
486 right: Option<&[u8]>,
487 field: &'static str,
488 at: u64,
489) -> Result<bool> {
490 parent
491 .execution()
492 .charge_work(1)
493 .map_err(|reason| Error::resource(reason, field, at))?;
494 match (left, right) {
495 (None, None) => Ok(true),
496 (Some(left), Some(right)) => same_bytes(parent, left, right, field, at),
497 _ => Ok(false),
498 }
499}