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