use std::fmt;
use serde::{Deserialize, Serialize};
use crate::error::SmimeError;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[non_exhaustive]
pub enum RecipientIdentifier {
IssuerAndSerialNumber {
issuer_der: Vec<u8>,
serial: Vec<u8>,
},
SubjectKeyIdentifier(Vec<u8>),
}
impl fmt::Display for RecipientIdentifier {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
RecipientIdentifier::IssuerAndSerialNumber { issuer_der, serial } => {
write!(
f,
"IssuerAndSerial(issuer={} bytes, serial=",
issuer_der.len()
)?;
for (i, b) in serial.iter().enumerate() {
if i > 0 {
write!(f, ":")?;
}
write!(f, "{b:02x}")?;
}
write!(f, ")")
}
RecipientIdentifier::SubjectKeyIdentifier(ski) => {
write!(f, "SubjectKeyIdentifier(")?;
for (i, b) in ski.iter().enumerate() {
if i > 0 {
write!(f, ":")?;
}
write!(f, "{b:02x}")?;
}
write!(f, ")")
}
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[non_exhaustive]
pub enum EcCurve {
P256,
P384,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[non_exhaustive]
pub enum KeyEncryptionAlgorithm {
RsaPkcs1v15,
RsaOaep,
EcdhEs { curve: EcCurve },
}
impl fmt::Display for KeyEncryptionAlgorithm {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
KeyEncryptionAlgorithm::RsaPkcs1v15 => f.write_str("RSA-PKCS1v15"),
KeyEncryptionAlgorithm::RsaOaep => f.write_str("RSA-OAEP"),
KeyEncryptionAlgorithm::EcdhEs { curve } => match curve {
EcCurve::P256 => f.write_str("ECDH-ES/P-256"),
EcCurve::P384 => f.write_str("ECDH-ES/P-384"),
},
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[non_exhaustive]
pub enum KeyWrapAlgorithm {
Aes128Kw,
Aes256Kw,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[non_exhaustive]
pub enum KariKeyAgreement {
StdDhSha256Kdf,
StdDhSha384Kdf,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct KariAlgorithm {
pub key_agreement: KariKeyAgreement,
pub key_wrap: KeyWrapAlgorithm,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[non_exhaustive]
pub enum DigestAlgorithm {
Sha256,
Sha384,
Sha512,
}
impl fmt::Display for DigestAlgorithm {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
DigestAlgorithm::Sha256 => f.write_str("sha-256"),
DigestAlgorithm::Sha384 => f.write_str("sha-384"),
DigestAlgorithm::Sha512 => f.write_str("sha-512"),
}
}
}
pub trait DecryptionKey {
fn decrypt_cek(
&self,
encrypted_key: &[u8],
algorithm: &KeyEncryptionAlgorithm,
) -> Result<Vec<u8>, SmimeError>;
fn matches_recipient(&self, id: &RecipientIdentifier) -> bool;
fn agree_ecdh(
&self,
ephemeral_public_key_bytes: &[u8],
ukm: Option<&[u8]>,
enc_cek: &[u8],
alg: &KariAlgorithm,
) -> Result<Vec<u8>, SmimeError> {
let _ = (ephemeral_public_key_bytes, ukm, enc_cek, alg);
Err(SmimeError::UnsupportedAlgorithm(
"KARI (ECDH key agreement) not supported by this key".into(),
))
}
fn supported_key_enc_algorithm(&self) -> Option<KeyEncryptionAlgorithm> {
None
}
}
pub trait RevocationChecker {
fn check(&self, cert: &x509_cert::Certificate) -> Result<(), SmimeError>;
}
pub struct NoRevocationCheck;
impl RevocationChecker for NoRevocationCheck {
fn check(&self, _cert: &x509_cert::Certificate) -> Result<(), SmimeError> {
Ok(())
}
}
pub trait SigningKey {
fn sign(&self, data: &[u8], algorithm: &DigestAlgorithm) -> Result<Vec<u8>, SmimeError>;
fn certificate(&self) -> &x509_cert::Certificate;
fn preferred_digest_algorithm(&self) -> Option<DigestAlgorithm> {
None
}
}