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> {
259 if !self.same_fields(other, parent)? {
260 return Ok(false);
261 }
262 let comparison_error = |source: structured_pkix::Error| {
265 if source.is_resource() {
266 Error::pkix(structured_pkix::Error::new(
267 source.code(),
268 "signedData.signerInfos",
269 other.span().start,
270 ))
271 } else {
272 Error::pkix(source)
273 }
274 };
275 if !self
280 .digest_algorithm
281 .same_written_in(&other.digest_algorithm, parent)
282 .map_err(comparison_error)?
283 && !self
284 .digest_algorithm
285 .digest_matches_in(&other.digest_algorithm, parent)
286 .map_err(comparison_error)?
287 {
288 return Ok(false);
289 }
290 self.signature_algorithm
291 .same_written_in(&other.signature_algorithm, parent)
292 .map_err(comparison_error)
293 }
294
295 pub(crate) fn same_fields(&self, other: &SignerInfo<'_>, parent: &Reader<'_>) -> Result<bool> {
299 let field = "signedData.signerInfos";
300 let at = other.span().start;
301 self.require_session(parent, field)?;
302 other.require_session(parent, field)?;
303 parent
304 .execution()
305 .charge_work(1)
306 .map_err(|reason| Error::resource(reason, field, at))?;
307 if self.version != other.version {
308 return Ok(false);
309 }
310 let same_sid = match (&self.sid, &other.sid) {
311 (
312 SignerIdentifier::IssuerAndSerial { issuer, serial },
313 SignerIdentifier::IssuerAndSerial {
314 issuer: right,
315 serial: number,
316 },
317 ) => {
318 same_bytes(parent, issuer.as_bytes(), right.as_bytes(), field, at)?
319 && same_bytes(parent, serial.as_bytes(), number.as_bytes(), field, at)?
320 }
321 (
322 SignerIdentifier::SubjectKeyIdentifier(left),
323 SignerIdentifier::SubjectKeyIdentifier(right),
324 ) => left.same_value(right, parent, field, at)?,
325 _ => false,
326 };
327 if !same_sid {
328 return Ok(false);
329 }
330 for (left, right) in [
331 (&self.signed_attributes, &other.signed_attributes),
332 (&self.unsigned_attributes, &other.unsigned_attributes),
333 ] {
334 if !same_optional(
335 parent,
336 left.as_ref().map(|attrs| attrs.element().as_bytes()),
337 right.as_ref().map(|attrs| attrs.element().as_bytes()),
338 field,
339 at,
340 )? {
341 return Ok(false);
342 }
343 }
344 self.signature
345 .same_value(&other.signature, parent, field, at)
346 }
347}
348
349pub(crate) fn required<'a>(reader: &mut Reader<'a>, field: &'static str) -> Result<Element<'a>> {
350 reader
351 .next_element()
352 .map_err(|error| Error::encoding(error, field))?
353 .ok_or_else(|| Error::schema(ErrorCode::MissingField, field, reader.offset()))
354}
355
356fn same_bytes(
357 parent: &Reader<'_>,
358 left: &[u8],
359 right: &[u8],
360 field: &'static str,
361 at: u64,
362) -> Result<bool> {
363 let execution = parent.execution();
364 execution
365 .charge_work(1)
366 .map_err(|reason| Error::resource(reason, field, at))?;
367 if left.len() != right.len() {
368 return Ok(false);
369 }
370 execution
371 .charge_work(left.len() as u64)
372 .map_err(|reason| Error::resource(reason, field, at))?;
373 Ok(left == right)
374}
375
376fn same_optional(
377 parent: &Reader<'_>,
378 left: Option<&[u8]>,
379 right: Option<&[u8]>,
380 field: &'static str,
381 at: u64,
382) -> Result<bool> {
383 parent
384 .execution()
385 .charge_work(1)
386 .map_err(|reason| Error::resource(reason, field, at))?;
387 match (left, right) {
388 (None, None) => Ok(true),
389 (Some(left), Some(right)) => same_bytes(parent, left, right, field, at),
390 _ => Ok(false),
391 }
392}