dynnsd/
packet.rs

1
2use sha2::{Sha256,Digest};
3use crate::{IP_LEN, HASH_LEN, HDR_LEN, IP_REQUEST, IP_CONFIRM, IP_CREATED, IP_RESPONSE, ZONE_CHANGE, ZONE_CHANGED, ZONE_HUP};
4use rand::RngCore;
5
6pub const PACKET_LEN: usize = HDR_LEN + IP_LEN + HASH_LEN + HASH_LEN;
7
8pub fn packet_type() -> u8 {
9    0
10}
11
12/// Create a signed `IP_REQUEST` packet, client wants to know its IP address.
13pub fn create_ip_request_packet(secret: &[u8; HASH_LEN]) -> [u8; PACKET_LEN] {
14
15    let ip = [0u8; IP_LEN];
16    let mut random = [0u8; HASH_LEN];
17    rand::thread_rng().fill_bytes(&mut random);
18
19    let mut sha256 = Sha256::new();
20    sha256.input(IP_REQUEST);
21    sha256.input(ip);
22    sha256.input(random);
23    sha256.input(secret);
24
25    let mut packet: [u8; PACKET_LEN] = [0; PACKET_LEN];
26    packet[0..HDR_LEN].copy_from_slice(&IP_REQUEST);
27    packet[HDR_LEN..HDR_LEN+IP_LEN].copy_from_slice(&ip);
28    packet[HDR_LEN+IP_LEN..HDR_LEN+IP_LEN+HASH_LEN].copy_from_slice(&random);
29    packet[HDR_LEN+IP_LEN+HASH_LEN..PACKET_LEN].copy_from_slice(sha256.result().as_slice());
30
31    return packet;
32}
33
34/// Create a signed `IP_RESPONSE` packet, server responds with the clients IP
35pub fn create_ip_response_packet(ip: [u8; IP_LEN], secret: &[u8; HASH_LEN]) -> [u8; PACKET_LEN] {
36
37    let mut random = [0u8; HASH_LEN];
38    rand::thread_rng().fill_bytes(&mut random);
39
40    let mut sha256 = Sha256::new();
41    sha256.input(IP_RESPONSE);
42    sha256.input(ip);
43    sha256.input(random);
44    sha256.input(secret);
45
46    let mut packet: [u8; PACKET_LEN] = [0; PACKET_LEN];
47    packet[0..HDR_LEN].copy_from_slice(&IP_RESPONSE);
48    packet[HDR_LEN..HDR_LEN+IP_LEN].copy_from_slice(&ip);
49    packet[HDR_LEN+IP_LEN..HDR_LEN+IP_LEN+HASH_LEN].copy_from_slice(&random);
50    packet[HDR_LEN+IP_LEN+HASH_LEN..PACKET_LEN].copy_from_slice(sha256.result().as_slice());
51    return packet;
52}
53
54/// Create a signed `IP_CONFIRM` packet, client sends this to all the DNS nodes
55pub fn create_ip_confirm_packet(ip: [u8; IP_LEN], host_index: u8, secret: &[u8; HASH_LEN]) -> [u8; PACKET_LEN] {
56
57    let mut random = [0u8; HASH_LEN];
58    rand::thread_rng().fill_bytes(&mut random);
59    random[0] = host_index;
60
61    let mut sha256 = Sha256::new();
62    sha256.input(IP_CONFIRM);
63    sha256.input(ip);
64    sha256.input(random);
65    sha256.input(secret);
66
67    let mut packet: [u8; PACKET_LEN] = [0; PACKET_LEN];
68    packet[0..HDR_LEN].copy_from_slice(&IP_CONFIRM);
69    packet[HDR_LEN..HDR_LEN+IP_LEN].copy_from_slice(&ip);
70    packet[HDR_LEN+IP_LEN..HDR_LEN+IP_LEN+HASH_LEN].copy_from_slice(&random);
71    packet[HDR_LEN+IP_LEN+HASH_LEN..PACKET_LEN].copy_from_slice(sha256.result().as_slice());
72
73    return packet;
74}
75
76/// Create a signed `IP_CREATED` packet
77pub fn create_ip_created_packet(host_index: u8, secret: &[u8; HASH_LEN]) -> [u8; PACKET_LEN] {
78    let ip = [host_index, 0, 0, 0];
79    let mut random = [0u8; HASH_LEN];
80    rand::thread_rng().fill_bytes(&mut random);
81
82    let mut sha256 = Sha256::new();
83    sha256.input(IP_CREATED);
84    sha256.input(ip);
85    sha256.input(random);
86    sha256.input(secret);
87
88    let mut packet = [0u8; PACKET_LEN];
89    packet[0..HDR_LEN].copy_from_slice(&IP_CREATED);
90    packet[HDR_LEN..HDR_LEN+IP_LEN].copy_from_slice(&ip);
91    packet[HDR_LEN+IP_LEN..HDR_LEN+IP_LEN+HASH_LEN].copy_from_slice(&random);
92    packet[HDR_LEN+IP_LEN+HASH_LEN..PACKET_LEN].copy_from_slice(sha256.result().as_slice());
93
94    return packet;
95}
96
97/// Create a signed `ZONE_CHANGE` packet
98pub fn create_zone_change(zone_index: u8, secret: &[u8; HASH_LEN]) -> [u8; PACKET_LEN] {
99    let ip = [zone_index, 0, 0, 0];
100    let mut random = [0u8; HASH_LEN];
101    rand::thread_rng().fill_bytes(&mut random);
102
103    let mut sha256 = Sha256::new();
104    sha256.input(ZONE_CHANGE);
105    sha256.input(ip);
106    sha256.input(random);
107    sha256.input(secret);
108
109    let mut packet = [0u8; PACKET_LEN];
110    packet[0..HDR_LEN].copy_from_slice(&ZONE_CHANGE);
111    packet[HDR_LEN..HDR_LEN+IP_LEN].copy_from_slice(&ip);
112    packet[HDR_LEN+IP_LEN..HDR_LEN+IP_LEN+HASH_LEN].copy_from_slice(&random);
113    packet[HDR_LEN+IP_LEN+HASH_LEN..PACKET_LEN].copy_from_slice(sha256.result().as_slice());
114
115    return packet;
116}
117
118/// Create a signed `ZONE_CHANGED` packet
119pub fn create_zone_changed(zone_index: u8, secret: &[u8; HASH_LEN]) -> [u8; PACKET_LEN] {
120    let ip = [zone_index, 0, 0, 0];
121    let mut random = [0u8; HASH_LEN];
122    rand::thread_rng().fill_bytes(&mut random);
123
124    let mut sha256 = Sha256::new();
125    sha256.input(ZONE_CHANGED);
126    sha256.input(ip);
127    sha256.input(random);
128    sha256.input(secret);
129
130    let mut packet = [0u8; PACKET_LEN];
131    packet[0..HDR_LEN].copy_from_slice(&ZONE_CHANGED);
132    packet[HDR_LEN..HDR_LEN+IP_LEN].copy_from_slice(&ip);
133    packet[HDR_LEN+IP_LEN..HDR_LEN+IP_LEN+HASH_LEN].copy_from_slice(&random);
134    packet[HDR_LEN+IP_LEN+HASH_LEN..PACKET_LEN].copy_from_slice(sha256.result().as_slice());
135
136    return packet;
137}
138
139/// Create a signed `ZONE_HUP` packet
140pub fn create_zone_hup_packet(secret: &[u8; HASH_LEN]) -> [u8; PACKET_LEN] {
141    let ip = [0, 0, 0, 0];
142    let mut random = [0u8; HASH_LEN];
143    rand::thread_rng().fill_bytes(&mut random);
144
145    let mut sha256 = Sha256::new();
146    sha256.input(ZONE_HUP);
147    sha256.input(ip);
148    sha256.input(random);
149    sha256.input(secret);
150
151    let mut packet = [0u8; PACKET_LEN];
152    packet[0..HDR_LEN].copy_from_slice(&ZONE_HUP);
153    packet[HDR_LEN..HDR_LEN+IP_LEN].copy_from_slice(&ip);
154    packet[HDR_LEN+IP_LEN..HDR_LEN+IP_LEN+HASH_LEN].copy_from_slice(&random);
155    packet[HDR_LEN+IP_LEN+HASH_LEN..PACKET_LEN].copy_from_slice(sha256.result().as_slice());
156
157    return packet;
158}
159
160/// validate a packets signature
161/// returns the message type & ip address if it is signed
162pub fn validate_packet(len: usize, packet: [u8; PACKET_LEN], secret: &[u8; HASH_LEN]) -> Result<(u8, [u8; IP_LEN]), ()> {
163    if len != PACKET_LEN || 23 != packet[0] {
164        return Err(());
165    }
166
167    let mut sha256 = Sha256::new();
168    sha256.input(&packet[0..HDR_LEN]);
169    sha256.input(&packet[HDR_LEN..HDR_LEN+IP_LEN]);
170    sha256.input(&packet[HDR_LEN+IP_LEN..HDR_LEN+IP_LEN+HASH_LEN]);
171    sha256.input(secret);
172
173    // compare iterators over u8
174    return if sha256.result().iter().eq(packet[HDR_LEN+IP_LEN+HASH_LEN..PACKET_LEN].iter()) {
175
176        let mut ip: [u8; IP_LEN] = [0; IP_LEN];
177        ip.copy_from_slice(&packet[HDR_LEN..HDR_LEN + IP_LEN]);
178
179        Ok((packet[1], ip))
180    } else {
181        Err(())
182    }
183
184}
185
186
187#[cfg(test)]
188mod tests {
189    use super::*;
190
191    #[test]
192    fn test_happy() {
193        let mut ip: [u8; IP_LEN] = [0; IP_LEN];
194        ip[0] = 10;
195        ip[IP_LEN - 1] = 23;
196        let mut random: [u8; HASH_LEN] = [0; HASH_LEN];
197        random[0] = 23;
198        random[HASH_LEN - 1] = 24;
199        let secret: [u8; HASH_LEN] = [0; HASH_LEN];
200
201        let packet = create_ip_request_packet(&secret);
202        assert!(validate_packet(packet.len(), packet, &secret).ok().is_some());
203
204        let packet = create_ip_response_packet([10 as u8, 0, 0, 23], &secret);
205        assert!(validate_packet(packet.len(), packet, &secret).ok().is_some());
206
207        let packet = create_ip_confirm_packet([10 as u8, 0, 0, 23], 0, &secret);
208        assert!(validate_packet(packet.len(), packet, &secret).ok().is_some());
209
210        let packet = create_ip_created_packet( 0, &secret);
211        assert!(validate_packet(packet.len(), packet, &secret).ok().is_some());
212    }
213}