use std::io::Cursor;
use tls_codec::{Deserialize, TlsDeserialize, TlsSerialize, TlsSize};
use crate::handshake::{
ciphersuite::{responder::ResponderCiphersuite, traits::CiphersuiteBase, types::PQCiphertext},
HandshakeError,
};
pub(crate) const PSQ_MLDSA_CONTEXT: &[u8] = b"PSQ";
pub mod builder;
pub mod initiator;
pub mod responder;
pub mod traits;
pub mod types;
#[derive(TlsSize, TlsSerialize, TlsDeserialize, Clone, Copy, Debug, PartialEq)]
#[repr(u8)]
#[allow(non_camel_case_types)]
pub enum CiphersuiteName {
X25519_NONE_X25519_CHACHA20POLY1305_HKDFSHA256,
X25519_MLKEM768_X25519_CHACHA20POLY1305_HKDFSHA256,
X25519_CLASSICMCELIECE_X25519_CHACHA20POLY1305_HKDFSHA256,
X25519_NONE_X25519_AESGCM128_HKDFSHA256,
X25519_MLKEM768_X25519_AESGCM128_HKDFSHA256,
X25519_CLASSICMCELIECE_X25519_AESGCM128_HKDFSHA256,
X25519_NONE_ED25519_CHACHA20POLY1305_HKDFSHA256,
X25519_MLKEM768_ED25519_CHACHA20POLY1305_HKDFSHA256,
X25519_CLASSICMCELIECE_ED25519_CHACHA20POLY1305_HKDFSHA256,
X25519_NONE_ED25519_AESGCM128_HKDFSHA256,
X25519_MLKEM768_ED25519_AESGCM128_HKDFSHA256,
X25519_CLASSICMCELIECE_ED25519_AESGCM128_HKDFSHA256,
X25519_NONE_MLDSA65_CHACHA20POLY1305_HKDFSHA256,
X25519_MLKEM768_MLDSA65_CHACHA20POLY1305_HKDFSHA256,
X25519_CLASSICMCELIECE_MLDSA65_CHACHA20POLY1305_HKDFSHA256,
X25519_NONE_MLDSA65_AESGCM128_HKDFSHA256,
X25519_MLKEM768_MLDSA65_AESGCM128_HKDFSHA256,
X25519_CLASSICMCELIECE_MLDSA65_AESGCM128_HKDFSHA256,
}
impl CiphersuiteName {
pub(crate) fn query_ciphersuite() -> Self {
Self::X25519_NONE_X25519_CHACHA20POLY1305_HKDFSHA256
}
pub(crate) fn coerce_compatible(
&self,
responder_ciphersuite: &ResponderCiphersuite,
) -> Result<CiphersuiteName, HandshakeError> {
match (self, responder_ciphersuite.name()) {
(CiphersuiteName::X25519_NONE_X25519_CHACHA20POLY1305_HKDFSHA256, _) => {
Ok(CiphersuiteName::X25519_NONE_X25519_CHACHA20POLY1305_HKDFSHA256)
}
(CiphersuiteName::X25519_NONE_ED25519_CHACHA20POLY1305_HKDFSHA256, _) => {
Ok(CiphersuiteName::X25519_NONE_ED25519_CHACHA20POLY1305_HKDFSHA256)
}
(CiphersuiteName::X25519_NONE_MLDSA65_CHACHA20POLY1305_HKDFSHA256, _) => {
Ok(CiphersuiteName::X25519_NONE_MLDSA65_CHACHA20POLY1305_HKDFSHA256)
}
(CiphersuiteName::X25519_NONE_X25519_AESGCM128_HKDFSHA256, _) => {
Ok(CiphersuiteName::X25519_NONE_X25519_AESGCM128_HKDFSHA256)
}
(CiphersuiteName::X25519_NONE_ED25519_AESGCM128_HKDFSHA256, _) => {
Ok(CiphersuiteName::X25519_NONE_ED25519_AESGCM128_HKDFSHA256)
}
(CiphersuiteName::X25519_NONE_MLDSA65_AESGCM128_HKDFSHA256, _) => {
Ok(CiphersuiteName::X25519_NONE_MLDSA65_AESGCM128_HKDFSHA256)
}
(x, y) if *x == y => Ok(y).into(),
_ => Err(HandshakeError::UnsupportedCiphersuite),
}
}
pub(crate) fn deserialize_encapsulation(
&self,
bytes: &[u8],
) -> Result<Option<PQCiphertext>, HandshakeError> {
match self {
CiphersuiteName::X25519_NONE_X25519_CHACHA20POLY1305_HKDFSHA256
| CiphersuiteName::X25519_NONE_X25519_AESGCM128_HKDFSHA256
| CiphersuiteName::X25519_NONE_ED25519_CHACHA20POLY1305_HKDFSHA256
| CiphersuiteName::X25519_NONE_ED25519_AESGCM128_HKDFSHA256
| CiphersuiteName::X25519_NONE_MLDSA65_CHACHA20POLY1305_HKDFSHA256
| CiphersuiteName::X25519_NONE_MLDSA65_AESGCM128_HKDFSHA256 => Ok(None),
CiphersuiteName::X25519_MLKEM768_X25519_AESGCM128_HKDFSHA256
| CiphersuiteName::X25519_MLKEM768_MLDSA65_AESGCM128_HKDFSHA256
| CiphersuiteName::X25519_MLKEM768_X25519_CHACHA20POLY1305_HKDFSHA256
| CiphersuiteName::X25519_MLKEM768_ED25519_CHACHA20POLY1305_HKDFSHA256
| CiphersuiteName::X25519_MLKEM768_ED25519_AESGCM128_HKDFSHA256
| CiphersuiteName::X25519_MLKEM768_MLDSA65_CHACHA20POLY1305_HKDFSHA256 => {
let enc = Option::<PQCiphertext>::tls_deserialize(&mut Cursor::new(bytes))
.map_err(HandshakeError::Deserialize)?;
Ok(enc)
}
#[cfg(feature = "classic-mceliece")]
CiphersuiteName::X25519_CLASSICMCELIECE_ED25519_AESGCM128_HKDFSHA256
| CiphersuiteName::X25519_CLASSICMCELIECE_MLDSA65_CHACHA20POLY1305_HKDFSHA256
| CiphersuiteName::X25519_CLASSICMCELIECE_X25519_CHACHA20POLY1305_HKDFSHA256
| CiphersuiteName::X25519_CLASSICMCELIECE_MLDSA65_AESGCM128_HKDFSHA256
| CiphersuiteName::X25519_CLASSICMCELIECE_X25519_AESGCM128_HKDFSHA256
| CiphersuiteName::X25519_CLASSICMCELIECE_ED25519_CHACHA20POLY1305_HKDFSHA256 => {
use std::io::Cursor;
let enc = Option::<PQCiphertext>::tls_deserialize(&mut Cursor::new(bytes))
.map_err(HandshakeError::Deserialize)?;
Ok(enc)
}
#[cfg(not(feature = "classic-mceliece"))]
CiphersuiteName::X25519_CLASSICMCELIECE_ED25519_AESGCM128_HKDFSHA256
| CiphersuiteName::X25519_CLASSICMCELIECE_MLDSA65_CHACHA20POLY1305_HKDFSHA256
| CiphersuiteName::X25519_CLASSICMCELIECE_X25519_CHACHA20POLY1305_HKDFSHA256
| CiphersuiteName::X25519_CLASSICMCELIECE_MLDSA65_AESGCM128_HKDFSHA256
| CiphersuiteName::X25519_CLASSICMCELIECE_X25519_AESGCM128_HKDFSHA256
| CiphersuiteName::X25519_CLASSICMCELIECE_ED25519_CHACHA20POLY1305_HKDFSHA256 => {
Err(HandshakeError::UnsupportedCiphersuite)
}
}
}
}