1use crate::attribute::{Attributes, Placement};
4use crate::{Error, ErrorCode, Octets, Result};
5use structured_asn1::memory::{OwnedVec, Work};
6use structured_asn1::{Element, Encoding, Integer, Reader, 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(crate) fn require_session(&self, parent: &Reader<'_>, field: &'static str) -> Result<()> {
85 if !self.digest_algorithm.same_session(parent) {
86 return Err(Error::pkix(structured_pkix::Error::new(
87 structured_pkix::ErrorCode::ForeignReader,
88 field,
89 self.span().start,
90 )));
91 }
92 Ok(())
93 }
94 pub fn read(parent: &Reader<'a>, element: &Element<'a>) -> Result<Self> {
105 const FIELD: &str = "signerInfo";
106 if element.tag() != Tag::constructed(universal::SEQUENCE) {
107 return Err(Error::schema(
108 ErrorCode::UnexpectedTag,
109 FIELD,
110 element.span().start,
111 ));
112 }
113 let mut inside = parent
114 .enter(element)
115 .map_err(|error| Error::encoding(error, FIELD))?;
116 let execution = parent.execution();
117 let mut faults = execution.vector();
118 let version_element = inside
119 .expect(Tag::primitive(universal::INTEGER))
120 .map_err(|error| Error::encoding(error, "signerInfo.version"))?;
121 let version = inside
122 .integer(&version_element)
123 .map_err(|error| Error::encoding(error, "signerInfo.version"))?
124 .as_u64()
125 .ok_or_else(|| {
126 Error::schema(
127 ErrorCode::ValueTooLarge,
128 "signerInfo.version",
129 version_element.span().start,
130 )
131 })?;
132 let named = required(&mut inside, "signerInfo.sid")?;
133 let sid = SignerIdentifier::read(&inside, &named)?;
134 if version != sid.required_version() {
135 faults
136 .try_push(Error::schema(
137 ErrorCode::VersionMismatch,
138 "signerInfo.version",
139 version_element.span().start,
140 ))
141 .map_err(|reason| {
142 Error::resource(reason, "signerInfo.version", version_element.span().start)
143 })?;
144 }
145 let digest = required(&mut inside, "signerInfo.digestAlgorithm")?;
146 let digest_algorithm =
147 read_algorithm(&inside, &digest, "signerInfo.digestAlgorithm", &mut faults)?;
148 let mut next = required(&mut inside, "signerInfo.signatureAlgorithm")?;
149 let signed_attributes = if next.tag() == Tag::context(true, 0) {
150 let attributes = read_attributes(&inside, &next, Placement::Signed, &mut faults)?;
151 next = required(&mut inside, "signerInfo.signatureAlgorithm")?;
152 Some(attributes)
153 } else {
154 None
155 };
156 let signature_algorithm =
157 read_algorithm(&inside, &next, "signerInfo.signatureAlgorithm", &mut faults)?;
158 let signature_element = required(&mut inside, "signerInfo.signature")?;
159 let signature = Octets::read(&inside, &signature_element, "signerInfo.signature")?;
160 let signed_fields = field_range(element, &version_element, &signature_element);
161 let unsigned_attributes = match inside
162 .next_element()
163 .map_err(|error| Error::encoding(error, "signerInfo.unsignedAttrs"))?
164 {
165 Some(attributes) => Some(read_attributes(
166 &inside,
167 &attributes,
168 Placement::Unsigned,
169 &mut faults,
170 )?),
171 None => None,
172 };
173 if !inside.is_empty() {
174 return Err(Error::schema(
175 ErrorCode::TrailingData,
176 FIELD,
177 inside.offset(),
178 ));
179 }
180 Ok(Self {
181 version,
182 sid,
183 digest_algorithm,
184 signed_attributes,
185 signature_algorithm,
186 signature,
187 signed_fields,
188 unsigned_attributes,
189 encoding: inside.encoding(),
190 element: *element,
191 faults: faults.into_owned(),
192 })
193 }
194
195 #[must_use]
197 pub fn version(&self) -> u64 {
198 self.version
199 }
200 #[must_use]
202 pub fn sid(&self) -> &SignerIdentifier<'a> {
203 &self.sid
204 }
205 #[must_use]
208 pub fn digest_algorithm(&self) -> &AlgorithmReading<'a> {
209 &self.digest_algorithm
210 }
211 #[must_use]
213 pub fn signed_attributes(&self) -> Option<&Attributes<'a>> {
214 self.signed_attributes.as_ref()
215 }
216 #[must_use]
219 pub fn signature_algorithm(&self) -> &AlgorithmReading<'a> {
220 &self.signature_algorithm
221 }
222 #[must_use]
224 pub fn signature(&self) -> &Octets<'a> {
225 &self.signature
226 }
227 #[must_use]
229 pub fn unsigned_attributes(&self) -> Option<&Attributes<'a>> {
230 self.unsigned_attributes.as_ref()
231 }
232
233 #[must_use]
236 pub fn signed_fields(&self) -> &'a [u8] {
237 self.signed_fields
238 }
239
240 pub fn countersignatures_in<'s>(
243 &'s self,
244 parent: &'s Reader<'a>,
245 ) -> crate::counter::Countersignatures<'s, 'a> {
246 crate::counter::Countersignatures::new(self, parent)
247 }
248 #[must_use]
250 pub fn encoding(&self) -> Encoding {
251 self.encoding
252 }
253 #[must_use]
255 pub fn span(&self) -> Span {
256 self.element.span()
257 }
258 #[must_use]
264 pub fn element(&self) -> &Element<'a> {
265 &self.element
266 }
267 #[must_use]
269 pub fn as_bytes(&self) -> &'a [u8] {
270 self.element.as_bytes()
271 }
272 #[must_use]
278 pub fn faults(&self) -> &[Error] {
279 &self.faults
280 }
281
282 pub fn same_value(&self, other: &SignerInfo<'_>, parent: &Reader<'_>) -> Result<bool> {
293 if !self.same_fields(other, parent)? {
294 return Ok(false);
295 }
296 let comparison_error = |source| duplicate_comparison_error(source, other.span().start);
299 if !self
304 .digest_algorithm
305 .same_written_in(&other.digest_algorithm, parent)
306 .map_err(comparison_error)?
307 {
308 let (Some(left), Some(right)) = (
309 self.digest_algorithm.identifier(),
310 other.digest_algorithm.identifier(),
311 ) else {
312 return Ok(false);
315 };
316 if !left
317 .digest_matches_in(&right, parent)
318 .map_err(comparison_error)?
319 {
320 return Ok(false);
321 }
322 }
323 self.signature_algorithm
324 .same_written_in(&other.signature_algorithm, parent)
325 .map_err(comparison_error)
326 }
327
328 pub(crate) fn same_fields(&self, other: &SignerInfo<'_>, parent: &Reader<'_>) -> Result<bool> {
332 let field = "signedData.signerInfos";
333 let at = other.span().start;
334 self.require_session(parent, field)?;
335 other.require_session(parent, field)?;
336 parent
337 .execution()
338 .charge_work(1)
339 .map_err(|reason| Error::resource(reason, field, at))?;
340 if self.version != other.version {
341 return Ok(false);
342 }
343 let same_sid = match (&self.sid, &other.sid) {
344 (
345 SignerIdentifier::IssuerAndSerial { issuer, serial },
346 SignerIdentifier::IssuerAndSerial {
347 issuer: right,
348 serial: number,
349 },
350 ) => {
351 issuer
355 .matches_in(right, parent)
356 .map_err(|source| duplicate_comparison_error(source, at))?
357 && same_bytes(parent, serial.as_bytes(), number.as_bytes(), field, at)?
358 }
359 (
360 SignerIdentifier::SubjectKeyIdentifier(left),
361 SignerIdentifier::SubjectKeyIdentifier(right),
362 ) => left.same_value(right, parent, field, at)?,
363 _ => false,
364 };
365 if !same_sid {
366 return Ok(false);
367 }
368 for (left, right) in [
369 (&self.signed_attributes, &other.signed_attributes),
370 (&self.unsigned_attributes, &other.unsigned_attributes),
371 ] {
372 if !same_optional(
373 parent,
374 left.as_ref().map(|attrs| attrs.element().as_bytes()),
375 right.as_ref().map(|attrs| attrs.element().as_bytes()),
376 field,
377 at,
378 )? {
379 return Ok(false);
380 }
381 }
382 self.signature
383 .same_value(&other.signature, parent, field, at)
384 }
385}
386
387fn read_attributes<'a, W: Work>(
388 parent: &Reader<'a>,
389 element: &Element<'a>,
390 placement: Placement,
391 faults: &mut OwnedVec<Error, W>,
392) -> Result<Attributes<'a>> {
393 let reading = Attributes::read_inspection(parent, element, placement)?;
394 if let Some(fault) = reading.fault() {
395 let field = fault.field();
396 let at = fault.offset();
397 faults
398 .try_push(fault)
399 .map_err(|reason| Error::resource(reason, field, at))?;
400 }
401 reading.inspect_registered(parent, faults)?;
402 Ok(reading)
403}
404
405fn read_algorithm<'a, W: Work>(
406 parent: &Reader<'a>,
407 element: &Element<'a>,
408 field: &'static str,
409 faults: &mut OwnedVec<Error, W>,
410) -> Result<AlgorithmReading<'a>> {
411 let reading =
417 structured_pkix::algorithm::read_inspection(parent, element, field).map_err(Error::pkix)?;
418 if let Some(fault) = reading.fault() {
419 faults
420 .try_push(Error::pkix(fault.clone()))
421 .map_err(|reason| Error::resource(reason, fault.field(), fault.offset()))?;
422 }
423 Ok(reading)
424}
425
426fn duplicate_comparison_error(source: structured_pkix::Error, at: u64) -> Error {
427 if source.is_resource() {
428 Error::pkix(structured_pkix::Error::new(
429 source.code(),
430 "signedData.signerInfos",
431 at,
432 ))
433 } else {
434 Error::pkix(source)
435 }
436}
437
438fn field_range<'a>(signer: &Element<'a>, first: &Element<'a>, last: &Element<'a>) -> &'a [u8] {
441 let origin = signer.span().start;
442 let start = first.span().start - origin;
443 let end = last.span().start + last.span().length - origin;
444 let bytes = signer.as_bytes();
445 let start = usize::try_from(start).expect("member offset fits the signer encoding");
447 let end = usize::try_from(end).expect("member end fits the signer encoding");
448 &bytes[start..end]
449}
450
451pub(crate) fn required<'a>(reader: &mut Reader<'a>, field: &'static str) -> Result<Element<'a>> {
452 reader
453 .next_element()
454 .map_err(|error| Error::encoding(error, field))?
455 .ok_or_else(|| Error::schema(ErrorCode::MissingField, field, reader.offset()))
456}
457
458fn same_bytes(
459 parent: &Reader<'_>,
460 left: &[u8],
461 right: &[u8],
462 field: &'static str,
463 at: u64,
464) -> Result<bool> {
465 let execution = parent.execution();
466 execution
467 .charge_work(1)
468 .map_err(|reason| Error::resource(reason, field, at))?;
469 if left.len() != right.len() {
470 return Ok(false);
471 }
472 execution
473 .charge_work(left.len() as u64)
474 .map_err(|reason| Error::resource(reason, field, at))?;
475 Ok(left == right)
476}
477
478fn same_optional(
479 parent: &Reader<'_>,
480 left: Option<&[u8]>,
481 right: Option<&[u8]>,
482 field: &'static str,
483 at: u64,
484) -> Result<bool> {
485 parent
486 .execution()
487 .charge_work(1)
488 .map_err(|reason| Error::resource(reason, field, at))?;
489 match (left, right) {
490 (None, None) => Ok(true),
491 (Some(left), Some(right)) => same_bytes(parent, left, right, field, at),
492 _ => Ok(false),
493 }
494}