flex_dns/rdata/
rrsig.rs

1use crate::{Buffer, DnsMessage, DnsMessageError, MutBuffer};
2use crate::characters::Characters;
3use crate::name::DnsName;
4use crate::parse::Parse;
5use crate::rdata::{RData, RDataParse};
6use crate::write::WriteBytes;
7
8/// # DNSSEC signature record
9/// This record is used to sign other records. It is used in conjunction with the
10/// DnsKey record to verify the authenticity of a record.
11#[derive(Copy, Clone, Debug, PartialEq)]
12pub struct RRSig<'a> {
13    /// The type of record that is covered by this signature.
14    pub type_covered: u16,
15    /// The algorithm used to create the signature.
16    pub algorithm: u8,
17    /// The number of seconds the signature is valid for.
18    pub original_ttl: u32,
19    /// The time at which the signature was created.
20    pub signature_expiration: u32,
21    /// The time at which the signature was last refreshed.
22    pub signature_inception: u32,
23    /// The key tag of the key that was used to create the signature.
24    pub key_tag: u16,
25    /// The name of the zone that this signature was created for.
26    pub signer_name: DnsName<'a>,
27    /// The signature.
28    pub signature: Characters<'a>,
29}
30
31impl<'a> RDataParse<'a> for RRSig<'a> {
32    #[inline]
33    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
34        let type_covered = u16::parse(rdata.buffer, i)?;
35        let algorithm = u8::parse(rdata.buffer, i)?;
36        let original_ttl = u32::parse(rdata.buffer, i)?;
37        let signature_expiration = u32::parse(rdata.buffer, i)?;
38        let signature_inception = u32::parse(rdata.buffer, i)?;
39        let key_tag = u16::parse(rdata.buffer, i)?;
40        let signer_name = DnsName::parse(rdata.buffer, i)?;
41        let signature = Characters::parse(rdata.buffer, i)?;
42
43        Ok(Self {
44            type_covered,
45            algorithm,
46            original_ttl,
47            signature_expiration,
48            signature_inception,
49            key_tag,
50            signer_name,
51            signature,
52        })
53    }
54}
55
56impl<'a> WriteBytes for RRSig<'a> {
57    #[inline]
58    fn write<
59        const PTR_STORAGE: usize,
60        const DNS_SECTION: usize,
61        B: MutBuffer + Buffer,
62    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<usize, DnsMessageError> {
63        let mut bytes = 0;
64
65        bytes += self.type_covered.write(message)?;
66        bytes += self.algorithm.write(message)?;
67        bytes += self.original_ttl.write(message)?;
68        bytes += self.signature_expiration.write(message)?;
69        bytes += self.signature_inception.write(message)?;
70        bytes += self.key_tag.write(message)?;
71        bytes += self.signer_name.write(message)?;
72        bytes += self.signature.write(message)?;
73
74        Ok(bytes)
75    }
76}
77
78#[cfg(test)]
79mod test {
80    use crate::rdata::testutils::parse_write_test;
81
82    use super::*;
83
84    parse_write_test!(
85        42,
86        [
87            0x00, 0x0e, // type covered
88            0x05, // algorithm
89            0x00, 0x00, 0x00, 0x0a, // original ttl
90            0x00, 0x00, 0x00, 0x0b, // signature expiration
91            0x00, 0x00, 0x00, 0x0c, // signature inception
92            0x00, 0x0d, // key tag
93            0x03, b'w', b'w', b'w',
94            0x07, b'e', b'x', b'a', b'm', b'p', b'l', b'e',
95            0x03, b'c', b'o', b'm',
96            0x00, // signer name
97            0x07, b'f', b'o', b'o', b'-', b'b', b'a', b'r', // signature
98        ],
99        RRSig {
100            type_covered: 14,
101            algorithm: 5,
102            original_ttl: 10,
103            signature_expiration: 11,
104            signature_inception: 12,
105            key_tag: 13,
106            signer_name: unsafe { DnsName::new_unchecked(b"\x03www\x07example\x03com\x00") },
107            signature: unsafe { Characters::new_unchecked(b"foo-bar") },
108        },
109    );
110}