Coverage Report

Created: 2024-01-26 01:52

/work/toxcore/announce.c
Line
Count
Source (jump to first uncovered line)
1
/* SPDX-License-Identifier: GPL-3.0-or-later
2
 * Copyright © 2020-2021 The TokTok team.
3
 */
4
5
/**
6
 * "Server side" of the DHT announcements protocol.
7
 */
8
9
#include "announce.h"
10
11
#include <assert.h>
12
#include <stdlib.h>
13
#include <string.h>
14
15
#include "DHT.h"
16
#include "LAN_discovery.h"
17
#include "ccompat.h"
18
#include "crypto_core.h"
19
#include "forwarding.h"
20
#include "logger.h"
21
#include "mem.h"
22
#include "mono_time.h"
23
#include "network.h"
24
#include "shared_key_cache.h"
25
#include "timed_auth.h"
26
#include "util.h"
27
28
// Settings for the shared key cache
29
3.76k
#define MAX_KEYS_PER_SLOT 4
30
3.76k
#define KEYS_TIMEOUT 600
31
32
uint8_t announce_response_of_request_type(uint8_t request_type)
33
4.05k
{
34
4.05k
    switch (request_type) {
35
4.05k
        case NET_PACKET_DATA_SEARCH_REQUEST:
36
4.05k
            return NET_PACKET_DATA_SEARCH_RESPONSE;
37
38
0
        case NET_PACKET_DATA_RETRIEVE_REQUEST:
39
0
            return NET_PACKET_DATA_RETRIEVE_RESPONSE;
40
41
0
        case NET_PACKET_STORE_ANNOUNCE_REQUEST:
42
0
            return NET_PACKET_STORE_ANNOUNCE_RESPONSE;
43
44
0
        default: {
45
0
            assert(false);
46
0
            return NET_PACKET_MAX;
47
0
        }
48
4.05k
    }
49
4.05k
}
50
51
typedef struct Announce_Entry {
52
    uint64_t store_until;
53
    uint8_t data_public_key[CRYPTO_PUBLIC_KEY_SIZE];
54
    uint8_t *data;
55
    uint32_t length;
56
} Announce_Entry;
57
58
struct Announcements {
59
    const Logger *log;
60
    const Memory *mem;
61
    const Random *rng;
62
    Forwarding *forwarding;
63
    const Mono_Time *mono_time;
64
    DHT *dht;
65
    Networking_Core *net;
66
    const uint8_t *public_key;
67
    const uint8_t *secret_key;
68
69
    Shared_Key_Cache *shared_keys;
70
    uint8_t hmac_key[CRYPTO_HMAC_KEY_SIZE];
71
72
    int32_t synch_offset;
73
74
    uint64_t start_time;
75
76
    Announce_Entry entries[ANNOUNCE_BUCKETS * ANNOUNCE_BUCKET_SIZE];
77
};
78
79
void announce_set_synch_offset(Announcements *announce, int32_t synch_offset)
80
3
{
81
3
    announce->synch_offset = synch_offset;
82
3
}
83
84
/**
85
 * An entry is considered to be "deleted" for the purposes of the protocol
86
 * once it has timed out.
87
 */
88
non_null()
89
static bool entry_is_empty(const Announcements *announce, const Announce_Entry *entry)
90
32.7k
{
91
32.7k
    return mono_time_get(announce->mono_time) >= entry->store_until;
92
32.7k
}
93
94
non_null()
95
static void delete_entry(Announce_Entry *entry)
96
0
{
97
0
    entry->store_until = 0;
98
0
}
99
100
/** Return bits (at most 8) from pk starting at index as uint8_t */
101
non_null()
102
static uint8_t truncate_pk_at_index(const uint8_t *pk, uint16_t index, uint16_t bits)
103
16.3k
{
104
16.3k
    assert(bits < 8);
105
16.3k
    const uint8_t i = index / 8;
106
16.3k
    const uint8_t j = index % 8;
107
16.3k
    return ((uint8_t)((i < CRYPTO_PUBLIC_KEY_SIZE ? pk[i] : 0) << j) >> (8 - bits)) |
108
16.3k
           ((i + 1 < CRYPTO_PUBLIC_KEY_SIZE ? pk[i + 1] : 0) >> (16 - bits - j));
109
16.3k
}
110
111
uint16_t announce_get_bucketnum(const uint8_t *base, const uint8_t *pk)
112
8.17k
{
113
8.17k
    const uint16_t index = bit_by_bit_cmp(base, pk);
114
115
8.17k
    return truncate_pk_at_index(base, index + 1, ANNOUNCE_BUCKET_PREFIX_LENGTH) ^
116
8.17k
           truncate_pk_at_index(pk, index + 1, ANNOUNCE_BUCKET_PREFIX_LENGTH);
117
8.17k
}
118
119
non_null()
120
static Announce_Entry *bucket_of_key(Announcements *announce, const uint8_t *pk)
121
4.09k
{
122
4.09k
    return &announce->entries[announce_get_bucketnum(announce->public_key, pk) * ANNOUNCE_BUCKET_SIZE];
123
4.09k
}
124
125
non_null()
126
static Announce_Entry *get_stored(Announcements *announce, const uint8_t *data_public_key)
127
0
{
128
0
    Announce_Entry *const bucket = bucket_of_key(announce, data_public_key);
129
130
0
    for (uint32_t i = 0; i < ANNOUNCE_BUCKET_SIZE; ++i) {
131
0
        if (pk_equal(bucket[i].data_public_key, data_public_key)) {
132
0
            if (entry_is_empty(announce, &bucket[i])) {
133
0
                break;
134
0
            }
135
136
0
            return &bucket[i];
137
0
        }
138
0
    }
139
140
0
    return nullptr;
141
0
}
142
143
non_null()
144
static const Announce_Entry *bucket_of_key_const(const Announcements *announce, const uint8_t *pk)
145
4.06k
{
146
4.06k
    return &announce->entries[announce_get_bucketnum(announce->public_key, pk) * ANNOUNCE_BUCKET_SIZE];
147
4.06k
}
148
149
non_null()
150
static const Announce_Entry *get_stored_const(const Announcements *announce, const uint8_t *data_public_key)
151
4.06k
{
152
4.06k
    const Announce_Entry *const bucket = bucket_of_key_const(announce, data_public_key);
153
154
36.5k
    for (uint32_t i = 0; i < ANNOUNCE_BUCKET_SIZE; ++i) {
155
32.5k
        if (pk_equal(bucket[i].data_public_key, data_public_key)) {
156
8
            if (entry_is_empty(announce, &bucket[i])) {
157
2
                break;
158
2
            }
159
160
6
            return &bucket[i];
161
8
        }
162
32.5k
    }
163
164
4.06k
    return nullptr;
165
4.06k
}
166
167
168
bool announce_on_stored(const Announcements *announce, const uint8_t *data_public_key,
169
                        announce_on_retrieve_cb *on_retrieve_callback, void *object)
170
12
{
171
12
    const Announce_Entry *const entry = get_stored_const(announce, data_public_key);
172
173
12
    if (entry == nullptr || entry->data == nullptr) {
174
6
        return false;
175
6
    }
176
177
6
    if (on_retrieve_callback != nullptr) {
178
3
        on_retrieve_callback(object, entry->data, entry->length);
179
3
    }
180
181
6
    return true;
182
12
}
183
184
/**
185
 * Return existing entry for this key if it exists, else an empty
186
 * slot in the key's bucket if one exists, else an entry in the key's bucket
187
 * of greatest 2-adic distance greater than that of the key bucket if one
188
 * exists, else nullptr.
189
 */
190
non_null()
191
static Announce_Entry *find_entry_slot(Announcements *announce, const uint8_t *data_public_key)
192
4.09k
{
193
4.09k
    Announce_Entry *const bucket = bucket_of_key(announce, data_public_key);
194
195
4.09k
    Announce_Entry *slot = nullptr;
196
4.09k
    uint16_t min_index = bit_by_bit_cmp(announce->public_key, data_public_key);
197
198
36.8k
    for (uint32_t i = 0; i < ANNOUNCE_BUCKET_SIZE; ++i) {
199
32.7k
        if (pk_equal(bucket[i].data_public_key, data_public_key)) {
200
2
            return &bucket[i];
201
2
        }
202
203
32.7k
        if (entry_is_empty(announce, &bucket[i])) {
204
32.5k
            slot = &bucket[i];
205
32.5k
            min_index = 0;
206
32.5k
            continue;
207
32.5k
        }
208
209
156
        const uint16_t index = bit_by_bit_cmp(announce->public_key, bucket[i].data_public_key);
210
211
156
        if (index < min_index) {
212
39
            slot = &bucket[i];
213
39
            min_index = index;
214
39
        }
215
156
    }
216
217
4.08k
    return slot;
218
4.09k
}
219
220
non_null()
221
static bool would_accept_store_request(Announcements *announce, const uint8_t *data_public_key)
222
4.05k
{
223
4.05k
    return find_entry_slot(announce, data_public_key) != nullptr;
224
4.05k
}
225
226
bool announce_store_data(Announcements *announce, const uint8_t *data_public_key,
227
                         const uint8_t *data, uint32_t length, uint32_t timeout)
228
36
{
229
36
    if (length > MAX_ANNOUNCEMENT_SIZE) {
230
0
        return false;
231
0
    }
232
233
36
    Announce_Entry *entry = find_entry_slot(announce, data_public_key);
234
235
36
    if (entry == nullptr) {
236
3
        return false;
237
3
    }
238
239
33
    if (length > 0) {
240
33
        assert(data != nullptr);
241
242
33
        if (entry->data != nullptr) {
243
6
            free(entry->data);
244
6
        }
245
246
33
        uint8_t *entry_data = (uint8_t *)malloc(length);
247
248
33
        if (entry_data == nullptr) {
249
0
            entry->data = nullptr;  // TODO(iphydf): Is this necessary?
250
0
            return false;
251
0
        }
252
253
33
        memcpy(entry_data, data, length);
254
33
        entry->data = entry_data;
255
33
    }
256
257
33
    entry->length = length;
258
33
    memcpy(entry->data_public_key, data_public_key, CRYPTO_PUBLIC_KEY_SIZE);
259
33
    entry->store_until = mono_time_get(announce->mono_time) + timeout;
260
261
33
    return true;
262
33
}
263
264
non_null()
265
static uint32_t calculate_timeout(const Announcements *announce, uint32_t requested_timeout)
266
10
{
267
10
    const uint64_t uptime = mono_time_get(announce->mono_time) - announce->start_time;
268
10
    const uint32_t max_announcement_timeout = max_u32(
269
10
                (uint32_t)min_u64(
270
10
                    MAX_MAX_ANNOUNCEMENT_TIMEOUT,
271
10
                    uptime / MAX_ANNOUNCEMENT_TIMEOUT_UPTIME_RATIO),
272
10
                MIN_MAX_ANNOUNCEMENT_TIMEOUT);
273
274
10
    return min_u32(max_announcement_timeout, requested_timeout);
275
10
}
276
277
12.3k
#define DATA_SEARCH_TO_AUTH_MAX_SIZE (CRYPTO_PUBLIC_KEY_SIZE * 2 + MAX_PACKED_IPPORT_SIZE + MAX_SENDBACK_SIZE)
278
279
non_null(1, 2, 3, 4, 7) nullable(5)
280
static int create_data_search_to_auth(const Logger *logger, const uint8_t *data_public_key,
281
                                      const uint8_t *requester_key,
282
                                      const IP_Port *source, const uint8_t *sendback, uint16_t sendback_length,
283
                                      uint8_t *dest, uint16_t max_length)
284
4.11k
{
285
4.11k
    if (max_length < DATA_SEARCH_TO_AUTH_MAX_SIZE
286
4.11k
            || sendback_length > MAX_SENDBACK_SIZE) {
287
1
        return -1;
288
1
    }
289
290
4.10k
    memcpy(dest, data_public_key, CRYPTO_PUBLIC_KEY_SIZE);
291
4.10k
    memcpy(dest + CRYPTO_PUBLIC_KEY_SIZE, requester_key, CRYPTO_PUBLIC_KEY_SIZE);
292
293
4.10k
    const int ipport_length = pack_ip_port(logger, dest + CRYPTO_PUBLIC_KEY_SIZE * 2, MAX_PACKED_IPPORT_SIZE, source);
294
295
4.10k
    if (ipport_length == -1) {
296
0
        return -1;
297
0
    }
298
299
4.10k
    if (sendback_length > 0) {
300
3
        assert(sendback != nullptr);
301
3
        memcpy(dest + CRYPTO_PUBLIC_KEY_SIZE * 2 + ipport_length, sendback, sendback_length);
302
3
    }
303
304
4.10k
    return CRYPTO_PUBLIC_KEY_SIZE * 2 + ipport_length + sendback_length;
305
4.10k
}
306
307
4.06k
#define DATA_SEARCH_TIMEOUT 60
308
309
non_null()
310
static int create_reply_plain_data_search_request(Announcements *announce,
311
        const IP_Port *source,
312
        const uint8_t *data, uint16_t length,
313
        uint8_t *reply, uint16_t reply_max_length,
314
        const uint8_t *to_auth, uint16_t to_auth_length)
315
4.07k
{
316
4.07k
    if (length != CRYPTO_PUBLIC_KEY_SIZE &&
317
4.07k
            length != CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SHA256_SIZE) {
318
17
        return -1;
319
17
    }
320
321
4.05k
    const uint8_t *const data_public_key = data;
322
323
4.05k
    const uint8_t *previous_hash = nullptr;
324
325
4.05k
    if (length == CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SHA256_SIZE) {
326
2
        previous_hash = data + CRYPTO_PUBLIC_KEY_SIZE;
327
2
    }
328
329
4.05k
    const int nodes_max_length = (int)reply_max_length -
330
4.05k
                                 (CRYPTO_PUBLIC_KEY_SIZE + 1 + CRYPTO_SHA256_SIZE + TIMED_AUTH_SIZE + 1 + 1);
331
332
4.05k
    if (nodes_max_length < 0) {
333
0
        return -1;
334
0
    }
335
336
4.05k
    uint8_t *p = reply;
337
338
4.05k
    memcpy(p, data_public_key, CRYPTO_PUBLIC_KEY_SIZE);
339
4.05k
    p += CRYPTO_PUBLIC_KEY_SIZE;
340
341
4.05k
    const Announce_Entry *const stored = get_stored_const(announce, data_public_key);
342
343
4.05k
    if (stored == nullptr) {
344
4.05k
        *p = 0;
345
4.05k
        ++p;
346
4.05k
    } else {
347
0
        *p = 1;
348
0
        ++p;
349
0
        crypto_sha256(p, stored->data, stored->length);
350
0
        p += CRYPTO_SHA256_SIZE;
351
0
    }
352
353
4.05k
    generate_timed_auth(announce->mono_time, DATA_SEARCH_TIMEOUT, announce->hmac_key,
354
4.05k
                        to_auth, to_auth_length, p);
355
4.05k
    p += TIMED_AUTH_SIZE;
356
357
4.05k
    *p = would_accept_store_request(announce, data_public_key);
358
4.05k
    ++p;
359
360
4.05k
    Node_format nodes_list[MAX_SENT_NODES];
361
4.05k
    const int num_nodes = get_close_nodes(announce->dht, data_public_key, nodes_list,
362
4.05k
                                          net_family_unspec(), ip_is_lan(&source->ip), true);
363
364
4.05k
    if (num_nodes < 0 || num_nodes > MAX_SENT_NODES) {
365
0
        return -1;
366
0
    }
367
368
4.05k
    *p = num_nodes;
369
4.05k
    ++p;
370
371
4.05k
    p += pack_nodes(announce->log, p, nodes_max_length, nodes_list, num_nodes);
372
373
4.05k
    const uint32_t reply_len = p - reply;
374
375
4.05k
    if (previous_hash != nullptr) {
376
2
        uint8_t hash[CRYPTO_SHA256_SIZE];
377
378
2
        crypto_sha256(hash, reply, reply_len);
379
380
2
        if (crypto_sha256_eq(hash, previous_hash)) {
381
1
            return CRYPTO_PUBLIC_KEY_SIZE;
382
1
        }
383
2
    }
384
385
4.05k
    return reply_len;
386
4.05k
}
387
388
non_null()
389
static int create_reply_plain_data_retrieve_request(
390
        const Announcements *announce,
391
        const IP_Port *source,
392
        const uint8_t *data, uint16_t length,
393
        uint8_t *reply, uint16_t reply_max_length,
394
        const uint8_t *to_auth, uint16_t to_auth_length)
395
12
{
396
12
    if (length != CRYPTO_PUBLIC_KEY_SIZE + 1 + TIMED_AUTH_SIZE) {
397
10
        return -1;
398
10
    }
399
400
2
    if (data[CRYPTO_PUBLIC_KEY_SIZE] != 0) {
401
1
        return -1;
402
1
    }
403
404
1
    const uint8_t *const data_public_key = data;
405
1
    const uint8_t *const auth = data + CRYPTO_PUBLIC_KEY_SIZE + 1;
406
407
1
    if (!check_timed_auth(announce->mono_time, DATA_SEARCH_TIMEOUT, announce->hmac_key,
408
1
                          to_auth, to_auth_length, auth)) {
409
1
        return -1;
410
1
    }
411
412
0
    const Announce_Entry *const entry = get_stored_const(announce, data_public_key);
413
414
0
    if (entry == nullptr) {
415
0
        return -1;
416
0
    }
417
418
0
    const uint16_t reply_len = CRYPTO_PUBLIC_KEY_SIZE + 1 + entry->length;
419
420
0
    if (reply_max_length < reply_len) {
421
0
        return -1;
422
0
    }
423
424
0
    memcpy(reply, data_public_key, CRYPTO_PUBLIC_KEY_SIZE);
425
0
    reply[CRYPTO_PUBLIC_KEY_SIZE] = 1;
426
0
    memcpy(reply + CRYPTO_PUBLIC_KEY_SIZE + 1, entry->data, entry->length);
427
428
0
    return reply_len;
429
0
}
430
431
non_null()
432
static int create_reply_plain_store_announce_request(Announcements *announce,
433
        const IP_Port *source,
434
        const uint8_t *data, uint16_t length,
435
        uint8_t *reply, uint16_t reply_max_length,
436
        const uint8_t *to_auth, uint16_t to_auth_length)
437
22
{
438
22
    const int plain_len = (int)length - (CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_MAC_SIZE);
439
22
    const int announcement_len = plain_len - (TIMED_AUTH_SIZE + sizeof(uint32_t) + 1);
440
441
22
    const uint8_t *const data_public_key = data;
442
443
22
    if (announcement_len < 0) {
444
12
        return -1;
445
12
    }
446
447
10
    VLA(uint8_t, plain, plain_len);
448
449
10
    const uint8_t* shared_key = shared_key_cache_lookup(announce->shared_keys, data_public_key);
450
451
10
    if (shared_key == nullptr) {
452
        /* Error looking up/deriving the shared key */
453
0
        return -1;
454
0
    }
455
456
10
    if (decrypt_data_symmetric(shared_key,
457
10
                               data + CRYPTO_PUBLIC_KEY_SIZE,
458
10
                               data + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE,
459
10
                               plain_len + CRYPTO_MAC_SIZE,
460
10
                               plain) != plain_len) {
461
0
        return -1;
462
0
    }
463
464
10
    const uint8_t *const auth = plain;
465
10
    uint32_t requested_timeout;
466
10
    net_unpack_u32(plain + TIMED_AUTH_SIZE, &requested_timeout);
467
10
    const uint32_t timeout = calculate_timeout(announce, requested_timeout);
468
10
    const uint8_t announcement_type = plain[TIMED_AUTH_SIZE + sizeof(uint32_t)];
469
10
    const uint8_t *announcement = plain + TIMED_AUTH_SIZE + sizeof(uint32_t) + 1;
470
471
10
    if (!check_timed_auth(announce->mono_time, DATA_SEARCH_TIMEOUT, announce->hmac_key,
472
10
                          to_auth, to_auth_length, auth)) {
473
10
        return -1;
474
10
    }
475
476
0
    if (announcement_type > 1) {
477
0
        return -1;
478
0
    }
479
480
0
    if (announcement_type == 1) {
481
0
        if (announcement_len != CRYPTO_SHA256_SIZE) {
482
0
            return -1;
483
0
        }
484
485
0
        Announce_Entry *stored = get_stored(announce, data_public_key);
486
487
0
        if (stored == nullptr) {
488
0
            return -1;
489
0
        }
490
491
0
        uint8_t stored_hash[CRYPTO_SHA256_SIZE];
492
0
        crypto_sha256(stored_hash, stored->data, stored->length);
493
494
0
        if (!crypto_sha256_eq(announcement, stored_hash)) {
495
0
            delete_entry(stored);
496
0
            return -1;
497
0
        } else {
498
0
            stored->store_until = mono_time_get(announce->mono_time) + timeout;
499
0
        }
500
0
    } else {
501
0
        if (!announce_store_data(announce, data_public_key, announcement, announcement_len, timeout)) {
502
0
            return -1;
503
0
        }
504
0
    }
505
506
0
    const uint16_t reply_len = CRYPTO_PUBLIC_KEY_SIZE + sizeof(uint32_t) + sizeof(uint64_t);
507
508
0
    if (reply_max_length < reply_len) {
509
0
        return -1;
510
0
    }
511
512
0
    memcpy(reply, data_public_key, CRYPTO_PUBLIC_KEY_SIZE);
513
0
    net_pack_u32(reply + CRYPTO_PUBLIC_KEY_SIZE, timeout);
514
0
    net_pack_u64(reply + CRYPTO_PUBLIC_KEY_SIZE + sizeof(uint32_t),
515
0
                 mono_time_get(announce->mono_time) + announce->synch_offset);
516
0
    return reply_len;
517
0
}
518
519
non_null(1, 2, 3, 7, 9) nullable(5)
520
static int create_reply_plain(Announcements *announce,
521
                              const uint8_t *requester_key, const IP_Port *source, uint8_t type,
522
                              const uint8_t *sendback, uint16_t sendback_length,
523
                              const uint8_t *data, uint16_t length,
524
                              uint8_t *reply, uint16_t reply_max_length)
525
4.12k
{
526
4.12k
    if (length < CRYPTO_PUBLIC_KEY_SIZE) {
527
12
        return -1;
528
12
    }
529
530
4.11k
    const uint8_t *const data_public_key = data;
531
532
4.11k
    uint8_t to_auth[DATA_SEARCH_TO_AUTH_MAX_SIZE];
533
4.11k
    const int to_auth_length = create_data_search_to_auth(announce->log, data_public_key, requester_key, source,
534
4.11k
                               sendback, sendback_length, to_auth, DATA_SEARCH_TO_AUTH_MAX_SIZE);
535
536
4.11k
    if (to_auth_length == -1) {
537
1
        return -1;
538
1
    }
539
540
4.10k
    switch (type) {
541
4.07k
        case NET_PACKET_DATA_SEARCH_REQUEST:
542
4.07k
            return create_reply_plain_data_search_request(announce, source, data, length, reply, reply_max_length, to_auth,
543
4.07k
                    (uint16_t)to_auth_length);
544
545
12
        case NET_PACKET_DATA_RETRIEVE_REQUEST:
546
12
            return create_reply_plain_data_retrieve_request(announce, source, data, length, reply, reply_max_length, to_auth,
547
12
                    (uint16_t)to_auth_length);
548
549
22
        case NET_PACKET_STORE_ANNOUNCE_REQUEST:
550
22
            return create_reply_plain_store_announce_request(announce, source, data, length, reply, reply_max_length, to_auth,
551
22
                    (uint16_t)to_auth_length);
552
553
3
        default:
554
3
            return -1;
555
4.10k
    }
556
4.10k
}
557
558
non_null(1, 2, 5, 7) nullable(3)
559
static int create_reply(Announcements *announce, const IP_Port *source,
560
                        const uint8_t *sendback, uint16_t sendback_length,
561
                        const uint8_t *data, uint16_t length,
562
                        uint8_t *reply, uint16_t reply_max_length)
563
4.14k
{
564
4.14k
    const int plain_len = (int)length - (1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_MAC_SIZE);
565
566
4.14k
    if (plain_len < (int)sizeof(uint64_t)) {
567
14
        return -1;
568
14
    }
569
570
4.13k
    VLA(uint8_t, plain, plain_len);
571
4.13k
    const uint8_t *shared_key = dht_get_shared_key_recv(announce->dht, data + 1);
572
573
4.13k
    if (decrypt_data_symmetric(shared_key,
574
4.13k
                               data + 1 + CRYPTO_PUBLIC_KEY_SIZE,
575
4.13k
                               data + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE,
576
4.13k
                               plain_len + CRYPTO_MAC_SIZE,
577
4.13k
                               plain) != plain_len) {
578
10
        return -1;
579
10
    }
580
581
4.12k
    const int plain_reply_max_len = (int)reply_max_length -
582
4.12k
                                    (1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_MAC_SIZE);
583
584
4.12k
    if (plain_reply_max_len < sizeof(uint64_t)) {
585
0
        return -1;
586
0
    }
587
588
4.12k
    VLA(uint8_t, plain_reply, plain_reply_max_len);
589
590
4.12k
    const int plain_reply_noping_len = create_reply_plain(announce,
591
4.12k
                                       data + 1, source, data[0],
592
4.12k
                                       sendback, sendback_length,
593
4.12k
                                       plain, plain_len - sizeof(uint64_t),
594
4.12k
                                       plain_reply, plain_reply_max_len - sizeof(uint64_t));
595
596
4.12k
    if (plain_reply_noping_len == -1) {
597
67
        return -1;
598
67
    }
599
600
4.05k
    memcpy(plain_reply + plain_reply_noping_len,
601
4.05k
           plain + (plain_len - sizeof(uint64_t)), sizeof(uint64_t));
602
603
4.05k
    const uint16_t plain_reply_len = plain_reply_noping_len + sizeof(uint64_t);
604
605
4.05k
    const uint8_t response_type = announce_response_of_request_type(data[0]);
606
607
4.05k
    return dht_create_packet(announce->mem, announce->rng, announce->public_key, shared_key,
608
4.05k
                             response_type, plain_reply, plain_reply_len, reply, reply_max_length);
609
4.12k
}
610
611
non_null(1, 2, 3, 5) nullable(7)
612
static void forwarded_request_callback(void *object, const IP_Port *forwarder,
613
                                       const uint8_t *sendback, uint16_t sendback_length,
614
                                       const uint8_t *data, uint16_t length, void *userdata)
615
7
{
616
7
    Announcements *announce = (Announcements *) object;
617
618
7
    uint8_t reply[MAX_FORWARD_DATA_SIZE];
619
620
7
    const int len = create_reply(announce, forwarder,
621
7
                                 sendback, sendback_length,
622
7
                                 data, length, reply, sizeof(reply));
623
624
7
    if (len == -1) {
625
7
        return;
626
7
    }
627
628
0
    forward_reply(announce->net, forwarder, sendback, sendback_length, reply, len);
629
0
}
630
631
non_null(1, 2, 3) nullable(5)
632
static int handle_dht_announce_request(
633
    void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, void *userdata)
634
4.13k
{
635
4.13k
    Announcements *announce = (Announcements *)object;
636
637
4.13k
    uint8_t reply[MAX_FORWARD_DATA_SIZE];
638
639
4.13k
    const int len
640
4.13k
        = create_reply(announce, source, nullptr, 0, packet, length, reply, sizeof(reply));
641
642
4.13k
    if (len == -1) {
643
106
        return -1;
644
106
    }
645
646
4.03k
    return sendpacket(announce->net, source, reply, len) == len ? 0 : -1;
647
4.13k
}
648
649
Announcements *new_announcements(const Logger *log, const Memory *mem, const Random *rng, const Mono_Time *mono_time,
650
                                 Forwarding *forwarding)
651
3.78k
{
652
3.78k
    if (log == nullptr || mono_time == nullptr || forwarding == nullptr) {
653
0
        return nullptr;
654
0
    }
655
656
3.78k
    Announcements *announce = (Announcements *)calloc(1, sizeof(Announcements));
657
658
3.78k
    if (announce == nullptr) {
659
20
        return nullptr;
660
20
    }
661
662
3.76k
    announce->log = log;
663
3.76k
    announce->mem = mem;
664
3.76k
    announce->rng = rng;
665
3.76k
    announce->forwarding = forwarding;
666
3.76k
    announce->mono_time = mono_time;
667
3.76k
    announce->dht = forwarding_get_dht(forwarding);
668
3.76k
    announce->net = dht_get_net(announce->dht);
669
3.76k
    announce->public_key = dht_get_self_public_key(announce->dht);
670
3.76k
    announce->secret_key = dht_get_self_secret_key(announce->dht);
671
3.76k
    new_hmac_key(announce->rng, announce->hmac_key);
672
3.76k
    announce->shared_keys = shared_key_cache_new(log, mono_time, mem, announce->secret_key, KEYS_TIMEOUT, MAX_KEYS_PER_SLOT);
673
3.76k
    if (announce->shared_keys == nullptr) {
674
45
        free(announce);
675
45
        return nullptr;
676
45
    }
677
678
3.71k
    announce->start_time = mono_time_get(announce->mono_time);
679
680
3.71k
    set_callback_forwarded_request(forwarding, forwarded_request_callback, announce);
681
682
3.71k
    networking_registerhandler(announce->net, NET_PACKET_DATA_SEARCH_REQUEST, handle_dht_announce_request, announce);
683
3.71k
    networking_registerhandler(announce->net, NET_PACKET_DATA_RETRIEVE_REQUEST, handle_dht_announce_request, announce);
684
3.71k
    networking_registerhandler(announce->net, NET_PACKET_STORE_ANNOUNCE_REQUEST, handle_dht_announce_request, announce);
685
686
3.71k
    return announce;
687
3.76k
}
688
689
void kill_announcements(Announcements *announce)
690
2.75k
{
691
2.75k
    if (announce == nullptr) {
692
85
        return;
693
85
    }
694
695
2.66k
    set_callback_forwarded_request(announce->forwarding, nullptr, nullptr);
696
697
2.66k
    networking_registerhandler(announce->net, NET_PACKET_DATA_SEARCH_REQUEST, nullptr, nullptr);
698
2.66k
    networking_registerhandler(announce->net, NET_PACKET_DATA_RETRIEVE_REQUEST, nullptr, nullptr);
699
2.66k
    networking_registerhandler(announce->net, NET_PACKET_STORE_ANNOUNCE_REQUEST, nullptr, nullptr);
700
701
2.66k
    crypto_memzero(announce->hmac_key, CRYPTO_HMAC_KEY_SIZE);
702
2.66k
    shared_key_cache_free(announce->shared_keys);
703
704
685k
    for (uint32_t i = 0; i < ANNOUNCE_BUCKETS * ANNOUNCE_BUCKET_SIZE; ++i) {
705
683k
        if (announce->entries[i].data != nullptr) {
706
27
            free(announce->entries[i].data);
707
27
        }
708
683k
    }
709
710
2.66k
    free(announce);
711
2.66k
}