2020-10-04 22:22:29 +08:00
|
|
|
use byteorder::{ByteOrder, NetworkEndian, BigEndian};
|
|
|
|
use num_enum::IntoPrimitive;
|
|
|
|
use num_enum::TryFromPrimitive;
|
|
|
|
use core::convert::TryFrom;
|
2020-10-11 13:46:24 +08:00
|
|
|
use core::convert::TryInto;
|
2020-10-04 22:22:29 +08:00
|
|
|
|
|
|
|
#[derive(Debug, PartialEq, Eq, Clone, Copy, IntoPrimitive, TryFromPrimitive)]
|
|
|
|
#[repr(u8)]
|
|
|
|
pub(crate) enum TlsContentType {
|
2020-10-11 13:46:24 +08:00
|
|
|
#[num_enum(default)]
|
2020-10-04 22:22:29 +08:00
|
|
|
Invalid = 0,
|
|
|
|
ChangeCipherSpec = 20,
|
|
|
|
Alert = 21,
|
|
|
|
Handshake = 22,
|
|
|
|
ApplicationData = 23
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, PartialEq, Eq, Clone, Copy, IntoPrimitive, TryFromPrimitive)]
|
|
|
|
#[repr(u16)]
|
|
|
|
pub(crate) enum TlsVersion {
|
2020-10-11 13:46:24 +08:00
|
|
|
#[num_enum(default)]
|
|
|
|
Unknown = 0x0000,
|
2020-10-04 22:22:29 +08:00
|
|
|
Tls10 = 0x0301,
|
|
|
|
Tls11 = 0x0302,
|
|
|
|
Tls12 = 0x0303,
|
|
|
|
Tls13 = 0x0304,
|
|
|
|
}
|
|
|
|
|
2020-10-11 13:46:24 +08:00
|
|
|
#[derive(Debug, Clone, Copy)]
|
|
|
|
pub(crate) struct TlsRepr<'a> {
|
2020-10-04 22:22:29 +08:00
|
|
|
pub(crate) content_type: TlsContentType,
|
|
|
|
pub(crate) version: TlsVersion,
|
|
|
|
pub(crate) length: u16,
|
|
|
|
pub(crate) payload: Option<&'a[u8]>,
|
2020-10-11 13:46:24 +08:00
|
|
|
pub(crate) handshake: Option<HandshakeRepr<'a>>
|
2020-10-04 22:22:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, PartialEq, Eq, Clone, Copy, IntoPrimitive, TryFromPrimitive)]
|
|
|
|
#[repr(u8)]
|
|
|
|
pub(crate) enum HandshakeType {
|
2020-10-11 13:46:24 +08:00
|
|
|
#[num_enum(default)]
|
|
|
|
Unknown = 0,
|
2020-10-04 22:22:29 +08:00
|
|
|
ClientHello = 1,
|
|
|
|
ServerHello = 2,
|
|
|
|
NewSessionTicket = 4,
|
|
|
|
EndOfEarlyData = 5,
|
|
|
|
EncryptedExtensions = 8,
|
|
|
|
Certificate = 11,
|
|
|
|
CertificateRequest = 13,
|
|
|
|
CertificateVerify = 15,
|
|
|
|
Finished = 20,
|
|
|
|
KeyUpdate = 24,
|
|
|
|
MessageHash = 254,
|
|
|
|
}
|
|
|
|
|
2020-10-11 13:46:24 +08:00
|
|
|
#[derive(Debug, Clone, Copy)]
|
|
|
|
pub(crate) struct HandshakeRepr<'a> {
|
2020-10-04 22:22:29 +08:00
|
|
|
pub(crate) msg_type: HandshakeType,
|
|
|
|
pub(crate) length: u32,
|
2020-10-11 13:46:24 +08:00
|
|
|
pub(crate) handshake_data: HandshakeData<'a>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a, 'b> HandshakeRepr<'a> {
|
|
|
|
pub(crate) fn get_length(&self) -> u16 {
|
|
|
|
let mut length :u16 = 1; // Handshake Type
|
|
|
|
length += 3; // Length of Handshake data
|
|
|
|
length += u16::try_from(self.handshake_data.get_length()).unwrap();
|
|
|
|
length
|
|
|
|
}
|
2020-10-04 22:22:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, PartialEq, Eq, Clone, Copy, IntoPrimitive, TryFromPrimitive)]
|
|
|
|
#[repr(u16)]
|
|
|
|
pub(crate) enum CipherSuite {
|
|
|
|
TLS_AES_128_GCM_SHA256 = 0x1301,
|
|
|
|
TLS_AES_256_GCM_SHA384 = 0x1302,
|
|
|
|
TLS_CHACHA20_POLY1305_SHA256 = 0x1303,
|
|
|
|
TLS_AES_128_CCM_SHA256 = 0x1304,
|
|
|
|
TLS_AES_128_CCM_8_SHA256 = 0x1305,
|
|
|
|
}
|
|
|
|
|
2020-10-11 13:46:24 +08:00
|
|
|
#[derive(Debug, Clone, Copy)]
|
|
|
|
pub(crate) struct ClientHello<'a> {
|
2020-10-04 22:22:29 +08:00
|
|
|
pub(crate) version: TlsVersion, // Legacy: Must be Tls12 (0x0303)
|
|
|
|
pub(crate) random: [u8; 32],
|
|
|
|
pub(crate) session_id_length: u8, // Legacy: Keep it 32
|
|
|
|
pub(crate) session_id: [u8; 32], // Legacy: Fill this with an unpredictable value
|
|
|
|
pub(crate) cipher_suites_length: u16,
|
|
|
|
pub(crate) cipher_suites: &'a[CipherSuite],
|
|
|
|
pub(crate) compression_method_length: u8, // Legacy: Must be 1, to contain a byte
|
|
|
|
pub(crate) compression_methods: u8, // Legacy: Must be 1 byte of 0
|
|
|
|
pub(crate) extension_length: u16,
|
2020-10-11 13:46:24 +08:00
|
|
|
pub(crate) extensions: &'a[Extension<'a>],
|
2020-10-04 22:22:29 +08:00
|
|
|
}
|
|
|
|
|
2020-10-11 13:46:24 +08:00
|
|
|
#[derive(Debug, Clone, Copy)]
|
|
|
|
pub(crate) enum HandshakeData<'a> {
|
2020-10-04 22:22:29 +08:00
|
|
|
Uninitialized,
|
2020-10-11 13:46:24 +08:00
|
|
|
ClientHello(ClientHello<'a>),
|
|
|
|
ServerHello(ServerHello<'a>),
|
2020-10-04 22:22:29 +08:00
|
|
|
}
|
|
|
|
|
2020-10-11 13:46:24 +08:00
|
|
|
impl<'a> HandshakeData<'a> {
|
|
|
|
pub(crate) fn get_length(&self) -> u32 {
|
|
|
|
match self {
|
|
|
|
HandshakeData::ClientHello(data) => data.get_length(),
|
|
|
|
HandshakeData::ServerHello(data) => todo!(),
|
|
|
|
_ => 0,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> ClientHello<'a> {
|
2020-10-04 22:22:29 +08:00
|
|
|
pub(crate) fn get_length(&self) -> u32 {
|
|
|
|
let mut length :u32 = 2; // TlsVersion size
|
|
|
|
length += 32; // Random size
|
|
|
|
length += 1; // Legacy session_id length size
|
|
|
|
length += 32; // Legacy session_id size
|
|
|
|
length += 2; // Cipher_suites_length size
|
|
|
|
length += (self.cipher_suites.len() as u32) * 2;
|
|
|
|
length += 1;
|
|
|
|
length += 1;
|
|
|
|
length += 2;
|
|
|
|
for extension in self.extensions.iter() {
|
|
|
|
length += (extension.get_length() as u32);
|
|
|
|
}
|
|
|
|
length
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-11 13:46:24 +08:00
|
|
|
#[derive(Debug, Clone, Copy)]
|
|
|
|
pub(crate) struct ServerHello<'a> {
|
2020-10-04 22:22:29 +08:00
|
|
|
pub(crate) version: TlsVersion,
|
2020-10-11 13:46:24 +08:00
|
|
|
pub(crate) random: &'a[u8],
|
2020-10-04 22:22:29 +08:00
|
|
|
pub(crate) session_id_echo_length: u8,
|
2020-10-11 13:46:24 +08:00
|
|
|
pub(crate) session_id_echo: &'a[u8],
|
2020-10-04 22:22:29 +08:00
|
|
|
pub(crate) cipher_suite: CipherSuite,
|
|
|
|
pub(crate) compression_method: u8, // Always 0
|
|
|
|
pub(crate) extension_length: u16,
|
2020-10-11 13:46:24 +08:00
|
|
|
pub(crate) extensions: &'a[Extension<'a>],
|
2020-10-04 22:22:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, PartialEq, Eq, Clone, Copy, IntoPrimitive, TryFromPrimitive)]
|
|
|
|
#[repr(u16)]
|
|
|
|
pub(crate) enum ExtensionType {
|
|
|
|
ServerName = 0,
|
|
|
|
MaxFragmentLength = 1,
|
|
|
|
StatusRequest = 5,
|
|
|
|
SupportedGroups = 10,
|
|
|
|
SignatureAlgorithms = 13,
|
|
|
|
UseSRTP = 14,
|
|
|
|
Heartbeat = 15,
|
|
|
|
ApplicationLayerProtocolNegotiation = 16,
|
|
|
|
SignedCertificateTimestamp = 18,
|
|
|
|
ClientCertificateType = 19,
|
|
|
|
ServerCertificateType = 20,
|
|
|
|
Padding = 21,
|
|
|
|
PreSharedKey = 41,
|
|
|
|
EarlyData = 42,
|
|
|
|
SupportedVersions = 43,
|
|
|
|
Cookie = 44,
|
|
|
|
PSKKeyExchangeModes = 45,
|
|
|
|
CertificateAuthorities = 47,
|
|
|
|
OIDFilters = 48,
|
|
|
|
PostHandshakeAuth = 49,
|
|
|
|
SignatureAlgorithmsCert = 50,
|
|
|
|
KeyShare = 51,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ExtensionType {
|
|
|
|
pub(crate) fn get_length(&self) -> u16 {
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-11 13:46:24 +08:00
|
|
|
#[derive(Debug, Clone, Copy)]
|
2020-10-04 22:22:29 +08:00
|
|
|
pub(crate) struct Extension<'a> {
|
|
|
|
pub(crate) extension_type: ExtensionType,
|
|
|
|
pub(crate) length: u16,
|
|
|
|
pub(crate) extension_data: &'a[u8],
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> Extension<'a> {
|
|
|
|
pub(crate) fn get_length(&self) -> u16 {
|
|
|
|
self.extension_type.get_length() + 2 + (self.extension_data.len() as u16)
|
|
|
|
}
|
|
|
|
}
|