structured_cms/timestamp/
requested.rs1use super::imprint_check::{ResolveError, Resolved};
4use super::{ImprintAgreement, MessageImprint};
5use crate::Error;
6use crate::provider::DigestProvider;
7use core::cmp::Ordering;
8use structured_asn1::{Reader, Span};
9
10#[derive(Debug)]
12pub enum RequestedContentError<SE, PE> {
13 Request(RequestImprintError<PE>),
15 Content(super::ImprintError<SE, PE>),
17}
18
19#[derive(Debug, Clone, Copy, PartialEq, Eq)]
21pub enum ImprintOperand {
22 Token,
24 Requested,
26}
27
28#[derive(Debug, Clone, Copy, PartialEq, Eq)]
30pub enum RequestAgreement {
31 Matches,
33 AlgorithmDiffers,
35 HashDiffers,
37 Unusable {
39 operand: ImprintOperand,
41 reason: ImprintAgreement,
43 },
44}
45
46#[derive(Debug)]
48pub enum RequestImprintError<E> {
49 Processing {
51 operand: ImprintOperand,
53 source: Error,
55 },
56 Callback {
58 operand: ImprintOperand,
60 span: Span,
62 source: E,
64 },
65}
66
67impl<'a> MessageImprint<'a> {
68 pub fn check_requested_content<P: DigestProvider<'a>, S: crate::stream::Source>(
74 &self,
75 requested: &MessageImprint<'a>,
76 provider: &'a P,
77 parents: (&Reader<'a>, &Reader<'a>),
78 covered: &mut S,
79 ) -> Result<(ImprintAgreement, RequestAgreement), RequestedContentError<S::Error, P::Error>>
80 {
81 let (token_parent, requested_parent) = parents;
82 preflight(self, requested, token_parent, requested_parent)
83 .map_err(RequestedContentError::Request)?;
84 let token = match resolve(self, provider, token_parent, ImprintOperand::Token)
85 .map_err(RequestedContentError::Request)?
86 {
87 Resolved::Ready(identity) => identity,
88 Resolved::Unusable(reason) => {
89 return Ok((
90 reason,
91 RequestAgreement::Unusable {
92 operand: ImprintOperand::Token,
93 reason,
94 },
95 ));
96 }
97 };
98 let agreement = compare_resolved(
99 self,
100 requested,
101 provider,
102 token_parent,
103 requested_parent,
104 &token,
105 )
106 .map_err(RequestedContentError::Request)?;
107 let content = self
108 .compute(provider, token_parent, covered, token)
109 .map_err(RequestedContentError::Content)?;
110 Ok((content, agreement))
111 }
112 pub fn matches_request<P: DigestProvider<'a>>(
127 &self,
128 requested: &MessageImprint<'a>,
129 provider: &'a P,
130 token_parent: &Reader<'a>,
131 requested_parent: &Reader<'a>,
132 ) -> Result<RequestAgreement, RequestImprintError<P::Error>> {
133 preflight(self, requested, token_parent, requested_parent)?;
134 let token = match resolve(self, provider, token_parent, ImprintOperand::Token)? {
135 Resolved::Ready(identity) => identity,
136 Resolved::Unusable(reason) => {
137 return Ok(RequestAgreement::Unusable {
138 operand: ImprintOperand::Token,
139 reason,
140 });
141 }
142 };
143 compare_resolved(
144 self,
145 requested,
146 provider,
147 token_parent,
148 requested_parent,
149 &token,
150 )
151 }
152}
153
154fn preflight<E>(
155 token: &MessageImprint<'_>,
156 requested: &MessageImprint<'_>,
157 token_parent: &Reader<'_>,
158 requested_parent: &Reader<'_>,
159) -> Result<(), RequestImprintError<E>> {
160 for (operand, imprint, parent) in [
162 (ImprintOperand::Token, token, token_parent),
163 (ImprintOperand::Requested, requested, requested_parent),
164 ] {
165 imprint
166 .require_session(parent)
167 .map_err(|source| RequestImprintError::Processing { operand, source })?;
168 }
169 Ok(())
170}
171
172fn compare_resolved<'a, P: DigestProvider<'a>>(
173 token_imprint: &MessageImprint<'a>,
174 requested: &MessageImprint<'a>,
175 provider: &'a P,
176 token_parent: &Reader<'a>,
177 requested_parent: &Reader<'a>,
178 token: &P::Identity,
179) -> Result<RequestAgreement, RequestImprintError<P::Error>> {
180 let asked = match resolve(
181 requested,
182 provider,
183 requested_parent,
184 ImprintOperand::Requested,
185 )? {
186 Resolved::Ready(identity) => identity,
187 Resolved::Unusable(reason) => {
188 return Ok(RequestAgreement::Unusable {
189 operand: ImprintOperand::Requested,
190 reason,
191 });
192 }
193 };
194 let execution = token_parent.execution();
195 if provider
196 .compare_digest(token, &asked, &execution)
197 .map_err(|source| RequestImprintError::Callback {
198 operand: ImprintOperand::Token,
199 span: token_imprint.span(),
200 source,
201 })?
202 != Ordering::Equal
203 {
204 return Ok(RequestAgreement::AlgorithmDiffers);
205 }
206 let matches = token_imprint
207 .hashed()
208 .same_value(
209 requested.hashed(),
210 token_parent,
211 "tstInfo.messageImprint.hashedMessage",
212 token_imprint.hashed().span().start,
213 )
214 .map_err(|source| RequestImprintError::Processing {
215 operand: ImprintOperand::Token,
216 source,
217 })?;
218 Ok(if matches {
219 RequestAgreement::Matches
220 } else {
221 RequestAgreement::HashDiffers
222 })
223}
224
225fn resolve<'a, P: DigestProvider<'a>>(
226 imprint: &MessageImprint<'a>,
227 provider: &'a P,
228 parent: &Reader<'a>,
229 operand: ImprintOperand,
230) -> Result<Resolved<P::Identity>, RequestImprintError<P::Error>> {
231 imprint
232 .resolve(provider, parent)
233 .map_err(|error| match error {
234 ResolveError::Processing(source) => RequestImprintError::Processing { operand, source },
235 ResolveError::Callback(source) => RequestImprintError::Callback {
236 operand,
237 span: imprint.span(),
238 source,
239 },
240 })
241}