1use alloc::string::String;
10use alloc::vec::Vec;
11use core::fmt;
12use core::str::FromStr;
13
14#[cfg(feature = "serde")]
15use serde::{Deserialize, Serialize};
16
17use crate::{
18 error::ProtoResult,
19 rr::{RData, RecordData, RecordDataDecodable, RecordType},
20 serialize::{
21 binary::{
22 BinDecodable, BinDecoder, BinEncodable, BinEncoder, DecodeError, RDataEncoding,
23 Restrict, RestrictedMath,
24 },
25 txt::ParseError,
26 },
27};
28
29#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
56#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
57pub enum CertType {
58 Reserved0,
60
61 PKIX,
63
64 SPKI,
66
67 PGP,
69
70 IPKIX,
72
73 ISPKI,
75
76 IPGP,
78
79 ACPKIX,
81
82 IACPKIX,
84
85 URI,
87
88 OID,
90
91 Reserved255,
93
94 Unassigned(u16),
96
97 Experimental(u16),
99
100 Reserved65535,
102}
103
104impl From<u16> for CertType {
105 fn from(cert_type: u16) -> Self {
106 match cert_type {
107 0 => Self::Reserved0,
108 1 => Self::PKIX,
109 2 => Self::SPKI,
110 3 => Self::PGP,
111 4 => Self::IPKIX,
112 5 => Self::ISPKI,
113 6 => Self::IPGP,
114 7 => Self::ACPKIX,
115 8 => Self::IACPKIX,
116 9_u16..=252_u16 => Self::Unassigned(cert_type),
117 253 => Self::URI,
118 254 => Self::OID,
119 255 => Self::Reserved255,
120 256_u16..=65279_u16 => Self::Unassigned(cert_type),
121 65280_u16..=65534_u16 => Self::Experimental(cert_type),
122 65535 => Self::Reserved65535,
123 }
124 }
125}
126
127impl From<CertType> for u16 {
128 fn from(cert_type: CertType) -> Self {
129 match cert_type {
130 CertType::Reserved0 => 0,
131 CertType::PKIX => 1,
132 CertType::SPKI => 2,
133 CertType::PGP => 3,
134 CertType::IPKIX => 4,
135 CertType::ISPKI => 5,
136 CertType::IPGP => 6,
137 CertType::ACPKIX => 7,
138 CertType::IACPKIX => 8,
139 CertType::URI => 253,
140 CertType::OID => 254,
141 CertType::Reserved255 => 255,
142 CertType::Unassigned(cert_type) => cert_type,
143 CertType::Experimental(cert_type) => cert_type,
144 CertType::Reserved65535 => 65535,
145 }
146 }
147}
148
149impl<'r> BinDecodable<'r> for CertType {
150 fn read(decoder: &mut BinDecoder<'r>) -> Result<Self, DecodeError> {
151 let algorithm_id = decoder
152 .read_u16()?
153 .unverified();
154 Ok(Self::from(algorithm_id))
155 }
156}
157
158impl fmt::Display for CertType {
159 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
160 write!(f, "{self:?}")
161 }
162}
163
164#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
240#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
241pub enum Algorithm {
242 Reserved(u8),
244
245 RSAMD5,
247
248 DH,
250
251 DSA,
253
254 ECC,
256
257 RSASHA1,
259
260 INDIRECT,
262
263 PRIVATEDNS,
265
266 PRIVATEOID,
268
269 DSANSEC3SHA1,
271
272 RSASHA1NSEC3SHA1,
274
275 RSASHA256,
277
278 RSASHA512,
280
281 ECCGOST,
283
284 ECDSAP256SHA256,
286
287 ECDSAP384SHA384,
289
290 ED25519,
292
293 ED448,
295
296 SM2SM3,
298
299 ECCGOST12,
301
302 Unassigned(u8),
304}
305
306impl From<u8> for Algorithm {
307 fn from(algorithm: u8) -> Self {
308 match algorithm {
309 0 => Self::Reserved(0),
310 1 => Self::RSAMD5,
311 2 => Self::DH,
312 3 => Self::DSA,
313 4 => Self::ECC,
314 5 => Self::RSASHA1,
315 6 => Self::DSANSEC3SHA1,
316 7 => Self::RSASHA1NSEC3SHA1,
317 8 => Self::RSASHA256,
318 9 => Self::Reserved(9),
319 10 => Self::RSASHA512,
320 11 => Self::Reserved(11),
321 12 => Self::ECCGOST,
322 13 => Self::ECDSAP256SHA256,
323 14 => Self::ECDSAP384SHA384,
324 15 => Self::ED25519,
325 16 => Self::ED448,
326 17 => Self::SM2SM3,
327 18..=22 => Self::Unassigned(algorithm),
328 23 => Self::ECCGOST12,
329 24..=122 => Self::Unassigned(algorithm),
330 252 => Self::INDIRECT,
331 253 => Self::PRIVATEDNS,
332 254 => Self::PRIVATEOID,
333 _ => Self::Unassigned(algorithm),
334 }
335 }
336}
337
338impl From<Algorithm> for u8 {
339 fn from(algorithm: Algorithm) -> Self {
340 match algorithm {
341 Algorithm::Reserved(value) if value == 0 => value,
342 Algorithm::RSAMD5 => 1,
343 Algorithm::DH => 2,
344 Algorithm::DSA => 3,
345 Algorithm::ECC => 4,
346 Algorithm::RSASHA1 => 5,
347 Algorithm::DSANSEC3SHA1 => 6,
348 Algorithm::RSASHA1NSEC3SHA1 => 7,
349 Algorithm::RSASHA256 => 8,
350 Algorithm::Reserved(value) if value == 9 => value,
351 Algorithm::RSASHA512 => 10,
352 Algorithm::Reserved(value) if value == 11 => value,
353 Algorithm::ECCGOST => 12,
354 Algorithm::ECDSAP256SHA256 => 13,
355 Algorithm::ECDSAP384SHA384 => 14,
356 Algorithm::ED25519 => 15,
357 Algorithm::ED448 => 16,
358 Algorithm::SM2SM3 => 17,
359 Algorithm::Unassigned(value) if (18..=22).contains(&value) => value,
360 Algorithm::ECCGOST12 => 23,
361 Algorithm::Unassigned(value) if (24..=122).contains(&value) => value,
362 Algorithm::INDIRECT => 252,
363 Algorithm::PRIVATEDNS => 253,
364 Algorithm::PRIVATEOID => 254,
365 Algorithm::Unassigned(value) => value,
366 Algorithm::Reserved(value) => value,
367 }
368 }
369}
370
371impl<'r> BinDecodable<'r> for Algorithm {
372 fn read(decoder: &mut BinDecoder<'r>) -> Result<Self, DecodeError> {
374 let algorithm_id = decoder
375 .read_u8()?
376 .unverified();
377 Ok(Self::from(algorithm_id))
378 }
379}
380
381impl fmt::Display for Algorithm {
382 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
383 write!(f, "{self:?}")
384 }
385}
386
387#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
407#[derive(Debug, PartialEq, Eq, Hash, Clone)]
408#[non_exhaustive]
409pub struct CERT {
410 pub cert_type: CertType,
412
413 pub key_tag: u16,
415
416 pub algorithm: Algorithm,
418
419 pub cert_data: Vec<u8>,
424}
425
426impl CERT {
427 pub const fn new(
429 cert_type: CertType,
430 key_tag: u16,
431 algorithm: Algorithm,
432 cert_data: Vec<u8>,
433 ) -> Self {
434 Self {
435 cert_type,
436 key_tag,
437 algorithm,
438 cert_data,
439 }
440 }
441
442 pub(crate) fn from_tokens<'i, I: Iterator<Item = &'i str>>(
444 tokens: I,
445 ) -> Result<Self, ParseError> {
446 let mut iter = tokens;
447
448 let token = iter
449 .next()
450 .ok_or(ParseError::Message("CERT cert type field missing"))?;
451 let cert_type = CertType::from(
452 u16::from_str(token)
453 .map_err(|_| ParseError::Message("Invalid digit found in cert_type token"))?,
454 );
455
456 let token = iter
457 .next()
458 .ok_or(ParseError::Message("CERT key tag field missing"))?;
459 let key_tag = u16::from_str(token)
460 .map_err(|_| ParseError::Message("Invalid digit found in key_tag token"))?;
461
462 let token = iter
463 .next()
464 .ok_or(ParseError::Message("CERT algorithm field missing"))?;
465 let algorithm = Algorithm::from(
466 u8::from_str(token)
467 .map_err(|_| ParseError::Message("Invalid digit found in algorithm token"))?,
468 );
469
470 let token = iter
471 .next()
472 .ok_or(ParseError::Message("CERT data missing"))?;
473
474 let cert_data = data_encoding::BASE64
475 .decode(token.as_bytes())
476 .map_err(|_| ParseError::Message("Invalid base64 CERT data"))?;
477
478 Ok(Self::new(cert_type, key_tag, algorithm, cert_data))
479 }
480
481 pub fn cert_base64(&self) -> String {
483 data_encoding::BASE64.encode(&self.cert_data).clone()
484 }
485}
486
487impl TryFrom<&[u8]> for CERT {
488 type Error = DecodeError;
489
490 fn try_from(cert_record: &[u8]) -> Result<Self, Self::Error> {
491 let mut decoder = BinDecoder::new(cert_record);
492 let length = Restrict::new(cert_record.len() as u16); Self::read_data(&mut decoder, length) }
495}
496
497impl BinEncodable for CERT {
498 fn emit(&self, encoder: &mut BinEncoder<'_>) -> ProtoResult<()> {
499 let mut encoder = encoder.with_rdata_behavior(RDataEncoding::Other);
500 encoder.emit_u16(self.cert_type.into())?;
501 encoder.emit_u16(self.key_tag)?;
502 encoder.emit_u8(self.algorithm.into())?;
503 encoder.emit_vec(&self.cert_data)?;
504
505 Ok(())
506 }
507}
508
509impl<'r> RecordDataDecodable<'r> for CERT {
510 fn read_data(decoder: &mut BinDecoder<'r>, length: Restrict<u16>) -> Result<Self, DecodeError> {
511 let rdata_length = length.map(|u| u as usize).unverified();
512
513 if rdata_length <= 5 {
514 return Err(DecodeError::IncorrectRDataLengthRead {
515 read: rdata_length,
516 len: 6,
517 });
518 }
519
520 let start_idx = decoder.index();
521
522 let cert_type = CertType::read(decoder)?;
524 let key_tag = decoder.read_u16()?.unverified();
525 let algorithm = Algorithm::read(decoder)?;
526
527 let cert_len = length
528 .map(|u| u as usize)
529 .checked_sub(decoder.index() - start_idx)
530 .map_err(|len| DecodeError::IncorrectRDataLengthRead { read: decoder.index() - start_idx, len })?
531 .unverified();
532
533 let cert_data = decoder.read_vec(cert_len)?.unverified();
534
535 Ok(Self {
536 cert_type,
537 key_tag,
538 algorithm,
539 cert_data,
540 })
541 }
542}
543
544impl RecordData for CERT {
545 fn try_borrow(data: &RData) -> Option<&Self> {
546 match data {
547 RData::CERT(data) => Some(data),
548 _ => None,
549 }
550 }
551
552 fn record_type(&self) -> RecordType {
553 RecordType::CERT
554 }
555
556 fn into_rdata(self) -> RData {
557 RData::CERT(self)
558 }
559}
560
561impl fmt::Display for CERT {
590 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
591 let cert_data = &data_encoding::BASE64.encode(&self.cert_data);
592
593 write!(
594 f,
595 "{cert_type} {key_tag} {algorithm} {cert_data}",
596 cert_type = self.cert_type,
597 key_tag = &self.key_tag,
598 algorithm = self.algorithm,
599 cert_data = &cert_data
600 )?;
601
602 Ok(())
603 }
604}
605
606#[cfg(test)]
607mod tests {
608 #![allow(clippy::dbg_macro, clippy::print_stdout)]
609
610 use super::*;
611
612 #[test]
613 fn test_cert_type() {
614 assert_eq!(CertType::Reserved0, CertType::from(0));
615 assert_eq!(CertType::PKIX, CertType::from(1));
616 assert_eq!(CertType::SPKI, CertType::from(2));
617 assert_eq!(CertType::PGP, CertType::from(3));
618 assert_eq!(CertType::IPKIX, CertType::from(4));
619 assert_eq!(CertType::ISPKI, CertType::from(5));
620 assert_eq!(CertType::IPGP, CertType::from(6));
621 assert_eq!(CertType::ACPKIX, CertType::from(7));
622 assert_eq!(CertType::IACPKIX, CertType::from(8));
623 assert_eq!(CertType::URI, CertType::from(253));
624 assert_eq!(CertType::OID, CertType::from(254));
625 assert_eq!(CertType::Reserved255, CertType::from(255));
626 assert_eq!(CertType::Unassigned(9), CertType::from(9));
627 assert_eq!(CertType::Unassigned(90), CertType::from(90));
628 assert_eq!(CertType::Experimental(65280), CertType::from(65280));
629 assert_eq!(CertType::Experimental(65390), CertType::from(65390));
630 assert_eq!(CertType::Reserved65535, CertType::from(65535));
631
632 let cert_type_iana_9 = CertType::Unassigned(9);
633 let cert_type_iana_90 = CertType::Unassigned(90);
634 let cert_type_experimental_80 = CertType::Experimental(65280);
635 let cert_type_experimental_90 = CertType::Experimental(65290);
636
637 assert_eq!(u16::from(CertType::Reserved0), 0);
638 assert_eq!(u16::from(CertType::PKIX), 1);
639 assert_eq!(u16::from(CertType::SPKI), 2);
640 assert_eq!(u16::from(CertType::PGP), 3);
641 assert_eq!(u16::from(CertType::IPKIX), 4);
642 assert_eq!(u16::from(CertType::ISPKI), 5);
643 assert_eq!(u16::from(CertType::IPGP), 6);
644 assert_eq!(u16::from(CertType::ACPKIX), 7);
645 assert_eq!(u16::from(CertType::IACPKIX), 8);
646 assert_eq!(u16::from(cert_type_iana_9), 9);
647 assert_eq!(u16::from(cert_type_iana_90), 90);
648 assert_eq!(u16::from(CertType::URI), 253);
649 assert_eq!(u16::from(CertType::OID), 254);
650 assert_eq!(u16::from(CertType::Reserved255), 255);
651 assert_eq!(u16::from(cert_type_experimental_80), 65280);
652 assert_eq!(u16::from(cert_type_experimental_90), 65290);
653 assert_eq!(u16::from(CertType::Reserved65535), 65535);
654 }
655
656 #[test]
657 fn test_algorithm() {
658 assert_eq!(Algorithm::Reserved(0), Algorithm::from(0));
659 assert_eq!(Algorithm::DH, Algorithm::from(2));
660 assert_eq!(Algorithm::DSA, Algorithm::from(3));
661 assert_eq!(Algorithm::ECC, Algorithm::from(4));
662 assert_eq!(Algorithm::RSASHA1, Algorithm::from(5));
663 assert_eq!(Algorithm::DSANSEC3SHA1, Algorithm::from(6));
664 assert_eq!(Algorithm::RSASHA1NSEC3SHA1, Algorithm::from(7));
665 assert_eq!(Algorithm::RSASHA256, Algorithm::from(8));
666 assert_eq!(Algorithm::Reserved(9), Algorithm::from(9));
667 assert_eq!(Algorithm::RSASHA512, Algorithm::from(10));
668 assert_eq!(Algorithm::Reserved(11), Algorithm::from(11));
669 assert_eq!(Algorithm::ECCGOST, Algorithm::from(12));
670 assert_eq!(Algorithm::ECDSAP256SHA256, Algorithm::from(13));
671 assert_eq!(Algorithm::ECDSAP384SHA384, Algorithm::from(14));
672 assert_eq!(Algorithm::ED25519, Algorithm::from(15));
673 assert_eq!(Algorithm::ED448, Algorithm::from(16));
674 assert_eq!(Algorithm::SM2SM3, Algorithm::from(17));
675 assert_eq!(Algorithm::Unassigned(18), Algorithm::from(18));
676 assert_eq!(Algorithm::Unassigned(20), Algorithm::from(20));
677 assert_eq!(Algorithm::ECCGOST12, Algorithm::from(23));
678 assert_eq!(Algorithm::INDIRECT, Algorithm::from(252));
679 assert_eq!(Algorithm::PRIVATEDNS, Algorithm::from(253));
680 assert_eq!(Algorithm::PRIVATEOID, Algorithm::from(254));
681
682 let algorithm_reserved_0 = Algorithm::Reserved(0);
683 let algorithm_reserved_9 = Algorithm::Reserved(9);
684
685 assert_eq!(u8::from(algorithm_reserved_0), 0);
686 assert_eq!(u8::from(Algorithm::DH), 2);
687
688 assert_eq!(u8::from(Algorithm::DSA), 3);
689 assert_eq!(u8::from(Algorithm::ECC), 4);
690 assert_eq!(u8::from(Algorithm::RSASHA1), 5);
691 assert_eq!(u8::from(Algorithm::DSANSEC3SHA1), 6);
692 assert_eq!(u8::from(Algorithm::RSASHA1NSEC3SHA1), 7);
693 assert_eq!(u8::from(Algorithm::RSASHA256), 8);
694 assert_eq!(u8::from(Algorithm::Reserved(9)), 9);
695 assert_eq!(u8::from(Algorithm::RSASHA512), 10);
696 assert_eq!(u8::from(Algorithm::Reserved(11)), 11);
697 assert_eq!(u8::from(Algorithm::ECCGOST), 12);
698 assert_eq!(u8::from(Algorithm::ECDSAP256SHA256), 13);
699 assert_eq!(u8::from(Algorithm::ECDSAP384SHA384), 14);
700 assert_eq!(u8::from(Algorithm::ED25519), 15);
701 assert_eq!(u8::from(Algorithm::ED448), 16);
702 assert_eq!(u8::from(Algorithm::SM2SM3), 17);
703 assert_eq!(u8::from(Algorithm::Unassigned(18)), 18);
704 assert_eq!(u8::from(Algorithm::Unassigned(20)), 20);
705 assert_eq!(u8::from(Algorithm::ECCGOST12), 23);
706 assert_eq!(u8::from(Algorithm::INDIRECT), 252);
707 assert_eq!(u8::from(Algorithm::PRIVATEDNS), 253);
708 assert_eq!(u8::from(Algorithm::PRIVATEOID), 254);
709
710 assert_eq!(u8::from(algorithm_reserved_9), 9);
711 }
712
713 #[test]
714 fn test_valid_cert_data_length() {
715 let valid_cert_data = [1, 2, 3, 4, 5, 6]; let result = CERT::try_from(&valid_cert_data[..]);
717 assert!(
718 result.is_ok(),
719 "Expected a valid result with sufficient cert_data length"
720 );
721 }
722
723 #[test]
724 fn test_cert_creation() {
725 let cert_type = CertType::PKIX;
727 let key_tag = 12345;
728 let algorithm = Algorithm::RSASHA256; let cert_data = [1, 2, 3, 4, 5];
730
731 let cert = CERT {
733 cert_type,
734 key_tag,
735 algorithm,
736 cert_data: cert_data.to_vec(),
737 };
738
739 assert_eq!(cert.cert_type, cert_type);
741 assert_eq!(cert.key_tag, key_tag);
742 assert_eq!(cert.algorithm, algorithm);
743 assert_eq!(cert.cert_data, cert_data);
744 }
745
746 #[test]
747 fn test_cert_empty_cert_data() {
748 let cert_type = CertType::PKIX;
749 let key_tag = 12345;
750 let algorithm = Algorithm::RSASHA256;
751 let cert_data = Vec::new(); let cert = CERT {
755 cert_type,
756 key_tag,
757 algorithm,
758 cert_data,
759 };
760
761 assert_eq!(cert.cert_type, cert_type);
763 assert_eq!(cert.key_tag, key_tag);
764 assert_eq!(cert.algorithm, algorithm);
765 assert!(cert.cert_data.is_empty());
766 }
767
768 #[test]
769 fn test_valid_cert_record() {
770 let valid_cert_record = [
772 0x00, 0x01, 0x30, 0x39, 0x08, 65, 81, 73, 68, ];
777
778 let cert = CERT::try_from(&valid_cert_record[..]);
779 assert!(cert.is_ok(), "Expected valid cert_record");
780
781 let cert = cert.unwrap();
782 assert_eq!(cert.cert_type, CertType::PKIX);
783 assert_eq!(cert.key_tag, 12345);
784 assert_eq!(cert.algorithm, Algorithm::RSASHA256); assert_eq!(cert.cert_data, [65, 81, 73, 68]);
786 }
787
788 #[test]
789 fn test_invalid_cert_record_length() {
790 let invalid_cert_record = [1, 2, 3, 4]; let result = CERT::try_from(&invalid_cert_record[..]);
793 assert!(
794 matches!(
795 result,
796 Err(DecodeError::IncorrectRDataLengthRead { read: 4, len: 6 })
797 ),
798 "Expected error due to invalid cert_record length, got {result:?}"
799 );
800 }
801
802 #[test]
803 fn test_valid_cert_data() {
804 let tokens = vec!["1", "123", "3", "Q2VydGlmaWNhdGUgZGF0YQ=="].into_iter();
806
807 let result = CERT::from_tokens(tokens);
808
809 assert!(result.is_ok());
810
811 let cert = result.unwrap();
812 assert_eq!(cert.cert_type, CertType::from(1));
813 assert_eq!(cert.key_tag, 123);
814 assert_eq!(cert.algorithm, Algorithm::from(3));
815 assert_eq!(cert.cert_data, b"Certificate data".to_vec()); }
817
818 #[test]
819 fn test_invalid_base64_data() {
820 let tokens = vec!["1", "123", "3", "Invalid_base64"].into_iter();
822
823 let result = CERT::from_tokens(tokens);
824
825 assert!(result.is_err());
827 let err = result.unwrap_err();
828 assert_eq!(format!("{err}"), "Invalid base64 CERT data");
829 }
830
831 #[test]
832 fn test_invalid_token_digit() {
833 let tokens = vec!["123", "3", "Q2VydGlmaWNhdGUgZGF0YQ=="].into_iter();
835
836 let result = CERT::from_tokens(tokens);
837
838 assert!(result.is_err());
840 let err = result.unwrap_err();
841 assert_eq!(format!("{err}"), "Invalid digit found in algorithm token");
842 }
843
844 #[test]
845 fn test_missing_cert_data() {
846 let tokens = vec!["1", "123", "3"].into_iter();
848
849 let result = CERT::from_tokens(tokens);
850
851 assert!(result.is_err());
853 let err = result.unwrap_err();
854 assert_eq!(format!("{err}"), "CERT data missing");
855 }
856}