use crate::{
Buf, BufMut, BufResult, Codec, Cursor,
tls::{ProtocolVersion, TlsVec},
tls1_3::SignatureScheme,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ExtensionType(pub u16);
impl ExtensionType {
pub const SERVER_NAME: Self = Self(0);
pub const STATUS_REQUEST: Self = Self(5);
pub const SUPPORTED_GROUPS: Self = Self(10);
pub const SIGNATURE_ALGORITHMS: Self = Self(13);
pub const USE_SRTP: Self = Self(14);
pub const HEARTBEAT: Self = Self(15);
pub const APPLICATION_LAYER_PROTOCOL_NEGOTIATION: Self = Self(16);
pub const CLIENT_CERTIFICATE_TYPE: Self = Self(19);
pub const SERVER_CERTIFICATE_TYPE: Self = Self(20);
pub const PADDING: Self = Self(21);
pub const COMPRESS_CERTIFICATE: Self = Self(27);
pub const RECORD_SIZE_LIMIT: Self = Self(28);
pub const DELEGATED_CREDENTIAL: Self = Self(34);
pub const SUPPORTED_EKT_CIPHERS: Self = Self(39);
pub const PRE_SHARED_KEY: Self = Self(41);
pub const EARLY_DATA: Self = Self(42);
pub const SUPPORTED_VERSIONS: Self = Self(43);
pub const COOKIE: Self = Self(44);
pub const PSK_KEY_EXCHANGE_MODES: Self = Self(45);
pub const CERTIFICATE_AUTHORITIES: Self = Self(47);
pub const OID_FILTERS: Self = Self(48);
pub const POST_HANDSHAKE_AUTH: Self = Self(49);
pub const SIGNATURE_ALGORITHMS_CERT: Self = Self(50);
pub const KEY_SHARE: Self = Self(51);
pub const TRANSPARENCY_INFO: Self = Self(52);
pub const EXTERNAL_ID_HASH: Self = Self(55);
pub const EXTERNAL_SESSION_ID: Self = Self(56);
pub const QUIC_TRANSPORT_PARAMETERS: Self = Self(57);
pub const TICKET_REQUEST: Self = Self(58);
pub const ECH_OUTER_EXTENSIONS: Self = Self(64768);
pub const ENCRYPTED_CLIENT_HELLO: Self = Self(65037);
}
impl Codec for ExtensionType {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
self.0.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
Ok(Self(u16::decode(reader, ())?))
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Extension {
pub extension_type: ExtensionType,
pub extension_data: TlsVec<u8, u16>,
}
impl Codec for Extension {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
self.extension_type.encode(writer, ())?;
self.extension_data.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
Ok(Self {
extension_type: ExtensionType::decode(reader, ())?,
extension_data: TlsVec::<u8, u16>::decode(reader, ())?,
})
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct NamedGroup(pub u16);
impl NamedGroup {
pub const SECP256R1: Self = Self(0x0017);
pub const SECP384R1: Self = Self(0x0018);
pub const X25519: Self = Self(0x001D);
pub const X448: Self = Self(0x001E);
}
impl Codec for NamedGroup {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
self.0.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
Ok(Self(u16::decode(reader, ())?))
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct KeyShareEntry {
pub group: NamedGroup,
pub key_exchange: TlsVec<u8, u16>,
}
impl Codec for KeyShareEntry {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
self.group.encode(writer, ())?;
self.key_exchange.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
Ok(Self {
group: NamedGroup::decode(reader, ())?,
key_exchange: TlsVec::<u8, u16>::decode(reader, ())?,
})
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ServerName(pub TlsVec<ServerNameEntry, u16>);
impl Codec for ServerName {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
self.0.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
Ok(Self(TlsVec::<ServerNameEntry, u16>::decode(reader, ())?))
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ServerNameEntry {
pub name_type: u8,
pub name: TlsVec<u8, u16>,
}
impl Codec for ServerNameEntry {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
self.name_type.encode(writer, ())?;
self.name.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
Ok(Self {
name_type: u8::decode(reader, ())?,
name: TlsVec::<u8, u16>::decode(reader, ())?,
})
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct MaxFragmentLength(pub u8);
impl Codec for MaxFragmentLength {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
self.0.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
Ok(Self(u8::decode(reader, ())?))
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct StatusRequest {
pub status_type: u8,
pub responder_id_list: TlsVec<TlsVec<u8, u16>, u16>,
pub request_extensions: TlsVec<u8, u16>,
}
impl Codec for StatusRequest {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
self.status_type.encode(writer, ())?;
self.responder_id_list.encode(writer, ())?;
self.request_extensions.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
Ok(Self {
status_type: u8::decode(reader, ())?,
responder_id_list: TlsVec::<TlsVec<u8, u16>, u16>::decode(reader, ())?,
request_extensions: TlsVec::<u8, u16>::decode(reader, ())?,
})
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct SupportedGroups(pub TlsVec<NamedGroup, u16>);
impl Codec for SupportedGroups {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
self.0.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
Ok(Self(TlsVec::<NamedGroup, u16>::decode(reader, ())?))
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct SignatureAlgorithms(pub TlsVec<SignatureScheme, u16>);
impl Codec for SignatureAlgorithms {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
self.0.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
Ok(Self(TlsVec::<SignatureScheme, u16>::decode(reader, ())?))
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct UseSrtp {
pub profiles: TlsVec<u16, u16>,
pub mki: TlsVec<u8, u8>,
}
impl Codec for UseSrtp {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
self.profiles.encode(writer, ())?;
self.mki.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
Ok(Self {
profiles: TlsVec::<u16, u16>::decode(reader, ())?,
mki: TlsVec::<u8, u8>::decode(reader, ())?,
})
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Heartbeat(pub u8);
impl Codec for Heartbeat {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
self.0.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
Ok(Self(u8::decode(reader, ())?))
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ApplicationLayerProtocolNegotiation(pub TlsVec<TlsVec<u8, u8>, u16>);
impl Codec for ApplicationLayerProtocolNegotiation {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
self.0.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
Ok(Self(TlsVec::<TlsVec<u8, u8>, u16>::decode(reader, ())?))
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct SignedCertificateTimestamp(pub TlsVec<u8, u16>);
impl Codec for SignedCertificateTimestamp {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
self.0.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
Ok(Self(TlsVec::<u8, u16>::decode(reader, ())?))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ClientCertificateType(pub u8);
impl Codec for ClientCertificateType {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
self.0.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
Ok(Self(u8::decode(reader, ())?))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ServerCertificateType(pub u8);
impl Codec for ServerCertificateType {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
self.0.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
Ok(Self(u8::decode(reader, ())?))
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Padding(pub TlsVec<u8, u16>);
impl Codec for Padding {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
self.0.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
Ok(Self(TlsVec::<u8, u16>::decode(reader, ())?))
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct KeyShare(pub TlsVec<KeyShareEntry, u16>);
impl Codec for KeyShare {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
self.0.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
Ok(Self(TlsVec::<KeyShareEntry, u16>::decode(reader, ())?))
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct PreSharedKey {
pub identities: TlsVec<PskIdentity, u16>,
pub binders: TlsVec<TlsVec<u8, u8>, u16>,
}
impl Codec for PreSharedKey {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
self.identities.encode(writer, ())?;
self.binders.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
Ok(Self {
identities: TlsVec::<PskIdentity, u16>::decode(reader, ())?,
binders: TlsVec::<TlsVec<u8, u8>, u16>::decode(reader, ())?,
})
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct PskIdentity {
pub identity: TlsVec<u8, u16>,
pub obfuscated_ticket_age: u32,
}
impl Codec for PskIdentity {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
self.identity.encode(writer, ())?;
self.obfuscated_ticket_age.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
Ok(Self {
identity: TlsVec::<u8, u16>::decode(reader, ())?,
obfuscated_ticket_age: u32::decode(reader, ())?,
})
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct PskKeyExchangeModes(pub TlsVec<u8, u8>);
impl Codec for PskKeyExchangeModes {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
self.0.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
Ok(Self(TlsVec::<u8, u8>::decode(reader, ())?))
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct EarlyData {
pub max_early_data_size: Option<u32>,
}
impl Codec for EarlyData {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
match self.max_early_data_size {
Some(size) => size.encode(writer, ()),
None => Ok(()),
}
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
let max_early_data_size = if reader.remaining() >= 4 {
Some(u32::decode(reader, ())?)
} else {
None
};
Ok(Self {
max_early_data_size,
})
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Cookie(pub TlsVec<u8, u16>);
impl Codec for Cookie {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
self.0.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
Ok(Self(TlsVec::<u8, u16>::decode(reader, ())?))
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct SupportedVersions(pub TlsVec<ProtocolVersion, u8>);
impl Codec for SupportedVersions {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
self.0.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
Ok(Self(TlsVec::<ProtocolVersion, u8>::decode(reader, ())?))
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct CertificateAuthorities(pub TlsVec<TlsVec<u8, u16>, u16>);
impl Codec for CertificateAuthorities {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
self.0.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
Ok(Self(TlsVec::<TlsVec<u8, u16>, u16>::decode(reader, ())?))
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct OidFilters(pub TlsVec<OidFilter, u16>);
impl Codec for OidFilters {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
self.0.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
Ok(Self(TlsVec::<OidFilter, u16>::decode(reader, ())?))
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct OidFilter {
pub certificate_extension_oid: TlsVec<u8, u8>,
pub certificate_extension_value: TlsVec<u8, u8>,
}
impl Codec for OidFilter {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
self.certificate_extension_oid.encode(writer, ())?;
self.certificate_extension_value.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
Ok(Self {
certificate_extension_oid: TlsVec::<u8, u8>::decode(reader, ())?,
certificate_extension_value: TlsVec::<u8, u8>::decode(reader, ())?,
})
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct PostHandshakeAuth;
impl Codec for PostHandshakeAuth {
fn encode<W: BufMut>(&self, _writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
Ok(())
}
fn decode<R: Buf>(_reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
Ok(Self)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct SignatureAlgorithmsCert(pub TlsVec<SignatureScheme, u16>);
impl Codec for SignatureAlgorithmsCert {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
self.0.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
Ok(Self(TlsVec::<SignatureScheme, u16>::decode(reader, ())?))
}
}
#[cfg(test)]
mod tests {
use core::fmt::Debug;
use super::{Extension, ExtensionType, NamedGroup};
use crate::tls::TlsVec;
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 extension_type() {
let etalon_bytes = &[0x00, 0x00];
let etalon_struct = ExtensionType::SERVER_NAME;
codec_roundtrip(etalon_struct, etalon_bytes, ());
}
#[test]
fn named_group() {
let etalon_bytes = &[0x00, 0x1D];
let etalon_struct = NamedGroup::X25519;
codec_roundtrip(etalon_struct, etalon_bytes, ());
}
#[test]
fn extension() {
let etalon_bytes = &[0x00, 0x00, 0x00, 0x00]; let etalon_struct = Extension {
extension_type: ExtensionType::SERVER_NAME,
extension_data: TlsVec::new(vec![]),
};
codec_roundtrip(etalon_struct, etalon_bytes, ());
}
}