1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
use crate::rr::Class;
use crate::DomainName;
use hex::encode;
use std::fmt::{Display, Formatter, Result as FmtResult};

/// The bit at offset 7 of the DNSKEY flags field is the [Zone Key flag].
///
/// [Zone Key flag]: https://tools.ietf.org/html/rfc4034#section-2.1.1
pub const ZONE_KEY_FLAG: u16 = 0b0000_0001_0000_0000;
/// The  bit at offset 15 of the DNSKEY flags field is the [Secure Entry Point flag].
///
/// [Secure Entry Point flag]: https://tools.ietf.org/html/rfc4034#section-2.1.1
pub const SECURE_ENTRY_POINT_FLAG: u16 = 0b0000_0000_0000_0001;
pub const DNSKEY_ZERO_MASK: u16 = 0b1111_1110_1111_1110;

try_from_enum_to_integer! {
    #[repr(u8)]
    #[derive(Debug, Clone, PartialEq, Eq, Hash)]
    /// https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml
    pub enum AlgorithmType {
        Reserved = 0x00,
        RsaMd5 = 0x01,
        DiffiHellman = 0x02,
        DsaSha1 = 0x03,
        EllipticCurve = 0x04,
        RsaSha1 = 0x05,
        DsaNsec3 = 0x06,
        RsaSha1Nsec3Sha1 = 0x07,
        RsaSha256 = 0x08,
        GostR = 0x0c,
        EcDsaP256 = 0x0d,
        EcDsaP386 = 0x0e,
        Ed25519 = 0x0f,
        Ed448 = 0x10,
        Indirect = 0xfc,
        PrivateDns = 0xfd,
        PrivateOid = 0xfe,
    }
}

try_from_enum_to_integer! {
    #[repr(u8)]
    #[derive(Debug, Clone, PartialEq, Eq, Hash)]
    /// https://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml#ds-rr-types-1
    pub enum DigestType {
        Reserved = 0x00,
        Sha1 = 0x01,
        Sha256 = 0x02,
        GostR = 0x03,
        Sha384 = 0x04,
    }
}

#[derive(Debug, PartialEq, Clone, Eq, Hash)]
pub struct DNSKEY {
    pub domain_name: DomainName,
    pub ttl: u32,
    pub class: Class,
    pub zone_key_flag: bool,
    pub secure_entry_point_flag: bool,
    pub algorithm_type: AlgorithmType,
    pub public_key: Vec<u8>,
}

impl DNSKEY {
    pub fn get_flags(&self) -> u16 {
        let mut flags: u16 = 0;
        if self.zone_key_flag {
            flags |= ZONE_KEY_FLAG;
        }
        if self.secure_entry_point_flag {
            flags |= SECURE_ENTRY_POINT_FLAG;
        }
        flags
    }
}

impl Display for DNSKEY {
    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
        write!(
            f,
            "{} {} {} DNSKEY {} 3 {} {}",
            self.domain_name,
            self.ttl,
            self.class,
            self.get_flags(),
            self.algorithm_type.clone() as u8,
            encode(&self.public_key),
        )
    }
}

#[derive(Debug, PartialEq, Clone, Eq, Hash)]
pub struct DS {
    pub domain_name: DomainName,
    pub ttl: u32,
    pub class: Class,
    pub key_tag: u16,
    pub algorithm_type: AlgorithmType,
    pub digest_type: DigestType,
    pub digest: Vec<u8>,
}

impl Display for DS {
    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
        write!(
            f,
            "{} {} {} DS {} {} {} {}",
            self.domain_name,
            self.ttl,
            self.class,
            self.key_tag,
            self.algorithm_type.clone() as u8,
            self.digest_type.clone() as u8,
            encode(&self.digest),
        )
    }
}