1use alloc::string::String;
10use alloc::string::ToString;
11use alloc::vec::Vec;
12use core::fmt;
13
14#[cfg(feature = "serde")]
15use serde::{Deserialize, Serialize};
16
17use crate::{
18 error::{ProtoError, ProtoResult},
19 rr::{RData, RecordData, RecordDataDecodable, RecordType},
20 serialize::binary::{
21 BinDecodable, BinDecoder, BinEncodable, BinEncoder, Restrict, RestrictedMath,
22 },
23};
24
25#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
52#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
53pub enum CertType {
54 Reserved,
56
57 PKIX,
59
60 SPKI,
62
63 PGP,
65
66 IPKIX,
68
69 ISPKI,
71
72 IPGP,
74
75 ACPKIX,
77
78 IACPKIX,
80
81 URI,
83
84 OID,
86
87 Unassigned(u16),
89
90 Experimental(u16),
92}
93
94impl From<u16> for CertType {
95 fn from(cert_type: u16) -> Self {
96 match cert_type {
97 0 => Self::Reserved,
98 1 => Self::PKIX,
99 2 => Self::SPKI,
100 3 => Self::PGP,
101 4 => Self::IPKIX,
102 5 => Self::ISPKI,
103 6 => Self::IPGP,
104 7 => Self::ACPKIX,
105 8 => Self::IACPKIX,
106 9_u16..=252_u16 => Self::Unassigned(cert_type),
107 253 => Self::URI,
108 254 => Self::OID,
109 255 => Self::Reserved,
110 256_u16..=65279_u16 => Self::Unassigned(cert_type),
111 65280_u16..=65534_u16 => Self::Experimental(cert_type),
112 65535 => Self::Reserved,
113 }
114 }
115}
116
117impl From<CertType> for u16 {
118 fn from(cert_type: CertType) -> Self {
119 match cert_type {
120 CertType::Reserved => 0,
121 CertType::PKIX => 1,
122 CertType::SPKI => 2,
123 CertType::PGP => 3,
124 CertType::IPKIX => 4,
125 CertType::ISPKI => 5,
126 CertType::IPGP => 6,
127 CertType::ACPKIX => 7,
128 CertType::IACPKIX => 8,
129 CertType::URI => 253,
130 CertType::OID => 254,
131 CertType::Unassigned(cert_type) => cert_type,
132 CertType::Experimental(cert_type) => cert_type,
133 }
134 }
135}
136
137impl<'r> BinDecodable<'r> for CertType {
138 fn read(decoder: &mut BinDecoder<'r>) -> ProtoResult<Self> {
139 let algorithm_id = decoder
140 .read_u16()?
141 .unverified();
142 Ok(Self::from(algorithm_id))
143 }
144}
145
146impl fmt::Display for CertType {
147 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
148 write!(f, "{:?}", self)
149 }
150}
151
152#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
228#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
229pub enum Algorithm {
230 Reserved(u8),
232
233 RSAMD5,
235
236 DH,
238
239 DSA,
241
242 ECC,
244
245 RSASHA1,
247
248 INDIRECT,
250
251 PRIVATEDNS,
253
254 PRIVATEOID,
256
257 DSANSEC3SHA1,
259
260 RSASHA1NSEC3SHA1,
262
263 RSASHA256,
265
266 RSASHA512,
268
269 ECCGOST,
271
272 ECDSAP256SHA256,
274
275 ECDSAP384SHA384,
277
278 ED25519,
280
281 ED448,
283
284 SM2SM3,
286
287 ECCGOST12,
289
290 Unassigned(u8),
292}
293
294impl From<u8> for Algorithm {
295 fn from(algorithm: u8) -> Self {
296 match algorithm {
297 0 => Self::Reserved(0),
298 1 => Self::RSAMD5,
299 2 => Self::DH,
300 3 => Self::DSA,
301 4 => Self::ECC,
302 5 => Self::RSASHA1,
303 6 => Self::DSANSEC3SHA1,
304 7 => Self::RSASHA1NSEC3SHA1,
305 8 => Self::RSASHA256,
306 9 => Self::Reserved(9),
307 10 => Self::RSASHA512,
308 11 => Self::Reserved(11),
309 12 => Self::ECCGOST,
310 13 => Self::ECDSAP256SHA256,
311 14 => Self::ECDSAP384SHA384,
312 15 => Self::ED25519,
313 16 => Self::ED448,
314 17 => Self::SM2SM3,
315 18..=22 => Self::Unassigned(algorithm),
316 23 => Self::ECCGOST12,
317 24..=122 => Self::Unassigned(algorithm),
318 252 => Self::INDIRECT,
319 253 => Self::PRIVATEDNS,
320 254 => Self::PRIVATEOID,
321 _ => Self::Unassigned(algorithm),
322 }
323 }
324}
325
326impl From<Algorithm> for u8 {
327 fn from(algorithm: Algorithm) -> Self {
328 match algorithm {
329 Algorithm::Reserved(value) if value == 0 => value,
330 Algorithm::RSAMD5 => 1,
331 Algorithm::DH => 2,
332 Algorithm::DSA => 3,
333 Algorithm::ECC => 4,
334 Algorithm::RSASHA1 => 5,
335 Algorithm::DSANSEC3SHA1 => 6,
336 Algorithm::RSASHA1NSEC3SHA1 => 7,
337 Algorithm::RSASHA256 => 8,
338 Algorithm::Reserved(value) if value == 9 => value,
339 Algorithm::RSASHA512 => 10,
340 Algorithm::Reserved(value) if value == 11 => value,
341 Algorithm::ECCGOST => 12,
342 Algorithm::ECDSAP256SHA256 => 13,
343 Algorithm::ECDSAP384SHA384 => 14,
344 Algorithm::ED25519 => 15,
345 Algorithm::ED448 => 16,
346 Algorithm::SM2SM3 => 17,
347 Algorithm::Unassigned(value) if (18..=22).contains(&value) => value,
348 Algorithm::ECCGOST12 => 23,
349 Algorithm::Unassigned(value) if (24..=122).contains(&value) => value,
350 Algorithm::INDIRECT => 252,
351 Algorithm::PRIVATEDNS => 253,
352 Algorithm::PRIVATEOID => 254,
353 Algorithm::Unassigned(value) => value,
354 Algorithm::Reserved(value) => value,
355 }
356 }
357}
358
359impl<'r> BinDecodable<'r> for Algorithm {
360 fn read(decoder: &mut BinDecoder<'r>) -> ProtoResult<Self> {
362 let algorithm_id = decoder
363 .read_u8()?
364 .unverified();
365 Ok(Self::from(algorithm_id))
366 }
367}
368
369impl fmt::Display for Algorithm {
370 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
371 write!(f, "{:?}", self)
372 }
373}
374
375#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
395#[derive(Debug, PartialEq, Eq, Hash, Clone)]
396pub struct CERT {
397 cert_type: CertType,
398 key_tag: u16,
399 algorithm: Algorithm,
400 cert_data: Vec<u8>,
401}
402
403impl CERT {
404 pub const fn new(
406 cert_type: CertType,
407 key_tag: u16,
408 algorithm: Algorithm,
409 cert_data: Vec<u8>,
410 ) -> Self {
411 Self {
412 cert_type,
413 key_tag,
414 algorithm,
415 cert_data,
416 }
417 }
418
419 pub fn cert_type(&self) -> CertType {
421 self.cert_type
422 }
423
424 pub fn key_tag(&self) -> u16 {
426 self.key_tag
427 }
428
429 pub fn algorithm(&self) -> Algorithm {
431 self.algorithm
432 }
433
434 pub fn cert_data(&self) -> Vec<u8> {
436 self.cert_data.clone()
437 }
438
439 pub fn cert_base64(&self) -> String {
441 data_encoding::BASE64.encode(&self.cert_data).clone()
442 }
443}
444
445impl TryFrom<&[u8]> for CERT {
446 type Error = ProtoError;
447
448 fn try_from(cert_record: &[u8]) -> Result<Self, Self::Error> {
449 let mut decoder = BinDecoder::new(cert_record);
450 let length = Restrict::new(cert_record.len() as u16); Self::read_data(&mut decoder, length) }
453}
454
455impl BinEncodable for CERT {
456 fn emit(&self, encoder: &mut BinEncoder<'_>) -> ProtoResult<()> {
457 encoder.emit_u16(self.cert_type.into())?;
458 encoder.emit_u16(self.key_tag)?;
459 encoder.emit_u8(self.algorithm.into())?;
460 encoder.emit_vec(&self.cert_data)?;
461
462 Ok(())
463 }
464}
465
466impl<'r> RecordDataDecodable<'r> for CERT {
467 fn read_data(decoder: &mut BinDecoder<'r>, length: Restrict<u16>) -> ProtoResult<Self> {
468 let rdata_length = length.map(|u| u as usize).unverified();
469
470 if rdata_length <= 5 {
471 return Err(ProtoError::from("invalid cert_record length".to_string()));
472 }
473
474 let start_idx = decoder.index();
475
476 let cert_type = CertType::read(decoder)?;
478 let key_tag = decoder.read_u16()?.unverified();
479 let algorithm = Algorithm::read(decoder)?;
480
481 let cert_len = length
482 .map(|u| u as usize)
483 .checked_sub(decoder.index() - start_idx)
484 .map_err(|_| ProtoError::from("invalid rdata length in CERT"))?
485 .unverified();
486
487 let cert_data = decoder.read_vec(cert_len)?.unverified();
488
489 Ok(Self {
490 cert_type,
491 key_tag,
492 algorithm,
493 cert_data,
494 })
495 }
496}
497
498impl RecordData for CERT {
499 fn try_from_rdata(data: RData) -> Result<Self, RData> {
500 match data {
501 RData::CERT(data) => Ok(data),
502 _ => Err(data),
503 }
504 }
505
506 fn try_borrow(data: &RData) -> Option<&Self> {
507 match data {
508 RData::CERT(data) => Some(data),
509 _ => None,
510 }
511 }
512
513 fn record_type(&self) -> RecordType {
514 RecordType::CERT
515 }
516
517 fn into_rdata(self) -> RData {
518 RData::CERT(self)
519 }
520}
521
522impl fmt::Display for CERT {
551 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
552 let cert_data = &data_encoding::BASE64.encode(&self.cert_data);
553
554 write!(
555 f,
556 "{cert_type} {key_tag} {algorithm} {cert_data}",
557 cert_type = self.cert_type,
558 key_tag = &self.key_tag,
559 algorithm = self.algorithm,
560 cert_data = &cert_data
561 )?;
562
563 Ok(())
564 }
565}
566
567#[cfg(test)]
568mod tests {
569 #![allow(clippy::dbg_macro, clippy::print_stdout)]
570
571 use super::*;
572
573 #[test]
574 fn test_cert_type() {
575 assert_eq!(CertType::Reserved, CertType::from(0));
576 assert_eq!(CertType::PKIX, CertType::from(1));
577 assert_eq!(CertType::SPKI, CertType::from(2));
578 assert_eq!(CertType::PGP, CertType::from(3));
579 assert_eq!(CertType::IPKIX, CertType::from(4));
580 assert_eq!(CertType::ISPKI, CertType::from(5));
581 assert_eq!(CertType::IPGP, CertType::from(6));
582 assert_eq!(CertType::ACPKIX, CertType::from(7));
583 assert_eq!(CertType::IACPKIX, CertType::from(8));
584 assert_eq!(CertType::URI, CertType::from(253));
585 assert_eq!(CertType::OID, CertType::from(254));
586 assert_eq!(CertType::Unassigned(9), CertType::from(9));
587 assert_eq!(CertType::Unassigned(90), CertType::from(90));
588 assert_eq!(CertType::Experimental(65280), CertType::from(65280));
589 assert_eq!(CertType::Experimental(65390), CertType::from(65390));
590
591 let cert_type_ianna_9 = CertType::Unassigned(9);
592 let cert_type_ianna_90 = CertType::Unassigned(90);
593 let cert_type_experimental_80 = CertType::Experimental(65280);
594 let cert_type_experimental_90 = CertType::Experimental(65290);
595
596 assert_eq!(u16::from(CertType::Reserved), 0);
597 assert_eq!(u16::from(CertType::PKIX), 1);
598 assert_eq!(u16::from(CertType::SPKI), 2);
599 assert_eq!(u16::from(CertType::PGP), 3);
600 assert_eq!(u16::from(CertType::IPKIX), 4);
601 assert_eq!(u16::from(CertType::ISPKI), 5);
602 assert_eq!(u16::from(CertType::IPGP), 6);
603 assert_eq!(u16::from(CertType::ACPKIX), 7);
604 assert_eq!(u16::from(CertType::IACPKIX), 8);
605 assert_eq!(u16::from(cert_type_ianna_9), 9);
606 assert_eq!(u16::from(cert_type_ianna_90), 90);
607 assert_eq!(u16::from(CertType::URI), 253);
608 assert_eq!(u16::from(CertType::OID), 254);
609 assert_eq!(u16::from(cert_type_experimental_80), 65280);
610 assert_eq!(u16::from(cert_type_experimental_90), 65290);
611 }
612
613 #[test]
614 fn test_algorithm() {
615 assert_eq!(Algorithm::Reserved(0), Algorithm::from(0));
616 assert_eq!(Algorithm::DH, Algorithm::from(2));
617 assert_eq!(Algorithm::DSA, Algorithm::from(3));
618 assert_eq!(Algorithm::ECC, Algorithm::from(4));
619 assert_eq!(Algorithm::RSASHA1, Algorithm::from(5));
620 assert_eq!(Algorithm::DSANSEC3SHA1, Algorithm::from(6));
621 assert_eq!(Algorithm::RSASHA1NSEC3SHA1, Algorithm::from(7));
622 assert_eq!(Algorithm::RSASHA256, Algorithm::from(8));
623 assert_eq!(Algorithm::Reserved(9), Algorithm::from(9));
624 assert_eq!(Algorithm::RSASHA512, Algorithm::from(10));
625 assert_eq!(Algorithm::Reserved(11), Algorithm::from(11));
626 assert_eq!(Algorithm::ECCGOST, Algorithm::from(12));
627 assert_eq!(Algorithm::ECDSAP256SHA256, Algorithm::from(13));
628 assert_eq!(Algorithm::ECDSAP384SHA384, Algorithm::from(14));
629 assert_eq!(Algorithm::ED25519, Algorithm::from(15));
630 assert_eq!(Algorithm::ED448, Algorithm::from(16));
631 assert_eq!(Algorithm::SM2SM3, Algorithm::from(17));
632 assert_eq!(Algorithm::Unassigned(18), Algorithm::from(18));
633 assert_eq!(Algorithm::Unassigned(20), Algorithm::from(20));
634 assert_eq!(Algorithm::ECCGOST12, Algorithm::from(23));
635 assert_eq!(Algorithm::INDIRECT, Algorithm::from(252));
636 assert_eq!(Algorithm::PRIVATEDNS, Algorithm::from(253));
637 assert_eq!(Algorithm::PRIVATEOID, Algorithm::from(254));
638
639 let algorithm_reserved_0 = Algorithm::Reserved(0);
640 let algorithm_reserved_9 = Algorithm::Reserved(9);
641
642 assert_eq!(u8::from(algorithm_reserved_0), 0);
643 assert_eq!(u8::from(Algorithm::DH), 2);
644
645 assert_eq!(u8::from(Algorithm::DSA), 3);
646 assert_eq!(u8::from(Algorithm::ECC), 4);
647 assert_eq!(u8::from(Algorithm::RSASHA1), 5);
648 assert_eq!(u8::from(Algorithm::DSANSEC3SHA1), 6);
649 assert_eq!(u8::from(Algorithm::RSASHA1NSEC3SHA1), 7);
650 assert_eq!(u8::from(Algorithm::RSASHA256), 8);
651 assert_eq!(u8::from(Algorithm::Reserved(9)), 9);
652 assert_eq!(u8::from(Algorithm::RSASHA512), 10);
653 assert_eq!(u8::from(Algorithm::Reserved(11)), 11);
654 assert_eq!(u8::from(Algorithm::ECCGOST), 12);
655 assert_eq!(u8::from(Algorithm::ECDSAP256SHA256), 13);
656 assert_eq!(u8::from(Algorithm::ECDSAP384SHA384), 14);
657 assert_eq!(u8::from(Algorithm::ED25519), 15);
658 assert_eq!(u8::from(Algorithm::ED448), 16);
659 assert_eq!(u8::from(Algorithm::SM2SM3), 17);
660 assert_eq!(u8::from(Algorithm::Unassigned(18)), 18);
661 assert_eq!(u8::from(Algorithm::Unassigned(20)), 20);
662 assert_eq!(u8::from(Algorithm::ECCGOST12), 23);
663 assert_eq!(u8::from(Algorithm::INDIRECT), 252);
664 assert_eq!(u8::from(Algorithm::PRIVATEDNS), 253);
665 assert_eq!(u8::from(Algorithm::PRIVATEOID), 254);
666
667 assert_eq!(u8::from(algorithm_reserved_9), 9);
668 }
669
670 #[test]
671 fn test_valid_cert_data_length() {
672 let valid_cert_data = [1, 2, 3, 4, 5, 6]; let result = CERT::try_from(&valid_cert_data[..]);
674 assert!(
675 result.is_ok(),
676 "Expected a valid result with sufficient cert_data length"
677 );
678 }
679
680 #[test]
681 fn test_cert_creation() {
682 let cert_type = CertType::PKIX;
684 let key_tag = 12345;
685 let algorithm = Algorithm::RSASHA256; let cert_data = [1, 2, 3, 4, 5];
687
688 let cert = CERT {
690 cert_type,
691 key_tag,
692 algorithm,
693 cert_data: cert_data.to_vec(),
694 };
695
696 assert_eq!(cert.cert_type, cert_type);
698 assert_eq!(cert.key_tag, key_tag);
699 assert_eq!(cert.algorithm, algorithm);
700 assert_eq!(cert.cert_data, cert_data);
701 }
702
703 #[test]
704 fn test_cert_empty_cert_data() {
705 let cert_type = CertType::PKIX;
706 let key_tag = 12345;
707 let algorithm = Algorithm::RSASHA256;
708 let cert_data = Vec::new(); let cert = CERT {
712 cert_type,
713 key_tag,
714 algorithm,
715 cert_data,
716 };
717
718 assert_eq!(cert.cert_type, cert_type);
720 assert_eq!(cert.key_tag, key_tag);
721 assert_eq!(cert.algorithm, algorithm);
722 assert!(cert.cert_data.is_empty());
723 }
724
725 #[test]
726 fn test_valid_cert_record() {
727 let valid_cert_record = [
729 0x00, 0x01, 0x30, 0x39, 0x08, 65, 81, 73, 68, ];
734
735 let cert = CERT::try_from(&valid_cert_record[..]);
736 assert!(cert.is_ok(), "Expected valid cert_record");
737
738 let cert = cert.unwrap();
739 assert_eq!(cert.cert_type, CertType::PKIX);
740 assert_eq!(cert.key_tag, 12345);
741 assert_eq!(cert.algorithm, Algorithm::RSASHA256); assert_eq!(cert.cert_data, [65, 81, 73, 68]);
743 }
744
745 #[test]
746 fn test_invalid_cert_record_length() {
747 let invalid_cert_record = [1, 2, 3, 4]; let result = CERT::try_from(&invalid_cert_record[..]);
750 assert!(
751 result.is_err(),
752 "Expected error due to invalid cert_record length"
753 );
754
755 if let Err(e) = result {
756 assert_eq!(e.to_string(), "invalid cert_record length".to_string());
757 }
758 }
759}