1use std::net::SocketAddr;
4
5use tox_binary_io::*;
6use tox_crypto::*;
7use tox_packet::dht::packed_node::*;
8use tox_packet::ip_port::*;
9use tox_packet::onion::*;
10use tox_packet::relay::OnionRequest;
11
12#[derive(Clone, Copy, Debug, Eq, PartialEq)]
14pub enum OnionPathType {
15 TCP,
17 UDP
19}
20
21#[derive(Clone, Copy, Debug, Eq, PartialEq)]
23pub struct OnionPathId {
24 pub keys: [PublicKey; 3],
26 pub path_type: OnionPathType,
28}
29
30#[derive(Clone, Debug, Eq, PartialEq)]
32pub struct OnionPathNode {
33 pub public_key: PublicKey,
35 pub temporary_public_key: PublicKey,
37 pub temporary_precomputed_key: PrecomputedKey,
39 pub saddr: SocketAddr,
41}
42
43impl OnionPathNode {
44 pub fn new(node: PackedNode) -> Self {
47 let (temporary_public_key, temporary_secret_key) = gen_keypair();
48 let temporary_precomputed_key = precompute(&node.pk, &temporary_secret_key);
49 OnionPathNode {
50 public_key: node.pk,
51 temporary_public_key,
52 temporary_precomputed_key,
53 saddr: node.saddr,
54 }
55 }
56}
57
58#[derive(Clone, Debug, Eq, PartialEq)]
60pub struct OnionPath {
61 pub nodes: [OnionPathNode; 3],
63 pub path_type: OnionPathType,
65}
66
67impl OnionPath {
68 pub fn new(nodes: [PackedNode; 3], path_type: OnionPathType) -> Self {
71 OnionPath {
72 nodes: [
73 OnionPathNode::new(nodes[0]),
74 OnionPathNode::new(nodes[1]),
75 OnionPathNode::new(nodes[2]),
76 ],
77 path_type,
78 }
79 }
80
81 pub fn id(&self) -> OnionPathId {
83 let keys = [
84 self.nodes[0].public_key,
85 self.nodes[1].public_key,
86 self.nodes[2].public_key,
87 ];
88 OnionPathId {
89 keys,
90 path_type: self.path_type,
91 }
92 }
93
94 pub fn create_udp_onion_request(&self, destination: SocketAddr, inner_onion_request: InnerOnionRequest) -> OnionRequest0 {
97 let nonce = gen_nonce();
98 let mut buf = [0; ONION_MAX_PACKET_SIZE];
99
100 let payload = OnionRequest2Payload {
101 ip_port: IpPort::from_udp_saddr(destination),
102 inner: inner_onion_request,
103 };
104 let (_, size) = payload.to_bytes((&mut buf, 0)).unwrap();
105 let encrypted = seal_precomputed(&buf[..size], &nonce, &self.nodes[2].temporary_precomputed_key);
106
107 let payload = OnionRequest1Payload {
108 ip_port: IpPort::from_udp_saddr(self.nodes[2].saddr),
109 temporary_pk: self.nodes[2].temporary_public_key,
110 inner: encrypted,
111 };
112 let (_, size) = payload.to_bytes((&mut buf, 0)).unwrap();
113 let encrypted = seal_precomputed(&buf[..size], &nonce, &self.nodes[1].temporary_precomputed_key);
114
115 let payload = OnionRequest0Payload {
116 ip_port: IpPort::from_udp_saddr(self.nodes[1].saddr),
117 temporary_pk: self.nodes[1].temporary_public_key,
118 inner: encrypted,
119 };
120 let (_, size) = payload.to_bytes((&mut buf, 0)).unwrap();
121 let encrypted = seal_precomputed(&buf[..size], &nonce, &self.nodes[0].temporary_precomputed_key);
122
123 OnionRequest0 {
124 nonce,
125 temporary_pk: self.nodes[0].temporary_public_key,
126 payload: encrypted
127 }
128 }
129
130 pub fn create_tcp_onion_request(&self, destination: SocketAddr, inner_onion_request: InnerOnionRequest) -> OnionRequest {
133 let nonce = gen_nonce();
134 let mut buf = [0; ONION_MAX_PACKET_SIZE];
135
136 let payload = OnionRequest2Payload {
137 ip_port: IpPort::from_udp_saddr(destination),
138 inner: inner_onion_request,
139 };
140 let (_, size) = payload.to_bytes((&mut buf, 0)).unwrap();
141 let encrypted = seal_precomputed(&buf[..size], &nonce, &self.nodes[2].temporary_precomputed_key);
142
143 let payload = OnionRequest1Payload {
144 ip_port: IpPort::from_udp_saddr(self.nodes[2].saddr),
145 temporary_pk: self.nodes[2].temporary_public_key,
146 inner: encrypted,
147 };
148 let (_, size) = payload.to_bytes((&mut buf, 0)).unwrap();
149 let encrypted = seal_precomputed(&buf[..size], &nonce, &self.nodes[1].temporary_precomputed_key);
150
151 OnionRequest {
152 nonce,
153 ip_port: IpPort::from_udp_saddr(self.nodes[1].saddr),
154 temporary_pk: self.nodes[1].temporary_public_key,
155 payload: encrypted,
156 }
157 }
158}
159
160#[cfg(test)]
161mod tests {
162 use super::*;
163
164 #[test]
165 fn onion_path_node_new() {
166 let saddr = "127.0.0.1:12345".parse().unwrap();
167 let (pk, sk) = gen_keypair();
168 let node = OnionPathNode::new(PackedNode::new(saddr, &pk));
169 let precomputed = precompute(&node.temporary_public_key, &sk);
170 assert_eq!(node.saddr, saddr);
171 assert_eq!(node.public_key, pk);
172 assert_eq!(node.temporary_precomputed_key, precomputed);
173 }
174
175 #[test]
176 fn onion_path_id() {
177 let saddr_1 = "127.0.0.1:12345".parse().unwrap();
178 let saddr_2 = "127.0.0.1:12346".parse().unwrap();
179 let saddr_3 = "127.0.0.1:12347".parse().unwrap();
180 let pk_1 = gen_keypair().0;
181 let pk_2 = gen_keypair().0;
182 let pk_3 = gen_keypair().0;
183 let path = OnionPath::new([
184 PackedNode::new(saddr_1, &pk_1),
185 PackedNode::new(saddr_2, &pk_2),
186 PackedNode::new(saddr_3, &pk_3),
187 ], OnionPathType::UDP);
188 assert_eq!(path.id(), OnionPathId {
189 keys: [pk_1, pk_2, pk_3],
190 path_type: OnionPathType::UDP,
191 });
192 }
193
194 #[test]
195 fn onion_path_create_udp_onion_request() {
196 let saddr_1 = "127.0.0.1:12345".parse().unwrap();
197 let saddr_2 = "127.0.0.1:12346".parse().unwrap();
198 let saddr_3 = "127.0.0.1:12347".parse().unwrap();
199 let pk_1 = gen_keypair().0;
200 let pk_2 = gen_keypair().0;
201 let pk_3 = gen_keypair().0;
202 let path = OnionPath::new([
203 PackedNode::new(saddr_1, &pk_1),
204 PackedNode::new(saddr_2, &pk_2),
205 PackedNode::new(saddr_3, &pk_3),
206 ], OnionPathType::UDP);
207 let inner_onion_request = InnerOnionRequest::InnerOnionAnnounceRequest(InnerOnionAnnounceRequest {
208 nonce: gen_nonce(),
209 pk: gen_keypair().0,
210 payload: vec![42; 123],
211 });
212 let destination = "127.0.0.1:12348".parse().unwrap();
213 let onion_request = path.create_udp_onion_request(destination, inner_onion_request.clone());
214
215 assert_eq!(onion_request.temporary_pk, path.nodes[0].temporary_public_key);
216 let payload = onion_request.get_payload(&path.nodes[0].temporary_precomputed_key).unwrap();
217 assert_eq!(payload.ip_port, IpPort::from_udp_saddr(saddr_2));
218 assert_eq!(payload.temporary_pk, path.nodes[1].temporary_public_key);
219 let payload = open_precomputed(&payload.inner, &onion_request.nonce, &path.nodes[1].temporary_precomputed_key).unwrap();
220 let payload = OnionRequest1Payload::from_bytes(&payload).unwrap().1;
221 assert_eq!(payload.ip_port, IpPort::from_udp_saddr(saddr_3));
222 assert_eq!(payload.temporary_pk, path.nodes[2].temporary_public_key);
223 let payload = open_precomputed(&payload.inner, &onion_request.nonce, &path.nodes[2].temporary_precomputed_key).unwrap();
224 let payload = OnionRequest2Payload::from_bytes(&payload).unwrap().1;
225 assert_eq!(payload.ip_port, IpPort::from_udp_saddr(destination));
226 assert_eq!(payload.inner, inner_onion_request);
227 }
228
229 #[test]
230 fn onion_path_create_tcp_onion_request() {
231 let saddr_1 = "127.0.0.1:12345".parse().unwrap();
232 let saddr_2 = "127.0.0.1:12346".parse().unwrap();
233 let saddr_3 = "127.0.0.1:12347".parse().unwrap();
234 let pk_1 = gen_keypair().0;
235 let pk_2 = gen_keypair().0;
236 let pk_3 = gen_keypair().0;
237 let path = OnionPath::new([
238 PackedNode::new(saddr_1, &pk_1),
239 PackedNode::new(saddr_2, &pk_2),
240 PackedNode::new(saddr_3, &pk_3),
241 ], OnionPathType::UDP);
242 let inner_onion_request = InnerOnionRequest::InnerOnionAnnounceRequest(InnerOnionAnnounceRequest {
243 nonce: gen_nonce(),
244 pk: gen_keypair().0,
245 payload: vec![42; 123],
246 });
247 let destination = "127.0.0.1:12348".parse().unwrap();
248 let onion_request = path.create_tcp_onion_request(destination, inner_onion_request.clone());
249
250 assert_eq!(onion_request.temporary_pk, path.nodes[1].temporary_public_key);
251 assert_eq!(onion_request.ip_port, IpPort::from_udp_saddr(saddr_2));
252 let payload = open_precomputed(&onion_request.payload, &onion_request.nonce, &path.nodes[1].temporary_precomputed_key).unwrap();
253 let payload = OnionRequest1Payload::from_bytes(&payload).unwrap().1;
254 assert_eq!(payload.ip_port, IpPort::from_udp_saddr(saddr_3));
255 assert_eq!(payload.temporary_pk, path.nodes[2].temporary_public_key);
256 let payload = open_precomputed(&payload.inner, &onion_request.nonce, &path.nodes[2].temporary_precomputed_key).unwrap();
257 let payload = OnionRequest2Payload::from_bytes(&payload).unwrap().1;
258 assert_eq!(payload.ip_port, IpPort::from_udp_saddr(destination));
259 assert_eq!(payload.inner, inner_onion_request);
260 }
261}