Home | History | Annotate | Line # | Download | only in internal
      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 #ifndef OSSL_INTERNAL_PACKET_QUIC_H
     11 #define OSSL_INTERNAL_PACKET_QUIC_H
     12 #pragma once
     13 
     14 #include "internal/packet.h"
     15 #include "internal/quic_vlint.h"
     16 
     17 #ifndef OPENSSL_NO_QUIC
     18 /*
     19  * Decodes a QUIC variable-length integer in |pkt| and stores the result in
     20  * |data|.
     21  */
     22 __owur static ossl_inline int PACKET_get_quic_vlint(PACKET *pkt,
     23     uint64_t *data)
     24 {
     25     size_t enclen;
     26 
     27     if (PACKET_remaining(pkt) < 1)
     28         return 0;
     29 
     30     enclen = ossl_quic_vlint_decode_len(*pkt->curr);
     31 
     32     if (PACKET_remaining(pkt) < enclen)
     33         return 0;
     34 
     35     *data = ossl_quic_vlint_decode_unchecked(pkt->curr);
     36     packet_forward(pkt, enclen);
     37     return 1;
     38 }
     39 
     40 /*
     41  * Decodes a QUIC variable-length integer in |pkt| and stores the result in
     42  * |data|. Unlike PACKET_get_quic_vlint, this does not advance the current
     43  * position. If was_minimal is non-NULL, *was_minimal is set to 1 if the integer
     44  * was encoded using the minimal possible number of bytes and 0 otherwise.
     45  */
     46 __owur static ossl_inline int PACKET_peek_quic_vlint_ex(PACKET *pkt,
     47     uint64_t *data,
     48     int *was_minimal)
     49 {
     50     size_t enclen;
     51 
     52     if (PACKET_remaining(pkt) < 1)
     53         return 0;
     54 
     55     enclen = ossl_quic_vlint_decode_len(*pkt->curr);
     56 
     57     if (PACKET_remaining(pkt) < enclen)
     58         return 0;
     59 
     60     *data = ossl_quic_vlint_decode_unchecked(pkt->curr);
     61 
     62     if (was_minimal != NULL)
     63         *was_minimal = (enclen == ossl_quic_vlint_encode_len(*data));
     64 
     65     return 1;
     66 }
     67 
     68 __owur static ossl_inline int PACKET_peek_quic_vlint(PACKET *pkt,
     69     uint64_t *data)
     70 {
     71     return PACKET_peek_quic_vlint_ex(pkt, data, NULL);
     72 }
     73 
     74 /*
     75  * Skips over a QUIC variable-length integer in |pkt| without decoding it.
     76  */
     77 __owur static ossl_inline int PACKET_skip_quic_vlint(PACKET *pkt)
     78 {
     79     size_t enclen;
     80 
     81     if (PACKET_remaining(pkt) < 1)
     82         return 0;
     83 
     84     enclen = ossl_quic_vlint_decode_len(*pkt->curr);
     85 
     86     if (PACKET_remaining(pkt) < enclen)
     87         return 0;
     88 
     89     packet_forward(pkt, enclen);
     90     return 1;
     91 }
     92 
     93 /*
     94  * Reads a variable-length vector prefixed with a QUIC variable-length integer
     95  * denoting the length, and stores the contents in |subpkt|. |pkt| can equal
     96  * |subpkt|. Data is not copied: the |subpkt| packet will share its underlying
     97  * buffer with the original |pkt|, so data wrapped by |pkt| must outlive the
     98  * |subpkt|. Upon failure, the original |pkt| and |subpkt| are not modified.
     99  */
    100 __owur static ossl_inline int PACKET_get_quic_length_prefixed(PACKET *pkt,
    101     PACKET *subpkt)
    102 {
    103     uint64_t length;
    104     const unsigned char *data;
    105     PACKET tmp = *pkt;
    106 
    107     if (!PACKET_get_quic_vlint(&tmp, &length) || length > SIZE_MAX || !PACKET_get_bytes(&tmp, &data, (size_t)length)) {
    108         return 0;
    109     }
    110 
    111     *pkt = tmp;
    112     subpkt->curr = data;
    113     subpkt->remaining = (size_t)length;
    114 
    115     return 1;
    116 }
    117 
    118 /*
    119  * Starts a QUIC sub-packet headed by a QUIC variable-length integer. A 4-byte
    120  * representation is used.
    121  */
    122 __owur int WPACKET_start_quic_sub_packet(WPACKET *pkt);
    123 
    124 /*
    125  * Starts a QUIC sub-packet headed by a QUIC variable-length integer. max_len
    126  * specifies the upper bound for the sub-packet size at the time the sub-packet
    127  * is closed, which determines the encoding size for the variable-length
    128  * integer header. max_len can be a precise figure or a worst-case bound
    129  * if a precise figure is not available.
    130  */
    131 __owur int WPACKET_start_quic_sub_packet_bound(WPACKET *pkt, size_t max_len);
    132 
    133 /*
    134  * Allocates a QUIC sub-packet with exactly len bytes of payload, headed by a
    135  * QUIC variable-length integer. The pointer to the payload buffer is output and
    136  * must be filled by the caller. This function assures optimal selection of
    137  * variable-length integer encoding length.
    138  */
    139 __owur int WPACKET_quic_sub_allocate_bytes(WPACKET *pkt, size_t len,
    140     unsigned char **bytes);
    141 
    142 /*
    143  * Write a QUIC variable-length integer to the packet.
    144  */
    145 __owur int WPACKET_quic_write_vlint(WPACKET *pkt, uint64_t v);
    146 
    147 #endif /* OPENSSL_NO_QUIC */
    148 #endif /* OSSL_INTERNAL_PACKET_QUIC_H */
    149