Path: blob/main/crypto/openssl/ssl/quic/quic_wire.c
48261 views
/*1* Copyright 2022-2024 The OpenSSL Project Authors. All Rights Reserved.2*3* Licensed under the Apache License 2.0 (the "License"). You may not use4* this file except in compliance with the License. You can obtain a copy5* in the file LICENSE in the source distribution or at6* https://www.openssl.org/source/license.html7*/89#include <openssl/macros.h>10#include <openssl/objects.h>11#include "internal/quic_ssl.h"12#include "internal/quic_vlint.h"13#include "internal/quic_wire.h"14#include "internal/quic_error.h"1516OSSL_SAFE_MATH_UNSIGNED(uint64_t, uint64_t)1718int ossl_quic_frame_ack_contains_pn(const OSSL_QUIC_FRAME_ACK *ack, QUIC_PN pn)19{20size_t i;2122for (i = 0; i < ack->num_ack_ranges; ++i)23if (pn >= ack->ack_ranges[i].start24&& pn <= ack->ack_ranges[i].end)25return 1;2627return 0;28}2930/*31* QUIC Wire Format Encoding32* =========================33*/3435int ossl_quic_wire_encode_padding(WPACKET *pkt, size_t num_bytes)36{37/*38* PADDING is frame type zero, which as a variable-length integer is39* represented as a single zero byte. As an optimisation, just use memset.40*/41return WPACKET_memset(pkt, 0, num_bytes);42}4344static int encode_frame_hdr(WPACKET *pkt, uint64_t frame_type)45{46return WPACKET_quic_write_vlint(pkt, frame_type);47}4849int ossl_quic_wire_encode_frame_ping(WPACKET *pkt)50{51return encode_frame_hdr(pkt, OSSL_QUIC_FRAME_TYPE_PING);52}5354int ossl_quic_wire_encode_frame_ack(WPACKET *pkt,55uint32_t ack_delay_exponent,56const OSSL_QUIC_FRAME_ACK *ack)57{58uint64_t frame_type = ack->ecn_present ? OSSL_QUIC_FRAME_TYPE_ACK_WITH_ECN59: OSSL_QUIC_FRAME_TYPE_ACK_WITHOUT_ECN;6061uint64_t largest_ackd, first_ack_range, ack_delay_enc;62uint64_t i, num_ack_ranges = ack->num_ack_ranges;63OSSL_TIME delay;6465if (num_ack_ranges == 0)66return 0;6768delay = ossl_time_divide(ossl_time_divide(ack->delay_time, OSSL_TIME_US),69(uint64_t)1 << ack_delay_exponent);70ack_delay_enc = ossl_time2ticks(delay);7172largest_ackd = ack->ack_ranges[0].end;73first_ack_range = ack->ack_ranges[0].end - ack->ack_ranges[0].start;7475if (!encode_frame_hdr(pkt, frame_type)76|| !WPACKET_quic_write_vlint(pkt, largest_ackd)77|| !WPACKET_quic_write_vlint(pkt, ack_delay_enc)78|| !WPACKET_quic_write_vlint(pkt, num_ack_ranges - 1)79|| !WPACKET_quic_write_vlint(pkt, first_ack_range))80return 0;8182for (i = 1; i < num_ack_ranges; ++i) {83uint64_t gap, range_len;8485gap = ack->ack_ranges[i - 1].start - ack->ack_ranges[i].end - 2;86range_len = ack->ack_ranges[i].end - ack->ack_ranges[i].start;8788if (!WPACKET_quic_write_vlint(pkt, gap)89|| !WPACKET_quic_write_vlint(pkt, range_len))90return 0;91}9293if (ack->ecn_present)94if (!WPACKET_quic_write_vlint(pkt, ack->ect0)95|| !WPACKET_quic_write_vlint(pkt, ack->ect1)96|| !WPACKET_quic_write_vlint(pkt, ack->ecnce))97return 0;9899return 1;100}101102int ossl_quic_wire_encode_frame_reset_stream(WPACKET *pkt,103const OSSL_QUIC_FRAME_RESET_STREAM *f)104{105if (!encode_frame_hdr(pkt, OSSL_QUIC_FRAME_TYPE_RESET_STREAM)106|| !WPACKET_quic_write_vlint(pkt, f->stream_id)107|| !WPACKET_quic_write_vlint(pkt, f->app_error_code)108|| !WPACKET_quic_write_vlint(pkt, f->final_size))109return 0;110111return 1;112}113114int ossl_quic_wire_encode_frame_stop_sending(WPACKET *pkt,115const OSSL_QUIC_FRAME_STOP_SENDING *f)116{117if (!encode_frame_hdr(pkt, OSSL_QUIC_FRAME_TYPE_STOP_SENDING)118|| !WPACKET_quic_write_vlint(pkt, f->stream_id)119|| !WPACKET_quic_write_vlint(pkt, f->app_error_code))120return 0;121122return 1;123}124125int ossl_quic_wire_encode_frame_crypto_hdr(WPACKET *pkt,126const OSSL_QUIC_FRAME_CRYPTO *f)127{128if (!encode_frame_hdr(pkt, OSSL_QUIC_FRAME_TYPE_CRYPTO)129|| !WPACKET_quic_write_vlint(pkt, f->offset)130|| !WPACKET_quic_write_vlint(pkt, f->len))131return 0;132133return 1;134}135136size_t ossl_quic_wire_get_encoded_frame_len_crypto_hdr(const OSSL_QUIC_FRAME_CRYPTO *f)137{138size_t a, b, c;139140a = ossl_quic_vlint_encode_len(OSSL_QUIC_FRAME_TYPE_CRYPTO);141b = ossl_quic_vlint_encode_len(f->offset);142c = ossl_quic_vlint_encode_len(f->len);143if (a == 0 || b == 0 || c == 0)144return 0;145146return a + b + c;147}148149void *ossl_quic_wire_encode_frame_crypto(WPACKET *pkt,150const OSSL_QUIC_FRAME_CRYPTO *f)151{152unsigned char *p = NULL;153154if (!ossl_quic_wire_encode_frame_crypto_hdr(pkt, f)155|| f->len > SIZE_MAX /* sizeof(uint64_t) > sizeof(size_t)? */156|| !WPACKET_allocate_bytes(pkt, (size_t)f->len, &p))157return NULL;158159if (f->data != NULL)160memcpy(p, f->data, (size_t)f->len);161162return p;163}164165int ossl_quic_wire_encode_frame_new_token(WPACKET *pkt,166const unsigned char *token,167size_t token_len)168{169if (!encode_frame_hdr(pkt, OSSL_QUIC_FRAME_TYPE_NEW_TOKEN)170|| !WPACKET_quic_write_vlint(pkt, token_len)171|| !WPACKET_memcpy(pkt, token, token_len))172return 0;173174return 1;175}176177int ossl_quic_wire_encode_frame_stream_hdr(WPACKET *pkt,178const OSSL_QUIC_FRAME_STREAM *f)179{180uint64_t frame_type = OSSL_QUIC_FRAME_TYPE_STREAM;181182if (f->offset != 0)183frame_type |= OSSL_QUIC_FRAME_FLAG_STREAM_OFF;184if (f->has_explicit_len)185frame_type |= OSSL_QUIC_FRAME_FLAG_STREAM_LEN;186if (f->is_fin)187frame_type |= OSSL_QUIC_FRAME_FLAG_STREAM_FIN;188189if (!encode_frame_hdr(pkt, frame_type)190|| !WPACKET_quic_write_vlint(pkt, f->stream_id))191return 0;192193if (f->offset != 0 && !WPACKET_quic_write_vlint(pkt, f->offset))194return 0;195196if (f->has_explicit_len && !WPACKET_quic_write_vlint(pkt, f->len))197return 0;198199return 1;200}201202size_t ossl_quic_wire_get_encoded_frame_len_stream_hdr(const OSSL_QUIC_FRAME_STREAM *f)203{204size_t a, b, c, d;205206a = ossl_quic_vlint_encode_len(OSSL_QUIC_FRAME_TYPE_STREAM);207b = ossl_quic_vlint_encode_len(f->stream_id);208if (a == 0 || b == 0)209return 0;210211if (f->offset > 0) {212c = ossl_quic_vlint_encode_len(f->offset);213if (c == 0)214return 0;215} else {216c = 0;217}218219if (f->has_explicit_len) {220d = ossl_quic_vlint_encode_len(f->len);221if (d == 0)222return 0;223} else {224d = 0;225}226227return a + b + c + d;228}229230void *ossl_quic_wire_encode_frame_stream(WPACKET *pkt,231const OSSL_QUIC_FRAME_STREAM *f)232{233234unsigned char *p = NULL;235236if (!ossl_quic_wire_encode_frame_stream_hdr(pkt, f)237|| f->len > SIZE_MAX /* sizeof(uint64_t) > sizeof(size_t)? */)238return NULL;239240if (!WPACKET_allocate_bytes(pkt, (size_t)f->len, &p))241return NULL;242243if (f->data != NULL)244memcpy(p, f->data, (size_t)f->len);245246return p;247}248249int ossl_quic_wire_encode_frame_max_data(WPACKET *pkt,250uint64_t max_data)251{252if (!encode_frame_hdr(pkt, OSSL_QUIC_FRAME_TYPE_MAX_DATA)253|| !WPACKET_quic_write_vlint(pkt, max_data))254return 0;255256return 1;257}258259int ossl_quic_wire_encode_frame_max_stream_data(WPACKET *pkt,260uint64_t stream_id,261uint64_t max_data)262{263if (!encode_frame_hdr(pkt, OSSL_QUIC_FRAME_TYPE_MAX_STREAM_DATA)264|| !WPACKET_quic_write_vlint(pkt, stream_id)265|| !WPACKET_quic_write_vlint(pkt, max_data))266return 0;267268return 1;269}270271int ossl_quic_wire_encode_frame_max_streams(WPACKET *pkt,272char is_uni,273uint64_t max_streams)274{275if (!encode_frame_hdr(pkt, is_uni ? OSSL_QUIC_FRAME_TYPE_MAX_STREAMS_UNI276: OSSL_QUIC_FRAME_TYPE_MAX_STREAMS_BIDI)277|| !WPACKET_quic_write_vlint(pkt, max_streams))278return 0;279280return 1;281}282283int ossl_quic_wire_encode_frame_data_blocked(WPACKET *pkt,284uint64_t max_data)285{286if (!encode_frame_hdr(pkt, OSSL_QUIC_FRAME_TYPE_DATA_BLOCKED)287|| !WPACKET_quic_write_vlint(pkt, max_data))288return 0;289290return 1;291}292293294int ossl_quic_wire_encode_frame_stream_data_blocked(WPACKET *pkt,295uint64_t stream_id,296uint64_t max_stream_data)297{298if (!encode_frame_hdr(pkt, OSSL_QUIC_FRAME_TYPE_STREAM_DATA_BLOCKED)299|| !WPACKET_quic_write_vlint(pkt, stream_id)300|| !WPACKET_quic_write_vlint(pkt, max_stream_data))301return 0;302303return 1;304}305306int ossl_quic_wire_encode_frame_streams_blocked(WPACKET *pkt,307char is_uni,308uint64_t max_streams)309{310if (!encode_frame_hdr(pkt, is_uni ? OSSL_QUIC_FRAME_TYPE_STREAMS_BLOCKED_UNI311: OSSL_QUIC_FRAME_TYPE_STREAMS_BLOCKED_BIDI)312|| !WPACKET_quic_write_vlint(pkt, max_streams))313return 0;314315return 1;316}317318int ossl_quic_wire_encode_frame_new_conn_id(WPACKET *pkt,319const OSSL_QUIC_FRAME_NEW_CONN_ID *f)320{321if (f->conn_id.id_len < 1322|| f->conn_id.id_len > QUIC_MAX_CONN_ID_LEN)323return 0;324325if (!encode_frame_hdr(pkt, OSSL_QUIC_FRAME_TYPE_NEW_CONN_ID)326|| !WPACKET_quic_write_vlint(pkt, f->seq_num)327|| !WPACKET_quic_write_vlint(pkt, f->retire_prior_to)328|| !WPACKET_put_bytes_u8(pkt, f->conn_id.id_len)329|| !WPACKET_memcpy(pkt, f->conn_id.id, f->conn_id.id_len)330|| !WPACKET_memcpy(pkt, f->stateless_reset.token,331sizeof(f->stateless_reset.token)))332return 0;333334return 1;335}336337int ossl_quic_wire_encode_frame_retire_conn_id(WPACKET *pkt,338uint64_t seq_num)339{340if (!encode_frame_hdr(pkt, OSSL_QUIC_FRAME_TYPE_RETIRE_CONN_ID)341|| !WPACKET_quic_write_vlint(pkt, seq_num))342return 0;343344return 1;345}346347int ossl_quic_wire_encode_frame_path_challenge(WPACKET *pkt,348uint64_t data)349{350if (!encode_frame_hdr(pkt, OSSL_QUIC_FRAME_TYPE_PATH_CHALLENGE)351|| !WPACKET_put_bytes_u64(pkt, data))352return 0;353354return 1;355}356357int ossl_quic_wire_encode_frame_path_response(WPACKET *pkt,358uint64_t data)359{360if (!encode_frame_hdr(pkt, OSSL_QUIC_FRAME_TYPE_PATH_RESPONSE)361|| !WPACKET_put_bytes_u64(pkt, data))362return 0;363364return 1;365}366367int ossl_quic_wire_encode_frame_conn_close(WPACKET *pkt,368const OSSL_QUIC_FRAME_CONN_CLOSE *f)369{370if (!encode_frame_hdr(pkt, f->is_app ? OSSL_QUIC_FRAME_TYPE_CONN_CLOSE_APP371: OSSL_QUIC_FRAME_TYPE_CONN_CLOSE_TRANSPORT)372|| !WPACKET_quic_write_vlint(pkt, f->error_code))373return 0;374375/*376* RFC 9000 s. 19.19: The application-specific variant of CONNECTION_CLOSE377* (type 0x1d) does not include this field.378*/379if (!f->is_app && !WPACKET_quic_write_vlint(pkt, f->frame_type))380return 0;381382if (!WPACKET_quic_write_vlint(pkt, f->reason_len)383|| !WPACKET_memcpy(pkt, f->reason, f->reason_len))384return 0;385386return 1;387}388389int ossl_quic_wire_encode_frame_handshake_done(WPACKET *pkt)390{391return encode_frame_hdr(pkt, OSSL_QUIC_FRAME_TYPE_HANDSHAKE_DONE);392}393394unsigned char *ossl_quic_wire_encode_transport_param_bytes(WPACKET *pkt,395uint64_t id,396const unsigned char *value,397size_t value_len)398{399unsigned char *b = NULL;400401if (!WPACKET_quic_write_vlint(pkt, id)402|| !WPACKET_quic_write_vlint(pkt, value_len))403return NULL;404405if (value_len == 0)406b = WPACKET_get_curr(pkt);407else if (!WPACKET_allocate_bytes(pkt, value_len, (unsigned char **)&b))408return NULL;409410if (value != NULL)411memcpy(b, value, value_len);412413return b;414}415416int ossl_quic_wire_encode_transport_param_int(WPACKET *pkt,417uint64_t id,418uint64_t value)419{420if (!WPACKET_quic_write_vlint(pkt, id)421|| !WPACKET_quic_write_vlint(pkt, ossl_quic_vlint_encode_len(value))422|| !WPACKET_quic_write_vlint(pkt, value))423return 0;424425return 1;426}427428int ossl_quic_wire_encode_transport_param_cid(WPACKET *wpkt,429uint64_t id,430const QUIC_CONN_ID *cid)431{432if (cid->id_len > QUIC_MAX_CONN_ID_LEN)433return 0;434435if (ossl_quic_wire_encode_transport_param_bytes(wpkt, id,436cid->id,437cid->id_len) == NULL)438return 0;439440return 1;441}442443/*444* QUIC Wire Format Decoding445* =========================446*/447int ossl_quic_wire_peek_frame_header(PACKET *pkt, uint64_t *type,448int *was_minimal)449{450return PACKET_peek_quic_vlint_ex(pkt, type, was_minimal);451}452453int ossl_quic_wire_skip_frame_header(PACKET *pkt, uint64_t *type)454{455return PACKET_get_quic_vlint(pkt, type);456}457458static int expect_frame_header_mask(PACKET *pkt,459uint64_t expected_frame_type,460uint64_t mask_bits,461uint64_t *actual_frame_type)462{463uint64_t actual_frame_type_;464465if (!ossl_quic_wire_skip_frame_header(pkt, &actual_frame_type_)466|| (actual_frame_type_ & ~mask_bits) != expected_frame_type)467return 0;468469if (actual_frame_type != NULL)470*actual_frame_type = actual_frame_type_;471472return 1;473}474475static int expect_frame_header(PACKET *pkt, uint64_t expected_frame_type)476{477uint64_t actual_frame_type;478479if (!ossl_quic_wire_skip_frame_header(pkt, &actual_frame_type)480|| actual_frame_type != expected_frame_type)481return 0;482483return 1;484}485486int ossl_quic_wire_peek_frame_ack_num_ranges(const PACKET *orig_pkt,487uint64_t *total_ranges)488{489PACKET pkt = *orig_pkt;490uint64_t ack_range_count, i;491492if (!expect_frame_header_mask(&pkt, OSSL_QUIC_FRAME_TYPE_ACK_WITHOUT_ECN,4931, NULL)494|| !PACKET_skip_quic_vlint(&pkt)495|| !PACKET_skip_quic_vlint(&pkt)496|| !PACKET_get_quic_vlint(&pkt, &ack_range_count))497return 0;498499/*500* Ensure the specified number of ack ranges listed in the ACK frame header501* actually are available in the frame data. This naturally bounds the502* number of ACK ranges which can be requested by the MDPL, and therefore by503* the MTU. This ensures we do not allocate memory for an excessive number504* of ACK ranges.505*/506for (i = 0; i < ack_range_count; ++i)507if (!PACKET_skip_quic_vlint(&pkt)508|| !PACKET_skip_quic_vlint(&pkt))509return 0;510511/* (cannot overflow because QUIC vlints can only encode up to 2**62-1) */512*total_ranges = ack_range_count + 1;513return 1;514}515516int ossl_quic_wire_decode_frame_ack(PACKET *pkt,517uint32_t ack_delay_exponent,518OSSL_QUIC_FRAME_ACK *ack,519uint64_t *total_ranges) {520uint64_t frame_type, largest_ackd, ack_delay_raw;521uint64_t ack_range_count, first_ack_range, start, end, i;522523/* This call matches both ACK_WITHOUT_ECN and ACK_WITH_ECN. */524if (!expect_frame_header_mask(pkt, OSSL_QUIC_FRAME_TYPE_ACK_WITHOUT_ECN,5251, &frame_type)526|| !PACKET_get_quic_vlint(pkt, &largest_ackd)527|| !PACKET_get_quic_vlint(pkt, &ack_delay_raw)528|| !PACKET_get_quic_vlint(pkt, &ack_range_count)529|| !PACKET_get_quic_vlint(pkt, &first_ack_range))530return 0;531532if (first_ack_range > largest_ackd)533return 0;534535if (ack_range_count > SIZE_MAX /* sizeof(uint64_t) > sizeof(size_t)? */)536return 0;537538start = largest_ackd - first_ack_range;539540if (ack != NULL) {541int err = 0;542ack->delay_time543= ossl_time_multiply(ossl_ticks2time(OSSL_TIME_US),544safe_mul_uint64_t(ack_delay_raw,545(uint64_t)1 << ack_delay_exponent,546&err));547if (err)548ack->delay_time = ossl_time_infinite();549550if (ack->num_ack_ranges > 0) {551ack->ack_ranges[0].end = largest_ackd;552ack->ack_ranges[0].start = start;553}554}555556for (i = 0; i < ack_range_count; ++i) {557uint64_t gap, len;558559if (!PACKET_get_quic_vlint(pkt, &gap)560|| !PACKET_get_quic_vlint(pkt, &len))561return 0;562563end = start - gap - 2;564if (start < gap + 2 || len > end)565return 0;566567if (ack != NULL && i + 1 < ack->num_ack_ranges) {568ack->ack_ranges[i + 1].start = start = end - len;569ack->ack_ranges[i + 1].end = end;570}571}572573if (ack != NULL && ack_range_count + 1 < ack->num_ack_ranges)574ack->num_ack_ranges = (size_t)ack_range_count + 1;575576if (total_ranges != NULL)577*total_ranges = ack_range_count + 1;578579if (frame_type == OSSL_QUIC_FRAME_TYPE_ACK_WITH_ECN) {580uint64_t ect0, ect1, ecnce;581582if (!PACKET_get_quic_vlint(pkt, &ect0)583|| !PACKET_get_quic_vlint(pkt, &ect1)584|| !PACKET_get_quic_vlint(pkt, &ecnce))585return 0;586587if (ack != NULL) {588ack->ect0 = ect0;589ack->ect1 = ect1;590ack->ecnce = ecnce;591ack->ecn_present = 1;592}593} else if (ack != NULL) {594ack->ecn_present = 0;595}596597return 1;598}599600int ossl_quic_wire_decode_frame_reset_stream(PACKET *pkt,601OSSL_QUIC_FRAME_RESET_STREAM *f)602{603if (!expect_frame_header(pkt, OSSL_QUIC_FRAME_TYPE_RESET_STREAM)604|| !PACKET_get_quic_vlint(pkt, &f->stream_id)605|| !PACKET_get_quic_vlint(pkt, &f->app_error_code)606|| !PACKET_get_quic_vlint(pkt, &f->final_size))607return 0;608609return 1;610}611612int ossl_quic_wire_decode_frame_stop_sending(PACKET *pkt,613OSSL_QUIC_FRAME_STOP_SENDING *f)614{615if (!expect_frame_header(pkt, OSSL_QUIC_FRAME_TYPE_STOP_SENDING)616|| !PACKET_get_quic_vlint(pkt, &f->stream_id)617|| !PACKET_get_quic_vlint(pkt, &f->app_error_code))618return 0;619620return 1;621}622623int ossl_quic_wire_decode_frame_crypto(PACKET *pkt,624int nodata,625OSSL_QUIC_FRAME_CRYPTO *f)626{627if (!expect_frame_header(pkt, OSSL_QUIC_FRAME_TYPE_CRYPTO)628|| !PACKET_get_quic_vlint(pkt, &f->offset)629|| !PACKET_get_quic_vlint(pkt, &f->len)630|| f->len > SIZE_MAX /* sizeof(uint64_t) > sizeof(size_t)? */)631return 0;632633if (f->offset + f->len > (((uint64_t)1) << 62) - 1)634/* RFC 9000 s. 19.6 */635return 0;636637if (nodata) {638f->data = NULL;639} else {640if (PACKET_remaining(pkt) < f->len)641return 0;642643f->data = PACKET_data(pkt);644645if (!PACKET_forward(pkt, (size_t)f->len))646return 0;647}648649return 1;650}651652int ossl_quic_wire_decode_frame_new_token(PACKET *pkt,653const unsigned char **token,654size_t *token_len)655{656uint64_t token_len_;657658if (!expect_frame_header(pkt, OSSL_QUIC_FRAME_TYPE_NEW_TOKEN)659|| !PACKET_get_quic_vlint(pkt, &token_len_))660return 0;661662if (token_len_ > SIZE_MAX)663return 0;664665*token = PACKET_data(pkt);666*token_len = (size_t)token_len_;667668if (!PACKET_forward(pkt, (size_t)token_len_))669return 0;670671return 1;672}673674int ossl_quic_wire_decode_frame_stream(PACKET *pkt,675int nodata,676OSSL_QUIC_FRAME_STREAM *f)677{678uint64_t frame_type;679680/* This call matches all STREAM values (low 3 bits are masked). */681if (!expect_frame_header_mask(pkt, OSSL_QUIC_FRAME_TYPE_STREAM,682OSSL_QUIC_FRAME_FLAG_STREAM_MASK,683&frame_type)684|| !PACKET_get_quic_vlint(pkt, &f->stream_id))685return 0;686687if ((frame_type & OSSL_QUIC_FRAME_FLAG_STREAM_OFF) != 0) {688if (!PACKET_get_quic_vlint(pkt, &f->offset))689return 0;690} else {691f->offset = 0;692}693694f->has_explicit_len = ((frame_type & OSSL_QUIC_FRAME_FLAG_STREAM_LEN) != 0);695f->is_fin = ((frame_type & OSSL_QUIC_FRAME_FLAG_STREAM_FIN) != 0);696697if (f->has_explicit_len) {698if (!PACKET_get_quic_vlint(pkt, &f->len))699return 0;700} else {701if (nodata)702f->len = 0;703else704f->len = PACKET_remaining(pkt);705}706707/*708* RFC 9000 s. 19.8: "The largest offset delivered on a stream -- the sum of709* the offset and data length -- cannot exceed 2**62 - 1, as it is not710* possible to provide flow control credit for that data."711*/712if (f->offset + f->len > (((uint64_t)1) << 62) - 1)713return 0;714715if (nodata) {716f->data = NULL;717} else {718f->data = PACKET_data(pkt);719720if (f->len > SIZE_MAX /* sizeof(uint64_t) > sizeof(size_t)? */721|| !PACKET_forward(pkt, (size_t)f->len))722return 0;723}724725return 1;726}727728int ossl_quic_wire_decode_frame_max_data(PACKET *pkt,729uint64_t *max_data)730{731if (!expect_frame_header(pkt, OSSL_QUIC_FRAME_TYPE_MAX_DATA)732|| !PACKET_get_quic_vlint(pkt, max_data))733return 0;734735return 1;736}737738int ossl_quic_wire_decode_frame_max_stream_data(PACKET *pkt,739uint64_t *stream_id,740uint64_t *max_stream_data)741{742if (!expect_frame_header(pkt, OSSL_QUIC_FRAME_TYPE_MAX_STREAM_DATA)743|| !PACKET_get_quic_vlint(pkt, stream_id)744|| !PACKET_get_quic_vlint(pkt, max_stream_data))745return 0;746747return 1;748}749750int ossl_quic_wire_decode_frame_max_streams(PACKET *pkt,751uint64_t *max_streams)752{753/* This call matches both MAX_STREAMS_BIDI and MAX_STREAMS_UNI. */754if (!expect_frame_header_mask(pkt, OSSL_QUIC_FRAME_TYPE_MAX_STREAMS_BIDI,7551, NULL)756|| !PACKET_get_quic_vlint(pkt, max_streams))757return 0;758759return 1;760}761762int ossl_quic_wire_decode_frame_data_blocked(PACKET *pkt,763uint64_t *max_data)764{765if (!expect_frame_header(pkt, OSSL_QUIC_FRAME_TYPE_DATA_BLOCKED)766|| !PACKET_get_quic_vlint(pkt, max_data))767return 0;768769return 1;770}771772int ossl_quic_wire_decode_frame_stream_data_blocked(PACKET *pkt,773uint64_t *stream_id,774uint64_t *max_stream_data)775{776if (!expect_frame_header(pkt, OSSL_QUIC_FRAME_TYPE_STREAM_DATA_BLOCKED)777|| !PACKET_get_quic_vlint(pkt, stream_id)778|| !PACKET_get_quic_vlint(pkt, max_stream_data))779return 0;780781return 1;782}783784int ossl_quic_wire_decode_frame_streams_blocked(PACKET *pkt,785uint64_t *max_streams)786{787/* This call matches both STREAMS_BLOCKED_BIDI and STREAMS_BLOCKED_UNI. */788if (!expect_frame_header_mask(pkt, OSSL_QUIC_FRAME_TYPE_STREAMS_BLOCKED_BIDI,7891, NULL)790|| !PACKET_get_quic_vlint(pkt, max_streams))791return 0;792793return 1;794}795796int ossl_quic_wire_decode_frame_new_conn_id(PACKET *pkt,797OSSL_QUIC_FRAME_NEW_CONN_ID *f)798{799unsigned int len;800801if (!expect_frame_header(pkt, OSSL_QUIC_FRAME_TYPE_NEW_CONN_ID)802|| !PACKET_get_quic_vlint(pkt, &f->seq_num)803|| !PACKET_get_quic_vlint(pkt, &f->retire_prior_to)804|| f->seq_num < f->retire_prior_to805|| !PACKET_get_1(pkt, &len)806|| len < 1807|| len > QUIC_MAX_CONN_ID_LEN)808return 0;809810f->conn_id.id_len = (unsigned char)len;811if (!PACKET_copy_bytes(pkt, f->conn_id.id, len))812return 0;813814/* Clear unused bytes to allow consistent memcmp. */815if (len < QUIC_MAX_CONN_ID_LEN)816memset(f->conn_id.id + len, 0, QUIC_MAX_CONN_ID_LEN - len);817818if (!PACKET_copy_bytes(pkt, f->stateless_reset.token,819sizeof(f->stateless_reset.token)))820return 0;821822return 1;823}824825int ossl_quic_wire_decode_frame_retire_conn_id(PACKET *pkt,826uint64_t *seq_num)827{828if (!expect_frame_header(pkt, OSSL_QUIC_FRAME_TYPE_RETIRE_CONN_ID)829|| !PACKET_get_quic_vlint(pkt, seq_num))830return 0;831832return 1;833}834835int ossl_quic_wire_decode_frame_path_challenge(PACKET *pkt,836uint64_t *data)837{838if (!expect_frame_header(pkt, OSSL_QUIC_FRAME_TYPE_PATH_CHALLENGE)839|| !PACKET_get_net_8(pkt, data))840return 0;841842return 1;843}844845int ossl_quic_wire_decode_frame_path_response(PACKET *pkt,846uint64_t *data)847{848if (!expect_frame_header(pkt, OSSL_QUIC_FRAME_TYPE_PATH_RESPONSE)849|| !PACKET_get_net_8(pkt, data))850return 0;851852return 1;853}854855int ossl_quic_wire_decode_frame_conn_close(PACKET *pkt,856OSSL_QUIC_FRAME_CONN_CLOSE *f)857{858uint64_t frame_type, reason_len;859860/* This call matches both CONN_CLOSE_TRANSPORT and CONN_CLOSE_APP. */861if (!expect_frame_header_mask(pkt, OSSL_QUIC_FRAME_TYPE_CONN_CLOSE_TRANSPORT,8621, &frame_type)863|| !PACKET_get_quic_vlint(pkt, &f->error_code))864return 0;865866f->is_app = ((frame_type & 1) != 0);867868if (!f->is_app) {869if (!PACKET_get_quic_vlint(pkt, &f->frame_type))870return 0;871} else {872f->frame_type = 0;873}874875if (!PACKET_get_quic_vlint(pkt, &reason_len)876|| reason_len > SIZE_MAX)877return 0;878879if (!PACKET_get_bytes(pkt, (const unsigned char **)&f->reason,880(size_t)reason_len))881return 0;882883f->reason_len = (size_t)reason_len;884return 1;885}886887size_t ossl_quic_wire_decode_padding(PACKET *pkt)888{889const unsigned char *start = PACKET_data(pkt), *end = PACKET_end(pkt),890*p = start;891892while (p < end && *p == 0)893++p;894895if (!PACKET_forward(pkt, p - start))896return 0;897898return p - start;899}900901int ossl_quic_wire_decode_frame_ping(PACKET *pkt)902{903return expect_frame_header(pkt, OSSL_QUIC_FRAME_TYPE_PING);904}905906int ossl_quic_wire_decode_frame_handshake_done(PACKET *pkt)907{908return expect_frame_header(pkt, OSSL_QUIC_FRAME_TYPE_HANDSHAKE_DONE);909}910911int ossl_quic_wire_peek_transport_param(PACKET *pkt, uint64_t *id)912{913return PACKET_peek_quic_vlint(pkt, id);914}915916const unsigned char *ossl_quic_wire_decode_transport_param_bytes(PACKET *pkt,917uint64_t *id,918size_t *len)919{920uint64_t len_;921const unsigned char *b = NULL;922uint64_t id_;923924if (!PACKET_get_quic_vlint(pkt, &id_)925|| !PACKET_get_quic_vlint(pkt, &len_))926return NULL;927928if (len_ > SIZE_MAX929|| !PACKET_get_bytes(pkt, (const unsigned char **)&b, (size_t)len_))930return NULL;931932*len = (size_t)len_;933if (id != NULL)934*id = id_;935return b;936}937938int ossl_quic_wire_decode_transport_param_int(PACKET *pkt,939uint64_t *id,940uint64_t *value)941{942PACKET sub;943944sub.curr = ossl_quic_wire_decode_transport_param_bytes(pkt,945id, &sub.remaining);946if (sub.curr == NULL)947return 0;948949if (!PACKET_get_quic_vlint(&sub, value))950return 0;951952if (PACKET_remaining(&sub) > 0)953return 0;954955return 1;956}957958int ossl_quic_wire_decode_transport_param_cid(PACKET *pkt,959uint64_t *id,960QUIC_CONN_ID *cid)961{962const unsigned char *body;963size_t len = 0;964965body = ossl_quic_wire_decode_transport_param_bytes(pkt, id, &len);966if (body == NULL || len > QUIC_MAX_CONN_ID_LEN)967return 0;968969cid->id_len = (unsigned char)len;970memcpy(cid->id, body, cid->id_len);971return 1;972}973974int ossl_quic_wire_decode_transport_param_preferred_addr(PACKET *pkt,975QUIC_PREFERRED_ADDR *p)976{977const unsigned char *body;978uint64_t id;979size_t len = 0;980PACKET pkt2;981unsigned int ipv4_port, ipv6_port, cidl;982983body = ossl_quic_wire_decode_transport_param_bytes(pkt, &id, &len);984if (body == NULL985|| len < QUIC_MIN_ENCODED_PREFERRED_ADDR_LEN986|| len > QUIC_MAX_ENCODED_PREFERRED_ADDR_LEN987|| id != QUIC_TPARAM_PREFERRED_ADDR)988return 0;989990if (!PACKET_buf_init(&pkt2, body, len))991return 0;992993if (!PACKET_copy_bytes(&pkt2, p->ipv4, sizeof(p->ipv4))994|| !PACKET_get_net_2(&pkt2, &ipv4_port)995|| !PACKET_copy_bytes(&pkt2, p->ipv6, sizeof(p->ipv6))996|| !PACKET_get_net_2(&pkt2, &ipv6_port)997|| !PACKET_get_1(&pkt2, &cidl)998|| cidl > QUIC_MAX_CONN_ID_LEN999|| !PACKET_copy_bytes(&pkt2, p->cid.id, cidl)1000|| !PACKET_copy_bytes(&pkt2, p->stateless_reset.token,1001sizeof(p->stateless_reset.token)))1002return 0;10031004p->ipv4_port = (uint16_t)ipv4_port;1005p->ipv6_port = (uint16_t)ipv6_port;1006p->cid.id_len = (unsigned char)cidl;1007return 1;1008}10091010const char *1011ossl_quic_frame_type_to_string(uint64_t frame_type)1012{1013switch (frame_type) {1014#define X(name) case OSSL_QUIC_FRAME_TYPE_##name: return #name;1015X(PADDING)1016X(PING)1017X(ACK_WITHOUT_ECN)1018X(ACK_WITH_ECN)1019X(RESET_STREAM)1020X(STOP_SENDING)1021X(CRYPTO)1022X(NEW_TOKEN)1023X(MAX_DATA)1024X(MAX_STREAM_DATA)1025X(MAX_STREAMS_BIDI)1026X(MAX_STREAMS_UNI)1027X(DATA_BLOCKED)1028X(STREAM_DATA_BLOCKED)1029X(STREAMS_BLOCKED_BIDI)1030X(STREAMS_BLOCKED_UNI)1031X(NEW_CONN_ID)1032X(RETIRE_CONN_ID)1033X(PATH_CHALLENGE)1034X(PATH_RESPONSE)1035X(CONN_CLOSE_TRANSPORT)1036X(CONN_CLOSE_APP)1037X(HANDSHAKE_DONE)1038X(STREAM)1039X(STREAM_FIN)1040X(STREAM_LEN)1041X(STREAM_LEN_FIN)1042X(STREAM_OFF)1043X(STREAM_OFF_FIN)1044X(STREAM_OFF_LEN)1045X(STREAM_OFF_LEN_FIN)1046#undef X1047default:1048return NULL;1049}1050}10511052const char *ossl_quic_err_to_string(uint64_t error_code)1053{1054switch (error_code) {1055#define X(name) case OSSL_QUIC_ERR_##name: return #name;1056X(NO_ERROR)1057X(INTERNAL_ERROR)1058X(CONNECTION_REFUSED)1059X(FLOW_CONTROL_ERROR)1060X(STREAM_LIMIT_ERROR)1061X(STREAM_STATE_ERROR)1062X(FINAL_SIZE_ERROR)1063X(FRAME_ENCODING_ERROR)1064X(TRANSPORT_PARAMETER_ERROR)1065X(CONNECTION_ID_LIMIT_ERROR)1066X(PROTOCOL_VIOLATION)1067X(INVALID_TOKEN)1068X(APPLICATION_ERROR)1069X(CRYPTO_BUFFER_EXCEEDED)1070X(KEY_UPDATE_ERROR)1071X(AEAD_LIMIT_REACHED)1072X(NO_VIABLE_PATH)1073#undef X1074default:1075return NULL;1076}1077}107810791080