Coverage Report

Created: 2026-04-01 06:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl36/ssl/quic/quic_wire_pkt.c
Line
Count
Source
1
/*
2
 * Copyright 2022-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 <openssl/err.h>
11
#include "internal/common.h"
12
#include "internal/quic_wire_pkt.h"
13
14
int ossl_quic_hdr_protector_init(QUIC_HDR_PROTECTOR *hpr,
15
    OSSL_LIB_CTX *libctx,
16
    const char *propq,
17
    uint32_t cipher_id,
18
    const unsigned char *quic_hp_key,
19
    size_t quic_hp_key_len)
20
180k
{
21
180k
    const char *cipher_name = NULL;
22
23
180k
    switch (cipher_id) {
24
106k
    case QUIC_HDR_PROT_CIPHER_AES_128:
25
106k
        cipher_name = "AES-128-ECB";
26
106k
        break;
27
69.1k
    case QUIC_HDR_PROT_CIPHER_AES_256:
28
69.1k
        cipher_name = "AES-256-ECB";
29
69.1k
        break;
30
4.21k
    case QUIC_HDR_PROT_CIPHER_CHACHA:
31
4.21k
        cipher_name = "ChaCha20";
32
4.21k
        break;
33
0
    default:
34
0
        ERR_raise(ERR_LIB_SSL, ERR_R_UNSUPPORTED);
35
0
        return 0;
36
180k
    }
37
38
180k
    hpr->cipher_ctx = EVP_CIPHER_CTX_new();
39
180k
    if (hpr->cipher_ctx == NULL) {
40
0
        ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
41
0
        return 0;
42
0
    }
43
44
180k
    hpr->cipher = EVP_CIPHER_fetch(libctx, cipher_name, propq);
45
180k
    if (hpr->cipher == NULL
46
180k
        || quic_hp_key_len != (size_t)EVP_CIPHER_get_key_length(hpr->cipher)) {
47
0
        ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
48
0
        goto err;
49
0
    }
50
51
180k
    if (!EVP_CipherInit_ex(hpr->cipher_ctx, hpr->cipher, NULL,
52
180k
            quic_hp_key, NULL, 1)) {
53
0
        ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
54
0
        goto err;
55
0
    }
56
57
180k
    hpr->libctx = libctx;
58
180k
    hpr->propq = propq;
59
180k
    hpr->cipher_id = cipher_id;
60
180k
    return 1;
61
62
0
err:
63
0
    ossl_quic_hdr_protector_cleanup(hpr);
64
0
    return 0;
65
180k
}
66
67
void ossl_quic_hdr_protector_cleanup(QUIC_HDR_PROTECTOR *hpr)
68
180k
{
69
180k
    EVP_CIPHER_CTX_free(hpr->cipher_ctx);
70
180k
    hpr->cipher_ctx = NULL;
71
72
180k
    EVP_CIPHER_free(hpr->cipher);
73
180k
    hpr->cipher = NULL;
74
180k
}
75
76
static int hdr_generate_mask(QUIC_HDR_PROTECTOR *hpr,
77
    const unsigned char *sample, size_t sample_len,
78
    unsigned char *mask)
79
3.42M
{
80
3.42M
    int l = 0;
81
3.42M
    unsigned char dst[16];
82
3.42M
    static const unsigned char zeroes[5] = { 0 };
83
3.42M
    size_t i;
84
85
3.42M
    if (hpr->cipher_id == QUIC_HDR_PROT_CIPHER_AES_128
86
3.29M
        || hpr->cipher_id == QUIC_HDR_PROT_CIPHER_AES_256) {
87
3.29M
        if (sample_len < 16) {
88
4.14k
            ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT);
89
4.14k
            return 0;
90
4.14k
        }
91
92
3.29M
        if (!EVP_CipherInit_ex(hpr->cipher_ctx, NULL, NULL, NULL, NULL, 1)
93
3.29M
            || !EVP_CipherUpdate(hpr->cipher_ctx, dst, &l, sample, 16)) {
94
0
            ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
95
0
            return 0;
96
0
        }
97
98
19.7M
        for (i = 0; i < 5; ++i)
99
16.4M
            mask[i] = dst[i];
100
3.29M
    } else if (hpr->cipher_id == QUIC_HDR_PROT_CIPHER_CHACHA) {
101
121k
        if (sample_len < 16) {
102
2.81k
            ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT);
103
2.81k
            return 0;
104
2.81k
        }
105
106
118k
        if (!EVP_CipherInit_ex(hpr->cipher_ctx, NULL, NULL, NULL, sample, 1)
107
118k
            || !EVP_CipherUpdate(hpr->cipher_ctx, mask, &l,
108
118k
                zeroes, sizeof(zeroes))) {
109
0
            ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
110
0
            return 0;
111
0
        }
112
118k
    } else {
113
0
        ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
114
0
        assert(0);
115
0
        return 0;
116
0
    }
117
118
3.41M
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
119
    /* No matter what we did above we use the same mask in fuzzing mode */
120
3.41M
    memset(mask, 0, 5);
121
3.41M
#endif
122
123
3.41M
    return 1;
124
3.42M
}
125
126
int ossl_quic_hdr_protector_decrypt(QUIC_HDR_PROTECTOR *hpr,
127
    QUIC_PKT_HDR_PTRS *ptrs)
128
1.21M
{
129
1.21M
    return ossl_quic_hdr_protector_decrypt_fields(hpr,
130
1.21M
        ptrs->raw_sample,
131
1.21M
        ptrs->raw_sample_len,
132
1.21M
        ptrs->raw_start,
133
1.21M
        ptrs->raw_pn);
134
1.21M
}
135
136
int ossl_quic_hdr_protector_decrypt_fields(QUIC_HDR_PROTECTOR *hpr,
137
    const unsigned char *sample,
138
    size_t sample_len,
139
    unsigned char *first_byte,
140
    unsigned char *pn_bytes)
141
1.21M
{
142
1.21M
    unsigned char mask[5], pn_len, i;
143
144
1.21M
    if (!hdr_generate_mask(hpr, sample, sample_len, mask))
145
6.96k
        return 0;
146
147
1.21M
    *first_byte ^= mask[0] & ((*first_byte & 0x80) != 0 ? 0xf : 0x1f);
148
1.21M
    pn_len = (*first_byte & 0x3) + 1;
149
150
5.50M
    for (i = 0; i < pn_len; ++i)
151
4.29M
        pn_bytes[i] ^= mask[i + 1];
152
153
1.21M
    return 1;
154
1.21M
}
155
156
int ossl_quic_hdr_protector_encrypt(QUIC_HDR_PROTECTOR *hpr,
157
    QUIC_PKT_HDR_PTRS *ptrs)
158
2.20M
{
159
2.20M
    return ossl_quic_hdr_protector_encrypt_fields(hpr,
160
2.20M
        ptrs->raw_sample,
161
2.20M
        ptrs->raw_sample_len,
162
2.20M
        ptrs->raw_start,
163
2.20M
        ptrs->raw_pn);
164
2.20M
}
165
166
int ossl_quic_hdr_protector_encrypt_fields(QUIC_HDR_PROTECTOR *hpr,
167
    const unsigned char *sample,
168
    size_t sample_len,
169
    unsigned char *first_byte,
170
    unsigned char *pn_bytes)
171
2.20M
{
172
2.20M
    unsigned char mask[5], pn_len, i;
173
174
2.20M
    if (!hdr_generate_mask(hpr, sample, sample_len, mask))
175
0
        return 0;
176
177
2.20M
    pn_len = (*first_byte & 0x3) + 1;
178
11.0M
    for (i = 0; i < pn_len; ++i)
179
8.81M
        pn_bytes[i] ^= mask[i + 1];
180
181
2.20M
    *first_byte ^= mask[0] & ((*first_byte & 0x80) != 0 ? 0xf : 0x1f);
182
2.20M
    return 1;
183
2.20M
}
184
185
int ossl_quic_wire_decode_pkt_hdr(PACKET *pkt,
186
    size_t short_conn_id_len,
187
    int partial,
188
    int nodata,
189
    QUIC_PKT_HDR *hdr,
190
    QUIC_PKT_HDR_PTRS *ptrs,
191
    uint64_t *fail_cause)
192
3.53M
{
193
3.53M
    unsigned int b0;
194
3.53M
    unsigned char *pn = NULL;
195
3.53M
    size_t l = PACKET_remaining(pkt);
196
197
3.53M
    if (fail_cause != NULL)
198
0
        *fail_cause = QUIC_PKT_HDR_DECODE_DECODE_ERR;
199
200
3.53M
    if (ptrs != NULL) {
201
2.88M
        ptrs->raw_start = (unsigned char *)PACKET_data(pkt);
202
2.88M
        ptrs->raw_sample = NULL;
203
2.88M
        ptrs->raw_sample_len = 0;
204
2.88M
        ptrs->raw_pn = NULL;
205
2.88M
    }
206
207
3.53M
    if (l < QUIC_MIN_VALID_PKT_LEN
208
3.53M
        || !PACKET_get_1(pkt, &b0))
209
0
        return 0;
210
211
3.53M
    hdr->partial = partial;
212
3.53M
    hdr->unused = 0;
213
3.53M
    hdr->reserved = 0;
214
215
3.53M
    if ((b0 & 0x80) == 0) {
216
        /* Short header. */
217
248k
        if (short_conn_id_len > QUIC_MAX_CONN_ID_LEN)
218
0
            return 0;
219
220
248k
        if ((b0 & 0x40) == 0 /* fixed bit not set? */
221
146k
            || l < QUIC_MIN_VALID_PKT_LEN_CRYPTO)
222
118k
            return 0;
223
224
130k
        hdr->type = QUIC_PKT_TYPE_1RTT;
225
130k
        hdr->fixed = 1;
226
130k
        hdr->spin_bit = (b0 & 0x20) != 0;
227
130k
        if (partial) {
228
71.7k
            hdr->key_phase = 0; /* protected, zero for now */
229
71.7k
            hdr->pn_len = 0; /* protected, zero for now */
230
71.7k
            hdr->reserved = 0; /* protected, zero for now */
231
71.7k
        } else {
232
59.1k
            hdr->key_phase = (b0 & 0x04) != 0;
233
59.1k
            hdr->pn_len = (b0 & 0x03) + 1;
234
59.1k
            hdr->reserved = (b0 & 0x18) >> 3;
235
59.1k
        }
236
237
        /* Copy destination connection ID field to header structure. */
238
130k
        if (!PACKET_copy_bytes(pkt, hdr->dst_conn_id.id, short_conn_id_len))
239
0
            return 0;
240
241
130k
        hdr->dst_conn_id.id_len = (unsigned char)short_conn_id_len;
242
243
        /*
244
         * Skip over the PN. If this is a partial decode, the PN length field
245
         * currently has header protection applied. Thus we do not know the
246
         * length of the PN but we are allowed to assume it is 4 bytes long at
247
         * this stage.
248
         */
249
130k
        memset(hdr->pn, 0, sizeof(hdr->pn));
250
130k
        pn = (unsigned char *)PACKET_data(pkt);
251
130k
        if (partial) {
252
71.7k
            if (!PACKET_forward(pkt, sizeof(hdr->pn)))
253
0
                return 0;
254
71.7k
        } else {
255
59.1k
            if (!PACKET_copy_bytes(pkt, hdr->pn, hdr->pn_len))
256
0
                return 0;
257
59.1k
        }
258
259
        /* Fields not used in short-header packets. */
260
130k
        hdr->version = 0;
261
130k
        hdr->src_conn_id.id_len = 0;
262
130k
        hdr->token = NULL;
263
130k
        hdr->token_len = 0;
264
265
        /*
266
         * Short-header packets always come last in a datagram, the length
267
         * is the remainder of the buffer.
268
         */
269
130k
        hdr->len = PACKET_remaining(pkt);
270
130k
        hdr->data = PACKET_data(pkt);
271
272
        /*
273
         * Skip over payload. Since this is a short header packet, which cannot
274
         * be followed by any other kind of packet, this advances us to the end
275
         * of the datagram.
276
         */
277
130k
        if (!PACKET_forward(pkt, hdr->len))
278
0
            return 0;
279
3.28M
    } else {
280
        /* Long header. */
281
3.28M
        unsigned long version;
282
3.28M
        unsigned int dst_conn_id_len, src_conn_id_len, raw_type;
283
284
3.28M
        if (!PACKET_get_net_4(pkt, &version))
285
0
            return 0;
286
287
        /*
288
         * All QUIC packets must have the fixed bit set, except exceptionally
289
         * for Version Negotiation packets.
290
         */
291
3.28M
        if (version != 0 && (b0 & 0x40) == 0)
292
9.92k
            return 0;
293
294
3.27M
        if (!PACKET_get_1(pkt, &dst_conn_id_len)
295
3.27M
            || dst_conn_id_len > QUIC_MAX_CONN_ID_LEN
296
3.26M
            || !PACKET_copy_bytes(pkt, hdr->dst_conn_id.id, dst_conn_id_len)
297
3.24M
            || !PACKET_get_1(pkt, &src_conn_id_len)
298
3.24M
            || src_conn_id_len > QUIC_MAX_CONN_ID_LEN
299
3.21M
            || !PACKET_copy_bytes(pkt, hdr->src_conn_id.id, src_conn_id_len))
300
68.0k
            return 0;
301
302
3.20M
        hdr->version = (uint32_t)version;
303
3.20M
        hdr->dst_conn_id.id_len = (unsigned char)dst_conn_id_len;
304
3.20M
        hdr->src_conn_id.id_len = (unsigned char)src_conn_id_len;
305
306
3.20M
        if (version == 0) {
307
            /*
308
             * Version negotiation packet. Version negotiation packets are
309
             * identified by a version field of 0 and the type bits in the first
310
             * byte are ignored (they may take any value, and we ignore them).
311
             */
312
371k
            hdr->type = QUIC_PKT_TYPE_VERSION_NEG;
313
371k
            hdr->fixed = (b0 & 0x40) != 0;
314
315
371k
            hdr->data = PACKET_data(pkt);
316
371k
            hdr->len = PACKET_remaining(pkt);
317
318
            /*
319
             * Version negotiation packets must contain an array of u32s, so it
320
             * is invalid for their payload length to not be divisible by 4.
321
             */
322
371k
            if ((hdr->len % 4) != 0)
323
7.71k
                return 0;
324
325
            /* Version negotiation packets are always fully decoded. */
326
363k
            hdr->partial = 0;
327
328
            /* Fields not used in version negotiation packets. */
329
363k
            hdr->pn_len = 0;
330
363k
            hdr->spin_bit = 0;
331
363k
            hdr->key_phase = 0;
332
363k
            hdr->token = NULL;
333
363k
            hdr->token_len = 0;
334
363k
            memset(hdr->pn, 0, sizeof(hdr->pn));
335
336
363k
            if (!PACKET_forward(pkt, hdr->len))
337
0
                return 0;
338
2.83M
        } else if (version != QUIC_VERSION_1) {
339
87.9k
            if (fail_cause != NULL)
340
0
                *fail_cause |= QUIC_PKT_HDR_DECODE_BAD_VERSION;
341
            /* Unknown version, do not decode. */
342
87.9k
            return 0;
343
2.74M
        } else {
344
2.74M
            if (l < QUIC_MIN_VALID_PKT_LEN_CRYPTO)
345
2.58k
                return 0;
346
347
            /* Get long packet type and decode to QUIC_PKT_TYPE_*. */
348
2.74M
            raw_type = ((b0 >> 4) & 0x3);
349
350
2.74M
            switch (raw_type) {
351
1.19M
            case 0:
352
1.19M
                hdr->type = QUIC_PKT_TYPE_INITIAL;
353
1.19M
                break;
354
708
            case 1:
355
708
                hdr->type = QUIC_PKT_TYPE_0RTT;
356
708
                break;
357
138k
            case 2:
358
138k
                hdr->type = QUIC_PKT_TYPE_HANDSHAKE;
359
138k
                break;
360
1.40M
            case 3:
361
1.40M
                hdr->type = QUIC_PKT_TYPE_RETRY;
362
1.40M
                break;
363
2.74M
            }
364
365
2.74M
            hdr->pn_len = 0;
366
2.74M
            hdr->fixed = 1;
367
368
            /* Fields not used in long-header packets. */
369
2.74M
            hdr->spin_bit = 0;
370
2.74M
            hdr->key_phase = 0;
371
372
2.74M
            if (hdr->type == QUIC_PKT_TYPE_INITIAL) {
373
                /* Initial packet. */
374
1.19M
                uint64_t token_len;
375
376
1.19M
                if (!PACKET_get_quic_vlint(pkt, &token_len)
377
1.19M
                    || token_len > SIZE_MAX
378
1.19M
                    || !PACKET_get_bytes(pkt, &hdr->token, (size_t)token_len))
379
4.55k
                    return 0;
380
381
1.18M
                hdr->token_len = (size_t)token_len;
382
1.18M
                if (token_len == 0)
383
1.18M
                    hdr->token = NULL;
384
1.54M
            } else {
385
1.54M
                hdr->token = NULL;
386
1.54M
                hdr->token_len = 0;
387
1.54M
            }
388
389
2.73M
            if (hdr->type == QUIC_PKT_TYPE_RETRY) {
390
                /* Retry packet. */
391
1.40M
                hdr->data = PACKET_data(pkt);
392
1.40M
                hdr->len = PACKET_remaining(pkt);
393
394
                /* Retry packets are always fully decoded. */
395
1.40M
                hdr->partial = 0;
396
397
                /* Unused bits in Retry header. */
398
1.40M
                hdr->unused = b0 & 0x0f;
399
400
                /* Fields not used in Retry packets. */
401
1.40M
                memset(hdr->pn, 0, sizeof(hdr->pn));
402
403
1.40M
                if (!PACKET_forward(pkt, hdr->len))
404
0
                    return 0;
405
1.40M
            } else {
406
                /* Initial, 0-RTT or Handshake packet. */
407
1.32M
                uint64_t len;
408
409
1.32M
                hdr->pn_len = partial ? 0 : ((b0 & 0x03) + 1);
410
1.32M
                hdr->reserved = partial ? 0 : ((b0 & 0x0C) >> 2);
411
412
1.32M
                if (!PACKET_get_quic_vlint(pkt, &len)
413
1.32M
                    || len < sizeof(hdr->pn))
414
5.14k
                    return 0;
415
416
1.32M
                if (!nodata && len > PACKET_remaining(pkt))
417
3.46k
                    return 0;
418
419
                /*
420
                 * Skip over the PN. If this is a partial decode, the PN length
421
                 * field currently has header protection applied. Thus we do not
422
                 * know the length of the PN but we are allowed to assume it is
423
                 * 4 bytes long at this stage.
424
                 */
425
1.31M
                pn = (unsigned char *)PACKET_data(pkt);
426
1.31M
                memset(hdr->pn, 0, sizeof(hdr->pn));
427
1.31M
                if (partial) {
428
721k
                    if (!PACKET_forward(pkt, sizeof(hdr->pn)))
429
0
                        return 0;
430
431
721k
                    hdr->len = (size_t)(len - sizeof(hdr->pn));
432
721k
                } else {
433
597k
                    if (!PACKET_copy_bytes(pkt, hdr->pn, hdr->pn_len))
434
0
                        return 0;
435
436
597k
                    hdr->len = (size_t)(len - hdr->pn_len);
437
597k
                }
438
439
1.31M
                if (nodata) {
440
0
                    hdr->data = NULL;
441
1.31M
                } else {
442
1.31M
                    hdr->data = PACKET_data(pkt);
443
444
                    /* Skip over packet body. */
445
1.31M
                    if (!PACKET_forward(pkt, hdr->len))
446
0
                        return 0;
447
1.31M
                }
448
1.31M
            }
449
2.73M
        }
450
3.20M
    }
451
452
3.22M
    if (ptrs != NULL) {
453
2.58M
        ptrs->raw_pn = pn;
454
2.58M
        if (pn != NULL) {
455
806k
            ptrs->raw_sample = pn + 4;
456
806k
            ptrs->raw_sample_len = PACKET_end(pkt) - ptrs->raw_sample;
457
806k
        }
458
2.58M
    }
459
460
    /*
461
     * Good decode, clear the generic DECODE_ERR flag
462
     */
463
3.22M
    if (fail_cause != NULL)
464
0
        *fail_cause &= ~QUIC_PKT_HDR_DECODE_DECODE_ERR;
465
466
3.22M
    return 1;
467
3.53M
}
468
469
int ossl_quic_wire_encode_pkt_hdr(WPACKET *pkt,
470
    size_t short_conn_id_len,
471
    const QUIC_PKT_HDR *hdr,
472
    QUIC_PKT_HDR_PTRS *ptrs)
473
1.55M
{
474
1.55M
    unsigned char b0;
475
1.55M
    size_t off_start, off_sample, off_pn;
476
1.55M
    unsigned char *start = WPACKET_get_curr(pkt);
477
478
1.55M
    if (!WPACKET_get_total_written(pkt, &off_start))
479
0
        return 0;
480
481
1.55M
    if (ptrs != NULL) {
482
        /* ptrs would not be stable on non-static WPACKET */
483
1.20M
        if (!ossl_assert(pkt->staticbuf != NULL))
484
0
            return 0;
485
1.20M
        ptrs->raw_start = NULL;
486
1.20M
        ptrs->raw_sample = NULL;
487
1.20M
        ptrs->raw_sample_len = 0;
488
1.20M
        ptrs->raw_pn = 0;
489
1.20M
    }
490
491
    /* Cannot serialize a partial header, or one whose DCID length is wrong. */
492
1.55M
    if (hdr->partial
493
1.55M
        || (hdr->type == QUIC_PKT_TYPE_1RTT
494
243k
            && hdr->dst_conn_id.id_len != short_conn_id_len))
495
0
        return 0;
496
497
1.55M
    if (hdr->type == QUIC_PKT_TYPE_1RTT) {
498
        /* Short header. */
499
500
        /*
501
         * Cannot serialize a header whose DCID length is wrong, or with an
502
         * invalid PN length.
503
         */
504
243k
        if (hdr->dst_conn_id.id_len != short_conn_id_len
505
243k
            || short_conn_id_len > QUIC_MAX_CONN_ID_LEN
506
243k
            || hdr->pn_len < 1 || hdr->pn_len > 4)
507
0
            return 0;
508
509
243k
        b0 = (hdr->spin_bit << 5)
510
243k
            | (hdr->key_phase << 2)
511
243k
            | (hdr->pn_len - 1)
512
243k
            | (hdr->reserved << 3)
513
243k
            | 0x40; /* fixed bit */
514
515
243k
        if (!WPACKET_put_bytes_u8(pkt, b0)
516
243k
            || !WPACKET_memcpy(pkt, hdr->dst_conn_id.id, short_conn_id_len)
517
243k
            || !WPACKET_get_total_written(pkt, &off_pn)
518
243k
            || !WPACKET_memcpy(pkt, hdr->pn, hdr->pn_len))
519
0
            return 0;
520
1.31M
    } else {
521
        /* Long header. */
522
1.31M
        unsigned int raw_type;
523
524
1.31M
        if (hdr->dst_conn_id.id_len > QUIC_MAX_CONN_ID_LEN
525
1.31M
            || hdr->src_conn_id.id_len > QUIC_MAX_CONN_ID_LEN)
526
0
            return 0;
527
528
1.31M
        if (ossl_quic_pkt_type_has_pn(hdr->type)
529
962k
            && (hdr->pn_len < 1 || hdr->pn_len > 4))
530
0
            return 0;
531
532
1.31M
        switch (hdr->type) {
533
0
        case QUIC_PKT_TYPE_VERSION_NEG:
534
0
            if (hdr->version != 0)
535
0
                return 0;
536
537
            /* Version negotiation packets use zero for the type bits */
538
0
            raw_type = 0;
539
0
            break;
540
541
813k
        case QUIC_PKT_TYPE_INITIAL:
542
813k
            raw_type = 0;
543
813k
            break;
544
0
        case QUIC_PKT_TYPE_0RTT:
545
0
            raw_type = 1;
546
0
            break;
547
149k
        case QUIC_PKT_TYPE_HANDSHAKE:
548
149k
            raw_type = 2;
549
149k
            break;
550
348k
        case QUIC_PKT_TYPE_RETRY:
551
348k
            raw_type = 3;
552
348k
            break;
553
0
        default:
554
0
            return 0;
555
1.31M
        }
556
557
1.31M
        b0 = (raw_type << 4) | 0x80; /* long */
558
1.31M
        if (hdr->type != QUIC_PKT_TYPE_VERSION_NEG || hdr->fixed)
559
1.31M
            b0 |= 0x40; /* fixed */
560
1.31M
        if (ossl_quic_pkt_type_has_pn(hdr->type)) {
561
962k
            b0 |= hdr->pn_len - 1;
562
962k
            b0 |= (hdr->reserved << 2);
563
962k
        }
564
1.31M
        if (hdr->type == QUIC_PKT_TYPE_RETRY)
565
348k
            b0 |= hdr->unused;
566
567
1.31M
        if (!WPACKET_put_bytes_u8(pkt, b0)
568
1.31M
            || !WPACKET_put_bytes_u32(pkt, hdr->version)
569
1.31M
            || !WPACKET_put_bytes_u8(pkt, hdr->dst_conn_id.id_len)
570
1.31M
            || !WPACKET_memcpy(pkt, hdr->dst_conn_id.id,
571
1.31M
                hdr->dst_conn_id.id_len)
572
1.31M
            || !WPACKET_put_bytes_u8(pkt, hdr->src_conn_id.id_len)
573
1.31M
            || !WPACKET_memcpy(pkt, hdr->src_conn_id.id,
574
1.31M
                hdr->src_conn_id.id_len))
575
0
            return 0;
576
577
1.31M
        if (hdr->type == QUIC_PKT_TYPE_VERSION_NEG) {
578
0
            if (hdr->len > 0 && !WPACKET_reserve_bytes(pkt, hdr->len, NULL))
579
0
                return 0;
580
581
0
            return 1;
582
0
        }
583
584
1.31M
        if (hdr->type == QUIC_PKT_TYPE_INITIAL) {
585
813k
            if (!WPACKET_quic_write_vlint(pkt, hdr->token_len)
586
813k
                || !WPACKET_memcpy(pkt, hdr->token, hdr->token_len))
587
0
                return 0;
588
813k
        }
589
590
1.31M
        if (hdr->type == QUIC_PKT_TYPE_RETRY) {
591
348k
            if (!WPACKET_memcpy(pkt, hdr->token, hdr->token_len))
592
0
                return 0;
593
348k
            return 1;
594
348k
        }
595
596
962k
        if (!WPACKET_quic_write_vlint(pkt, hdr->len + hdr->pn_len)
597
962k
            || !WPACKET_get_total_written(pkt, &off_pn)
598
962k
            || !WPACKET_memcpy(pkt, hdr->pn, hdr->pn_len))
599
0
            return 0;
600
962k
    }
601
602
1.20M
    if (hdr->len > 0 && !WPACKET_reserve_bytes(pkt, hdr->len, NULL))
603
0
        return 0;
604
605
1.20M
    off_sample = off_pn + 4;
606
607
1.20M
    if (ptrs != NULL) {
608
1.20M
        ptrs->raw_start = start;
609
1.20M
        ptrs->raw_sample = start + (off_sample - off_start);
610
1.20M
        ptrs->raw_sample_len
611
1.20M
            = WPACKET_get_curr(pkt) + hdr->len - ptrs->raw_sample;
612
1.20M
        ptrs->raw_pn = start + (off_pn - off_start);
613
1.20M
    }
614
615
1.20M
    return 1;
616
1.20M
}
617
618
size_t ossl_quic_wire_get_encoded_pkt_hdr_len(size_t short_conn_id_len,
619
    const QUIC_PKT_HDR *hdr)
620
56.2M
{
621
56.2M
    size_t len = 0, enclen;
622
623
    /* Cannot serialize a partial header, or one whose DCID length is wrong. */
624
56.2M
    if (hdr->partial
625
56.2M
        || (hdr->type == QUIC_PKT_TYPE_1RTT
626
13.2M
            && hdr->dst_conn_id.id_len != short_conn_id_len))
627
0
        return 0;
628
629
56.2M
    if (hdr->type == QUIC_PKT_TYPE_1RTT) {
630
        /* Short header. */
631
632
        /*
633
         * Cannot serialize a header whose DCID length is wrong, or with an
634
         * invalid PN length.
635
         */
636
13.2M
        if (hdr->dst_conn_id.id_len != short_conn_id_len
637
13.2M
            || short_conn_id_len > QUIC_MAX_CONN_ID_LEN
638
13.2M
            || hdr->pn_len < 1 || hdr->pn_len > 4)
639
0
            return 0;
640
641
13.2M
        return 1 + short_conn_id_len + hdr->pn_len;
642
42.9M
    } else {
643
        /* Long header. */
644
42.9M
        if (hdr->dst_conn_id.id_len > QUIC_MAX_CONN_ID_LEN
645
42.9M
            || hdr->src_conn_id.id_len > QUIC_MAX_CONN_ID_LEN)
646
0
            return 0;
647
648
42.9M
        len += 1 /* Initial byte */ + 4 /* Version */
649
42.9M
            + 1 + hdr->dst_conn_id.id_len /* DCID Len, DCID */
650
42.9M
            + 1 + hdr->src_conn_id.id_len /* SCID Len, SCID */
651
42.9M
            ;
652
653
42.9M
        if (ossl_quic_pkt_type_has_pn(hdr->type)) {
654
42.9M
            if (hdr->pn_len < 1 || hdr->pn_len > 4)
655
0
                return 0;
656
657
42.9M
            len += hdr->pn_len;
658
42.9M
        }
659
660
42.9M
        if (hdr->type == QUIC_PKT_TYPE_INITIAL) {
661
40.1M
            enclen = ossl_quic_vlint_encode_len(hdr->token_len);
662
40.1M
            if (!enclen)
663
0
                return 0;
664
665
40.1M
            len += enclen + hdr->token_len;
666
40.1M
        }
667
668
42.9M
        if (!ossl_quic_pkt_type_must_be_last(hdr->type)) {
669
42.9M
            enclen = ossl_quic_vlint_encode_len(hdr->len + hdr->pn_len);
670
42.9M
            if (!enclen)
671
0
                return 0;
672
673
42.9M
            len += enclen;
674
42.9M
        }
675
676
42.9M
        return len;
677
42.9M
    }
678
56.2M
}
679
680
int ossl_quic_wire_get_pkt_hdr_dst_conn_id(const unsigned char *buf,
681
    size_t buf_len,
682
    size_t short_conn_id_len,
683
    QUIC_CONN_ID *dst_conn_id)
684
11.6M
{
685
11.6M
    unsigned char b0;
686
11.6M
    size_t blen;
687
688
11.6M
    if (buf_len < QUIC_MIN_VALID_PKT_LEN
689
5.47M
        || short_conn_id_len > QUIC_MAX_CONN_ID_LEN)
690
6.18M
        return 0;
691
692
5.47M
    b0 = buf[0];
693
5.47M
    if ((b0 & 0x80) != 0) {
694
        /*
695
         * Long header. We need 6 bytes (initial byte, 4 version bytes, DCID
696
         * length byte to begin with). This is covered by the buf_len test
697
         * above.
698
         */
699
700
        /*
701
         * If the version field is non-zero (meaning that this is not a Version
702
         * Negotiation packet), the fixed bit must be set.
703
         */
704
4.93M
        if ((buf[1] || buf[2] || buf[3] || buf[4]) && (b0 & 0x40) == 0)
705
8.51k
            return 0;
706
707
4.92M
        blen = (size_t)buf[5]; /* DCID Length */
708
4.92M
        if (blen > QUIC_MAX_CONN_ID_LEN
709
4.36M
            || buf_len < QUIC_MIN_VALID_PKT_LEN + blen)
710
564k
            return 0;
711
712
4.35M
        dst_conn_id->id_len = (unsigned char)blen;
713
4.35M
        memcpy(dst_conn_id->id, buf + 6, blen);
714
4.35M
        return 1;
715
4.92M
    } else {
716
        /* Short header. */
717
543k
        if ((b0 & 0x40) == 0)
718
            /* Fixed bit not set, not a valid QUIC packet header. */
719
439k
            return 0;
720
721
103k
        if (buf_len < QUIC_MIN_VALID_PKT_LEN_CRYPTO + short_conn_id_len)
722
1.03k
            return 0;
723
724
102k
        dst_conn_id->id_len = (unsigned char)short_conn_id_len;
725
102k
        memcpy(dst_conn_id->id, buf + 1, short_conn_id_len);
726
102k
        return 1;
727
103k
    }
728
5.47M
}
729
730
int ossl_quic_wire_decode_pkt_hdr_pn(const unsigned char *enc_pn,
731
    size_t enc_pn_len,
732
    QUIC_PN largest_pn,
733
    QUIC_PN *res_pn)
734
1.21M
{
735
1.21M
    int64_t expected_pn, truncated_pn, candidate_pn, pn_win, pn_hwin, pn_mask;
736
737
1.21M
    switch (enc_pn_len) {
738
44.3k
    case 1:
739
44.3k
        truncated_pn = enc_pn[0];
740
44.3k
        break;
741
2.79k
    case 2:
742
2.79k
        truncated_pn = ((QUIC_PN)enc_pn[0] << 8)
743
2.79k
            | (QUIC_PN)enc_pn[1];
744
2.79k
        break;
745
403k
    case 3:
746
403k
        truncated_pn = ((QUIC_PN)enc_pn[0] << 16)
747
403k
            | ((QUIC_PN)enc_pn[1] << 8)
748
403k
            | (QUIC_PN)enc_pn[2];
749
403k
        break;
750
759k
    case 4:
751
759k
        truncated_pn = ((QUIC_PN)enc_pn[0] << 24)
752
759k
            | ((QUIC_PN)enc_pn[1] << 16)
753
759k
            | ((QUIC_PN)enc_pn[2] << 8)
754
759k
            | (QUIC_PN)enc_pn[3];
755
759k
        break;
756
0
    default:
757
0
        return 0;
758
1.21M
    }
759
760
    /* Implemented as per RFC 9000 Section A.3. */
761
1.21M
    expected_pn = largest_pn + 1;
762
1.21M
    pn_win = ((int64_t)1) << (enc_pn_len * 8);
763
1.21M
    pn_hwin = pn_win / 2;
764
1.21M
    pn_mask = pn_win - 1;
765
1.21M
    candidate_pn = (expected_pn & ~pn_mask) | truncated_pn;
766
1.21M
    if (candidate_pn <= expected_pn - pn_hwin
767
171k
        && candidate_pn < (((int64_t)1) << 62) - pn_win)
768
171k
        *res_pn = candidate_pn + pn_win;
769
1.03M
    else if (candidate_pn > expected_pn + pn_hwin
770
79.5k
        && candidate_pn >= pn_win)
771
69.0k
        *res_pn = candidate_pn - pn_win;
772
969k
    else
773
969k
        *res_pn = candidate_pn;
774
1.21M
    return 1;
775
1.21M
}
776
777
/* From RFC 9000 Section A.2. Simplified implementation. */
778
int ossl_quic_wire_determine_pn_len(QUIC_PN pn,
779
    QUIC_PN largest_acked)
780
0
{
781
0
    uint64_t num_unacked
782
0
        = (largest_acked == QUIC_PN_INVALID) ? pn + 1 : pn - largest_acked;
783
784
    /*
785
     * num_unacked \in [    0, 2** 7] -> 1 byte
786
     * num_unacked \in (2** 7, 2**15] -> 2 bytes
787
     * num_unacked \in (2**15, 2**23] -> 3 bytes
788
     * num_unacked \in (2**23,      ] -> 4 bytes
789
     */
790
791
0
    if (num_unacked <= (1U << 7))
792
0
        return 1;
793
0
    if (num_unacked <= (1U << 15))
794
0
        return 2;
795
0
    if (num_unacked <= (1U << 23))
796
0
        return 3;
797
0
    return 4;
798
0
}
799
800
int ossl_quic_wire_encode_pkt_hdr_pn(QUIC_PN pn,
801
    unsigned char *enc_pn,
802
    size_t enc_pn_len)
803
2.20M
{
804
2.20M
    switch (enc_pn_len) {
805
0
    case 1:
806
0
        enc_pn[0] = (unsigned char)pn;
807
0
        break;
808
0
    case 2:
809
0
        enc_pn[1] = (unsigned char)pn;
810
0
        enc_pn[0] = (unsigned char)(pn >> 8);
811
0
        break;
812
0
    case 3:
813
0
        enc_pn[2] = (unsigned char)pn;
814
0
        enc_pn[1] = (unsigned char)(pn >> 8);
815
0
        enc_pn[0] = (unsigned char)(pn >> 16);
816
0
        break;
817
2.20M
    case 4:
818
2.20M
        enc_pn[3] = (unsigned char)pn;
819
2.20M
        enc_pn[2] = (unsigned char)(pn >> 8);
820
2.20M
        enc_pn[1] = (unsigned char)(pn >> 16);
821
2.20M
        enc_pn[0] = (unsigned char)(pn >> 24);
822
2.20M
        break;
823
0
    default:
824
0
        return 0;
825
2.20M
    }
826
827
2.20M
    return 1;
828
2.20M
}
829
830
int ossl_quic_validate_retry_integrity_tag(OSSL_LIB_CTX *libctx,
831
    const char *propq,
832
    const QUIC_PKT_HDR *hdr,
833
    const QUIC_CONN_ID *client_initial_dcid)
834
515k
{
835
515k
    unsigned char expected_tag[QUIC_RETRY_INTEGRITY_TAG_LEN];
836
515k
    const unsigned char *actual_tag;
837
838
515k
    if (hdr == NULL || hdr->len < QUIC_RETRY_INTEGRITY_TAG_LEN)
839
0
        return 0;
840
841
515k
    if (!ossl_quic_calculate_retry_integrity_tag(libctx, propq,
842
515k
            hdr, client_initial_dcid,
843
515k
            expected_tag))
844
0
        return 0;
845
846
515k
    actual_tag = hdr->data + hdr->len - QUIC_RETRY_INTEGRITY_TAG_LEN;
847
848
515k
    return !CRYPTO_memcmp(expected_tag, actual_tag,
849
515k
        QUIC_RETRY_INTEGRITY_TAG_LEN);
850
515k
}
851
852
/* RFC 9001 s. 5.8 */
853
static const unsigned char retry_integrity_key[] = {
854
    0xbe, 0x0c, 0x69, 0x0b, 0x9f, 0x66, 0x57, 0x5a,
855
    0x1d, 0x76, 0x6b, 0x54, 0xe3, 0x68, 0xc8, 0x4e
856
};
857
858
static const unsigned char retry_integrity_nonce[] = {
859
    0x46, 0x15, 0x99, 0xd3, 0x5d, 0x63, 0x2b, 0xf2,
860
    0x23, 0x98, 0x25, 0xbb
861
};
862
863
int ossl_quic_calculate_retry_integrity_tag(OSSL_LIB_CTX *libctx,
864
    const char *propq,
865
    const QUIC_PKT_HDR *hdr,
866
    const QUIC_CONN_ID *client_initial_dcid,
867
    unsigned char *tag)
868
515k
{
869
515k
    EVP_CIPHER *cipher = NULL;
870
515k
    EVP_CIPHER_CTX *cctx = NULL;
871
515k
    int ok = 0, l = 0, l2 = 0, wpkt_valid = 0;
872
515k
    WPACKET wpkt;
873
    /* Worst case length of the Retry Psuedo-Packet header is 68 bytes. */
874
515k
    unsigned char buf[128];
875
515k
    QUIC_PKT_HDR hdr2;
876
515k
    size_t hdr_enc_len = 0;
877
878
515k
    if (hdr->type != QUIC_PKT_TYPE_RETRY || hdr->version == 0
879
515k
        || hdr->len < QUIC_RETRY_INTEGRITY_TAG_LEN
880
515k
        || hdr->data == NULL
881
515k
        || client_initial_dcid == NULL || tag == NULL
882
515k
        || client_initial_dcid->id_len > QUIC_MAX_CONN_ID_LEN) {
883
0
        ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT);
884
0
        goto err;
885
0
    }
886
887
    /*
888
     * Do not reserve packet body in WPACKET. Retry packet header
889
     * does not contain a Length field so this does not affect
890
     * the serialized packet header.
891
     */
892
515k
    hdr2 = *hdr;
893
515k
    hdr2.len = 0;
894
895
    /* Assemble retry psuedo-packet. */
896
515k
    if (!WPACKET_init_static_len(&wpkt, buf, sizeof(buf), 0)) {
897
0
        ERR_raise(ERR_LIB_SSL, ERR_R_CRYPTO_LIB);
898
0
        goto err;
899
0
    }
900
901
515k
    wpkt_valid = 1;
902
903
    /* Prepend original DCID to the packet. */
904
515k
    if (!WPACKET_put_bytes_u8(&wpkt, client_initial_dcid->id_len)
905
515k
        || !WPACKET_memcpy(&wpkt, client_initial_dcid->id,
906
515k
            client_initial_dcid->id_len)) {
907
0
        ERR_raise(ERR_LIB_SSL, ERR_R_CRYPTO_LIB);
908
0
        goto err;
909
0
    }
910
911
    /* Encode main retry header. */
912
515k
    if (!ossl_quic_wire_encode_pkt_hdr(&wpkt, hdr2.dst_conn_id.id_len,
913
515k
            &hdr2, NULL))
914
0
        goto err;
915
916
515k
    if (!WPACKET_get_total_written(&wpkt, &hdr_enc_len)) {
917
0
        ERR_raise(ERR_LIB_SSL, ERR_R_CRYPTO_LIB);
918
0
        goto err;
919
0
    }
920
921
    /* Create and initialise cipher context. */
922
    /* TODO(QUIC FUTURE): Cipher fetch caching. */
923
515k
    if ((cipher = EVP_CIPHER_fetch(libctx, "AES-128-GCM", propq)) == NULL) {
924
0
        ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
925
0
        goto err;
926
0
    }
927
928
515k
    if ((cctx = EVP_CIPHER_CTX_new()) == NULL) {
929
0
        ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
930
0
        goto err;
931
0
    }
932
933
515k
    if (!EVP_CipherInit_ex(cctx, cipher, NULL,
934
515k
            retry_integrity_key, retry_integrity_nonce, /*enc=*/1)) {
935
0
        ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
936
0
        goto err;
937
0
    }
938
939
    /* Feed packet header as AAD data. */
940
515k
    if (EVP_CipherUpdate(cctx, NULL, &l, buf, (int)hdr_enc_len) != 1) {
941
0
        ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
942
0
        goto err;
943
0
    }
944
945
    /* Feed packet body as AAD data. */
946
515k
    if (EVP_CipherUpdate(cctx, NULL, &l, hdr->data,
947
515k
            (int)(hdr->len - QUIC_RETRY_INTEGRITY_TAG_LEN))
948
515k
        != 1) {
949
0
        ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
950
0
        goto err;
951
0
    }
952
953
    /* Finalise and get tag. */
954
515k
    if (EVP_CipherFinal_ex(cctx, NULL, &l2) != 1) {
955
0
        ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
956
0
        goto err;
957
0
    }
958
959
515k
    if (EVP_CIPHER_CTX_ctrl(cctx, EVP_CTRL_AEAD_GET_TAG,
960
515k
            QUIC_RETRY_INTEGRITY_TAG_LEN,
961
515k
            tag)
962
515k
        != 1) {
963
0
        ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
964
0
        goto err;
965
0
    }
966
967
515k
    ok = 1;
968
515k
err:
969
515k
    EVP_CIPHER_free(cipher);
970
515k
    EVP_CIPHER_CTX_free(cctx);
971
515k
    if (wpkt_valid)
972
515k
        WPACKET_finish(&wpkt);
973
974
515k
    return ok;
975
515k
}