1use crate::content::{ContentInfo, Encapsulated};
4use crate::signer::{SignerInfo, required};
5use crate::{Error, ErrorCode, Result, oid};
6use structured_asn1::memory::{OwnedVec, Work};
7use structured_asn1::{Element, Parser, Reader, Span, Tag, universal};
8use structured_pkix::{AlgorithmIdentifier, Certificate};
9
10#[derive(Debug, Clone, Copy)]
15pub enum CertificateChoice<'a> {
16 X509(usize),
18 Extended(Element<'a>),
20 AttributeV1(Element<'a>),
22 AttributeV2(Element<'a>),
24 Other(Element<'a>),
26}
27
28#[derive(Debug)]
30pub struct SignedData<'a> {
31 version: u64,
32 required_version: u64,
33 algorithms: OwnedVec<AlgorithmIdentifier<'a>>,
34 content: Encapsulated<'a>,
35 choices: OwnedVec<CertificateChoice<'a>>,
36 certificates: OwnedVec<Certificate<'a>>,
37 certificate_field: Option<Span>,
38 revocations: OwnedVec<Element<'a>>,
39 revocation_field: Option<Span>,
40 signers: OwnedVec<SignerInfo<'a>>,
41 faults: OwnedVec<Error>,
42 element: Element<'a>,
43}
44
45impl<'a> SignedData<'a> {
46 pub fn read(parser: &'a Parser, encoded: &'a [u8], base: u64) -> Result<Self> {
48 let mut root = parser
49 .read(encoded, base)
50 .map_err(|error| Error::encoding(error, "contentInfo"))?;
51 let (envelope, parent) = ContentInfo::read(&mut root)?;
52 parent
53 .execution()
54 .charge_work(envelope.kind().as_bytes().len() as u64)
55 .map_err(|reason| {
56 Error::resource(reason, "contentInfo.contentType", envelope.span().start)
57 })?;
58 if envelope.kind() != oid::SIGNED_DATA {
59 return Err(Error::schema(
60 ErrorCode::UnexpectedContentType,
61 "contentInfo.contentType",
62 envelope.span().start,
63 ));
64 }
65 Self::read_element(&parent, envelope.content())
66 }
67
68 pub fn read_element(parent: &Reader<'a>, element: &Element<'a>) -> Result<Self> {
70 const FIELD: &str = "signedData";
71 if element.tag() != Tag::constructed(universal::SEQUENCE) {
72 return Err(Error::schema(
73 ErrorCode::UnexpectedTag,
74 FIELD,
75 element.span().start,
76 ));
77 }
78 let mut inside = parent
79 .enter(element)
80 .map_err(|error| Error::encoding(error, FIELD))?;
81 let execution = parent.execution();
82 let (version, version_element) = read_version(&mut inside)?;
83 let set = required(&mut inside, "signedData.digestAlgorithms")?;
84 let algorithms = catalogue(
85 &inside,
86 &set,
87 Tag::constructed(universal::SET),
88 "signedData.digestAlgorithms",
89 |members, entry| {
90 structured_pkix::algorithm::read(members, entry, "signedData.digestAlgorithms")
91 .map_err(Error::pkix)
92 },
93 )?;
94 let content_element = required(&mut inside, "signedData.encapContentInfo")?;
95 let content = Encapsulated::read(&inside, &content_element)?;
96 execution
97 .charge_work(content.kind().as_bytes().len() as u64)
98 .map_err(|reason| {
99 Error::resource(
100 reason,
101 "signedData.encapContentInfo.eContentType",
102 content.span().start,
103 )
104 })?;
105 let mut required_version = if content.kind() == oid::DATA { 1 } else { 3 };
109 let mut choices = parent.memory().vector();
110 let mut certificates = parent.memory().vector();
111 let mut revocations = parent.memory().vector();
112 let mut certificate_field = None;
113 let mut revocation_field = None;
114 let mut next = required(&mut inside, "signedData.signerInfos")?;
115 if next.tag() == Tag::context(true, 0) {
116 certificate_field = Some(next.span());
117 (choices, certificates) = read_certificates(&inside, &next, &mut required_version)?;
118 next = required(&mut inside, "signedData.signerInfos")?;
119 }
120 if next.tag() == Tag::context(true, 1) {
121 revocation_field = Some(next.span());
122 revocations = read_revocations(&inside, &next, &mut required_version)?;
123 next = required(&mut inside, "signedData.signerInfos")?;
124 }
125 let signers = catalogue(
126 &inside,
127 &next,
128 Tag::constructed(universal::SET),
129 "signedData.signerInfos",
130 |members, entry| {
131 let signer = SignerInfo::read(members, entry)?;
132 if signer.version() == 3 {
133 required_version = required_version.max(3);
134 }
135 Ok(signer)
136 },
137 )?;
138 if !inside.is_empty() {
139 return Err(Error::schema(
140 ErrorCode::TrailingData,
141 FIELD,
142 inside.offset(),
143 ));
144 }
145 let mut faults = execution.vector();
146 if version != required_version {
147 faults
148 .try_push(Error::schema(
149 ErrorCode::VersionMismatch,
150 "signedData.version",
151 version_element.span().start,
152 ))
153 .map_err(|reason| {
154 Error::resource(reason, "signedData.version", version_element.span().start)
155 })?;
156 }
157 Ok(Self {
158 version,
159 required_version,
160 algorithms,
161 content,
162 choices,
163 certificates,
164 certificate_field,
165 revocations,
166 revocation_field,
167 signers,
168 faults: faults.into_owned(),
169 element: *element,
170 })
171 }
172
173 #[must_use]
175 pub fn version(&self) -> u64 {
176 self.version
177 }
178 #[must_use]
180 pub fn required_version(&self) -> u64 {
181 self.required_version
182 }
183 #[must_use]
189 pub fn digest_algorithms(&self) -> &[AlgorithmIdentifier<'a>] {
190 &self.algorithms
191 }
192 #[must_use]
194 pub fn content(&self) -> &Encapsulated<'a> {
195 &self.content
196 }
197 #[must_use]
199 pub fn certificate_choices(&self) -> &[CertificateChoice<'a>] {
200 &self.choices
201 }
202 #[must_use]
204 pub fn certificates(&self) -> &[Certificate<'a>] {
205 &self.certificates
206 }
207 #[must_use]
209 pub fn certificate_field(&self) -> Option<Span> {
210 self.certificate_field
211 }
212 #[must_use]
214 pub fn revocation_field(&self) -> Option<Span> {
215 self.revocation_field
216 }
217 #[must_use]
219 pub fn revocations(&self) -> &[Element<'a>] {
220 &self.revocations
221 }
222 #[must_use]
224 pub fn signers(&self) -> &[SignerInfo<'a>] {
225 &self.signers
226 }
227 #[must_use]
229 pub fn faults(&self) -> &[Error] {
230 &self.faults
231 }
232 #[must_use]
234 pub fn span(&self) -> Span {
235 self.element.span()
236 }
237 #[must_use]
239 pub fn as_bytes(&self) -> &'a [u8] {
240 self.element.as_bytes()
241 }
242}
243
244fn ordered<'a>(
245 parent: &Reader<'a>,
246 previous: &mut Option<&'a [u8]>,
247 element: &Element<'a>,
248 field: &'static str,
249) -> Result<()> {
250 if parent.encoding().is_der() {
251 if let Some(earlier) = *previous
252 && !structured_pkix::der::set_ordered(parent, earlier, element, field)
253 .map_err(Error::pkix)?
254 {
255 return Err(Error::schema(
256 ErrorCode::SetOrder,
257 field,
258 element.span().start,
259 ));
260 }
261 *previous = Some(element.as_bytes());
262 }
263 Ok(())
264}
265
266fn other_format(parent: &Reader<'_>, element: &Element<'_>, field: &'static str) -> Result<()> {
267 let mut inside = parent
268 .enter(element)
269 .map_err(|error| Error::encoding(error, field))?;
270 inside
271 .read_oid()
272 .map_err(|error| Error::encoding(error, field))?;
273 required(&mut inside, field)?;
274 if !inside.is_empty() {
275 return Err(Error::schema(
276 ErrorCode::TrailingData,
277 field,
278 inside.offset(),
279 ));
280 }
281 Ok(())
282}
283
284fn catalogue<'a, T>(
285 parent: &Reader<'a>,
286 set: &Element<'a>,
287 tag: Tag,
288 field: &'static str,
289 mut read: impl FnMut(&Reader<'a>, &Element<'a>) -> Result<T>,
290) -> Result<OwnedVec<T>> {
291 if set.tag() != tag {
292 return Err(Error::schema(
293 ErrorCode::UnexpectedTag,
294 field,
295 set.span().start,
296 ));
297 }
298 let mut members = parent
299 .enter(set)
300 .map_err(|error| Error::encoding(error, field))?;
301 let execution = parent.execution();
302 let mut values = execution.vector();
303 let mut previous = None;
304 while let Some(entry) = members
305 .next_element()
306 .map_err(|error| Error::encoding(error, field))?
307 {
308 ordered(&members, &mut previous, &entry, field)?;
309 values
310 .try_reserve(1)
311 .map_err(|reason| Error::resource(reason, field, entry.span().start))?;
312 let value = read(&members, &entry)?;
313 values
314 .try_push(value)
315 .map_err(|reason| Error::resource(reason, field, entry.span().start))?;
316 }
317 Ok(values.into_owned())
318}
319
320fn read_certificates<'a>(
321 parent: &Reader<'a>,
322 set: &Element<'a>,
323 version: &mut u64,
324) -> Result<(OwnedVec<CertificateChoice<'a>>, OwnedVec<Certificate<'a>>)> {
325 const FIELD: &str = "signedData.certificates";
326 let execution = parent.execution();
327 let mut certificates = execution.vector();
328 let choices = catalogue(
329 parent,
330 set,
331 Tag::context(true, 0),
332 FIELD,
333 |members, entry| {
334 Ok(match entry.tag() {
335 tag if tag == Tag::constructed(universal::SEQUENCE) => {
336 certificates
337 .try_reserve(1)
338 .map_err(|reason| Error::resource(reason, FIELD, entry.span().start))?;
339 let certificate =
340 Certificate::read_element(members, entry).map_err(Error::pkix)?;
341 let index = certificates.len();
342 certificates
343 .try_push(certificate)
344 .map_err(|reason| Error::resource(reason, FIELD, entry.span().start))?;
345 CertificateChoice::X509(index)
346 }
347 tag if tag == Tag::context(true, 0) => CertificateChoice::Extended(*entry),
348 tag if tag == Tag::context(true, 1) => {
349 *version = (*version).max(3);
350 CertificateChoice::AttributeV1(*entry)
351 }
352 tag if tag == Tag::context(true, 2) => {
353 *version = (*version).max(4);
354 CertificateChoice::AttributeV2(*entry)
355 }
356 tag if tag == Tag::context(true, 3) => {
357 other_format(members, entry, FIELD)?;
358 *version = 5;
359 CertificateChoice::Other(*entry)
360 }
361 _ => {
362 return Err(Error::schema(
363 ErrorCode::UnexpectedTag,
364 FIELD,
365 entry.span().start,
366 ));
367 }
368 })
369 },
370 )?;
371 Ok((choices, certificates.into_owned()))
372}
373
374fn read_version<'a>(inside: &mut Reader<'a>) -> Result<(u64, Element<'a>)> {
375 const FIELD: &str = "signedData.version";
376 let element = inside
377 .expect(Tag::primitive(universal::INTEGER))
378 .map_err(|error| Error::encoding(error, FIELD))?;
379 let version = inside
380 .integer(&element)
381 .map_err(|error| Error::encoding(error, FIELD))?
382 .as_u64()
383 .ok_or_else(|| Error::schema(ErrorCode::ValueTooLarge, FIELD, element.span().start))?;
384 Ok((version, element))
385}
386
387fn read_revocations<'a>(
388 parent: &Reader<'a>,
389 set: &Element<'a>,
390 version: &mut u64,
391) -> Result<OwnedVec<Element<'a>>> {
392 const FIELD: &str = "signedData.crls";
393 catalogue(
394 parent,
395 set,
396 Tag::context(true, 1),
397 FIELD,
398 |members, entry| {
399 if entry.tag() == Tag::context(true, 1) {
400 other_format(members, entry, FIELD)?;
401 *version = 5;
402 } else if entry.tag() != Tag::constructed(universal::SEQUENCE) {
403 return Err(Error::schema(
404 ErrorCode::UnexpectedTag,
405 FIELD,
406 entry.span().start,
407 ));
408 }
409 Ok(*entry)
410 },
411 )
412}