Coverage Report

Created: 2025-12-31 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl36/ssl/quic/quic_lcidm.c
Line
Count
Source
1
/*
2
 * Copyright 2023-2025 The OpenSSL Project Authors. All Rights Reserved.
3
 *
4
 * Licensed under the Apache License 2.0 (the "License").  You may not use
5
 * this file except in compliance with the License.  You can obtain a copy
6
 * in the file LICENSE in the source distribution or at
7
 * https://www.openssl.org/source/license.html
8
 */
9
10
#include "internal/quic_lcidm.h"
11
#include "internal/quic_types.h"
12
#include "internal/quic_vlint.h"
13
#include "internal/common.h"
14
#include "crypto/siphash.h"
15
#include <openssl/lhash.h>
16
#include <openssl/rand.h>
17
#include <openssl/err.h>
18
19
/*
20
 * QUIC Local Connection ID Manager
21
 * ================================
22
 */
23
24
typedef struct quic_lcidm_conn_st QUIC_LCIDM_CONN;
25
26
enum {
27
    LCID_TYPE_ODCID, /* This LCID is the ODCID from the peer */
28
    LCID_TYPE_INITIAL, /* This is our Initial SCID */
29
    LCID_TYPE_NCID /* This LCID was issued via a NCID frame */
30
};
31
32
typedef struct quic_lcid_st {
33
    QUIC_CONN_ID cid;
34
    uint64_t seq_num;
35
36
    /* copy of the hash key from lcidm */
37
    uint64_t *hash_key;
38
39
    /* Back-pointer to the owning QUIC_LCIDM_CONN structure. */
40
    QUIC_LCIDM_CONN *conn;
41
42
    /* LCID_TYPE_* */
43
    unsigned int type : 2;
44
} QUIC_LCID;
45
46
DEFINE_LHASH_OF_EX(QUIC_LCID);
47
DEFINE_LHASH_OF_EX(QUIC_LCIDM_CONN);
48
49
struct quic_lcidm_conn_st {
50
    size_t num_active_lcid;
51
    LHASH_OF(QUIC_LCID) *lcids;
52
    void *opaque;
53
    QUIC_LCID *odcid_lcid_obj;
54
    uint64_t next_seq_num;
55
56
    /* Have we enrolled an ODCID? */
57
    unsigned int done_odcid : 1;
58
};
59
60
struct quic_lcidm_st {
61
    OSSL_LIB_CTX *libctx;
62
    uint64_t hash_key[2]; /* random key for siphash */
63
    LHASH_OF(QUIC_LCID) *lcids; /* (QUIC_CONN_ID) -> (QUIC_LCID *)  */
64
    LHASH_OF(QUIC_LCIDM_CONN) *conns; /* (void *opaque) -> (QUIC_LCIDM_CONN *) */
65
    size_t lcid_len; /* Length in bytes for all LCIDs */
66
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
67
    QUIC_CONN_ID next_lcid;
68
#endif
69
};
70
71
static unsigned long lcid_hash(const QUIC_LCID *lcid_obj)
72
6.89M
{
73
6.89M
    SIPHASH siphash = {
74
6.89M
        0,
75
6.89M
    };
76
6.89M
    unsigned long hashval = 0;
77
78
6.89M
    if (!SipHash_set_hash_size(&siphash, sizeof(unsigned long)))
79
0
        goto out;
80
6.89M
    if (!SipHash_Init(&siphash, (uint8_t *)lcid_obj->hash_key, 0, 0))
81
0
        goto out;
82
6.89M
    SipHash_Update(&siphash, lcid_obj->cid.id, lcid_obj->cid.id_len);
83
6.89M
    if (!SipHash_Final(&siphash, (unsigned char *)&hashval,
84
6.89M
            sizeof(unsigned long)))
85
0
        goto out;
86
6.89M
out:
87
6.89M
    return hashval;
88
6.89M
}
89
90
static int lcid_comp(const QUIC_LCID *a, const QUIC_LCID *b)
91
11.0M
{
92
11.0M
    return !ossl_quic_conn_id_eq(&a->cid, &b->cid);
93
11.0M
}
94
95
static unsigned long lcidm_conn_hash(const QUIC_LCIDM_CONN *conn)
96
3.47M
{
97
3.47M
    return (unsigned long)(uintptr_t)conn->opaque;
98
3.47M
}
99
100
static int lcidm_conn_comp(const QUIC_LCIDM_CONN *a, const QUIC_LCIDM_CONN *b)
101
3.15M
{
102
3.15M
    return a->opaque != b->opaque;
103
3.15M
}
104
105
QUIC_LCIDM *ossl_quic_lcidm_new(OSSL_LIB_CTX *libctx, size_t lcid_len)
106
33.1k
{
107
33.1k
    QUIC_LCIDM *lcidm = NULL;
108
109
33.1k
    if (lcid_len > QUIC_MAX_CONN_ID_LEN)
110
0
        goto err;
111
112
33.1k
    if ((lcidm = OPENSSL_zalloc(sizeof(*lcidm))) == NULL)
113
0
        goto err;
114
115
    /* generate a random key for the hash tables hash function */
116
33.1k
    if (!RAND_bytes_ex(libctx, (unsigned char *)&lcidm->hash_key,
117
33.1k
            sizeof(uint64_t) * 2, 0))
118
0
        goto err;
119
120
33.1k
    if ((lcidm->lcids = lh_QUIC_LCID_new(lcid_hash, lcid_comp)) == NULL)
121
0
        goto err;
122
123
33.1k
    if ((lcidm->conns = lh_QUIC_LCIDM_CONN_new(lcidm_conn_hash,
124
33.1k
             lcidm_conn_comp))
125
33.1k
        == NULL)
126
0
        goto err;
127
128
33.1k
    lcidm->libctx = libctx;
129
33.1k
    lcidm->lcid_len = lcid_len;
130
33.1k
    return lcidm;
131
132
0
err:
133
0
    if (lcidm != NULL) {
134
0
        lh_QUIC_LCID_free(lcidm->lcids);
135
0
        lh_QUIC_LCIDM_CONN_free(lcidm->conns);
136
0
        OPENSSL_free(lcidm);
137
0
    }
138
0
    return NULL;
139
33.1k
}
140
141
static void lcidm_delete_conn(QUIC_LCIDM *lcidm, QUIC_LCIDM_CONN *conn);
142
143
static void lcidm_delete_conn_(QUIC_LCIDM_CONN *conn, void *arg)
144
69.1k
{
145
69.1k
    lcidm_delete_conn((QUIC_LCIDM *)arg, conn);
146
69.1k
}
147
148
void ossl_quic_lcidm_free(QUIC_LCIDM *lcidm)
149
56.6k
{
150
56.6k
    if (lcidm == NULL)
151
19
        return;
152
153
    /*
154
     * Calling OPENSSL_lh_delete during a doall call is unsafe with our
155
     * current LHASH implementation for several reasons:
156
     *
157
     * - firstly, because deletes can cause the hashtable to be contracted,
158
     *   resulting in rehashing which might cause items in later buckets to
159
     *   move to earlier buckets, which might cause doall to skip an item,
160
     *   resulting in a memory leak;
161
     *
162
     * - secondly, because doall in general is not safe across hashtable
163
     *   size changes, as it caches hashtable size and pointer values
164
     *   while operating.
165
     *
166
     * The fix for this is to disable hashtable contraction using the following
167
     * call, which guarantees that no rehashing will occur so long as we only
168
     * call delete and not insert.
169
     */
170
56.5k
    lh_QUIC_LCIDM_CONN_set_down_load(lcidm->conns, 0);
171
172
56.5k
    lh_QUIC_LCIDM_CONN_doall_arg(lcidm->conns, lcidm_delete_conn_, lcidm);
173
174
56.5k
    lh_QUIC_LCID_free(lcidm->lcids);
175
56.5k
    lh_QUIC_LCIDM_CONN_free(lcidm->conns);
176
56.5k
    OPENSSL_free(lcidm);
177
56.5k
}
178
179
static QUIC_LCID *lcidm_get0_lcid(const QUIC_LCIDM *lcidm, const QUIC_CONN_ID *lcid)
180
4.89M
{
181
4.89M
    QUIC_LCID key;
182
183
4.89M
    key.cid = *lcid;
184
4.89M
    key.hash_key = (uint64_t *)lcidm->hash_key;
185
186
4.89M
    if (key.cid.id_len > QUIC_MAX_CONN_ID_LEN)
187
0
        return NULL;
188
189
4.89M
    return lh_QUIC_LCID_retrieve(lcidm->lcids, &key);
190
4.89M
}
191
192
static QUIC_LCIDM_CONN *lcidm_get0_conn(const QUIC_LCIDM *lcidm, void *opaque)
193
3.01M
{
194
3.01M
    QUIC_LCIDM_CONN key;
195
196
3.01M
    key.opaque = opaque;
197
198
3.01M
    return lh_QUIC_LCIDM_CONN_retrieve(lcidm->conns, &key);
199
3.01M
}
200
201
static QUIC_LCIDM_CONN *lcidm_upsert_conn(const QUIC_LCIDM *lcidm, void *opaque)
202
3.01M
{
203
3.01M
    QUIC_LCIDM_CONN *conn = lcidm_get0_conn(lcidm, opaque);
204
205
3.01M
    if (conn != NULL)
206
2.88M
        return conn;
207
208
136k
    if ((conn = OPENSSL_zalloc(sizeof(*conn))) == NULL)
209
0
        goto err;
210
211
136k
    if ((conn->lcids = lh_QUIC_LCID_new(lcid_hash, lcid_comp)) == NULL)
212
0
        goto err;
213
214
136k
    conn->opaque = opaque;
215
216
136k
    lh_QUIC_LCIDM_CONN_insert(lcidm->conns, conn);
217
136k
    if (lh_QUIC_LCIDM_CONN_error(lcidm->conns))
218
0
        goto err;
219
220
136k
    return conn;
221
222
0
err:
223
0
    if (conn != NULL) {
224
0
        lh_QUIC_LCID_free(conn->lcids);
225
0
        OPENSSL_free(conn);
226
0
    }
227
0
    return NULL;
228
136k
}
229
230
static void lcidm_delete_conn_lcid(QUIC_LCIDM *lcidm, QUIC_LCID *lcid_obj)
231
2.72M
{
232
2.72M
    lh_QUIC_LCID_delete(lcidm->lcids, lcid_obj);
233
2.72M
    lh_QUIC_LCID_delete(lcid_obj->conn->lcids, lcid_obj);
234
2.72M
    assert(lcid_obj->conn->num_active_lcid > 0);
235
2.72M
    --lcid_obj->conn->num_active_lcid;
236
2.72M
    OPENSSL_free(lcid_obj);
237
2.72M
}
238
239
/* doall_arg wrapper */
240
static void lcidm_delete_conn_lcid_(QUIC_LCID *lcid_obj, void *arg)
241
2.69M
{
242
2.69M
    lcidm_delete_conn_lcid((QUIC_LCIDM *)arg, lcid_obj);
243
2.69M
}
244
245
static void lcidm_delete_conn(QUIC_LCIDM *lcidm, QUIC_LCIDM_CONN *conn)
246
136k
{
247
    /* See comment in ossl_quic_lcidm_free */
248
136k
    lh_QUIC_LCID_set_down_load(conn->lcids, 0);
249
250
136k
    lh_QUIC_LCID_doall_arg(conn->lcids, lcidm_delete_conn_lcid_, lcidm);
251
136k
    lh_QUIC_LCIDM_CONN_delete(lcidm->conns, conn);
252
136k
    lh_QUIC_LCID_free(conn->lcids);
253
136k
    OPENSSL_free(conn);
254
136k
}
255
256
static QUIC_LCID *lcidm_conn_new_lcid(QUIC_LCIDM *lcidm, QUIC_LCIDM_CONN *conn,
257
    const QUIC_CONN_ID *lcid)
258
2.72M
{
259
2.72M
    QUIC_LCID *lcid_obj = NULL;
260
261
2.72M
    if (lcid->id_len > QUIC_MAX_CONN_ID_LEN)
262
0
        return NULL;
263
264
2.72M
    if ((lcid_obj = OPENSSL_zalloc(sizeof(*lcid_obj))) == NULL)
265
0
        goto err;
266
267
2.72M
    lcid_obj->cid = *lcid;
268
2.72M
    lcid_obj->conn = conn;
269
2.72M
    lcid_obj->hash_key = lcidm->hash_key;
270
271
2.72M
    lh_QUIC_LCID_insert(conn->lcids, lcid_obj);
272
2.72M
    if (lh_QUIC_LCID_error(conn->lcids))
273
0
        goto err;
274
275
2.72M
    lh_QUIC_LCID_insert(lcidm->lcids, lcid_obj);
276
2.72M
    if (lh_QUIC_LCID_error(lcidm->lcids)) {
277
0
        lh_QUIC_LCID_delete(conn->lcids, lcid_obj);
278
0
        goto err;
279
0
    }
280
281
2.72M
    ++conn->num_active_lcid;
282
2.72M
    return lcid_obj;
283
284
0
err:
285
0
    OPENSSL_free(lcid_obj);
286
0
    return NULL;
287
2.72M
}
288
289
size_t ossl_quic_lcidm_get_lcid_len(const QUIC_LCIDM *lcidm)
290
0
{
291
0
    return lcidm->lcid_len;
292
0
}
293
294
size_t ossl_quic_lcidm_get_num_active_lcid(const QUIC_LCIDM *lcidm,
295
    void *opaque)
296
0
{
297
0
    QUIC_LCIDM_CONN *conn;
298
299
0
    conn = lcidm_get0_conn(lcidm, opaque);
300
0
    if (conn == NULL)
301
0
        return 0;
302
303
0
    return conn->num_active_lcid;
304
0
}
305
306
static int lcidm_generate_cid(QUIC_LCIDM *lcidm,
307
    QUIC_CONN_ID *cid)
308
3.66M
{
309
3.66M
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
310
3.66M
    int i;
311
312
3.66M
    lcidm->next_lcid.id_len = (unsigned char)lcidm->lcid_len;
313
3.66M
    *cid = lcidm->next_lcid;
314
315
3.68M
    for (i = lcidm->lcid_len - 1; i >= 0; --i)
316
3.22M
        if (++lcidm->next_lcid.id[i] != 0)
317
3.21M
            break;
318
319
3.66M
    return 1;
320
#else
321
    return ossl_quic_gen_rand_conn_id(lcidm->libctx, lcidm->lcid_len, cid);
322
#endif
323
3.66M
}
324
325
static int lcidm_generate(QUIC_LCIDM *lcidm,
326
    void *opaque,
327
    unsigned int type,
328
    QUIC_CONN_ID *lcid_out,
329
    uint64_t *seq_num)
330
2.95M
{
331
2.95M
    QUIC_LCIDM_CONN *conn;
332
2.95M
    QUIC_LCID key, *lcid_obj;
333
2.95M
    size_t i;
334
3.78M
#define MAX_RETRIES 8
335
336
2.95M
    if ((conn = lcidm_upsert_conn(lcidm, opaque)) == NULL)
337
0
        return 0;
338
339
2.95M
    if ((type == LCID_TYPE_INITIAL && conn->next_seq_num > 0)
340
2.82M
        || conn->next_seq_num > OSSL_QUIC_VLINT_MAX)
341
126k
        return 0;
342
343
2.82M
    i = 0;
344
3.78M
    do {
345
3.78M
        if (i++ >= MAX_RETRIES)
346
            /*
347
             * Too many retries; should not happen but if it does, don't loop
348
             * endlessly.
349
             */
350
118k
            return 0;
351
352
3.66M
        if (!lcidm_generate_cid(lcidm, lcid_out))
353
0
            return 0;
354
355
3.66M
        key.cid = *lcid_out;
356
3.66M
        key.hash_key = lcidm->hash_key;
357
358
        /* If a collision occurs, retry. */
359
3.66M
    } while (lh_QUIC_LCID_retrieve(lcidm->lcids, &key) != NULL);
360
361
2.70M
    if ((lcid_obj = lcidm_conn_new_lcid(lcidm, conn, lcid_out)) == NULL)
362
0
        return 0;
363
364
2.70M
    lcid_obj->seq_num = conn->next_seq_num;
365
2.70M
    lcid_obj->type = type;
366
367
2.70M
    if (seq_num != NULL)
368
2.63M
        *seq_num = lcid_obj->seq_num;
369
370
2.70M
    ++conn->next_seq_num;
371
2.70M
    return 1;
372
2.70M
}
373
374
int ossl_quic_lcidm_enrol_odcid(QUIC_LCIDM *lcidm,
375
    void *opaque,
376
    const QUIC_CONN_ID *initial_odcid)
377
735k
{
378
735k
    QUIC_LCIDM_CONN *conn;
379
735k
    QUIC_LCID key, *lcid_obj;
380
381
735k
    if (initial_odcid == NULL || initial_odcid->id_len < QUIC_MIN_ODCID_LEN
382
24.9k
        || initial_odcid->id_len > QUIC_MAX_CONN_ID_LEN)
383
710k
        return 0;
384
385
24.9k
    if ((conn = lcidm_upsert_conn(lcidm, opaque)) == NULL)
386
0
        return 0;
387
388
24.9k
    if (conn->done_odcid)
389
8.94k
        return 0;
390
391
15.9k
    key.cid = *initial_odcid;
392
15.9k
    key.hash_key = lcidm->hash_key;
393
15.9k
    if (lh_QUIC_LCID_retrieve(lcidm->lcids, &key) != NULL)
394
3.79k
        return 0;
395
396
12.1k
    if ((lcid_obj = lcidm_conn_new_lcid(lcidm, conn, initial_odcid)) == NULL)
397
0
        return 0;
398
399
12.1k
    lcid_obj->seq_num = LCIDM_ODCID_SEQ_NUM;
400
12.1k
    lcid_obj->type = LCID_TYPE_ODCID;
401
402
12.1k
    conn->odcid_lcid_obj = lcid_obj;
403
12.1k
    conn->done_odcid = 1;
404
12.1k
    return 1;
405
12.1k
}
406
407
int ossl_quic_lcidm_generate_initial(QUIC_LCIDM *lcidm,
408
    void *opaque,
409
    QUIC_CONN_ID *initial_lcid)
410
214k
{
411
214k
    return lcidm_generate(lcidm, opaque, LCID_TYPE_INITIAL,
412
214k
        initial_lcid, NULL);
413
214k
}
414
415
int ossl_quic_lcidm_bind_channel(QUIC_LCIDM *lcidm, void *opaque,
416
    const QUIC_CONN_ID *lcid)
417
0
{
418
0
    QUIC_LCIDM_CONN *conn;
419
0
    QUIC_LCID *lcid_obj;
420
421
    /*
422
     * the plan is simple:
423
     *   make sure the lcid is still unused.
424
     *   do the same business as ossl_quic_lcidm_gnerate_initial() does,
425
     *   except we will use lcid instead of generating a new one.
426
     */
427
0
    if (ossl_quic_lcidm_lookup(lcidm, lcid, NULL, NULL) != 0)
428
0
        return 0;
429
430
0
    if ((conn = lcidm_upsert_conn(lcidm, opaque)) == NULL)
431
0
        return 0;
432
433
0
    if ((lcid_obj = lcidm_conn_new_lcid(lcidm, conn, lcid)) == NULL) {
434
0
        lcidm_delete_conn(lcidm, conn);
435
0
        return 0;
436
0
    }
437
438
0
    lcid_obj->seq_num = conn->next_seq_num;
439
0
    lcid_obj->type = LCID_TYPE_INITIAL;
440
0
    conn->next_seq_num++;
441
442
0
    return 1;
443
0
}
444
445
int ossl_quic_lcidm_generate(QUIC_LCIDM *lcidm,
446
    void *opaque,
447
    OSSL_QUIC_FRAME_NEW_CONN_ID *ncid_frame)
448
2.73M
{
449
2.73M
    ncid_frame->seq_num = 0;
450
2.73M
    ncid_frame->retire_prior_to = 0;
451
452
2.73M
    return lcidm_generate(lcidm, opaque, LCID_TYPE_NCID,
453
2.73M
        &ncid_frame->conn_id,
454
2.73M
        &ncid_frame->seq_num);
455
2.73M
}
456
457
int ossl_quic_lcidm_retire_odcid(QUIC_LCIDM *lcidm, void *opaque)
458
40.6k
{
459
40.6k
    QUIC_LCIDM_CONN *conn;
460
461
40.6k
    if ((conn = lcidm_upsert_conn(lcidm, opaque)) == NULL)
462
0
        return 0;
463
464
40.6k
    if (conn->odcid_lcid_obj == NULL)
465
33.4k
        return 0;
466
467
7.19k
    lcidm_delete_conn_lcid(lcidm, conn->odcid_lcid_obj);
468
7.19k
    conn->odcid_lcid_obj = NULL;
469
7.19k
    return 1;
470
40.6k
}
471
472
struct retire_args {
473
    QUIC_LCID *earliest_seq_num_lcid_obj;
474
    uint64_t earliest_seq_num, retire_prior_to;
475
};
476
477
static void retire_for_conn(QUIC_LCID *lcid_obj, void *arg)
478
9.38M
{
479
9.38M
    struct retire_args *args = arg;
480
481
    /* ODCID LCID cannot be retired via this API */
482
9.38M
    if (lcid_obj->type == LCID_TYPE_ODCID
483
9.37M
        || lcid_obj->seq_num >= args->retire_prior_to)
484
2.06M
        return;
485
486
7.31M
    if (lcid_obj->seq_num < args->earliest_seq_num) {
487
226k
        args->earliest_seq_num = lcid_obj->seq_num;
488
226k
        args->earliest_seq_num_lcid_obj = lcid_obj;
489
226k
    }
490
7.31M
}
491
492
int ossl_quic_lcidm_retire(QUIC_LCIDM *lcidm,
493
    void *opaque,
494
    uint64_t retire_prior_to,
495
    const QUIC_CONN_ID *containing_pkt_dcid,
496
    QUIC_CONN_ID *retired_lcid,
497
    uint64_t *retired_seq_num,
498
    int *did_retire)
499
85.3k
{
500
85.3k
    QUIC_LCIDM_CONN key, *conn;
501
85.3k
    struct retire_args args = { 0 };
502
503
85.3k
    key.opaque = opaque;
504
505
85.3k
    if (did_retire == NULL)
506
0
        return 0;
507
508
85.3k
    *did_retire = 0;
509
85.3k
    if ((conn = lh_QUIC_LCIDM_CONN_retrieve(lcidm->conns, &key)) == NULL)
510
19.8k
        return 1;
511
512
65.4k
    args.retire_prior_to = retire_prior_to;
513
65.4k
    args.earliest_seq_num = UINT64_MAX;
514
515
65.4k
    lh_QUIC_LCID_doall_arg(conn->lcids, retire_for_conn, &args);
516
65.4k
    if (args.earliest_seq_num_lcid_obj == NULL)
517
47.5k
        return 1;
518
519
17.9k
    if (containing_pkt_dcid != NULL
520
0
        && ossl_quic_conn_id_eq(&args.earliest_seq_num_lcid_obj->cid,
521
0
            containing_pkt_dcid))
522
0
        return 0;
523
524
17.9k
    *did_retire = 1;
525
17.9k
    if (retired_lcid != NULL)
526
17.9k
        *retired_lcid = args.earliest_seq_num_lcid_obj->cid;
527
17.9k
    if (retired_seq_num != NULL)
528
17.9k
        *retired_seq_num = args.earliest_seq_num_lcid_obj->seq_num;
529
530
17.9k
    lcidm_delete_conn_lcid(lcidm, args.earliest_seq_num_lcid_obj);
531
17.9k
    return 1;
532
17.9k
}
533
534
int ossl_quic_lcidm_cull(QUIC_LCIDM *lcidm, void *opaque)
535
102k
{
536
102k
    QUIC_LCIDM_CONN key, *conn;
537
538
102k
    key.opaque = opaque;
539
540
102k
    if ((conn = lh_QUIC_LCIDM_CONN_retrieve(lcidm->conns, &key)) == NULL)
541
35.2k
        return 0;
542
543
66.8k
    lcidm_delete_conn(lcidm, conn);
544
66.8k
    return 1;
545
102k
}
546
547
int ossl_quic_lcidm_lookup(QUIC_LCIDM *lcidm,
548
    const QUIC_CONN_ID *lcid,
549
    uint64_t *seq_num,
550
    void **opaque)
551
4.89M
{
552
4.89M
    QUIC_LCID *lcid_obj;
553
554
4.89M
    if (lcid == NULL)
555
0
        return 0;
556
557
4.89M
    if ((lcid_obj = lcidm_get0_lcid(lcidm, lcid)) == NULL)
558
351k
        return 0;
559
560
4.54M
    if (seq_num != NULL)
561
22.4k
        *seq_num = lcid_obj->seq_num;
562
563
4.54M
    if (opaque != NULL)
564
4.54M
        *opaque = lcid_obj->conn->opaque;
565
566
4.54M
    return 1;
567
4.89M
}
568
569
int ossl_quic_lcidm_debug_remove(QUIC_LCIDM *lcidm,
570
    const QUIC_CONN_ID *lcid)
571
0
{
572
0
    QUIC_LCID key, *lcid_obj;
573
574
0
    key.cid = *lcid;
575
0
    key.hash_key = lcidm->hash_key;
576
0
    if ((lcid_obj = lh_QUIC_LCID_retrieve(lcidm->lcids, &key)) == NULL)
577
0
        return 0;
578
579
0
    lcidm_delete_conn_lcid(lcidm, lcid_obj);
580
0
    return 1;
581
0
}
582
583
int ossl_quic_lcidm_debug_add(QUIC_LCIDM *lcidm, void *opaque,
584
    const QUIC_CONN_ID *lcid,
585
    uint64_t seq_num)
586
0
{
587
0
    QUIC_LCIDM_CONN *conn;
588
0
    QUIC_LCID key, *lcid_obj;
589
590
0
    if (lcid == NULL || lcid->id_len > QUIC_MAX_CONN_ID_LEN)
591
0
        return 0;
592
593
0
    if ((conn = lcidm_upsert_conn(lcidm, opaque)) == NULL)
594
0
        return 0;
595
596
0
    key.cid = *lcid;
597
0
    key.hash_key = lcidm->hash_key;
598
0
    if (lh_QUIC_LCID_retrieve(lcidm->lcids, &key) != NULL)
599
0
        return 0;
600
601
0
    if ((lcid_obj = lcidm_conn_new_lcid(lcidm, conn, lcid)) == NULL)
602
0
        return 0;
603
604
0
    lcid_obj->seq_num = seq_num;
605
0
    lcid_obj->type = LCID_TYPE_NCID;
606
0
    return 1;
607
0
}
608
609
int ossl_quic_lcidm_get_unused_cid(QUIC_LCIDM *lcidm, QUIC_CONN_ID *cid)
610
0
{
611
0
    int i;
612
613
0
    for (i = 0; i < 10; i++) {
614
0
        if (lcidm_generate_cid(lcidm, cid)
615
0
            && lcidm_get0_lcid(lcidm, cid) == NULL)
616
0
            return 1; /* not found <=> radomly generated cid is unused */
617
0
    }
618
619
0
    return 0;
620
0
}