6063ba950b1a9150fe544f88422e8024a77fbbdb
[dnssec-prover] / src / ser.rs
1 //! Logic to read and write resource record (streams)
2
3 use alloc::vec::Vec;
4 use alloc::string::String;
5
6 use crate::rr::*;
7 use crate::query::QueryBuf;
8
9 pub(crate) fn read_u8(inp: &mut &[u8]) -> Result<u8, ()> {
10         let res = *inp.get(0).ok_or(())?;
11         *inp = &inp[1..];
12         Ok(res)
13 }
14 pub(crate) fn read_u16(inp: &mut &[u8]) -> Result<u16, ()> {
15         if inp.len() < 2 { return Err(()); }
16         let mut bytes = [0; 2];
17         bytes.copy_from_slice(&inp[..2]);
18         *inp = &inp[2..];
19         Ok(u16::from_be_bytes(bytes))
20 }
21 pub(crate) fn read_u32(inp: &mut &[u8]) -> Result<u32, ()> {
22         if inp.len() < 4 { return Err(()); }
23         let mut bytes = [0; 4];
24         bytes.copy_from_slice(&inp[..4]);
25         *inp = &inp[4..];
26         Ok(u32::from_be_bytes(bytes))
27 }
28
29 pub(crate) fn read_u8_len_prefixed_bytes(inp: &mut &[u8]) -> Result<Vec<u8>, ()> {
30         let len = *inp.get(0).ok_or(())?;
31         *inp = &inp[1..];
32         if inp.len() < len.into() { return Err(()); }
33         let mut res = Vec::with_capacity(len.into());
34         res.extend_from_slice(&inp[..len.into()]);
35         *inp = &inp[len.into()..];
36         Ok(res)
37 }
38
39 pub(crate) fn write_nsec_types_bitmap<W: Writer>(out: &mut W, types: &[u8; 8192]) {
40         for (idx, flags) in types.chunks(32).enumerate() {
41                 debug_assert_eq!(flags.len(), 32);
42                 if flags != &[0; 32] {
43                         let last_nonzero_idx = flags.iter().rposition(|flag| *flag != 0)
44                                 .unwrap_or_else(|| { debug_assert!(false); 0 });
45                         out.write(&(idx as u8).to_be_bytes());
46                         out.write(&(last_nonzero_idx as u8 + 1).to_be_bytes());
47                         out.write(&flags[..last_nonzero_idx + 1]);
48                 }
49         }
50 }
51 pub(crate) fn nsec_types_bitmap_len(types: &[u8; 8192]) -> u16 {
52         let mut total_len = 0;
53         for flags in types.chunks(32) {
54                 debug_assert_eq!(flags.len(), 32);
55                 if flags != &[0; 32] {
56                         total_len += 3 + flags.iter().rposition(|flag| *flag != 0)
57                                 .unwrap_or_else(|| { debug_assert!(false); 0 }) as u16;
58                 }
59         }
60         total_len
61 }
62
63 pub(crate) fn read_nsec_types_bitmap(inp: &mut &[u8]) -> Result<[u8; 8192], ()> {
64         let mut res = [0; 8192];
65         while !inp.is_empty() {
66                 let block = *inp.get(0).ok_or(())?;
67                 let len = *inp.get(1).ok_or(())?;
68                 *inp = &inp[2..];
69                 if inp.len() < len as usize { return Err(()); }
70                 res[block as usize * 32..block as usize * 32 + len as usize]
71                         .copy_from_slice(&inp[..len as usize]);
72                 *inp = &inp[len as usize..];
73         }
74         Ok(res)
75 }
76
77 fn do_read_wire_packet_labels(inp: &mut &[u8], wire_packet: &[u8], name: &mut String, recursion_limit: usize) -> Result<(), ()> {
78         loop {
79                 let len = read_u8(inp)? as usize;
80                 if len == 0 {
81                         if name.is_empty() { *name += "."; }
82                         break;
83                 } else if len >= 0xc0 && recursion_limit > 0 {
84                         let offs = ((len & !0xc0) << 8) | read_u8(inp)? as usize;
85                         if offs >= wire_packet.len() { return Err(()); }
86                         do_read_wire_packet_labels(&mut &wire_packet[offs..], wire_packet, name, recursion_limit - 1)?;
87                         break;
88                 }
89                 if inp.len() <= len { return Err(()); }
90                 *name += core::str::from_utf8(&inp[..len]).map_err(|_| ())?;
91                 *name += ".";
92                 *inp = &inp[len..];
93                 if name.len() > 255 { return Err(()); }
94         }
95         Ok(())
96 }
97
98 fn read_wire_packet_labels(inp: &mut &[u8], wire_packet: &[u8], name: &mut String) -> Result<(), ()> {
99         do_read_wire_packet_labels(inp, wire_packet, name, 255)
100 }
101
102 pub(crate) fn read_wire_packet_name(inp: &mut &[u8], wire_packet: &[u8]) -> Result<Name, ()> {
103         let mut name = String::with_capacity(1024);
104         read_wire_packet_labels(inp, wire_packet, &mut name)?;
105         Ok(name.try_into()?)
106 }
107
108 pub(crate) trait Writer { fn write(&mut self, buf: &[u8]); }
109 impl Writer for Vec<u8> { fn write(&mut self, buf: &[u8]) { self.extend_from_slice(buf); } }
110 impl Writer for QueryBuf { fn write(&mut self, buf: &[u8]) { self.extend_from_slice(buf); } }
111 #[cfg(feature = "validation")]
112 impl Writer for ring::digest::Context { fn write(&mut self, buf: &[u8]) { self.update(buf); } }
113 pub(crate) fn write_name<W: Writer>(out: &mut W, name: &str) {
114         let canonical_name = name.to_ascii_lowercase();
115         if canonical_name == "." {
116                 out.write(&[0]);
117         } else {
118                 for label in canonical_name.split(".") {
119                         out.write(&(label.len() as u8).to_be_bytes());
120                         out.write(label.as_bytes());
121                 }
122         }
123 }
124 pub(crate) fn name_len(name: &Name) -> u16 {
125         if name.as_str() == "." {
126                 1
127         } else {
128                 let mut res = 0;
129                 for label in name.split(".") {
130                         res += 1 + label.len();
131                 }
132                 res as u16
133         }
134 }
135
136 pub(crate) fn parse_wire_packet_rr(inp: &mut &[u8], wire_packet: &[u8]) -> Result<(RR, u32), ()> {
137         let name = read_wire_packet_name(inp, wire_packet)?;
138         let ty = read_u16(inp)?;
139         let class = read_u16(inp)?;
140         if class != 1 { return Err(()); } // We only support the INternet
141         let ttl = read_u32(inp)?;
142         let data_len = read_u16(inp)? as usize;
143         if inp.len() < data_len { return Err(()); }
144         let data = &inp[..data_len];
145         *inp = &inp[data_len..];
146
147         let rr = match ty {
148                 A::TYPE => RR::A(A::read_from_data(name, data, wire_packet)?),
149                 AAAA::TYPE => RR::AAAA(AAAA::read_from_data(name, data, wire_packet)?),
150                 NS::TYPE => RR::NS(NS::read_from_data(name, data, wire_packet)?),
151                 Txt::TYPE => RR::Txt(Txt::read_from_data(name, data, wire_packet)?),
152                 CName::TYPE => RR::CName(CName::read_from_data(name, data, wire_packet)?),
153                 DName::TYPE => RR::DName(DName::read_from_data(name, data, wire_packet)?),
154                 TLSA::TYPE => RR::TLSA(TLSA::read_from_data(name, data, wire_packet)?),
155                 DnsKey::TYPE => RR::DnsKey(DnsKey::read_from_data(name, data, wire_packet)?),
156                 DS::TYPE => RR::DS(DS::read_from_data(name, data, wire_packet)?),
157                 RRSig::TYPE => RR::RRSig(RRSig::read_from_data(name, data, wire_packet)?),
158                 NSec::TYPE => RR::NSec(NSec::read_from_data(name, data, wire_packet)?),
159                 NSec3::TYPE => RR::NSec3(NSec3::read_from_data(name, data, wire_packet)?),
160                 _ => return Err(()),
161         };
162         Ok((rr, ttl))
163 }
164
165 pub(crate) fn parse_rr(inp: &mut &[u8]) -> Result<RR, ()> {
166         parse_wire_packet_rr(inp, &[]).map(|(rr, _)| rr)
167 }
168
169 /// Parse a stream of [`RR`]s from the format described in [RFC 9102](https://www.rfc-editor.org/rfc/rfc9102.html).
170 ///
171 /// Note that this is only the series of `AuthenticationChain` records, and does not read the
172 /// `ExtSupportLifetime` field at the start of a `DnssecChainExtension`.
173 pub fn parse_rr_stream(mut inp: &[u8]) -> Result<Vec<RR>, ()> {
174         let mut res = Vec::with_capacity(32);
175         while !inp.is_empty() {
176                 res.push(parse_rr(&mut inp)?);
177         }
178         Ok(res)
179 }
180
181 /// Writes the given resource record in its wire encoding to the given `Vec`.
182 ///
183 /// An [RFC 9102](https://www.rfc-editor.org/rfc/rfc9102.html) `AuthenticationChain` is simply a
184 /// series of such records with no additional bytes in between.
185 pub fn write_rr<RR: Record>(rr: &RR, ttl: u32, out: &mut Vec<u8>) {
186         write_name(out, rr.name());
187         out.extend_from_slice(&rr.ty().to_be_bytes());
188         out.extend_from_slice(&1u16.to_be_bytes()); // The INternet class
189         out.extend_from_slice(&ttl.to_be_bytes());
190         rr.write_u16_len_prefixed_data(out);
191 }