use crate::Octets;
use core::cmp::Ordering;
use structured_asn1::digest::Resolution;
use structured_asn1::memory::Work;
use structured_asn1::{Encoding, Reader, Span};
use structured_pkix::AlgorithmIdentifier;
use structured_pkix::algorithm::digest::{self as asn_digest, Algorithm, AsnDigest};
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,
},
}
impl ImpliedDigest {
#[must_use]
pub const fn algorithm(self) -> Algorithm {
match self {
Self::EssSha1 => Algorithm::Sha1,
Self::EssV2Sha256 => Algorithm::Sha256,
}
}
}
pub(crate) fn resolve_digest<'a, P: AsnDigest<'a>>(
provider: &P,
algorithm: DigestAlgorithm<'_>,
parent: &Reader<'_>,
) -> crate::Result<Resolution<P::Identity>> {
match algorithm {
DigestAlgorithm::Written(identifier) => {
asn_digest::resolve(provider, &identifier, &parent.execution())
.map_err(crate::Error::pkix)
}
DigestAlgorithm::Implied { algorithm, .. } => {
Ok(asn_digest::supported(provider, algorithm.algorithm()))
}
}
}
#[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],
}
#[derive(Debug)]
pub struct Finished<'v, P, I, O> {
provider: &'v P,
identity: &'v I,
output: &'v O,
}
impl<P, I, O> Clone for Finished<'_, P, I, O> {
fn clone(&self) -> Self {
*self
}
}
impl<P, I, O> Copy for Finished<'_, P, I, O> {}
impl<'v, P, I, O: AsRef<[u8]>> Finished<'v, P, I, O> {
pub(crate) fn new(provider: &'v P, identity: &'v I, output: &'v O) -> Self {
Self {
provider,
identity,
output,
}
}
#[must_use]
pub fn from_provider(&self, provider: &P) -> bool {
core::ptr::eq(self.provider, provider)
}
#[must_use]
pub fn identity(&self) -> &'v I {
self.identity
}
#[must_use]
pub fn output(&self) -> &'v O {
self.output
}
}
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())
}
#[must_use]
pub fn finished(&self) -> Finished<'_, P, I, O> {
Finished {
provider: self.provider,
identity: &self.identity,
output: &self.output,
}
}
pub(crate) fn new(provider: &'p P, identity: I, output: O) -> Self {
Self {
provider,
identity,
output,
}
}
}
pub trait SignatureProvider<'a>: AsnDigest<'a> + Sized {
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>;
}