Skip to main content

structured_xades/material/credentials/
scope.rs

1//! Whole incorporation or one exact earlier archive's original coverage.
2
3use super::{Error, Missing};
4use crate::Xades;
5use crate::binary::Location;
6use crate::material::{Archived, Index};
7use crate::xml::{Access, Xml};
8use structured_asn1::memory::{HashWork, Memory, Work};
9use structured_ltv::material::{ArchiveError, ArtifactRef, Coverage};
10use structured_ltv::timestamp::{Purpose, TimestampRequirements, TimestampScope, Verified};
11
12/// Optional original archive coverage; only these constructors expose it.
13/// The check verifies its source/role/property against the source-derived scope
14/// BEFORE handler calls. A whole-signature check cannot impersonate an archive.
15pub struct Scope<'a, N: HashWork, D, G, C: Work = Memory> {
16    archive: Option<Archive<'a, N, D, G, C>>,
17}
18
19type Archive<'a, N, D, G, C> = (
20    &'a Coverage<N, D, G, C, Xades>,
21    &'a Verified<N, D, G, Xades>,
22);
23
24impl<N: HashWork, D, G> Scope<'_, N, D, G> {
25    /// Whole-signature incorporation, with no archive implication.
26    #[must_use]
27    pub fn whole() -> Self {
28        Self { archive: None }
29    }
30}
31
32impl<'a, N: HashWork, D, G, C: Work> Scope<'a, N, D, G, C> {
33    /// Exact selected archive input and its private mathematical token receipt.
34    #[must_use]
35    pub fn before_archive(
36        coverage: &'a Coverage<N, D, G, C, Xades>,
37        evidence: &'a Verified<N, D, G, Xades>,
38    ) -> Self {
39        Self {
40            archive: Some((coverage, evidence)),
41        }
42    }
43}
44
45impl<N: Copy + Eq + HashWork, D: Copy + Eq, G: Copy + Eq, C: Work> Scope<'_, N, D, G, C> {
46    pub(super) fn require<X: Xml<Id = N, Document = D, Generation = G>, W: Work, Q: Work, PE>(
47        &self,
48        required: &TimestampRequirements<N, D, G, Xades>,
49        index: &Index<'_, N, D, G, W>,
50        access: &Access<'_, X, Q>,
51    ) -> Result<(), Error<X::Error, PE, N>> {
52        let location = required.scope().location();
53        let node = location.node;
54        if location.snapshot != access.snapshot() {
55            return Err(Error::Foreign { node });
56        }
57        index
58            .require_signature(required.signature(), access)
59            .map_err(Error::Index)?;
60        match (required.scope(), self.archive) {
61            (TimestampScope::All(_), None) => Ok(()),
62            (TimestampScope::BeforeArchive(_), Some((coverage, evidence))) => {
63                if evidence.purpose() != Purpose::Archive
64                    || evidence.token().snapshot != location.snapshot
65                    || !access
66                        .equal_id(evidence.signature(), required.signature())
67                        .map_err(|cause| Error::Resource { node, cause })?
68                    || !access
69                        .equal_id(evidence.property(), node)
70                        .map_err(|cause| Error::Resource { node, cause })?
71                {
72                    return Err(Error::Foreign { node });
73                }
74                coverage
75                    .require_evidence(evidence, node, access)
76                    .map_err(|cause| Error::Archive(ArchiveError::Coverage(cause)))
77            }
78            _ => Err(Error::Foreign { node }),
79        }
80    }
81
82    pub(super) fn known<X: Xml<Id = N, Document = D, Generation = G>, W: Work, Q: Work, PE>(
83        &self,
84        need: ArtifactRef<'_, '_>,
85        index: &Index<'_, N, D, G, W>,
86        access: &Access<'_, X, Q>,
87    ) -> Result<Option<Missing>, Error<X::Error, PE, N>> {
88        if let Some((coverage, evidence)) = self.archive {
89            return index
90                .archived(need, coverage, evidence, access)
91                .map(|value| match value {
92                    Archived::Present(_) => None,
93                    Archived::Missing => Some(Missing::Absent),
94                    Archived::Uncovered => Some(Missing::Uncovered),
95                })
96                .map_err(Error::Archive);
97        }
98        let mut copies = index.artifact(need, access).map_err(Error::Index)?;
99        copies
100            .next()
101            .transpose()
102            .map(|value| {
103                if value.is_some() {
104                    None
105                } else {
106                    Some(Missing::Absent)
107                }
108            })
109            .map_err(Error::Index)
110    }
111
112    pub(super) fn open<X: Xml<Id = N, Document = D, Generation = G>, Q: Work, PE>(
113        &self,
114        location: Location<N, D, G>,
115        access: &Access<'_, X, Q>,
116    ) -> Result<Option<Missing>, Error<X::Error, PE, N>> {
117        if let Some((coverage, evidence)) = self.archive {
118            return coverage
119                .covers(evidence, location.node, access)
120                .map(|covered| {
121                    if covered {
122                        None
123                    } else {
124                        Some(Missing::Uncovered)
125                    }
126                })
127                .map_err(|cause| Error::Archive(ArchiveError::Coverage(cause)));
128        }
129        Ok(None)
130    }
131}