use crate::{
Buf,
BufError::{self},
BufMut, BufResult, Codec, Cursor,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(u16)]
pub enum CipherSuite {
TlsNullWithNullNull = 0x0000,
TlsRsaWithNullMd5 = 0x0001,
TlsRsaWithNullSha = 0x0002,
TlsRsaExportWithRc440Md5 = 0x0003,
TlsRsaWithRc4128Md5 = 0x0004,
TlsRsaWithRc4128Sha = 0x0005,
TlsRsaExportWithRc2Cbc40Md5 = 0x0006,
TlsRsaWithIdeaCbcSha = 0x0007,
TlsRsaExportWithDes40CbcSha = 0x0008,
TlsRsaWithDesCbcSha = 0x0009,
TlsRsaWith3desEdeCbcSha = 0x000A,
TlsDhDssExportWithDes40CbcSha = 0x000B,
TlsDhDssWithDesCbcSha = 0x000C,
TlsDhDssWith3desEdeCbcSha = 0x000D,
TlsDhRsaExportWithDes40CbcSha = 0x000E,
TlsDhRsaWithDesCbcSha = 0x000F,
TlsDhRsaWith3desEdeCbcSha = 0x0010,
TlsDheDssExportWithDes40CbcSha = 0x0011,
TlsDheDssWithDesCbcSha = 0x0012,
TlsDheDssWith3desEdeCbcSha = 0x0013,
TlsDheRsaExportWithDes40CbcSha = 0x0014,
TlsDheRsaWithDesCbcSha = 0x0015,
TlsDheRsaWith3desEdeCbcSha = 0x0016,
TlsDhAnonExportWithRc440Md5 = 0x0017,
TlsDhAnonWithRc4128Md5 = 0x0018,
TlsDhAnonExportWithDes40CbcSha = 0x0019,
TlsDhAnonWithDesCbcSha = 0x001A,
TlsDhAnonWith3desEdeCbcSha = 0x001B,
}
impl Codec for CipherSuite {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
let bytes = (*self as u16).to_be_bytes();
bytes.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
let bytes = <[u8; 2]>::decode(reader, ())?;
let val = u16::from_be_bytes(bytes);
Self::try_from(val).map_err(|_| BufError::UnexpectedValue)
}
}
impl TryFrom<u16> for CipherSuite {
type Error = ();
fn try_from(value: u16) -> Result<Self, Self::Error> {
match value {
0x0000 => Ok(Self::TlsNullWithNullNull),
0x0001 => Ok(Self::TlsRsaWithNullMd5),
0x0002 => Ok(Self::TlsRsaWithNullSha),
0x0003 => Ok(Self::TlsRsaExportWithRc440Md5),
0x0004 => Ok(Self::TlsRsaWithRc4128Md5),
0x0005 => Ok(Self::TlsRsaWithRc4128Sha),
0x0006 => Ok(Self::TlsRsaExportWithRc2Cbc40Md5),
0x0007 => Ok(Self::TlsRsaWithIdeaCbcSha),
0x0008 => Ok(Self::TlsRsaExportWithDes40CbcSha),
0x0009 => Ok(Self::TlsRsaWithDesCbcSha),
0x000A => Ok(Self::TlsRsaWith3desEdeCbcSha),
0x000B => Ok(Self::TlsDhDssExportWithDes40CbcSha),
0x000C => Ok(Self::TlsDhDssWithDesCbcSha),
0x000D => Ok(Self::TlsDhDssWith3desEdeCbcSha),
0x000E => Ok(Self::TlsDhRsaExportWithDes40CbcSha),
0x000F => Ok(Self::TlsDhRsaWithDesCbcSha),
0x0010 => Ok(Self::TlsDhRsaWith3desEdeCbcSha),
0x0011 => Ok(Self::TlsDheDssExportWithDes40CbcSha),
0x0012 => Ok(Self::TlsDheDssWithDesCbcSha),
0x0013 => Ok(Self::TlsDheDssWith3desEdeCbcSha),
0x0014 => Ok(Self::TlsDheRsaExportWithDes40CbcSha),
0x0015 => Ok(Self::TlsDheRsaWithDesCbcSha),
0x0016 => Ok(Self::TlsDheRsaWith3desEdeCbcSha),
0x0017 => Ok(Self::TlsDhAnonExportWithRc440Md5),
0x0018 => Ok(Self::TlsDhAnonWithRc4128Md5),
0x0019 => Ok(Self::TlsDhAnonExportWithDes40CbcSha),
0x001A => Ok(Self::TlsDhAnonWithDesCbcSha),
0x001B => Ok(Self::TlsDhAnonWith3desEdeCbcSha),
_ => Err(()),
}
}
}
#[cfg(test)]
mod tests {
use core::fmt::Debug;
use super::CipherSuite;
use crate::{Codec, Cursor};
fn codec_roundtrip<T: Codec<C> + Debug + Eq, C: Copy>(
etalon_struct: T,
etalon_bytes: &[u8],
context: C,
) {
let mut encoded_bytes = vec![];
{
let writer = &mut Cursor::new(&mut encoded_bytes);
etalon_struct.encode(writer, context).unwrap();
}
assert_eq!(etalon_bytes, &encoded_bytes);
let decoded_struct = {
let reader = &mut Cursor::new(&mut encoded_bytes);
T::decode(reader, context).unwrap()
};
assert_eq!(etalon_struct, decoded_struct);
encoded_bytes.fill(0x00);
{
let writer = &mut Cursor::new(&mut encoded_bytes);
decoded_struct.encode(writer, context).unwrap();
}
assert_eq!(etalon_bytes, &encoded_bytes);
}
#[test]
fn cipher_suite() {
let etalon_bytes = &[0x00, 0x0A];
let etalon_struct = CipherSuite::TlsRsaWith3desEdeCbcSha;
codec_roundtrip(etalon_struct, etalon_bytes, ());
}
}