use crate::handshake::ShakeBuf;
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[repr(transparent)]
pub struct TurtlsCipherList {
pub(crate) suites: u8,
}
impl TurtlsCipherList {
pub const TURTLS_CHA_CHA_POLY1305_SHA256: u8 = 0b00000001;
pub const TURTLS_AES_128_GCM_SHA256: u8 = 0b00000010;
pub(crate) const LEN_SIZE: usize = 2;
pub(crate) const fn len(&self) -> usize {
self.suites.count_ones() as usize * size_of::<CipherSuite>()
}
pub(crate) fn write_to(&self, buf: &mut ShakeBuf) {
if self.suites & Self::TURTLS_CHA_CHA_POLY1305_SHA256 > 0 {
buf.extend_from_slice(&CipherSuite::ChaCha20Poly1305Sha256.to_be_bytes());
}
if self.suites & Self::TURTLS_AES_128_GCM_SHA256 > 0 {
buf.extend_from_slice(&CipherSuite::Aes128GcmSha256.to_be_bytes());
}
}
pub(crate) fn parse_singular(suite: [u8; size_of::<CipherSuite>()]) -> Self {
match suite {
x if x == CipherSuite::Aes128GcmSha256.as_int().to_be_bytes() => Self {
suites: Self::TURTLS_AES_128_GCM_SHA256,
},
x if x == CipherSuite::ChaCha20Poly1305Sha256.as_int().to_be_bytes() => Self {
suites: Self::TURTLS_CHA_CHA_POLY1305_SHA256,
},
_ => Self { suites: 0 },
}
}
}
impl Default for TurtlsCipherList {
fn default() -> Self {
Self {
suites: Self::TURTLS_CHA_CHA_POLY1305_SHA256 | Self::TURTLS_AES_128_GCM_SHA256,
}
}
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[repr(u16)]
pub(crate) enum CipherSuite {
Aes128GcmSha256 = 0x1301,
#[expect(unused, reason = "AES_256_GCM_SHA384 is not supported")]
Aes256GcmSha384 = 0x1302,
ChaCha20Poly1305Sha256 = 0x1303,
#[expect(unused, reason = "AES_128_CCM_SHA256 is not supported")]
Aes128CcmSha256 = 0x1304,
#[expect(unused, reason = "AES_128_CCM8_SHA256 is not supported")]
Aes128Ccm8Sha256 = 0x1305,
}
impl CipherSuite {
pub(crate) const fn as_int(self) -> u16 {
self as u16
}
pub(crate) const fn to_be_bytes(self) -> [u8; 2] {
self.as_int().to_be_bytes()
}
}