1use std::cmp::Ordering;
7use std::fmt;
8use std::time::Instant;
9
10use arrayvec::ArrayVec;
11use nom::IResult;
12use nom::bytes::complete::take;
13use nom::number::complete::{be_u8, be_u16};
14
15use crate::SeededRng;
16use crate::buffer::Buf;
17use crate::time_tricks::InstantExt;
18
19pub type NamedGroupVec = ArrayVec<NamedGroup, { NamedGroup::supported().len() }>;
20
21#[derive(Debug, Clone, Copy, PartialEq, Eq)]
34pub struct Random {
35 pub bytes: [u8; 32],
37}
38
39impl Random {
40 pub fn new(rng: &mut SeededRng) -> Self {
42 Self {
43 bytes: rng.random(),
44 }
45 }
46
47 pub fn new_with_time(now: Instant, rng: &mut SeededRng) -> Self {
49 let gmt_duration = now.to_unix_duration();
50 let gmt_unix_time = gmt_duration.as_secs() as u32;
52
53 let random_bytes: [u8; 28] = rng.random();
54
55 let mut bytes = [0u8; 32];
56 bytes[..4].copy_from_slice(&gmt_unix_time.to_be_bytes());
57 bytes[4..].copy_from_slice(&random_bytes);
58
59 Self { bytes }
60 }
61
62 pub fn parse(input: &[u8]) -> IResult<&[u8], Random> {
64 let (input, data) = take(32_usize)(input)?;
65 let mut bytes = [0u8; 32];
66 bytes.copy_from_slice(data);
67 Ok((input, Random { bytes }))
68 }
69
70 pub fn serialize(&self, output: &mut Buf) {
72 output.extend_from_slice(&self.bytes);
73 }
74}
75
76#[derive(Debug, Clone, Copy, PartialEq, Eq)]
85#[non_exhaustive]
86pub enum NamedGroup {
87 Sect163k1,
89 Sect163r1,
91 Sect163r2,
93 Sect193r1,
95 Sect193r2,
97 Sect233k1,
99 Sect233r1,
101 Sect239k1,
103 Sect283k1,
105 Sect283r1,
107 Sect409k1,
109 Sect409r1,
111 Sect571k1,
113 Sect571r1,
115 Secp160k1,
117 Secp160r1,
119 Secp160r2,
121 Secp192k1,
123 Secp192r1,
125 Secp224k1,
127 Secp224r1,
129 Secp256k1,
131 Secp256r1,
133 Secp384r1,
135 Secp521r1,
137 X25519,
139 X448,
141 Unknown(u16),
143}
144
145impl NamedGroup {
146 pub fn from_u16(value: u16) -> Self {
148 match value {
149 1 => NamedGroup::Sect163k1,
150 2 => NamedGroup::Sect163r1,
151 3 => NamedGroup::Sect163r2,
152 4 => NamedGroup::Sect193r1,
153 5 => NamedGroup::Sect193r2,
154 6 => NamedGroup::Sect233k1,
155 7 => NamedGroup::Sect233r1,
156 8 => NamedGroup::Sect239k1,
157 9 => NamedGroup::Sect283k1,
158 10 => NamedGroup::Sect283r1,
159 11 => NamedGroup::Sect409k1,
160 12 => NamedGroup::Sect409r1,
161 13 => NamedGroup::Sect571k1,
162 14 => NamedGroup::Sect571r1,
163 15 => NamedGroup::Secp160k1,
164 16 => NamedGroup::Secp160r1,
165 17 => NamedGroup::Secp160r2,
166 18 => NamedGroup::Secp192k1,
167 19 => NamedGroup::Secp192r1,
168 20 => NamedGroup::Secp224k1,
169 21 => NamedGroup::Secp224r1,
170 22 => NamedGroup::Secp256k1,
171 23 => NamedGroup::Secp256r1,
172 24 => NamedGroup::Secp384r1,
173 25 => NamedGroup::Secp521r1,
174 29 => NamedGroup::X25519,
175 30 => NamedGroup::X448,
176 _ => NamedGroup::Unknown(value),
177 }
178 }
179
180 pub fn as_u16(&self) -> u16 {
182 match self {
183 NamedGroup::Sect163k1 => 1,
184 NamedGroup::Sect163r1 => 2,
185 NamedGroup::Sect163r2 => 3,
186 NamedGroup::Sect193r1 => 4,
187 NamedGroup::Sect193r2 => 5,
188 NamedGroup::Sect233k1 => 6,
189 NamedGroup::Sect233r1 => 7,
190 NamedGroup::Sect239k1 => 8,
191 NamedGroup::Sect283k1 => 9,
192 NamedGroup::Sect283r1 => 10,
193 NamedGroup::Sect409k1 => 11,
194 NamedGroup::Sect409r1 => 12,
195 NamedGroup::Sect571k1 => 13,
196 NamedGroup::Sect571r1 => 14,
197 NamedGroup::Secp160k1 => 15,
198 NamedGroup::Secp160r1 => 16,
199 NamedGroup::Secp160r2 => 17,
200 NamedGroup::Secp192k1 => 18,
201 NamedGroup::Secp192r1 => 19,
202 NamedGroup::Secp224k1 => 20,
203 NamedGroup::Secp224r1 => 21,
204 NamedGroup::Secp256k1 => 22,
205 NamedGroup::Secp256r1 => 23,
206 NamedGroup::Secp384r1 => 24,
207 NamedGroup::Secp521r1 => 25,
208 NamedGroup::X25519 => 29,
209 NamedGroup::X448 => 30,
210 NamedGroup::Unknown(value) => *value,
211 }
212 }
213
214 pub fn parse(input: &[u8]) -> IResult<&[u8], NamedGroup> {
216 let (input, value) = be_u16(input)?;
217 Ok((input, NamedGroup::from_u16(value)))
218 }
219
220 pub fn is_supported(&self) -> bool {
222 Self::supported().contains(self)
223 }
224
225 pub const fn all() -> &'static [NamedGroup; 27] {
227 &[
228 NamedGroup::Sect163k1,
229 NamedGroup::Sect163r1,
230 NamedGroup::Sect163r2,
231 NamedGroup::Sect193r1,
232 NamedGroup::Sect193r2,
233 NamedGroup::Sect233k1,
234 NamedGroup::Sect233r1,
235 NamedGroup::Sect239k1,
236 NamedGroup::Sect283k1,
237 NamedGroup::Sect283r1,
238 NamedGroup::Sect409k1,
239 NamedGroup::Sect409r1,
240 NamedGroup::Sect571k1,
241 NamedGroup::Sect571r1,
242 NamedGroup::Secp160k1,
243 NamedGroup::Secp160r1,
244 NamedGroup::Secp160r2,
245 NamedGroup::Secp192k1,
246 NamedGroup::Secp192r1,
247 NamedGroup::Secp224k1,
248 NamedGroup::Secp224r1,
249 NamedGroup::Secp256k1,
250 NamedGroup::Secp256r1,
251 NamedGroup::Secp384r1,
252 NamedGroup::Secp521r1,
253 NamedGroup::X25519,
254 NamedGroup::X448,
255 ]
256 }
257
258 pub const fn supported() -> &'static [NamedGroup; 4] {
260 &[
261 NamedGroup::X25519,
262 NamedGroup::Secp256r1,
263 NamedGroup::Secp384r1,
264 NamedGroup::Secp521r1,
265 ]
266 }
267}
268
269#[derive(Debug, Clone, Copy, PartialEq, Eq)]
278#[allow(non_camel_case_types)]
279pub enum HashAlgorithm {
280 None,
282 MD5,
284 SHA1,
286 SHA224,
288 SHA256,
290 SHA384,
292 SHA512,
294 Unknown(u8),
296}
297
298impl Default for HashAlgorithm {
299 fn default() -> Self {
300 Self::Unknown(0)
301 }
302}
303
304impl HashAlgorithm {
305 pub fn from_u8(value: u8) -> Self {
307 match value {
308 0 => HashAlgorithm::None,
309 1 => HashAlgorithm::MD5,
310 2 => HashAlgorithm::SHA1,
311 3 => HashAlgorithm::SHA224,
312 4 => HashAlgorithm::SHA256,
313 5 => HashAlgorithm::SHA384,
314 6 => HashAlgorithm::SHA512,
315 _ => HashAlgorithm::Unknown(value),
316 }
317 }
318
319 pub fn as_u8(&self) -> u8 {
321 match self {
322 HashAlgorithm::None => 0,
323 HashAlgorithm::MD5 => 1,
324 HashAlgorithm::SHA1 => 2,
325 HashAlgorithm::SHA224 => 3,
326 HashAlgorithm::SHA256 => 4,
327 HashAlgorithm::SHA384 => 5,
328 HashAlgorithm::SHA512 => 6,
329 HashAlgorithm::Unknown(value) => *value,
330 }
331 }
332
333 pub fn parse(input: &[u8]) -> IResult<&[u8], HashAlgorithm> {
335 let (input, value) = be_u8(input)?;
336 Ok((input, HashAlgorithm::from_u8(value)))
337 }
338
339 pub fn output_len(&self) -> usize {
341 match self {
342 HashAlgorithm::None => 0,
343 HashAlgorithm::MD5 => 16,
344 HashAlgorithm::SHA1 => 20,
345 HashAlgorithm::SHA224 => 28,
346 HashAlgorithm::SHA256 => 32,
347 HashAlgorithm::SHA384 => 48,
348 HashAlgorithm::SHA512 => 64,
349 HashAlgorithm::Unknown(_) => 0,
350 }
351 }
352}
353
354#[derive(Debug, Clone, Copy, PartialEq, Eq)]
363#[allow(non_camel_case_types)]
364pub enum SignatureAlgorithm {
365 Anonymous,
367 RSA,
369 DSA,
371 ECDSA,
373 Unknown(u8),
375}
376
377impl Default for SignatureAlgorithm {
378 fn default() -> Self {
379 Self::Unknown(0)
380 }
381}
382
383impl SignatureAlgorithm {
384 pub fn from_u8(value: u8) -> Self {
386 match value {
387 0 => SignatureAlgorithm::Anonymous,
388 1 => SignatureAlgorithm::RSA,
389 2 => SignatureAlgorithm::DSA,
390 3 => SignatureAlgorithm::ECDSA,
391 _ => SignatureAlgorithm::Unknown(value),
392 }
393 }
394
395 pub fn as_u8(&self) -> u8 {
397 match self {
398 SignatureAlgorithm::Anonymous => 0,
399 SignatureAlgorithm::RSA => 1,
400 SignatureAlgorithm::DSA => 2,
401 SignatureAlgorithm::ECDSA => 3,
402 SignatureAlgorithm::Unknown(value) => *value,
403 }
404 }
405
406 pub fn parse(input: &[u8]) -> IResult<&[u8], SignatureAlgorithm> {
408 let (input, value) = be_u8(input)?;
409 Ok((input, SignatureAlgorithm::from_u8(value)))
410 }
411}
412
413#[derive(Debug, Clone, Copy, PartialEq, Eq)]
422pub enum ContentType {
423 ChangeCipherSpec,
425 Alert,
427 Handshake,
429 ApplicationData,
431 Ack,
433 Unknown(u8),
435}
436
437impl Default for ContentType {
438 fn default() -> Self {
439 Self::Unknown(0)
440 }
441}
442
443impl ContentType {
444 pub fn from_u8(value: u8) -> Self {
446 match value {
447 20 => ContentType::ChangeCipherSpec,
448 21 => ContentType::Alert,
449 22 => ContentType::Handshake,
450 23 => ContentType::ApplicationData,
451 26 => ContentType::Ack,
452 _ => ContentType::Unknown(value),
453 }
454 }
455
456 pub fn as_u8(&self) -> u8 {
458 match self {
459 ContentType::ChangeCipherSpec => 20,
460 ContentType::Alert => 21,
461 ContentType::Handshake => 22,
462 ContentType::ApplicationData => 23,
463 ContentType::Ack => 26,
464 ContentType::Unknown(value) => *value,
465 }
466 }
467
468 pub fn parse(input: &[u8]) -> IResult<&[u8], ContentType> {
470 let (input, byte) = be_u8(input)?;
471 Ok((input, Self::from_u8(byte)))
472 }
473}
474
475#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
484pub struct Sequence {
485 pub epoch: u16,
487 pub sequence_number: u64,
489}
490
491impl Sequence {
492 pub fn new(epoch: u16) -> Self {
494 Self {
495 epoch,
496 sequence_number: 0,
497 }
498 }
499}
500
501impl fmt::Display for Sequence {
502 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
503 write!(
504 f,
505 "[epoch: {}, sequence_number: {}]",
506 self.epoch, self.sequence_number,
507 )
508 }
509}
510
511impl Ord for Sequence {
512 fn cmp(&self, other: &Self) -> Ordering {
513 if self.epoch < other.epoch {
514 Ordering::Less
515 } else if self.epoch > other.epoch {
516 Ordering::Greater
517 } else {
518 self.sequence_number.cmp(&other.sequence_number)
519 }
520 }
521}
522
523impl PartialOrd for Sequence {
524 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
525 Some(self.cmp(other))
526 }
527}
528
529#[derive(Debug, Clone, Copy, PartialEq, Eq)]
539#[allow(non_camel_case_types)]
540#[non_exhaustive]
541pub enum SignatureScheme {
542 ECDSA_SECP256R1_SHA256,
544 ECDSA_SECP384R1_SHA384,
546 ECDSA_SECP521R1_SHA512,
548 ED25519,
550 ED448,
552 RSA_PSS_RSAE_SHA256,
554 RSA_PSS_RSAE_SHA384,
556 RSA_PSS_RSAE_SHA512,
558 RSA_PSS_PSS_SHA256,
560 RSA_PSS_PSS_SHA384,
562 RSA_PSS_PSS_SHA512,
564 RSA_PKCS1_SHA256,
566 RSA_PKCS1_SHA384,
568 RSA_PKCS1_SHA512,
570 Unknown(u16),
572}
573
574impl SignatureScheme {
575 pub fn from_u16(value: u16) -> Self {
577 match value {
578 0x0403 => SignatureScheme::ECDSA_SECP256R1_SHA256,
579 0x0503 => SignatureScheme::ECDSA_SECP384R1_SHA384,
580 0x0603 => SignatureScheme::ECDSA_SECP521R1_SHA512,
581 0x0807 => SignatureScheme::ED25519,
582 0x0808 => SignatureScheme::ED448,
583 0x0804 => SignatureScheme::RSA_PSS_RSAE_SHA256,
584 0x0805 => SignatureScheme::RSA_PSS_RSAE_SHA384,
585 0x0806 => SignatureScheme::RSA_PSS_RSAE_SHA512,
586 0x0809 => SignatureScheme::RSA_PSS_PSS_SHA256,
587 0x080a => SignatureScheme::RSA_PSS_PSS_SHA384,
588 0x080b => SignatureScheme::RSA_PSS_PSS_SHA512,
589 0x0401 => SignatureScheme::RSA_PKCS1_SHA256,
590 0x0501 => SignatureScheme::RSA_PKCS1_SHA384,
591 0x0601 => SignatureScheme::RSA_PKCS1_SHA512,
592 _ => SignatureScheme::Unknown(value),
593 }
594 }
595
596 pub fn as_u16(&self) -> u16 {
598 match self {
599 SignatureScheme::ECDSA_SECP256R1_SHA256 => 0x0403,
600 SignatureScheme::ECDSA_SECP384R1_SHA384 => 0x0503,
601 SignatureScheme::ECDSA_SECP521R1_SHA512 => 0x0603,
602 SignatureScheme::ED25519 => 0x0807,
603 SignatureScheme::ED448 => 0x0808,
604 SignatureScheme::RSA_PSS_RSAE_SHA256 => 0x0804,
605 SignatureScheme::RSA_PSS_RSAE_SHA384 => 0x0805,
606 SignatureScheme::RSA_PSS_RSAE_SHA512 => 0x0806,
607 SignatureScheme::RSA_PSS_PSS_SHA256 => 0x0809,
608 SignatureScheme::RSA_PSS_PSS_SHA384 => 0x080a,
609 SignatureScheme::RSA_PSS_PSS_SHA512 => 0x080b,
610 SignatureScheme::RSA_PKCS1_SHA256 => 0x0401,
611 SignatureScheme::RSA_PKCS1_SHA384 => 0x0501,
612 SignatureScheme::RSA_PKCS1_SHA512 => 0x0601,
613 SignatureScheme::Unknown(value) => *value,
614 }
615 }
616
617 pub fn parse(input: &[u8]) -> IResult<&[u8], SignatureScheme> {
619 let (input, value) = be_u16(input)?;
620 Ok((input, SignatureScheme::from_u16(value)))
621 }
622
623 pub fn is_supported(&self) -> bool {
625 Self::SUPPORTED.contains(self)
626 }
627
628 pub fn all() -> &'static [SignatureScheme] {
630 &[
631 SignatureScheme::ECDSA_SECP256R1_SHA256,
632 SignatureScheme::ECDSA_SECP384R1_SHA384,
633 SignatureScheme::ECDSA_SECP521R1_SHA512,
634 SignatureScheme::ED25519,
635 SignatureScheme::ED448,
636 SignatureScheme::RSA_PSS_RSAE_SHA256,
637 SignatureScheme::RSA_PSS_RSAE_SHA384,
638 SignatureScheme::RSA_PSS_RSAE_SHA512,
639 SignatureScheme::RSA_PSS_PSS_SHA256,
640 SignatureScheme::RSA_PSS_PSS_SHA384,
641 SignatureScheme::RSA_PSS_PSS_SHA512,
642 SignatureScheme::RSA_PKCS1_SHA256,
643 SignatureScheme::RSA_PKCS1_SHA384,
644 SignatureScheme::RSA_PKCS1_SHA512,
645 ]
646 }
647
648 const SUPPORTED: &[SignatureScheme] = &[
649 SignatureScheme::ECDSA_SECP256R1_SHA256,
650 SignatureScheme::ECDSA_SECP384R1_SHA384,
651 ];
652
653 pub fn supported() -> ArrayVec<SignatureScheme, 2> {
655 let mut schemes = ArrayVec::new();
656 schemes.push(SignatureScheme::ECDSA_SECP256R1_SHA256);
657 schemes.push(SignatureScheme::ECDSA_SECP384R1_SHA384);
658 schemes
659 }
660
661 pub fn named_group(&self) -> Option<NamedGroup> {
666 match self {
667 SignatureScheme::ECDSA_SECP256R1_SHA256 => Some(NamedGroup::Secp256r1),
668 SignatureScheme::ECDSA_SECP384R1_SHA384 => Some(NamedGroup::Secp384r1),
669 _ => None,
670 }
671 }
672
673 pub fn hash_algorithm(&self) -> HashAlgorithm {
675 match self {
676 SignatureScheme::ECDSA_SECP256R1_SHA256
677 | SignatureScheme::RSA_PSS_RSAE_SHA256
678 | SignatureScheme::RSA_PSS_PSS_SHA256
679 | SignatureScheme::RSA_PKCS1_SHA256 => HashAlgorithm::SHA256,
680 SignatureScheme::ECDSA_SECP384R1_SHA384
681 | SignatureScheme::RSA_PSS_RSAE_SHA384
682 | SignatureScheme::RSA_PSS_PSS_SHA384
683 | SignatureScheme::RSA_PKCS1_SHA384 => HashAlgorithm::SHA384,
684 SignatureScheme::ECDSA_SECP521R1_SHA512
685 | SignatureScheme::RSA_PSS_RSAE_SHA512
686 | SignatureScheme::RSA_PSS_PSS_SHA512
687 | SignatureScheme::RSA_PKCS1_SHA512 => HashAlgorithm::SHA512,
688 SignatureScheme::ED25519 | SignatureScheme::ED448 => HashAlgorithm::None,
690 SignatureScheme::Unknown(_) => HashAlgorithm::Unknown(0),
691 }
692 }
693}
694
695#[derive(Debug, Clone, Copy, PartialEq, Eq)]
704#[allow(non_camel_case_types)]
705#[non_exhaustive]
706pub enum Dtls13CipherSuite {
707 AES_128_GCM_SHA256,
709 AES_256_GCM_SHA384,
711 CHACHA20_POLY1305_SHA256,
713 AES_128_CCM_SHA256,
715 AES_128_CCM_8_SHA256,
717 Unknown(u16),
719}
720
721impl Dtls13CipherSuite {
722 pub fn from_u16(value: u16) -> Self {
724 match value {
725 0x1301 => Dtls13CipherSuite::AES_128_GCM_SHA256,
726 0x1302 => Dtls13CipherSuite::AES_256_GCM_SHA384,
727 0x1303 => Dtls13CipherSuite::CHACHA20_POLY1305_SHA256,
728 0x1304 => Dtls13CipherSuite::AES_128_CCM_SHA256,
729 0x1305 => Dtls13CipherSuite::AES_128_CCM_8_SHA256,
730 _ => Dtls13CipherSuite::Unknown(value),
731 }
732 }
733
734 pub fn as_u16(&self) -> u16 {
736 match self {
737 Dtls13CipherSuite::AES_128_GCM_SHA256 => 0x1301,
738 Dtls13CipherSuite::AES_256_GCM_SHA384 => 0x1302,
739 Dtls13CipherSuite::CHACHA20_POLY1305_SHA256 => 0x1303,
740 Dtls13CipherSuite::AES_128_CCM_SHA256 => 0x1304,
741 Dtls13CipherSuite::AES_128_CCM_8_SHA256 => 0x1305,
742 Dtls13CipherSuite::Unknown(value) => *value,
743 }
744 }
745
746 pub fn parse(input: &[u8]) -> IResult<&[u8], Dtls13CipherSuite> {
748 let (input, value) = be_u16(input)?;
749 Ok((input, Dtls13CipherSuite::from_u16(value)))
750 }
751
752 pub fn hash_algorithm(&self) -> HashAlgorithm {
754 match self {
755 Dtls13CipherSuite::AES_128_GCM_SHA256
756 | Dtls13CipherSuite::CHACHA20_POLY1305_SHA256
757 | Dtls13CipherSuite::AES_128_CCM_SHA256
758 | Dtls13CipherSuite::AES_128_CCM_8_SHA256 => HashAlgorithm::SHA256,
759 Dtls13CipherSuite::AES_256_GCM_SHA384 => HashAlgorithm::SHA384,
760 Dtls13CipherSuite::Unknown(_) => HashAlgorithm::Unknown(0),
761 }
762 }
763
764 pub fn is_supported(&self) -> bool {
766 Self::supported().contains(self)
767 }
768
769 pub fn all() -> &'static [Dtls13CipherSuite] {
771 &[
772 Dtls13CipherSuite::AES_128_GCM_SHA256,
773 Dtls13CipherSuite::AES_256_GCM_SHA384,
774 Dtls13CipherSuite::CHACHA20_POLY1305_SHA256,
775 Dtls13CipherSuite::AES_128_CCM_SHA256,
776 Dtls13CipherSuite::AES_128_CCM_8_SHA256,
777 ]
778 }
779
780 pub fn supported() -> &'static [Dtls13CipherSuite] {
782 &[
783 Dtls13CipherSuite::AES_128_GCM_SHA256,
784 Dtls13CipherSuite::AES_256_GCM_SHA384,
785 Dtls13CipherSuite::CHACHA20_POLY1305_SHA256,
786 ]
787 }
788
789 pub fn verify_data_length(&self) -> usize {
791 self.hash_algorithm().output_len()
792 }
793}
794
795#[derive(Debug, Clone, Copy, PartialEq, Eq)]
803pub enum ProtocolVersion {
804 DTLS1_0,
806 DTLS1_2,
808 DTLS1_3,
810 Unknown(u16),
812}
813
814impl Default for ProtocolVersion {
815 fn default() -> Self {
816 Self::Unknown(0)
817 }
818}
819
820impl ProtocolVersion {
821 pub fn as_u16(&self) -> u16 {
823 match self {
824 ProtocolVersion::DTLS1_0 => 0xFEFF,
825 ProtocolVersion::DTLS1_2 => 0xFEFD,
826 ProtocolVersion::DTLS1_3 => 0xFEFC,
827 ProtocolVersion::Unknown(value) => *value,
828 }
829 }
830
831 pub fn parse(input: &[u8]) -> IResult<&[u8], ProtocolVersion> {
833 let (input, version) = be_u16(input)?;
834 let protocol_version = match version {
835 0xFEFF => ProtocolVersion::DTLS1_0,
836 0xFEFD => ProtocolVersion::DTLS1_2,
837 0xFEFC => ProtocolVersion::DTLS1_3,
838 _ => ProtocolVersion::Unknown(version),
839 };
840 Ok((input, protocol_version))
841 }
842
843 pub fn serialize(&self, output: &mut Buf) {
845 output.extend_from_slice(&self.as_u16().to_be_bytes());
846 }
847}
848
849#[derive(Debug, Clone, Copy, PartialEq, Eq)]
858pub enum CompressionMethod {
859 Null,
861 Deflate,
863 Unknown(u8),
865}
866
867impl Default for CompressionMethod {
868 fn default() -> Self {
869 Self::Unknown(0)
870 }
871}
872
873impl CompressionMethod {
874 pub fn from_u8(value: u8) -> Self {
876 match value {
877 0x00 => CompressionMethod::Null,
878 0x01 => CompressionMethod::Deflate,
879 _ => CompressionMethod::Unknown(value),
880 }
881 }
882
883 pub fn is_supported(&self) -> bool {
885 Self::supported().contains(self)
886 }
887
888 pub const fn all() -> &'static [CompressionMethod; 2] {
890 &[CompressionMethod::Null, CompressionMethod::Deflate]
891 }
892
893 pub const fn supported() -> &'static [CompressionMethod; 1] {
899 &[CompressionMethod::Null]
900 }
901
902 pub fn as_u8(&self) -> u8 {
904 match self {
905 CompressionMethod::Null => 0x00,
906 CompressionMethod::Deflate => 0x01,
907 CompressionMethod::Unknown(value) => *value,
908 }
909 }
910
911 pub fn parse(input: &[u8]) -> IResult<&[u8], CompressionMethod> {
913 let (input, value) = be_u8(input)?;
914 Ok((input, CompressionMethod::from_u8(value)))
915 }
916}
917
918#[cfg(test)]
919mod tests {
920 use super::*;
921
922 #[test]
923 fn random_parse() {
924 let data = [
925 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
926 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C,
927 0x1D, 0x1E, 0x1F, 0x20,
928 ];
929
930 let expected = Random { bytes: data };
931
932 let (_, parsed) = Random::parse(&data).unwrap();
933 assert_eq!(parsed, expected);
934 }
935
936 #[test]
937 fn random_serialize() {
938 let random = Random {
939 bytes: [
940 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
941 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C,
942 0x1D, 0x1E, 0x1F, 0x20,
943 ],
944 };
945
946 let mut serialized = Buf::new();
947 random.serialize(&mut serialized);
948
949 assert_eq!(&*serialized, &random.bytes);
950 }
951
952 #[test]
953 fn compression_supported_has_only_null() {
954 let supported = CompressionMethod::supported();
955 assert_eq!(
956 supported,
957 &[CompressionMethod::Null],
958 "Only Null compression should be supported"
959 );
960 }
961
962 #[test]
963 fn signature_scheme_named_group_ecdsa() {
964 assert_eq!(
965 SignatureScheme::ECDSA_SECP256R1_SHA256.named_group(),
966 Some(NamedGroup::Secp256r1)
967 );
968 assert_eq!(
969 SignatureScheme::ECDSA_SECP384R1_SHA384.named_group(),
970 Some(NamedGroup::Secp384r1)
971 );
972 }
973
974 #[test]
975 fn signature_scheme_named_group_non_ecdsa() {
976 assert_eq!(SignatureScheme::RSA_PSS_RSAE_SHA256.named_group(), None);
977 assert_eq!(SignatureScheme::ED25519.named_group(), None);
978 assert_eq!(SignatureScheme::ECDSA_SECP521R1_SHA512.named_group(), None);
979 assert_eq!(SignatureScheme::Unknown(0xFFFF).named_group(), None);
980 }
981
982 #[test]
983 fn random_parse_roundtrip() {
984 let data = [
985 0x5F, 0x37, 0xA9, 0x4B, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
987 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C,
988 ];
989
990 let (_, parsed) = Random::parse(&data).unwrap();
991 let mut serialized = Buf::new();
992 parsed.serialize(&mut serialized);
993
994 assert_eq!(&*serialized, &data[..]);
995 }
996}