use std::ops::Deref;
use libcrux_ed25519::VerificationKey as Ed25519VerificationKey;
use libcrux_kem::{MlKem768Ciphertext, MlKem768PrivateKey, MlKem768PublicKey};
use libcrux_ml_dsa::ml_dsa_65::{MLDSA65Signature, MLDSA65VerificationKey};
use libcrux_ml_kem::MlKemSharedSecret;
use tls_codec::{TlsDeserialize, TlsSerialize, TlsSerializeBytes, TlsSize};
#[cfg(feature = "classic-mceliece")]
use crate::classic_mceliece::{Ciphertext, PublicKey, SecretKey, SharedSecret};
use crate::handshake::{
ciphersuite::{initiator::Auth, PSQ_MLDSA_CONTEXT},
dhkem::DHPublicKey,
transcript::Transcript,
HandshakeError,
};
#[derive(Clone, TlsSize, TlsDeserialize, TlsSerialize)]
#[repr(u8)]
pub enum Authenticator {
Dh(DHPublicKey),
Sig(SignatureVerificationKey),
}
pub trait ProvideAuthenticator {
fn authenticator(&self) -> Authenticator;
}
impl ProvideAuthenticator for Ed25519VerificationKey {
fn authenticator(&self) -> Authenticator {
Authenticator::Sig(SignatureVerificationKey::Ed25519(*self))
}
}
impl ProvideAuthenticator for MLDSA65VerificationKey {
fn authenticator(&self) -> Authenticator {
Authenticator::Sig(SignatureVerificationKey::MlDsa65(Box::new(self.clone())))
}
}
impl From<Auth<'_>> for Authenticator {
fn from(value: Auth<'_>) -> Self {
match value {
Auth::DH(dhkey_pair) => Authenticator::Dh(dhkey_pair.pk),
Auth::Sig(sig_auth) => Authenticator::Sig(sig_auth.into()),
}
}
}
impl ProvideAuthenticator for SignatureVerificationKey {
fn authenticator(&self) -> Authenticator {
match &self {
SignatureVerificationKey::Ed25519(verification_key) => verification_key.authenticator(),
SignatureVerificationKey::MlDsa65(mldsaverification_key) => {
mldsaverification_key.deref().authenticator()
}
}
}
}
#[derive(TlsSize, TlsDeserialize, TlsSerialize, Clone)]
#[repr(u8)]
pub enum SignatureVerificationKey {
Ed25519(Ed25519VerificationKey),
MlDsa65(Box<MLDSA65VerificationKey>),
}
pub enum SignatureType {
Ed25519,
MlDsa,
}
impl SignatureVerificationKey {
pub(crate) fn verify(
&self,
tx1: &Transcript,
signature: &Signature,
) -> Result<(), HandshakeError> {
use tls_codec::SerializeBytes;
let payload = tx1.tls_serialize().map_err(HandshakeError::Serialize)?;
match (self, signature) {
(SignatureVerificationKey::Ed25519(verification_key), Signature::Ed25519(sig)) => {
libcrux_ed25519::verify(&payload, verification_key.as_ref(), sig)
.map_err(|e| e.into())
}
(
SignatureVerificationKey::MlDsa65(mldsaverification_key),
Signature::MlDsa65(mldsasignature),
) => libcrux_ml_dsa::ml_dsa_65::verify(
mldsaverification_key,
&payload,
PSQ_MLDSA_CONTEXT,
mldsasignature,
)
.map_err(|e| e.into()),
(SignatureVerificationKey::Ed25519(_), Signature::MlDsa65(_))
| (SignatureVerificationKey::MlDsa65(_), Signature::Ed25519(_)) => {
Err(HandshakeError::UnsupportedCiphersuite)
}
}
}
}
#[derive(TlsSize, TlsDeserialize, TlsSerialize)]
#[repr(u8)]
pub enum Signature {
Ed25519([u8; 64]),
MlDsa65(Box<MLDSA65Signature>),
}
#[derive(TlsSize, TlsDeserialize, TlsSerialize)]
#[repr(u8)]
pub enum PQCiphertext {
MlKem(Box<MlKem768Ciphertext>) = 1,
#[cfg(feature = "classic-mceliece")]
CMC(Box<Ciphertext>) = 2,
#[cfg(not(feature = "classic-mceliece"))]
CMC = 3,
}
#[derive(TlsSize, TlsSerialize)]
#[repr(u8)]
pub enum PQEncapsulationKey<'a> {
MlKem(&'a MlKem768PublicKey) = 1,
#[cfg(feature = "classic-mceliece")]
CMC(&'a PublicKey) = 2,
#[cfg(not(feature = "classic-mceliece"))]
CMC = 3,
}
impl<'a> From<&'a MlKem768PublicKey> for PQEncapsulationKey<'a> {
fn from(value: &'a MlKem768PublicKey) -> Self {
Self::MlKem(value)
}
}
#[cfg(feature = "classic-mceliece")]
impl<'a> From<&'a PublicKey> for PQEncapsulationKey<'a> {
fn from(value: &'a PublicKey) -> Self {
Self::CMC(value)
}
}
#[derive(TlsSize, TlsSerializeBytes)]
#[repr(u8)]
pub enum PQSharedSecret {
None,
MlKem(MlKemSharedSecret),
#[cfg(feature = "classic-mceliece")]
CMC(SharedSecret<'static>),
#[cfg(not(feature = "classic-mceliece"))]
CMC,
}
pub enum PQDecapsulationKey {
None,
MlKem(Box<MlKem768PrivateKey>),
#[cfg(feature = "classic-mceliece")]
CMC(Box<SecretKey>),
#[cfg(not(feature = "classic-mceliece"))]
CMC,
}