1use crate::{
4 content::Content,
5 error::Error as ArchiveError,
6 payload::Payload,
7 zip::{Member, MemberId, ReadFailure},
8};
9use structured_asn1::{
10 Reader,
11 memory::{OwnedVec, Work},
12 range::RangeSource,
13};
14use structured_cms::{
15 SignedData,
16 prepare::ResolvedSigner,
17 provider::SignatureProvider,
18 verify::{CheckError, Checked, ContentMode, DocumentBatch, DocumentChecks, PassError},
19};
20use structured_pkix::{Certificate, algorithm::digest::AsnDigest};
21
22pub struct Challenge<'a, P: SignatureProvider<'a>> {
24 pub message: &'a SignedData<'a>,
26 pub parent: &'a Reader<'a>,
28 pub provider: &'a P,
30 pub requests: OwnedVec<ResolvedSigner<'a, P>>,
32}
33
34#[derive(Debug)]
36pub enum Error<SE, PE, D, G> {
37 MissingSigner(structured_asn1::Span),
40 Archive(ArchiveError<SE>),
42 Source(ReadFailure<SE, D, G>),
44 Prepare(CheckError<PE>),
46 Pass(PassError<ReadFailure<SE, D, G>, PE>),
48}
49
50pub struct Checks<'a, 'v, 's, S: RangeSource> {
53 content: &'a Content<'v, 's, S>,
54 payload: MemberId<S::Document, S::Generation>,
55 inner: DocumentChecks<'a>,
56}
57
58impl<'v, 's, S: RangeSource> Content<'v, 's, S> {
59 pub async fn check_cades<'a, P: SignatureProvider<'a>>(
63 &'a self,
64 challenge: Challenge<'a, P>,
65 payload: &impl Payload<'v, 's, S>,
66 ) -> Result<Checks<'a, 'v, 's, S>, Error<S::Error, P::Error, S::Document, S::Generation>> {
67 let execution = challenge.parent.execution();
68 self.require(challenge.message, challenge.parent, &execution)
69 .map_err(Error::Archive)?;
70 let refusal = |cause| Error::Archive(crate::error::resource(self.enclosure(), cause));
74 let mut selected = execution.map();
75 for request in &challenge.requests {
76 challenge
77 .message
78 .require_signer(request.signer(), "asic.signerInfos")
79 .map_err(|cause| Error::Prepare(CheckError::Processing(cause)))?;
80 selected
81 .try_insert(request.signer().element().index(), ())
82 .map_err(refusal)?;
83 }
84 for signer in challenge.message.signers() {
85 if selected
86 .get(&signer.element().index(), &execution)
87 .map_err(refusal)?
88 .is_none()
89 {
90 return Err(Error::MissingSigner(signer.span()));
91 }
92 }
93 drop(selected);
94 if !core::ptr::eq(self.member().archive(), payload.member().archive()) {
95 return Err(Error::Archive(ArchiveError::Foreign {
96 range: self.enclosure(),
97 }));
98 }
99 let mut source = payload.source(&execution).map_err(Error::Source)?;
100 let batch = DocumentBatch::prepare(
101 challenge.provider,
102 challenge.message,
103 challenge.requests,
104 ContentMode::Detached,
105 challenge.parent,
106 )
107 .map_err(Error::Prepare)?;
108 let checks = batch
109 .run_detached_async(&mut source)
110 .await
111 .map_err(Error::Pass)?;
112 self.member()
113 .archive()
114 .admit(&execution, self.enclosure())
115 .map_err(Error::Archive)?;
116 Ok(Checks {
117 content: self,
118 payload: payload.member().id(),
119 inner: checks,
120 })
121 }
122}
123
124#[derive(Debug)]
126pub enum BindError<SE, PE> {
127 Archive(ArchiveError<SE>),
129 Cades(structured_cades::basic::BindError<PE>),
131}
132
133pub struct Signer<'r, 'm, 'd, 'p, 'v, 's, S: RangeSource> {
136 member: Member<'v, 's, S>,
137 payload: MemberId<S::Document, S::Generation>,
138 inner: structured_cades::basic::SignerBinding<'r, 'm, 'd, 'p>,
139}
140
141impl<'a, 'v, 's, S: RangeSource> Checks<'a, 'v, 's, S> {
142 #[must_use]
144 pub fn checks(&self) -> &DocumentChecks<'a> {
145 &self.inner
146 }
147 #[must_use]
149 pub fn payload(&self) -> MemberId<S::Document, S::Generation> {
150 self.payload
151 }
152 pub fn bind<'provider, 'r, 'm, 'd, 'p, P: AsnDigest<'provider>>(
156 &self,
157 prepared: &'r structured_cades::prepare::Preparation<'m, 'd>,
158 checked: &Checked<'_>,
159 certificate: &'p Certificate<'d>,
160 path: Option<&'p structured_ltv::pki::CheckedPath<'d>>,
161 provider: &'provider P,
162 parent: &Reader<'provider>,
163 ) -> Result<Signer<'r, 'm, 'd, 'p, 'v, 's, S>, BindError<S::Error, P::Error>>
164 where
165 'd: 'provider,
166 {
167 let execution = parent.execution();
168 self.content
169 .require(self.inner.message(), parent, &execution)
170 .map_err(BindError::Archive)?;
171 let inner = structured_cades::basic::bind(
172 prepared,
173 &self.inner,
174 checked,
175 certificate,
176 path,
177 provider,
178 parent,
179 )
180 .map_err(BindError::Cades)?;
181 let member = self
182 .content
183 .member()
184 .archive()
185 .original(self.content.member().id(), &execution)
186 .map_err(BindError::Archive)?;
187 Ok(Signer {
188 member,
189 payload: self.payload,
190 inner,
191 })
192 }
193}
194
195pub struct Assessment<'a, 'm, 'd, E, D, G> {
198 signature: MemberId<D, G>,
199 payload: MemberId<D, G>,
200 inner: structured_cades::baseline::Assessment<'a, 'm, 'd, E>,
201}
202
203#[derive(Debug)]
205pub enum LevelError<E> {
206 Archive(ArchiveError<E>),
208 Foreign,
210 Cades(structured_cades::baseline::LevelError),
212}
213
214pub type LevelResult<'a, 'm, 'd, E, S> = Result<
216 Assessment<'a, 'm, 'd, E, <S as RangeSource>::Document, <S as RangeSource>::Generation>,
217 LevelError<<S as RangeSource>::Error>,
218>;
219
220impl<'r, 'm, 'd, 'p, S: RangeSource> Signer<'r, 'm, 'd, 'p, '_, '_, S> {
221 #[must_use]
224 pub fn inner(&self) -> &structured_cades::basic::SignerBinding<'r, 'm, 'd, 'p> {
225 &self.inner
226 }
227 pub fn assess<'e, E>(
230 &'e self,
231 evidence: structured_cades::baseline::Evidence<'e, 'm, 'd, E>,
232 operation: &Reader<'_>,
233 ) -> LevelResult<'e, 'm, 'd, E, S> {
234 self.member
235 .archive()
236 .admit(&operation.execution(), self.member.central_span())
237 .map_err(LevelError::Archive)?;
238 let binding = match &evidence {
239 structured_cades::baseline::Evidence::Basic(basic) => basic.binding(),
240 structured_cades::baseline::Evidence::Timestamped(timed) => timed.basic().binding(),
241 structured_cades::baseline::Evidence::LongTerm(long)
242 | structured_cades::baseline::Evidence::Archival {
243 long_term: long, ..
244 } => long.timed().basic().binding(),
245 };
246 if !core::ptr::eq(
247 core::ptr::from_ref(binding).cast::<()>(),
248 core::ptr::from_ref(&self.inner).cast::<()>(),
249 ) {
250 return Err(LevelError::Foreign);
251 }
252 let inner =
253 structured_cades::baseline::assess(evidence, operation).map_err(LevelError::Cades)?;
254 Ok(Assessment {
255 signature: self.member.id(),
256 payload: self.payload,
257 inner,
258 })
259 }
260}
261
262impl<'a, 'm, 'd, E, D: Copy, G: Copy> Assessment<'a, 'm, 'd, E, D, G> {
263 #[must_use]
265 pub fn signature(&self) -> MemberId<D, G> {
266 self.signature
267 }
268 #[must_use]
270 pub fn payload(&self) -> MemberId<D, G> {
271 self.payload
272 }
273 #[must_use]
275 pub fn cades(&self) -> &structured_cades::baseline::Assessment<'a, 'm, 'd, E> {
276 &self.inner
277 }
278}