Coverage Report

Created: 2026-10-24 08:16

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