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}