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::{AlgorithmIdentifier, Name};
8
9#[derive(Debug)]
11pub enum SignerIdentifier<'a> {
12 IssuerAndSerial {
14 issuer: Name<'a>,
16 serial: Integer<'a>,
18 },
19 SubjectKeyIdentifier(Octets<'a>),
21}
22
23impl<'a> SignerIdentifier<'a> {
24 fn read(parent: &Reader<'a>, element: &Element<'a>) -> Result<Self> {
25 const FIELD: &str = "signerInfo.sid";
26 if element.tag() == Tag::context(false, 0) || element.tag() == Tag::context(true, 0) {
27 return Octets::read_identifier(parent, element, FIELD).map(Self::SubjectKeyIdentifier);
28 }
29 if element.tag() != Tag::constructed(universal::SEQUENCE) {
30 return Err(Error::schema(
31 ErrorCode::UnexpectedTag,
32 FIELD,
33 element.span().start,
34 ));
35 }
36 let mut inside = parent
37 .enter(element)
38 .map_err(|error| Error::encoding(error, FIELD))?;
39 let name = inside
40 .expect(Tag::constructed(universal::SEQUENCE))
41 .map_err(|error| Error::encoding(error, FIELD))?;
42 let issuer = structured_pkix::name::read(&inside, &name, FIELD).map_err(Error::pkix)?;
43 let serial = inside
44 .read_integer()
45 .map_err(|error| Error::encoding(error, FIELD))?;
46 if !inside.is_empty() {
47 return Err(Error::schema(
48 ErrorCode::TrailingData,
49 FIELD,
50 inside.offset(),
51 ));
52 }
53 Ok(Self::IssuerAndSerial { issuer, serial })
54 }
55
56 #[must_use]
58 pub fn required_version(&self) -> u64 {
59 match self {
60 Self::IssuerAndSerial { .. } => 1,
61 Self::SubjectKeyIdentifier(_) => 3,
62 }
63 }
64}
65
66#[derive(Debug)]
68pub struct SignerInfo<'a> {
69 version: u64,
70 sid: SignerIdentifier<'a>,
71 digest_algorithm: AlgorithmIdentifier<'a>,
72 signed_attributes: Option<Attributes<'a>>,
73 signature_algorithm: AlgorithmIdentifier<'a>,
74 signature: Octets<'a>,
75 unsigned_attributes: Option<Attributes<'a>>,
76 encoding: Encoding,
77 element: Element<'a>,
78 faults: OwnedVec<Error>,
79}
80
81impl<'a> SignerInfo<'a> {
82 pub(crate) fn require_session(&self, parent: &Reader<'_>, field: &'static str) -> Result<()> {
83 if !self.digest_algorithm.same_session(parent) {
84 return Err(Error::pkix(structured_pkix::Error::new(
85 structured_pkix::ErrorCode::ForeignReader,
86 field,
87 self.span().start,
88 )));
89 }
90 Ok(())
91 }
92 pub fn read(parent: &Reader<'a>, element: &Element<'a>) -> Result<Self> {
99 const FIELD: &str = "signerInfo";
100 if element.tag() != Tag::constructed(universal::SEQUENCE) {
101 return Err(Error::schema(
102 ErrorCode::UnexpectedTag,
103 FIELD,
104 element.span().start,
105 ));
106 }
107 let mut inside = parent
108 .enter(element)
109 .map_err(|error| Error::encoding(error, FIELD))?;
110 let execution = parent.execution();
111 let mut faults = execution.vector();
112 let version_element = inside
113 .expect(Tag::primitive(universal::INTEGER))
114 .map_err(|error| Error::encoding(error, "signerInfo.version"))?;
115 let version = inside
116 .integer(&version_element)
117 .map_err(|error| Error::encoding(error, "signerInfo.version"))?
118 .as_u64()
119 .ok_or_else(|| {
120 Error::schema(
121 ErrorCode::ValueTooLarge,
122 "signerInfo.version",
123 version_element.span().start,
124 )
125 })?;
126 let named = required(&mut inside, "signerInfo.sid")?;
127 let sid = SignerIdentifier::read(&inside, &named)?;
128 if version != sid.required_version() {
129 faults
130 .try_push(Error::schema(
131 ErrorCode::VersionMismatch,
132 "signerInfo.version",
133 version_element.span().start,
134 ))
135 .map_err(|reason| {
136 Error::resource(reason, "signerInfo.version", version_element.span().start)
137 })?;
138 }
139 let digest = required(&mut inside, "signerInfo.digestAlgorithm")?;
140 let digest_algorithm =
141 structured_pkix::algorithm::read(&inside, &digest, "signerInfo.digestAlgorithm")
142 .map_err(Error::pkix)?;
143 let mut next = required(&mut inside, "signerInfo.signatureAlgorithm")?;
144 let signed_attributes = if next.tag() == Tag::context(true, 0) {
145 let attributes = Attributes::read(&inside, &next, Placement::Signed)?;
146 next = required(&mut inside, "signerInfo.signatureAlgorithm")?;
147 Some(attributes)
148 } else {
149 None
150 };
151 let signature_algorithm =
152 structured_pkix::algorithm::read(&inside, &next, "signerInfo.signatureAlgorithm")
153 .map_err(Error::pkix)?;
154 let signature_element = required(&mut inside, "signerInfo.signature")?;
155 let signature = Octets::read(&inside, &signature_element, "signerInfo.signature")?;
156 let unsigned_attributes = match inside
157 .next_element()
158 .map_err(|error| Error::encoding(error, "signerInfo.unsignedAttrs"))?
159 {
160 Some(attributes) => Some(Attributes::read(&inside, &attributes, Placement::Unsigned)?),
161 None => None,
162 };
163 if !inside.is_empty() {
164 return Err(Error::schema(
165 ErrorCode::TrailingData,
166 FIELD,
167 inside.offset(),
168 ));
169 }
170 Ok(Self {
171 version,
172 sid,
173 digest_algorithm,
174 signed_attributes,
175 signature_algorithm,
176 signature,
177 unsigned_attributes,
178 encoding: inside.encoding(),
179 element: *element,
180 faults: faults.into_owned(),
181 })
182 }
183
184 #[must_use]
186 pub fn version(&self) -> u64 {
187 self.version
188 }
189 #[must_use]
191 pub fn sid(&self) -> &SignerIdentifier<'a> {
192 &self.sid
193 }
194 #[must_use]
196 pub fn digest_algorithm(&self) -> AlgorithmIdentifier<'a> {
197 self.digest_algorithm
198 }
199 #[must_use]
201 pub fn signed_attributes(&self) -> Option<&Attributes<'a>> {
202 self.signed_attributes.as_ref()
203 }
204 #[must_use]
206 pub fn signature_algorithm(&self) -> AlgorithmIdentifier<'a> {
207 self.signature_algorithm
208 }
209 #[must_use]
211 pub fn signature(&self) -> &Octets<'a> {
212 &self.signature
213 }
214 #[must_use]
216 pub fn unsigned_attributes(&self) -> Option<&Attributes<'a>> {
217 self.unsigned_attributes.as_ref()
218 }
219
220 pub fn countersignatures_in<'s>(
223 &'s self,
224 parent: &'s Reader<'a>,
225 ) -> crate::counter::Countersignatures<'s, 'a> {
226 crate::counter::Countersignatures::new(self, parent)
227 }
228 #[must_use]
230 pub fn encoding(&self) -> Encoding {
231 self.encoding
232 }
233 #[must_use]
235 pub fn span(&self) -> Span {
236 self.element.span()
237 }
238 #[must_use]
240 pub fn as_bytes(&self) -> &'a [u8] {
241 self.element.as_bytes()
242 }
243 #[must_use]
245 pub fn faults(&self) -> &[Error] {
246 &self.faults
247 }
248
249 pub fn same_value(&self, other: &SignerInfo<'_>, parent: &Reader<'_>) -> Result<bool> {
260 if !self.same_fields(other, parent)? {
261 return Ok(false);
262 }
263 let comparison_error = |source| duplicate_comparison_error(source, other.span().start);
266 if !self
271 .digest_algorithm
272 .same_written_in(&other.digest_algorithm, parent)
273 .map_err(comparison_error)?
274 && !self
275 .digest_algorithm
276 .digest_matches_in(&other.digest_algorithm, parent)
277 .map_err(comparison_error)?
278 {
279 return Ok(false);
280 }
281 self.signature_algorithm
282 .same_written_in(&other.signature_algorithm, parent)
283 .map_err(comparison_error)
284 }
285
286 pub(crate) fn same_fields(&self, other: &SignerInfo<'_>, parent: &Reader<'_>) -> Result<bool> {
290 let field = "signedData.signerInfos";
291 let at = other.span().start;
292 self.require_session(parent, field)?;
293 other.require_session(parent, field)?;
294 parent
295 .execution()
296 .charge_work(1)
297 .map_err(|reason| Error::resource(reason, field, at))?;
298 if self.version != other.version {
299 return Ok(false);
300 }
301 let same_sid = match (&self.sid, &other.sid) {
302 (
303 SignerIdentifier::IssuerAndSerial { issuer, serial },
304 SignerIdentifier::IssuerAndSerial {
305 issuer: right,
306 serial: number,
307 },
308 ) => {
309 issuer
313 .matches_in(right, parent)
314 .map_err(|source| duplicate_comparison_error(source, at))?
315 && same_bytes(parent, serial.as_bytes(), number.as_bytes(), field, at)?
316 }
317 (
318 SignerIdentifier::SubjectKeyIdentifier(left),
319 SignerIdentifier::SubjectKeyIdentifier(right),
320 ) => left.same_value(right, parent, field, at)?,
321 _ => false,
322 };
323 if !same_sid {
324 return Ok(false);
325 }
326 for (left, right) in [
327 (&self.signed_attributes, &other.signed_attributes),
328 (&self.unsigned_attributes, &other.unsigned_attributes),
329 ] {
330 if !same_optional(
331 parent,
332 left.as_ref().map(|attrs| attrs.element().as_bytes()),
333 right.as_ref().map(|attrs| attrs.element().as_bytes()),
334 field,
335 at,
336 )? {
337 return Ok(false);
338 }
339 }
340 self.signature
341 .same_value(&other.signature, parent, field, at)
342 }
343}
344
345fn duplicate_comparison_error(source: structured_pkix::Error, at: u64) -> Error {
346 if source.is_resource() {
347 Error::pkix(structured_pkix::Error::new(
348 source.code(),
349 "signedData.signerInfos",
350 at,
351 ))
352 } else {
353 Error::pkix(source)
354 }
355}
356
357pub(crate) fn required<'a>(reader: &mut Reader<'a>, field: &'static str) -> Result<Element<'a>> {
358 reader
359 .next_element()
360 .map_err(|error| Error::encoding(error, field))?
361 .ok_or_else(|| Error::schema(ErrorCode::MissingField, field, reader.offset()))
362}
363
364fn same_bytes(
365 parent: &Reader<'_>,
366 left: &[u8],
367 right: &[u8],
368 field: &'static str,
369 at: u64,
370) -> Result<bool> {
371 let execution = parent.execution();
372 execution
373 .charge_work(1)
374 .map_err(|reason| Error::resource(reason, field, at))?;
375 if left.len() != right.len() {
376 return Ok(false);
377 }
378 execution
379 .charge_work(left.len() as u64)
380 .map_err(|reason| Error::resource(reason, field, at))?;
381 Ok(left == right)
382}
383
384fn same_optional(
385 parent: &Reader<'_>,
386 left: Option<&[u8]>,
387 right: Option<&[u8]>,
388 field: &'static str,
389 at: u64,
390) -> Result<bool> {
391 parent
392 .execution()
393 .charge_work(1)
394 .map_err(|reason| Error::resource(reason, field, at))?;
395 match (left, right) {
396 (None, None) => Ok(true),
397 (Some(left), Some(right)) => same_bytes(parent, left, right, field, at),
398 _ => Ok(false),
399 }
400}