Skip to main content

structured_cms/provider/
session.rs

1//! Stable selection ownership, including zero-sized backend adapters.
2
3use super::{
4    DigestAlgorithm, DigestProvider, Prehash, Resolution, SignatureAnswer, SignatureMode,
5    SignatureProvider,
6};
7use crate::Octets;
8use core::cmp::Ordering;
9use structured_asn1::{Encoding, Reader, memory::Work};
10use structured_pkix::{AlgorithmIdentifier, path::WorkingKey};
11
12/// One explicitly selected backend session with stable nonzero-sized ownership.
13///
14/// This owns the adapter, not a global registry or cryptographic engine. A
15/// borrowed adapter may itself hold the caller's existing engine/policy. Its
16/// address remains stable while finalized outputs or challenges borrow it.
17/// Distinct selections remain distinct even for zero-sized stateless adapters.
18/// There is no implicit Clone, allocation or synchronization requirement.
19#[derive(Debug)]
20pub struct ProviderSession<P> {
21    backend: P,
22    marker: u8,
23}
24
25impl<P> ProviderSession<P> {
26    /// Creates a distinct selection owner before resolving any document input.
27    #[must_use]
28    pub const fn new(backend: P) -> Self {
29        Self { backend, marker: 0 }
30    }
31    /// The selected adapter; this accessor does not transfer session provenance.
32    #[must_use]
33    pub const fn backend(&self) -> &P {
34        &self.backend
35    }
36    /// Identity of the live selection owner, even when both adapters are ZSTs.
37    #[must_use]
38    pub fn same_session(&self, other: &Self) -> bool {
39        core::ptr::eq(
40            core::ptr::from_ref(&self.marker),
41            core::ptr::from_ref(&other.marker),
42        )
43    }
44}
45
46impl<P> core::ops::Deref for ProviderSession<P> {
47    type Target = P;
48    fn deref(&self) -> &P {
49        self.backend()
50    }
51}
52
53impl<'a, P: DigestProvider<'a>> DigestProvider<'a> for ProviderSession<P> {
54    type Error = P::Error;
55    type Identity = P::Identity;
56    type State = P::State;
57    type Output = P::Output;
58    fn resolve_digest(
59        &'a self,
60        algorithm: DigestAlgorithm<'a>,
61        encoding: Encoding,
62        parent: &Reader<'a>,
63    ) -> Result<Resolution<Self::Identity>, Self::Error> {
64        self.backend.resolve_digest(algorithm, encoding, parent)
65    }
66    fn compare_digest<W: Work>(
67        &self,
68        left: &Self::Identity,
69        right: &Self::Identity,
70        work: &W,
71    ) -> Result<Ordering, Self::Error> {
72        self.backend.compare_digest(left, right, work)
73    }
74    fn digest_width(&self, identity: &Self::Identity) -> Option<usize> {
75        self.backend.digest_width(identity)
76    }
77    fn start_digest<W: Work>(
78        &'a self,
79        identity: &Self::Identity,
80        work: &W,
81    ) -> Result<Self::State, Self::Error> {
82        self.backend.start_digest(identity, work)
83    }
84    fn update_digest<W: Work>(
85        &self,
86        state: &mut Self::State,
87        bytes: &[u8],
88        work: &W,
89    ) -> Result<(), Self::Error> {
90        self.backend.update_digest(state, bytes, work)
91    }
92    fn finish_digest<W: Work>(
93        &self,
94        state: Self::State,
95        work: &W,
96    ) -> Result<Self::Output, Self::Error> {
97        self.backend.finish_digest(state, work)
98    }
99    fn matches_digest<W: Work>(
100        &self,
101        digest: Prehash<'_, '_, Self, Self::Identity>,
102        expected: &[u8],
103        work: &W,
104    ) -> Result<bool, Self::Error> {
105        // Common processing verifies session provenance before dispatch. The
106        // engine receives a view under the same adapter that created the state.
107        self.backend.matches_digest(
108            Prehash::new(&self.backend, digest.identity(), digest.as_bytes()),
109            expected,
110            work,
111        )
112    }
113}
114
115impl<'a, P: SignatureProvider<'a>> SignatureProvider<'a> for ProviderSession<P> {
116    type SignatureIdentity = P::SignatureIdentity;
117    type RawState = P::RawState;
118    fn resolve_signature(
119        &'a self,
120        algorithm: AlgorithmIdentifier<'a>,
121        digest: &Self::Identity,
122        key: WorkingKey<'a>,
123        encoding: Encoding,
124        parent: &Reader<'a>,
125    ) -> Result<Resolution<SignatureMode<Self::SignatureIdentity>>, Self::Error> {
126        self.backend
127            .resolve_signature(algorithm, digest, key, encoding, parent)
128    }
129    fn compare_signature<W: Work>(
130        &self,
131        left: &Self::SignatureIdentity,
132        right: &Self::SignatureIdentity,
133        work: &W,
134    ) -> Result<Ordering, Self::Error> {
135        self.backend.compare_signature(left, right, work)
136    }
137    fn start_raw<W: Work>(
138        &'a self,
139        identity: &Self::SignatureIdentity,
140        key: WorkingKey<'a>,
141        signature: &'a Octets<'a>,
142        work: &W,
143    ) -> Result<Self::RawState, Self::Error> {
144        self.backend.start_raw(identity, key, signature, work)
145    }
146    fn update_raw<W: Work>(
147        &self,
148        state: &mut Self::RawState,
149        bytes: &[u8],
150        work: &W,
151    ) -> Result<(), Self::Error> {
152        self.backend.update_raw(state, bytes, work)
153    }
154    fn finish_raw<W: Work>(
155        &self,
156        state: Self::RawState,
157        work: &W,
158    ) -> Result<SignatureAnswer, Self::Error> {
159        self.backend.finish_raw(state, work)
160    }
161    fn verify_prehashed<W: Work>(
162        &'a self,
163        identity: &Self::SignatureIdentity,
164        key: WorkingKey<'a>,
165        signature: &Octets<'a>,
166        digest: Prehash<'_, '_, Self, Self::Identity>,
167        work: &W,
168    ) -> Result<SignatureAnswer, Self::Error> {
169        self.backend.verify_prehashed(
170            identity,
171            key,
172            signature,
173            Prehash::new(&self.backend, digest.identity(), digest.as_bytes()),
174            work,
175        )
176    }
177}