Coverage Report

Created: 2025-12-04 06:33

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