/work/toxcore/net_crypto.h
Line | Count | Source |
1 | | /* SPDX-License-Identifier: GPL-3.0-or-later |
2 | | * Copyright © 2016-2025 The TokTok team. |
3 | | * Copyright © 2013 Tox project. |
4 | | */ |
5 | | |
6 | | /** |
7 | | * Functions for the core network crypto. |
8 | | */ |
9 | | #ifndef C_TOXCORE_TOXCORE_NET_CRYPTO_H |
10 | | #define C_TOXCORE_TOXCORE_NET_CRYPTO_H |
11 | | |
12 | | #include "DHT.h" |
13 | | #include "TCP_client.h" |
14 | | #include "TCP_connection.h" |
15 | | #include "attributes.h" |
16 | | #include "crypto_core.h" |
17 | | #include "logger.h" |
18 | | #include "mem.h" |
19 | | #include "mono_time.h" |
20 | | #include "net_profile.h" |
21 | | #include "network.h" |
22 | | |
23 | | #ifdef __cplusplus |
24 | | extern "C" { |
25 | | #endif |
26 | | |
27 | | /*** Crypto payloads. */ |
28 | | |
29 | | /*** Ranges. */ |
30 | | |
31 | | /** Packets in this range are reserved for net_crypto events_alloc use. */ |
32 | | #define PACKET_ID_RANGE_RESERVED_START 0 |
33 | | #define PACKET_ID_RANGE_RESERVED_END 15 |
34 | | /** Packets in this range are reserved for Messenger use. */ |
35 | 848k | #define PACKET_ID_RANGE_LOSSLESS_START 16 |
36 | | #define PACKET_ID_RANGE_LOSSLESS_NORMAL_START 16 |
37 | | #define PACKET_ID_RANGE_LOSSLESS_NORMAL_END 159 |
38 | | /** Packets in this range can be used for anything. */ |
39 | 19.8k | #define PACKET_ID_RANGE_LOSSLESS_CUSTOM_START 160 |
40 | 40.2k | #define PACKET_ID_RANGE_LOSSLESS_CUSTOM_END 191 |
41 | 424k | #define PACKET_ID_RANGE_LOSSLESS_END 191 |
42 | | /** Packets in this range are reserved for AV use. */ |
43 | 138k | #define PACKET_ID_RANGE_LOSSY_START 192 |
44 | 6 | #define PACKET_ID_RANGE_LOSSY_AV_START 192 |
45 | 54 | #define PACKET_ID_RANGE_LOSSY_AV_END 199 |
46 | | /** Packets in this range can be used for anything. */ |
47 | 1.21k | #define PACKET_ID_RANGE_LOSSY_CUSTOM_START 200 |
48 | | #define PACKET_ID_RANGE_LOSSY_CUSTOM_END 254 |
49 | 137k | #define PACKET_ID_RANGE_LOSSY_END 254 |
50 | | |
51 | | /*** Messages. */ |
52 | | |
53 | | typedef enum Packet_Id { |
54 | | PACKET_ID_REQUEST = 1, // Used to request unreceived packets |
55 | | PACKET_ID_KILL = 2, // Used to kill connection |
56 | | |
57 | | PACKET_ID_ONLINE = 24, |
58 | | PACKET_ID_OFFLINE = 25, |
59 | | PACKET_ID_NICKNAME = 48, |
60 | | PACKET_ID_STATUSMESSAGE = 49, |
61 | | PACKET_ID_USERSTATUS = 50, |
62 | | PACKET_ID_TYPING = 51, |
63 | | PACKET_ID_MESSAGE = 64, |
64 | | PACKET_ID_ACTION = 65, // PACKET_ID_MESSAGE + MESSAGE_ACTION |
65 | | PACKET_ID_MSI = 69, // Used by AV to setup calls and etc |
66 | | PACKET_ID_FILE_SENDREQUEST = 80, |
67 | | PACKET_ID_FILE_CONTROL = 81, |
68 | | PACKET_ID_FILE_DATA = 82, |
69 | | PACKET_ID_INVITE_GROUPCHAT = 95, |
70 | | PACKET_ID_INVITE_CONFERENCE = 96, |
71 | | PACKET_ID_ONLINE_PACKET = 97, |
72 | | PACKET_ID_DIRECT_CONFERENCE = 98, |
73 | | PACKET_ID_MESSAGE_CONFERENCE = 99, |
74 | | PACKET_ID_REJOIN_CONFERENCE = 100, |
75 | | PACKET_ID_LOSSY_CONFERENCE = 199, |
76 | | } Packet_Id; |
77 | | |
78 | | /** Maximum size of receiving and sending packet buffers. */ |
79 | 3.37M | #define CRYPTO_PACKET_BUFFER_SIZE 32768 // Must be a power of 2 |
80 | | |
81 | | /** Minimum packet rate per second. */ |
82 | 866k | #define CRYPTO_PACKET_MIN_RATE 4.0 |
83 | | |
84 | | /** Minimum packet queue max length. */ |
85 | 194k | #define CRYPTO_MIN_QUEUE_LENGTH 64 |
86 | | |
87 | | /** Maximum total size of packets that net_crypto sends. */ |
88 | 3.02M | #define MAX_CRYPTO_PACKET_SIZE (uint16_t)1400 |
89 | | |
90 | 1.72M | #define CRYPTO_DATA_PACKET_MIN_SIZE (uint16_t)(1 + sizeof(uint16_t) + (sizeof(uint32_t) + sizeof(uint32_t)) + CRYPTO_MAC_SIZE) |
91 | | |
92 | | /** Max size of data in packets */ |
93 | 1.49M | #define MAX_CRYPTO_DATA_SIZE (uint16_t)(MAX_CRYPTO_PACKET_SIZE - CRYPTO_DATA_PACKET_MIN_SIZE) |
94 | | |
95 | | /** Interval in ms between sending cookie request/handshake packets. */ |
96 | 489k | #define CRYPTO_SEND_PACKET_INTERVAL 1000 |
97 | | |
98 | | /** |
99 | | * The maximum number of times we try to send the cookie request and handshake |
100 | | * before giving up. |
101 | | */ |
102 | 14.4k | #define MAX_NUM_SENDPACKET_TRIES 8 |
103 | | |
104 | | /** The timeout of no received UDP packets before the direct UDP connection is considered dead. */ |
105 | 1.47M | #define UDP_DIRECT_TIMEOUT 8 |
106 | | |
107 | | #define MAX_TCP_CONNECTIONS 64 |
108 | | #define MAX_TCP_RELAYS_PEER 4 |
109 | | |
110 | | /** All packets will be padded a number of bytes based on this number. */ |
111 | 341k | #define CRYPTO_MAX_PADDING 8 |
112 | | |
113 | | /** |
114 | | * Base current transfer speed on last CONGESTION_QUEUE_ARRAY_SIZE number of points taken |
115 | | * at the dT defined in net_crypto.c |
116 | | */ |
117 | 4.63M | #define CONGESTION_QUEUE_ARRAY_SIZE 12 |
118 | 2.04M | #define CONGESTION_LAST_SENT_ARRAY_SIZE (CONGESTION_QUEUE_ARRAY_SIZE * 2) |
119 | | |
120 | | /** Default connection ping in ms. */ |
121 | 1.87k | #define DEFAULT_PING_CONNECTION 1000 |
122 | 131 | #define DEFAULT_TCP_PING_CONNECTION 500 |
123 | | |
124 | | typedef struct Net_Crypto Net_Crypto; |
125 | | |
126 | | const uint8_t *_Nonnull nc_get_self_public_key(const Net_Crypto *_Nonnull c); |
127 | | const uint8_t *_Nonnull nc_get_self_secret_key(const Net_Crypto *_Nonnull c); |
128 | | TCP_Connections *_Nonnull nc_get_tcp_c(const Net_Crypto *_Nonnull c); |
129 | | DHT *_Nonnull nc_get_dht(const Net_Crypto *_Nonnull c); |
130 | | |
131 | | typedef struct New_Connection { |
132 | | IP_Port source; |
133 | | uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE]; /* The real public key of the peer. */ |
134 | | uint8_t dht_public_key[CRYPTO_PUBLIC_KEY_SIZE]; /* The dht public key of the peer. */ |
135 | | uint8_t recv_nonce[CRYPTO_NONCE_SIZE]; /* Nonce of received packets. */ |
136 | | uint8_t peersessionpublic_key[CRYPTO_PUBLIC_KEY_SIZE]; /* The public key of the peer. */ |
137 | | uint8_t *_Nullable cookie; |
138 | | uint8_t cookie_length; |
139 | | } New_Connection; |
140 | | |
141 | | typedef int connection_status_cb(void *_Nonnull object, int id, bool status, void *_Nullable userdata); |
142 | | typedef int connection_data_cb(void *_Nonnull object, int id, const uint8_t *_Nonnull data, uint16_t length, void *_Nullable userdata); |
143 | | typedef int connection_lossy_data_cb(void *_Nonnull object, int id, const uint8_t *_Nonnull data, uint16_t length, void *_Nullable userdata); |
144 | | typedef void dht_pk_cb(void *_Nonnull object, int32_t number, const uint8_t *_Nonnull dht_public_key, void *_Nullable userdata); |
145 | | typedef int new_connection_cb(void *_Nonnull object, const New_Connection *_Nonnull n_c); |
146 | | |
147 | | /** @brief Set function to be called when someone requests a new connection to us. |
148 | | * |
149 | | * The set function should return -1 on failure and 0 on success. |
150 | | * |
151 | | * n_c is only valid for the duration of the function call. |
152 | | */ |
153 | | void new_connection_handler(Net_Crypto *_Nonnull c, new_connection_cb *_Nonnull new_connection_callback, void *_Nonnull object); |
154 | | |
155 | | /** @brief Accept a crypto connection. |
156 | | * |
157 | | * return -1 on failure. |
158 | | * return connection id on success. |
159 | | */ |
160 | | int accept_crypto_connection(Net_Crypto *_Nonnull c, const New_Connection *_Nonnull n_c); |
161 | | |
162 | | /** @brief Create a crypto connection. |
163 | | * If one to that real public key already exists, return it. |
164 | | * |
165 | | * return -1 on failure. |
166 | | * return connection id on success. |
167 | | */ |
168 | | int new_crypto_connection(Net_Crypto *_Nonnull c, const uint8_t *_Nonnull real_public_key, const uint8_t *_Nonnull dht_public_key); |
169 | | |
170 | | /** @brief Set the direct ip of the crypto connection. |
171 | | * |
172 | | * Connected is 0 if we are not sure we are connected to that person, 1 if we are sure. |
173 | | * |
174 | | * return -1 on failure. |
175 | | * return 0 on success. |
176 | | */ |
177 | | int set_direct_ip_port(Net_Crypto *_Nonnull c, int crypt_connection_id, const IP_Port *_Nonnull ip_port, bool connected); |
178 | | |
179 | | /** @brief Set function to be called when connection with crypt_connection_id goes connects/disconnects. |
180 | | * |
181 | | * The set function should return -1 on failure and 0 on success. |
182 | | * Note that if this function is set, the connection will clear itself on disconnect. |
183 | | * Object and id will be passed to this function untouched. |
184 | | * status is 1 if the connection is going online, 0 if it is going offline. |
185 | | * |
186 | | * return -1 on failure. |
187 | | * return 0 on success. |
188 | | */ |
189 | | int connection_status_handler(const Net_Crypto *_Nonnull c, int crypt_connection_id, connection_status_cb *_Nonnull connection_status_callback, void *_Nonnull object, int id); |
190 | | |
191 | | /** @brief Set function to be called when connection with crypt_connection_id receives a lossless data packet of length. |
192 | | * |
193 | | * The set function should return -1 on failure and 0 on success. |
194 | | * Object and id will be passed to this function untouched. |
195 | | * |
196 | | * return -1 on failure. |
197 | | * return 0 on success. |
198 | | */ |
199 | | int connection_data_handler(const Net_Crypto *_Nonnull c, int crypt_connection_id, connection_data_cb *_Nonnull connection_data_callback, void *_Nonnull object, int id); |
200 | | |
201 | | /** @brief Set function to be called when connection with crypt_connection_id receives a lossy data packet of length. |
202 | | * |
203 | | * The set function should return -1 on failure and 0 on success. |
204 | | * Object and id will be passed to this function untouched. |
205 | | * |
206 | | * return -1 on failure. |
207 | | * return 0 on success. |
208 | | */ |
209 | | int connection_lossy_data_handler(const Net_Crypto *_Nonnull c, int crypt_connection_id, connection_lossy_data_cb *_Nonnull connection_lossy_data_callback, void *_Nonnull object, int id); |
210 | | |
211 | | /** @brief Set the function for this friend that will be callbacked with object and number if |
212 | | * the friend sends us a different dht public key than we have associated to him. |
213 | | * |
214 | | * If this function is called, the connection should be recreated with the new public key. |
215 | | * |
216 | | * object and number will be passed as argument to this function. |
217 | | * |
218 | | * return -1 on failure. |
219 | | * return 0 on success. |
220 | | */ |
221 | | int nc_dht_pk_callback(const Net_Crypto *_Nonnull c, int crypt_connection_id, dht_pk_cb *_Nonnull function, void *_Nonnull object, uint32_t number); |
222 | | |
223 | | /** |
224 | | * @return the number of packet slots left in the sendbuffer. |
225 | | * @retval 0 if failure. |
226 | | */ |
227 | | uint32_t crypto_num_free_sendqueue_slots(const Net_Crypto *_Nonnull c, int crypt_connection_id); |
228 | | |
229 | | /** |
230 | | * @retval 1 if max speed was reached for this connection (no more data can be physically through the pipe). |
231 | | * @retval 0 if it wasn't reached. |
232 | | */ |
233 | | bool max_speed_reached(const Net_Crypto *_Nonnull c, int crypt_connection_id); |
234 | | |
235 | | /** @brief Sends a lossless cryptopacket. |
236 | | * |
237 | | * return -1 if data could not be put in packet queue. |
238 | | * return positive packet number if data was put into the queue. |
239 | | * |
240 | | * The first byte of data must be in the PACKET_ID_RANGE_LOSSLESS. |
241 | | * |
242 | | * congestion_control: should congestion control apply to this packet? |
243 | | */ |
244 | | int64_t write_cryptpacket(const Net_Crypto *_Nonnull c, int crypt_connection_id, const uint8_t *_Nonnull data, uint16_t length, bool congestion_control); |
245 | | |
246 | | /** @brief Check if packet_number was received by the other side. |
247 | | * |
248 | | * packet_number must be a valid packet number of a packet sent on this connection. |
249 | | * |
250 | | * return -1 on failure. |
251 | | * return 0 on success. |
252 | | * |
253 | | * Note: The condition `buffer_end - buffer_start < packet_number - buffer_start` is |
254 | | * a trick which handles situations `buffer_end >= buffer_start` and |
255 | | * `buffer_end < buffer_start` (when buffer_end overflowed) both correctly. |
256 | | * |
257 | | * It CANNOT be simplified to `packet_number < buffer_start`, as it will fail |
258 | | * when `buffer_end < buffer_start`. |
259 | | */ |
260 | | int cryptpacket_received(const Net_Crypto *_Nonnull c, int crypt_connection_id, uint32_t packet_number); |
261 | | |
262 | | /** @brief Sends a lossy cryptopacket. |
263 | | * |
264 | | * return -1 on failure. |
265 | | * return 0 on success. |
266 | | * |
267 | | * The first byte of data must be in the PACKET_ID_RANGE_LOSSY. |
268 | | */ |
269 | | int send_lossy_cryptpacket(const Net_Crypto *_Nonnull c, int crypt_connection_id, const uint8_t *_Nonnull data, uint16_t length); |
270 | | |
271 | | /** @brief Add a tcp relay, associating it to a crypt_connection_id. |
272 | | * |
273 | | * return 0 if it was added. |
274 | | * return -1 if it wasn't. |
275 | | */ |
276 | | int add_tcp_relay_peer(Net_Crypto *_Nonnull c, int crypt_connection_id, const IP_Port *_Nonnull ip_port, const uint8_t *_Nonnull public_key); |
277 | | |
278 | | /** @brief Add a tcp relay to the array. |
279 | | * |
280 | | * return 0 if it was added. |
281 | | * return -1 if it wasn't. |
282 | | */ |
283 | | int add_tcp_relay(Net_Crypto *_Nonnull c, const IP_Port *_Nonnull ip_port, const uint8_t *_Nonnull public_key); |
284 | | |
285 | | /** @brief Return a random TCP connection number for use in send_tcp_onion_request. |
286 | | * |
287 | | * TODO(irungentoo): This number is just the index of an array that the elements can |
288 | | * change without warning. |
289 | | * |
290 | | * return TCP connection number on success. |
291 | | * return -1 on failure. |
292 | | */ |
293 | | int get_random_tcp_con_number(const Net_Crypto *_Nonnull c); |
294 | | |
295 | | /** @brief Put IP_Port of a random onion TCP connection in ip_port. |
296 | | * |
297 | | * return true on success. |
298 | | * return false on failure. |
299 | | */ |
300 | | bool get_random_tcp_conn_ip_port(const Net_Crypto *_Nonnull c, IP_Port *_Nonnull ip_port); |
301 | | |
302 | | /** @brief Send an onion packet via the TCP relay corresponding to tcp_connections_number. |
303 | | * |
304 | | * return 0 on success. |
305 | | * return -1 on failure. |
306 | | */ |
307 | | int send_tcp_onion_request(Net_Crypto *_Nonnull c, unsigned int tcp_connections_number, const uint8_t *_Nonnull data, uint16_t length); |
308 | | |
309 | | /** |
310 | | * Send a forward request to the TCP relay with IP_Port tcp_forwarder, |
311 | | * requesting to forward data via a chain of dht nodes starting with dht_node. |
312 | | * A chain_length of 0 means that dht_node is the final destination of data. |
313 | | * |
314 | | * return 0 on success. |
315 | | * return -1 on failure. |
316 | | */ |
317 | | int send_tcp_forward_request(const Logger *_Nonnull logger, Net_Crypto *_Nonnull c, const IP_Port *_Nonnull tcp_forwarder, const IP_Port *_Nonnull dht_node, |
318 | | const uint8_t *_Nonnull chain_keys, uint16_t chain_length, const uint8_t *_Nonnull data, uint16_t data_length); |
319 | | |
320 | | /** @brief Copy a maximum of num random TCP relays we are connected to to tcp_relays. |
321 | | * |
322 | | * NOTE that the family of the copied ip ports will be set to TCP_INET or TCP_INET6. |
323 | | * |
324 | | * return number of relays copied to tcp_relays on success. |
325 | | * return 0 on failure. |
326 | | */ |
327 | | unsigned int copy_connected_tcp_relays(const Net_Crypto *_Nonnull c, Node_format *_Nonnull tcp_relays, uint16_t num); |
328 | | |
329 | | /** |
330 | | * Copy a maximum of `max_num` TCP relays we are connected to starting at the index in the TCP relay array |
331 | | * for `tcp_c` designated by `idx`. If idx is greater than the array length a modulo operation is performed. |
332 | | * |
333 | | * Returns the number of relays successfully copied. |
334 | | */ |
335 | | uint32_t copy_connected_tcp_relays_index(const Net_Crypto *_Nonnull c, Node_format *_Nonnull tcp_relays, uint16_t num, uint32_t idx); |
336 | | |
337 | | /** @brief Kill a crypto connection. |
338 | | * |
339 | | * return -1 on failure. |
340 | | * return 0 on success. |
341 | | */ |
342 | | int crypto_kill(Net_Crypto *_Nonnull c, int crypt_connection_id); |
343 | | |
344 | | /** |
345 | | * @retval true if connection is valid, false otherwise |
346 | | * |
347 | | * sets direct_connected to 1 if connection connects directly to other, 0 if it isn't. |
348 | | * sets online_tcp_relays to the number of connected tcp relays this connection has. |
349 | | */ |
350 | | bool crypto_connection_status( |
351 | | const Net_Crypto *_Nonnull c, int crypt_connection_id, bool *_Nonnull direct_connected, uint32_t *_Nullable online_tcp_relays); |
352 | | /** @brief Generate our public and private keys. |
353 | | * Only call this function the first time the program starts. |
354 | | */ |
355 | | void new_keys(Net_Crypto *_Nonnull c); |
356 | | |
357 | | /** @brief Save the public and private keys to the keys array. |
358 | | * Length must be CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SECRET_KEY_SIZE. |
359 | | * |
360 | | * TODO(irungentoo): Save only secret key. |
361 | | */ |
362 | | void save_keys(const Net_Crypto *_Nonnull c, uint8_t *_Nonnull keys); |
363 | | |
364 | | /** @brief Load the secret key. |
365 | | * Length must be CRYPTO_SECRET_KEY_SIZE. |
366 | | */ |
367 | | void load_secret_key(Net_Crypto *_Nonnull c, const uint8_t *_Nonnull sk); |
368 | | |
369 | | /** @brief Create new instance of Net_Crypto. |
370 | | * Sets all the global connection variables to their default values. |
371 | | */ |
372 | | Net_Crypto *_Nullable new_net_crypto(const Logger *_Nonnull log, const Memory *_Nonnull mem, const Random *_Nonnull rng, const Network *_Nonnull ns, Mono_Time *_Nonnull mono_time, DHT *_Nonnull dht, |
373 | | const TCP_Proxy_Info *_Nonnull proxy_info, Net_Profile *_Nonnull tcp_np); |
374 | | |
375 | | /** return the optimal interval in ms for running do_net_crypto. */ |
376 | | uint32_t crypto_run_interval(const Net_Crypto *_Nonnull c); |
377 | | |
378 | | /** Main loop. */ |
379 | | void do_net_crypto(Net_Crypto *_Nonnull c, void *_Nullable userdata); |
380 | | void kill_net_crypto(Net_Crypto *_Nullable c); |
381 | | #ifdef __cplusplus |
382 | | } /* extern "C" */ |
383 | | #endif |
384 | | |
385 | | #endif /* C_TOXCORE_TOXCORE_NET_CRYPTO_H */ |