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
12pub 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
34pub 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
54pub 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
76pub 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
97pub 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
118pub 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
139pub 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
160pub 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 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}