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    pub struct HandshakeType(pub u8);
136
137    enum HandshakeTypeName {
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    pub struct ContentType(pub u8);
165
166    pub(crate) enum ContentTypeName {
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    pub struct ProtocolVersion(pub u16);
179
180    enum ProtocolVersionName {
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    pub struct CertificateCompressionAlgorithm(pub u16);
199
200    enum CertificateCompressionAlgorithmName {
201        Zlib => 1,
202        Brotli => 2,
203        Zstd => 3,
204    }
205}
206
207enum_builder! {
208    /// The `CertificateType` enum sent in the cert_type extensions.
209    /// Values in this enum are taken from the various RFCs covering TLS, and are listed by IANA.
210    ///
211    /// [RFC 6091 Section 5]: <https://datatracker.ietf.org/doc/html/rfc6091#section-5>
212    /// [RFC 7250 Section 7]: <https://datatracker.ietf.org/doc/html/rfc7250#section-7>
213    pub struct CertificateType(pub u8);
214
215    enum CertificateTypeName {
216        X509 => 0x00,
217        RawPublicKey => 0x02,
218    }
219}
220
221impl Default for CertificateType {
222    fn default() -> Self {
223        Self::X509
224    }
225}
226
227enum_builder! {
228    /// The type of Encrypted Client Hello (`EchClientHelloType`).
229    ///
230    /// Specified in [RFC 9849 Section 5].
231    ///
232    /// [RFC 9849 Section 5]: <https://datatracker.ietf.org/doc/html/rfc9849#section-5>
233    pub struct EchClientHelloType(pub u8);
234
235    enum EchClientHelloTypeName {
236        ClientHelloOuter => 0,
237        ClientHelloInner => 1
238    }
239}
240
241#[cfg(test)]
242mod tests {
243    use super::*;
244    use crate::msgs::{test_enum8, test_enum16};
245
246    #[test]
247    fn test_enums() {
248        test_enum8::<ContentType>(ContentType::ChangeCipherSpec, ContentType::Heartbeat);
249        test_enum8::<HandshakeType>(HandshakeType::HelloRequest, HandshakeType::MessageHash);
250        test_enum16::<CertificateCompressionAlgorithm>(
251            CertificateCompressionAlgorithm::Zlib,
252            CertificateCompressionAlgorithm::Zstd,
253        );
254        test_enum8::<CertificateType>(CertificateType::X509, CertificateType::RawPublicKey);
255    }
256}