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 unsigned_attributes: Option<Attributes<'a>>,
77 encoding: Encoding,
78 element: Element<'a>,
79 faults: OwnedVec<Error>,
80}
81
82impl<'a> SignerInfo<'a> {
83 pub(crate) fn require_session(&self, parent: &Reader<'_>, field: &'static str) -> Result<()> {
84 if !self.digest_algorithm.same_session(parent) {
85 return Err(Error::pkix(structured_pkix::Error::new(
86 structured_pkix::ErrorCode::ForeignReader,
87 field,
88 self.span().start,
89 )));
90 }
91 Ok(())
92 }
93 pub fn read(parent: &Reader<'a>, element: &Element<'a>) -> Result<Self> {
104 const FIELD: &str = "signerInfo";
105 if element.tag() != Tag::constructed(universal::SEQUENCE) {
106 return Err(Error::schema(
107 ErrorCode::UnexpectedTag,
108 FIELD,
109 element.span().start,
110 ));
111 }
112 let mut inside = parent
113 .enter(element)
114 .map_err(|error| Error::encoding(error, FIELD))?;
115 let execution = parent.execution();
116 let mut faults = execution.vector();
117 let version_element = inside
118 .expect(Tag::primitive(universal::INTEGER))
119 .map_err(|error| Error::encoding(error, "signerInfo.version"))?;
120 let version = inside
121 .integer(&version_element)
122 .map_err(|error| Error::encoding(error, "signerInfo.version"))?
123 .as_u64()
124 .ok_or_else(|| {
125 Error::schema(
126 ErrorCode::ValueTooLarge,
127 "signerInfo.version",
128 version_element.span().start,
129 )
130 })?;
131 let named = required(&mut inside, "signerInfo.sid")?;
132 let sid = SignerIdentifier::read(&inside, &named)?;
133 if version != sid.required_version() {
134 faults
135 .try_push(Error::schema(
136 ErrorCode::VersionMismatch,
137 "signerInfo.version",
138 version_element.span().start,
139 ))
140 .map_err(|reason| {
141 Error::resource(reason, "signerInfo.version", version_element.span().start)
142 })?;
143 }
144 let digest = required(&mut inside, "signerInfo.digestAlgorithm")?;
145 let digest_algorithm =
146 read_algorithm(&inside, &digest, "signerInfo.digestAlgorithm", &mut faults)?;
147 let mut next = required(&mut inside, "signerInfo.signatureAlgorithm")?;
148 let signed_attributes = if next.tag() == Tag::context(true, 0) {
149 let attributes = read_attributes(&inside, &next, Placement::Signed, &mut faults)?;
150 next = required(&mut inside, "signerInfo.signatureAlgorithm")?;
151 Some(attributes)
152 } else {
153 None
154 };
155 let signature_algorithm =
156 read_algorithm(&inside, &next, "signerInfo.signatureAlgorithm", &mut faults)?;
157 let signature_element = required(&mut inside, "signerInfo.signature")?;
158 let signature = Octets::read(&inside, &signature_element, "signerInfo.signature")?;
159 let unsigned_attributes = match inside
160 .next_element()
161 .map_err(|error| Error::encoding(error, "signerInfo.unsignedAttrs"))?
162 {
163 Some(attributes) => Some(read_attributes(
164 &inside,
165 &attributes,
166 Placement::Unsigned,
167 &mut faults,
168 )?),
169 None => None,
170 };
171 if !inside.is_empty() {
172 return Err(Error::schema(
173 ErrorCode::TrailingData,
174 FIELD,
175 inside.offset(),
176 ));
177 }
178 Ok(Self {
179 version,
180 sid,
181 digest_algorithm,
182 signed_attributes,
183 signature_algorithm,
184 signature,
185 unsigned_attributes,
186 encoding: inside.encoding(),
187 element: *element,
188 faults: faults.into_owned(),
189 })
190 }
191
192 #[must_use]
194 pub fn version(&self) -> u64 {
195 self.version
196 }
197 #[must_use]
199 pub fn sid(&self) -> &SignerIdentifier<'a> {
200 &self.sid
201 }
202 #[must_use]
205 pub fn digest_algorithm(&self) -> &AlgorithmReading<'a> {
206 &self.digest_algorithm
207 }
208 #[must_use]
210 pub fn signed_attributes(&self) -> Option<&Attributes<'a>> {
211 self.signed_attributes.as_ref()
212 }
213 #[must_use]
216 pub fn signature_algorithm(&self) -> &AlgorithmReading<'a> {
217 &self.signature_algorithm
218 }
219 #[must_use]
221 pub fn signature(&self) -> &Octets<'a> {
222 &self.signature
223 }
224 #[must_use]
226 pub fn unsigned_attributes(&self) -> Option<&Attributes<'a>> {
227 self.unsigned_attributes.as_ref()
228 }
229
230 pub fn countersignatures_in<'s>(
233 &'s self,
234 parent: &'s Reader<'a>,
235 ) -> crate::counter::Countersignatures<'s, 'a> {
236 crate::counter::Countersignatures::new(self, parent)
237 }
238 #[must_use]
240 pub fn encoding(&self) -> Encoding {
241 self.encoding
242 }
243 #[must_use]
245 pub fn span(&self) -> Span {
246 self.element.span()
247 }
248 #[must_use]
254 pub fn element(&self) -> &Element<'a> {
255 &self.element
256 }
257 #[must_use]
259 pub fn as_bytes(&self) -> &'a [u8] {
260 self.element.as_bytes()
261 }
262 #[must_use]
268 pub fn faults(&self) -> &[Error] {
269 &self.faults
270 }
271
272 pub fn same_value(&self, other: &SignerInfo<'_>, parent: &Reader<'_>) -> Result<bool> {
283 if !self.same_fields(other, parent)? {
284 return Ok(false);
285 }
286 let comparison_error = |source| duplicate_comparison_error(source, other.span().start);
289 if !self
294 .digest_algorithm
295 .same_written_in(&other.digest_algorithm, parent)
296 .map_err(comparison_error)?
297 {
298 let (Some(left), Some(right)) = (
299 self.digest_algorithm.identifier(),
300 other.digest_algorithm.identifier(),
301 ) else {
302 return Ok(false);
305 };
306 if !left
307 .digest_matches_in(&right, parent)
308 .map_err(comparison_error)?
309 {
310 return Ok(false);
311 }
312 }
313 self.signature_algorithm
314 .same_written_in(&other.signature_algorithm, parent)
315 .map_err(comparison_error)
316 }
317
318 pub(crate) fn same_fields(&self, other: &SignerInfo<'_>, parent: &Reader<'_>) -> Result<bool> {
322 let field = "signedData.signerInfos";
323 let at = other.span().start;
324 self.require_session(parent, field)?;
325 other.require_session(parent, field)?;
326 parent
327 .execution()
328 .charge_work(1)
329 .map_err(|reason| Error::resource(reason, field, at))?;
330 if self.version != other.version {
331 return Ok(false);
332 }
333 let same_sid = match (&self.sid, &other.sid) {
334 (
335 SignerIdentifier::IssuerAndSerial { issuer, serial },
336 SignerIdentifier::IssuerAndSerial {
337 issuer: right,
338 serial: number,
339 },
340 ) => {
341 issuer
345 .matches_in(right, parent)
346 .map_err(|source| duplicate_comparison_error(source, at))?
347 && same_bytes(parent, serial.as_bytes(), number.as_bytes(), field, at)?
348 }
349 (
350 SignerIdentifier::SubjectKeyIdentifier(left),
351 SignerIdentifier::SubjectKeyIdentifier(right),
352 ) => left.same_value(right, parent, field, at)?,
353 _ => false,
354 };
355 if !same_sid {
356 return Ok(false);
357 }
358 for (left, right) in [
359 (&self.signed_attributes, &other.signed_attributes),
360 (&self.unsigned_attributes, &other.unsigned_attributes),
361 ] {
362 if !same_optional(
363 parent,
364 left.as_ref().map(|attrs| attrs.element().as_bytes()),
365 right.as_ref().map(|attrs| attrs.element().as_bytes()),
366 field,
367 at,
368 )? {
369 return Ok(false);
370 }
371 }
372 self.signature
373 .same_value(&other.signature, parent, field, at)
374 }
375}
376
377fn read_attributes<'a, W: Work>(
378 parent: &Reader<'a>,
379 element: &Element<'a>,
380 placement: Placement,
381 faults: &mut OwnedVec<Error, W>,
382) -> Result<Attributes<'a>> {
383 let reading = Attributes::read_inspection(parent, element, placement)?;
384 if let Some(fault) = reading.fault() {
385 let field = fault.field();
386 let at = fault.offset();
387 faults
388 .try_push(fault)
389 .map_err(|reason| Error::resource(reason, field, at))?;
390 }
391 reading.inspect_registered(parent, faults)?;
392 Ok(reading)
393}
394
395fn read_algorithm<'a, W: Work>(
396 parent: &Reader<'a>,
397 element: &Element<'a>,
398 field: &'static str,
399 faults: &mut OwnedVec<Error, W>,
400) -> Result<AlgorithmReading<'a>> {
401 let reading =
407 structured_pkix::algorithm::read_inspection(parent, element, field).map_err(Error::pkix)?;
408 if let Some(fault) = reading.fault() {
409 faults
410 .try_push(Error::pkix(fault.clone()))
411 .map_err(|reason| Error::resource(reason, fault.field(), fault.offset()))?;
412 }
413 Ok(reading)
414}
415
416fn duplicate_comparison_error(source: structured_pkix::Error, at: u64) -> Error {
417 if source.is_resource() {
418 Error::pkix(structured_pkix::Error::new(
419 source.code(),
420 "signedData.signerInfos",
421 at,
422 ))
423 } else {
424 Error::pkix(source)
425 }
426}
427
428pub(crate) fn required<'a>(reader: &mut Reader<'a>, field: &'static str) -> Result<Element<'a>> {
429 reader
430 .next_element()
431 .map_err(|error| Error::encoding(error, field))?
432 .ok_or_else(|| Error::schema(ErrorCode::MissingField, field, reader.offset()))
433}
434
435fn same_bytes(
436 parent: &Reader<'_>,
437 left: &[u8],
438 right: &[u8],
439 field: &'static str,
440 at: u64,
441) -> Result<bool> {
442 let execution = parent.execution();
443 execution
444 .charge_work(1)
445 .map_err(|reason| Error::resource(reason, field, at))?;
446 if left.len() != right.len() {
447 return Ok(false);
448 }
449 execution
450 .charge_work(left.len() as u64)
451 .map_err(|reason| Error::resource(reason, field, at))?;
452 Ok(left == right)
453}
454
455fn same_optional(
456 parent: &Reader<'_>,
457 left: Option<&[u8]>,
458 right: Option<&[u8]>,
459 field: &'static str,
460 at: u64,
461) -> Result<bool> {
462 parent
463 .execution()
464 .charge_work(1)
465 .map_err(|reason| Error::resource(reason, field, at))?;
466 match (left, right) {
467 (None, None) => Ok(true),
468 (Some(left), Some(right)) => same_bytes(parent, left, right, field, at),
469 _ => Ok(false),
470 }
471}