Path: blob/main/crypto/openssl/ssl/quic/quic_wire.c
107437 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_UNI : OSSL_QUIC_FRAME_TYPE_MAX_STREAMS_BIDI)276|| !WPACKET_quic_write_vlint(pkt, max_streams))277return 0;278279return 1;280}281282int ossl_quic_wire_encode_frame_data_blocked(WPACKET *pkt,283uint64_t max_data)284{285if (!encode_frame_hdr(pkt, OSSL_QUIC_FRAME_TYPE_DATA_BLOCKED)286|| !WPACKET_quic_write_vlint(pkt, max_data))287return 0;288289return 1;290}291292int ossl_quic_wire_encode_frame_stream_data_blocked(WPACKET *pkt,293uint64_t stream_id,294uint64_t max_stream_data)295{296if (!encode_frame_hdr(pkt, OSSL_QUIC_FRAME_TYPE_STREAM_DATA_BLOCKED)297|| !WPACKET_quic_write_vlint(pkt, stream_id)298|| !WPACKET_quic_write_vlint(pkt, max_stream_data))299return 0;300301return 1;302}303304int ossl_quic_wire_encode_frame_streams_blocked(WPACKET *pkt,305char is_uni,306uint64_t max_streams)307{308if (!encode_frame_hdr(pkt, is_uni ? OSSL_QUIC_FRAME_TYPE_STREAMS_BLOCKED_UNI : OSSL_QUIC_FRAME_TYPE_STREAMS_BLOCKED_BIDI)309|| !WPACKET_quic_write_vlint(pkt, max_streams))310return 0;311312return 1;313}314315int ossl_quic_wire_encode_frame_new_conn_id(WPACKET *pkt,316const OSSL_QUIC_FRAME_NEW_CONN_ID *f)317{318if (f->conn_id.id_len < 1319|| f->conn_id.id_len > QUIC_MAX_CONN_ID_LEN)320return 0;321322if (!encode_frame_hdr(pkt, OSSL_QUIC_FRAME_TYPE_NEW_CONN_ID)323|| !WPACKET_quic_write_vlint(pkt, f->seq_num)324|| !WPACKET_quic_write_vlint(pkt, f->retire_prior_to)325|| !WPACKET_put_bytes_u8(pkt, f->conn_id.id_len)326|| !WPACKET_memcpy(pkt, f->conn_id.id, f->conn_id.id_len)327|| !WPACKET_memcpy(pkt, f->stateless_reset.token,328sizeof(f->stateless_reset.token)))329return 0;330331return 1;332}333334int ossl_quic_wire_encode_frame_retire_conn_id(WPACKET *pkt,335uint64_t seq_num)336{337if (!encode_frame_hdr(pkt, OSSL_QUIC_FRAME_TYPE_RETIRE_CONN_ID)338|| !WPACKET_quic_write_vlint(pkt, seq_num))339return 0;340341return 1;342}343344int ossl_quic_wire_encode_frame_path_challenge(WPACKET *pkt,345uint64_t data)346{347if (!encode_frame_hdr(pkt, OSSL_QUIC_FRAME_TYPE_PATH_CHALLENGE)348|| !WPACKET_put_bytes_u64(pkt, data))349return 0;350351return 1;352}353354int ossl_quic_wire_encode_frame_path_response(WPACKET *pkt,355uint64_t data)356{357if (!encode_frame_hdr(pkt, OSSL_QUIC_FRAME_TYPE_PATH_RESPONSE)358|| !WPACKET_put_bytes_u64(pkt, data))359return 0;360361return 1;362}363364int ossl_quic_wire_encode_frame_conn_close(WPACKET *pkt,365const OSSL_QUIC_FRAME_CONN_CLOSE *f)366{367if (!encode_frame_hdr(pkt, f->is_app ? OSSL_QUIC_FRAME_TYPE_CONN_CLOSE_APP : OSSL_QUIC_FRAME_TYPE_CONN_CLOSE_TRANSPORT)368|| !WPACKET_quic_write_vlint(pkt, f->error_code))369return 0;370371/*372* RFC 9000 s. 19.19: The application-specific variant of CONNECTION_CLOSE373* (type 0x1d) does not include this field.374*/375if (!f->is_app && !WPACKET_quic_write_vlint(pkt, f->frame_type))376return 0;377378if (!WPACKET_quic_write_vlint(pkt, f->reason_len)379|| !WPACKET_memcpy(pkt, f->reason, f->reason_len))380return 0;381382return 1;383}384385int ossl_quic_wire_encode_frame_handshake_done(WPACKET *pkt)386{387return encode_frame_hdr(pkt, OSSL_QUIC_FRAME_TYPE_HANDSHAKE_DONE);388}389390unsigned char *ossl_quic_wire_encode_transport_param_bytes(WPACKET *pkt,391uint64_t id,392const unsigned char *value,393size_t value_len)394{395unsigned char *b = NULL;396397if (!WPACKET_quic_write_vlint(pkt, id)398|| !WPACKET_quic_write_vlint(pkt, value_len))399return NULL;400401if (value_len == 0)402b = WPACKET_get_curr(pkt);403else if (!WPACKET_allocate_bytes(pkt, value_len, (unsigned char **)&b))404return NULL;405406if (value != NULL)407memcpy(b, value, value_len);408409return b;410}411412int ossl_quic_wire_encode_transport_param_int(WPACKET *pkt,413uint64_t id,414uint64_t value)415{416if (!WPACKET_quic_write_vlint(pkt, id)417|| !WPACKET_quic_write_vlint(pkt, ossl_quic_vlint_encode_len(value))418|| !WPACKET_quic_write_vlint(pkt, value))419return 0;420421return 1;422}423424int ossl_quic_wire_encode_transport_param_cid(WPACKET *wpkt,425uint64_t id,426const QUIC_CONN_ID *cid)427{428if (cid->id_len > QUIC_MAX_CONN_ID_LEN)429return 0;430431if (ossl_quic_wire_encode_transport_param_bytes(wpkt, id,432cid->id,433cid->id_len)434== NULL)435return 0;436437return 1;438}439440/*441* QUIC Wire Format Decoding442* =========================443*/444int ossl_quic_wire_peek_frame_header(PACKET *pkt, uint64_t *type,445int *was_minimal)446{447return PACKET_peek_quic_vlint_ex(pkt, type, was_minimal);448}449450int ossl_quic_wire_skip_frame_header(PACKET *pkt, uint64_t *type)451{452return PACKET_get_quic_vlint(pkt, type);453}454455static int expect_frame_header_mask(PACKET *pkt,456uint64_t expected_frame_type,457uint64_t mask_bits,458uint64_t *actual_frame_type)459{460uint64_t actual_frame_type_;461462if (!ossl_quic_wire_skip_frame_header(pkt, &actual_frame_type_)463|| (actual_frame_type_ & ~mask_bits) != expected_frame_type)464return 0;465466if (actual_frame_type != NULL)467*actual_frame_type = actual_frame_type_;468469return 1;470}471472static int expect_frame_header(PACKET *pkt, uint64_t expected_frame_type)473{474uint64_t actual_frame_type;475476if (!ossl_quic_wire_skip_frame_header(pkt, &actual_frame_type)477|| actual_frame_type != expected_frame_type)478return 0;479480return 1;481}482483int ossl_quic_wire_peek_frame_ack_num_ranges(const PACKET *orig_pkt,484uint64_t *total_ranges)485{486PACKET pkt = *orig_pkt;487uint64_t ack_range_count, i;488489if (!expect_frame_header_mask(&pkt, OSSL_QUIC_FRAME_TYPE_ACK_WITHOUT_ECN,4901, NULL)491|| !PACKET_skip_quic_vlint(&pkt)492|| !PACKET_skip_quic_vlint(&pkt)493|| !PACKET_get_quic_vlint(&pkt, &ack_range_count))494return 0;495496/*497* Ensure the specified number of ack ranges listed in the ACK frame header498* actually are available in the frame data. This naturally bounds the499* number of ACK ranges which can be requested by the MDPL, and therefore by500* the MTU. This ensures we do not allocate memory for an excessive number501* of ACK ranges.502*/503for (i = 0; i < ack_range_count; ++i)504if (!PACKET_skip_quic_vlint(&pkt)505|| !PACKET_skip_quic_vlint(&pkt))506return 0;507508/* (cannot overflow because QUIC vlints can only encode up to 2**62-1) */509*total_ranges = ack_range_count + 1;510return 1;511}512513int ossl_quic_wire_decode_frame_ack(PACKET *pkt,514uint32_t ack_delay_exponent,515OSSL_QUIC_FRAME_ACK *ack,516uint64_t *total_ranges)517{518uint64_t frame_type, largest_ackd, ack_delay_raw;519uint64_t ack_range_count, first_ack_range, start, end, i;520521/* This call matches both ACK_WITHOUT_ECN and ACK_WITH_ECN. */522if (!expect_frame_header_mask(pkt, OSSL_QUIC_FRAME_TYPE_ACK_WITHOUT_ECN,5231, &frame_type)524|| !PACKET_get_quic_vlint(pkt, &largest_ackd)525|| !PACKET_get_quic_vlint(pkt, &ack_delay_raw)526|| !PACKET_get_quic_vlint(pkt, &ack_range_count)527|| !PACKET_get_quic_vlint(pkt, &first_ack_range))528return 0;529530if (first_ack_range > largest_ackd)531return 0;532533if (ack_range_count > SIZE_MAX /* sizeof(uint64_t) > sizeof(size_t)? */)534return 0;535536start = largest_ackd - first_ack_range;537538if (ack != NULL) {539int err = 0;540ack->delay_time541= ossl_time_multiply(ossl_ticks2time(OSSL_TIME_US),542safe_mul_uint64_t(ack_delay_raw,543(uint64_t)1 << ack_delay_exponent,544&err));545if (err)546ack->delay_time = ossl_time_infinite();547548if (ack->num_ack_ranges > 0) {549ack->ack_ranges[0].end = largest_ackd;550ack->ack_ranges[0].start = start;551}552}553554for (i = 0; i < ack_range_count; ++i) {555uint64_t gap, len;556557if (!PACKET_get_quic_vlint(pkt, &gap)558|| !PACKET_get_quic_vlint(pkt, &len))559return 0;560561end = start - gap - 2;562if (start < gap + 2 || len > end)563return 0;564565if (ack != NULL && i + 1 < ack->num_ack_ranges) {566ack->ack_ranges[i + 1].start = start = end - len;567ack->ack_ranges[i + 1].end = end;568}569}570571if (ack != NULL && ack_range_count + 1 < ack->num_ack_ranges)572ack->num_ack_ranges = (size_t)ack_range_count + 1;573574if (total_ranges != NULL)575*total_ranges = ack_range_count + 1;576577if (frame_type == OSSL_QUIC_FRAME_TYPE_ACK_WITH_ECN) {578uint64_t ect0, ect1, ecnce;579580if (!PACKET_get_quic_vlint(pkt, &ect0)581|| !PACKET_get_quic_vlint(pkt, &ect1)582|| !PACKET_get_quic_vlint(pkt, &ecnce))583return 0;584585if (ack != NULL) {586ack->ect0 = ect0;587ack->ect1 = ect1;588ack->ecnce = ecnce;589ack->ecn_present = 1;590}591} else if (ack != NULL) {592ack->ecn_present = 0;593}594595return 1;596}597598int ossl_quic_wire_decode_frame_reset_stream(PACKET *pkt,599OSSL_QUIC_FRAME_RESET_STREAM *f)600{601if (!expect_frame_header(pkt, OSSL_QUIC_FRAME_TYPE_RESET_STREAM)602|| !PACKET_get_quic_vlint(pkt, &f->stream_id)603|| !PACKET_get_quic_vlint(pkt, &f->app_error_code)604|| !PACKET_get_quic_vlint(pkt, &f->final_size))605return 0;606607return 1;608}609610int ossl_quic_wire_decode_frame_stop_sending(PACKET *pkt,611OSSL_QUIC_FRAME_STOP_SENDING *f)612{613if (!expect_frame_header(pkt, OSSL_QUIC_FRAME_TYPE_STOP_SENDING)614|| !PACKET_get_quic_vlint(pkt, &f->stream_id)615|| !PACKET_get_quic_vlint(pkt, &f->app_error_code))616return 0;617618return 1;619}620621int ossl_quic_wire_decode_frame_crypto(PACKET *pkt,622int nodata,623OSSL_QUIC_FRAME_CRYPTO *f)624{625if (!expect_frame_header(pkt, OSSL_QUIC_FRAME_TYPE_CRYPTO)626|| !PACKET_get_quic_vlint(pkt, &f->offset)627|| !PACKET_get_quic_vlint(pkt, &f->len)628|| f->len > SIZE_MAX /* sizeof(uint64_t) > sizeof(size_t)? */)629return 0;630631if (f->offset + f->len > (((uint64_t)1) << 62) - 1)632/* RFC 9000 s. 19.6 */633return 0;634635if (nodata) {636f->data = NULL;637} else {638if (PACKET_remaining(pkt) < f->len)639return 0;640641f->data = PACKET_data(pkt);642643if (!PACKET_forward(pkt, (size_t)f->len))644return 0;645}646647return 1;648}649650int ossl_quic_wire_decode_frame_new_token(PACKET *pkt,651const unsigned char **token,652size_t *token_len)653{654uint64_t token_len_;655656if (!expect_frame_header(pkt, OSSL_QUIC_FRAME_TYPE_NEW_TOKEN)657|| !PACKET_get_quic_vlint(pkt, &token_len_))658return 0;659660if (token_len_ > SIZE_MAX)661return 0;662663*token = PACKET_data(pkt);664*token_len = (size_t)token_len_;665666if (!PACKET_forward(pkt, (size_t)token_len_))667return 0;668669return 1;670}671672int ossl_quic_wire_decode_frame_stream(PACKET *pkt,673int nodata,674OSSL_QUIC_FRAME_STREAM *f)675{676uint64_t frame_type;677678/* This call matches all STREAM values (low 3 bits are masked). */679if (!expect_frame_header_mask(pkt, OSSL_QUIC_FRAME_TYPE_STREAM,680OSSL_QUIC_FRAME_FLAG_STREAM_MASK,681&frame_type)682|| !PACKET_get_quic_vlint(pkt, &f->stream_id))683return 0;684685if ((frame_type & OSSL_QUIC_FRAME_FLAG_STREAM_OFF) != 0) {686if (!PACKET_get_quic_vlint(pkt, &f->offset))687return 0;688} else {689f->offset = 0;690}691692f->has_explicit_len = ((frame_type & OSSL_QUIC_FRAME_FLAG_STREAM_LEN) != 0);693f->is_fin = ((frame_type & OSSL_QUIC_FRAME_FLAG_STREAM_FIN) != 0);694695if (f->has_explicit_len) {696if (!PACKET_get_quic_vlint(pkt, &f->len))697return 0;698} else {699if (nodata)700f->len = 0;701else702f->len = PACKET_remaining(pkt);703}704705/*706* RFC 9000 s. 19.8: "The largest offset delivered on a stream -- the sum of707* the offset and data length -- cannot exceed 2**62 - 1, as it is not708* possible to provide flow control credit for that data."709*/710if (f->offset + f->len > (((uint64_t)1) << 62) - 1)711return 0;712713if (nodata) {714f->data = NULL;715} else {716f->data = PACKET_data(pkt);717718if (f->len > SIZE_MAX /* sizeof(uint64_t) > sizeof(size_t)? */719|| !PACKET_forward(pkt, (size_t)f->len))720return 0;721}722723return 1;724}725726int ossl_quic_wire_decode_frame_max_data(PACKET *pkt,727uint64_t *max_data)728{729if (!expect_frame_header(pkt, OSSL_QUIC_FRAME_TYPE_MAX_DATA)730|| !PACKET_get_quic_vlint(pkt, max_data))731return 0;732733return 1;734}735736int ossl_quic_wire_decode_frame_max_stream_data(PACKET *pkt,737uint64_t *stream_id,738uint64_t *max_stream_data)739{740if (!expect_frame_header(pkt, OSSL_QUIC_FRAME_TYPE_MAX_STREAM_DATA)741|| !PACKET_get_quic_vlint(pkt, stream_id)742|| !PACKET_get_quic_vlint(pkt, max_stream_data))743return 0;744745return 1;746}747748int ossl_quic_wire_decode_frame_max_streams(PACKET *pkt,749uint64_t *max_streams)750{751/* This call matches both MAX_STREAMS_BIDI and MAX_STREAMS_UNI. */752if (!expect_frame_header_mask(pkt, OSSL_QUIC_FRAME_TYPE_MAX_STREAMS_BIDI,7531, NULL)754|| !PACKET_get_quic_vlint(pkt, max_streams))755return 0;756757return 1;758}759760int ossl_quic_wire_decode_frame_data_blocked(PACKET *pkt,761uint64_t *max_data)762{763if (!expect_frame_header(pkt, OSSL_QUIC_FRAME_TYPE_DATA_BLOCKED)764|| !PACKET_get_quic_vlint(pkt, max_data))765return 0;766767return 1;768}769770int ossl_quic_wire_decode_frame_stream_data_blocked(PACKET *pkt,771uint64_t *stream_id,772uint64_t *max_stream_data)773{774if (!expect_frame_header(pkt, OSSL_QUIC_FRAME_TYPE_STREAM_DATA_BLOCKED)775|| !PACKET_get_quic_vlint(pkt, stream_id)776|| !PACKET_get_quic_vlint(pkt, max_stream_data))777return 0;778779return 1;780}781782int ossl_quic_wire_decode_frame_streams_blocked(PACKET *pkt,783uint64_t *max_streams)784{785/* This call matches both STREAMS_BLOCKED_BIDI and STREAMS_BLOCKED_UNI. */786if (!expect_frame_header_mask(pkt, OSSL_QUIC_FRAME_TYPE_STREAMS_BLOCKED_BIDI,7871, NULL)788|| !PACKET_get_quic_vlint(pkt, max_streams))789return 0;790791return 1;792}793794int ossl_quic_wire_decode_frame_new_conn_id(PACKET *pkt,795OSSL_QUIC_FRAME_NEW_CONN_ID *f)796{797unsigned int len;798799if (!expect_frame_header(pkt, OSSL_QUIC_FRAME_TYPE_NEW_CONN_ID)800|| !PACKET_get_quic_vlint(pkt, &f->seq_num)801|| !PACKET_get_quic_vlint(pkt, &f->retire_prior_to)802|| f->seq_num < f->retire_prior_to803|| !PACKET_get_1(pkt, &len)804|| len < 1805|| len > QUIC_MAX_CONN_ID_LEN)806return 0;807808f->conn_id.id_len = (unsigned char)len;809if (!PACKET_copy_bytes(pkt, f->conn_id.id, len))810return 0;811812/* Clear unused bytes to allow consistent memcmp. */813if (len < QUIC_MAX_CONN_ID_LEN)814memset(f->conn_id.id + len, 0, QUIC_MAX_CONN_ID_LEN - len);815816if (!PACKET_copy_bytes(pkt, f->stateless_reset.token,817sizeof(f->stateless_reset.token)))818return 0;819820return 1;821}822823int ossl_quic_wire_decode_frame_retire_conn_id(PACKET *pkt,824uint64_t *seq_num)825{826if (!expect_frame_header(pkt, OSSL_QUIC_FRAME_TYPE_RETIRE_CONN_ID)827|| !PACKET_get_quic_vlint(pkt, seq_num))828return 0;829830return 1;831}832833int ossl_quic_wire_decode_frame_path_challenge(PACKET *pkt,834uint64_t *data)835{836if (!expect_frame_header(pkt, OSSL_QUIC_FRAME_TYPE_PATH_CHALLENGE)837|| !PACKET_get_net_8(pkt, data))838return 0;839840return 1;841}842843int ossl_quic_wire_decode_frame_path_response(PACKET *pkt,844uint64_t *data)845{846if (!expect_frame_header(pkt, OSSL_QUIC_FRAME_TYPE_PATH_RESPONSE)847|| !PACKET_get_net_8(pkt, data))848return 0;849850return 1;851}852853int ossl_quic_wire_decode_frame_conn_close(PACKET *pkt,854OSSL_QUIC_FRAME_CONN_CLOSE *f)855{856uint64_t frame_type, reason_len;857858/* This call matches both CONN_CLOSE_TRANSPORT and CONN_CLOSE_APP. */859if (!expect_frame_header_mask(pkt, OSSL_QUIC_FRAME_TYPE_CONN_CLOSE_TRANSPORT,8601, &frame_type)861|| !PACKET_get_quic_vlint(pkt, &f->error_code))862return 0;863864f->is_app = ((frame_type & 1) != 0);865866if (!f->is_app) {867if (!PACKET_get_quic_vlint(pkt, &f->frame_type))868return 0;869} else {870f->frame_type = 0;871}872873if (!PACKET_get_quic_vlint(pkt, &reason_len)874|| reason_len > SIZE_MAX)875return 0;876877if (!PACKET_get_bytes(pkt, (const unsigned char **)&f->reason,878(size_t)reason_len))879return 0;880881f->reason_len = (size_t)reason_len;882return 1;883}884885size_t ossl_quic_wire_decode_padding(PACKET *pkt)886{887const unsigned char *start = PACKET_data(pkt), *end = PACKET_end(pkt),888*p = start;889890while (p < end && *p == 0)891++p;892893if (!PACKET_forward(pkt, p - start))894return 0;895896return p - start;897}898899int ossl_quic_wire_decode_frame_ping(PACKET *pkt)900{901return expect_frame_header(pkt, OSSL_QUIC_FRAME_TYPE_PING);902}903904int ossl_quic_wire_decode_frame_handshake_done(PACKET *pkt)905{906return expect_frame_header(pkt, OSSL_QUIC_FRAME_TYPE_HANDSHAKE_DONE);907}908909int ossl_quic_wire_peek_transport_param(PACKET *pkt, uint64_t *id)910{911return PACKET_peek_quic_vlint(pkt, id);912}913914const unsigned char *ossl_quic_wire_decode_transport_param_bytes(PACKET *pkt,915uint64_t *id,916size_t *len)917{918uint64_t len_;919const unsigned char *b = NULL;920uint64_t id_;921922if (!PACKET_get_quic_vlint(pkt, &id_)923|| !PACKET_get_quic_vlint(pkt, &len_))924return NULL;925926if (len_ > SIZE_MAX927|| !PACKET_get_bytes(pkt, (const unsigned char **)&b, (size_t)len_))928return NULL;929930*len = (size_t)len_;931if (id != NULL)932*id = id_;933return b;934}935936int ossl_quic_wire_decode_transport_param_int(PACKET *pkt,937uint64_t *id,938uint64_t *value)939{940PACKET sub;941942sub.curr = ossl_quic_wire_decode_transport_param_bytes(pkt,943id, &sub.remaining);944if (sub.curr == NULL)945return 0;946947if (!PACKET_get_quic_vlint(&sub, value))948return 0;949950if (PACKET_remaining(&sub) > 0)951return 0;952953return 1;954}955956int ossl_quic_wire_decode_transport_param_cid(PACKET *pkt,957uint64_t *id,958QUIC_CONN_ID *cid)959{960const unsigned char *body;961size_t len = 0;962963body = ossl_quic_wire_decode_transport_param_bytes(pkt, id, &len);964if (body == NULL || len > QUIC_MAX_CONN_ID_LEN)965return 0;966967cid->id_len = (unsigned char)len;968memcpy(cid->id, body, cid->id_len);969return 1;970}971972int ossl_quic_wire_decode_transport_param_preferred_addr(PACKET *pkt,973QUIC_PREFERRED_ADDR *p)974{975const unsigned char *body;976uint64_t id;977size_t len = 0;978PACKET pkt2;979unsigned int ipv4_port, ipv6_port, cidl;980981body = ossl_quic_wire_decode_transport_param_bytes(pkt, &id, &len);982if (body == NULL983|| len < QUIC_MIN_ENCODED_PREFERRED_ADDR_LEN984|| len > QUIC_MAX_ENCODED_PREFERRED_ADDR_LEN985|| id != QUIC_TPARAM_PREFERRED_ADDR)986return 0;987988if (!PACKET_buf_init(&pkt2, body, len))989return 0;990991if (!PACKET_copy_bytes(&pkt2, p->ipv4, sizeof(p->ipv4))992|| !PACKET_get_net_2(&pkt2, &ipv4_port)993|| !PACKET_copy_bytes(&pkt2, p->ipv6, sizeof(p->ipv6))994|| !PACKET_get_net_2(&pkt2, &ipv6_port)995|| !PACKET_get_1(&pkt2, &cidl)996|| cidl > QUIC_MAX_CONN_ID_LEN997|| !PACKET_copy_bytes(&pkt2, p->cid.id, cidl)998|| !PACKET_copy_bytes(&pkt2, p->stateless_reset.token,999sizeof(p->stateless_reset.token)))1000return 0;10011002p->ipv4_port = (uint16_t)ipv4_port;1003p->ipv6_port = (uint16_t)ipv6_port;1004p->cid.id_len = (unsigned char)cidl;1005return 1;1006}10071008const char *1009ossl_quic_frame_type_to_string(uint64_t frame_type)1010{1011switch (frame_type) {1012#define X(name) \1013case OSSL_QUIC_FRAME_TYPE_##name: \1014return #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) \1056case OSSL_QUIC_ERR_##name: \1057return #name;1058X(NO_ERROR)1059X(INTERNAL_ERROR)1060X(CONNECTION_REFUSED)1061X(FLOW_CONTROL_ERROR)1062X(STREAM_LIMIT_ERROR)1063X(STREAM_STATE_ERROR)1064X(FINAL_SIZE_ERROR)1065X(FRAME_ENCODING_ERROR)1066X(TRANSPORT_PARAMETER_ERROR)1067X(CONNECTION_ID_LIMIT_ERROR)1068X(PROTOCOL_VIOLATION)1069X(INVALID_TOKEN)1070X(APPLICATION_ERROR)1071X(CRYPTO_BUFFER_EXCEEDED)1072X(KEY_UPDATE_ERROR)1073X(AEAD_LIMIT_REACHED)1074X(NO_VIABLE_PATH)1075#undef X1076default:1077return NULL;1078}1079}108010811082