Home | History | Annotate | Line # | Download | only in quic
      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 {
     21     const char *cipher_name = NULL;
     22 
     23     switch (cipher_id) {
     24     case QUIC_HDR_PROT_CIPHER_AES_128:
     25         cipher_name = "AES-128-ECB";
     26         break;
     27     case QUIC_HDR_PROT_CIPHER_AES_256:
     28         cipher_name = "AES-256-ECB";
     29         break;
     30     case QUIC_HDR_PROT_CIPHER_CHACHA:
     31         cipher_name = "ChaCha20";
     32         break;
     33     default:
     34         ERR_raise(ERR_LIB_SSL, ERR_R_UNSUPPORTED);
     35         return 0;
     36     }
     37 
     38     hpr->cipher_ctx = EVP_CIPHER_CTX_new();
     39     if (hpr->cipher_ctx == NULL) {
     40         ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
     41         return 0;
     42     }
     43 
     44     hpr->cipher = EVP_CIPHER_fetch(libctx, cipher_name, propq);
     45     if (hpr->cipher == NULL
     46         || quic_hp_key_len != (size_t)EVP_CIPHER_get_key_length(hpr->cipher)) {
     47         ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
     48         goto err;
     49     }
     50 
     51     if (!EVP_CipherInit_ex(hpr->cipher_ctx, hpr->cipher, NULL,
     52             quic_hp_key, NULL, 1)) {
     53         ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
     54         goto err;
     55     }
     56 
     57     hpr->libctx = libctx;
     58     hpr->propq = propq;
     59     hpr->cipher_id = cipher_id;
     60     return 1;
     61 
     62 err:
     63     ossl_quic_hdr_protector_cleanup(hpr);
     64     return 0;
     65 }
     66 
     67 void ossl_quic_hdr_protector_cleanup(QUIC_HDR_PROTECTOR *hpr)
     68 {
     69     EVP_CIPHER_CTX_free(hpr->cipher_ctx);
     70     hpr->cipher_ctx = NULL;
     71 
     72     EVP_CIPHER_free(hpr->cipher);
     73     hpr->cipher = NULL;
     74 }
     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 {
     80     int l = 0;
     81     unsigned char dst[16];
     82     static const unsigned char zeroes[5] = { 0 };
     83     size_t i;
     84 
     85     if (hpr->cipher_id == QUIC_HDR_PROT_CIPHER_AES_128
     86         || hpr->cipher_id == QUIC_HDR_PROT_CIPHER_AES_256) {
     87         if (sample_len < 16) {
     88             ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT);
     89             return 0;
     90         }
     91 
     92         if (!EVP_CipherInit_ex(hpr->cipher_ctx, NULL, NULL, NULL, NULL, 1)
     93             || !EVP_CipherUpdate(hpr->cipher_ctx, dst, &l, sample, 16)) {
     94             ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
     95             return 0;
     96         }
     97 
     98         for (i = 0; i < 5; ++i)
     99             mask[i] = dst[i];
    100     } else if (hpr->cipher_id == QUIC_HDR_PROT_CIPHER_CHACHA) {
    101         if (sample_len < 16) {
    102             ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT);
    103             return 0;
    104         }
    105 
    106         if (!EVP_CipherInit_ex(hpr->cipher_ctx, NULL, NULL, NULL, sample, 1)
    107             || !EVP_CipherUpdate(hpr->cipher_ctx, mask, &l,
    108                 zeroes, sizeof(zeroes))) {
    109             ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
    110             return 0;
    111         }
    112     } else {
    113         ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
    114         assert(0);
    115         return 0;
    116     }
    117 
    118 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
    119     /* No matter what we did above we use the same mask in fuzzing mode */
    120     memset(mask, 0, 5);
    121 #endif
    122 
    123     return 1;
    124 }
    125 
    126 int ossl_quic_hdr_protector_decrypt(QUIC_HDR_PROTECTOR *hpr,
    127     QUIC_PKT_HDR_PTRS *ptrs)
    128 {
    129     return ossl_quic_hdr_protector_decrypt_fields(hpr,
    130         ptrs->raw_sample,
    131         ptrs->raw_sample_len,
    132         ptrs->raw_start,
    133         ptrs->raw_pn);
    134 }
    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 {
    142     unsigned char mask[5], pn_len, i;
    143 
    144     if (!hdr_generate_mask(hpr, sample, sample_len, mask))
    145         return 0;
    146 
    147     *first_byte ^= mask[0] & ((*first_byte & 0x80) != 0 ? 0xf : 0x1f);
    148     pn_len = (*first_byte & 0x3) + 1;
    149 
    150     for (i = 0; i < pn_len; ++i)
    151         pn_bytes[i] ^= mask[i + 1];
    152 
    153     return 1;
    154 }
    155 
    156 int ossl_quic_hdr_protector_encrypt(QUIC_HDR_PROTECTOR *hpr,
    157     QUIC_PKT_HDR_PTRS *ptrs)
    158 {
    159     return ossl_quic_hdr_protector_encrypt_fields(hpr,
    160         ptrs->raw_sample,
    161         ptrs->raw_sample_len,
    162         ptrs->raw_start,
    163         ptrs->raw_pn);
    164 }
    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 {
    172     unsigned char mask[5], pn_len, i;
    173 
    174     if (!hdr_generate_mask(hpr, sample, sample_len, mask))
    175         return 0;
    176 
    177     pn_len = (*first_byte & 0x3) + 1;
    178     for (i = 0; i < pn_len; ++i)
    179         pn_bytes[i] ^= mask[i + 1];
    180 
    181     *first_byte ^= mask[0] & ((*first_byte & 0x80) != 0 ? 0xf : 0x1f);
    182     return 1;
    183 }
    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 {
    193     unsigned int b0;
    194     unsigned char *pn = NULL;
    195     size_t l = PACKET_remaining(pkt);
    196 
    197     if (fail_cause != NULL)
    198         *fail_cause = QUIC_PKT_HDR_DECODE_DECODE_ERR;
    199 
    200     if (ptrs != NULL) {
    201         ptrs->raw_start = (unsigned char *)PACKET_data(pkt);
    202         ptrs->raw_sample = NULL;
    203         ptrs->raw_sample_len = 0;
    204         ptrs->raw_pn = NULL;
    205     }
    206 
    207     if (l < QUIC_MIN_VALID_PKT_LEN
    208         || !PACKET_get_1(pkt, &b0))
    209         return 0;
    210 
    211     hdr->partial = partial;
    212     hdr->unused = 0;
    213     hdr->reserved = 0;
    214 
    215     if ((b0 & 0x80) == 0) {
    216         /* Short header. */
    217         if (short_conn_id_len > QUIC_MAX_CONN_ID_LEN)
    218             return 0;
    219 
    220         if ((b0 & 0x40) == 0 /* fixed bit not set? */
    221             || l < QUIC_MIN_VALID_PKT_LEN_CRYPTO)
    222             return 0;
    223 
    224         hdr->type = QUIC_PKT_TYPE_1RTT;
    225         hdr->fixed = 1;
    226         hdr->spin_bit = (b0 & 0x20) != 0;
    227         if (partial) {
    228             hdr->key_phase = 0; /* protected, zero for now */
    229             hdr->pn_len = 0; /* protected, zero for now */
    230             hdr->reserved = 0; /* protected, zero for now */
    231         } else {
    232             hdr->key_phase = (b0 & 0x04) != 0;
    233             hdr->pn_len = (b0 & 0x03) + 1;
    234             hdr->reserved = (b0 & 0x18) >> 3;
    235         }
    236 
    237         /* Copy destination connection ID field to header structure. */
    238         if (!PACKET_copy_bytes(pkt, hdr->dst_conn_id.id, short_conn_id_len))
    239             return 0;
    240 
    241         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         memset(hdr->pn, 0, sizeof(hdr->pn));
    250         pn = (unsigned char *)PACKET_data(pkt);
    251         if (partial) {
    252             if (!PACKET_forward(pkt, sizeof(hdr->pn)))
    253                 return 0;
    254         } else {
    255             if (!PACKET_copy_bytes(pkt, hdr->pn, hdr->pn_len))
    256                 return 0;
    257         }
    258 
    259         /* Fields not used in short-header packets. */
    260         hdr->version = 0;
    261         hdr->src_conn_id.id_len = 0;
    262         hdr->token = NULL;
    263         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         hdr->len = PACKET_remaining(pkt);
    270         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         if (!PACKET_forward(pkt, hdr->len))
    278             return 0;
    279     } else {
    280         /* Long header. */
    281         unsigned long version;
    282         unsigned int dst_conn_id_len, src_conn_id_len, raw_type;
    283 
    284         if (!PACKET_get_net_4(pkt, &version))
    285             return 0;
    286 
    287         /*
    288          * All QUIC packets must have the fixed bit set, except exceptionally
    289          * for Version Negotiation packets.
    290          */
    291         if (version != 0 && (b0 & 0x40) == 0)
    292             return 0;
    293 
    294         if (!PACKET_get_1(pkt, &dst_conn_id_len)
    295             || dst_conn_id_len > QUIC_MAX_CONN_ID_LEN
    296             || !PACKET_copy_bytes(pkt, hdr->dst_conn_id.id, dst_conn_id_len)
    297             || !PACKET_get_1(pkt, &src_conn_id_len)
    298             || src_conn_id_len > QUIC_MAX_CONN_ID_LEN
    299             || !PACKET_copy_bytes(pkt, hdr->src_conn_id.id, src_conn_id_len))
    300             return 0;
    301 
    302         hdr->version = (uint32_t)version;
    303         hdr->dst_conn_id.id_len = (unsigned char)dst_conn_id_len;
    304         hdr->src_conn_id.id_len = (unsigned char)src_conn_id_len;
    305 
    306         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             hdr->type = QUIC_PKT_TYPE_VERSION_NEG;
    313             hdr->fixed = (b0 & 0x40) != 0;
    314 
    315             hdr->data = PACKET_data(pkt);
    316             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             if ((hdr->len % 4) != 0)
    323                 return 0;
    324 
    325             /* Version negotiation packets are always fully decoded. */
    326             hdr->partial = 0;
    327 
    328             /* Fields not used in version negotiation packets. */
    329             hdr->pn_len = 0;
    330             hdr->spin_bit = 0;
    331             hdr->key_phase = 0;
    332             hdr->token = NULL;
    333             hdr->token_len = 0;
    334             memset(hdr->pn, 0, sizeof(hdr->pn));
    335 
    336             if (!PACKET_forward(pkt, hdr->len))
    337                 return 0;
    338         } else if (version != QUIC_VERSION_1) {
    339             if (fail_cause != NULL)
    340                 *fail_cause |= QUIC_PKT_HDR_DECODE_BAD_VERSION;
    341             /* Unknown version, do not decode. */
    342             return 0;
    343         } else {
    344             if (l < QUIC_MIN_VALID_PKT_LEN_CRYPTO)
    345                 return 0;
    346 
    347             /* Get long packet type and decode to QUIC_PKT_TYPE_*. */
    348             raw_type = ((b0 >> 4) & 0x3);
    349 
    350             switch (raw_type) {
    351             case 0:
    352                 hdr->type = QUIC_PKT_TYPE_INITIAL;
    353                 break;
    354             case 1:
    355                 hdr->type = QUIC_PKT_TYPE_0RTT;
    356                 break;
    357             case 2:
    358                 hdr->type = QUIC_PKT_TYPE_HANDSHAKE;
    359                 break;
    360             case 3:
    361                 hdr->type = QUIC_PKT_TYPE_RETRY;
    362                 break;
    363             }
    364 
    365             hdr->pn_len = 0;
    366             hdr->fixed = 1;
    367 
    368             /* Fields not used in long-header packets. */
    369             hdr->spin_bit = 0;
    370             hdr->key_phase = 0;
    371 
    372             if (hdr->type == QUIC_PKT_TYPE_INITIAL) {
    373                 /* Initial packet. */
    374                 uint64_t token_len;
    375 
    376                 if (!PACKET_get_quic_vlint(pkt, &token_len)
    377                     || token_len > SIZE_MAX
    378                     || !PACKET_get_bytes(pkt, &hdr->token, (size_t)token_len))
    379                     return 0;
    380 
    381                 hdr->token_len = (size_t)token_len;
    382                 if (token_len == 0)
    383                     hdr->token = NULL;
    384             } else {
    385                 hdr->token = NULL;
    386                 hdr->token_len = 0;
    387             }
    388 
    389             if (hdr->type == QUIC_PKT_TYPE_RETRY) {
    390                 /* Retry packet. */
    391                 hdr->data = PACKET_data(pkt);
    392                 hdr->len = PACKET_remaining(pkt);
    393 
    394                 /* Retry packets are always fully decoded. */
    395                 hdr->partial = 0;
    396 
    397                 /* Unused bits in Retry header. */
    398                 hdr->unused = b0 & 0x0f;
    399 
    400                 /* Fields not used in Retry packets. */
    401                 memset(hdr->pn, 0, sizeof(hdr->pn));
    402 
    403                 if (!PACKET_forward(pkt, hdr->len))
    404                     return 0;
    405             } else {
    406                 /* Initial, 0-RTT or Handshake packet. */
    407                 uint64_t len;
    408 
    409                 hdr->pn_len = partial ? 0 : ((b0 & 0x03) + 1);
    410                 hdr->reserved = partial ? 0 : ((b0 & 0x0C) >> 2);
    411 
    412                 if (!PACKET_get_quic_vlint(pkt, &len)
    413                     || len < sizeof(hdr->pn))
    414                     return 0;
    415 
    416                 if (!nodata && len > PACKET_remaining(pkt))
    417                     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                 pn = (unsigned char *)PACKET_data(pkt);
    426                 memset(hdr->pn, 0, sizeof(hdr->pn));
    427                 if (partial) {
    428                     if (!PACKET_forward(pkt, sizeof(hdr->pn)))
    429                         return 0;
    430 
    431                     hdr->len = (size_t)(len - sizeof(hdr->pn));
    432                 } else {
    433                     if (!PACKET_copy_bytes(pkt, hdr->pn, hdr->pn_len))
    434                         return 0;
    435 
    436                     hdr->len = (size_t)(len - hdr->pn_len);
    437                 }
    438 
    439                 if (nodata) {
    440                     hdr->data = NULL;
    441                 } else {
    442                     hdr->data = PACKET_data(pkt);
    443 
    444                     /* Skip over packet body. */
    445                     if (!PACKET_forward(pkt, hdr->len))
    446                         return 0;
    447                 }
    448             }
    449         }
    450     }
    451 
    452     if (ptrs != NULL) {
    453         ptrs->raw_pn = pn;
    454         if (pn != NULL) {
    455             ptrs->raw_sample = pn + 4;
    456             ptrs->raw_sample_len = PACKET_end(pkt) - ptrs->raw_sample;
    457         }
    458     }
    459 
    460     /*
    461      * Good decode, clear the generic DECODE_ERR flag
    462      */
    463     if (fail_cause != NULL)
    464         *fail_cause &= ~QUIC_PKT_HDR_DECODE_DECODE_ERR;
    465 
    466     return 1;
    467 }
    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 {
    474     unsigned char b0;
    475     size_t off_start, off_sample, off_pn;
    476     unsigned char *start = WPACKET_get_curr(pkt);
    477 
    478     if (!WPACKET_get_total_written(pkt, &off_start))
    479         return 0;
    480 
    481     if (ptrs != NULL) {
    482         /* ptrs would not be stable on non-static WPACKET */
    483         if (!ossl_assert(pkt->staticbuf != NULL))
    484             return 0;
    485         ptrs->raw_start = NULL;
    486         ptrs->raw_sample = NULL;
    487         ptrs->raw_sample_len = 0;
    488         ptrs->raw_pn = 0;
    489     }
    490 
    491     /* Cannot serialize a partial header, or one whose DCID length is wrong. */
    492     if (hdr->partial
    493         || (hdr->type == QUIC_PKT_TYPE_1RTT
    494             && hdr->dst_conn_id.id_len != short_conn_id_len))
    495         return 0;
    496 
    497     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         if (hdr->dst_conn_id.id_len != short_conn_id_len
    505             || short_conn_id_len > QUIC_MAX_CONN_ID_LEN
    506             || hdr->pn_len < 1 || hdr->pn_len > 4)
    507             return 0;
    508 
    509         b0 = (hdr->spin_bit << 5)
    510             | (hdr->key_phase << 2)
    511             | (hdr->pn_len - 1)
    512             | (hdr->reserved << 3)
    513             | 0x40; /* fixed bit */
    514 
    515         if (!WPACKET_put_bytes_u8(pkt, b0)
    516             || !WPACKET_memcpy(pkt, hdr->dst_conn_id.id, short_conn_id_len)
    517             || !WPACKET_get_total_written(pkt, &off_pn)
    518             || !WPACKET_memcpy(pkt, hdr->pn, hdr->pn_len))
    519             return 0;
    520     } else {
    521         /* Long header. */
    522         unsigned int raw_type;
    523 
    524         if (hdr->dst_conn_id.id_len > QUIC_MAX_CONN_ID_LEN
    525             || hdr->src_conn_id.id_len > QUIC_MAX_CONN_ID_LEN)
    526             return 0;
    527 
    528         if (ossl_quic_pkt_type_has_pn(hdr->type)
    529             && (hdr->pn_len < 1 || hdr->pn_len > 4))
    530             return 0;
    531 
    532         switch (hdr->type) {
    533         case QUIC_PKT_TYPE_VERSION_NEG:
    534             if (hdr->version != 0)
    535                 return 0;
    536 
    537             /* Version negotiation packets use zero for the type bits */
    538             raw_type = 0;
    539             break;
    540 
    541         case QUIC_PKT_TYPE_INITIAL:
    542             raw_type = 0;
    543             break;
    544         case QUIC_PKT_TYPE_0RTT:
    545             raw_type = 1;
    546             break;
    547         case QUIC_PKT_TYPE_HANDSHAKE:
    548             raw_type = 2;
    549             break;
    550         case QUIC_PKT_TYPE_RETRY:
    551             raw_type = 3;
    552             break;
    553         default:
    554             return 0;
    555         }
    556 
    557         b0 = (raw_type << 4) | 0x80; /* long */
    558         if (hdr->type != QUIC_PKT_TYPE_VERSION_NEG || hdr->fixed)
    559             b0 |= 0x40; /* fixed */
    560         if (ossl_quic_pkt_type_has_pn(hdr->type)) {
    561             b0 |= hdr->pn_len - 1;
    562             b0 |= (hdr->reserved << 2);
    563         }
    564         if (hdr->type == QUIC_PKT_TYPE_RETRY)
    565             b0 |= hdr->unused;
    566 
    567         if (!WPACKET_put_bytes_u8(pkt, b0)
    568             || !WPACKET_put_bytes_u32(pkt, hdr->version)
    569             || !WPACKET_put_bytes_u8(pkt, hdr->dst_conn_id.id_len)
    570             || !WPACKET_memcpy(pkt, hdr->dst_conn_id.id,
    571                 hdr->dst_conn_id.id_len)
    572             || !WPACKET_put_bytes_u8(pkt, hdr->src_conn_id.id_len)
    573             || !WPACKET_memcpy(pkt, hdr->src_conn_id.id,
    574                 hdr->src_conn_id.id_len))
    575             return 0;
    576 
    577         if (hdr->type == QUIC_PKT_TYPE_VERSION_NEG) {
    578             if (hdr->len > 0 && !WPACKET_reserve_bytes(pkt, hdr->len, NULL))
    579                 return 0;
    580 
    581             return 1;
    582         }
    583 
    584         if (hdr->type == QUIC_PKT_TYPE_INITIAL) {
    585             if (!WPACKET_quic_write_vlint(pkt, hdr->token_len)
    586                 || !WPACKET_memcpy(pkt, hdr->token, hdr->token_len))
    587                 return 0;
    588         }
    589 
    590         if (hdr->type == QUIC_PKT_TYPE_RETRY) {
    591             if (!WPACKET_memcpy(pkt, hdr->token, hdr->token_len))
    592                 return 0;
    593             return 1;
    594         }
    595 
    596         if (!WPACKET_quic_write_vlint(pkt, hdr->len + hdr->pn_len)
    597             || !WPACKET_get_total_written(pkt, &off_pn)
    598             || !WPACKET_memcpy(pkt, hdr->pn, hdr->pn_len))
    599             return 0;
    600     }
    601 
    602     if (hdr->len > 0 && !WPACKET_reserve_bytes(pkt, hdr->len, NULL))
    603         return 0;
    604 
    605     off_sample = off_pn + 4;
    606 
    607     if (ptrs != NULL) {
    608         ptrs->raw_start = start;
    609         ptrs->raw_sample = start + (off_sample - off_start);
    610         ptrs->raw_sample_len
    611             = WPACKET_get_curr(pkt) + hdr->len - ptrs->raw_sample;
    612         ptrs->raw_pn = start + (off_pn - off_start);
    613     }
    614 
    615     return 1;
    616 }
    617 
    618 int ossl_quic_wire_get_encoded_pkt_hdr_len(size_t short_conn_id_len,
    619     const QUIC_PKT_HDR *hdr)
    620 {
    621     size_t len = 0, enclen;
    622 
    623     /* Cannot serialize a partial header, or one whose DCID length is wrong. */
    624     if (hdr->partial
    625         || (hdr->type == QUIC_PKT_TYPE_1RTT
    626             && hdr->dst_conn_id.id_len != short_conn_id_len))
    627         return 0;
    628 
    629     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         if (hdr->dst_conn_id.id_len != short_conn_id_len
    637             || short_conn_id_len > QUIC_MAX_CONN_ID_LEN
    638             || hdr->pn_len < 1 || hdr->pn_len > 4)
    639             return 0;
    640 
    641         return 1 + short_conn_id_len + hdr->pn_len;
    642     } else {
    643         /* Long header. */
    644         if (hdr->dst_conn_id.id_len > QUIC_MAX_CONN_ID_LEN
    645             || hdr->src_conn_id.id_len > QUIC_MAX_CONN_ID_LEN)
    646             return 0;
    647 
    648         len += 1 /* Initial byte */ + 4 /* Version */
    649             + 1 + hdr->dst_conn_id.id_len /* DCID Len, DCID */
    650             + 1 + hdr->src_conn_id.id_len /* SCID Len, SCID */
    651             ;
    652 
    653         if (ossl_quic_pkt_type_has_pn(hdr->type)) {
    654             if (hdr->pn_len < 1 || hdr->pn_len > 4)
    655                 return 0;
    656 
    657             len += hdr->pn_len;
    658         }
    659 
    660         if (hdr->type == QUIC_PKT_TYPE_INITIAL) {
    661             enclen = ossl_quic_vlint_encode_len(hdr->token_len);
    662             if (!enclen)
    663                 return 0;
    664 
    665             len += enclen + hdr->token_len;
    666         }
    667 
    668         if (!ossl_quic_pkt_type_must_be_last(hdr->type)) {
    669             enclen = ossl_quic_vlint_encode_len(hdr->len + hdr->pn_len);
    670             if (!enclen)
    671                 return 0;
    672 
    673             len += enclen;
    674         }
    675 
    676         return len;
    677     }
    678 }
    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 {
    685     unsigned char b0;
    686     size_t blen;
    687 
    688     if (buf_len < QUIC_MIN_VALID_PKT_LEN
    689         || short_conn_id_len > QUIC_MAX_CONN_ID_LEN)
    690         return 0;
    691 
    692     b0 = buf[0];
    693     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         if ((buf[1] || buf[2] || buf[3] || buf[4]) && (b0 & 0x40) == 0)
    705             return 0;
    706 
    707         blen = (size_t)buf[5]; /* DCID Length */
    708         if (blen > QUIC_MAX_CONN_ID_LEN
    709             || buf_len < QUIC_MIN_VALID_PKT_LEN + blen)
    710             return 0;
    711 
    712         dst_conn_id->id_len = (unsigned char)blen;
    713         memcpy(dst_conn_id->id, buf + 6, blen);
    714         return 1;
    715     } else {
    716         /* Short header. */
    717         if ((b0 & 0x40) == 0)
    718             /* Fixed bit not set, not a valid QUIC packet header. */
    719             return 0;
    720 
    721         if (buf_len < QUIC_MIN_VALID_PKT_LEN_CRYPTO + short_conn_id_len)
    722             return 0;
    723 
    724         dst_conn_id->id_len = (unsigned char)short_conn_id_len;
    725         memcpy(dst_conn_id->id, buf + 1, short_conn_id_len);
    726         return 1;
    727     }
    728 }
    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 {
    735     int64_t expected_pn, truncated_pn, candidate_pn, pn_win, pn_hwin, pn_mask;
    736 
    737     switch (enc_pn_len) {
    738     case 1:
    739         truncated_pn = enc_pn[0];
    740         break;
    741     case 2:
    742         truncated_pn = ((QUIC_PN)enc_pn[0] << 8)
    743             | (QUIC_PN)enc_pn[1];
    744         break;
    745     case 3:
    746         truncated_pn = ((QUIC_PN)enc_pn[0] << 16)
    747             | ((QUIC_PN)enc_pn[1] << 8)
    748             | (QUIC_PN)enc_pn[2];
    749         break;
    750     case 4:
    751         truncated_pn = ((QUIC_PN)enc_pn[0] << 24)
    752             | ((QUIC_PN)enc_pn[1] << 16)
    753             | ((QUIC_PN)enc_pn[2] << 8)
    754             | (QUIC_PN)enc_pn[3];
    755         break;
    756     default:
    757         return 0;
    758     }
    759 
    760     /* Implemented as per RFC 9000 Section A.3. */
    761     expected_pn = largest_pn + 1;
    762     pn_win = ((int64_t)1) << (enc_pn_len * 8);
    763     pn_hwin = pn_win / 2;
    764     pn_mask = pn_win - 1;
    765     candidate_pn = (expected_pn & ~pn_mask) | truncated_pn;
    766     if (candidate_pn <= expected_pn - pn_hwin
    767         && candidate_pn < (((int64_t)1) << 62) - pn_win)
    768         *res_pn = candidate_pn + pn_win;
    769     else if (candidate_pn > expected_pn + pn_hwin
    770         && candidate_pn >= pn_win)
    771         *res_pn = candidate_pn - pn_win;
    772     else
    773         *res_pn = candidate_pn;
    774     return 1;
    775 }
    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 {
    781     uint64_t num_unacked
    782         = (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     if (num_unacked <= (1U << 7))
    792         return 1;
    793     if (num_unacked <= (1U << 15))
    794         return 2;
    795     if (num_unacked <= (1U << 23))
    796         return 3;
    797     return 4;
    798 }
    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 {
    804     switch (enc_pn_len) {
    805     case 1:
    806         enc_pn[0] = (unsigned char)pn;
    807         break;
    808     case 2:
    809         enc_pn[1] = (unsigned char)pn;
    810         enc_pn[0] = (unsigned char)(pn >> 8);
    811         break;
    812     case 3:
    813         enc_pn[2] = (unsigned char)pn;
    814         enc_pn[1] = (unsigned char)(pn >> 8);
    815         enc_pn[0] = (unsigned char)(pn >> 16);
    816         break;
    817     case 4:
    818         enc_pn[3] = (unsigned char)pn;
    819         enc_pn[2] = (unsigned char)(pn >> 8);
    820         enc_pn[1] = (unsigned char)(pn >> 16);
    821         enc_pn[0] = (unsigned char)(pn >> 24);
    822         break;
    823     default:
    824         return 0;
    825     }
    826 
    827     return 1;
    828 }
    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 {
    835     unsigned char expected_tag[QUIC_RETRY_INTEGRITY_TAG_LEN];
    836     const unsigned char *actual_tag;
    837 
    838     if (hdr == NULL || hdr->len < QUIC_RETRY_INTEGRITY_TAG_LEN)
    839         return 0;
    840 
    841     if (!ossl_quic_calculate_retry_integrity_tag(libctx, propq,
    842             hdr, client_initial_dcid,
    843             expected_tag))
    844         return 0;
    845 
    846     actual_tag = hdr->data + hdr->len - QUIC_RETRY_INTEGRITY_TAG_LEN;
    847 
    848     return !CRYPTO_memcmp(expected_tag, actual_tag,
    849         QUIC_RETRY_INTEGRITY_TAG_LEN);
    850 }
    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 {
    869     EVP_CIPHER *cipher = NULL;
    870     EVP_CIPHER_CTX *cctx = NULL;
    871     int ok = 0, l = 0, l2 = 0, wpkt_valid = 0;
    872     WPACKET wpkt;
    873     /* Worst case length of the Retry Psuedo-Packet header is 68 bytes. */
    874     unsigned char buf[128];
    875     QUIC_PKT_HDR hdr2;
    876     size_t hdr_enc_len = 0;
    877 
    878     if (hdr->type != QUIC_PKT_TYPE_RETRY || hdr->version == 0
    879         || hdr->len < QUIC_RETRY_INTEGRITY_TAG_LEN
    880         || hdr->data == NULL
    881         || client_initial_dcid == NULL || tag == NULL
    882         || client_initial_dcid->id_len > QUIC_MAX_CONN_ID_LEN) {
    883         ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT);
    884         goto err;
    885     }
    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     hdr2 = *hdr;
    893     hdr2.len = 0;
    894 
    895     /* Assemble retry psuedo-packet. */
    896     if (!WPACKET_init_static_len(&wpkt, buf, sizeof(buf), 0)) {
    897         ERR_raise(ERR_LIB_SSL, ERR_R_CRYPTO_LIB);
    898         goto err;
    899     }
    900 
    901     wpkt_valid = 1;
    902 
    903     /* Prepend original DCID to the packet. */
    904     if (!WPACKET_put_bytes_u8(&wpkt, client_initial_dcid->id_len)
    905         || !WPACKET_memcpy(&wpkt, client_initial_dcid->id,
    906             client_initial_dcid->id_len)) {
    907         ERR_raise(ERR_LIB_SSL, ERR_R_CRYPTO_LIB);
    908         goto err;
    909     }
    910 
    911     /* Encode main retry header. */
    912     if (!ossl_quic_wire_encode_pkt_hdr(&wpkt, hdr2.dst_conn_id.id_len,
    913             &hdr2, NULL))
    914         goto err;
    915 
    916     if (!WPACKET_get_total_written(&wpkt, &hdr_enc_len)) {
    917         ERR_raise(ERR_LIB_SSL, ERR_R_CRYPTO_LIB);
    918         goto err;
    919     }
    920 
    921     /* Create and initialise cipher context. */
    922     /* TODO(QUIC FUTURE): Cipher fetch caching. */
    923     if ((cipher = EVP_CIPHER_fetch(libctx, "AES-128-GCM", propq)) == NULL) {
    924         ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
    925         goto err;
    926     }
    927 
    928     if ((cctx = EVP_CIPHER_CTX_new()) == NULL) {
    929         ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
    930         goto err;
    931     }
    932 
    933     if (!EVP_CipherInit_ex(cctx, cipher, NULL,
    934             retry_integrity_key, retry_integrity_nonce, /*enc=*/1)) {
    935         ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
    936         goto err;
    937     }
    938 
    939     /* Feed packet header as AAD data. */
    940     if (EVP_CipherUpdate(cctx, NULL, &l, buf, hdr_enc_len) != 1) {
    941         ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
    942         goto err;
    943     }
    944 
    945     /* Feed packet body as AAD data. */
    946     if (EVP_CipherUpdate(cctx, NULL, &l, hdr->data,
    947             hdr->len - QUIC_RETRY_INTEGRITY_TAG_LEN)
    948         != 1) {
    949         ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
    950         goto err;
    951     }
    952 
    953     /* Finalise and get tag. */
    954     if (EVP_CipherFinal_ex(cctx, NULL, &l2) != 1) {
    955         ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
    956         goto err;
    957     }
    958 
    959     if (EVP_CIPHER_CTX_ctrl(cctx, EVP_CTRL_AEAD_GET_TAG,
    960             QUIC_RETRY_INTEGRITY_TAG_LEN,
    961             tag)
    962         != 1) {
    963         ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
    964         goto err;
    965     }
    966 
    967     ok = 1;
    968 err:
    969     EVP_CIPHER_free(cipher);
    970     EVP_CIPHER_CTX_free(cctx);
    971     if (wpkt_valid)
    972         WPACKET_finish(&wpkt);
    973 
    974     return ok;
    975 }
    976