structured_ltv/pki/
responder.rs1use super::{CheckedPath, OcspTarget, authority};
4use structured_asn1::memory::{MemoryError, Work};
5use structured_pkix::{
6 ocsp::{AuthoritySource, ResponderRevocation},
7 temporal::{LeapTable, Uncertainty},
8};
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub enum ResponderFailure {
13 Anchor,
15 Signer,
17 EffectiveKey,
19 Interval,
21}
22
23#[derive(Debug)]
25pub enum ResponderError {
26 SourceKind,
30 Resource(MemoryError),
32 Name(structured_pkix::Error),
34 Time(Uncertainty),
36}
37
38impl From<authority::Error> for ResponderError {
39 fn from(value: authority::Error) -> Self {
40 match value {
41 authority::Error::Resource(cause) => Self::Resource(cause),
42 authority::Error::Name(cause) => Self::Name(cause),
43 authority::Error::Time(cause) => Self::Time(cause),
44 }
45 }
46}
47
48impl From<authority::Failure> for ResponderFailure {
49 fn from(value: authority::Failure) -> Self {
50 match value {
51 authority::Failure::Anchor => Self::Anchor,
52 authority::Failure::Signer => Self::Signer,
53 authority::Failure::EffectiveKey => Self::EffectiveKey,
54 authority::Failure::Interval => Self::Interval,
55 }
56 }
57}
58
59pub struct ResponderPath<'receipt, 'view, 'certificate, 'document> {
63 target: &'receipt OcspTarget<'view, 'certificate, 'document>,
64 path: &'receipt CheckedPath<'document>,
65 revocation: ResponderRevocation,
66}
67
68impl<'receipt, 'view, 'certificate, 'document>
69 ResponderPath<'receipt, 'view, 'certificate, 'document>
70{
71 #[must_use]
73 pub fn target(&self) -> &'receipt OcspTarget<'view, 'certificate, 'document> {
74 self.target
75 }
76
77 #[must_use]
79 pub fn path(&self) -> &'receipt CheckedPath<'document> {
80 self.path
81 }
82
83 #[must_use]
85 pub fn revocation(&self) -> ResponderRevocation {
86 self.revocation
87 }
88}
89
90pub enum ResponderBinding<'receipt, 'view, 'certificate, 'document> {
92 Bound(ResponderPath<'receipt, 'view, 'certificate, 'document>),
94 Rejected(ResponderFailure),
96}
97
98impl<'view, 'certificate, 'document> OcspTarget<'view, 'certificate, 'document> {
99 pub fn bind_responder_path<'receipt, W: Work>(
107 &'receipt self,
108 path: &'receipt CheckedPath<'document>,
109 utc: &LeapTable<'_>,
110 execution: &W,
111 ) -> Result<ResponderBinding<'receipt, 'view, 'certificate, 'document>, ResponderError> {
112 execution.charge_work(1).map_err(ResponderError::Resource)?;
113 let AuthoritySource::Delegate { revocation } = self.authority() else {
114 return Err(ResponderError::SourceKind);
115 };
116 let evidence = self.evidence().evidence();
117 let signed = evidence.source().signed();
118 if let Some(cause) = self.path().path_authority(
119 path,
120 signed.signer(),
121 signed.key(),
122 self.evidence().evaluated_at(),
123 utc,
124 execution,
125 )? {
126 return Ok(ResponderBinding::Rejected(cause.into()));
127 }
128 Ok(ResponderBinding::Bound(ResponderPath {
129 target: self,
130 path,
131 revocation,
132 }))
133 }
134}