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]
250 pub fn as_bytes(&self) -> &'a [u8] {
251 self.element.as_bytes()
252 }
253 #[must_use]
255 pub fn faults(&self) -> &[Error] {
256 &self.faults
257 }
258
259 pub fn same_value(&self, other: &SignerInfo<'_>, parent: &Reader<'_>) -> Result<bool> {
270 if !self.same_fields(other, parent)? {
271 return Ok(false);
272 }
273 let comparison_error = |source| duplicate_comparison_error(source, other.span().start);
276 if !self
281 .digest_algorithm
282 .same_written_in(&other.digest_algorithm, parent)
283 .map_err(comparison_error)?
284 {
285 let (Some(left), Some(right)) = (
286 self.digest_algorithm.identifier(),
287 other.digest_algorithm.identifier(),
288 ) else {
289 return Ok(false);
292 };
293 if !left
294 .digest_matches_in(&right, parent)
295 .map_err(comparison_error)?
296 {
297 return Ok(false);
298 }
299 }
300 self.signature_algorithm
301 .same_written_in(&other.signature_algorithm, parent)
302 .map_err(comparison_error)
303 }
304
305 pub(crate) fn same_fields(&self, other: &SignerInfo<'_>, parent: &Reader<'_>) -> Result<bool> {
309 let field = "signedData.signerInfos";
310 let at = other.span().start;
311 self.require_session(parent, field)?;
312 other.require_session(parent, field)?;
313 parent
314 .execution()
315 .charge_work(1)
316 .map_err(|reason| Error::resource(reason, field, at))?;
317 if self.version != other.version {
318 return Ok(false);
319 }
320 let same_sid = match (&self.sid, &other.sid) {
321 (
322 SignerIdentifier::IssuerAndSerial { issuer, serial },
323 SignerIdentifier::IssuerAndSerial {
324 issuer: right,
325 serial: number,
326 },
327 ) => {
328 issuer
332 .matches_in(right, parent)
333 .map_err(|source| duplicate_comparison_error(source, at))?
334 && same_bytes(parent, serial.as_bytes(), number.as_bytes(), field, at)?
335 }
336 (
337 SignerIdentifier::SubjectKeyIdentifier(left),
338 SignerIdentifier::SubjectKeyIdentifier(right),
339 ) => left.same_value(right, parent, field, at)?,
340 _ => false,
341 };
342 if !same_sid {
343 return Ok(false);
344 }
345 for (left, right) in [
346 (&self.signed_attributes, &other.signed_attributes),
347 (&self.unsigned_attributes, &other.unsigned_attributes),
348 ] {
349 if !same_optional(
350 parent,
351 left.as_ref().map(|attrs| attrs.element().as_bytes()),
352 right.as_ref().map(|attrs| attrs.element().as_bytes()),
353 field,
354 at,
355 )? {
356 return Ok(false);
357 }
358 }
359 self.signature
360 .same_value(&other.signature, parent, field, at)
361 }
362}
363
364fn read_attributes<'a, W: Work>(
365 parent: &Reader<'a>,
366 element: &Element<'a>,
367 placement: Placement,
368 faults: &mut OwnedVec<Error, W>,
369) -> Result<Attributes<'a>> {
370 let reading = Attributes::read_inspection(parent, element, placement)?;
371 if let Some(fault) = reading.fault() {
372 let field = fault.field();
373 let at = fault.offset();
374 faults
375 .try_push(fault)
376 .map_err(|reason| Error::resource(reason, field, at))?;
377 }
378 Ok(reading)
379}
380
381fn read_algorithm<'a, W: Work>(
382 parent: &Reader<'a>,
383 element: &Element<'a>,
384 field: &'static str,
385 faults: &mut OwnedVec<Error, W>,
386) -> Result<AlgorithmReading<'a>> {
387 let reading =
393 structured_pkix::algorithm::read_inspection(parent, element, field).map_err(Error::pkix)?;
394 if let Some(fault) = reading.fault() {
395 faults
396 .try_push(Error::pkix(fault.clone()))
397 .map_err(|reason| Error::resource(reason, fault.field(), fault.offset()))?;
398 }
399 Ok(reading)
400}
401
402fn duplicate_comparison_error(source: structured_pkix::Error, at: u64) -> Error {
403 if source.is_resource() {
404 Error::pkix(structured_pkix::Error::new(
405 source.code(),
406 "signedData.signerInfos",
407 at,
408 ))
409 } else {
410 Error::pkix(source)
411 }
412}
413
414pub(crate) fn required<'a>(reader: &mut Reader<'a>, field: &'static str) -> Result<Element<'a>> {
415 reader
416 .next_element()
417 .map_err(|error| Error::encoding(error, field))?
418 .ok_or_else(|| Error::schema(ErrorCode::MissingField, field, reader.offset()))
419}
420
421fn same_bytes(
422 parent: &Reader<'_>,
423 left: &[u8],
424 right: &[u8],
425 field: &'static str,
426 at: u64,
427) -> Result<bool> {
428 let execution = parent.execution();
429 execution
430 .charge_work(1)
431 .map_err(|reason| Error::resource(reason, field, at))?;
432 if left.len() != right.len() {
433 return Ok(false);
434 }
435 execution
436 .charge_work(left.len() as u64)
437 .map_err(|reason| Error::resource(reason, field, at))?;
438 Ok(left == right)
439}
440
441fn same_optional(
442 parent: &Reader<'_>,
443 left: Option<&[u8]>,
444 right: Option<&[u8]>,
445 field: &'static str,
446 at: u64,
447) -> Result<bool> {
448 parent
449 .execution()
450 .charge_work(1)
451 .map_err(|reason| Error::resource(reason, field, at))?;
452 match (left, right) {
453 (None, None) => Ok(true),
454 (Some(left), Some(right)) => same_bytes(parent, left, right, field, at),
455 _ => Ok(false),
456 }
457}