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