Skip to main content

structured_cms/provider/
session.rs

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