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)]
76pub struct SignerInfo<'a> {
77 version: u64,
78 sid: SignerIdentifier<'a>,
79 digest_algorithm: AlgorithmReading<'a>,
80 signed_attributes: Option<Attributes<'a>>,
81 signature_algorithm: AlgorithmReading<'a>,
82 signature: Octets<'a>,
83 signed_fields: &'a [u8],
84 unsigned_attributes: Option<Attributes<'a>>,
85 encoding: Encoding,
86 element: Element<'a>,
87 faults: OwnedVec<Error>,
88}
89
90impl<'a> SignerInfo<'a> {
91 pub fn require_session(&self, parent: &Reader<'_>, field: &'static str) -> Result<()> {
94 if !self.digest_algorithm.same_session(parent) {
95 return Err(Error::pkix(structured_pkix::Error::new(
96 structured_pkix::ErrorCode::ForeignReader,
97 field,
98 self.span().start,
99 )));
100 }
101 Ok(())
102 }
103 pub fn read(parent: &Reader<'a>, element: &Element<'a>) -> Result<Self> {
114 const FIELD: &str = "signerInfo";
115 if element.tag() != Tag::constructed(universal::SEQUENCE) {
116 return Err(Error::schema(
117 ErrorCode::UnexpectedTag,
118 FIELD,
119 element.span().start,
120 ));
121 }
122 let mut inside = parent
123 .enter(element)
124 .map_err(|error| Error::encoding(error, FIELD))?;
125 let execution = parent.execution();
126 let mut faults = execution.vector();
127 let version_element = inside
128 .expect(Tag::primitive(universal::INTEGER))
129 .map_err(|error| Error::encoding(error, "signerInfo.version"))?;
130 let version = inside
131 .integer(&version_element)
132 .map_err(|error| Error::encoding(error, "signerInfo.version"))?
133 .as_u64()
134 .ok_or_else(|| {
135 Error::schema(
136 ErrorCode::ValueTooLarge,
137 "signerInfo.version",
138 version_element.span().start,
139 )
140 })?;
141 let named = required(&mut inside, "signerInfo.sid")?;
142 let sid = SignerIdentifier::read(&inside, &named)?;
143 if version != sid.required_version() {
144 faults
145 .try_push(Error::schema(
146 ErrorCode::VersionMismatch,
147 "signerInfo.version",
148 version_element.span().start,
149 ))
150 .map_err(|reason| {
151 Error::resource(reason, "signerInfo.version", version_element.span().start)
152 })?;
153 }
154 let digest = required(&mut inside, "signerInfo.digestAlgorithm")?;
155 let digest_algorithm =
156 read_algorithm(&inside, &digest, "signerInfo.digestAlgorithm", &mut faults)?;
157 let mut next = required(&mut inside, "signerInfo.signatureAlgorithm")?;
158 let signed_attributes = if next.tag() == Tag::context(true, 0) {
159 let attributes = read_attributes(&inside, &next, Placement::Signed, &mut faults)?;
160 next = required(&mut inside, "signerInfo.signatureAlgorithm")?;
161 Some(attributes)
162 } else {
163 None
164 };
165 let signature_algorithm =
166 read_algorithm(&inside, &next, "signerInfo.signatureAlgorithm", &mut faults)?;
167 let signature_element = required(&mut inside, "signerInfo.signature")?;
168 let signature = Octets::read(&inside, &signature_element, "signerInfo.signature")?;
169 let signed_fields = field_range(element, &version_element, &signature_element);
170 let unsigned_attributes = match inside
171 .next_element()
172 .map_err(|error| Error::encoding(error, "signerInfo.unsignedAttrs"))?
173 {
174 Some(attributes) => Some(read_attributes(
175 &inside,
176 &attributes,
177 Placement::Unsigned,
178 &mut faults,
179 )?),
180 None => None,
181 };
182 if !inside.is_empty() {
183 return Err(Error::schema(
184 ErrorCode::TrailingData,
185 FIELD,
186 inside.offset(),
187 ));
188 }
189 Ok(Self {
190 version,
191 sid,
192 digest_algorithm,
193 signed_attributes,
194 signature_algorithm,
195 signature,
196 signed_fields,
197 unsigned_attributes,
198 encoding: inside.encoding(),
199 element: *element,
200 faults: faults.into_owned(),
201 })
202 }
203
204 #[must_use]
206 pub fn version(&self) -> u64 {
207 self.version
208 }
209 #[must_use]
211 pub fn sid(&self) -> &SignerIdentifier<'a> {
212 &self.sid
213 }
214 #[must_use]
217 pub fn digest_algorithm(&self) -> &AlgorithmReading<'a> {
218 &self.digest_algorithm
219 }
220 #[must_use]
222 pub fn signed_attributes(&self) -> Option<&Attributes<'a>> {
223 self.signed_attributes.as_ref()
224 }
225 #[must_use]
228 pub fn signature_algorithm(&self) -> &AlgorithmReading<'a> {
229 &self.signature_algorithm
230 }
231 #[must_use]
233 pub fn signature(&self) -> &Octets<'a> {
234 &self.signature
235 }
236 #[must_use]
238 pub fn unsigned_attributes(&self) -> Option<&Attributes<'a>> {
239 self.unsigned_attributes.as_ref()
240 }
241
242 #[must_use]
245 pub fn signed_fields(&self) -> &'a [u8] {
246 self.signed_fields
247 }
248
249 pub fn countersignatures_in<'s>(
252 &'s self,
253 parent: &'s Reader<'a>,
254 ) -> crate::counter::Countersignatures<'s, 'a> {
255 crate::counter::Countersignatures::new(self, parent)
256 }
257 #[must_use]
259 pub fn encoding(&self) -> Encoding {
260 self.encoding
261 }
262 #[must_use]
264 pub fn span(&self) -> Span {
265 self.element.span()
266 }
267 #[must_use]
273 pub fn element(&self) -> &Element<'a> {
274 &self.element
275 }
276 #[must_use]
278 pub fn as_bytes(&self) -> &'a [u8] {
279 self.element.as_bytes()
280 }
281 #[must_use]
287 pub fn faults(&self) -> &[Error] {
288 &self.faults
289 }
290
291 pub fn same_value(&self, other: &SignerInfo<'_>, parent: &Reader<'_>) -> Result<bool> {
302 if !self.same_fields(other, parent)? {
303 return Ok(false);
304 }
305 let comparison_error = |source| duplicate_comparison_error(source, other.span().start);
308 if !self
313 .digest_algorithm
314 .same_written_in(&other.digest_algorithm, parent)
315 .map_err(comparison_error)?
316 {
317 let (Some(left), Some(right)) = (
318 self.digest_algorithm.identifier(),
319 other.digest_algorithm.identifier(),
320 ) else {
321 return Ok(false);
324 };
325 if !left
326 .digest_matches_in(&right, parent)
327 .map_err(comparison_error)?
328 {
329 return Ok(false);
330 }
331 }
332 self.signature_algorithm
333 .same_written_in(&other.signature_algorithm, parent)
334 .map_err(comparison_error)
335 }
336
337 pub(crate) fn same_fields(&self, other: &SignerInfo<'_>, parent: &Reader<'_>) -> Result<bool> {
341 let field = "signedData.signerInfos";
342 let at = other.span().start;
343 self.require_session(parent, field)?;
344 other.require_session(parent, field)?;
345 parent
346 .execution()
347 .charge_work(1)
348 .map_err(|reason| Error::resource(reason, field, at))?;
349 if self.version != other.version {
350 return Ok(false);
351 }
352 let same_sid = match (&self.sid, &other.sid) {
353 (
354 SignerIdentifier::IssuerAndSerial { issuer, serial },
355 SignerIdentifier::IssuerAndSerial {
356 issuer: right,
357 serial: number,
358 },
359 ) => {
360 issuer
364 .matches_in(right, parent)
365 .map_err(|source| duplicate_comparison_error(source, at))?
366 && same_bytes(parent, serial.as_bytes(), number.as_bytes(), field, at)?
367 }
368 (
369 SignerIdentifier::SubjectKeyIdentifier(left),
370 SignerIdentifier::SubjectKeyIdentifier(right),
371 ) => left.same_value(right, parent, field, at)?,
372 _ => false,
373 };
374 if !same_sid {
375 return Ok(false);
376 }
377 for (left, right) in [
378 (&self.signed_attributes, &other.signed_attributes),
379 (&self.unsigned_attributes, &other.unsigned_attributes),
380 ] {
381 if !same_optional(
382 parent,
383 left.as_ref().map(|attrs| attrs.element().as_bytes()),
384 right.as_ref().map(|attrs| attrs.element().as_bytes()),
385 field,
386 at,
387 )? {
388 return Ok(false);
389 }
390 }
391 self.signature
392 .same_value(&other.signature, parent, field, at)
393 }
394}
395
396fn read_attributes<'a, W: Work>(
397 parent: &Reader<'a>,
398 element: &Element<'a>,
399 placement: Placement,
400 faults: &mut OwnedVec<Error, W>,
401) -> Result<Attributes<'a>> {
402 let reading = Attributes::read_inspection(parent, element, placement)?;
403 if let Some(fault) = reading.fault() {
404 let field = fault.field();
405 let at = fault.offset();
406 faults
407 .try_push(fault)
408 .map_err(|reason| Error::resource(reason, field, at))?;
409 }
410 reading.inspect_registered(parent, faults)?;
411 Ok(reading)
412}
413
414fn read_algorithm<'a, W: Work>(
415 parent: &Reader<'a>,
416 element: &Element<'a>,
417 field: &'static str,
418 faults: &mut OwnedVec<Error, W>,
419) -> Result<AlgorithmReading<'a>> {
420 let reading =
426 structured_pkix::algorithm::read_inspection(parent, element, field).map_err(Error::pkix)?;
427 if let Some(fault) = reading.fault() {
428 faults
429 .try_push(Error::pkix(fault.clone()))
430 .map_err(|reason| Error::resource(reason, fault.field(), fault.offset()))?;
431 }
432 Ok(reading)
433}
434
435fn duplicate_comparison_error(source: structured_pkix::Error, at: u64) -> Error {
436 if source.is_resource() {
437 Error::pkix(structured_pkix::Error::new(
438 source.code(),
439 "signedData.signerInfos",
440 at,
441 ))
442 } else {
443 Error::pkix(source)
444 }
445}
446
447fn field_range<'a>(signer: &Element<'a>, first: &Element<'a>, last: &Element<'a>) -> &'a [u8] {
450 let origin = signer.span().start;
451 let start = first.span().start - origin;
452 let end = last.span().start + last.span().length - origin;
453 let bytes = signer.as_bytes();
454 let start = usize::try_from(start).expect("member offset fits the signer encoding");
456 let end = usize::try_from(end).expect("member end fits the signer encoding");
457 &bytes[start..end]
458}
459
460pub(crate) fn required<'a>(
461 reader: &mut ScopedReader<'a, '_>,
462 field: &'static str,
463) -> Result<Element<'a>> {
464 reader
465 .next_element()
466 .map_err(|error| Error::encoding(error, field))?
467 .ok_or_else(|| Error::schema(ErrorCode::MissingField, field, reader.offset()))
468}
469
470fn same_bytes(
471 parent: &Reader<'_>,
472 left: &[u8],
473 right: &[u8],
474 field: &'static str,
475 at: u64,
476) -> Result<bool> {
477 let execution = parent.execution();
478 execution
479 .charge_work(1)
480 .map_err(|reason| Error::resource(reason, field, at))?;
481 if left.len() != right.len() {
482 return Ok(false);
483 }
484 execution
485 .charge_work(left.len() as u64)
486 .map_err(|reason| Error::resource(reason, field, at))?;
487 Ok(left == right)
488}
489
490fn same_optional(
491 parent: &Reader<'_>,
492 left: Option<&[u8]>,
493 right: Option<&[u8]>,
494 field: &'static str,
495 at: u64,
496) -> Result<bool> {
497 parent
498 .execution()
499 .charge_work(1)
500 .map_err(|reason| Error::resource(reason, field, at))?;
501 match (left, right) {
502 (None, None) => Ok(true),
503 (Some(left), Some(right)) => same_bytes(parent, left, right, field, at),
504 _ => Ok(false),
505 }
506}