use super::{
DigestAlgorithm, DigestProvider, Prehash, Resolution, SignatureAnswer, SignatureMode,
SignatureProvider,
};
use crate::Octets;
use core::cmp::Ordering;
use structured_asn1::{Encoding, Reader, memory::Work};
use structured_pkix::{AlgorithmIdentifier, path::WorkingKey};
#[derive(Debug)]
pub struct ProviderSession<P> {
backend: P,
marker: u8,
}
impl<P> ProviderSession<P> {
#[must_use]
pub const fn new(backend: P) -> Self {
Self { backend, marker: 0 }
}
#[must_use]
pub const fn backend(&self) -> &P {
&self.backend
}
#[must_use]
pub fn same_session(&self, other: &Self) -> bool {
core::ptr::eq(
core::ptr::from_ref(&self.marker),
core::ptr::from_ref(&other.marker),
)
}
}
impl<P> core::ops::Deref for ProviderSession<P> {
type Target = P;
fn deref(&self) -> &P {
self.backend()
}
}
impl<'a, P: DigestProvider<'a>> DigestProvider<'a> for ProviderSession<P> {
type Error = P::Error;
type Identity = P::Identity;
type State = P::State;
type Output = P::Output;
fn resolve_digest(
&'a self,
algorithm: DigestAlgorithm<'a>,
encoding: Encoding,
parent: &Reader<'a>,
) -> Result<Resolution<Self::Identity>, Self::Error> {
self.backend.resolve_digest(algorithm, encoding, parent)
}
fn compare_digest<W: Work>(
&self,
left: &Self::Identity,
right: &Self::Identity,
work: &W,
) -> Result<Ordering, Self::Error> {
self.backend.compare_digest(left, right, work)
}
fn digest_width(&self, identity: &Self::Identity) -> Option<usize> {
self.backend.digest_width(identity)
}
fn start_digest<W: Work>(
&'a self,
identity: &Self::Identity,
work: &W,
) -> Result<Self::State, Self::Error> {
self.backend.start_digest(identity, work)
}
fn update_digest<W: Work>(
&self,
state: &mut Self::State,
bytes: &[u8],
work: &W,
) -> Result<(), Self::Error> {
self.backend.update_digest(state, bytes, work)
}
fn finish_digest<W: Work>(
&self,
state: Self::State,
work: &W,
) -> Result<Self::Output, Self::Error> {
self.backend.finish_digest(state, work)
}
fn matches_digest<W: Work>(
&self,
digest: Prehash<'_, '_, Self, Self::Identity>,
expected: &[u8],
work: &W,
) -> Result<bool, Self::Error> {
self.backend.matches_digest(
Prehash::new(&self.backend, digest.identity(), digest.as_bytes()),
expected,
work,
)
}
}
impl<'a, P: SignatureProvider<'a>> SignatureProvider<'a> for ProviderSession<P> {
type SignatureIdentity = P::SignatureIdentity;
type RawState = P::RawState;
fn resolve_signature(
&'a self,
algorithm: AlgorithmIdentifier<'a>,
digest: &Self::Identity,
key: WorkingKey<'a>,
encoding: Encoding,
parent: &Reader<'a>,
) -> Result<Resolution<SignatureMode<Self::SignatureIdentity>>, Self::Error> {
self.backend
.resolve_signature(algorithm, digest, key, encoding, parent)
}
fn compare_signature<W: Work>(
&self,
left: &Self::SignatureIdentity,
right: &Self::SignatureIdentity,
work: &W,
) -> Result<Ordering, Self::Error> {
self.backend.compare_signature(left, right, work)
}
fn start_raw<W: Work>(
&'a self,
identity: &Self::SignatureIdentity,
key: WorkingKey<'a>,
signature: &'a Octets<'a>,
work: &W,
) -> Result<Self::RawState, Self::Error> {
self.backend.start_raw(identity, key, signature, work)
}
fn update_raw<W: Work>(
&self,
state: &mut Self::RawState,
bytes: &[u8],
work: &W,
) -> Result<(), Self::Error> {
self.backend.update_raw(state, bytes, work)
}
fn finish_raw<W: Work>(
&self,
state: Self::RawState,
work: &W,
) -> Result<SignatureAnswer, Self::Error> {
self.backend.finish_raw(state, work)
}
fn verify_prehashed<W: Work>(
&'a self,
identity: &Self::SignatureIdentity,
key: WorkingKey<'a>,
signature: &Octets<'a>,
digest: Prehash<'_, '_, Self, Self::Identity>,
work: &W,
) -> Result<SignatureAnswer, Self::Error> {
self.backend.verify_prehashed(
identity,
key,
signature,
Prehash::new(&self.backend, digest.identity(), digest.as_bytes()),
work,
)
}
}