structured_xades/validation/
ref_crl_value.rs1use super::{
4 CrlReferenceError, CrlReferenceIdentity, ReferenceDigest, ReferenceDigestError, ReferenceKind,
5 ReferenceProperty, ReferenceTarget, ReferenceTime, check_crl_reference,
6 compare_reference_target,
7};
8use crate::{
9 binary::{self, BinaryXml, Located},
10 certificate::{Agreement, DigestProvider},
11 properties::CalendarXml,
12 scalar::TextXml,
13 xml::{Access, AccessError, Xml},
14};
15use structured_asn1::ScopedReader;
16use structured_pkix::crl::CertificateList;
17
18pub struct CrlValueReference<'references, 'actual, 'document, N, D, G> {
22 references: &'references ReferenceProperty<N, D, G>,
23 entry: usize,
24 actual: &'actual CertificateList<'document>,
25 identity: Option<Located<CrlReferenceIdentity<N>, N, D, G>>,
26 digest: Option<ReferenceDigest>,
27}
28
29impl<'r, 'a, 'd, N: Copy, D: Copy, G: Copy> CrlValueReference<'r, 'a, 'd, N, D, G> {
30 #[must_use]
32 pub fn references(&self) -> &'r ReferenceProperty<N, D, G> {
33 self.references
34 }
35
36 #[must_use]
38 pub fn entry(&self) -> usize {
39 self.entry
40 }
41
42 #[must_use]
44 pub fn actual(&self) -> &'a CertificateList<'d> {
45 self.actual
46 }
47
48 #[must_use]
50 pub fn identity(&self) -> Option<&Located<CrlReferenceIdentity<N>, N, D, G>> {
51 self.identity.as_ref()
52 }
53
54 #[must_use]
57 pub fn digest(&self) -> Option<ReferenceDigest> {
58 self.digest
59 }
60
61 #[must_use]
67 pub fn agrees(&self) -> bool {
68 if self.digest != Some(ReferenceDigest::Compared(Agreement::Matches)) {
69 return false;
70 }
71 if let Some(identity) = &self.identity {
72 return identity.value.issuer_matches()
73 && identity.value.issued_at() == ReferenceTime::Matches;
74 }
75 true
76 }
77}
78
79#[derive(Debug)]
81pub enum CrlValueError<E, PE, N, D, G> {
82 Access(AccessError<E, N>),
84 Index {
86 index: usize,
88 },
89 Identity(CrlReferenceError<E, N>),
91 Digest(binary::Error<E, ReferenceDigestError<PE>, N, D, G>),
93}
94
95pub type CrlValueResult<'r, 'a, 'd, X, PE> = Result<
97 Option<
98 CrlValueReference<'r, 'a, 'd, <X as Xml>::Id, <X as Xml>::Document, <X as Xml>::Generation>,
99 >,
100 CrlValueError<
101 <X as Xml>::Error,
102 PE,
103 <X as Xml>::Id,
104 <X as Xml>::Document,
105 <X as Xml>::Generation,
106 >,
107>;
108
109pub fn check_crl_value_reference<'r, 'a, 'd, 'q, X, P>(
120 xml: &X,
121 references: &'r ReferenceProperty<X::Id, X::Document, X::Generation>,
122 index: usize,
123 actual: &'a CertificateList<'d>,
124 provider: &'q P,
125 operation: &ScopedReader<'_, '_>,
126) -> CrlValueResult<'r, 'a, 'd, X, P::Error>
127where
128 X: BinaryXml + CalendarXml + TextXml,
129 P: DigestProvider<'q, X>,
130{
131 let work = operation.execution();
132 let access = Access::new(xml, references.snapshot(), &work);
133 access
134 .query(references.node(), |_, _, _| Ok(()))
135 .map_err(CrlValueError::Access)?;
136 let Some(entry) = references.entries().get(index) else {
137 return Err(CrlValueError::Index { index });
138 };
139 if entry.kind() != ReferenceKind::Crl {
140 return Ok(None);
141 }
142 let identity = check_crl_reference(xml, references, index, actual, operation)
143 .map_err(CrlValueError::Identity)?;
144 let digest = match identity.as_ref() {
145 Some(identity)
146 if matches!(
147 identity.value.issued_at(),
148 ReferenceTime::Malformed | ReferenceTime::Unsupported
149 ) =>
150 {
151 None
152 }
153 _ => Some(
154 compare_reference_target(
155 xml,
156 references,
157 index,
158 ReferenceTarget::Crl(actual),
159 provider,
160 &work,
161 )
162 .map_err(CrlValueError::Digest)?,
163 ),
164 };
165 access
166 .query(entry.node(), |_, _, _| Ok(()))
167 .map_err(CrlValueError::Access)?;
168 Ok(Some(CrlValueReference {
169 references,
170 entry: index,
171 actual,
172 identity,
173 digest,
174 }))
175}