1#![allow(clippy::upper_case_acronyms)]
2#![allow(non_camel_case_types)]
3use crate::crypto::{KeyExchangeAlgorithm, hash};
4use crate::msgs::codec::{Codec, Reader};
5
6enum_builder! {
7    #[repr(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
22impl HashAlgorithm {
23    pub(crate) fn hash_for_empty_input(&self) -> Option<hash::Output> {
28        match self {
29            Self::SHA256 => Some(hash::Output::new(
30                b"\xe3\xb0\xc4\x42\x98\xfc\x1c\x14\
31                  \x9a\xfb\xf4\xc8\x99\x6f\xb9\x24\
32                  \x27\xae\x41\xe4\x64\x9b\x93\x4c\
33                  \xa4\x95\x99\x1b\x78\x52\xb8\x55",
34            )),
35            Self::SHA384 => Some(hash::Output::new(
36                b"\x38\xb0\x60\xa7\x51\xac\x96\x38\
37                  \x4c\xd9\x32\x7e\xb1\xb1\xe3\x6a\
38                  \x21\xfd\xb7\x11\x14\xbe\x07\x43\
39                  \x4c\x0c\xc7\xbf\x63\xf6\xe1\xda\
40                  \x27\x4e\xde\xbf\xe7\x6f\x65\xfb\
41                  \xd5\x1a\xd2\xf1\x48\x98\xb9\x5b",
42            )),
43            _ => None,
44        }
45    }
46}
47
48enum_builder! {
49    #[repr(u8)]
53    pub(crate) enum ClientCertificateType {
54        RSASign => 0x01,
55        DSSSign => 0x02,
56        RSAFixedDH => 0x03,
57        DSSFixedDH => 0x04,
58        RSAEphemeralDH => 0x05,
59        DSSEphemeralDH => 0x06,
60        FortezzaDMS => 0x14,
61        ECDSASign => 0x40,
62        RSAFixedECDH => 0x41,
63        ECDSAFixedECDH => 0x42,
64    }
65}
66
67enum_builder! {
68    #[repr(u8)]
72    pub enum Compression {
73        Null => 0x00,
74        Deflate => 0x01,
75        LSZ => 0x40,
76    }
77}
78
79enum_builder! {
80    #[repr(u8)]
84    pub enum AlertLevel {
85        Warning => 0x01,
86        Fatal => 0x02,
87    }
88}
89
90enum_builder! {
91    #[repr(u8)]
95    pub(crate) enum HeartbeatMessageType {
96        Request => 0x01,
97        Response => 0x02,
98    }
99}
100
101enum_builder! {
102    #[repr(u16)]
106    pub enum ExtensionType {
107        ServerName => 0x0000,
108        MaxFragmentLength => 0x0001,
109        ClientCertificateUrl => 0x0002,
110        TrustedCAKeys => 0x0003,
111        TruncatedHMAC => 0x0004,
112        StatusRequest => 0x0005,
113        UserMapping => 0x0006,
114        ClientAuthz => 0x0007,
115        ServerAuthz => 0x0008,
116        CertificateType => 0x0009,
117        EllipticCurves => 0x000a,
118        ECPointFormats => 0x000b,
119        SRP => 0x000c,
120        SignatureAlgorithms => 0x000d,
121        UseSRTP => 0x000e,
122        Heartbeat => 0x000f,
123        ALProtocolNegotiation => 0x0010,
124        SCT => 0x0012,
125        ClientCertificateType => 0x0013,
126        ServerCertificateType => 0x0014,
127        Padding => 0x0015,
128        ExtendedMasterSecret => 0x0017,
129        CompressCertificate => 0x001b,
130        SessionTicket => 0x0023,
131        PreSharedKey => 0x0029,
132        EarlyData => 0x002a,
133        SupportedVersions => 0x002b,
134        Cookie => 0x002c,
135        PSKKeyExchangeModes => 0x002d,
136        TicketEarlyDataInfo => 0x002e,
137        CertificateAuthorities => 0x002f,
138        OIDFilters => 0x0030,
139        PostHandshakeAuth => 0x0031,
140        SignatureAlgorithmsCert => 0x0032,
141        KeyShare => 0x0033,
142        TransportParameters => 0x0039,
143        NextProtocolNegotiation => 0x3374,
144        ChannelId => 0x754f,
145        RenegotiationInfo => 0xff01,
146        TransportParametersDraft => 0xffa5,
147        EncryptedClientHello => 0xfe0d, EncryptedClientHelloOuterExtensions => 0xfd00, }
150}
151
152impl ExtensionType {
153    pub(crate) fn ech_compress(&self) -> bool {
164        matches!(
166            self,
167            Self::StatusRequest
168                | Self::EllipticCurves
169                | Self::SignatureAlgorithms
170                | Self::SignatureAlgorithmsCert
171                | Self::ALProtocolNegotiation
172                | Self::SupportedVersions
173                | Self::Cookie
174                | Self::KeyShare
175                | Self::PSKKeyExchangeModes
176        )
177    }
178}
179
180enum_builder! {
181    #[repr(u8)]
185    pub(crate) enum ServerNameType {
186        HostName => 0x00,
187    }
188}
189
190enum_builder! {
191    #[repr(u16)]
200    pub(crate) enum NamedCurve {
201        sect163k1 => 0x0001,
202        sect163r1 => 0x0002,
203        sect163r2 => 0x0003,
204        sect193r1 => 0x0004,
205        sect193r2 => 0x0005,
206        sect233k1 => 0x0006,
207        sect233r1 => 0x0007,
208        sect239k1 => 0x0008,
209        sect283k1 => 0x0009,
210        sect283r1 => 0x000a,
211        sect409k1 => 0x000b,
212        sect409r1 => 0x000c,
213        sect571k1 => 0x000d,
214        sect571r1 => 0x000e,
215        secp160k1 => 0x000f,
216        secp160r1 => 0x0010,
217        secp160r2 => 0x0011,
218        secp192k1 => 0x0012,
219        secp192r1 => 0x0013,
220        secp224k1 => 0x0014,
221        secp224r1 => 0x0015,
222        secp256k1 => 0x0016,
223        secp256r1 => 0x0017,
224        secp384r1 => 0x0018,
225        secp521r1 => 0x0019,
226        brainpoolp256r1 => 0x001a,
227        brainpoolp384r1 => 0x001b,
228        brainpoolp512r1 => 0x001c,
229        X25519 => 0x001d,
230        X448 => 0x001e,
231        arbitrary_explicit_prime_curves => 0xff01,
232        arbitrary_explicit_char2_curves => 0xff02,
233    }
234}
235
236enum_builder! {
237    #[repr(u16)]
241    pub enum NamedGroup {
242        secp256r1 => 0x0017,
243        secp384r1 => 0x0018,
244        secp521r1 => 0x0019,
245        X25519 => 0x001d,
246        X448 => 0x001e,
247        FFDHE2048 => 0x0100,
248        FFDHE3072 => 0x0101,
249        FFDHE4096 => 0x0102,
250        FFDHE6144 => 0x0103,
251        FFDHE8192 => 0x0104,
252        MLKEM512 => 0x0200,
253        MLKEM768 => 0x0201,
254        MLKEM1024 => 0x0202,
255        secp256r1MLKEM768 => 0x11eb,
256        X25519MLKEM768 => 0x11ec,
257    }
258}
259
260impl NamedGroup {
261    pub fn key_exchange_algorithm(self) -> KeyExchangeAlgorithm {
263        match u16::from(self) {
264            x if (0x100..0x200).contains(&x) => KeyExchangeAlgorithm::DHE,
265            _ => KeyExchangeAlgorithm::ECDHE,
266        }
267    }
268}
269
270enum_builder! {
271    #[repr(u8)]
275    pub enum ECPointFormat {
276        Uncompressed => 0x00,
277        ANSIX962CompressedPrime => 0x01,
278        ANSIX962CompressedChar2 => 0x02,
279    }
280}
281
282enum_builder! {
283    #[repr(u8)]
287    pub(crate) enum HeartbeatMode {
288        PeerAllowedToSend => 0x01,
289        PeerNotAllowedToSend => 0x02,
290    }
291}
292
293enum_builder! {
294    #[repr(u8)]
298    pub(crate) enum ECCurveType {
299        ExplicitPrime => 0x01,
300        ExplicitChar2 => 0x02,
301        NamedCurve => 0x03,
302    }
303}
304
305enum_builder! {
306    #[repr(u8)]
310    pub enum PskKeyExchangeMode {
311        PSK_KE => 0x00,
312        PSK_DHE_KE => 0x01,
313    }
314}
315
316enum_builder! {
317    #[repr(u8)]
321    pub enum KeyUpdateRequest {
322        UpdateNotRequested => 0x00,
323        UpdateRequested => 0x01,
324    }
325}
326
327enum_builder! {
328    #[repr(u8)]
332    pub enum CertificateStatusType {
333        OCSP => 0x01,
334    }
335}
336
337enum_builder! {
338    #[repr(u16)]
343    pub enum HpkeKem {
344        DHKEM_P256_HKDF_SHA256 => 0x0010,
345        DHKEM_P384_HKDF_SHA384 => 0x0011,
346        DHKEM_P521_HKDF_SHA512 => 0x0012,
347        DHKEM_X25519_HKDF_SHA256 => 0x0020,
348        DHKEM_X448_HKDF_SHA512 => 0x0021,
349    }
350}
351
352enum_builder! {
353    #[repr(u16)]
358    pub enum HpkeKdf {
359        HKDF_SHA256 => 0x0001,
360        HKDF_SHA384 => 0x0002,
361        HKDF_SHA512 => 0x0003,
362    }
363}
364
365impl Default for HpkeKdf {
366    fn default() -> Self {
368        Self::HKDF_SHA256
369    }
370}
371
372enum_builder! {
373    #[repr(u16)]
378    pub enum HpkeAead {
379        AES_128_GCM => 0x0001,
380        AES_256_GCM => 0x0002,
381        CHACHA20_POLY_1305 => 0x0003,
382        EXPORT_ONLY => 0xFFFF,
383    }
384}
385
386impl HpkeAead {
387    pub(crate) fn tag_len(&self) -> Option<usize> {
389        match self {
390            Self::AES_128_GCM | Self::AES_256_GCM | Self::CHACHA20_POLY_1305 => Some(16),
394            _ => None,
395        }
396    }
397}
398
399impl Default for HpkeAead {
400    fn default() -> Self {
402        Self::AES_128_GCM
403    }
404}
405
406enum_builder! {
407    #[repr(u16)]
414    pub enum EchVersion {
415        V18 => 0xfe0d,
416    }
417}
418
419#[cfg(test)]
420pub(crate) mod tests {
421    use std::prelude::v1::*;
425
426    use super::*;
427
428    #[test]
429    fn test_enums() {
430        test_enum8::<HashAlgorithm>(HashAlgorithm::NONE, HashAlgorithm::SHA512);
431        test_enum8::<ClientCertificateType>(
432            ClientCertificateType::RSASign,
433            ClientCertificateType::ECDSAFixedECDH,
434        );
435        test_enum8::<Compression>(Compression::Null, Compression::LSZ);
436        test_enum8::<AlertLevel>(AlertLevel::Warning, AlertLevel::Fatal);
437        test_enum8::<HeartbeatMessageType>(
438            HeartbeatMessageType::Request,
439            HeartbeatMessageType::Response,
440        );
441        test_enum16::<ExtensionType>(ExtensionType::ServerName, ExtensionType::RenegotiationInfo);
442        test_enum8::<ServerNameType>(ServerNameType::HostName, ServerNameType::HostName);
443        test_enum16::<NamedCurve>(
444            NamedCurve::sect163k1,
445            NamedCurve::arbitrary_explicit_char2_curves,
446        );
447        test_enum16::<NamedGroup>(NamedGroup::secp256r1, NamedGroup::FFDHE8192);
448        test_enum8::<ECPointFormat>(
449            ECPointFormat::Uncompressed,
450            ECPointFormat::ANSIX962CompressedChar2,
451        );
452        test_enum8::<HeartbeatMode>(
453            HeartbeatMode::PeerAllowedToSend,
454            HeartbeatMode::PeerNotAllowedToSend,
455        );
456        test_enum8::<ECCurveType>(ECCurveType::ExplicitPrime, ECCurveType::NamedCurve);
457        test_enum8::<PskKeyExchangeMode>(
458            PskKeyExchangeMode::PSK_KE,
459            PskKeyExchangeMode::PSK_DHE_KE,
460        );
461        test_enum8::<KeyUpdateRequest>(
462            KeyUpdateRequest::UpdateNotRequested,
463            KeyUpdateRequest::UpdateRequested,
464        );
465        test_enum8::<CertificateStatusType>(
466            CertificateStatusType::OCSP,
467            CertificateStatusType::OCSP,
468        );
469    }
470
471    pub(crate) fn test_enum8<T: for<'a> Codec<'a>>(first: T, last: T) {
472        let first_v = get8(&first);
473        let last_v = get8(&last);
474
475        for val in first_v..last_v + 1 {
476            let mut buf = Vec::new();
477            val.encode(&mut buf);
478            assert_eq!(buf.len(), 1);
479
480            let t = T::read_bytes(&buf).unwrap();
481            assert_eq!(val, get8(&t));
482        }
483    }
484
485    pub(crate) fn test_enum16<T: for<'a> Codec<'a>>(first: T, last: T) {
486        let first_v = get16(&first);
487        let last_v = get16(&last);
488
489        for val in first_v..last_v + 1 {
490            let mut buf = Vec::new();
491            val.encode(&mut buf);
492            assert_eq!(buf.len(), 2);
493
494            let t = T::read_bytes(&buf).unwrap();
495            assert_eq!(val, get16(&t));
496        }
497    }
498
499    fn get8<T: for<'a> Codec<'a>>(enum_value: &T) -> u8 {
500        let enc = enum_value.get_encoding();
501        assert_eq!(enc.len(), 1);
502        enc[0]
503    }
504
505    fn get16<T: for<'a> Codec<'a>>(enum_value: &T) -> u16 {
506        let enc = enum_value.get_encoding();
507        assert_eq!(enc.len(), 2);
508        (enc[0] as u16 >> 8) | (enc[1] as u16)
509    }
510}