Coverage Report

Created: 2025-10-08 19:34

/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 */