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 @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 @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 @U8
46 pub enum Compression {
47 Null => 0x00,
48 Deflate => 0x01,
49 LSZ => 0x40,
50 }
51}
52
53enum_builder! {
54 @U8
58 pub enum AlertLevel {
59 Warning => 0x01,
60 Fatal => 0x02,
61 }
62}
63
64enum_builder! {
65 @U8
69 pub(crate) enum HeartbeatMessageType {
70 Request => 0x01,
71 Response => 0x02,
72 }
73}
74
75enum_builder! {
76 @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, EncryptedClientHelloOuterExtensions => 0xfd00, }
122}
123
124impl ExtensionType {
125 pub(crate) fn ech_compress(&self) -> bool {
136 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 @U8
157 pub(crate) enum ServerNameType {
158 HostName => 0x00,
159 }
160}
161
162enum_builder! {
163 @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 @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 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 @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 @U8
258 pub(crate) enum HeartbeatMode {
259 PeerAllowedToSend => 0x01,
260 PeerNotAllowedToSend => 0x02,
261 }
262}
263
264enum_builder! {
265 @U8
269 pub(crate) enum ECCurveType {
270 ExplicitPrime => 0x01,
271 ExplicitChar2 => 0x02,
272 NamedCurve => 0x03,
273 }
274}
275
276enum_builder! {
277 @U8
281 pub enum PSKKeyExchangeMode {
282 PSK_KE => 0x00,
283 PSK_DHE_KE => 0x01,
284 }
285}
286
287enum_builder! {
288 @U8
292 pub enum KeyUpdateRequest {
293 UpdateNotRequested => 0x00,
294 UpdateRequested => 0x01,
295 }
296}
297
298enum_builder! {
299 @U8
303 pub enum CertificateStatusType {
304 OCSP => 0x01,
305 }
306}
307
308enum_builder! {
309 @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 @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 fn default() -> Self {
339 Self::HKDF_SHA256
340 }
341}
342
343enum_builder! {
344 @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 pub(crate) fn tag_len(&self) -> Option<usize> {
360 match self {
361 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 fn default() -> Self {
373 Self::AES_128_GCM
374 }
375}
376
377enum_builder! {
378 @U16
385 pub enum EchVersion {
386 V18 => 0xfe0d,
387 }
388}
389
390#[cfg(test)]
391pub(crate) mod tests {
392 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}