Coverage Report

Created: 2026-10-24 08:16

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