1use crate::signed::{CertificateChoice, catalogue, read_certificates, read_revocations};
11use crate::{
12 ContentInfo, Error, ErrorCode, Octets, Result, attribute::Attribute, signer::required,
13};
14use structured_asn1::memory::{OwnedVec, Work};
15use structured_asn1::{Element, Encoding, Oid, Parser, Reader, Tag, universal};
16use structured_pkix::{AlgorithmIdentifier, Certificate};
17
18mod recipient;
19pub use recipient::{AgreementIdentifier, KeyIdentifier, Originator, Recipient, RecipientKey};
20
21pub const IDENTIFIER: Oid<'static> = Oid::from_bytes(&[42, 134, 72, 134, 247, 13, 1, 7, 3]);
23const FIELD: &str = "envelopedData";
24
25#[derive(Debug, Clone, Copy)]
29pub struct EncodedValue<'a> {
30 element: Element<'a>,
31 parser: &'a Parser,
32 encoding: Encoding,
33 depth: u32,
34}
35impl<'a> EncodedValue<'a> {
36 pub(crate) fn new(parent: &Reader<'a>, element: Element<'a>) -> Self {
37 Self {
38 element,
39 parser: parent.parser(),
40 encoding: parent.encoding(),
41 depth: parent.depth(),
42 }
43 }
44 #[must_use]
46 pub fn element(&self) -> &Element<'a> {
47 &self.element
48 }
49 pub fn reader_in<'op>(&self, query: &Reader<'op>) -> Result<Reader<'op>>
52 where
53 'a: 'op,
54 {
55 self.parser
56 .read_query_in(
57 query,
58 self.element.as_bytes(),
59 self.element.span().start,
60 self.encoding,
61 self.depth,
62 )
63 .map_err(|e| Error::encoding(e, FIELD))
64 }
65}
66
67#[derive(Debug)]
69pub struct OriginatorInfo<'a> {
70 parser: &'a Parser,
71 encoding: Encoding,
72 outer: u32,
73 at: u64,
74 choices: OwnedVec<CertificateChoice<'a>>,
75 certificates: OwnedVec<Certificate<'a>>,
76 revocations: OwnedVec<Element<'a>>,
77}
78
79impl<'a> OriginatorInfo<'a> {
80 #[must_use]
82 pub fn choices(&self) -> &[CertificateChoice<'a>] {
83 &self.choices
84 }
85 #[must_use]
87 pub fn certificates(&self) -> &[Certificate<'a>] {
88 &self.certificates
89 }
90 #[must_use]
92 pub fn revocations(&self) -> &[Element<'a>] {
93 &self.revocations
94 }
95 pub fn certificate_reader_in<'op>(
98 &self,
99 query: &Reader<'op>,
100 ordinal: usize,
101 ) -> Result<Option<Reader<'op>>>
102 where
103 'a: 'op,
104 {
105 self.admit(query)?;
106 let Some(
107 CertificateChoice::Extended(entry)
108 | CertificateChoice::AttributeV1(entry)
109 | CertificateChoice::AttributeV2(entry)
110 | CertificateChoice::Other(entry),
111 ) = self.choices.get(ordinal)
112 else {
113 return Ok(None);
114 };
115 self.reopen(query, entry).map(Some)
116 }
117 pub fn revocation_reader_in<'op>(
120 &self,
121 query: &Reader<'op>,
122 ordinal: usize,
123 ) -> Result<Option<Reader<'op>>>
124 where
125 'a: 'op,
126 {
127 self.admit(query)?;
128 self.revocations
129 .get(ordinal)
130 .map(|entry| self.reopen(query, entry))
131 .transpose()
132 }
133 fn admit(&self, query: &Reader<'_>) -> Result<()> {
134 query
135 .execution()
136 .execution_for(self.parser)
137 .charge_work(1)
138 .map_err(|e| Error::resource(e, "envelopedData.originatorInfo", self.at))
139 }
140 fn reopen<'op>(&self, query: &Reader<'op>, entry: &Element<'a>) -> Result<Reader<'op>>
141 where
142 'a: 'op,
143 {
144 self.parser
147 .read_nested_query_in(
148 query,
149 entry.as_bytes(),
150 entry.span().start,
151 self.encoding,
152 self.outer,
153 )
154 .map_err(|e| Error::encoding(e, "envelopedData.originatorInfo"))
155 }
156}
157
158#[derive(Debug)]
160pub struct EncryptedContent<'a> {
161 pub kind: Oid<'a>,
163 pub algorithm: AlgorithmIdentifier<'a>,
165 pub ciphertext: Option<Octets<'a>>,
167}
168
169#[derive(Debug)]
171pub struct EnvelopedData<'a> {
172 parser: &'a Parser,
173 element: Element<'a>,
174 depth: u32,
175 encoding: Encoding,
176 pub version: u64,
178 pub originator: Option<OriginatorInfo<'a>>,
180 pub recipients: OwnedVec<Recipient<'a>>,
182 pub content: EncryptedContent<'a>,
184 pub unprotected: Option<OwnedVec<Attribute<'a>>>,
186}
187
188impl<'a> EnvelopedData<'a> {
189 pub fn read(parent: &mut Reader<'a>) -> Result<Self> {
191 let (wrapper, reader) = ContentInfo::read(parent)?;
192 Self::from_content_info(&wrapper, &reader)
193 }
194 pub fn read_content_info(parent: &Reader<'a>, element: &Element<'a>) -> Result<Self> {
196 let (wrapper, reader) = ContentInfo::read_element(parent, element)?;
197 Self::from_content_info(&wrapper, &reader)
198 }
199 fn from_content_info(wrapper: &ContentInfo<'a>, parent: &Reader<'a>) -> Result<Self> {
200 oid_is(
201 wrapper.kind(),
202 IDENTIFIER,
203 parent,
204 "contentInfo.contentType",
205 wrapper.span().start,
206 )?;
207 Self::read_element(parent, wrapper.content())
208 }
209 pub fn read_element(parent: &Reader<'a>, element: &Element<'a>) -> Result<Self> {
211 tag(element, Tag::constructed(universal::SEQUENCE), FIELD)?;
212 let mut inside = enter(parent, element, FIELD)?;
213 let (version, at) = number(&mut inside, "envelopedData.version")?;
214 let mut next = required(&mut inside, FIELD)?;
215 let mut material_version = 0;
216 let originator = if next.tag() == Tag::context(true, 0) {
217 let original = originator_info(&inside, &next, &mut material_version)?;
218 next = required(&mut inside, FIELD)?;
219 Some(original)
220 } else {
221 None
222 };
223 let mut all_zero = true;
224 let mut advanced = false;
225 let recipients = catalogue(
226 &inside,
227 &next,
228 Tag::constructed(universal::SET),
229 "envelopedData.recipientInfos",
230 |reader, entry| {
231 let recipient = Recipient::read(reader, entry)?;
232 all_zero &= recipient.is_transport_zero();
233 advanced |= matches!(
234 recipient,
235 Recipient::Password { .. } | Recipient::Other { .. }
236 );
237 Ok(recipient)
238 },
239 )?;
240 if recipients.is_empty() {
241 return Err(Error::schema(
242 ErrorCode::MissingField,
243 "envelopedData.recipientInfos",
244 next.span().start,
245 ));
246 }
247 let value = required(&mut inside, "envelopedData.encryptedContentInfo")?;
248 let content = encrypted_content(&inside, &value)?;
249 let unprotected = inside
250 .next_element()
251 .map_err(|e| Error::encoding(e, FIELD))?
252 .map(|set| {
253 let values = catalogue(
254 &inside,
255 &set,
256 Tag::context(true, 1),
257 "envelopedData.unprotectedAttrs",
258 |r, e| Attribute::read(r, e, "envelopedData.unprotectedAttrs"),
259 )?;
260 if values.is_empty() {
261 return Err(Error::schema(
262 ErrorCode::EmptyAttributes,
263 "envelopedData.unprotectedAttrs",
264 set.span().start,
265 ));
266 }
267 Ok(values)
268 })
269 .transpose()?;
270 end(&inside, FIELD)?;
271 let expected = if material_version == 5 {
275 4
276 } else if material_version >= 4 || advanced {
277 3
278 } else if originator.is_none() && unprotected.is_none() && all_zero {
279 0
280 } else {
281 2
282 };
283 if version != expected {
284 return Err(Error::schema(
285 ErrorCode::VersionMismatch,
286 "envelopedData.version",
287 at,
288 ));
289 }
290 Ok(Self {
291 parser: parent.parser(),
292 element: *element,
293 depth: parent.depth(),
294 encoding: parent.encoding(),
295 version,
296 originator,
297 recipients,
298 content,
299 unprotected,
300 })
301 }
302 #[must_use]
304 pub fn element(&self) -> &Element<'a> {
305 &self.element
306 }
307 pub fn execution_in<'op, W: Work>(
309 &self,
310 current: &'op W,
311 ) -> structured_asn1::memory::Execution<'op>
312 where
313 'a: 'op,
314 {
315 current.execution_for(self.parser)
316 }
317 pub fn reader_in<'op>(&self, current: &Reader<'op>) -> Result<Reader<'op>>
320 where
321 'a: 'op,
322 {
323 let outer = self.element.span();
324 self.parser
325 .read_query_in(
326 current,
327 self.element.as_bytes(),
328 outer.start,
329 self.encoding,
330 self.depth,
331 )
332 .map_err(|e| Error::encoding(e, FIELD))
333 }
334}
335
336fn originator_info<'a>(
337 parent: &Reader<'a>,
338 element: &Element<'a>,
339 version: &mut u64,
340) -> Result<OriginatorInfo<'a>> {
341 let field = "envelopedData.originatorInfo";
342 let mut inside = enter(parent, element, field)?;
343 let work = parent.execution();
344 let mut choices = work.vector().into_owned();
345 let mut certificates = work.vector().into_owned();
346 let mut revocations = work.vector().into_owned();
347 let mut next = inside
348 .next_element()
349 .map_err(|e| Error::encoding(e, field))?;
350 if let Some(set) = next.as_ref().filter(|e| e.tag() == Tag::context(true, 0)) {
351 (choices, certificates) =
352 read_certificates(&inside, set, version, "envelopedData.originatorInfo.certs")?;
353 next = inside
354 .next_element()
355 .map_err(|e| Error::encoding(e, field))?;
356 }
357 if let Some(set) = next.as_ref().filter(|e| e.tag() == Tag::context(true, 1)) {
358 revocations = read_revocations(&inside, set, version, "envelopedData.originatorInfo.crls")?;
359 next = inside
360 .next_element()
361 .map_err(|e| Error::encoding(e, field))?;
362 }
363 if let Some(extra) = next {
364 return Err(Error::schema(
365 ErrorCode::UnknownField,
366 field,
367 extra.span().start,
368 ));
369 }
370 Ok(OriginatorInfo {
371 parser: parent.parser(),
372 encoding: parent.encoding(),
373 outer: inside.depth(),
374 at: element.span().start,
375 choices,
376 certificates,
377 revocations,
378 })
379}
380pub(crate) fn encrypted_content<'a>(
381 parent: &Reader<'a>,
382 element: &Element<'a>,
383) -> Result<EncryptedContent<'a>> {
384 let field = "envelopedData.encryptedContentInfo";
385 tag(element, Tag::constructed(universal::SEQUENCE), field)?;
386 let mut inside = enter(parent, element, field)?;
387 let kind = inside.read_oid().map_err(|e| Error::encoding(e, field))?;
388 let value = required(&mut inside, field)?;
389 let algorithm = algorithm(&inside, &value, field)?;
390 let ciphertext = inside
391 .next_element()
392 .map_err(|e| Error::encoding(e, field))?
393 .map(|value| Octets::read_identifier(&inside, &value, field))
394 .transpose()?;
395 end(&inside, field)?;
396 Ok(EncryptedContent {
397 kind,
398 algorithm,
399 ciphertext,
400 })
401}
402fn enter<'a>(
403 parent: &Reader<'a>,
404 element: &Element<'a>,
405 field: &'static str,
406) -> Result<Reader<'a>> {
407 parent.enter(element).map_err(|e| Error::encoding(e, field))
408}
409fn end(parent: &Reader<'_>, field: &'static str) -> Result<()> {
410 if !parent.is_empty() {
411 return Err(Error::schema(
412 ErrorCode::TrailingData,
413 field,
414 parent.offset(),
415 ));
416 }
417 Ok(())
418}
419fn tag(element: &Element<'_>, expected: Tag, field: &'static str) -> Result<()> {
420 if element.tag() != expected {
421 return Err(Error::schema(
422 ErrorCode::UnexpectedTag,
423 field,
424 element.span().start,
425 ));
426 }
427 Ok(())
428}
429fn number(parent: &mut Reader<'_>, field: &'static str) -> Result<(u64, u64)> {
430 let element = parent
431 .expect(Tag::primitive(universal::INTEGER))
432 .map_err(|e| Error::encoding(e, field))?;
433 let value = parent
434 .integer(&element)
435 .map_err(|e| Error::encoding(e, field))?
436 .as_u64()
437 .ok_or_else(|| Error::schema(ErrorCode::ValueTooLarge, field, element.span().start))?;
438 Ok((value, element.span().start))
439}
440fn version(parent: &mut Reader<'_>, expected: u64, field: &'static str) -> Result<()> {
441 let (value, at) = number(parent, field)?;
442 if value != expected {
443 return Err(Error::schema(ErrorCode::UnsupportedVersion, field, at));
444 }
445 Ok(())
446}
447fn algorithm<'a>(
448 parent: &Reader<'a>,
449 element: &Element<'a>,
450 field: &'static str,
451) -> Result<AlgorithmIdentifier<'a>> {
452 structured_pkix::algorithm::read(parent, element, field).map_err(Error::pkix)
453}
454pub(crate) fn oid_is(
455 value: Oid<'_>,
456 expected: Oid<'_>,
457 parent: &Reader<'_>,
458 field: &'static str,
459 at: u64,
460) -> Result<()> {
461 parent.charge(1).map_err(|e| Error::encoding(e, field))?;
462 if value.as_bytes().len() == expected.as_bytes().len() {
463 parent
464 .charge(value.as_bytes().len() as u64)
465 .map_err(|e| Error::encoding(e, field))?;
466 if value == expected {
467 return Ok(());
468 }
469 }
470 Err(Error::schema(ErrorCode::UnexpectedContentType, field, at))
471}