Coverage Report

Created: 2023-11-22 10:24

/src/c-toxcore/toxcore/onion.c
Line
Count
Source (jump to first uncovered line)
1
/* SPDX-License-Identifier: GPL-3.0-or-later
2
 * Copyright © 2016-2018 The TokTok team.
3
 * Copyright © 2013 Tox project.
4
 */
5
6
/**
7
 * Implementation of the onion part of docs/Prevent_Tracking.txt
8
 */
9
#include "onion.h"
10
11
#include <assert.h>
12
#include <stdlib.h>
13
#include <string.h>
14
15
#include "ccompat.h"
16
#include "mono_time.h"
17
#include "util.h"
18
19
462
#define RETURN_1 ONION_RETURN_1
20
57
#define RETURN_2 ONION_RETURN_2
21
56
#define RETURN_3 ONION_RETURN_3
22
23
42
#define SEND_BASE ONION_SEND_BASE
24
14
#define SEND_3 ONION_SEND_3
25
16
#define SEND_2 ONION_SEND_2
26
14
#define SEND_1 ONION_SEND_1
27
28
113
#define KEY_REFRESH_INTERVAL (2 * 60 * 60)
29
30
31
// Settings for the shared key cache
32
9.25k
#define MAX_KEYS_PER_SLOT 4
33
9.25k
#define KEYS_TIMEOUT 600
34
35
/** Change symmetric keys every 2 hours to make paths expire eventually. */
36
non_null()
37
static void change_symmetric_key(Onion *onion)
38
113
{
39
113
    if (mono_time_is_timeout(onion->mono_time, onion->timestamp, KEY_REFRESH_INTERVAL)) {
40
0
        new_symmetric_key(onion->rng, onion->secret_symmetric_key);
41
0
        onion->timestamp = mono_time_get(onion->mono_time);
42
0
    }
43
113
}
44
45
/** packing and unpacking functions */
46
non_null()
47
static void ip_pack(uint8_t *data, const IP *source)
48
5
{
49
5
    data[0] = source->family.value;
50
51
5
    if (net_family_is_ipv4(source->family) || net_family_is_tox_tcp_ipv4(source->family)) {
52
4
        memset(data + 1, 0, SIZE_IP6);
53
4
        memcpy(data + 1, source->ip.v4.uint8, SIZE_IP4);
54
4
    } else {
55
1
        memcpy(data + 1, source->ip.v6.uint8, SIZE_IP6);
56
1
    }
57
5
}
58
59
/** return 0 on success, -1 on failure. */
60
non_null()
61
static int ip_unpack(IP *target, const uint8_t *data, unsigned int data_size, bool disable_family_check)
62
150
{
63
150
    if (data_size < (1 + SIZE_IP6)) {
64
0
        return -1;
65
0
    }
66
67
    // TODO(iphydf): Validate input.
68
150
    target->family.value = data[0];
69
70
150
    if (net_family_is_ipv4(target->family) || net_family_is_tox_tcp_ipv4(target->family)) {
71
58
        memcpy(target->ip.v4.uint8, data + 1, SIZE_IP4);
72
92
    } else {
73
92
        memcpy(target->ip.v6.uint8, data + 1, SIZE_IP6);
74
92
    }
75
76
150
    const bool valid = disable_family_check ||
77
150
                 net_family_is_ipv4(target->family) ||
78
150
                 net_family_is_ipv6(target->family);
79
80
150
    return valid ? 0 : -1;
81
150
}
82
83
non_null()
84
static void ipport_pack(uint8_t *data, const IP_Port *source)
85
5
{
86
5
    ip_pack(data, &source->ip);
87
5
    memcpy(data + SIZE_IP, &source->port, SIZE_PORT);
88
5
}
89
90
/** return 0 on success, -1 on failure. */
91
non_null()
92
static int ipport_unpack(IP_Port *target, const uint8_t *data, unsigned int data_size, bool disable_family_check)
93
150
{
94
150
    if (data_size < (SIZE_IP + SIZE_PORT)) {
95
0
        return -1;
96
0
    }
97
98
150
    if (ip_unpack(&target->ip, data, data_size, disable_family_check) == -1) {
99
51
        return -1;
100
51
    }
101
102
99
    memcpy(&target->port, data + SIZE_IP, SIZE_PORT);
103
99
    return 0;
104
150
}
105
106
107
/** @brief Create a new onion path.
108
 *
109
 * Create a new onion path out of nodes (nodes is a list of ONION_PATH_LENGTH nodes)
110
 *
111
 * new_path must be an empty memory location of at least Onion_Path size.
112
 *
113
 * return -1 on failure.
114
 * return 0 on success.
115
 */
116
int create_onion_path(const Random *rng, const DHT *dht, Onion_Path *new_path, const Node_format *nodes)
117
0
{
118
0
    if (new_path == nullptr || nodes == nullptr) {
119
0
        return -1;
120
0
    }
121
122
0
    encrypt_precompute(nodes[0].public_key, dht_get_self_secret_key(dht), new_path->shared_key1);
123
0
    memcpy(new_path->public_key1, dht_get_self_public_key(dht), CRYPTO_PUBLIC_KEY_SIZE);
124
125
0
    uint8_t random_public_key[CRYPTO_PUBLIC_KEY_SIZE];
126
0
    uint8_t random_secret_key[CRYPTO_SECRET_KEY_SIZE];
127
128
0
    crypto_new_keypair(rng, random_public_key, random_secret_key);
129
0
    encrypt_precompute(nodes[1].public_key, random_secret_key, new_path->shared_key2);
130
0
    memcpy(new_path->public_key2, random_public_key, CRYPTO_PUBLIC_KEY_SIZE);
131
132
0
    crypto_new_keypair(rng, random_public_key, random_secret_key);
133
0
    encrypt_precompute(nodes[2].public_key, random_secret_key, new_path->shared_key3);
134
0
    memcpy(new_path->public_key3, random_public_key, CRYPTO_PUBLIC_KEY_SIZE);
135
136
0
    crypto_memzero(random_secret_key, sizeof(random_secret_key));
137
138
0
    new_path->ip_port1 = nodes[0].ip_port;
139
0
    new_path->ip_port2 = nodes[1].ip_port;
140
0
    new_path->ip_port3 = nodes[2].ip_port;
141
142
0
    memcpy(new_path->node_public_key1, nodes[0].public_key, CRYPTO_PUBLIC_KEY_SIZE);
143
0
    memcpy(new_path->node_public_key2, nodes[1].public_key, CRYPTO_PUBLIC_KEY_SIZE);
144
0
    memcpy(new_path->node_public_key3, nodes[2].public_key, CRYPTO_PUBLIC_KEY_SIZE);
145
146
0
    return 0;
147
0
}
148
149
/** @brief Dump nodes in onion path to nodes of length num_nodes.
150
 *
151
 * return -1 on failure.
152
 * return 0 on success.
153
 */
154
int onion_path_to_nodes(Node_format *nodes, unsigned int num_nodes, const Onion_Path *path)
155
0
{
156
0
    if (num_nodes < ONION_PATH_LENGTH) {
157
0
        return -1;
158
0
    }
159
160
0
    nodes[0].ip_port = path->ip_port1;
161
0
    nodes[1].ip_port = path->ip_port2;
162
0
    nodes[2].ip_port = path->ip_port3;
163
164
0
    memcpy(nodes[0].public_key, path->node_public_key1, CRYPTO_PUBLIC_KEY_SIZE);
165
0
    memcpy(nodes[1].public_key, path->node_public_key2, CRYPTO_PUBLIC_KEY_SIZE);
166
0
    memcpy(nodes[2].public_key, path->node_public_key3, CRYPTO_PUBLIC_KEY_SIZE);
167
0
    return 0;
168
0
}
169
170
/** @brief Create a onion packet.
171
 *
172
 * Use Onion_Path path to create packet for data of length to dest.
173
 * Maximum length of data is ONION_MAX_DATA_SIZE.
174
 * packet should be at least ONION_MAX_PACKET_SIZE big.
175
 *
176
 * return -1 on failure.
177
 * return length of created packet on success.
178
 */
179
int create_onion_packet(const Random *rng, uint8_t *packet, uint16_t max_packet_length,
180
                        const Onion_Path *path, const IP_Port *dest,
181
                        const uint8_t *data, uint16_t length)
182
0
{
183
0
    if (1 + length + SEND_1 > max_packet_length || length == 0) {
184
0
        return -1;
185
0
    }
186
187
0
    VLA(uint8_t, step1, SIZE_IPPORT + length);
188
189
0
    ipport_pack(step1, dest);
190
0
    memcpy(step1 + SIZE_IPPORT, data, length);
191
192
0
    uint8_t nonce[CRYPTO_NONCE_SIZE];
193
0
    random_nonce(rng, nonce);
194
195
0
    VLA(uint8_t, step2, SIZE_IPPORT + SEND_BASE + length);
196
0
    ipport_pack(step2, &path->ip_port3);
197
0
    memcpy(step2 + SIZE_IPPORT, path->public_key3, CRYPTO_PUBLIC_KEY_SIZE);
198
199
0
    int len = encrypt_data_symmetric(path->shared_key3, nonce, step1, SIZEOF_VLA(step1),
200
0
                                     step2 + SIZE_IPPORT + CRYPTO_PUBLIC_KEY_SIZE);
201
202
0
    if (len != SIZE_IPPORT + length + CRYPTO_MAC_SIZE) {
203
0
        return -1;
204
0
    }
205
206
0
    VLA(uint8_t, step3, SIZE_IPPORT + SEND_BASE * 2 + length);
207
0
    ipport_pack(step3, &path->ip_port2);
208
0
    memcpy(step3 + SIZE_IPPORT, path->public_key2, CRYPTO_PUBLIC_KEY_SIZE);
209
0
    len = encrypt_data_symmetric(path->shared_key2, nonce, step2, SIZEOF_VLA(step2),
210
0
                                 step3 + SIZE_IPPORT + CRYPTO_PUBLIC_KEY_SIZE);
211
212
0
    if (len != SIZE_IPPORT + SEND_BASE + length + CRYPTO_MAC_SIZE) {
213
0
        return -1;
214
0
    }
215
216
0
    packet[0] = NET_PACKET_ONION_SEND_INITIAL;
217
0
    memcpy(packet + 1, nonce, CRYPTO_NONCE_SIZE);
218
0
    memcpy(packet + 1 + CRYPTO_NONCE_SIZE, path->public_key1, CRYPTO_PUBLIC_KEY_SIZE);
219
220
0
    len = encrypt_data_symmetric(path->shared_key1, nonce, step3, SIZEOF_VLA(step3),
221
0
                                 packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE);
222
223
0
    if (len != SIZE_IPPORT + SEND_BASE * 2 + length + CRYPTO_MAC_SIZE) {
224
0
        return -1;
225
0
    }
226
227
0
    return 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + len;
228
0
}
229
230
/** @brief Create a onion packet to be sent over tcp.
231
 *
232
 * Use Onion_Path path to create packet for data of length to dest.
233
 * Maximum length of data is ONION_MAX_DATA_SIZE.
234
 * packet should be at least ONION_MAX_PACKET_SIZE big.
235
 *
236
 * return -1 on failure.
237
 * return length of created packet on success.
238
 */
239
int create_onion_packet_tcp(const Random *rng, uint8_t *packet, uint16_t max_packet_length,
240
                            const Onion_Path *path, const IP_Port *dest,
241
                            const uint8_t *data, uint16_t length)
242
0
{
243
0
    if (CRYPTO_NONCE_SIZE + SIZE_IPPORT + SEND_BASE * 2 + length > max_packet_length || length == 0) {
244
0
        return -1;
245
0
    }
246
247
0
    VLA(uint8_t, step1, SIZE_IPPORT + length);
248
249
0
    ipport_pack(step1, dest);
250
0
    memcpy(step1 + SIZE_IPPORT, data, length);
251
252
0
    uint8_t nonce[CRYPTO_NONCE_SIZE];
253
0
    random_nonce(rng, nonce);
254
255
0
    VLA(uint8_t, step2, SIZE_IPPORT + SEND_BASE + length);
256
0
    ipport_pack(step2, &path->ip_port3);
257
0
    memcpy(step2 + SIZE_IPPORT, path->public_key3, CRYPTO_PUBLIC_KEY_SIZE);
258
259
0
    int len = encrypt_data_symmetric(path->shared_key3, nonce, step1, SIZEOF_VLA(step1),
260
0
                                     step2 + SIZE_IPPORT + CRYPTO_PUBLIC_KEY_SIZE);
261
262
0
    if (len != SIZE_IPPORT + length + CRYPTO_MAC_SIZE) {
263
0
        return -1;
264
0
    }
265
266
0
    ipport_pack(packet + CRYPTO_NONCE_SIZE, &path->ip_port2);
267
0
    memcpy(packet + CRYPTO_NONCE_SIZE + SIZE_IPPORT, path->public_key2, CRYPTO_PUBLIC_KEY_SIZE);
268
0
    len = encrypt_data_symmetric(path->shared_key2, nonce, step2, SIZEOF_VLA(step2),
269
0
                                 packet + CRYPTO_NONCE_SIZE + SIZE_IPPORT + CRYPTO_PUBLIC_KEY_SIZE);
270
271
0
    if (len != SIZE_IPPORT + SEND_BASE + length + CRYPTO_MAC_SIZE) {
272
0
        return -1;
273
0
    }
274
275
0
    memcpy(packet, nonce, CRYPTO_NONCE_SIZE);
276
277
0
    return CRYPTO_NONCE_SIZE + SIZE_IPPORT + CRYPTO_PUBLIC_KEY_SIZE + len;
278
0
}
279
280
/** @brief Create and send a onion response sent initially to dest with.
281
 * Maximum length of data is ONION_RESPONSE_MAX_DATA_SIZE.
282
 *
283
 * return -1 on failure.
284
 * return 0 on success.
285
 */
286
int send_onion_response(const Networking_Core *net, const IP_Port *dest, const uint8_t *data, uint16_t length,
287
                        const uint8_t *ret)
288
6
{
289
6
    if (length > ONION_RESPONSE_MAX_DATA_SIZE || length == 0) {
290
0
        return -1;
291
0
    }
292
293
6
    VLA(uint8_t, packet, 1 + RETURN_3 + length);
294
6
    packet[0] = NET_PACKET_ONION_RECV_3;
295
6
    memcpy(packet + 1, ret, RETURN_3);
296
6
    memcpy(packet + 1 + RETURN_3, data, length);
297
298
6
    if ((uint32_t)sendpacket(net, dest, packet, SIZEOF_VLA(packet)) != SIZEOF_VLA(packet)) {
299
0
        return -1;
300
0
    }
301
302
6
    return 0;
303
6
}
304
305
non_null()
306
static int handle_send_initial(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length,
307
                               void *userdata)
308
17
{
309
17
    Onion *onion = (Onion *)object;
310
311
17
    if (length > ONION_MAX_PACKET_SIZE) {
312
3
        return 1;
313
3
    }
314
315
14
    if (length <= 1 + SEND_1) {
316
11
        return 1;
317
11
    }
318
319
3
    change_symmetric_key(onion);
320
321
3
    uint8_t plain[ONION_MAX_PACKET_SIZE];
322
3
    const uint8_t *public_key = packet + 1 + CRYPTO_NONCE_SIZE;
323
3
    const uint8_t *shared_key = shared_key_cache_lookup(onion->shared_keys_1, public_key);
324
325
3
    if (shared_key == nullptr) {
326
        /* Error looking up/deriving the shared key */
327
0
        return 1;
328
0
    }
329
330
3
    const int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE,
331
3
                                     length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE), plain);
332
333
3
    if (len != length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_MAC_SIZE)) {
334
0
        return 1;
335
0
    }
336
337
3
    return onion_send_1(onion, plain, len, source, packet + 1);
338
3
}
339
340
int onion_send_1(const Onion *onion, const uint8_t *plain, uint16_t len, const IP_Port *source, const uint8_t *nonce)
341
42
{
342
42
    if (len > ONION_MAX_PACKET_SIZE + SIZE_IPPORT - (1 + CRYPTO_NONCE_SIZE + ONION_RETURN_1)) {
343
0
        return 1;
344
0
    }
345
346
42
    if (len <= SIZE_IPPORT + SEND_BASE * 2) {
347
1
        return 1;
348
1
    }
349
350
41
    IP_Port send_to;
351
352
41
    if (ipport_unpack(&send_to, plain, len, false) == -1) {
353
38
        return 1;
354
38
    }
355
356
3
    uint8_t ip_port[SIZE_IPPORT];
357
3
    ipport_pack(ip_port, source);
358
359
3
    uint8_t data[ONION_MAX_PACKET_SIZE] = {0};
360
3
    data[0] = NET_PACKET_ONION_SEND_1;
361
3
    memcpy(data + 1, nonce, CRYPTO_NONCE_SIZE);
362
3
    memcpy(data + 1 + CRYPTO_NONCE_SIZE, plain + SIZE_IPPORT, len - SIZE_IPPORT);
363
3
    uint16_t data_len = 1 + CRYPTO_NONCE_SIZE + (len - SIZE_IPPORT);
364
3
    uint8_t *ret_part = data + data_len;
365
3
    random_nonce(onion->rng, ret_part);
366
3
    len = encrypt_data_symmetric(onion->secret_symmetric_key, ret_part, ip_port, SIZE_IPPORT,
367
3
                                 ret_part + CRYPTO_NONCE_SIZE);
368
369
3
    if (len != SIZE_IPPORT + CRYPTO_MAC_SIZE) {
370
0
        return 1;
371
0
    }
372
373
3
    data_len += CRYPTO_NONCE_SIZE + len;
374
375
3
    if ((uint32_t)sendpacket(onion->net, &send_to, data, data_len) != data_len) {
376
1
        return 1;
377
1
    }
378
379
2
    return 0;
380
3
}
381
382
non_null()
383
static int handle_send_1(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, void *userdata)
384
19
{
385
19
    Onion *onion = (Onion *)object;
386
387
19
    if (length > ONION_MAX_PACKET_SIZE) {
388
3
        return 1;
389
3
    }
390
391
16
    if (length <= 1 + SEND_2) {
392
10
        return 1;
393
10
    }
394
395
6
    change_symmetric_key(onion);
396
397
6
    uint8_t plain[ONION_MAX_PACKET_SIZE];
398
6
    const uint8_t *public_key = packet + 1 + CRYPTO_NONCE_SIZE;
399
6
    const uint8_t *shared_key = shared_key_cache_lookup(onion->shared_keys_2, public_key);
400
401
6
    if (shared_key == nullptr) {
402
        /* Error looking up/deriving the shared key */
403
0
        return 1;
404
0
    }
405
406
6
    int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE,
407
6
                                     length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + RETURN_1), plain);
408
409
6
    if (len != length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + RETURN_1 + CRYPTO_MAC_SIZE)) {
410
0
        return 1;
411
0
    }
412
413
6
    IP_Port send_to;
414
415
6
    if (ipport_unpack(&send_to, plain, len, false) == -1) {
416
5
        return 1;
417
5
    }
418
419
1
    uint8_t data[ONION_MAX_PACKET_SIZE] = {0};
420
1
    data[0] = NET_PACKET_ONION_SEND_2;
421
1
    memcpy(data + 1, packet + 1, CRYPTO_NONCE_SIZE);
422
1
    memcpy(data + 1 + CRYPTO_NONCE_SIZE, plain + SIZE_IPPORT, len - SIZE_IPPORT);
423
1
    uint16_t data_len = 1 + CRYPTO_NONCE_SIZE + (len - SIZE_IPPORT);
424
1
    uint8_t *ret_part = data + data_len;
425
1
    random_nonce(onion->rng, ret_part);
426
1
    uint8_t ret_data[RETURN_1 + SIZE_IPPORT];
427
1
    ipport_pack(ret_data, source);
428
1
    memcpy(ret_data + SIZE_IPPORT, packet + (length - RETURN_1), RETURN_1);
429
1
    len = encrypt_data_symmetric(onion->secret_symmetric_key, ret_part, ret_data, sizeof(ret_data),
430
1
                                 ret_part + CRYPTO_NONCE_SIZE);
431
432
1
    if (len != RETURN_2 - CRYPTO_NONCE_SIZE) {
433
0
        return 1;
434
0
    }
435
436
1
    data_len += CRYPTO_NONCE_SIZE + len;
437
438
1
    if ((uint32_t)sendpacket(onion->net, &send_to, data, data_len) != data_len) {
439
0
        return 1;
440
0
    }
441
442
1
    return 0;
443
1
}
444
445
non_null()
446
static int handle_send_2(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, void *userdata)
447
17
{
448
17
    Onion *onion = (Onion *)object;
449
450
17
    if (length > ONION_MAX_PACKET_SIZE) {
451
3
        return 1;
452
3
    }
453
454
14
    if (length <= 1 + SEND_3) {
455
10
        return 1;
456
10
    }
457
458
4
    change_symmetric_key(onion);
459
460
4
    uint8_t plain[ONION_MAX_PACKET_SIZE];
461
4
    const uint8_t *public_key = packet + 1 + CRYPTO_NONCE_SIZE;
462
4
    const uint8_t *shared_key = shared_key_cache_lookup(onion->shared_keys_3, public_key);
463
464
4
    if (shared_key == nullptr) {
465
        /* Error looking up/deriving the shared key */
466
0
        return 1;
467
0
    }
468
469
4
    int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE,
470
4
                                     length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + RETURN_2), plain);
471
472
4
    if (len != length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + RETURN_2 + CRYPTO_MAC_SIZE)) {
473
0
        return 1;
474
0
    }
475
476
4
    assert(len > SIZE_IPPORT);
477
478
4
    const uint8_t packet_id = plain[SIZE_IPPORT];
479
480
4
    if (packet_id != NET_PACKET_ANNOUNCE_REQUEST && packet_id != NET_PACKET_ANNOUNCE_REQUEST_OLD &&
481
4
            packet_id != NET_PACKET_ONION_DATA_REQUEST) {
482
1
        return 1;
483
1
    }
484
485
3
    IP_Port send_to;
486
487
3
    if (ipport_unpack(&send_to, plain, len, false) == -1) {
488
2
        return 1;
489
2
    }
490
491
1
    uint8_t data[ONION_MAX_PACKET_SIZE] = {0};
492
1
    memcpy(data, plain + SIZE_IPPORT, len - SIZE_IPPORT);
493
1
    uint16_t data_len = len - SIZE_IPPORT;
494
1
    uint8_t *ret_part = data + (len - SIZE_IPPORT);
495
1
    random_nonce(onion->rng, ret_part);
496
1
    uint8_t ret_data[RETURN_2 + SIZE_IPPORT];
497
1
    ipport_pack(ret_data, source);
498
1
    memcpy(ret_data + SIZE_IPPORT, packet + (length - RETURN_2), RETURN_2);
499
1
    len = encrypt_data_symmetric(onion->secret_symmetric_key, ret_part, ret_data, sizeof(ret_data),
500
1
                                 ret_part + CRYPTO_NONCE_SIZE);
501
502
1
    if (len != RETURN_3 - CRYPTO_NONCE_SIZE) {
503
0
        return 1;
504
0
    }
505
506
1
    data_len += RETURN_3;
507
508
1
    if ((uint32_t)sendpacket(onion->net, &send_to, data, data_len) != data_len) {
509
0
        return 1;
510
0
    }
511
512
1
    return 0;
513
1
}
514
515
516
non_null()
517
static int handle_recv_3(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, void *userdata)
518
26
{
519
26
    Onion *onion = (Onion *)object;
520
521
26
    if (length > ONION_MAX_PACKET_SIZE) {
522
3
        return 1;
523
3
    }
524
525
23
    if (length <= 1 + RETURN_3) {
526
10
        return 1;
527
10
    }
528
529
13
    const uint8_t packet_id = packet[1 + RETURN_3];
530
531
13
    if (packet_id != NET_PACKET_ANNOUNCE_RESPONSE && packet_id != NET_PACKET_ANNOUNCE_RESPONSE_OLD &&
532
13
            packet_id != NET_PACKET_ONION_DATA_RESPONSE) {
533
7
        return 1;
534
7
    }
535
536
6
    change_symmetric_key(onion);
537
538
6
    uint8_t plain[SIZE_IPPORT + RETURN_2];
539
6
    const int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE,
540
6
                                     SIZE_IPPORT + RETURN_2 + CRYPTO_MAC_SIZE, plain);
541
542
6
    if ((uint32_t)len != sizeof(plain)) {
543
0
        return 1;
544
0
    }
545
546
6
    IP_Port send_to;
547
548
6
    if (ipport_unpack(&send_to, plain, len, false) == -1) {
549
4
        return 1;
550
4
    }
551
552
2
    uint8_t data[ONION_MAX_PACKET_SIZE] = {0};
553
2
    data[0] = NET_PACKET_ONION_RECV_2;
554
2
    memcpy(data + 1, plain + SIZE_IPPORT, RETURN_2);
555
2
    memcpy(data + 1 + RETURN_2, packet + 1 + RETURN_3, length - (1 + RETURN_3));
556
2
    const uint16_t data_len = 1 + RETURN_2 + (length - (1 + RETURN_3));
557
558
2
    if ((uint32_t)sendpacket(onion->net, &send_to, data, data_len) != data_len) {
559
0
        return 1;
560
0
    }
561
562
2
    return 0;
563
2
}
564
565
non_null()
566
static int handle_recv_2(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, void *userdata)
567
18
{
568
18
    Onion *onion = (Onion *)object;
569
570
18
    if (length > ONION_MAX_PACKET_SIZE) {
571
1
        return 1;
572
1
    }
573
574
17
    if (length <= 1 + RETURN_2) {
575
3
        return 1;
576
3
    }
577
578
14
    const uint8_t packet_id = packet[1 + RETURN_2];
579
580
14
    if (packet_id != NET_PACKET_ANNOUNCE_RESPONSE && packet_id != NET_PACKET_ANNOUNCE_RESPONSE_OLD &&
581
14
            packet_id != NET_PACKET_ONION_DATA_RESPONSE) {
582
11
        return 1;
583
11
    }
584
585
3
    change_symmetric_key(onion);
586
587
3
    uint8_t plain[SIZE_IPPORT + RETURN_1];
588
3
    const int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE,
589
3
                                     SIZE_IPPORT + RETURN_1 + CRYPTO_MAC_SIZE, plain);
590
591
3
    if ((uint32_t)len != sizeof(plain)) {
592
0
        return 1;
593
0
    }
594
595
3
    IP_Port send_to;
596
597
3
    if (ipport_unpack(&send_to, plain, len, false) == -1) {
598
2
        return 1;
599
2
    }
600
601
1
    uint8_t data[ONION_MAX_PACKET_SIZE] = {0};
602
1
    data[0] = NET_PACKET_ONION_RECV_1;
603
1
    memcpy(data + 1, plain + SIZE_IPPORT, RETURN_1);
604
1
    memcpy(data + 1 + RETURN_1, packet + 1 + RETURN_2, length - (1 + RETURN_2));
605
1
    const uint16_t data_len = 1 + RETURN_1 + (length - (1 + RETURN_2));
606
607
1
    if ((uint32_t)sendpacket(onion->net, &send_to, data, data_len) != data_len) {
608
0
        return 1;
609
0
    }
610
611
1
    return 0;
612
1
}
613
614
non_null()
615
static int handle_recv_1(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, void *userdata)
616
141
{
617
141
    Onion *onion = (Onion *)object;
618
619
141
    if (length > ONION_MAX_PACKET_SIZE) {
620
3
        return 1;
621
3
    }
622
623
138
    if (length <= 1 + RETURN_1) {
624
16
        return 1;
625
16
    }
626
627
122
    const uint8_t packet_id = packet[1 + RETURN_1];
628
629
122
    if (packet_id != NET_PACKET_ANNOUNCE_RESPONSE && packet_id != NET_PACKET_ANNOUNCE_RESPONSE_OLD &&
630
122
            packet_id != NET_PACKET_ONION_DATA_RESPONSE) {
631
31
        return 1;
632
31
    }
633
634
91
    change_symmetric_key(onion);
635
636
91
    uint8_t plain[SIZE_IPPORT];
637
91
    const int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE,
638
91
                                     SIZE_IPPORT + CRYPTO_MAC_SIZE, plain);
639
640
91
    if ((uint32_t)len != SIZE_IPPORT) {
641
0
        return 1;
642
0
    }
643
644
91
    IP_Port send_to;
645
646
91
    if (ipport_unpack(&send_to, plain, len, true) == -1) {
647
0
        return 1;
648
0
    }
649
650
91
    const uint16_t data_len = length - (1 + RETURN_1);
651
652
91
    if (onion->recv_1_function != nullptr &&
653
91
            !net_family_is_ipv4(send_to.ip.family) &&
654
91
            !net_family_is_ipv6(send_to.ip.family)) {
655
13
        return onion->recv_1_function(onion->callback_object, &send_to, packet + (1 + RETURN_1), data_len);
656
13
    }
657
658
78
    if ((uint32_t)sendpacket(onion->net, &send_to, packet + (1 + RETURN_1), data_len) != data_len) {
659
30
        return 1;
660
30
    }
661
662
48
    return 0;
663
78
}
664
665
void set_callback_handle_recv_1(Onion *onion, onion_recv_1_cb *function, void *object)
666
290
{
667
290
    onion->recv_1_function = function;
668
290
    onion->callback_object = object;
669
290
}
670
671
Onion *new_onion(const Logger *log, const Memory *mem, const Mono_Time *mono_time, const Random *rng, DHT *dht)
672
3.08k
{
673
3.08k
    if (dht == nullptr) {
674
0
        return nullptr;
675
0
    }
676
677
3.08k
    Onion *onion = (Onion *)mem_alloc(mem, sizeof(Onion));
678
679
3.08k
    if (onion == nullptr) {
680
3
        return nullptr;
681
3
    }
682
683
3.08k
    onion->log = log;
684
3.08k
    onion->dht = dht;
685
3.08k
    onion->net = dht_get_net(dht);
686
3.08k
    onion->mono_time = mono_time;
687
3.08k
    onion->rng = rng;
688
3.08k
    onion->mem = mem;
689
3.08k
    new_symmetric_key(rng, onion->secret_symmetric_key);
690
3.08k
    onion->timestamp = mono_time_get(onion->mono_time);
691
692
3.08k
    const uint8_t *secret_key = dht_get_self_secret_key(dht);
693
3.08k
    onion->shared_keys_1 = shared_key_cache_new(mono_time, mem, secret_key, KEYS_TIMEOUT, MAX_KEYS_PER_SLOT);
694
3.08k
    onion->shared_keys_2 = shared_key_cache_new(mono_time, mem, secret_key, KEYS_TIMEOUT, MAX_KEYS_PER_SLOT);
695
3.08k
    onion->shared_keys_3 = shared_key_cache_new(mono_time, mem, secret_key, KEYS_TIMEOUT, MAX_KEYS_PER_SLOT);
696
697
3.08k
    if (onion->shared_keys_1 == nullptr ||
698
3.08k
        onion->shared_keys_2 == nullptr ||
699
3.08k
        onion->shared_keys_3 == nullptr) {
700
6
        kill_onion(onion);
701
6
        return nullptr;
702
6
    }
703
704
705
3.07k
    networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_INITIAL, &handle_send_initial, onion);
706
3.07k
    networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_1, &handle_send_1, onion);
707
3.07k
    networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_2, &handle_send_2, onion);
708
709
3.07k
    networking_registerhandler(onion->net, NET_PACKET_ONION_RECV_3, &handle_recv_3, onion);
710
3.07k
    networking_registerhandler(onion->net, NET_PACKET_ONION_RECV_2, &handle_recv_2, onion);
711
3.07k
    networking_registerhandler(onion->net, NET_PACKET_ONION_RECV_1, &handle_recv_1, onion);
712
713
3.07k
    return onion;
714
3.08k
}
715
716
void kill_onion(Onion *onion)
717
3.09k
{
718
3.09k
    if (onion == nullptr) {
719
9
        return;
720
9
    }
721
722
3.08k
    networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_INITIAL, nullptr, nullptr);
723
3.08k
    networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_1, nullptr, nullptr);
724
3.08k
    networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_2, nullptr, nullptr);
725
726
3.08k
    networking_registerhandler(onion->net, NET_PACKET_ONION_RECV_3, nullptr, nullptr);
727
3.08k
    networking_registerhandler(onion->net, NET_PACKET_ONION_RECV_2, nullptr, nullptr);
728
3.08k
    networking_registerhandler(onion->net, NET_PACKET_ONION_RECV_1, nullptr, nullptr);
729
730
3.08k
    crypto_memzero(onion->secret_symmetric_key, sizeof(onion->secret_symmetric_key));
731
732
3.08k
    shared_key_cache_free(onion->shared_keys_1);
733
3.08k
    shared_key_cache_free(onion->shared_keys_2);
734
3.08k
    shared_key_cache_free(onion->shared_keys_3);
735
736
3.08k
    mem_delete(onion->mem, onion);
737
3.08k
}