rustls/msgs/
enums.rs

1#![allow(clippy::upper_case_acronyms)]
2#![allow(non_camel_case_types)]
3use crate::crypto::KeyExchangeAlgorithm;
4use crate::msgs::codec::{Codec, Reader};
5
6enum_builder! {
7    /// The `HashAlgorithm` TLS protocol enum.  Values in this enum are taken
8    /// from the various RFCs covering TLS, and are listed by IANA.
9    /// The `Unknown` item is used when processing unrecognised ordinals.
10    @U8
11    pub enum HashAlgorithm {
12        NONE => 0x00,
13        MD5 => 0x01,
14        SHA1 => 0x02,
15        SHA224 => 0x03,
16        SHA256 => 0x04,
17        SHA384 => 0x05,
18        SHA512 => 0x06,
19    }
20}
21
22enum_builder! {
23    /// The `ClientCertificateType` TLS protocol enum.  Values in this enum are taken
24    /// from the various RFCs covering TLS, and are listed by IANA.
25    /// The `Unknown` item is used when processing unrecognised ordinals.
26    @U8
27    pub(crate) enum ClientCertificateType {
28        RSASign => 0x01,
29        DSSSign => 0x02,
30        RSAFixedDH => 0x03,
31        DSSFixedDH => 0x04,
32        RSAEphemeralDH => 0x05,
33        DSSEphemeralDH => 0x06,
34        FortezzaDMS => 0x14,
35        ECDSASign => 0x40,
36        RSAFixedECDH => 0x41,
37        ECDSAFixedECDH => 0x42,
38    }
39}
40
41enum_builder! {
42    /// The `Compression` TLS protocol enum.  Values in this enum are taken
43    /// from the various RFCs covering TLS, and are listed by IANA.
44    /// The `Unknown` item is used when processing unrecognised ordinals.
45    @U8
46    pub enum Compression {
47        Null => 0x00,
48        Deflate => 0x01,
49        LSZ => 0x40,
50    }
51}
52
53enum_builder! {
54    /// The `AlertLevel` TLS protocol enum.  Values in this enum are taken
55    /// from the various RFCs covering TLS, and are listed by IANA.
56    /// The `Unknown` item is used when processing unrecognised ordinals.
57    @U8
58    pub enum AlertLevel {
59        Warning => 0x01,
60        Fatal => 0x02,
61    }
62}
63
64enum_builder! {
65    /// The `HeartbeatMessageType` TLS protocol enum.  Values in this enum are taken
66    /// from the various RFCs covering TLS, and are listed by IANA.
67    /// The `Unknown` item is used when processing unrecognised ordinals.
68    @U8
69    pub(crate) enum HeartbeatMessageType {
70        Request => 0x01,
71        Response => 0x02,
72    }
73}
74
75enum_builder! {
76    /// The `ExtensionType` TLS protocol enum.  Values in this enum are taken
77    /// from the various RFCs covering TLS, and are listed by IANA.
78    /// The `Unknown` item is used when processing unrecognised ordinals.
79    @U16
80    pub enum ExtensionType {
81        ServerName => 0x0000,
82        MaxFragmentLength => 0x0001,
83        ClientCertificateUrl => 0x0002,
84        TrustedCAKeys => 0x0003,
85        TruncatedHMAC => 0x0004,
86        StatusRequest => 0x0005,
87        UserMapping => 0x0006,
88        ClientAuthz => 0x0007,
89        ServerAuthz => 0x0008,
90        CertificateType => 0x0009,
91        EllipticCurves => 0x000a,
92        ECPointFormats => 0x000b,
93        SRP => 0x000c,
94        SignatureAlgorithms => 0x000d,
95        UseSRTP => 0x000e,
96        Heartbeat => 0x000f,
97        ALProtocolNegotiation => 0x0010,
98        SCT => 0x0012,
99        Padding => 0x0015,
100        ExtendedMasterSecret => 0x0017,
101        CompressCertificate => 0x001b,
102        SessionTicket => 0x0023,
103        PreSharedKey => 0x0029,
104        EarlyData => 0x002a,
105        SupportedVersions => 0x002b,
106        Cookie => 0x002c,
107        PSKKeyExchangeModes => 0x002d,
108        TicketEarlyDataInfo => 0x002e,
109        CertificateAuthorities => 0x002f,
110        OIDFilters => 0x0030,
111        PostHandshakeAuth => 0x0031,
112        SignatureAlgorithmsCert => 0x0032,
113        KeyShare => 0x0033,
114        TransportParameters => 0x0039,
115        NextProtocolNegotiation => 0x3374,
116        ChannelId => 0x754f,
117        RenegotiationInfo => 0xff01,
118        TransportParametersDraft => 0xffa5,
119        EncryptedClientHello => 0xfe0d, // https://datatracker.ietf.org/doc/html/draft-ietf-tls-esni-18#section-11.1
120        EncryptedClientHelloOuterExtensions => 0xfd00, // https://datatracker.ietf.org/doc/html/draft-ietf-tls-esni-18#section-5.1
121    }
122}
123
124impl ExtensionType {
125    /// Returns true if the extension type can be compressed in an "inner" client hello for ECH.
126    ///
127    /// This function should only return true for extension types where the inner hello and outer
128    /// hello extensions values will always be identical. Extensions that may be identical
129    /// sometimes (e.g. server name, cert compression methods), but not always, SHOULD NOT be
130    /// compressed.
131    ///
132    /// See [draft-ietf-esni-18 §5](https://datatracker.ietf.org/doc/html/draft-ietf-tls-esni-18#section-5)
133    /// and [draft-ietf-esni-18 §10.5](https://datatracker.ietf.org/doc/html/draft-ietf-tls-esni-18#section-10.5)
134    /// for more information.
135    pub(crate) fn ech_compress(&self) -> bool {
136        // We match which extensions we will compress with BoringSSL and Go's stdlib.
137        matches!(
138            self,
139            Self::StatusRequest
140                | Self::EllipticCurves
141                | Self::SignatureAlgorithms
142                | Self::SignatureAlgorithmsCert
143                | Self::ALProtocolNegotiation
144                | Self::SupportedVersions
145                | Self::Cookie
146                | Self::KeyShare
147                | Self::PSKKeyExchangeModes
148        )
149    }
150}
151
152enum_builder! {
153    /// The `ServerNameType` TLS protocol enum.  Values in this enum are taken
154    /// from the various RFCs covering TLS, and are listed by IANA.
155    /// The `Unknown` item is used when processing unrecognised ordinals.
156    @U8
157    pub(crate) enum ServerNameType {
158        HostName => 0x00,
159    }
160}
161
162enum_builder! {
163    /// The `NamedCurve` TLS protocol enum.  Values in this enum are taken
164    /// from the various RFCs covering TLS, and are listed by IANA.
165    /// The `Unknown` item is used when processing unrecognised ordinals.
166    ///
167    /// This enum is used for recognizing elliptic curve parameters advertised
168    /// by a peer during a TLS handshake. It is **not** a list of curves that
169    /// Rustls supports. See [`crate::crypto::ring::kx_group`] for the list of supported
170    /// elliptic curve groups.
171    @U16
172    pub(crate) enum NamedCurve {
173        sect163k1 => 0x0001,
174        sect163r1 => 0x0002,
175        sect163r2 => 0x0003,
176        sect193r1 => 0x0004,
177        sect193r2 => 0x0005,
178        sect233k1 => 0x0006,
179        sect233r1 => 0x0007,
180        sect239k1 => 0x0008,
181        sect283k1 => 0x0009,
182        sect283r1 => 0x000a,
183        sect409k1 => 0x000b,
184        sect409r1 => 0x000c,
185        sect571k1 => 0x000d,
186        sect571r1 => 0x000e,
187        secp160k1 => 0x000f,
188        secp160r1 => 0x0010,
189        secp160r2 => 0x0011,
190        secp192k1 => 0x0012,
191        secp192r1 => 0x0013,
192        secp224k1 => 0x0014,
193        secp224r1 => 0x0015,
194        secp256k1 => 0x0016,
195        secp256r1 => 0x0017,
196        secp384r1 => 0x0018,
197        secp521r1 => 0x0019,
198        brainpoolp256r1 => 0x001a,
199        brainpoolp384r1 => 0x001b,
200        brainpoolp512r1 => 0x001c,
201        X25519 => 0x001d,
202        X448 => 0x001e,
203        arbitrary_explicit_prime_curves => 0xff01,
204        arbitrary_explicit_char2_curves => 0xff02,
205    }
206}
207
208enum_builder! {
209    /// The `NamedGroup` TLS protocol enum.  Values in this enum are taken
210    /// from the various RFCs covering TLS, and are listed by IANA.
211    /// The `Unknown` item is used when processing unrecognised ordinals.
212    @U16
213    pub enum NamedGroup {
214        secp256r1 => 0x0017,
215        secp384r1 => 0x0018,
216        secp521r1 => 0x0019,
217        X25519 => 0x001d,
218        X448 => 0x001e,
219        FFDHE2048 => 0x0100,
220        FFDHE3072 => 0x0101,
221        FFDHE4096 => 0x0102,
222        FFDHE6144 => 0x0103,
223        FFDHE8192 => 0x0104,
224    }
225}
226
227impl NamedGroup {
228    /// Return the key exchange algorithm associated with this `NamedGroup`
229    pub fn key_exchange_algorithm(self) -> KeyExchangeAlgorithm {
230        match u16::from(self) {
231            x if (0x100..0x200).contains(&x) => KeyExchangeAlgorithm::DHE,
232            _ => KeyExchangeAlgorithm::ECDHE,
233        }
234    }
235}
236
237enum_builder! {
238    /// The `ECPointFormat` TLS protocol enum.  Values in this enum are taken
239    /// from the various RFCs covering TLS, and are listed by IANA.
240    /// The `Unknown` item is used when processing unrecognised ordinals.
241    @U8
242    pub enum ECPointFormat {
243        Uncompressed => 0x00,
244        ANSIX962CompressedPrime => 0x01,
245        ANSIX962CompressedChar2 => 0x02,
246    }
247}
248
249impl ECPointFormat {
250    pub(crate) const SUPPORTED: [Self; 1] = [Self::Uncompressed];
251}
252
253enum_builder! {
254    /// The `HeartbeatMode` TLS protocol enum.  Values in this enum are taken
255    /// from the various RFCs covering TLS, and are listed by IANA.
256    /// The `Unknown` item is used when processing unrecognised ordinals.
257    @U8
258    pub(crate) enum HeartbeatMode {
259        PeerAllowedToSend => 0x01,
260        PeerNotAllowedToSend => 0x02,
261    }
262}
263
264enum_builder! {
265    /// The `ECCurveType` TLS protocol enum.  Values in this enum are taken
266    /// from the various RFCs covering TLS, and are listed by IANA.
267    /// The `Unknown` item is used when processing unrecognised ordinals.
268    @U8
269    pub(crate) enum ECCurveType {
270        ExplicitPrime => 0x01,
271        ExplicitChar2 => 0x02,
272        NamedCurve => 0x03,
273    }
274}
275
276enum_builder! {
277    /// The `PSKKeyExchangeMode` TLS protocol enum.  Values in this enum are taken
278    /// from the various RFCs covering TLS, and are listed by IANA.
279    /// The `Unknown` item is used when processing unrecognised ordinals.
280    @U8
281    pub enum PSKKeyExchangeMode {
282        PSK_KE => 0x00,
283        PSK_DHE_KE => 0x01,
284    }
285}
286
287enum_builder! {
288    /// The `KeyUpdateRequest` TLS protocol enum.  Values in this enum are taken
289    /// from the various RFCs covering TLS, and are listed by IANA.
290    /// The `Unknown` item is used when processing unrecognised ordinals.
291    @U8
292    pub enum KeyUpdateRequest {
293        UpdateNotRequested => 0x00,
294        UpdateRequested => 0x01,
295    }
296}
297
298enum_builder! {
299    /// The `CertificateStatusType` TLS protocol enum.  Values in this enum are taken
300    /// from the various RFCs covering TLS, and are listed by IANA.
301    /// The `Unknown` item is used when processing unrecognised ordinals.
302    @U8
303    pub enum CertificateStatusType {
304        OCSP => 0x01,
305    }
306}
307
308enum_builder! {
309    /// The Key Encapsulation Mechanism (`Kem`) type for HPKE operations.
310    /// Listed by IANA, as specified in [RFC 9180 Section 7.1]
311    ///
312    /// [RFC 9180 Section 7.1]: <https://datatracker.ietf.org/doc/html/rfc9180#kemid-values>
313    @U16
314    pub enum HpkeKem {
315        DHKEM_P256_HKDF_SHA256 => 0x0010,
316        DHKEM_P384_HKDF_SHA384 => 0x0011,
317        DHKEM_P521_HKDF_SHA512 => 0x0012,
318        DHKEM_X25519_HKDF_SHA256 => 0x0020,
319        DHKEM_X448_HKDF_SHA512 => 0x0021,
320    }
321}
322
323enum_builder! {
324    /// The Key Derivation Function (`Kdf`) type for HPKE operations.
325    /// Listed by IANA, as specified in [RFC 9180 Section 7.2]
326    ///
327    /// [RFC 9180 Section 7.2]: <https://datatracker.ietf.org/doc/html/rfc9180#name-key-derivation-functions-kd>
328    @U16
329    pub enum HpkeKdf {
330        HKDF_SHA256 => 0x0001,
331        HKDF_SHA384 => 0x0002,
332        HKDF_SHA512 => 0x0003,
333    }
334}
335
336impl Default for HpkeKdf {
337    // TODO(XXX): revisit the default configuration. This is just what Cloudflare ships right now.
338    fn default() -> Self {
339        Self::HKDF_SHA256
340    }
341}
342
343enum_builder! {
344    /// The Authenticated Encryption with Associated Data (`Aead`) type for HPKE operations.
345    /// Listed by IANA, as specified in [RFC 9180 Section 7.3]
346    ///
347    /// [RFC 9180 Section 7.3]: <https://datatracker.ietf.org/doc/html/rfc9180#name-authenticated-encryption-wi>
348    @U16
349    pub enum HpkeAead {
350        AES_128_GCM => 0x0001,
351        AES_256_GCM => 0x0002,
352        CHACHA20_POLY_1305 => 0x0003,
353        EXPORT_ONLY => 0xFFFF,
354    }
355}
356
357impl HpkeAead {
358    /// Returns the length of the tag for the AEAD algorithm, or none if the AEAD is EXPORT_ONLY.
359    pub(crate) fn tag_len(&self) -> Option<usize> {
360        match self {
361            // See RFC 9180 Section 7.3, column `Nt`, the length in bytes of the authentication tag
362            // for the algorithm.
363            // https://www.rfc-editor.org/rfc/rfc9180.html#section-7.3
364            Self::AES_128_GCM | Self::AES_256_GCM | Self::CHACHA20_POLY_1305 => Some(16),
365            _ => None,
366        }
367    }
368}
369
370impl Default for HpkeAead {
371    // TODO(XXX): revisit the default configuration. This is just what Cloudflare ships right now.
372    fn default() -> Self {
373        Self::AES_128_GCM
374    }
375}
376
377enum_builder! {
378    /// The Encrypted Client Hello protocol version (`EchVersion`).
379    ///
380    /// Specified in [draft-ietf-tls-esni Section 4].
381    /// TODO(XXX): Update reference once RFC is published.
382    ///
383    /// [draft-ietf-tls-esni Section 4]: <https://www.ietf.org/archive/id/draft-ietf-tls-esni-17.html#section-4>
384    @U16
385    pub enum EchVersion {
386        V18 => 0xfe0d,
387    }
388}
389
390#[cfg(test)]
391pub(crate) mod tests {
392    // These tests are intended to provide coverage and
393    // check panic-safety of relatively unused values.
394
395    use std::prelude::v1::*;
396
397    use super::*;
398
399    #[test]
400    fn test_enums() {
401        test_enum8::<HashAlgorithm>(HashAlgorithm::NONE, HashAlgorithm::SHA512);
402        test_enum8::<ClientCertificateType>(
403            ClientCertificateType::RSASign,
404            ClientCertificateType::ECDSAFixedECDH,
405        );
406        test_enum8::<Compression>(Compression::Null, Compression::LSZ);
407        test_enum8::<AlertLevel>(AlertLevel::Warning, AlertLevel::Fatal);
408        test_enum8::<HeartbeatMessageType>(
409            HeartbeatMessageType::Request,
410            HeartbeatMessageType::Response,
411        );
412        test_enum16::<ExtensionType>(ExtensionType::ServerName, ExtensionType::RenegotiationInfo);
413        test_enum8::<ServerNameType>(ServerNameType::HostName, ServerNameType::HostName);
414        test_enum16::<NamedCurve>(
415            NamedCurve::sect163k1,
416            NamedCurve::arbitrary_explicit_char2_curves,
417        );
418        test_enum16::<NamedGroup>(NamedGroup::secp256r1, NamedGroup::FFDHE8192);
419        test_enum8::<ECPointFormat>(
420            ECPointFormat::Uncompressed,
421            ECPointFormat::ANSIX962CompressedChar2,
422        );
423        test_enum8::<HeartbeatMode>(
424            HeartbeatMode::PeerAllowedToSend,
425            HeartbeatMode::PeerNotAllowedToSend,
426        );
427        test_enum8::<ECCurveType>(ECCurveType::ExplicitPrime, ECCurveType::NamedCurve);
428        test_enum8::<PSKKeyExchangeMode>(
429            PSKKeyExchangeMode::PSK_KE,
430            PSKKeyExchangeMode::PSK_DHE_KE,
431        );
432        test_enum8::<KeyUpdateRequest>(
433            KeyUpdateRequest::UpdateNotRequested,
434            KeyUpdateRequest::UpdateRequested,
435        );
436        test_enum8::<CertificateStatusType>(
437            CertificateStatusType::OCSP,
438            CertificateStatusType::OCSP,
439        );
440    }
441
442    pub(crate) fn test_enum8<T: for<'a> Codec<'a>>(first: T, last: T) {
443        let first_v = get8(&first);
444        let last_v = get8(&last);
445
446        for val in first_v..last_v + 1 {
447            let mut buf = Vec::new();
448            val.encode(&mut buf);
449            assert_eq!(buf.len(), 1);
450
451            let t = T::read_bytes(&buf).unwrap();
452            assert_eq!(val, get8(&t));
453        }
454    }
455
456    pub(crate) fn test_enum16<T: for<'a> Codec<'a>>(first: T, last: T) {
457        let first_v = get16(&first);
458        let last_v = get16(&last);
459
460        for val in first_v..last_v + 1 {
461            let mut buf = Vec::new();
462            val.encode(&mut buf);
463            assert_eq!(buf.len(), 2);
464
465            let t = T::read_bytes(&buf).unwrap();
466            assert_eq!(val, get16(&t));
467        }
468    }
469
470    fn get8<T: for<'a> Codec<'a>>(enum_value: &T) -> u8 {
471        let enc = enum_value.get_encoding();
472        assert_eq!(enc.len(), 1);
473        enc[0]
474    }
475
476    fn get16<T: for<'a> Codec<'a>>(enum_value: &T) -> u16 {
477        let enc = enum_value.get_encoding();
478        assert_eq!(enc.len(), 2);
479        (enc[0] as u16 >> 8) | (enc[1] as u16)
480    }
481}