462ad9260deb8c19623b9233577f280a2d8a32d0
[dnssec-prover] / src / ser.rs
1 //! Serialization/Deserialization logic lives here
2
3 use alloc::vec::Vec;
4 use alloc::string::String;
5
6 use ring::signature;
7
8 use crate::rr::*;
9
10 pub(crate) fn read_u8(inp: &mut &[u8]) -> Result<u8, ()> {
11         let res = *inp.get(0).ok_or(())?;
12         *inp = &inp[1..];
13         Ok(res)
14 }
15 pub(crate) fn read_u16(inp: &mut &[u8]) -> Result<u16, ()> {
16         if inp.len() < 2 { return Err(()); }
17         let mut bytes = [0; 2];
18         bytes.copy_from_slice(&inp[..2]);
19         *inp = &inp[2..];
20         Ok(u16::from_be_bytes(bytes))
21 }
22 pub(crate) fn read_u32(inp: &mut &[u8]) -> Result<u32, ()> {
23         if inp.len() < 4 { return Err(()); }
24         let mut bytes = [0; 4];
25         bytes.copy_from_slice(&inp[..4]);
26         *inp = &inp[4..];
27         Ok(u32::from_be_bytes(bytes))
28 }
29
30 fn read_wire_packet_labels(inp: &mut &[u8], wire_packet: &[u8], name: &mut String) -> Result<(), ()> {
31         loop {
32                 let len = read_u8(inp)? as usize;
33                 if len == 0 {
34                         if name.is_empty() { *name += "."; }
35                         break;
36                 } else if len >= 0xc0 {
37                         let offs = ((len & !0xc0) << 8) | read_u8(inp)? as usize;
38                         if offs >= wire_packet.len() { return Err(()); }
39                         read_wire_packet_labels(&mut &wire_packet[offs..], wire_packet, name)?;
40                         break;
41                 }
42                 if inp.len() <= len { return Err(()); }
43                 *name += core::str::from_utf8(&inp[..len]).map_err(|_| ())?;
44                 *name += ".";
45                 *inp = &inp[len..];
46                 if name.len() > 255 { return Err(()); }
47         }
48         Ok(())
49 }
50
51 pub(crate) fn read_wire_packet_name(inp: &mut &[u8], wire_packet: &[u8]) -> Result<Name, ()> {
52         let mut name = String::with_capacity(1024);
53         read_wire_packet_labels(inp, wire_packet, &mut name)?;
54         Ok(name.try_into()?)
55 }
56
57 pub(crate) trait Writer { fn write(&mut self, buf: &[u8]); }
58 impl Writer for Vec<u8> { fn write(&mut self, buf: &[u8]) { self.extend_from_slice(buf); } }
59 impl Writer for ring::digest::Context { fn write(&mut self, buf: &[u8]) { self.update(buf); } }
60 pub(crate) fn write_name<W: Writer>(out: &mut W, name: &str) {
61         let canonical_name = name.to_ascii_lowercase();
62         if canonical_name == "." {
63                 out.write(&[0]);
64         } else {
65                 for label in canonical_name.split(".") {
66                         out.write(&(label.len() as u8).to_be_bytes());
67                         out.write(label.as_bytes());
68                 }
69         }
70 }
71 pub(crate) fn name_len(name: &Name) -> u16 {
72         if name.as_str() == "." {
73                 1
74         } else {
75                 let mut res = 0;
76                 for label in name.split(".") {
77                         res += 1 + label.len();
78                 }
79                 res as u16
80         }
81 }
82
83 pub(crate) fn parse_wire_packet_rr(inp: &mut &[u8], wire_packet: &[u8]) -> Result<(RR, u32), ()> {
84         let name = read_wire_packet_name(inp, wire_packet)?;
85         let ty = read_u16(inp)?;
86         let class = read_u16(inp)?;
87         if class != 1 { return Err(()); } // We only support the INternet
88         let ttl = read_u32(inp)?;
89         let data_len = read_u16(inp)? as usize;
90         if inp.len() < data_len { return Err(()); }
91         let data = &inp[..data_len];
92         *inp = &inp[data_len..];
93
94         let rr = match ty {
95                 A::TYPE => RR::A(A::read_from_data(name, data, wire_packet)?),
96                 AAAA::TYPE => RR::AAAA(AAAA::read_from_data(name, data, wire_packet)?),
97                 NS::TYPE => RR::NS(NS::read_from_data(name, data, wire_packet)?),
98                 Txt::TYPE => RR::Txt(Txt::read_from_data(name, data, wire_packet)?),
99                 CName::TYPE => RR::CName(CName::read_from_data(name, data, wire_packet)?),
100                 TLSA::TYPE => RR::TLSA(TLSA::read_from_data(name, data, wire_packet)?),
101                 DnsKey::TYPE => RR::DnsKey(DnsKey::read_from_data(name, data, wire_packet)?),
102                 DS::TYPE => RR::DS(DS::read_from_data(name, data, wire_packet)?),
103                 RRSig::TYPE => RR::RRSig(RRSig::read_from_data(name, data, wire_packet)?),
104                 _ => return Err(()),
105         };
106         Ok((rr, ttl))
107 }
108
109 pub(crate) fn parse_rr(inp: &mut &[u8]) -> Result<RR, ()> {
110         parse_wire_packet_rr(inp, &[]).map(|(rr, _)| rr)
111 }
112
113 pub(crate) fn bytes_to_rsa_pk<'a>(pubkey: &'a [u8])
114 -> Result<signature::RsaPublicKeyComponents<&'a [u8]>, ()> {
115         if pubkey.len() <= 3 { return Err(()); }
116
117         let mut pos = 0;
118         let exponent_length;
119         if pubkey[0] == 0 {
120                 exponent_length = ((pubkey[1] as usize) << 8) | (pubkey[2] as usize);
121                 pos += 3;
122         } else {
123                 exponent_length = pubkey[0] as usize;
124                 pos += 1;
125         }
126
127         if pubkey.len() <= pos + exponent_length { return Err(()); }
128         Ok(signature::RsaPublicKeyComponents {
129                 n: &pubkey[pos + exponent_length..],
130                 e: &pubkey[pos..pos + exponent_length]
131         })
132 }