Skip to main content

net_wire/tls/extensions/
extension.rs

1use super::{
2    alpn::{AlpnProtocolList, ServerSelectedAlpn},
3    key_share::{ClientKeyShare, HrrKeyShare, ServerKeyShare},
4    layout::{empty, len, v16},
5    psk::{ClientPreSharedKey, PskKeyExchangeModes, ServerPreSharedKey},
6    scalar_lists::{
7        CertificateCompressionAlgorithms, EcPointFormats, SignatureAlgorithms, SupportedGroups,
8    },
9    server_name::ClientServerNameList,
10    versions::{ClientSupportedVersions, ServerSupportedVersion},
11};
12use crate::tls::{
13    error::TlsParseError,
14    types::{TlsExtensionType, TlsProtocolVersion},
15};
16
17/// A raw TLS extension preserving its type and opaque payload.
18#[derive(Clone, Copy, Debug, Eq, PartialEq)]
19pub struct TlsExtension<'a> {
20    extension_type: TlsExtensionType,
21    data: &'a [u8],
22}
23impl<'a> TlsExtension<'a> {
24    /// Returns the raw extension type.
25    pub const fn extension_type(&self) -> TlsExtensionType {
26        self.extension_type
27    }
28    /// Returns the exact extension payload.
29    pub const fn data(&self) -> &'a [u8] {
30        self.data
31    }
32    fn ty(&self, t: TlsExtensionType) -> Result<(), TlsParseError> {
33        if self.extension_type == t {
34            Ok(())
35        } else {
36            Err(TlsParseError::InvalidValue)
37        }
38    }
39    /// Parses the ClientHello server_name list layout.
40    pub fn client_server_name_list(&self) -> Result<ClientServerNameList<'a>, TlsParseError> {
41        self.ty(TlsExtensionType::SERVER_NAME)?;
42        ClientServerNameList::parse(self.data)
43    }
44    /// Validates the empty ServerHello server_name acknowledgement.
45    pub fn server_name_acknowledgement(&self) -> Result<(), TlsParseError> {
46        self.ty(TlsExtensionType::SERVER_NAME)?;
47        empty(self.data)
48    }
49    /// Parses an ordered ALPN protocol-name list.
50    pub fn alpn_protocol_list(&self) -> Result<AlpnProtocolList<'a>, TlsParseError> {
51        self.ty(TlsExtensionType::APPLICATION_LAYER_PROTOCOL_NEGOTIATION)?;
52        AlpnProtocolList::parse(self.data)
53    }
54    /// Parses the single protocol selected by a server ALPN extension.
55    pub fn server_selected_alpn(&self) -> Result<ServerSelectedAlpn<'a>, TlsParseError> {
56        self.ty(TlsExtensionType::APPLICATION_LAYER_PROTOCOL_NEGOTIATION)?;
57        ServerSelectedAlpn::parse(self.data)
58    }
59    /// Parses the ClientHello supported_versions vector.
60    pub fn client_supported_versions(&self) -> Result<ClientSupportedVersions<'a>, TlsParseError> {
61        self.ty(TlsExtensionType::SUPPORTED_VERSIONS)?;
62        ClientSupportedVersions::parse(self.data)
63    }
64    /// Returns the selected server or HelloRetryRequest protocol version.
65    pub fn server_supported_version(&self) -> Result<TlsProtocolVersion, TlsParseError> {
66        Ok(self.server_supported_version_view()?.version())
67    }
68    /// Parses the server or HelloRetryRequest supported_versions layout.
69    pub fn server_supported_version_view(&self) -> Result<ServerSupportedVersion, TlsParseError> {
70        self.ty(TlsExtensionType::SUPPORTED_VERSIONS)?;
71        ServerSupportedVersion::parse(self.data)
72    }
73    /// Parses the ordered supported named groups.
74    pub fn supported_groups(&self) -> Result<SupportedGroups<'a>, TlsParseError> {
75        self.ty(TlsExtensionType::SUPPORTED_GROUPS)?;
76        SupportedGroups::parse(self.data)
77    }
78    /// Parses the signature_algorithms scheme list.
79    pub fn signature_algorithms(&self) -> Result<SignatureAlgorithms<'a>, TlsParseError> {
80        self.ty(TlsExtensionType::SIGNATURE_ALGORITHMS)?;
81        SignatureAlgorithms::parse(self.data)
82    }
83    /// Parses the signature_algorithms_cert scheme list.
84    pub fn signature_algorithms_cert(&self) -> Result<SignatureAlgorithms<'a>, TlsParseError> {
85        self.ty(TlsExtensionType::SIGNATURE_ALGORITHMS_CERT)?;
86        SignatureAlgorithms::parse(self.data)
87    }
88    /// Parses the legacy EC point-format list.
89    pub fn ec_point_formats(&self) -> Result<EcPointFormats<'a>, TlsParseError> {
90        self.ty(TlsExtensionType::EC_POINT_FORMATS)?;
91        EcPointFormats::parse(self.data)
92    }
93    /// Parses the ClientHello key-share entry vector.
94    pub fn client_key_share(&self) -> Result<ClientKeyShare<'a>, TlsParseError> {
95        self.ty(TlsExtensionType::KEY_SHARE)?;
96        ClientKeyShare::parse(self.data)
97    }
98    /// Parses the single ServerHello key-share entry.
99    pub fn server_key_share(&self) -> Result<ServerKeyShare<'a>, TlsParseError> {
100        self.ty(TlsExtensionType::KEY_SHARE)?;
101        ServerKeyShare::parse(self.data)
102    }
103    /// Parses the selected HelloRetryRequest key-share group.
104    pub fn hrr_key_share(&self) -> Result<HrrKeyShare, TlsParseError> {
105        self.ty(TlsExtensionType::KEY_SHARE)?;
106        HrrKeyShare::parse(self.data)
107    }
108    /// Parses the ordered PSK key-exchange modes.
109    pub fn psk_key_exchange_modes(&self) -> Result<PskKeyExchangeModes<'a>, TlsParseError> {
110        self.ty(TlsExtensionType::PSK_KEY_EXCHANGE_MODES)?;
111        PskKeyExchangeModes::parse(self.data)
112    }
113    /// Parses ClientHello PSK identities and binders.
114    pub fn client_pre_shared_key(&self) -> Result<ClientPreSharedKey<'a>, TlsParseError> {
115        self.ty(TlsExtensionType::PRE_SHARED_KEY)?;
116        ClientPreSharedKey::parse(self.data)
117    }
118    /// Parses the ServerHello selected PSK identity.
119    pub fn server_pre_shared_key(&self) -> Result<ServerPreSharedKey, TlsParseError> {
120        self.ty(TlsExtensionType::PRE_SHARED_KEY)?;
121        ServerPreSharedKey::parse(self.data)
122    }
123    /// Parses the offered certificate-compression algorithms.
124    pub fn certificate_compression_algorithms(
125        &self,
126    ) -> Result<CertificateCompressionAlgorithms<'a>, TlsParseError> {
127        self.ty(TlsExtensionType::COMPRESS_CERTIFICATE)?;
128        CertificateCompressionAlgorithms::parse(self.data)
129    }
130    /// Parses the nonempty cookie vector.
131    pub fn cookie(&self) -> Result<Cookie<'a>, TlsParseError> {
132        self.ty(TlsExtensionType::COOKIE)?;
133        Cookie::parse(self.data)
134    }
135    /// Validates an empty ClientHello or EncryptedExtensions early_data marker.
136    pub fn early_data_marker(&self) -> Result<(), TlsParseError> {
137        self.ty(TlsExtensionType::EARLY_DATA)?;
138        empty(self.data)
139    }
140    /// Parses a NewSessionTicket maximum early-data size.
141    pub fn early_data_max_size(&self) -> Result<u32, TlsParseError> {
142        self.ty(TlsExtensionType::EARLY_DATA)?;
143        if self.data.len() != 4 {
144            return Err(len(4, self.data.len()));
145        }
146        Ok(u32::from_be_bytes(self.data.try_into().expect("checked")))
147    }
148}
149/// A fallible iterator over ordered TLS extension TLVs.
150#[derive(Clone, Debug)]
151pub struct TlsExtensions<'a> {
152    bytes: &'a [u8],
153}
154impl<'a> TlsExtensions<'a> {
155    /// Creates an iterator over a caller-supplied extension block.
156    ///
157    /// Individual malformed or truncated TLVs are reported by iteration.
158    pub const fn new(bytes: &'a [u8]) -> Self {
159        Self { bytes }
160    }
161}
162impl<'a> Iterator for TlsExtensions<'a> {
163    type Item = Result<TlsExtension<'a>, TlsParseError>;
164    fn next(&mut self) -> Option<Self::Item> {
165        if self.bytes.is_empty() {
166            return None;
167        }
168        let a = self.bytes.len();
169        if a < 4 {
170            self.bytes = &[];
171            return Some(Err(TlsParseError::Incomplete {
172                required: 4,
173                available: a,
174            }));
175        }
176        let n = usize::from(u16::from_be_bytes([self.bytes[2], self.bytes[3]]));
177        let total = 4 + n;
178        if a < total {
179            self.bytes = &[];
180            return Some(Err(TlsParseError::Incomplete {
181                required: total,
182                available: a,
183            }));
184        }
185        let x = TlsExtension {
186            extension_type: TlsExtensionType::new(u16::from_be_bytes([
187                self.bytes[0],
188                self.bytes[1],
189            ])),
190            data: &self.bytes[4..total],
191        };
192        self.bytes = &self.bytes[total..];
193        Some(Ok(x))
194    }
195}
196/// A nonempty opaque TLS cookie.
197#[derive(Clone, Copy, Debug, Eq, PartialEq)]
198pub struct Cookie<'a>(&'a [u8]);
199impl<'a> Cookie<'a> {
200    pub(super) fn parse(b: &'a [u8]) -> Result<Self, TlsParseError> {
201        Ok(Self(v16(b, 1, false)?))
202    }
203    /// Returns the cookie bytes.
204    pub const fn as_bytes(self) -> &'a [u8] {
205        self.0
206    }
207}