use nom::bytes::streaming::{tag, take};
use nom::combinator::{complete, cond, map, map_parser, opt, verify};
use nom::error::{make_error, ErrorKind};
use nom::multi::{length_data, many0};
use nom::number::streaming::{be_u16, be_u32, be_u8};
use nom::{Err, IResult};
use nom_derive::Nom;
use rusticata_macros::newtype_enum;
use std::convert::From;
use crate::tls::{parse_tls_versions, TlsCipherSuiteID, TlsVersion};
use crate::tls_ec::{parse_named_groups, NamedGroup};
#[derive(Clone, Copy, Debug, PartialEq, Eq, Nom)]
pub struct TlsExtensionType(pub u16);
newtype_enum! {
impl display TlsExtensionType {
ServerName = 0,
MaxFragmentLength = 1,
ClientCertificate = 2,
TrustedCaKeys = 3,
TruncatedHMac = 4,
StatusRequest = 5,
UserMapping = 6,
ClientAuthz = 7,
ServerAuthz = 8,
CertType = 9,
SupportedGroups = 10,
EcPointFormats = 11,
Srp = 12,
SignatureAlgorithms = 13,
UseSrtp = 14,
Heartbeat = 15,
ApplicationLayerProtocolNegotiation = 16,
StatusRequestv2 = 17,
SignedCertificateTimestamp = 18,
ClientCertificateType = 19,
ServerCertificateType = 20,
Padding = 21,
EncryptThenMac = 22,
ExtendedMasterSecret = 23,
TokenBinding = 24,
CachedInfo = 25,
RecordSizeLimit = 28,
SessionTicketTLS = 35,
KeyShareOld = 40,
PreSharedKey = 41,
EarlyData = 42,
SupportedVersions = 43,
Cookie = 44,
PskExchangeModes = 45,
TicketEarlyDataInfo = 46,
CertificateAuthorities = 47,
OidFilters = 48,
PostHandshakeAuth = 49,
SigAlgorithmsCert = 50,
KeyShare = 51,
NextProtocolNegotiation = 13172,
Grease = 0xfafa,
RenegotiationInfo = 0xff01,
EncryptedServerName = 0xffce,
}
}
impl TlsExtensionType {
pub fn from_u16(t: u16) -> TlsExtensionType {
TlsExtensionType(t)
}
}
impl From<TlsExtensionType> for u16 {
fn from(ext: TlsExtensionType) -> u16 {
ext.0
}
}
#[derive(Clone, PartialEq)]
pub enum TlsExtension<'a> {
SNI(Vec<(SNIType, &'a [u8])>),
MaxFragmentLength(u8),
StatusRequest(Option<(CertificateStatusType, &'a [u8])>),
EllipticCurves(Vec<NamedGroup>),
EcPointFormats(&'a [u8]),
SignatureAlgorithms(Vec<u16>),
RecordSizeLimit(u16),
SessionTicket(&'a [u8]),
KeyShareOld(&'a [u8]),
KeyShare(&'a [u8]),
PreSharedKey(&'a [u8]),
EarlyData(Option<u32>),
SupportedVersions(Vec<TlsVersion>),
Cookie(&'a [u8]),
PskExchangeModes(Vec<u8>),
Heartbeat(u8),
ALPN(Vec<&'a [u8]>),
SignedCertificateTimestamp(Option<&'a [u8]>),
Padding(&'a [u8]),
EncryptThenMac,
ExtendedMasterSecret,
OidFilters(Vec<OidFilter<'a>>),
PostHandshakeAuth,
NextProtocolNegotiation,
RenegotiationInfo(&'a [u8]),
EncryptedServerName {
ciphersuite: TlsCipherSuiteID,
group: NamedGroup,
key_share: &'a [u8],
record_digest: &'a [u8],
encrypted_sni: &'a [u8],
},
Grease(u16, &'a [u8]),
Unknown(TlsExtensionType, &'a [u8]),
}
impl<'a> From<&'a TlsExtension<'a>> for TlsExtensionType {
#[rustfmt::skip]
fn from(ext: &TlsExtension) -> TlsExtensionType {
match *ext {
TlsExtension::SNI(_) => TlsExtensionType::ServerName,
TlsExtension::MaxFragmentLength(_) => TlsExtensionType::MaxFragmentLength,
TlsExtension::StatusRequest(_) => TlsExtensionType::StatusRequest,
TlsExtension::EllipticCurves(_) => TlsExtensionType::SupportedGroups,
TlsExtension::EcPointFormats(_) => TlsExtensionType::EcPointFormats,
TlsExtension::SignatureAlgorithms(_) => TlsExtensionType::SignatureAlgorithms,
TlsExtension::SessionTicket(_) => TlsExtensionType::SessionTicketTLS,
TlsExtension::RecordSizeLimit(_) => TlsExtensionType::RecordSizeLimit,
TlsExtension::KeyShareOld(_) => TlsExtensionType::KeyShareOld,
TlsExtension::KeyShare(_) => TlsExtensionType::KeyShare,
TlsExtension::PreSharedKey(_) => TlsExtensionType::PreSharedKey,
TlsExtension::EarlyData(_) => TlsExtensionType::EarlyData,
TlsExtension::SupportedVersions(_) => TlsExtensionType::SupportedVersions,
TlsExtension::Cookie(_) => TlsExtensionType::Cookie,
TlsExtension::PskExchangeModes(_) => TlsExtensionType::PskExchangeModes,
TlsExtension::Heartbeat(_) => TlsExtensionType::Heartbeat,
TlsExtension::ALPN(_) => TlsExtensionType::ApplicationLayerProtocolNegotiation,
TlsExtension::SignedCertificateTimestamp(_) => TlsExtensionType::SignedCertificateTimestamp,
TlsExtension::Padding(_) => TlsExtensionType::Padding,
TlsExtension::EncryptThenMac => TlsExtensionType::EncryptThenMac,
TlsExtension::ExtendedMasterSecret => TlsExtensionType::ExtendedMasterSecret,
TlsExtension::OidFilters(_) => TlsExtensionType::OidFilters,
TlsExtension::PostHandshakeAuth => TlsExtensionType::PostHandshakeAuth,
TlsExtension::NextProtocolNegotiation => TlsExtensionType::NextProtocolNegotiation,
TlsExtension::RenegotiationInfo(_) => TlsExtensionType::RenegotiationInfo,
TlsExtension::EncryptedServerName{..} => TlsExtensionType::EncryptedServerName,
TlsExtension::Grease(_,_) => TlsExtensionType::Grease,
TlsExtension::Unknown(x,_) => x
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct KeyShareEntry<'a> {
pub group: NamedGroup,
pub kx: &'a [u8],
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Nom)]
pub struct PskKeyExchangeMode(pub u8);
newtype_enum! {
impl PskKeyExchangeMode {
Psk = 0,
PskDhe = 1,
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Nom)]
pub struct SNIType(pub u8);
newtype_enum! {
impl display SNIType {
HostName = 0,
}
}
#[derive(Clone, Copy, PartialEq, Eq, Nom)]
pub struct CertificateStatusType(pub u8);
newtype_enum! {
impl debug CertificateStatusType {
OCSP = 1,
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct OidFilter<'a> {
pub cert_ext_oid: &'a [u8],
pub cert_ext_val: &'a [u8],
}
pub fn parse_tls_extension_sni_hostname(i: &[u8]) -> IResult<&[u8], (SNIType, &[u8])> {
let (i, t) = SNIType::parse(i)?;
let (i, v) = length_data(be_u16)(i)?;
Ok((i, (t, v)))
}
pub fn parse_tls_extension_sni_content(i: &[u8]) -> IResult<&[u8], TlsExtension> {
if i.is_empty() {
return Ok((i, TlsExtension::SNI(Vec::new())));
}
let (i, list_len) = be_u16(i)?;
let (i, v) = map_parser(
take(list_len),
many0(complete(parse_tls_extension_sni_hostname)),
)(i)?;
Ok((i, TlsExtension::SNI(v)))
}
pub fn parse_tls_extension_sni(i: &[u8]) -> IResult<&[u8], TlsExtension> {
let (i, _) = tag([0x00, 0x00])(i)?;
map_parser(length_data(be_u16), parse_tls_extension_sni_content)(i)
}
pub fn parse_tls_extension_max_fragment_length_content(i: &[u8]) -> IResult<&[u8], TlsExtension> {
map(be_u8, TlsExtension::MaxFragmentLength)(i)
}
pub fn parse_tls_extension_max_fragment_length(i: &[u8]) -> IResult<&[u8], TlsExtension> {
let (i, _) = tag([0x00, 0x01])(i)?;
map_parser(
length_data(be_u16),
parse_tls_extension_max_fragment_length_content,
)(i)
}
fn parse_tls_extension_status_request_content(
i: &[u8],
ext_len: u16,
) -> IResult<&[u8], TlsExtension> {
match ext_len {
0 => Ok((i, TlsExtension::StatusRequest(None))),
_ => {
let (i, status_type) = be_u8(i)?;
let (i, request) = take(ext_len - 1)(i)?;
Ok((
i,
TlsExtension::StatusRequest(Some((CertificateStatusType(status_type), request))),
))
}
}
}
pub fn parse_tls_extension_status_request(i: &[u8]) -> IResult<&[u8], TlsExtension> {
let (i, _) = tag([0x00, 0x05])(i)?;
let (i, ext_len) = be_u16(i)?;
map_parser(take(ext_len), move |d| {
parse_tls_extension_status_request_content(d, ext_len)
})(i)
}
pub fn parse_tls_extension_elliptic_curves_content(i: &[u8]) -> IResult<&[u8], TlsExtension> {
map_parser(
length_data(be_u16),
map(parse_named_groups, TlsExtension::EllipticCurves),
)(i)
}
pub fn parse_tls_extension_elliptic_curves(i: &[u8]) -> IResult<&[u8], TlsExtension> {
let (i, _) = tag([0x00, 0x0a])(i)?;
map_parser(
length_data(be_u16),
parse_tls_extension_elliptic_curves_content,
)(i)
}
pub fn parse_tls_extension_ec_point_formats_content(i: &[u8]) -> IResult<&[u8], TlsExtension> {
map(length_data(be_u8), TlsExtension::EcPointFormats)(i)
}
pub fn parse_tls_extension_ec_point_formats(i: &[u8]) -> IResult<&[u8], TlsExtension> {
let (i, _) = tag([0x00, 0x0a])(i)?;
map_parser(
length_data(be_u16),
parse_tls_extension_ec_point_formats_content,
)(i)
}
pub fn parse_tls_extension_signature_algorithms_content(i: &[u8]) -> IResult<&[u8], TlsExtension> {
let (i, l) = map_parser(length_data(be_u16), many0(complete(be_u16)))(i)?;
Ok((i, TlsExtension::SignatureAlgorithms(l)))
}
pub fn parse_tls_extension_signature_algorithms(i: &[u8]) -> IResult<&[u8], TlsExtension> {
let (i, _) = tag([0x00, 13])(i)?;
map_parser(
length_data(be_u16),
parse_tls_extension_signature_algorithms_content,
)(i)
}
pub fn parse_tls_extension_heartbeat_content(i: &[u8]) -> IResult<&[u8], TlsExtension> {
map(be_u8, TlsExtension::Heartbeat)(i)
}
pub fn parse_tls_extension_heartbeat(i: &[u8]) -> IResult<&[u8], TlsExtension> {
let (i, _) = tag([0x00, 0x0d])(i)?;
let (i, ext_len) = verify(be_u16, |&n| n == 1)(i)?;
map_parser(take(ext_len), parse_tls_extension_heartbeat_content)(i)
}
fn parse_protocol_name(i: &[u8]) -> IResult<&[u8], &[u8]> {
length_data(be_u8)(i)
}
pub fn parse_tls_extension_alpn_content(i: &[u8]) -> IResult<&[u8], TlsExtension> {
let (i, v) = map_parser(length_data(be_u16), many0(complete(parse_protocol_name)))(i)?;
Ok((i, TlsExtension::ALPN(v)))
}
fn parse_tls_extension_padding_content(i: &[u8], ext_len: u16) -> IResult<&[u8], TlsExtension> {
map(take(ext_len), TlsExtension::Padding)(i)
}
pub fn parse_tls_extension_signed_certificate_timestamp_content(
i: &[u8],
) -> IResult<&[u8], TlsExtension> {
map(
opt(complete(length_data(be_u16))),
TlsExtension::SignedCertificateTimestamp,
)(i)
}
fn parse_tls_extension_encrypt_then_mac_content(
i: &[u8],
ext_len: u16,
) -> IResult<&[u8], TlsExtension> {
if ext_len != 0 {
return Err(Err::Error(make_error(i, ErrorKind::Verify)));
}
Ok((i, TlsExtension::EncryptThenMac))
}
pub fn parse_tls_extension_encrypt_then_mac(i: &[u8]) -> IResult<&[u8], TlsExtension> {
let (i, _) = tag([0x00, 0x16])(i)?;
let (i, ext_len) = be_u16(i)?;
map_parser(take(ext_len), move |d| {
parse_tls_extension_encrypt_then_mac_content(d, ext_len)
})(i)
}
fn parse_tls_extension_extended_master_secret_content(
i: &[u8],
ext_len: u16,
) -> IResult<&[u8], TlsExtension> {
if ext_len != 0 {
return Err(Err::Error(make_error(i, ErrorKind::Verify)));
}
Ok((i, TlsExtension::ExtendedMasterSecret))
}
pub fn parse_tls_extension_extended_master_secret(i: &[u8]) -> IResult<&[u8], TlsExtension> {
let (i, _) = tag([0x00, 0x17])(i)?;
let (i, ext_len) = be_u16(i)?;
map_parser(take(ext_len), move |d| {
parse_tls_extension_extended_master_secret_content(d, ext_len)
})(i)
}
fn parse_tls_extension_record_size_limit(i: &[u8]) -> IResult<&[u8], TlsExtension> {
map(be_u16, TlsExtension::RecordSizeLimit)(i)
}
fn parse_tls_extension_session_ticket_content(
i: &[u8],
ext_len: u16,
) -> IResult<&[u8], TlsExtension> {
map(take(ext_len), TlsExtension::SessionTicket)(i)
}
pub fn parse_tls_extension_session_ticket(i: &[u8]) -> IResult<&[u8], TlsExtension> {
let (i, _) = tag([0x00, 0x23])(i)?;
let (i, ext_len) = be_u16(i)?;
map_parser(take(ext_len), move |d| {
parse_tls_extension_session_ticket_content(d, ext_len)
})(i)
}
fn parse_tls_extension_key_share_old_content(
i: &[u8],
ext_len: u16,
) -> IResult<&[u8], TlsExtension> {
map(take(ext_len), TlsExtension::KeyShareOld)(i)
}
fn parse_tls_extension_key_share_content(i: &[u8], ext_len: u16) -> IResult<&[u8], TlsExtension> {
map(take(ext_len), TlsExtension::KeyShare)(i)
}
pub fn parse_tls_extension_key_share(i: &[u8]) -> IResult<&[u8], TlsExtension> {
let (i, _) = tag([0x00, 0x33])(i)?;
let (i, ext_len) = be_u16(i)?;
map_parser(take(ext_len), move |d| {
parse_tls_extension_key_share_content(d, ext_len)
})(i)
}
fn parse_tls_extension_pre_shared_key_content(
i: &[u8],
ext_len: u16,
) -> IResult<&[u8], TlsExtension> {
map(take(ext_len), TlsExtension::PreSharedKey)(i)
}
pub fn parse_tls_extension_pre_shared_key(i: &[u8]) -> IResult<&[u8], TlsExtension> {
let (i, _) = tag([0x00, 0x28])(i)?;
let (i, ext_len) = be_u16(i)?;
map_parser(take(ext_len), move |d| {
parse_tls_extension_pre_shared_key_content(d, ext_len)
})(i)
}
fn parse_tls_extension_early_data_content(i: &[u8], ext_len: u16) -> IResult<&[u8], TlsExtension> {
map(cond(ext_len > 0, be_u32), TlsExtension::EarlyData)(i)
}
pub fn parse_tls_extension_early_data(i: &[u8]) -> IResult<&[u8], TlsExtension> {
let (i, _) = tag([0x00, 0x2a])(i)?;
let (i, ext_len) = be_u16(i)?;
map_parser(take(ext_len), move |d| {
parse_tls_extension_early_data_content(d, ext_len)
})(i)
}
fn parse_tls_extension_supported_versions_content(
i: &[u8],
ext_len: u16,
) -> IResult<&[u8], TlsExtension> {
if ext_len == 2 {
map(be_u16, |x| {
TlsExtension::SupportedVersions(vec![TlsVersion(x)])
})(i)
} else {
let (i, _) = be_u8(i)?;
if ext_len == 0 {
return Err(Err::Error(make_error(i, ErrorKind::Verify)));
}
let (i, l) = map_parser(take(ext_len - 1), parse_tls_versions)(i)?;
Ok((i, TlsExtension::SupportedVersions(l)))
}
}
pub fn parse_tls_extension_supported_versions(i: &[u8]) -> IResult<&[u8], TlsExtension> {
let (i, _) = tag([0x00, 0x2b])(i)?;
let (i, ext_len) = be_u16(i)?;
map_parser(take(ext_len), move |d| {
parse_tls_extension_supported_versions_content(d, ext_len)
})(i)
}
fn parse_tls_extension_cookie_content(i: &[u8], ext_len: u16) -> IResult<&[u8], TlsExtension> {
map(take(ext_len), TlsExtension::Cookie)(i)
}
pub fn parse_tls_extension_cookie(i: &[u8]) -> IResult<&[u8], TlsExtension> {
let (i, _) = tag([0x00, 0x2c])(i)?;
let (i, ext_len) = be_u16(i)?;
map_parser(take(ext_len), move |d| {
parse_tls_extension_cookie_content(d, ext_len)
})(i)
}
pub fn parse_tls_extension_psk_key_exchange_modes_content(
i: &[u8],
) -> IResult<&[u8], TlsExtension> {
let (i, v) = length_data(be_u8)(i)?;
Ok((i, TlsExtension::PskExchangeModes(v.to_vec())))
}
pub fn parse_tls_extension_psk_key_exchange_modes(i: &[u8]) -> IResult<&[u8], TlsExtension> {
let (i, _) = tag([0x00, 0x2d])(i)?;
let (i, ext_len) = be_u16(i)?;
map_parser(
take(ext_len),
parse_tls_extension_psk_key_exchange_modes_content,
)(i)
}
fn parse_tls_extension_npn_content(i: &[u8], ext_len: u16) -> IResult<&[u8], TlsExtension> {
if ext_len != 0 {
return Err(Err::Error(make_error(i, ErrorKind::Verify)));
}
Ok((i, TlsExtension::NextProtocolNegotiation))
}
pub fn parse_tls_extension_renegotiation_info_content(i: &[u8]) -> IResult<&[u8], TlsExtension> {
map(length_data(be_u8), TlsExtension::RenegotiationInfo)(i)
}
pub fn parse_tls_extension_encrypted_server_name(i: &[u8]) -> IResult<&[u8], TlsExtension> {
let (i, ciphersuite) = map(be_u16, TlsCipherSuiteID)(i)?;
let (i, group) = NamedGroup::parse(i)?;
let (i, key_share) = length_data(be_u16)(i)?;
let (i, record_digest) = length_data(be_u16)(i)?;
let (i, encrypted_sni) = length_data(be_u16)(i)?;
let esn = TlsExtension::EncryptedServerName {
ciphersuite,
group,
key_share,
record_digest,
encrypted_sni,
};
Ok((i, esn))
}
fn parse_tls_oid_filter(i: &[u8]) -> IResult<&[u8], OidFilter> {
let (i, cert_ext_oid) = length_data(be_u8)(i)?;
let (i, cert_ext_val) = length_data(be_u16)(i)?;
let filter = OidFilter {
cert_ext_oid,
cert_ext_val,
};
Ok((i, filter))
}
fn parse_tls_extension_oid_filters(i: &[u8]) -> IResult<&[u8], TlsExtension> {
let (i, v) = map_parser(length_data(be_u16), many0(complete(parse_tls_oid_filter)))(i)?;
Ok((i, TlsExtension::OidFilters(v)))
}
fn parse_tls_extension_post_handshake_auth_content(
i: &[u8],
ext_len: u16,
) -> IResult<&[u8], TlsExtension> {
if ext_len != 0 {
return Err(Err::Error(make_error(i, ErrorKind::Verify)));
}
Ok((i, TlsExtension::PostHandshakeAuth))
}
pub fn parse_tls_extension_unknown(i: &[u8]) -> IResult<&[u8], TlsExtension> {
let (i, ext_type) = be_u16(i)?;
let (i, ext_data) = length_data(be_u16)(i)?;
Ok((
i,
TlsExtension::Unknown(TlsExtensionType(ext_type), ext_data),
))
}
pub fn parse_tls_client_hello_extension(i: &[u8]) -> IResult<&[u8], TlsExtension> {
let (i, ext_type) = be_u16(i)?;
let (i, ext_data) = length_data(be_u16)(i)?;
if ext_type & 0x0f0f == 0x0a0a {
return Ok((i, TlsExtension::Grease(ext_type, ext_data)));
}
let ext_len = ext_data.len() as u16;
let (_, ext) = match ext_type {
0 => parse_tls_extension_sni_content(ext_data),
1 => parse_tls_extension_max_fragment_length_content(ext_data),
5 => parse_tls_extension_status_request_content(ext_data, ext_len),
10 => parse_tls_extension_elliptic_curves_content(ext_data),
11 => parse_tls_extension_ec_point_formats_content(ext_data),
13 => parse_tls_extension_signature_algorithms_content(ext_data),
15 => parse_tls_extension_heartbeat_content(ext_data),
16 => parse_tls_extension_alpn_content(ext_data),
18 => parse_tls_extension_signed_certificate_timestamp_content(ext_data),
21 => parse_tls_extension_padding_content(ext_data, ext_len),
22 => parse_tls_extension_encrypt_then_mac_content(ext_data, ext_len),
23 => parse_tls_extension_extended_master_secret_content(ext_data, ext_len),
28 => parse_tls_extension_record_size_limit(ext_data),
35 => parse_tls_extension_session_ticket_content(ext_data, ext_len),
41 => parse_tls_extension_pre_shared_key_content(ext_data, ext_len),
42 => parse_tls_extension_early_data_content(ext_data, ext_len),
43 => parse_tls_extension_supported_versions_content(ext_data, ext_len),
44 => parse_tls_extension_cookie_content(ext_data, ext_len),
45 => parse_tls_extension_psk_key_exchange_modes_content(ext_data),
48 => parse_tls_extension_oid_filters(ext_data),
49 => parse_tls_extension_post_handshake_auth_content(ext_data, ext_len),
51 => parse_tls_extension_key_share_content(ext_data, ext_len),
13172 => parse_tls_extension_npn_content(ext_data, ext_len),
0xff01 => parse_tls_extension_renegotiation_info_content(ext_data),
0xffce => parse_tls_extension_encrypted_server_name(ext_data),
_ => Ok((
i,
TlsExtension::Unknown(TlsExtensionType(ext_type), ext_data),
)),
}?;
Ok((i, ext))
}
pub fn parse_tls_server_hello_extension(i: &[u8]) -> IResult<&[u8], TlsExtension> {
let (i, ext_type) = be_u16(i)?;
let (i, ext_data) = length_data(be_u16)(i)?;
if ext_type & 0x0f0f == 0x0a0a {
return Ok((i, TlsExtension::Grease(ext_type, ext_data)));
}
let ext_len = ext_data.len() as u16;
let (_, ext) = match ext_type {
0 => parse_tls_extension_sni_content(ext_data),
1 => parse_tls_extension_max_fragment_length_content(ext_data),
5 => parse_tls_extension_status_request_content(ext_data, ext_len),
11 => parse_tls_extension_ec_point_formats_content(ext_data),
13 => parse_tls_extension_signature_algorithms_content(ext_data),
15 => parse_tls_extension_heartbeat_content(ext_data),
16 => parse_tls_extension_alpn_content(ext_data),
18 => parse_tls_extension_signed_certificate_timestamp_content(ext_data),
21 => parse_tls_extension_encrypt_then_mac_content(ext_data, ext_len),
23 => parse_tls_extension_extended_master_secret_content(ext_data, ext_len),
28 => parse_tls_extension_record_size_limit(ext_data),
35 => parse_tls_extension_session_ticket_content(ext_data, ext_len),
41 => parse_tls_extension_pre_shared_key_content(ext_data, ext_len),
42 => parse_tls_extension_early_data_content(ext_data, ext_len),
43 => parse_tls_extension_supported_versions_content(ext_data, ext_len),
44 => parse_tls_extension_cookie_content(ext_data, ext_len),
51 => parse_tls_extension_key_share_content(ext_data, ext_len),
13172 => parse_tls_extension_npn_content(ext_data, ext_len),
0xff01 => parse_tls_extension_renegotiation_info_content(ext_data),
_ => Ok((
i,
TlsExtension::Unknown(TlsExtensionType(ext_type), ext_data),
)),
}?;
Ok((i, ext))
}
pub fn parse_tls_extension(i: &[u8]) -> IResult<&[u8], TlsExtension> {
let (i, ext_type) = be_u16(i)?;
let (i, ext_data) = length_data(be_u16)(i)?;
if ext_type & 0x0f0f == 0x0a0a {
return Ok((i, TlsExtension::Grease(ext_type, ext_data)));
}
let ext_len = ext_data.len() as u16;
let (_, ext) = match ext_type {
0 => parse_tls_extension_sni_content(ext_data),
1 => parse_tls_extension_max_fragment_length_content(ext_data),
5 => parse_tls_extension_status_request_content(ext_data, ext_len),
10 => parse_tls_extension_elliptic_curves_content(ext_data),
11 => parse_tls_extension_ec_point_formats_content(ext_data),
13 => parse_tls_extension_signature_algorithms_content(ext_data),
15 => parse_tls_extension_heartbeat_content(ext_data),
16 => parse_tls_extension_alpn_content(ext_data),
18 => parse_tls_extension_signed_certificate_timestamp_content(ext_data),
21 => parse_tls_extension_padding_content(ext_data, ext_len),
22 => parse_tls_extension_encrypt_then_mac_content(ext_data, ext_len),
23 => parse_tls_extension_extended_master_secret_content(ext_data, ext_len),
28 => parse_tls_extension_record_size_limit(ext_data),
35 => parse_tls_extension_session_ticket_content(ext_data, ext_len),
40 => parse_tls_extension_key_share_old_content(ext_data, ext_len),
41 => parse_tls_extension_pre_shared_key_content(ext_data, ext_len),
42 => parse_tls_extension_early_data_content(ext_data, ext_len),
43 => parse_tls_extension_supported_versions_content(ext_data, ext_len),
44 => parse_tls_extension_cookie_content(ext_data, ext_len),
45 => parse_tls_extension_psk_key_exchange_modes_content(ext_data),
48 => parse_tls_extension_oid_filters(ext_data),
49 => parse_tls_extension_post_handshake_auth_content(ext_data, ext_len),
51 => parse_tls_extension_key_share_content(ext_data, ext_len),
13172 => parse_tls_extension_npn_content(ext_data, ext_len),
0xff01 => parse_tls_extension_renegotiation_info_content(ext_data),
0xffce => parse_tls_extension_encrypted_server_name(ext_data),
_ => Ok((
i,
TlsExtension::Unknown(TlsExtensionType(ext_type), ext_data),
)),
}?;
Ok((i, ext))
}
pub fn parse_tls_client_hello_extensions(i: &[u8]) -> IResult<&[u8], Vec<TlsExtension>> {
many0(complete(parse_tls_client_hello_extension))(i)
}
pub fn parse_tls_server_hello_extensions(i: &[u8]) -> IResult<&[u8], Vec<TlsExtension>> {
many0(complete(parse_tls_server_hello_extension))(i)
}
pub fn parse_tls_extensions(i: &[u8]) -> IResult<&[u8], Vec<TlsExtension>> {
many0(complete(parse_tls_extension))(i)
}