use crate::Octets;
use core::cmp::Ordering;
use structured_asn1::memory::Work;
use structured_asn1::{Encoding, Reader, Span};
use structured_pkix::AlgorithmIdentifier;
use structured_pkix::path::WorkingKey;
mod session;
pub use session::ProviderSession;
pub(crate) fn require_instance<P>(_: &P, field: &'static str, at: u64) -> crate::Result<()> {
if core::mem::size_of::<P>() == 0 {
return Err(crate::Error::schema(
crate::ErrorCode::ProviderMismatch,
field,
at,
));
}
Ok(())
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ImpliedDigest {
EssSha1,
EssV2Sha256,
}
#[derive(Debug, Clone, Copy)]
pub enum DigestAlgorithm<'a> {
Written(AlgorithmIdentifier<'a>),
Implied {
algorithm: ImpliedDigest,
field: &'static str,
span: Span,
},
}
#[derive(Debug)]
pub enum Resolution<T> {
Supported(T),
Unsupported,
Malformed,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SignatureAnswer {
Valid,
Invalid,
}
#[derive(Debug)]
pub enum SignatureMode<T> {
Raw(T),
Prehashed(T),
}
#[derive(Debug)]
pub struct Finalized<'p, P, I, O> {
provider: &'p P,
identity: I,
output: O,
}
#[derive(Debug)]
pub struct Prehash<'i, 'o, P, I> {
provider: &'i P,
identity: &'i I,
bytes: &'o [u8],
}
impl<'i, 'o, P, I> Prehash<'i, 'o, P, I> {
pub(crate) fn new(provider: &'i P, identity: &'i I, bytes: &'o [u8]) -> Self {
Self {
provider,
identity,
bytes,
}
}
#[must_use]
pub fn from_provider(&self, provider: &P) -> bool {
core::ptr::eq(self.provider, provider)
}
#[must_use]
pub fn identity(&self) -> &'i I {
self.identity
}
#[must_use]
pub fn as_bytes(&self) -> &'o [u8] {
self.bytes
}
}
impl<'p, P, I, O: AsRef<[u8]>> Finalized<'p, P, I, O> {
#[must_use]
pub fn identity(&self) -> &I {
&self.identity
}
#[must_use]
pub fn as_bytes(&self) -> &[u8] {
self.output.as_ref()
}
#[must_use]
pub fn prehash(&self) -> Prehash<'_, '_, P, I> {
Prehash::new(self.provider, &self.identity, self.output.as_ref())
}
pub(crate) fn new(provider: &'p P, identity: I, output: O) -> Self {
Self {
provider,
identity,
output,
}
}
}
pub trait DigestProvider<'a>: Sized {
type Error;
type Identity;
type State;
type Output: AsRef<[u8]>;
fn resolve_digest(
&'a self,
identifier: DigestAlgorithm<'a>,
encoding: Encoding,
parent: &Reader<'a>,
) -> core::result::Result<Resolution<Self::Identity>, Self::Error>;
fn compare_digest<W: Work>(
&self,
left: &Self::Identity,
right: &Self::Identity,
execution: &W,
) -> core::result::Result<Ordering, Self::Error>;
fn digest_width(&self, identity: &Self::Identity) -> Option<usize>;
fn start_digest<W: Work>(
&'a self,
identity: &Self::Identity,
execution: &W,
) -> core::result::Result<Self::State, Self::Error>;
fn update_digest<W: Work>(
&self,
state: &mut Self::State,
bytes: &[u8],
execution: &W,
) -> core::result::Result<(), Self::Error>;
fn finish_digest<W: Work>(
&self,
state: Self::State,
execution: &W,
) -> core::result::Result<Self::Output, Self::Error>;
fn matches_digest<W: Work>(
&self,
digest: Prehash<'_, '_, Self, Self::Identity>,
expected: &[u8],
execution: &W,
) -> core::result::Result<bool, Self::Error>;
}
pub trait SignatureProvider<'a>: DigestProvider<'a> {
type SignatureIdentity;
type RawState;
fn resolve_signature(
&'a self,
identifier: AlgorithmIdentifier<'a>,
digest: &Self::Identity,
key: WorkingKey<'a>,
encoding: Encoding,
parent: &Reader<'a>,
) -> core::result::Result<Resolution<SignatureMode<Self::SignatureIdentity>>, Self::Error>;
fn compare_signature<W: Work>(
&self,
left: &Self::SignatureIdentity,
right: &Self::SignatureIdentity,
execution: &W,
) -> core::result::Result<Ordering, Self::Error>;
fn start_raw<W: Work>(
&'a self,
identity: &Self::SignatureIdentity,
key: WorkingKey<'a>,
signature: &'a Octets<'a>,
execution: &W,
) -> core::result::Result<Self::RawState, Self::Error>;
fn update_raw<W: Work>(
&self,
state: &mut Self::RawState,
bytes: &[u8],
execution: &W,
) -> core::result::Result<(), Self::Error>;
fn finish_raw<W: Work>(
&self,
state: Self::RawState,
execution: &W,
) -> core::result::Result<SignatureAnswer, Self::Error>;
fn verify_prehashed<W: Work>(
&'a self,
identity: &Self::SignatureIdentity,
key: WorkingKey<'a>,
signature: &Octets<'a>,
digest: Prehash<'_, '_, Self, Self::Identity>,
execution: &W,
) -> core::result::Result<SignatureAnswer, Self::Error>;
}