Skip to main content

rustls/
enums.rs

1#![expect(missing_docs)]
2
3use alloc::borrow::Cow;
4use alloc::vec::Vec;
5
6use crate::crypto::cipher::Payload;
7use crate::error::InvalidMessage;
8use crate::msgs::{Codec, ListLength, NonEmpty, Reader, SizedPayload, TlsListElement};
9
10#[non_exhaustive]
11#[derive(Debug, Clone, PartialEq, Eq)]
12pub enum ApplicationProtocol<'a> {
13    AcmeTls1,
14    DoT,
15    DoQ,
16    Ftp,
17    Http09,
18    Http10,
19    Http11,
20    Http2,
21    Http3,
22    Imap,
23    Mqtt,
24    Pop3,
25    Postgresql,
26    WebRtc,
27    Other(Cow<'a, [u8]>),
28}
29
30impl<'a> ApplicationProtocol<'a> {
31    fn new(data: Cow<'a, [u8]>) -> Self {
32        match data.as_ref() {
33            b"acme-tls/1" => Self::AcmeTls1,
34            b"dot" => Self::DoT,
35            b"doq" => Self::DoQ,
36            b"ftp" => Self::Ftp,
37            b"http/0.9" => Self::Http09,
38            b"http/1.0" => Self::Http10,
39            b"http/1.1" => Self::Http11,
40            b"h2" => Self::Http2,
41            b"h3" => Self::Http3,
42            b"imap" => Self::Imap,
43            b"mqtt" => Self::Mqtt,
44            b"pop3" => Self::Pop3,
45            b"postgresql" => Self::Postgresql,
46            b"webrtc" => Self::WebRtc,
47            _r => Self::Other(data),
48        }
49    }
50
51    pub fn to_owned(&self) -> ApplicationProtocol<'static> {
52        match self {
53            Self::AcmeTls1 => ApplicationProtocol::AcmeTls1,
54            Self::DoT => ApplicationProtocol::DoT,
55            Self::DoQ => ApplicationProtocol::DoQ,
56            Self::Ftp => ApplicationProtocol::Ftp,
57            Self::Http09 => ApplicationProtocol::Http09,
58            Self::Http10 => ApplicationProtocol::Http10,
59            Self::Http11 => ApplicationProtocol::Http11,
60            Self::Http2 => ApplicationProtocol::Http2,
61            Self::Http3 => ApplicationProtocol::Http3,
62            Self::Imap => ApplicationProtocol::Imap,
63            Self::Mqtt => ApplicationProtocol::Mqtt,
64            Self::Pop3 => ApplicationProtocol::Pop3,
65            Self::Postgresql => ApplicationProtocol::Postgresql,
66            Self::WebRtc => ApplicationProtocol::WebRtc,
67            Self::Other(data) => ApplicationProtocol::Other(Cow::Owned(data.to_vec())),
68        }
69    }
70}
71
72impl<'a> Codec<'a> for ApplicationProtocol<'a> {
73    fn encode(&self, bytes: &mut Vec<u8>) {
74        SizedPayload::<u8, NonEmpty>::from(Payload::Borrowed(self.as_ref())).encode(bytes);
75    }
76
77    fn read(r: &mut Reader<'a>) -> Result<Self, InvalidMessage> {
78        match SizedPayload::<u8, NonEmpty>::read(r)?.inner {
79            Payload::Borrowed(data) => Ok(Self::new(Cow::Borrowed(data))),
80            Payload::Owned(data) => Ok(Self::new(Cow::Owned(data))),
81        }
82    }
83}
84
85/// RFC7301: `ProtocolName protocol_name_list<2..2^16-1>`
86impl TlsListElement for ApplicationProtocol<'_> {
87    const SIZE_LEN: ListLength = ListLength::NonZeroU16 {
88        empty_error: InvalidMessage::IllegalEmptyList("ProtocolNames"),
89    };
90}
91
92impl From<Vec<u8>> for ApplicationProtocol<'static> {
93    fn from(data: Vec<u8>) -> Self {
94        Self::new(Cow::Owned(data))
95    }
96}
97
98impl<'a, const N: usize> From<&'a [u8; N]> for ApplicationProtocol<'a> {
99    fn from(data: &'a [u8; N]) -> Self {
100        ApplicationProtocol::from(&data[..])
101    }
102}
103
104impl<'a> From<&'a [u8]> for ApplicationProtocol<'a> {
105    fn from(data: &'a [u8]) -> Self {
106        Self::new(Cow::Borrowed(data))
107    }
108}
109
110impl AsRef<[u8]> for ApplicationProtocol<'_> {
111    fn as_ref(&self) -> &[u8] {
112        match self {
113            Self::AcmeTls1 => b"acme-tls/1",
114            Self::DoT => b"dot",
115            Self::DoQ => b"doq",
116            Self::Ftp => b"ftp",
117            Self::Http09 => b"http/0.9",
118            Self::Http10 => b"http/1.0",
119            Self::Http11 => b"http/1.1",
120            Self::Http2 => b"h2",
121            Self::Http3 => b"h3",
122            Self::Imap => b"imap",
123            Self::Mqtt => b"mqtt",
124            Self::Pop3 => b"pop3",
125            Self::Postgresql => b"postgresql",
126            Self::WebRtc => b"webrtc",
127            Self::Other(data) => data.as_ref(),
128        }
129    }
130}
131
132enum_builder! {
133    /// The `HandshakeType` TLS protocol enum.  Values in this enum are taken
134    /// from the various RFCs covering TLS, and are listed by IANA.
135    /// The `Unknown` item is used when processing unrecognized ordinals.
136    #[repr(u8)]
137    pub enum HandshakeType {
138        HelloRequest => 0x00,
139        ClientHello => 0x01,
140        ServerHello => 0x02,
141        HelloVerifyRequest => 0x03,
142        NewSessionTicket => 0x04,
143        EndOfEarlyData => 0x05,
144        HelloRetryRequest => 0x06,
145        EncryptedExtensions => 0x08,
146        Certificate => 0x0b,
147        ServerKeyExchange => 0x0c,
148        CertificateRequest => 0x0d,
149        ServerHelloDone => 0x0e,
150        CertificateVerify => 0x0f,
151        ClientKeyExchange => 0x10,
152        Finished => 0x14,
153        CertificateURL => 0x15,
154        CertificateStatus => 0x16,
155        KeyUpdate => 0x18,
156        CompressedCertificate => 0x19,
157        MessageHash => 0xfe,
158    }
159}
160
161enum_builder! {
162    /// The `ContentType` TLS protocol enum.  Values in this enum are taken
163    /// from the various RFCs covering TLS, and are listed by IANA.
164    /// The `Unknown` item is used when processing unrecognized ordinals.
165    #[repr(u8)]
166    pub enum ContentType {
167        ChangeCipherSpec => 0x14,
168        Alert => 0x15,
169        Handshake => 0x16,
170        ApplicationData => 0x17,
171        Heartbeat => 0x18,
172    }
173}
174
175enum_builder! {
176    /// The `ProtocolVersion` TLS protocol enum.  Values in this enum are taken
177    /// from the various RFCs covering TLS, and are listed by IANA.
178    /// The `Unknown` item is used when processing unrecognized ordinals.
179    #[repr(u16)]
180    pub enum ProtocolVersion {
181        SSLv2 => 0x0002,
182        SSLv3 => 0x0300,
183        TLSv1_0 => 0x0301,
184        TLSv1_1 => 0x0302,
185        TLSv1_2 => 0x0303,
186        TLSv1_3 => 0x0304,
187        DTLSv1_0 => 0xFEFF,
188        DTLSv1_2 => 0xFEFD,
189        DTLSv1_3 => 0xFEFC,
190    }
191}
192
193enum_builder! {
194    /// The "TLS Certificate Compression Algorithm IDs" TLS protocol enum.
195    /// Values in this enum are taken from [RFC8879].
196    ///
197    /// [RFC8879]: https://www.rfc-editor.org/rfc/rfc8879.html#section-7.3
198    #[repr(u16)]
199    pub enum CertificateCompressionAlgorithm {
200        Zlib => 1,
201        Brotli => 2,
202        Zstd => 3,
203    }
204}
205
206enum_builder! {
207    /// The `CertificateType` enum sent in the cert_type extensions.
208    /// Values in this enum are taken from the various RFCs covering TLS, and are listed by IANA.
209    ///
210    /// [RFC 6091 Section 5]: <https://datatracker.ietf.org/doc/html/rfc6091#section-5>
211    /// [RFC 7250 Section 7]: <https://datatracker.ietf.org/doc/html/rfc7250#section-7>
212    #[repr(u8)]
213    #[derive(Default)]
214    pub enum CertificateType {
215        #[default]
216        X509 => 0x00,
217        RawPublicKey => 0x02,
218    }
219}
220
221enum_builder! {
222    /// The type of Encrypted Client Hello (`EchClientHelloType`).
223    ///
224    /// Specified in [draft-ietf-tls-esni Section 5].
225    ///
226    /// [draft-ietf-tls-esni Section 5]: <https://www.ietf.org/archive/id/draft-ietf-tls-esni-18.html#section-5>
227    #[repr(u8)]
228    pub enum EchClientHelloType {
229        ClientHelloOuter => 0,
230        ClientHelloInner => 1
231    }
232}
233
234#[cfg(test)]
235mod tests {
236    use super::*;
237    use crate::msgs::{test_enum8, test_enum16};
238
239    #[test]
240    fn test_enums() {
241        test_enum8::<ContentType>(ContentType::ChangeCipherSpec, ContentType::Heartbeat);
242        test_enum8::<HandshakeType>(HandshakeType::HelloRequest, HandshakeType::MessageHash);
243        test_enum16::<CertificateCompressionAlgorithm>(
244            CertificateCompressionAlgorithm::Zlib,
245            CertificateCompressionAlgorithm::Zstd,
246        );
247        test_enum8::<CertificateType>(CertificateType::X509, CertificateType::RawPublicKey);
248    }
249}