1use crate::{
4 certificate,
5 container::XADES,
6 properties::{self, Error, PropertyResult},
7 timestamp::XADES_141,
8 unsigned,
9 xml::{Access, Name, Snapshot, Xml},
10};
11use structured_asn1::memory::{OwnedVec, Work};
12
13#[derive(Clone, Copy, Debug, PartialEq, Eq)]
15pub enum ReferenceKind {
16 Certificate,
18 Crl,
20 Ocsp,
22 Other,
24}
25
26#[derive(Clone, Copy, Debug)]
28pub enum ReferenceField<N> {
29 Uri(N),
31 Integer(N),
33 DateTime(N),
35 Binary(N),
37}
38
39#[derive(Clone, Copy, Debug)]
42pub enum ReferenceIdentifier<N> {
43 Absent,
45 Certificate {
47 issuer_serial: N,
49 },
50 Crl {
52 node: N,
54 issuer: N,
56 time: N,
58 number: Option<N>,
60 },
61 Ocsp {
63 node: N,
65 responder: ResponderIdentifier<N>,
67 time: N,
69 },
70}
71
72#[derive(Clone, Copy, Debug)]
74pub enum ResponderIdentifier<N> {
75 Name(N),
77 Key(N),
79}
80
81pub struct ReferenceEntry<N> {
84 node: N,
85 kind: ReferenceKind,
86 digest: Option<(N, N)>,
87 identifier: ReferenceIdentifier<N>,
88}
89
90impl<N: Copy> ReferenceEntry<N> {
91 #[must_use]
93 pub fn node(&self) -> N {
94 self.node
95 }
96 #[must_use]
98 pub fn kind(&self) -> ReferenceKind {
99 self.kind
100 }
101 #[must_use]
103 pub fn digest(&self) -> Option<(N, N)> {
104 self.digest
105 }
106 #[must_use]
108 pub fn identifier(&self) -> ReferenceIdentifier<N> {
109 self.identifier
110 }
111 #[must_use]
114 pub fn fields(&self) -> [Option<ReferenceField<N>>; 4] {
115 let digest = self.digest.map(|(_, node)| ReferenceField::Binary(node));
116 match self.identifier {
117 ReferenceIdentifier::Certificate { issuer_serial } => [
118 digest,
119 Some(ReferenceField::Uri(self.node)),
120 Some(ReferenceField::Binary(issuer_serial)),
121 None,
122 ],
123 ReferenceIdentifier::Crl {
124 node, time, number, ..
125 } => [
126 digest,
127 Some(ReferenceField::DateTime(time)),
128 Some(ReferenceField::Uri(node)),
129 number.map(ReferenceField::Integer),
130 ],
131 ReferenceIdentifier::Ocsp {
132 node,
133 responder,
134 time,
135 } => [
136 match responder {
137 ResponderIdentifier::Key(node) => Some(ReferenceField::Binary(node)),
138 ResponderIdentifier::Name(_) => None,
139 },
140 Some(ReferenceField::DateTime(time)),
141 Some(ReferenceField::Uri(node)),
142 digest,
143 ],
144 ReferenceIdentifier::Absent => [
145 digest,
146 if self.kind == ReferenceKind::Certificate {
147 Some(ReferenceField::Uri(self.node))
148 } else {
149 None
150 },
151 None,
152 None,
153 ],
154 }
155 }
156}
157
158pub struct ReferenceProperty<N, D, G> {
161 snapshot: Snapshot<D, G>,
162 signature: N,
163 node: N,
164 role: unsigned::Role,
165 entries: OwnedVec<ReferenceEntry<N>>,
166}
167
168impl<N: Copy, D: Copy, G: Copy> ReferenceProperty<N, D, G> {
169 #[must_use]
171 pub fn snapshot(&self) -> Snapshot<D, G> {
172 self.snapshot
173 }
174 #[must_use]
176 pub fn signature(&self) -> N {
177 self.signature
178 }
179 #[must_use]
181 pub fn node(&self) -> N {
182 self.node
183 }
184 #[must_use]
186 pub fn role(&self) -> unsigned::Role {
187 self.role
188 }
189 #[must_use]
191 pub fn entries(&self) -> &[ReferenceEntry<N>] {
192 &self.entries
193 }
194}
195
196type Reading<X> = ReferenceProperty<<X as Xml>::Id, <X as Xml>::Document, <X as Xml>::Generation>;
197
198pub(crate) fn read<X: Xml, W: Work>(
204 access: &Access<'_, X, W>,
205 signature: X::Id,
206 original: unsigned::Entry<X::Id>,
207) -> PropertyResult<Reading<X>, X> {
208 let node = original.node;
209 let mut entries = access.execution().vector();
210 match original.role {
211 unsigned::Role::CertificateReferences | unsigned::Role::AttributeCertificateReferences => {
212 let mut children = access.children(node);
213 let list = required(&mut children, node, "CertRefs")?;
214 expect(access, list, XADES_141, "CertRefs")?;
215 finish(&mut children)?;
216 read_group(access, list, ReferenceKind::Certificate, &mut entries)?;
217 }
218 unsigned::Role::RevocationReferences | unsigned::Role::AttributeRevocationReferences => {
219 let mut prior = None;
220 for child in access.children(node) {
221 let child = child.map_err(Error::Child)?;
222 let (rank, kind) = if named(access, child, XADES, "CRLRefs")? {
223 (0, ReferenceKind::Crl)
224 } else if named(access, child, XADES, "OCSPRefs")? {
225 (1, ReferenceKind::Ocsp)
226 } else if named(access, child, XADES, "OtherRefs")? {
227 (2, ReferenceKind::Other)
228 } else {
229 return Err(Error::Unexpected { node: child });
230 };
231 if let Some(previous) = prior {
232 if rank == previous {
233 return Err(Error::Duplicate { node: child });
234 }
235 if rank < previous {
236 return Err(Error::Order { node: child });
237 }
238 }
239 prior = Some(rank);
240 read_group(access, child, kind, &mut entries)?;
241 }
242 if original.role == unsigned::Role::RevocationReferences && entries.is_empty() {
243 return Err(Error::Missing {
244 parent: node,
245 local: "CRLRefs, OCSPRefs or OtherRefs",
246 });
247 }
248 }
249 _ => return Err(Error::Unexpected { node }),
250 }
251 Ok(ReferenceProperty {
252 snapshot: access.snapshot(),
253 signature,
254 node,
255 role: original.role,
256 entries: entries.into_owned(),
257 })
258}
259
260fn read_group<X: Xml, W: Work>(
261 access: &Access<'_, X, W>,
262 parent: X::Id,
263 kind: ReferenceKind,
264 entries: &mut OwnedVec<ReferenceEntry<X::Id>, W>,
265) -> PropertyResult<(), X> {
266 let local = match kind {
267 ReferenceKind::Certificate => "Cert",
268 ReferenceKind::Crl => "CRLRef",
269 ReferenceKind::Ocsp => "OCSPRef",
270 ReferenceKind::Other => "OtherRef",
271 };
272 let mut found = false;
273 for child in access.children(parent) {
274 let node = child.map_err(Error::Child)?;
275 expect(access, node, XADES, local)?;
276 let mut entry = ReferenceEntry {
277 node,
278 kind,
279 digest: None,
280 identifier: ReferenceIdentifier::Absent,
281 };
282 match kind {
283 ReferenceKind::Certificate => {
284 let reference = certificate::read_entry(access, node)?;
285 entry.digest = Some((reference.method(), reference.digest()));
286 if let Some(issuer) = reference.issuer_serial() {
287 properties::simple_content(access, issuer)?;
288 entry.identifier = ReferenceIdentifier::Certificate {
289 issuer_serial: issuer,
290 };
291 }
292 }
293 ReferenceKind::Crl => crl(access, &mut entry)?,
294 ReferenceKind::Ocsp => ocsp(access, &mut entry)?,
295 ReferenceKind::Other => {}
296 }
297 entries
298 .try_push(entry)
299 .map_err(|cause| Error::Resource { node, cause })?;
300 found = true;
301 }
302 if !found {
303 return Err(Error::Missing { parent, local });
304 }
305 Ok(())
306}
307
308fn crl<X: Xml, W: Work>(
309 access: &Access<'_, X, W>,
310 entry: &mut ReferenceEntry<X::Id>,
311) -> PropertyResult<(), X> {
312 let mut children = access.children(entry.node);
313 let digest = required(&mut children, entry.node, "DigestAlgAndValue")?;
314 expect(access, digest, XADES, "DigestAlgAndValue")?;
315 let (method, value) = properties::digest_value(access, digest)?;
316 entry.digest = Some((method, value));
317 if let Some(identifier) = children.next() {
318 let identifier = identifier.map_err(Error::Child)?;
319 expect(access, identifier, XADES, "CRLIdentifier")?;
320 let mut fields = access.children(identifier);
321 let issuer = required(&mut fields, identifier, "Issuer")?;
322 simple(access, issuer, "Issuer")?;
323 let time = required(&mut fields, identifier, "IssueTime")?;
324 simple(access, time, "IssueTime")?;
325 let mut crl_number = None;
326 if let Some(number) = fields.next() {
327 let number = number.map_err(Error::Child)?;
328 simple(access, number, "Number")?;
329 crl_number = Some(number);
330 }
331 finish(&mut fields)?;
332 entry.identifier = ReferenceIdentifier::Crl {
333 node: identifier,
334 issuer,
335 time,
336 number: crl_number,
337 };
338 }
339 finish(&mut children)
340}
341
342fn ocsp<X: Xml, W: Work>(
343 access: &Access<'_, X, W>,
344 entry: &mut ReferenceEntry<X::Id>,
345) -> PropertyResult<(), X> {
346 let mut children = access.children(entry.node);
347 let identifier = required(&mut children, entry.node, "OCSPIdentifier")?;
348 expect(access, identifier, XADES, "OCSPIdentifier")?;
349 let mut fields = access.children(identifier);
350 let responder = required(&mut fields, identifier, "ResponderID")?;
351 expect(access, responder, XADES, "ResponderID")?;
352 let mut choice = access.children(responder);
353 let value = required(&mut choice, responder, "ByName or ByKey")?;
354 let responder = if named(access, value, XADES, "ByKey")? {
355 ResponderIdentifier::Key(value)
356 } else {
357 expect(access, value, XADES, "ByName")?;
358 ResponderIdentifier::Name(value)
359 };
360 properties::simple_content(access, value)?;
361 finish(&mut choice)?;
362 let time = required(&mut fields, identifier, "ProducedAt")?;
363 simple(access, time, "ProducedAt")?;
364 finish(&mut fields)?;
365 entry.identifier = ReferenceIdentifier::Ocsp {
366 node: identifier,
367 responder,
368 time,
369 };
370 if let Some(digest) = children.next() {
371 let digest = digest.map_err(Error::Child)?;
372 expect(access, digest, XADES, "DigestAlgAndValue")?;
373 let (method, value) = properties::digest_value(access, digest)?;
374 entry.digest = Some((method, value));
375 }
376 finish(&mut children)
377}
378
379fn required<X: Xml, W: Work>(
380 children: &mut crate::xml::Children<'_, '_, X, W>,
381 parent: X::Id,
382 local: &'static str,
383) -> PropertyResult<X::Id, X> {
384 children
385 .next()
386 .transpose()
387 .map_err(Error::Child)?
388 .ok_or(Error::Missing { parent, local })
389}
390fn finish<X: Xml, W: Work>(
391 children: &mut crate::xml::Children<'_, '_, X, W>,
392) -> PropertyResult<(), X> {
393 if let Some(extra) = children.next() {
394 return Err(Error::Unexpected {
395 node: extra.map_err(Error::Child)?,
396 });
397 }
398 Ok(())
399}
400fn simple<X: Xml, W: Work>(
401 access: &Access<'_, X, W>,
402 node: X::Id,
403 local: &str,
404) -> PropertyResult<(), X> {
405 expect(access, node, XADES, local)?;
406 properties::simple_content(access, node)
407}
408fn expect<X: Xml, W: Work>(
409 access: &Access<'_, X, W>,
410 node: X::Id,
411 namespace: &str,
412 local: &str,
413) -> PropertyResult<(), X> {
414 if !named(access, node, namespace, local)? {
415 return Err(Error::Unexpected { node });
416 }
417 Ok(())
418}
419fn named<X: Xml, W: Work>(
420 access: &Access<'_, X, W>,
421 node: X::Id,
422 namespace: &str,
423 local: &str,
424) -> PropertyResult<bool, X> {
425 access
426 .has_name(node, Name { namespace, local })
427 .map_err(Error::Access)
428}