1use super::{DelegateFacts, Digest, Lookup, ResponderRevocation, SignedResponse};
4use crate::Certificate;
5use crate::error::{CallbackResult, Error, Result};
6use crate::path::WorkingKey;
7use structured_asn1::memory::{Memory, MemoryError};
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub enum AuthoritySource {
12 Issuer,
14 Delegate {
16 revocation: ResponderRevocation,
18 },
19 Configured,
22}
23
24#[derive(Debug, Clone, Copy, PartialEq, Eq)]
26pub enum AuthorityFailure {
27 IssuerKeyBinding,
29 Signer,
31 EffectiveKey,
33 KeyUsage,
35}
36
37#[derive(Debug, Clone, Copy)]
40pub struct ScopedResponse<'r, 'a> {
41 signed: SignedResponse<'r, 'a>,
42 issuer: &'r Certificate<'a>,
43 source: AuthoritySource,
44}
45
46impl<'r, 'a> ScopedResponse<'r, 'a> {
47 #[must_use]
49 pub fn signed(self) -> SignedResponse<'r, 'a> {
50 self.signed
51 }
52 #[must_use]
54 pub fn issuer(self) -> &'r Certificate<'a> {
55 self.issuer
56 }
57 #[must_use]
59 pub fn source(self) -> AuthoritySource {
60 self.source
61 }
62 pub fn find<D: Digest>(
64 self,
65 target: &Certificate<'_>,
66 digest: &D,
67 execution: &Memory,
68 ) -> CallbackResult<Lookup<'r, 'a>, D::Error> {
69 self.signed.find(target, self.issuer, digest, execution)
70 }
71}
72
73#[derive(Debug, Clone, Copy)]
75pub enum AuthorityBinding<'r, 'a> {
76 Bound(ScopedResponse<'r, 'a>),
78 Rejected(AuthorityFailure),
80}
81
82fn equal_bytes(left: &[u8], right: &[u8], execution: &Memory, at: u64) -> Result<bool> {
83 let work = u64::try_from(left.len().max(right.len()))
84 .ok()
85 .and_then(|n| n.checked_mul(2))
86 .and_then(|n| n.checked_add(1))
87 .ok_or_else(|| Error::resource(MemoryError::WorkExceeded, "ocspResponse.authority", at))?;
88 execution
89 .charge_work(work)
90 .map_err(|reason| Error::resource(reason, "ocspResponse.authority", at))?;
91 Ok(left == right)
92}
93
94fn equal_key(
95 left: WorkingKey<'_>,
96 right: WorkingKey<'_>,
97 execution: &Memory,
98 at: u64,
99) -> Result<bool> {
100 if !equal_bytes(left.key().as_bytes(), right.key().as_bytes(), execution, at)? {
101 return Ok(false);
102 }
103 match (left.parameters(), right.parameters()) {
104 (None, None) => Ok(true),
105 (Some(left), Some(right)) => equal_bytes(left, right, execution, at),
106 _ => Ok(false),
107 }
108}
109
110pub(super) fn signing_usage(certificate: &Certificate<'_>, execution: &Memory) -> Result<bool> {
111 Ok(certificate
115 .tbs()
116 .extensions()
117 .key_usage(execution)?
118 .is_none_or(|usage| usage.digital_signature() || usage.content_commitment()))
119}
120
121impl<'r, 'a> SignedResponse<'r, 'a> {
122 pub fn bind_issuer(
127 self,
128 issuer: &'r Certificate<'a>,
129 issuing_key: WorkingKey<'a>,
130 execution: &Memory,
131 ) -> Result<AuthorityBinding<'r, 'a>> {
132 let at = self.response().span().start;
133 if !equal_bytes(
134 issuer.tbs().public_key().as_bytes(),
135 issuing_key.key().as_bytes(),
136 execution,
137 at,
138 )? {
139 return Ok(AuthorityBinding::Rejected(
140 AuthorityFailure::IssuerKeyBinding,
141 ));
142 }
143 if !equal_bytes(
144 self.signer().tbs().public_key().as_bytes(),
145 issuer.tbs().public_key().as_bytes(),
146 execution,
147 at,
148 )? || !self
149 .signer()
150 .tbs()
151 .subject()
152 .matches(issuer.tbs().subject(), execution)?
153 {
154 return Ok(AuthorityBinding::Rejected(AuthorityFailure::Signer));
155 }
156 if !equal_key(self.key(), issuing_key, execution, at)? {
157 return Ok(AuthorityBinding::Rejected(AuthorityFailure::EffectiveKey));
158 }
159 if !signing_usage(issuer, execution)? {
160 return Ok(AuthorityBinding::Rejected(AuthorityFailure::KeyUsage));
161 }
162 Ok(AuthorityBinding::Bound(ScopedResponse {
163 signed: self,
164 issuer,
165 source: AuthoritySource::Issuer,
166 }))
167 }
168
169 pub fn bind_delegate(
172 self,
173 facts: DelegateFacts<'a>,
174 execution: &Memory,
175 ) -> Result<AuthorityBinding<'r, 'a>>
176 where
177 'a: 'r,
178 {
179 let at = self.response().span().start;
180 if !equal_bytes(
181 self.signer().as_bytes(),
182 facts.responder().as_bytes(),
183 execution,
184 at,
185 )? {
186 return Ok(AuthorityBinding::Rejected(AuthorityFailure::Signer));
187 }
188 if !equal_key(self.key(), facts.key(), execution, at)? {
189 return Ok(AuthorityBinding::Rejected(AuthorityFailure::EffectiveKey));
190 }
191 Ok(AuthorityBinding::Bound(ScopedResponse {
192 signed: self,
193 issuer: facts.issuer(),
194 source: AuthoritySource::Delegate {
195 revocation: facts.revocation(),
196 },
197 }))
198 }
199
200 #[must_use]
205 pub fn trust_for_issuer(self, issuer: &'r Certificate<'a>) -> ScopedResponse<'r, 'a> {
206 ScopedResponse {
207 signed: self,
208 issuer,
209 source: AuthoritySource::Configured,
210 }
211 }
212}