Path: blob/main/crypto/openssl/ssl/quic/quic_channel.c
109934 views
/*1* Copyright 2022-2026 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/rand.h>10#include <openssl/err.h>11#include "internal/ssl_unwrap.h"12#include "internal/quic_channel.h"13#include "internal/quic_error.h"14#include "internal/quic_rx_depack.h"15#include "internal/quic_lcidm.h"16#include "internal/quic_srtm.h"17#include "internal/qlog_event_helpers.h"18#include "internal/quic_txp.h"19#include "internal/quic_tls.h"20#include "internal/quic_ssl.h"21#include "../ssl_local.h"22#include "quic_channel_local.h"23#include "quic_port_local.h"24#include "quic_engine_local.h"2526#define INIT_CRYPTO_RECV_BUF_LEN 1638427#define INIT_CRYPTO_SEND_BUF_LEN 1638428#define INIT_APP_BUF_LEN 81922930/*31* Interval before we force a PING to ensure NATs don't timeout. This is based32* on the lowest commonly seen value of 30 seconds as cited in RFC 9000 s.33* 10.1.2.34*/35#define MAX_NAT_INTERVAL (ossl_ms2time(25000))3637/*38* Our maximum ACK delay on the TX side. This is up to us to choose. Note that39* this could differ from QUIC_DEFAULT_MAX_DELAY in future as that is a protocol40* value which determines the value of the maximum ACK delay if the41* max_ack_delay transport parameter is not set.42*/43#define DEFAULT_MAX_ACK_DELAY QUIC_DEFAULT_MAX_ACK_DELAY4445DEFINE_LIST_OF_IMPL(ch, QUIC_CHANNEL);4647static void ch_save_err_state(QUIC_CHANNEL *ch);48static int ch_rx(QUIC_CHANNEL *ch, int channel_only, int *notify_other_threads);49static int ch_tx(QUIC_CHANNEL *ch, int *notify_other_threads);50static int ch_tick_tls(QUIC_CHANNEL *ch, int channel_only, int *notify_other_threads);51static void ch_rx_handle_packet(QUIC_CHANNEL *ch, int channel_only);52static OSSL_TIME ch_determine_next_tick_deadline(QUIC_CHANNEL *ch);53static int ch_retry(QUIC_CHANNEL *ch,54const unsigned char *retry_token,55size_t retry_token_len,56const QUIC_CONN_ID *retry_scid,57int drop_later_pn);58static int ch_restart(QUIC_CHANNEL *ch);5960static void ch_cleanup(QUIC_CHANNEL *ch);61static int ch_generate_transport_params(QUIC_CHANNEL *ch);62static int ch_on_transport_params(const unsigned char *params,63size_t params_len,64void *arg);65static int ch_on_handshake_alert(void *arg, unsigned char alert_code);66static int ch_on_handshake_complete(void *arg);67static int ch_on_handshake_yield_secret(uint32_t prot_level, int direction,68uint32_t suite_id, EVP_MD *md,69const unsigned char *secret,70size_t secret_len,71void *arg);72static int ch_on_crypto_recv_record(const unsigned char **buf,73size_t *bytes_read, void *arg);74static int ch_on_crypto_release_record(size_t bytes_read, void *arg);75static int crypto_ensure_empty(QUIC_RSTREAM *rstream);76static int ch_on_crypto_send(const unsigned char *buf, size_t buf_len,77size_t *consumed, void *arg);78static OSSL_TIME get_time(void *arg);79static uint64_t get_stream_limit(int uni, void *arg);80static int rx_late_validate(QUIC_PN pn, int pn_space, void *arg);81static void rxku_detected(QUIC_PN pn, void *arg);82static int ch_retry(QUIC_CHANNEL *ch,83const unsigned char *retry_token,84size_t retry_token_len,85const QUIC_CONN_ID *retry_scid,86int drop_later_pn);87static void ch_update_idle(QUIC_CHANNEL *ch);88static int ch_discard_el(QUIC_CHANNEL *ch,89uint32_t enc_level);90static void ch_on_idle_timeout(QUIC_CHANNEL *ch);91static void ch_update_idle(QUIC_CHANNEL *ch);92static void ch_update_ping_deadline(QUIC_CHANNEL *ch);93static void ch_on_terminating_timeout(QUIC_CHANNEL *ch);94static void ch_start_terminating(QUIC_CHANNEL *ch,95const QUIC_TERMINATE_CAUSE *tcause,96int force_immediate);97static void ch_on_txp_ack_tx(const OSSL_QUIC_FRAME_ACK *ack, uint32_t pn_space,98void *arg);99static void ch_record_state_transition(QUIC_CHANNEL *ch, uint32_t new_state);100101DEFINE_LHASH_OF_EX(QUIC_SRT_ELEM);102103QUIC_NEEDS_LOCK104static QLOG *ch_get_qlog(QUIC_CHANNEL *ch)105{106#ifndef OPENSSL_NO_QLOG107QLOG_TRACE_INFO qti = { 0 };108109if (ch->qlog != NULL)110return ch->qlog;111112if (!ch->use_qlog)113return NULL;114115if (ch->is_server && ch->init_dcid.id_len == 0)116return NULL;117118qti.odcid = ch->init_dcid;119qti.title = ch->qlog_title;120qti.description = NULL;121qti.group_id = NULL;122qti.is_server = ch->is_server;123qti.now_cb = get_time;124qti.now_cb_arg = ch;125if ((ch->qlog = ossl_qlog_new_from_env(&qti)) == NULL) {126ch->use_qlog = 0; /* don't try again */127return NULL;128}129130return ch->qlog;131#else132return NULL;133#endif134}135136QUIC_NEEDS_LOCK137static QLOG *ch_get_qlog_cb(void *arg)138{139QUIC_CHANNEL *ch = arg;140141return ch_get_qlog(ch);142}143144/*145* QUIC Channel Initialization and Teardown146* ========================================147*/148#define DEFAULT_INIT_CONN_RXFC_WND (768 * 1024)149#define DEFAULT_CONN_RXFC_MAX_WND_MUL 20150151#define DEFAULT_INIT_STREAM_RXFC_WND (512 * 1024)152#define DEFAULT_STREAM_RXFC_MAX_WND_MUL 12153154#define DEFAULT_INIT_CONN_MAX_STREAMS 100155156static int ch_init(QUIC_CHANNEL *ch)157{158OSSL_QUIC_TX_PACKETISER_ARGS txp_args = { 0 };159OSSL_QTX_ARGS qtx_args = { 0 };160OSSL_QRX_ARGS qrx_args = { 0 };161QUIC_TLS_ARGS tls_args = { 0 };162uint32_t pn_space;163size_t rx_short_dcid_len;164size_t tx_init_dcid_len;165166if (ch->port == NULL || ch->lcidm == NULL || ch->srtm == NULL)167goto err;168169rx_short_dcid_len = ossl_quic_port_get_rx_short_dcid_len(ch->port);170tx_init_dcid_len = ossl_quic_port_get_tx_init_dcid_len(ch->port);171172/* For clients, generate our initial DCID. */173if (!ch->is_server174&& !ossl_quic_gen_rand_conn_id(ch->port->engine->libctx, tx_init_dcid_len,175&ch->init_dcid))176goto err;177178/* We plug in a network write BIO to the QTX later when we get one. */179qtx_args.libctx = ch->port->engine->libctx;180qtx_args.get_qlog_cb = ch_get_qlog_cb;181qtx_args.get_qlog_cb_arg = ch;182qtx_args.mdpl = QUIC_MIN_INITIAL_DGRAM_LEN;183ch->rx_max_udp_payload_size = qtx_args.mdpl;184185ch->ping_deadline = ossl_time_infinite();186187ch->qtx = ossl_qtx_new(&qtx_args);188if (ch->qtx == NULL)189goto err;190191ch->txpim = ossl_quic_txpim_new();192if (ch->txpim == NULL)193goto err;194195ch->cfq = ossl_quic_cfq_new();196if (ch->cfq == NULL)197goto err;198199if (!ossl_quic_txfc_init(&ch->conn_txfc, NULL))200goto err;201202/*203* Note: The TP we transmit governs what the peer can transmit and thus204* applies to the RXFC.205*/206ch->tx_init_max_stream_data_bidi_local = DEFAULT_INIT_STREAM_RXFC_WND;207ch->tx_init_max_stream_data_bidi_remote = DEFAULT_INIT_STREAM_RXFC_WND;208ch->tx_init_max_stream_data_uni = DEFAULT_INIT_STREAM_RXFC_WND;209210if (!ossl_quic_rxfc_init(&ch->conn_rxfc, NULL,211DEFAULT_INIT_CONN_RXFC_WND,212DEFAULT_CONN_RXFC_MAX_WND_MUL * DEFAULT_INIT_CONN_RXFC_WND,213get_time, ch))214goto err;215216for (pn_space = QUIC_PN_SPACE_INITIAL; pn_space < QUIC_PN_SPACE_NUM; ++pn_space)217if (!ossl_quic_rxfc_init_standalone(&ch->crypto_rxfc[pn_space],218INIT_CRYPTO_RECV_BUF_LEN,219get_time, ch))220goto err;221222if (!ossl_quic_rxfc_init_standalone(&ch->max_streams_bidi_rxfc,223DEFAULT_INIT_CONN_MAX_STREAMS,224get_time, ch))225goto err;226227if (!ossl_quic_rxfc_init_standalone(&ch->max_streams_uni_rxfc,228DEFAULT_INIT_CONN_MAX_STREAMS,229get_time, ch))230goto err;231232if (!ossl_statm_init(&ch->statm))233goto err;234235ch->have_statm = 1;236ch->cc_method = &ossl_cc_newreno_method;237if ((ch->cc_data = ch->cc_method->new(get_time, ch)) == NULL)238goto err;239240if ((ch->ackm = ossl_ackm_new(get_time, ch, &ch->statm,241ch->cc_method, ch->cc_data,242ch->is_server))243== NULL)244goto err;245246if (!ossl_quic_stream_map_init(&ch->qsm, get_stream_limit, ch,247&ch->max_streams_bidi_rxfc,248&ch->max_streams_uni_rxfc,249ch->is_server))250goto err;251252ch->have_qsm = 1;253254if (!ch->is_server255&& !ossl_quic_lcidm_generate_initial(ch->lcidm, ch, &ch->init_scid))256goto err;257258txp_args.cur_scid = ch->init_scid;259txp_args.cur_dcid = ch->init_dcid;260txp_args.ack_delay_exponent = 3;261txp_args.qtx = ch->qtx;262txp_args.txpim = ch->txpim;263txp_args.cfq = ch->cfq;264txp_args.ackm = ch->ackm;265txp_args.qsm = &ch->qsm;266txp_args.conn_txfc = &ch->conn_txfc;267txp_args.conn_rxfc = &ch->conn_rxfc;268txp_args.max_streams_bidi_rxfc = &ch->max_streams_bidi_rxfc;269txp_args.max_streams_uni_rxfc = &ch->max_streams_uni_rxfc;270txp_args.cc_method = ch->cc_method;271txp_args.cc_data = ch->cc_data;272txp_args.now = get_time;273txp_args.now_arg = ch;274txp_args.get_qlog_cb = ch_get_qlog_cb;275txp_args.get_qlog_cb_arg = ch;276txp_args.protocol_version = QUIC_VERSION_1;277278for (pn_space = QUIC_PN_SPACE_INITIAL; pn_space < QUIC_PN_SPACE_NUM; ++pn_space) {279ch->crypto_send[pn_space] = ossl_quic_sstream_new(INIT_CRYPTO_SEND_BUF_LEN);280if (ch->crypto_send[pn_space] == NULL)281goto err;282283txp_args.crypto[pn_space] = ch->crypto_send[pn_space];284}285286ch->txp = ossl_quic_tx_packetiser_new(&txp_args);287if (ch->txp == NULL)288goto err;289290/* clients have no amplification limit, so are considered always valid */291if (!ch->is_server)292ossl_quic_tx_packetiser_set_validated(ch->txp);293294ossl_quic_tx_packetiser_set_ack_tx_cb(ch->txp, ch_on_txp_ack_tx, ch);295296/*297* qrx does not exist yet, then we must be dealing with client channel298* (QUIC connection initiator).299* If qrx exists already, then we are dealing with server channel which300* qrx gets created by port_default_packet_handler() before301* port_default_packet_handler() accepts connection and creates channel302* for it.303* The exception here is tserver which always creates channel,304* before the first packet is ever seen.305*/306if (ch->qrx == NULL && ch->is_tserver_ch == 0) {307/* we are regular client, create channel */308qrx_args.libctx = ch->port->engine->libctx;309qrx_args.demux = ch->port->demux;310qrx_args.short_conn_id_len = rx_short_dcid_len;311qrx_args.max_deferred = 32;312313if ((ch->qrx = ossl_qrx_new(&qrx_args)) == NULL)314goto err;315}316317if (ch->qrx != NULL) {318/*319* callbacks for channels associated with tserver's port320* are set up later when we call ossl_quic_channel_bind_qrx()321* in port_default_packet_handler()322*/323if (!ossl_qrx_set_late_validation_cb(ch->qrx,324rx_late_validate,325ch))326goto err;327328if (!ossl_qrx_set_key_update_cb(ch->qrx,329rxku_detected,330ch))331goto err;332}333334for (pn_space = QUIC_PN_SPACE_INITIAL; pn_space < QUIC_PN_SPACE_NUM; ++pn_space) {335ch->crypto_recv[pn_space] = ossl_quic_rstream_new(NULL, NULL, 0);336if (ch->crypto_recv[pn_space] == NULL)337goto err;338}339340/* Plug in the TLS handshake layer. */341tls_args.s = ch->tls;342tls_args.crypto_send_cb = ch_on_crypto_send;343tls_args.crypto_send_cb_arg = ch;344tls_args.crypto_recv_rcd_cb = ch_on_crypto_recv_record;345tls_args.crypto_recv_rcd_cb_arg = ch;346tls_args.crypto_release_rcd_cb = ch_on_crypto_release_record;347tls_args.crypto_release_rcd_cb_arg = ch;348tls_args.yield_secret_cb = ch_on_handshake_yield_secret;349tls_args.yield_secret_cb_arg = ch;350tls_args.got_transport_params_cb = ch_on_transport_params;351tls_args.got_transport_params_cb_arg = ch;352tls_args.handshake_complete_cb = ch_on_handshake_complete;353tls_args.handshake_complete_cb_arg = ch;354tls_args.alert_cb = ch_on_handshake_alert;355tls_args.alert_cb_arg = ch;356tls_args.is_server = ch->is_server;357tls_args.ossl_quic = 1;358359if ((ch->qtls = ossl_quic_tls_new(&tls_args)) == NULL)360goto err;361362ch->tx_max_ack_delay = DEFAULT_MAX_ACK_DELAY;363ch->rx_max_ack_delay = QUIC_DEFAULT_MAX_ACK_DELAY;364ch->rx_ack_delay_exp = QUIC_DEFAULT_ACK_DELAY_EXP;365ch->rx_active_conn_id_limit = QUIC_MIN_ACTIVE_CONN_ID_LIMIT;366ch->tx_enc_level = QUIC_ENC_LEVEL_INITIAL;367ch->rx_enc_level = QUIC_ENC_LEVEL_INITIAL;368ch->txku_threshold_override = UINT64_MAX;369370ch->max_idle_timeout_local_req = QUIC_DEFAULT_IDLE_TIMEOUT;371ch->max_idle_timeout_remote_req = 0;372ch->max_idle_timeout = ch->max_idle_timeout_local_req;373374ossl_ackm_set_tx_max_ack_delay(ch->ackm, ossl_ms2time(ch->tx_max_ack_delay));375ossl_ackm_set_rx_max_ack_delay(ch->ackm, ossl_ms2time(ch->rx_max_ack_delay));376377ch_update_idle(ch);378ossl_list_ch_insert_tail(&ch->port->channel_list, ch);379ch->on_port_list = 1;380return 1;381382err:383ch_cleanup(ch);384return 0;385}386387static void ch_cleanup(QUIC_CHANNEL *ch)388{389uint32_t pn_space;390391if (ch->ackm != NULL)392for (pn_space = QUIC_PN_SPACE_INITIAL;393pn_space < QUIC_PN_SPACE_NUM;394++pn_space)395ossl_ackm_on_pkt_space_discarded(ch->ackm, pn_space);396397ossl_quic_lcidm_cull(ch->lcidm, ch);398ossl_quic_srtm_cull(ch->srtm, ch);399ossl_quic_tx_packetiser_free(ch->txp);400ossl_quic_txpim_free(ch->txpim);401ossl_quic_cfq_free(ch->cfq);402ossl_qtx_free(ch->qtx);403if (ch->cc_data != NULL)404ch->cc_method->free(ch->cc_data);405if (ch->have_statm)406ossl_statm_destroy(&ch->statm);407ossl_ackm_free(ch->ackm);408409if (ch->have_qsm)410ossl_quic_stream_map_cleanup(&ch->qsm);411412for (pn_space = QUIC_PN_SPACE_INITIAL; pn_space < QUIC_PN_SPACE_NUM; ++pn_space) {413ossl_quic_sstream_free(ch->crypto_send[pn_space]);414ossl_quic_rstream_free(ch->crypto_recv[pn_space]);415}416417ossl_qrx_pkt_release(ch->qrx_pkt);418ch->qrx_pkt = NULL;419420ossl_quic_tls_free(ch->qtls);421ossl_qrx_free(ch->qrx);422OPENSSL_free(ch->local_transport_params);423OPENSSL_free((char *)ch->terminate_cause.reason);424OSSL_ERR_STATE_free(ch->err_state);425OPENSSL_free(ch->ack_range_scratch);426OPENSSL_free(ch->pending_new_token);427428if (ch->on_port_list) {429ossl_list_ch_remove(&ch->port->channel_list, ch);430ch->on_port_list = 0;431}432433#ifndef OPENSSL_NO_QLOG434if (ch->qlog != NULL)435ossl_qlog_flush(ch->qlog); /* best effort */436437OPENSSL_free(ch->qlog_title);438ossl_qlog_free(ch->qlog);439#endif440}441442int ossl_quic_channel_init(QUIC_CHANNEL *ch)443{444return ch_init(ch);445}446447void ossl_quic_channel_bind_qrx(QUIC_CHANNEL *tserver_ch, OSSL_QRX *qrx)448{449if (tserver_ch->qrx == NULL && tserver_ch->is_tserver_ch == 1) {450tserver_ch->qrx = qrx;451ossl_qrx_set_late_validation_cb(tserver_ch->qrx, rx_late_validate,452tserver_ch);453ossl_qrx_set_key_update_cb(tserver_ch->qrx, rxku_detected,454tserver_ch);455}456}457458QUIC_CHANNEL *ossl_quic_channel_alloc(const QUIC_CHANNEL_ARGS *args)459{460QUIC_CHANNEL *ch = NULL;461462if ((ch = OPENSSL_zalloc(sizeof(*ch))) == NULL)463return NULL;464465ch->port = args->port;466ch->is_server = args->is_server;467ch->tls = args->tls;468ch->lcidm = args->lcidm;469ch->srtm = args->srtm;470ch->qrx = args->qrx;471ch->is_tserver_ch = args->is_tserver_ch;472#ifndef OPENSSL_NO_QLOG473ch->use_qlog = args->use_qlog;474475if (ch->use_qlog && args->qlog_title != NULL) {476if ((ch->qlog_title = OPENSSL_strdup(args->qlog_title)) == NULL) {477OPENSSL_free(ch);478return NULL;479}480}481#endif482483return ch;484}485486void ossl_quic_channel_free(QUIC_CHANNEL *ch)487{488if (ch == NULL)489return;490491ch_cleanup(ch);492OPENSSL_free(ch);493}494495/* Set mutator callbacks for test framework support */496int ossl_quic_channel_set_mutator(QUIC_CHANNEL *ch,497ossl_mutate_packet_cb mutatecb,498ossl_finish_mutate_cb finishmutatecb,499void *mutatearg)500{501if (ch->qtx == NULL)502return 0;503504ossl_qtx_set_mutator(ch->qtx, mutatecb, finishmutatecb, mutatearg);505return 1;506}507508int ossl_quic_channel_get_peer_addr(QUIC_CHANNEL *ch, BIO_ADDR *peer_addr)509{510if (!ch->addressed_mode)511return 0;512513return BIO_ADDR_copy(peer_addr, &ch->cur_peer_addr);514}515516int ossl_quic_channel_set_peer_addr(QUIC_CHANNEL *ch, const BIO_ADDR *peer_addr)517{518if (ch->state != QUIC_CHANNEL_STATE_IDLE)519return 0;520521if (peer_addr == NULL || BIO_ADDR_family(peer_addr) == AF_UNSPEC) {522BIO_ADDR_clear(&ch->cur_peer_addr);523ch->addressed_mode = 0;524return 1;525}526527if (!BIO_ADDR_copy(&ch->cur_peer_addr, peer_addr)) {528ch->addressed_mode = 0;529return 0;530}531ch->addressed_mode = 1;532533return 1;534}535536QUIC_REACTOR *ossl_quic_channel_get_reactor(QUIC_CHANNEL *ch)537{538return ossl_quic_port_get0_reactor(ch->port);539}540541QUIC_STREAM_MAP *ossl_quic_channel_get_qsm(QUIC_CHANNEL *ch)542{543return &ch->qsm;544}545546OSSL_STATM *ossl_quic_channel_get_statm(QUIC_CHANNEL *ch)547{548return &ch->statm;549}550551SSL *ossl_quic_channel_get0_tls(QUIC_CHANNEL *ch)552{553return ch->tls;554}555556static void free_buf_mem(unsigned char *buf, size_t buf_len, void *arg)557{558BUF_MEM_free((BUF_MEM *)arg);559}560561int ossl_quic_channel_schedule_new_token(QUIC_CHANNEL *ch,562const unsigned char *token,563size_t token_len)564{565int rc = 0;566QUIC_CFQ_ITEM *cfq_item;567WPACKET wpkt;568BUF_MEM *buf_mem = NULL;569size_t l = 0;570571buf_mem = BUF_MEM_new();572if (buf_mem == NULL)573goto err;574575if (!WPACKET_init(&wpkt, buf_mem))576goto err;577578if (!ossl_quic_wire_encode_frame_new_token(&wpkt, token,579token_len)) {580WPACKET_cleanup(&wpkt);581goto err;582}583584WPACKET_finish(&wpkt);585586if (!WPACKET_get_total_written(&wpkt, &l))587goto err;588589cfq_item = ossl_quic_cfq_add_frame(ch->cfq, 1,590QUIC_PN_SPACE_APP,591OSSL_QUIC_FRAME_TYPE_NEW_TOKEN, 0,592(unsigned char *)buf_mem->data, l,593free_buf_mem,594buf_mem);595if (cfq_item == NULL)596goto err;597598rc = 1;599err:600if (!rc)601BUF_MEM_free(buf_mem);602return rc;603}604605size_t ossl_quic_channel_get_short_header_conn_id_len(QUIC_CHANNEL *ch)606{607return ossl_quic_port_get_rx_short_dcid_len(ch->port);608}609610QUIC_STREAM *ossl_quic_channel_get_stream_by_id(QUIC_CHANNEL *ch,611uint64_t stream_id)612{613return ossl_quic_stream_map_get_by_id(&ch->qsm, stream_id);614}615616int ossl_quic_channel_is_active(const QUIC_CHANNEL *ch)617{618return ch != NULL && ch->state == QUIC_CHANNEL_STATE_ACTIVE;619}620621int ossl_quic_channel_is_closing(const QUIC_CHANNEL *ch)622{623return ch->state == QUIC_CHANNEL_STATE_TERMINATING_CLOSING;624}625626static int ossl_quic_channel_is_draining(const QUIC_CHANNEL *ch)627{628return ch->state == QUIC_CHANNEL_STATE_TERMINATING_DRAINING;629}630631static int ossl_quic_channel_is_terminating(const QUIC_CHANNEL *ch)632{633return ossl_quic_channel_is_closing(ch)634|| ossl_quic_channel_is_draining(ch);635}636637int ossl_quic_channel_is_terminated(const QUIC_CHANNEL *ch)638{639return ch->state == QUIC_CHANNEL_STATE_TERMINATED;640}641642int ossl_quic_channel_is_term_any(const QUIC_CHANNEL *ch)643{644return ossl_quic_channel_is_terminating(ch)645|| ossl_quic_channel_is_terminated(ch);646}647648const QUIC_TERMINATE_CAUSE *649ossl_quic_channel_get_terminate_cause(const QUIC_CHANNEL *ch)650{651return ossl_quic_channel_is_term_any(ch) ? &ch->terminate_cause : NULL;652}653654int ossl_quic_channel_is_handshake_complete(const QUIC_CHANNEL *ch)655{656return ch->handshake_complete;657}658659int ossl_quic_channel_is_handshake_confirmed(const QUIC_CHANNEL *ch)660{661return ch->handshake_confirmed;662}663664QUIC_DEMUX *ossl_quic_channel_get0_demux(QUIC_CHANNEL *ch)665{666return ch->port->demux;667}668669QUIC_PORT *ossl_quic_channel_get0_port(QUIC_CHANNEL *ch)670{671return ch->port;672}673674QUIC_ENGINE *ossl_quic_channel_get0_engine(QUIC_CHANNEL *ch)675{676return ossl_quic_port_get0_engine(ch->port);677}678679CRYPTO_MUTEX *ossl_quic_channel_get_mutex(QUIC_CHANNEL *ch)680{681return ossl_quic_port_get0_mutex(ch->port);682}683684int ossl_quic_channel_has_pending(const QUIC_CHANNEL *ch)685{686return ossl_quic_demux_has_pending(ch->port->demux)687|| ossl_qrx_processed_read_pending(ch->qrx);688}689690/*691* QUIC Channel: Callbacks from Miscellaneous Subsidiary Components692* ================================================================693*/694695/* Used by various components. */696static OSSL_TIME get_time(void *arg)697{698QUIC_CHANNEL *ch = arg;699700return ossl_quic_port_get_time(ch->port);701}702703/* Used by QSM. */704static uint64_t get_stream_limit(int uni, void *arg)705{706QUIC_CHANNEL *ch = arg;707708return uni ? ch->max_local_streams_uni : ch->max_local_streams_bidi;709}710711/*712* Called by QRX to determine if a packet is potentially invalid before trying713* to decrypt it.714*/715static int rx_late_validate(QUIC_PN pn, int pn_space, void *arg)716{717QUIC_CHANNEL *ch = arg;718719/* Potential duplicates should not be processed. */720if (!ossl_ackm_is_rx_pn_processable(ch->ackm, pn, pn_space))721return 0;722723return 1;724}725726/*727* Triggers a TXKU (whether spontaneous or solicited). Does not check whether728* spontaneous TXKU is currently allowed.729*/730QUIC_NEEDS_LOCK731static void ch_trigger_txku(QUIC_CHANNEL *ch)732{733uint64_t next_pn734= ossl_quic_tx_packetiser_get_next_pn(ch->txp, QUIC_PN_SPACE_APP);735736if (!ossl_quic_pn_valid(next_pn)737|| !ossl_qtx_trigger_key_update(ch->qtx)) {738ossl_quic_channel_raise_protocol_error(ch, OSSL_QUIC_ERR_INTERNAL_ERROR, 0,739"key update");740return;741}742743ch->txku_in_progress = 1;744ch->txku_pn = next_pn;745ch->rxku_expected = ch->ku_locally_initiated;746}747748QUIC_NEEDS_LOCK749static int txku_in_progress(QUIC_CHANNEL *ch)750{751if (ch->txku_in_progress752&& ossl_ackm_get_largest_acked(ch->ackm, QUIC_PN_SPACE_APP) >= ch->txku_pn) {753OSSL_TIME pto = ossl_ackm_get_pto_duration(ch->ackm);754755/*756* RFC 9001 s. 6.5: Endpoints SHOULD wait three times the PTO before757* initiating a key update after receiving an acknowledgment that758* confirms that the previous key update was received.759*760* Note that by the above wording, this period starts from when we get761* the ack for a TXKU-triggering packet, not when the TXKU is initiated.762* So we defer TXKU cooldown deadline calculation to this point.763*/764ch->txku_in_progress = 0;765ch->txku_cooldown_deadline = ossl_time_add(get_time(ch),766ossl_time_multiply(pto, 3));767}768769return ch->txku_in_progress;770}771772QUIC_NEEDS_LOCK773static int txku_allowed(QUIC_CHANNEL *ch)774{775return ch->tx_enc_level == QUIC_ENC_LEVEL_1RTT /* Sanity check. */776/* Strict RFC 9001 criterion for TXKU. */777&& ch->handshake_confirmed778&& !txku_in_progress(ch);779}780781QUIC_NEEDS_LOCK782static int txku_recommendable(QUIC_CHANNEL *ch)783{784if (!txku_allowed(ch))785return 0;786787return788/* Recommended RFC 9001 criterion for TXKU. */789ossl_time_compare(get_time(ch), ch->txku_cooldown_deadline) >= 0790/* Some additional sensible criteria. */791&& !ch->rxku_in_progress792&& !ch->rxku_pending_confirm;793}794795QUIC_NEEDS_LOCK796static int txku_desirable(QUIC_CHANNEL *ch)797{798uint64_t cur_pkt_count, max_pkt_count, thresh_pkt_count;799const uint32_t enc_level = QUIC_ENC_LEVEL_1RTT;800801/* Check AEAD limit to determine if we should perform a spontaneous TXKU. */802cur_pkt_count = ossl_qtx_get_cur_epoch_pkt_count(ch->qtx, enc_level);803max_pkt_count = ossl_qtx_get_max_epoch_pkt_count(ch->qtx, enc_level);804805thresh_pkt_count = max_pkt_count / 2;806if (ch->txku_threshold_override != UINT64_MAX)807thresh_pkt_count = ch->txku_threshold_override;808809return cur_pkt_count >= thresh_pkt_count;810}811812QUIC_NEEDS_LOCK813static void ch_maybe_trigger_spontaneous_txku(QUIC_CHANNEL *ch)814{815if (!txku_recommendable(ch) || !txku_desirable(ch))816return;817818ch->ku_locally_initiated = 1;819ch_trigger_txku(ch);820}821822QUIC_NEEDS_LOCK823static int rxku_allowed(QUIC_CHANNEL *ch)824{825/*826* RFC 9001 s. 6.1: An endpoint MUST NOT initiate a key update prior to827* having confirmed the handshake (Section 4.1.2).828*829* RFC 9001 s. 6.1: An endpoint MUST NOT initiate a subsequent key update830* unless it has received an acknowledgment for a packet that was sent831* protected with keys from the current key phase.832*833* RFC 9001 s. 6.2: If an endpoint detects a second update before it has834* sent any packets with updated keys containing an acknowledgment for the835* packet that initiated the key update, it indicates that its peer has836* updated keys twice without awaiting confirmation. An endpoint MAY treat837* such consecutive key updates as a connection error of type838* KEY_UPDATE_ERROR.839*/840return ch->handshake_confirmed && !ch->rxku_pending_confirm;841}842843/*844* Called when the QRX detects a new RX key update event.845*/846enum rxku_decision {847DECISION_RXKU_ONLY,848DECISION_PROTOCOL_VIOLATION,849DECISION_SOLICITED_TXKU850};851852/* Called when the QRX detects a key update has occurred. */853QUIC_NEEDS_LOCK854static void rxku_detected(QUIC_PN pn, void *arg)855{856QUIC_CHANNEL *ch = arg;857enum rxku_decision decision;858OSSL_TIME pto;859860/*861* Note: rxku_in_progress is always 0 here as an RXKU cannot be detected862* when we are still in UPDATING or COOLDOWN (see quic_record_rx.h).863*/864assert(!ch->rxku_in_progress);865866if (!rxku_allowed(ch))867/* Is RXKU even allowed at this time? */868decision = DECISION_PROTOCOL_VIOLATION;869870else if (ch->ku_locally_initiated)871/*872* If this key update was locally initiated (meaning that this detected873* RXKU event is a result of our own spontaneous TXKU), we do not874* trigger another TXKU; after all, to do so would result in an infinite875* ping-pong of key updates. We still process it as an RXKU.876*/877decision = DECISION_RXKU_ONLY;878879else880/*881* Otherwise, a peer triggering a KU means we have to trigger a KU also.882*/883decision = DECISION_SOLICITED_TXKU;884885if (decision == DECISION_PROTOCOL_VIOLATION) {886ossl_quic_channel_raise_protocol_error(ch, OSSL_QUIC_ERR_KEY_UPDATE_ERROR,8870, "RX key update again too soon");888return;889}890891pto = ossl_ackm_get_pto_duration(ch->ackm);892893ch->ku_locally_initiated = 0;894ch->rxku_in_progress = 1;895ch->rxku_pending_confirm = 1;896ch->rxku_trigger_pn = pn;897ch->rxku_update_end_deadline = ossl_time_add(get_time(ch), pto);898ch->rxku_expected = 0;899900if (decision == DECISION_SOLICITED_TXKU)901/* NOT gated by usual txku_allowed() */902ch_trigger_txku(ch);903904/*905* Ordinarily, we only generate ACK when some ACK-eliciting frame has been906* received. In some cases, this may not occur for a long time, for example907* if transmission of application data is going in only one direction and908* nothing else is happening with the connection. However, since the peer909* cannot initiate a subsequent (spontaneous) TXKU until its prior910* (spontaneous or solicited) TXKU has completed - meaning that prior911* TXKU's trigger packet (or subsequent packet) has been acknowledged, this912* can lead to very long times before a TXKU is considered 'completed'.913* Optimise this by forcing ACK generation after triggering TXKU.914* (Basically, we consider a RXKU event something that is 'ACK-eliciting',915* which it more or less should be; it is necessarily separate from ordinary916* processing of ACK-eliciting frames as key update is not indicated via a917* frame.)918*/919ossl_quic_tx_packetiser_schedule_ack(ch->txp, QUIC_PN_SPACE_APP);920}921922/* Called per tick to handle RXKU timer events. */923QUIC_NEEDS_LOCK924static void ch_rxku_tick(QUIC_CHANNEL *ch)925{926if (!ch->rxku_in_progress927|| ossl_time_compare(get_time(ch), ch->rxku_update_end_deadline) < 0)928return;929930ch->rxku_update_end_deadline = ossl_time_infinite();931ch->rxku_in_progress = 0;932933if (!ossl_qrx_key_update_timeout(ch->qrx, /*normal=*/1))934ossl_quic_channel_raise_protocol_error(ch, OSSL_QUIC_ERR_INTERNAL_ERROR, 0,935"RXKU cooldown internal error");936}937938QUIC_NEEDS_LOCK939static void ch_on_txp_ack_tx(const OSSL_QUIC_FRAME_ACK *ack, uint32_t pn_space,940void *arg)941{942QUIC_CHANNEL *ch = arg;943944if (pn_space != QUIC_PN_SPACE_APP || !ch->rxku_pending_confirm945|| !ossl_quic_frame_ack_contains_pn(ack, ch->rxku_trigger_pn))946return;947948/*949* Defer clearing rxku_pending_confirm until TXP generate call returns950* successfully.951*/952ch->rxku_pending_confirm_done = 1;953}954955/*956* QUIC Channel: Handshake Layer Event Handling957* ============================================958*/959static int ch_on_crypto_send(const unsigned char *buf, size_t buf_len,960size_t *consumed, void *arg)961{962int ret;963QUIC_CHANNEL *ch = arg;964uint32_t enc_level = ch->tx_enc_level;965uint32_t pn_space = ossl_quic_enc_level_to_pn_space(enc_level);966QUIC_SSTREAM *sstream = ch->crypto_send[pn_space];967968if (!ossl_assert(sstream != NULL))969return 0;970971ret = ossl_quic_sstream_append(sstream, buf, buf_len, consumed);972return ret;973}974975static int crypto_ensure_empty(QUIC_RSTREAM *rstream)976{977size_t avail = 0;978int is_fin = 0;979980if (rstream == NULL)981return 1;982983if (!ossl_quic_rstream_available(rstream, &avail, &is_fin))984return 0;985986return avail == 0;987}988989static int ch_on_crypto_recv_record(const unsigned char **buf,990size_t *bytes_read, void *arg)991{992QUIC_CHANNEL *ch = arg;993QUIC_RSTREAM *rstream;994int is_fin = 0; /* crypto stream is never finished, so we don't use this */995uint32_t i;996997/*998* After we move to a later EL we must not allow our peer to send any new999* bytes in the crypto stream on a previous EL. Retransmissions of old bytes1000* are allowed.1001*1002* In practice we will only move to a new EL when we have consumed all bytes1003* which should be sent on the crypto stream at a previous EL. For example,1004* the Handshake EL should not be provisioned until we have completely1005* consumed a TLS 1.3 ServerHello. Thus when we provision an EL the output1006* of ossl_quic_rstream_available() should be 0 for all lower ELs. Thus if a1007* given EL is available we simply ensure we have not received any further1008* bytes at a lower EL.1009*/1010for (i = QUIC_ENC_LEVEL_INITIAL; i < ch->rx_enc_level; ++i)1011if (i != QUIC_ENC_LEVEL_0RTT && !crypto_ensure_empty(ch->crypto_recv[ossl_quic_enc_level_to_pn_space(i)])) {1012/* Protocol violation (RFC 9001 s. 4.1.3) */1013ossl_quic_channel_raise_protocol_error(ch, OSSL_QUIC_ERR_PROTOCOL_VIOLATION,1014OSSL_QUIC_FRAME_TYPE_CRYPTO,1015"crypto stream data in wrong EL");1016return 0;1017}10181019rstream = ch->crypto_recv[ossl_quic_enc_level_to_pn_space(ch->rx_enc_level)];1020if (rstream == NULL)1021return 0;10221023return ossl_quic_rstream_get_record(rstream, buf, bytes_read,1024&is_fin);1025}10261027static int ch_on_crypto_release_record(size_t bytes_read, void *arg)1028{1029QUIC_CHANNEL *ch = arg;1030QUIC_RSTREAM *rstream;1031OSSL_RTT_INFO rtt_info;1032uint32_t rx_pn_space = ossl_quic_enc_level_to_pn_space(ch->rx_enc_level);10331034rstream = ch->crypto_recv[rx_pn_space];1035if (rstream == NULL)1036return 0;10371038ossl_statm_get_rtt_info(ossl_quic_channel_get_statm(ch), &rtt_info);1039if (!ossl_quic_rxfc_on_retire(&ch->crypto_rxfc[rx_pn_space], bytes_read,1040rtt_info.smoothed_rtt))1041return 0;10421043return ossl_quic_rstream_release_record(rstream, bytes_read);1044}10451046static int ch_on_handshake_yield_secret(uint32_t prot_level, int direction,1047uint32_t suite_id, EVP_MD *md,1048const unsigned char *secret,1049size_t secret_len,1050void *arg)1051{1052QUIC_CHANNEL *ch = arg;1053uint32_t i;1054uint32_t enc_level;10551056/* Convert TLS protection level to QUIC encryption level */1057switch (prot_level) {1058case OSSL_RECORD_PROTECTION_LEVEL_EARLY:1059enc_level = QUIC_ENC_LEVEL_0RTT;1060break;10611062case OSSL_RECORD_PROTECTION_LEVEL_HANDSHAKE:1063enc_level = QUIC_ENC_LEVEL_HANDSHAKE;1064break;10651066case OSSL_RECORD_PROTECTION_LEVEL_APPLICATION:1067enc_level = QUIC_ENC_LEVEL_1RTT;1068break;10691070default:1071return 0;1072}10731074if (enc_level < QUIC_ENC_LEVEL_HANDSHAKE || enc_level >= QUIC_ENC_LEVEL_NUM)1075/* Invalid EL. */1076return 0;10771078if (direction) {1079/* TX */1080if (enc_level <= ch->tx_enc_level)1081/*1082* Does not make sense for us to try and provision an EL we have already1083* attained.1084*/1085return 0;10861087if (!ossl_qtx_provide_secret(ch->qtx, enc_level,1088suite_id, md,1089secret, secret_len))1090return 0;10911092ch->tx_enc_level = enc_level;1093} else {1094/* RX */1095if (enc_level <= ch->rx_enc_level)1096/*1097* Does not make sense for us to try and provision an EL we have already1098* attained.1099*/1100return 0;11011102/*1103* Ensure all crypto streams for previous ELs are now empty of available1104* data.1105*/1106for (i = QUIC_ENC_LEVEL_INITIAL; i < enc_level; ++i)1107if (!crypto_ensure_empty(ch->crypto_recv[ossl_quic_enc_level_to_pn_space(i)])) {1108/* Protocol violation (RFC 9001 s. 4.1.3) */1109ossl_quic_channel_raise_protocol_error(ch, OSSL_QUIC_ERR_PROTOCOL_VIOLATION,1110OSSL_QUIC_FRAME_TYPE_CRYPTO,1111"crypto stream data in wrong EL");1112return 0;1113}11141115if (!ossl_qrx_provide_secret(ch->qrx, enc_level,1116suite_id, md,1117secret, secret_len))1118return 0;11191120ch->have_new_rx_secret = 1;1121ch->rx_enc_level = enc_level;1122}11231124return 1;1125}11261127static int ch_on_handshake_complete(void *arg)1128{1129QUIC_CHANNEL *ch = arg;11301131if (!ossl_assert(!ch->handshake_complete))1132return 0; /* this should not happen twice */11331134if (!ossl_assert(ch->tx_enc_level == QUIC_ENC_LEVEL_1RTT))1135return 0;11361137/*1138* When handshake is complete, we no longer need to abide by the1139* 3x amplification limit, though we should be validated as soon1140* as we see a handshake key encrypted packet (see ossl_quic_handle_packet)1141*/1142ossl_quic_tx_packetiser_set_validated(ch->txp);11431144if (!ch->got_remote_transport_params) {1145/*1146* Was not a valid QUIC handshake if we did not get valid transport1147* params.1148*/1149ossl_quic_channel_raise_protocol_error(ch, OSSL_QUIC_ERR_CRYPTO_MISSING_EXT,1150OSSL_QUIC_FRAME_TYPE_CRYPTO,1151"no transport parameters received");1152return 0;1153}11541155/* Don't need transport parameters anymore. */1156OPENSSL_free(ch->local_transport_params);1157ch->local_transport_params = NULL;11581159/* Tell the QRX it can now process 1-RTT packets. */1160ossl_qrx_allow_1rtt_processing(ch->qrx);11611162/* Tell TXP the handshake is complete. */1163ossl_quic_tx_packetiser_notify_handshake_complete(ch->txp);11641165ch->handshake_complete = 1;11661167if (ch->pending_new_token != NULL) {1168/*1169* Note this is a best effort operation here1170* If scheduling a new token fails, the worst outcome is that1171* a client, not having received it, will just have to go through1172* an extra roundtrip on a subsequent connection via the retry frame1173* path, at which point we get another opportunity to schedule another1174* new token. As a result, we don't need to handle any errors here1175*/1176ossl_quic_channel_schedule_new_token(ch,1177ch->pending_new_token,1178ch->pending_new_token_len);1179OPENSSL_free(ch->pending_new_token);1180ch->pending_new_token = NULL;1181ch->pending_new_token_len = 0;1182}11831184if (ch->is_server) {1185/*1186* On the server, the handshake is confirmed as soon as it is complete.1187*/1188ossl_quic_channel_on_handshake_confirmed(ch);11891190ossl_quic_tx_packetiser_schedule_handshake_done(ch->txp);1191}11921193ch_record_state_transition(ch, ch->state);1194return 1;1195}11961197static int ch_on_handshake_alert(void *arg, unsigned char alert_code)1198{1199QUIC_CHANNEL *ch = arg;12001201/*1202* RFC 9001 s. 4.4: More specifically, servers MUST NOT send post-handshake1203* TLS CertificateRequest messages, and clients MUST treat receipt of such1204* messages as a connection error of type PROTOCOL_VIOLATION.1205*/1206if (alert_code == SSL_AD_UNEXPECTED_MESSAGE1207&& ch->handshake_complete1208&& ossl_quic_tls_is_cert_request(ch->qtls))1209ossl_quic_channel_raise_protocol_error(ch,1210OSSL_QUIC_ERR_PROTOCOL_VIOLATION,12110,1212"Post-handshake TLS "1213"CertificateRequest received");1214/*1215* RFC 9001 s. 4.6.1: Servers MUST NOT send the early_data extension with a1216* max_early_data_size field set to any value other than 0xffffffff. A1217* client MUST treat receipt of a NewSessionTicket that contains an1218* early_data extension with any other value as a connection error of type1219* PROTOCOL_VIOLATION.1220*/1221else if (alert_code == SSL_AD_ILLEGAL_PARAMETER1222&& ch->handshake_complete1223&& ossl_quic_tls_has_bad_max_early_data(ch->qtls))1224ossl_quic_channel_raise_protocol_error(ch,1225OSSL_QUIC_ERR_PROTOCOL_VIOLATION,12260,1227"Bad max_early_data received");1228else1229ossl_quic_channel_raise_protocol_error(ch,1230OSSL_QUIC_ERR_CRYPTO_ERR_BEGIN1231+ alert_code,12320, "handshake alert");12331234return 1;1235}12361237/*1238* QUIC Channel: Transport Parameter Handling1239* ==========================================1240*/12411242/*1243* Called by handshake layer when we receive QUIC Transport Parameters from the1244* peer. Note that these are not authenticated until the handshake is marked1245* as complete.1246*/1247#define TP_REASON_SERVER_ONLY(x) \1248x " may not be sent by a client"1249#define TP_REASON_DUP(x) \1250x " appears multiple times"1251#define TP_REASON_MALFORMED(x) \1252x " is malformed"1253#define TP_REASON_EXPECTED_VALUE(x) \1254x " does not match expected value"1255#define TP_REASON_NOT_RETRY(x) \1256x " sent when not performing a retry"1257#define TP_REASON_REQUIRED(x) \1258x " was not sent but is required"1259#define TP_REASON_INTERNAL_ERROR(x) \1260x " encountered internal error"12611262static void txfc_bump_cwm_bidi(QUIC_STREAM *s, void *arg)1263{1264if (!ossl_quic_stream_is_bidi(s)1265|| ossl_quic_stream_is_server_init(s))1266return;12671268ossl_quic_txfc_bump_cwm(&s->txfc, *(uint64_t *)arg);1269}12701271static void txfc_bump_cwm_uni(QUIC_STREAM *s, void *arg)1272{1273if (ossl_quic_stream_is_bidi(s)1274|| ossl_quic_stream_is_server_init(s))1275return;12761277ossl_quic_txfc_bump_cwm(&s->txfc, *(uint64_t *)arg);1278}12791280static void do_update(QUIC_STREAM *s, void *arg)1281{1282QUIC_CHANNEL *ch = arg;12831284ossl_quic_stream_map_update_state(&ch->qsm, s);1285}12861287static uint64_t min_u64_ignore_0(uint64_t a, uint64_t b)1288{1289if (a == 0)1290return b;1291if (b == 0)1292return a;12931294return a < b ? a : b;1295}12961297static int ch_on_transport_params(const unsigned char *params,1298size_t params_len,1299void *arg)1300{1301QUIC_CHANNEL *ch = arg;1302PACKET pkt;1303uint64_t id, v;1304size_t len;1305const unsigned char *body;1306int got_orig_dcid = 0;1307int got_initial_scid = 0;1308int got_retry_scid = 0;1309int got_initial_max_data = 0;1310int got_initial_max_stream_data_bidi_local = 0;1311int got_initial_max_stream_data_bidi_remote = 0;1312int got_initial_max_stream_data_uni = 0;1313int got_initial_max_streams_bidi = 0;1314int got_initial_max_streams_uni = 0;1315int got_stateless_reset_token = 0;1316int got_preferred_addr = 0;1317int got_ack_delay_exp = 0;1318int got_max_ack_delay = 0;1319int got_max_udp_payload_size = 0;1320int got_max_idle_timeout = 0;1321int got_active_conn_id_limit = 0;1322int got_disable_active_migration = 0;1323QUIC_CONN_ID cid;1324const char *reason = "bad transport parameter";1325ossl_unused uint64_t rx_max_idle_timeout = 0;1326ossl_unused const void *stateless_reset_token_p = NULL;1327QUIC_PREFERRED_ADDR pfa;1328SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(ch->tls);13291330/*1331* When HRR happens the client sends the transport params in the new client1332* hello again. Reset the transport params here and load them again.1333*/1334if (ch->is_server && sc->hello_retry_request != SSL_HRR_NONE1335&& ch->got_remote_transport_params) {1336ch->max_local_streams_bidi = 0;1337ch->max_local_streams_uni = 0;1338ch->got_local_transport_params = 0;1339OPENSSL_free(ch->local_transport_params);1340ch->local_transport_params = NULL;1341} else if (ch->got_remote_transport_params) {1342reason = "multiple transport parameter extensions";1343goto malformed;1344}13451346if (!PACKET_buf_init(&pkt, params, params_len)) {1347ossl_quic_channel_raise_protocol_error(ch, OSSL_QUIC_ERR_INTERNAL_ERROR, 0,1348"internal error (packet buf init)");1349return 0;1350}13511352while (PACKET_remaining(&pkt) > 0) {1353if (!ossl_quic_wire_peek_transport_param(&pkt, &id))1354goto malformed;13551356switch (id) {1357case QUIC_TPARAM_ORIG_DCID:1358if (got_orig_dcid) {1359reason = TP_REASON_DUP("ORIG_DCID");1360goto malformed;1361}13621363if (ch->is_server) {1364reason = TP_REASON_SERVER_ONLY("ORIG_DCID");1365goto malformed;1366}13671368if (!ossl_quic_wire_decode_transport_param_cid(&pkt, NULL, &cid)) {1369reason = TP_REASON_MALFORMED("ORIG_DCID");1370goto malformed;1371}13721373#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION1374/* Must match our initial DCID. */1375if (!ossl_quic_conn_id_eq(&ch->init_dcid, &cid)) {1376reason = TP_REASON_EXPECTED_VALUE("ORIG_DCID");1377goto malformed;1378}1379#endif13801381got_orig_dcid = 1;1382break;13831384case QUIC_TPARAM_RETRY_SCID:1385if (ch->is_server) {1386reason = TP_REASON_SERVER_ONLY("RETRY_SCID");1387goto malformed;1388}13891390if (got_retry_scid) {1391reason = TP_REASON_DUP("RETRY_SCID");1392goto malformed;1393}13941395if (!ch->doing_retry) {1396reason = TP_REASON_NOT_RETRY("RETRY_SCID");1397goto malformed;1398}13991400if (!ossl_quic_wire_decode_transport_param_cid(&pkt, NULL, &cid)) {1401reason = TP_REASON_MALFORMED("RETRY_SCID");1402goto malformed;1403}14041405/* Must match Retry packet SCID. */1406if (!ossl_quic_conn_id_eq(&ch->retry_scid, &cid)) {1407reason = TP_REASON_EXPECTED_VALUE("RETRY_SCID");1408goto malformed;1409}14101411got_retry_scid = 1;1412break;14131414case QUIC_TPARAM_INITIAL_SCID:1415if (got_initial_scid) {1416/* must not appear more than once */1417reason = TP_REASON_DUP("INITIAL_SCID");1418goto malformed;1419}14201421if (!ossl_quic_wire_decode_transport_param_cid(&pkt, NULL, &cid)) {1422reason = TP_REASON_MALFORMED("INITIAL_SCID");1423goto malformed;1424}14251426if (!ossl_quic_conn_id_eq(&ch->init_scid, &cid)) {1427reason = TP_REASON_EXPECTED_VALUE("INITIAL_SCID");1428goto malformed;1429}14301431got_initial_scid = 1;1432break;14331434case QUIC_TPARAM_INITIAL_MAX_DATA:1435if (got_initial_max_data) {1436/* must not appear more than once */1437reason = TP_REASON_DUP("INITIAL_MAX_DATA");1438goto malformed;1439}14401441if (!ossl_quic_wire_decode_transport_param_int(&pkt, &id, &v)) {1442reason = TP_REASON_MALFORMED("INITIAL_MAX_DATA");1443goto malformed;1444}14451446ossl_quic_txfc_bump_cwm(&ch->conn_txfc, v);1447got_initial_max_data = 1;1448break;14491450case QUIC_TPARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL:1451if (got_initial_max_stream_data_bidi_local) {1452/* must not appear more than once */1453reason = TP_REASON_DUP("INITIAL_MAX_STREAM_DATA_BIDI_LOCAL");1454goto malformed;1455}14561457if (!ossl_quic_wire_decode_transport_param_int(&pkt, &id, &v)) {1458reason = TP_REASON_MALFORMED("INITIAL_MAX_STREAM_DATA_BIDI_LOCAL");1459goto malformed;1460}14611462/*1463* This is correct; the BIDI_LOCAL TP governs streams created by1464* the endpoint which sends the TP, i.e., our peer.1465*/1466ch->rx_init_max_stream_data_bidi_remote = v;1467got_initial_max_stream_data_bidi_local = 1;1468break;14691470case QUIC_TPARAM_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE:1471if (got_initial_max_stream_data_bidi_remote) {1472/* must not appear more than once */1473reason = TP_REASON_DUP("INITIAL_MAX_STREAM_DATA_BIDI_REMOTE");1474goto malformed;1475}14761477if (!ossl_quic_wire_decode_transport_param_int(&pkt, &id, &v)) {1478reason = TP_REASON_MALFORMED("INITIAL_MAX_STREAM_DATA_BIDI_REMOTE");1479goto malformed;1480}14811482/*1483* This is correct; the BIDI_REMOTE TP governs streams created1484* by the endpoint which receives the TP, i.e., us.1485*/1486ch->rx_init_max_stream_data_bidi_local = v;14871488/* Apply to all existing streams. */1489ossl_quic_stream_map_visit(&ch->qsm, txfc_bump_cwm_bidi, &v);1490got_initial_max_stream_data_bidi_remote = 1;1491break;14921493case QUIC_TPARAM_INITIAL_MAX_STREAM_DATA_UNI:1494if (got_initial_max_stream_data_uni) {1495/* must not appear more than once */1496reason = TP_REASON_DUP("INITIAL_MAX_STREAM_DATA_UNI");1497goto malformed;1498}14991500if (!ossl_quic_wire_decode_transport_param_int(&pkt, &id, &v)) {1501reason = TP_REASON_MALFORMED("INITIAL_MAX_STREAM_DATA_UNI");1502goto malformed;1503}15041505ch->rx_init_max_stream_data_uni = v;15061507/* Apply to all existing streams. */1508ossl_quic_stream_map_visit(&ch->qsm, txfc_bump_cwm_uni, &v);1509got_initial_max_stream_data_uni = 1;1510break;15111512case QUIC_TPARAM_ACK_DELAY_EXP:1513if (got_ack_delay_exp) {1514/* must not appear more than once */1515reason = TP_REASON_DUP("ACK_DELAY_EXP");1516goto malformed;1517}15181519if (!ossl_quic_wire_decode_transport_param_int(&pkt, &id, &v)1520|| v > QUIC_MAX_ACK_DELAY_EXP) {1521reason = TP_REASON_MALFORMED("ACK_DELAY_EXP");1522goto malformed;1523}15241525ch->rx_ack_delay_exp = (unsigned char)v;1526got_ack_delay_exp = 1;1527break;15281529case QUIC_TPARAM_MAX_ACK_DELAY:1530if (got_max_ack_delay) {1531/* must not appear more than once */1532reason = TP_REASON_DUP("MAX_ACK_DELAY");1533goto malformed;1534}15351536if (!ossl_quic_wire_decode_transport_param_int(&pkt, &id, &v)1537|| v >= (((uint64_t)1) << 14)) {1538reason = TP_REASON_MALFORMED("MAX_ACK_DELAY");1539goto malformed;1540}15411542ch->rx_max_ack_delay = v;1543ossl_ackm_set_rx_max_ack_delay(ch->ackm,1544ossl_ms2time(ch->rx_max_ack_delay));15451546got_max_ack_delay = 1;1547break;15481549case QUIC_TPARAM_INITIAL_MAX_STREAMS_BIDI:1550if (got_initial_max_streams_bidi) {1551/* must not appear more than once */1552reason = TP_REASON_DUP("INITIAL_MAX_STREAMS_BIDI");1553goto malformed;1554}15551556if (!ossl_quic_wire_decode_transport_param_int(&pkt, &id, &v)1557|| v > (((uint64_t)1) << 60)) {1558reason = TP_REASON_MALFORMED("INITIAL_MAX_STREAMS_BIDI");1559goto malformed;1560}15611562assert(ch->max_local_streams_bidi == 0);1563ch->max_local_streams_bidi = v;1564got_initial_max_streams_bidi = 1;1565break;15661567case QUIC_TPARAM_INITIAL_MAX_STREAMS_UNI:1568if (got_initial_max_streams_uni) {1569/* must not appear more than once */1570reason = TP_REASON_DUP("INITIAL_MAX_STREAMS_UNI");1571goto malformed;1572}15731574if (!ossl_quic_wire_decode_transport_param_int(&pkt, &id, &v)1575|| v > (((uint64_t)1) << 60)) {1576reason = TP_REASON_MALFORMED("INITIAL_MAX_STREAMS_UNI");1577goto malformed;1578}15791580assert(ch->max_local_streams_uni == 0);1581ch->max_local_streams_uni = v;1582got_initial_max_streams_uni = 1;1583break;15841585case QUIC_TPARAM_MAX_IDLE_TIMEOUT:1586if (got_max_idle_timeout) {1587/* must not appear more than once */1588reason = TP_REASON_DUP("MAX_IDLE_TIMEOUT");1589goto malformed;1590}15911592if (!ossl_quic_wire_decode_transport_param_int(&pkt, &id, &v)) {1593reason = TP_REASON_MALFORMED("MAX_IDLE_TIMEOUT");1594goto malformed;1595}15961597ch->max_idle_timeout_remote_req = v;15981599ch->max_idle_timeout = min_u64_ignore_0(ch->max_idle_timeout_local_req,1600ch->max_idle_timeout_remote_req);16011602ch_update_idle(ch);1603got_max_idle_timeout = 1;1604rx_max_idle_timeout = v;1605break;16061607case QUIC_TPARAM_MAX_UDP_PAYLOAD_SIZE:1608if (got_max_udp_payload_size) {1609/* must not appear more than once */1610reason = TP_REASON_DUP("MAX_UDP_PAYLOAD_SIZE");1611goto malformed;1612}16131614if (!ossl_quic_wire_decode_transport_param_int(&pkt, &id, &v)1615|| v < QUIC_MIN_INITIAL_DGRAM_LEN) {1616reason = TP_REASON_MALFORMED("MAX_UDP_PAYLOAD_SIZE");1617goto malformed;1618}16191620ch->rx_max_udp_payload_size = v;1621got_max_udp_payload_size = 1;1622break;16231624case QUIC_TPARAM_ACTIVE_CONN_ID_LIMIT:1625if (got_active_conn_id_limit) {1626/* must not appear more than once */1627reason = TP_REASON_DUP("ACTIVE_CONN_ID_LIMIT");1628goto malformed;1629}16301631if (!ossl_quic_wire_decode_transport_param_int(&pkt, &id, &v)1632|| v < QUIC_MIN_ACTIVE_CONN_ID_LIMIT) {1633reason = TP_REASON_MALFORMED("ACTIVE_CONN_ID_LIMIT");1634goto malformed;1635}16361637ch->rx_active_conn_id_limit = v;1638got_active_conn_id_limit = 1;1639break;16401641case QUIC_TPARAM_STATELESS_RESET_TOKEN:1642if (got_stateless_reset_token) {1643reason = TP_REASON_DUP("STATELESS_RESET_TOKEN");1644goto malformed;1645}16461647/*1648* RFC 9000 s. 18.2: This transport parameter MUST NOT be sent1649* by a client but MAY be sent by a server.1650*/1651if (ch->is_server) {1652reason = TP_REASON_SERVER_ONLY("STATELESS_RESET_TOKEN");1653goto malformed;1654}16551656body = ossl_quic_wire_decode_transport_param_bytes(&pkt, &id, &len);1657if (body == NULL || len != QUIC_STATELESS_RESET_TOKEN_LEN) {1658reason = TP_REASON_MALFORMED("STATELESS_RESET_TOKEN");1659goto malformed;1660}1661if (!ossl_quic_srtm_add(ch->srtm, ch, ch->cur_remote_seq_num,1662(const QUIC_STATELESS_RESET_TOKEN *)body)) {1663reason = TP_REASON_INTERNAL_ERROR("STATELESS_RESET_TOKEN");1664goto malformed;1665}16661667stateless_reset_token_p = body;1668got_stateless_reset_token = 1;1669break;16701671case QUIC_TPARAM_PREFERRED_ADDR:1672/* TODO(QUIC FUTURE): Handle preferred address. */1673if (got_preferred_addr) {1674reason = TP_REASON_DUP("PREFERRED_ADDR");1675goto malformed;1676}16771678/*1679* RFC 9000 s. 18.2: "A server that chooses a zero-length1680* connection ID MUST NOT provide a preferred address.1681* Similarly, a server MUST NOT include a zero-length connection1682* ID in this transport parameter. A client MUST treat a1683* violation of these requirements as a connection error of type1684* TRANSPORT_PARAMETER_ERROR."1685*/1686if (ch->is_server) {1687reason = TP_REASON_SERVER_ONLY("PREFERRED_ADDR");1688goto malformed;1689}16901691if (ch->cur_remote_dcid.id_len == 0) {1692reason = "PREFERRED_ADDR provided for zero-length CID";1693goto malformed;1694}16951696if (!ossl_quic_wire_decode_transport_param_preferred_addr(&pkt, &pfa)) {1697reason = TP_REASON_MALFORMED("PREFERRED_ADDR");1698goto malformed;1699}17001701if (pfa.cid.id_len == 0) {1702reason = "zero-length CID in PREFERRED_ADDR";1703goto malformed;1704}17051706got_preferred_addr = 1;1707break;17081709case QUIC_TPARAM_DISABLE_ACTIVE_MIGRATION:1710/* We do not currently handle migration, so nothing to do. */1711if (got_disable_active_migration) {1712/* must not appear more than once */1713reason = TP_REASON_DUP("DISABLE_ACTIVE_MIGRATION");1714goto malformed;1715}17161717body = ossl_quic_wire_decode_transport_param_bytes(&pkt, &id, &len);1718if (body == NULL || len > 0) {1719reason = TP_REASON_MALFORMED("DISABLE_ACTIVE_MIGRATION");1720goto malformed;1721}17221723got_disable_active_migration = 1;1724break;17251726default:1727/*1728* Skip over and ignore.1729*1730* RFC 9000 s. 7.4: We SHOULD treat duplicated transport parameters1731* as a connection error, but we are not required to. Currently,1732* handle this programmatically by checking for duplicates in the1733* parameters that we recognise, as above, but don't bother1734* maintaining a list of duplicates for anything we don't recognise.1735*/1736body = ossl_quic_wire_decode_transport_param_bytes(&pkt, &id,1737&len);1738if (body == NULL)1739goto malformed;17401741break;1742}1743}17441745if (!got_initial_scid) {1746reason = TP_REASON_REQUIRED("INITIAL_SCID");1747goto malformed;1748}17491750if (!ch->is_server) {1751if (!got_orig_dcid) {1752reason = TP_REASON_REQUIRED("ORIG_DCID");1753goto malformed;1754}17551756if (ch->doing_retry && !got_retry_scid) {1757reason = TP_REASON_REQUIRED("RETRY_SCID");1758goto malformed;1759}1760}17611762ch->got_remote_transport_params = 1;17631764#ifndef OPENSSL_NO_QLOG1765QLOG_EVENT_BEGIN(ch_get_qlog(ch), transport, parameters_set)1766QLOG_STR("owner", "remote");17671768if (got_orig_dcid)1769QLOG_CID("original_destination_connection_id",1770&ch->init_dcid);1771if (got_initial_scid)1772QLOG_CID("original_source_connection_id",1773&ch->init_dcid);1774if (got_retry_scid)1775QLOG_CID("retry_source_connection_id",1776&ch->retry_scid);1777if (got_initial_max_data)1778QLOG_U64("initial_max_data",1779ossl_quic_txfc_get_cwm(&ch->conn_txfc));1780if (got_initial_max_stream_data_bidi_local)1781QLOG_U64("initial_max_stream_data_bidi_local",1782ch->rx_init_max_stream_data_bidi_local);1783if (got_initial_max_stream_data_bidi_remote)1784QLOG_U64("initial_max_stream_data_bidi_remote",1785ch->rx_init_max_stream_data_bidi_remote);1786if (got_initial_max_stream_data_uni)1787QLOG_U64("initial_max_stream_data_uni",1788ch->rx_init_max_stream_data_uni);1789if (got_initial_max_streams_bidi)1790QLOG_U64("initial_max_streams_bidi",1791ch->max_local_streams_bidi);1792if (got_initial_max_streams_uni)1793QLOG_U64("initial_max_streams_uni",1794ch->max_local_streams_uni);1795if (got_ack_delay_exp)1796QLOG_U64("ack_delay_exponent", ch->rx_ack_delay_exp);1797if (got_max_ack_delay)1798QLOG_U64("max_ack_delay", ch->rx_max_ack_delay);1799if (got_max_udp_payload_size)1800QLOG_U64("max_udp_payload_size", ch->rx_max_udp_payload_size);1801if (got_max_idle_timeout)1802QLOG_U64("max_idle_timeout", rx_max_idle_timeout);1803if (got_active_conn_id_limit)1804QLOG_U64("active_connection_id_limit", ch->rx_active_conn_id_limit);1805if (got_stateless_reset_token)1806QLOG_BIN("stateless_reset_token", stateless_reset_token_p,1807QUIC_STATELESS_RESET_TOKEN_LEN);1808if (got_preferred_addr) {1809QLOG_BEGIN("preferred_addr")1810QLOG_U64("port_v4", pfa.ipv4_port);1811QLOG_U64("port_v6", pfa.ipv6_port);1812QLOG_BIN("ip_v4", pfa.ipv4, sizeof(pfa.ipv4));1813QLOG_BIN("ip_v6", pfa.ipv6, sizeof(pfa.ipv6));1814QLOG_BIN("stateless_reset_token", pfa.stateless_reset.token,1815sizeof(pfa.stateless_reset.token));1816QLOG_CID("connection_id", &pfa.cid);1817QLOG_END()1818}1819QLOG_BOOL("disable_active_migration", got_disable_active_migration);1820QLOG_EVENT_END()1821#endif18221823if (got_initial_max_data || got_initial_max_stream_data_bidi_remote1824|| got_initial_max_streams_bidi || got_initial_max_streams_uni)1825/*1826* If FC credit was bumped, we may now be able to send. Update all1827* streams.1828*/1829ossl_quic_stream_map_visit(&ch->qsm, do_update, ch);18301831/* If we are a server, we now generate our own transport parameters. */1832if (ch->is_server && !ch_generate_transport_params(ch)) {1833ossl_quic_channel_raise_protocol_error(ch, OSSL_QUIC_ERR_INTERNAL_ERROR, 0,1834"internal error");1835return 0;1836}18371838return 1;18391840malformed:1841ossl_quic_channel_raise_protocol_error(ch, OSSL_QUIC_ERR_TRANSPORT_PARAMETER_ERROR,18420, reason);1843return 0;1844}18451846/*1847* Called when we want to generate transport parameters. This is called1848* immediately at instantiation time for a client and after we receive the1849* client's transport parameters for a server.1850*/1851static int ch_generate_transport_params(QUIC_CHANNEL *ch)1852{1853int ok = 0;1854BUF_MEM *buf_mem = NULL;1855WPACKET wpkt;1856int wpkt_valid = 0;1857size_t buf_len = 0;1858QUIC_CONN_ID *id_to_use = NULL;18591860/*1861* We need to select which connection id to encode in the1862* QUIC_TPARAM_ORIG_DCID transport parameter1863* If we have an odcid, then this connection was established1864* in response to a retry request, and we need to use the connection1865* id sent in the first initial packet.1866* If we don't have an odcid, then this connection was established1867* without a retry and the init_dcid is the connection we should use1868*/1869if (ch->odcid.id_len == 0)1870id_to_use = &ch->init_dcid;1871else1872id_to_use = &ch->odcid;18731874if (ch->local_transport_params != NULL || ch->got_local_transport_params)1875goto err;18761877if ((buf_mem = BUF_MEM_new()) == NULL)1878goto err;18791880if (!WPACKET_init(&wpkt, buf_mem))1881goto err;18821883wpkt_valid = 1;18841885if (ossl_quic_wire_encode_transport_param_bytes(&wpkt, QUIC_TPARAM_DISABLE_ACTIVE_MIGRATION,1886NULL, 0)1887== NULL)1888goto err;18891890if (ch->is_server) {1891if (!ossl_quic_wire_encode_transport_param_cid(&wpkt, QUIC_TPARAM_ORIG_DCID,1892id_to_use))1893goto err;18941895if (!ossl_quic_wire_encode_transport_param_cid(&wpkt, QUIC_TPARAM_INITIAL_SCID,1896&ch->cur_local_cid))1897goto err;1898if (ch->odcid.id_len != 0)1899if (!ossl_quic_wire_encode_transport_param_cid(&wpkt,1900QUIC_TPARAM_RETRY_SCID,1901&ch->init_dcid))1902goto err;1903} else {1904if (!ossl_quic_wire_encode_transport_param_cid(&wpkt, QUIC_TPARAM_INITIAL_SCID,1905&ch->init_scid))1906goto err;1907}19081909if (!ossl_quic_wire_encode_transport_param_int(&wpkt, QUIC_TPARAM_MAX_IDLE_TIMEOUT,1910ch->max_idle_timeout_local_req))1911goto err;19121913if (!ossl_quic_wire_encode_transport_param_int(&wpkt, QUIC_TPARAM_MAX_UDP_PAYLOAD_SIZE,1914QUIC_MIN_INITIAL_DGRAM_LEN))1915goto err;19161917if (!ossl_quic_wire_encode_transport_param_int(&wpkt, QUIC_TPARAM_ACTIVE_CONN_ID_LIMIT,1918QUIC_MIN_ACTIVE_CONN_ID_LIMIT))1919goto err;19201921if (ch->tx_max_ack_delay != QUIC_DEFAULT_MAX_ACK_DELAY1922&& !ossl_quic_wire_encode_transport_param_int(&wpkt, QUIC_TPARAM_MAX_ACK_DELAY,1923ch->tx_max_ack_delay))1924goto err;19251926if (!ossl_quic_wire_encode_transport_param_int(&wpkt, QUIC_TPARAM_INITIAL_MAX_DATA,1927ossl_quic_rxfc_get_cwm(&ch->conn_rxfc)))1928goto err;19291930/* Send the default CWM for a new RXFC. */1931if (!ossl_quic_wire_encode_transport_param_int(&wpkt, QUIC_TPARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL,1932ch->tx_init_max_stream_data_bidi_local))1933goto err;19341935if (!ossl_quic_wire_encode_transport_param_int(&wpkt, QUIC_TPARAM_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE,1936ch->tx_init_max_stream_data_bidi_remote))1937goto err;19381939if (!ossl_quic_wire_encode_transport_param_int(&wpkt, QUIC_TPARAM_INITIAL_MAX_STREAM_DATA_UNI,1940ch->tx_init_max_stream_data_uni))1941goto err;19421943if (!ossl_quic_wire_encode_transport_param_int(&wpkt, QUIC_TPARAM_INITIAL_MAX_STREAMS_BIDI,1944ossl_quic_rxfc_get_cwm(&ch->max_streams_bidi_rxfc)))1945goto err;19461947if (!ossl_quic_wire_encode_transport_param_int(&wpkt, QUIC_TPARAM_INITIAL_MAX_STREAMS_UNI,1948ossl_quic_rxfc_get_cwm(&ch->max_streams_uni_rxfc)))1949goto err;19501951if (!WPACKET_finish(&wpkt))1952goto err;19531954wpkt_valid = 0;19551956if (!WPACKET_get_total_written(&wpkt, &buf_len))1957goto err;19581959ch->local_transport_params = (unsigned char *)buf_mem->data;1960buf_mem->data = NULL;19611962if (!ossl_quic_tls_set_transport_params(ch->qtls, ch->local_transport_params,1963buf_len))1964goto err;19651966#ifndef OPENSSL_NO_QLOG1967QLOG_EVENT_BEGIN(ch_get_qlog(ch), transport, parameters_set)1968QLOG_STR("owner", "local");1969QLOG_BOOL("disable_active_migration", 1);1970if (ch->is_server) {1971QLOG_CID("original_destination_connection_id", &ch->init_dcid);1972QLOG_CID("initial_source_connection_id", &ch->cur_local_cid);1973} else {1974QLOG_STR("initial_source_connection_id", "");1975}1976QLOG_U64("max_idle_timeout", ch->max_idle_timeout);1977QLOG_U64("max_udp_payload_size", QUIC_MIN_INITIAL_DGRAM_LEN);1978QLOG_U64("active_connection_id_limit", QUIC_MIN_ACTIVE_CONN_ID_LIMIT);1979QLOG_U64("max_ack_delay", ch->tx_max_ack_delay);1980QLOG_U64("initial_max_data", ossl_quic_rxfc_get_cwm(&ch->conn_rxfc));1981QLOG_U64("initial_max_stream_data_bidi_local",1982ch->tx_init_max_stream_data_bidi_local);1983QLOG_U64("initial_max_stream_data_bidi_remote",1984ch->tx_init_max_stream_data_bidi_remote);1985QLOG_U64("initial_max_stream_data_uni",1986ch->tx_init_max_stream_data_uni);1987QLOG_U64("initial_max_streams_bidi",1988ossl_quic_rxfc_get_cwm(&ch->max_streams_bidi_rxfc));1989QLOG_U64("initial_max_streams_uni",1990ossl_quic_rxfc_get_cwm(&ch->max_streams_uni_rxfc));1991QLOG_EVENT_END()1992#endif19931994ch->got_local_transport_params = 1;19951996ok = 1;1997err:1998if (wpkt_valid)1999WPACKET_cleanup(&wpkt);2000BUF_MEM_free(buf_mem);2001return ok;2002}20032004/*2005* QUIC Channel: Ticker-Mutator2006* ============================2007*/20082009/*2010* The central ticker function called by the reactor. This does everything, or2011* at least everything network I/O related. Best effort - not allowed to fail2012* "loudly".2013*/2014void ossl_quic_channel_subtick(QUIC_CHANNEL *ch, QUIC_TICK_RESULT *res,2015uint32_t flags)2016{2017OSSL_TIME now, deadline;2018int channel_only = (flags & QUIC_REACTOR_TICK_FLAG_CHANNEL_ONLY) != 0;2019int notify_other_threads = 0;20202021/*2022* When we tick the QUIC connection, we do everything we need to do2023* periodically. Network I/O handling will already have been performed2024* as necessary by the QUIC port. Thus, in order, we:2025*2026* - handle any packets the DEMUX has queued up for us;2027* - handle any timer events which are due to fire (ACKM, etc.);2028* - generate any packets which need to be sent;2029* - determine the time at which we should next be ticked.2030*/20312032/*2033* If the connection has not yet started, or we are in the TERMINATED state,2034* there is nothing to do.2035*/2036if (ch->state == QUIC_CHANNEL_STATE_IDLE2037|| ossl_quic_channel_is_terminated(ch)) {2038res->net_read_desired = 0;2039res->net_write_desired = 0;2040res->notify_other_threads = 0;2041res->tick_deadline = ossl_time_infinite();2042return;2043}20442045/*2046* If we are in the TERMINATING state, check if the terminating timer has2047* expired.2048*/2049if (ossl_quic_channel_is_terminating(ch)) {2050now = get_time(ch);20512052if (ossl_time_compare(now, ch->terminate_deadline) >= 0) {2053ch_on_terminating_timeout(ch);2054res->net_read_desired = 0;2055res->net_write_desired = 0;2056res->notify_other_threads = 1;2057res->tick_deadline = ossl_time_infinite();2058return; /* abort normal processing, nothing to do */2059}2060}20612062if (!ch->port->engine->inhibit_tick) {2063/* Handle RXKU timeouts. */2064ch_rxku_tick(ch);20652066do {2067/* Process queued incoming packets. */2068ch->did_tls_tick = 0;2069ch->have_new_rx_secret = 0;2070ch_rx(ch, channel_only, ¬ify_other_threads);20712072/*2073* Allow the handshake layer to check for any new incoming data and2074* generate new outgoing data.2075*/2076if (!ch->did_tls_tick)2077ch_tick_tls(ch, channel_only, ¬ify_other_threads);20782079/*2080* If the handshake layer gave us a new secret, we need to do RX2081* again because packets that were not previously processable and2082* were deferred might now be processable.2083*2084* TODO(QUIC FUTURE): Consider handling this in the yield_secret callback.2085*/2086} while (ch->have_new_rx_secret);2087}20882089/*2090* Handle any timer events which are due to fire; namely, the loss2091* detection deadline and the idle timeout.2092*2093* ACKM ACK generation deadline is polled by TXP, so we don't need to2094* handle it here.2095*/2096now = get_time(ch);2097if (ossl_time_compare(now, ch->idle_deadline) >= 0) {2098/*2099* Idle timeout differs from normal protocol violation because we do2100* not send a CONN_CLOSE frame; go straight to TERMINATED.2101*/2102if (!ch->port->engine->inhibit_tick)2103ch_on_idle_timeout(ch);21042105res->net_read_desired = 0;2106res->net_write_desired = 0;2107res->notify_other_threads = 1;2108res->tick_deadline = ossl_time_infinite();2109return;2110}21112112if (!ch->port->engine->inhibit_tick) {2113deadline = ossl_ackm_get_loss_detection_deadline(ch->ackm);2114if (!ossl_time_is_zero(deadline)2115&& ossl_time_compare(now, deadline) >= 0)2116ossl_ackm_on_timeout(ch->ackm);21172118/* If a ping is due, inform TXP. */2119if (ossl_time_compare(now, ch->ping_deadline) >= 0) {2120int pn_space = ossl_quic_enc_level_to_pn_space(ch->tx_enc_level);21212122ossl_quic_tx_packetiser_schedule_ack_eliciting(ch->txp, pn_space);21232124/*2125* If we have no CC budget at this time we cannot process the above2126* PING request immediately. In any case we have scheduled the2127* request so bump the ping deadline. If we don't do this we will2128* busy-loop endlessly as the above deadline comparison condition2129* will still be met.2130*/2131ch_update_ping_deadline(ch);2132}21332134/* Queue any data to be sent for transmission. */2135ch_tx(ch, ¬ify_other_threads);21362137/* Do stream GC. */2138ossl_quic_stream_map_gc(&ch->qsm);2139}21402141/* Determine the time at which we should next be ticked. */2142res->tick_deadline = ch_determine_next_tick_deadline(ch);21432144/*2145* Always process network input unless we are now terminated. Although we2146* had not terminated at the beginning of this tick, network errors in2147* ch_tx() may have caused us to transition to the Terminated state.2148*/2149res->net_read_desired = !ossl_quic_channel_is_terminated(ch);21502151/* We want to write to the network if we have any data in our TX queue. */2152res->net_write_desired2153= (!ossl_quic_channel_is_terminated(ch)2154&& ossl_qtx_get_queue_len_datagrams(ch->qtx) > 0);21552156res->notify_other_threads = notify_other_threads;2157}21582159static int ch_tick_tls(QUIC_CHANNEL *ch, int channel_only, int *notify_other_threads)2160{2161uint64_t error_code;2162const char *error_msg;2163ERR_STATE *error_state = NULL;21642165if (channel_only)2166return 1;21672168ch->did_tls_tick = 1;2169ossl_quic_tls_tick(ch->qtls);21702171if (ossl_quic_tls_get_error(ch->qtls, &error_code, &error_msg,2172&error_state)) {2173ossl_quic_channel_raise_protocol_error_state(ch, error_code, 0,2174error_msg, error_state);2175if (notify_other_threads != NULL)2176*notify_other_threads = 1;21772178return 0;2179}21802181return 1;2182}21832184/* Check incoming forged packet limit and terminate connection if needed. */2185static void ch_rx_check_forged_pkt_limit(QUIC_CHANNEL *ch)2186{2187uint32_t enc_level;2188uint64_t limit = UINT64_MAX, l;21892190for (enc_level = QUIC_ENC_LEVEL_INITIAL;2191enc_level < QUIC_ENC_LEVEL_NUM;2192++enc_level) {2193/*2194* Different ELs can have different AEADs which can in turn impose2195* different limits, so use the lowest value of any currently valid EL.2196*/2197if ((ch->el_discarded & (1U << enc_level)) != 0)2198continue;21992200if (enc_level > ch->rx_enc_level)2201break;22022203l = ossl_qrx_get_max_forged_pkt_count(ch->qrx, enc_level);2204if (l < limit)2205limit = l;2206}22072208if (ossl_qrx_get_cur_forged_pkt_count(ch->qrx) < limit)2209return;22102211ossl_quic_channel_raise_protocol_error(ch, OSSL_QUIC_ERR_AEAD_LIMIT_REACHED, 0,2212"forgery limit");2213}22142215/* Process queued incoming packets and handle frames, if any. */2216static int ch_rx(QUIC_CHANNEL *ch, int channel_only, int *notify_other_threads)2217{2218int handled_any = 0;2219const int closing = ossl_quic_channel_is_closing(ch);22202221if (!ch->is_server && !ch->have_sent_any_pkt)2222/*2223* We have not sent anything yet, therefore there is no need to check2224* for incoming data.2225*/2226return 1;22272228for (;;) {2229assert(ch->qrx_pkt == NULL);22302231if (!ossl_qrx_read_pkt(ch->qrx, &ch->qrx_pkt))2232break;22332234/* Track the amount of data received while in the closing state */2235if (closing)2236ossl_quic_tx_packetiser_record_received_closing_bytes(2237ch->txp, ch->qrx_pkt->hdr->len);22382239if (!handled_any) {2240ch_update_idle(ch);2241ch_update_ping_deadline(ch);2242}22432244ch_rx_handle_packet(ch, channel_only); /* best effort */22452246/*2247* Regardless of the outcome of frame handling, unref the packet.2248* This will free the packet unless something added another2249* reference to it during frame processing.2250*/2251ossl_qrx_pkt_release(ch->qrx_pkt);2252ch->qrx_pkt = NULL;22532254ch->have_sent_ack_eliciting_since_rx = 0;2255handled_any = 1;2256}22572258ch_rx_check_forged_pkt_limit(ch);22592260if (handled_any && notify_other_threads != NULL)2261*notify_other_threads = 1;22622263/*2264* When in TERMINATING - CLOSING, generate a CONN_CLOSE frame whenever we2265* process one or more incoming packets.2266*/2267if (handled_any && closing)2268ch->conn_close_queued = 1;22692270return 1;2271}22722273static int bio_addr_eq(const BIO_ADDR *a, const BIO_ADDR *b)2274{2275if (BIO_ADDR_family(a) != BIO_ADDR_family(b))2276return 0;22772278switch (BIO_ADDR_family(a)) {2279case AF_INET:2280return !memcmp(&a->s_in.sin_addr,2281&b->s_in.sin_addr,2282sizeof(a->s_in.sin_addr))2283&& a->s_in.sin_port == b->s_in.sin_port;2284#if OPENSSL_USE_IPV62285case AF_INET6:2286return !memcmp(&a->s_in6.sin6_addr,2287&b->s_in6.sin6_addr,2288sizeof(a->s_in6.sin6_addr))2289&& a->s_in6.sin6_port == b->s_in6.sin6_port;2290#endif2291default:2292return 0; /* not supported */2293}22942295return 1;2296}22972298/* Handles the packet currently in ch->qrx_pkt->hdr. */2299static void ch_rx_handle_packet(QUIC_CHANNEL *ch, int channel_only)2300{2301uint32_t enc_level;2302int old_have_processed_any_pkt = ch->have_processed_any_pkt;2303OSSL_QTX_IOVEC iovec;2304PACKET vpkt;2305unsigned long supported_ver;23062307assert(ch->qrx_pkt != NULL);23082309/*2310* RFC 9000 s. 10.2.1 Closing Connection State:2311* An endpoint that is closing is not required to process any2312* received frame.2313*/2314if (!ossl_quic_channel_is_active(ch))2315return;23162317if (ossl_quic_pkt_type_is_encrypted(ch->qrx_pkt->hdr->type)) {2318if (!ch->have_received_enc_pkt) {2319ch->cur_remote_dcid = ch->init_scid = ch->qrx_pkt->hdr->src_conn_id;2320ch->have_received_enc_pkt = 1;23212322/*2323* We change to using the SCID in the first Initial packet as the2324* DCID.2325*/2326ossl_quic_tx_packetiser_set_cur_dcid(ch->txp, &ch->init_scid);2327}23282329enc_level = ossl_quic_pkt_type_to_enc_level(ch->qrx_pkt->hdr->type);2330if ((ch->el_discarded & (1U << enc_level)) != 0)2331/* Do not process packets from ELs we have already discarded. */2332return;2333}23342335/*2336* RFC 9000 s. 9.6: "If a client receives packets from a new server address2337* when the client has not initiated a migration to that address, the client2338* SHOULD discard these packets."2339*2340* We need to be a bit careful here as due to the BIO abstraction layer an2341* application is liable to be weird and lie to us about peer addresses.2342* Only apply this check if we actually are using a real AF_INET or AF_INET62343* address.2344*/2345if (!ch->is_server2346&& ch->qrx_pkt->peer != NULL2347&& (BIO_ADDR_family(&ch->cur_peer_addr) == AF_INET2348#if OPENSSL_USE_IPV62349|| BIO_ADDR_family(&ch->cur_peer_addr) == AF_INET62350#endif2351)2352&& !bio_addr_eq(ch->qrx_pkt->peer, &ch->cur_peer_addr))2353return;23542355if (!ch->is_server2356&& ch->have_received_enc_pkt2357&& ossl_quic_pkt_type_has_scid(ch->qrx_pkt->hdr->type)) {2358/*2359* RFC 9000 s. 7.2: "Once a client has received a valid Initial packet2360* from the server, it MUST discard any subsequent packet it receives on2361* that connection with a different SCID."2362*/2363if (!ossl_quic_conn_id_eq(&ch->qrx_pkt->hdr->src_conn_id,2364&ch->init_scid))2365return;2366}23672368if (ossl_quic_pkt_type_has_version(ch->qrx_pkt->hdr->type)2369&& ch->qrx_pkt->hdr->version != QUIC_VERSION_1)2370/*2371* RFC 9000 s. 5.2.1: If a client receives a packet that uses a2372* different version than it initially selected, it MUST discard the2373* packet. We only ever use v1, so require it.2374*/2375return;23762377if (ch->qrx_pkt->hdr->type == QUIC_PKT_TYPE_VERSION_NEG) {23782379/*2380* Sanity check. Version negotiation packet MUST have a version2381* value of 0 according to the RFC. We must discard such packets2382*/2383if (ch->qrx_pkt->hdr->version != 0)2384return;23852386/*2387* RFC 9000 s. 6.2: If a client receives a version negotiation2388* packet, we need to do the following:2389* a) If the negotiation packet lists the version we initially sent2390* then we must abandon this connection attempt2391* b) We have to select a version from the list provided in the2392* version negotiation packet, and retry the connection attempt2393* in much the same way that ch_retry does, but we can reuse the2394* connection id values2395*/23962397if (old_have_processed_any_pkt == 1) {2398/*2399* We've gotten previous packets, need to discard this.2400*/2401return;2402}24032404/*2405* Indicate that we have processed a packet, as any subsequently2406* received version negotiation packet must be discarded above2407*/2408ch->have_processed_any_pkt = 1;24092410/*2411* Following the header, version negotiation packets2412* contain an array of 32 bit integers representing2413* the supported versions that the server honors2414* this array, bounded by the hdr->len field2415* needs to be traversed so that we can find a matching2416* version2417*/2418if (!PACKET_buf_init(&vpkt, ch->qrx_pkt->hdr->data,2419ch->qrx_pkt->hdr->len))2420return;24212422while (PACKET_remaining(&vpkt) > 0) {2423/*2424* We only support quic version 1 at the moment, so2425* look to see if that's offered2426*/2427if (!PACKET_get_net_4(&vpkt, &supported_ver))2428return;24292430if (supported_ver == QUIC_VERSION_1) {2431/*2432* If the server supports version 1, set it as2433* the packetisers version2434*/2435ossl_quic_tx_packetiser_set_protocol_version(ch->txp, QUIC_VERSION_1);24362437/*2438* And then request a restart of the QUIC connection2439*/2440if (!ch_restart(ch))2441ossl_quic_channel_raise_protocol_error(ch,2442OSSL_QUIC_ERR_INTERNAL_ERROR,24430, "handling ver negotiation packet");2444return;2445}2446}24472448/*2449* If we get here, then the server doesn't support a version of the2450* protocol that we can handle, abandon the connection2451*/2452ossl_quic_channel_raise_protocol_error(ch, OSSL_QUIC_ERR_CONNECTION_REFUSED,24530, "unsupported protocol version");2454return;2455}24562457ch->have_processed_any_pkt = 1;24582459/*2460* RFC 9000 s. 17.2: "An endpoint MUST treat receipt of a packet that has a2461* non-zero value for [the reserved bits] after removing both packet and2462* header protection as a connection error of type PROTOCOL_VIOLATION."2463*/2464if (ossl_quic_pkt_type_is_encrypted(ch->qrx_pkt->hdr->type)2465&& ch->qrx_pkt->hdr->reserved != 0) {2466ossl_quic_channel_raise_protocol_error(ch, OSSL_QUIC_ERR_PROTOCOL_VIOLATION,24670, "packet header reserved bits");2468return;2469}24702471iovec.buf = ch->qrx_pkt->hdr->data;2472iovec.buf_len = ch->qrx_pkt->hdr->len;2473ossl_qlog_event_transport_packet_received(ch_get_qlog(ch), ch->qrx_pkt->hdr,2474ch->qrx_pkt->pn, &iovec, 1,2475ch->qrx_pkt->datagram_id);24762477/* Handle incoming packet. */2478switch (ch->qrx_pkt->hdr->type) {2479case QUIC_PKT_TYPE_RETRY:2480if (ch->doing_retry || ch->is_server)2481/*2482* It is not allowed to ask a client to do a retry more than2483* once. Clients may not send retries.2484*/2485return;24862487/*2488* RFC 9000 s 17.2.5.2: After the client has received and processed an2489* Initial or Retry packet from the server, it MUST discard any2490* subsequent Retry packets that it receives.2491*/2492if (ch->have_received_enc_pkt)2493return;24942495if (ch->qrx_pkt->hdr->len <= QUIC_RETRY_INTEGRITY_TAG_LEN)2496/* Packets with zero-length Retry Tokens are invalid. */2497return;24982499/*2500* TODO(QUIC FUTURE): Theoretically this should probably be in the QRX.2501* However because validation is dependent on context (namely the2502* client's initial DCID) we can't do this cleanly. In the future we2503* should probably add a callback to the QRX to let it call us (via2504* the DEMUX) and ask us about the correct original DCID, rather2505* than allow the QRX to emit a potentially malformed packet to the2506* upper layers. However, special casing this will do for now.2507*/2508if (!ossl_quic_validate_retry_integrity_tag(ch->port->engine->libctx,2509ch->port->engine->propq,2510ch->qrx_pkt->hdr,2511&ch->init_dcid))2512/* Malformed retry packet, ignore. */2513return;25142515if (!ch_retry(ch, ch->qrx_pkt->hdr->data,2516ch->qrx_pkt->hdr->len - QUIC_RETRY_INTEGRITY_TAG_LEN,2517&ch->qrx_pkt->hdr->src_conn_id, old_have_processed_any_pkt))2518ossl_quic_channel_raise_protocol_error(ch, OSSL_QUIC_ERR_INTERNAL_ERROR,25190, "handling retry packet");2520break;25212522case QUIC_PKT_TYPE_0RTT:2523if (!ch->is_server)2524/* Clients should never receive 0-RTT packets. */2525return;25262527/*2528* TODO(QUIC 0RTT): Implement 0-RTT on the server side. We currently2529* do not need to implement this as a client can only do 0-RTT if we2530* have given it permission to in a previous session.2531*/2532break;25332534case QUIC_PKT_TYPE_INITIAL:2535case QUIC_PKT_TYPE_HANDSHAKE:2536case QUIC_PKT_TYPE_1RTT:2537if (ch->is_server && ch->qrx_pkt->hdr->type == QUIC_PKT_TYPE_HANDSHAKE)2538/*2539* We automatically drop INITIAL EL keys when first successfully2540* decrypting a HANDSHAKE packet, as per the RFC.2541*/2542ch_discard_el(ch, QUIC_ENC_LEVEL_INITIAL);25432544if (ch->rxku_in_progress2545&& ch->qrx_pkt->hdr->type == QUIC_PKT_TYPE_1RTT2546&& ch->qrx_pkt->pn >= ch->rxku_trigger_pn2547&& ch->qrx_pkt->key_epoch < ossl_qrx_get_key_epoch(ch->qrx)) {2548/*2549* RFC 9001 s. 6.4: Packets with higher packet numbers MUST be2550* protected with either the same or newer packet protection keys2551* than packets with lower packet numbers. An endpoint that2552* successfully removes protection with old keys when newer keys2553* were used for packets with lower packet numbers MUST treat this2554* as a connection error of type KEY_UPDATE_ERROR.2555*/2556ossl_quic_channel_raise_protocol_error(ch, OSSL_QUIC_ERR_KEY_UPDATE_ERROR,25570, "new packet with old keys");2558break;2559}25602561if (!ch->is_server2562&& ch->qrx_pkt->hdr->type == QUIC_PKT_TYPE_INITIAL2563&& ch->qrx_pkt->hdr->token_len > 0) {2564/*2565* RFC 9000 s. 17.2.2: Clients that receive an Initial packet with a2566* non-zero Token Length field MUST either discard the packet or2567* generate a connection error of type PROTOCOL_VIOLATION.2568*2569* TODO(QUIC FUTURE): consider the implications of RFC 9000 s. 10.2.32570* Immediate Close during the Handshake:2571* However, at the cost of reducing feedback about2572* errors for legitimate peers, some forms of denial of2573* service can be made more difficult for an attacker2574* if endpoints discard illegal packets rather than2575* terminating a connection with CONNECTION_CLOSE. For2576* this reason, endpoints MAY discard packets rather2577* than immediately close if errors are detected in2578* packets that lack authentication.2579* I.e. should we drop this packet instead of closing the connection?2580*/2581ossl_quic_channel_raise_protocol_error(ch, OSSL_QUIC_ERR_PROTOCOL_VIOLATION,25820, "client received initial token");2583break;2584}25852586/* This packet contains frames, pass to the RXDP. */2587ossl_quic_handle_frames(ch, ch->qrx_pkt); /* best effort */25882589if (ch->did_crypto_frame)2590ch_tick_tls(ch, channel_only, NULL);25912592break;25932594default:2595assert(0);2596break;2597}2598}25992600/* Try to generate packets and if possible, flush them to the network. */2601static int ch_tx(QUIC_CHANNEL *ch, int *notify_other_threads)2602{2603QUIC_TXP_STATUS status;2604int res;26052606/*2607* RFC 9000 s. 10.2.2: Draining Connection State:2608* While otherwise identical to the closing state, an endpoint2609* in the draining state MUST NOT send any packets.2610* and:2611* An endpoint MUST NOT send further packets.2612*/2613if (ossl_quic_channel_is_draining(ch))2614return 0;26152616if (ossl_quic_channel_is_closing(ch)) {2617/*2618* While closing, only send CONN_CLOSE if we've received more traffic2619* from the peer. Once we tell the TXP to generate CONN_CLOSE, all2620* future calls to it generate CONN_CLOSE frames, so otherwise we would2621* just constantly generate CONN_CLOSE frames.2622*2623* Confirming to RFC 9000 s. 10.2.1 Closing Connection State:2624* An endpoint SHOULD limit the rate at which it generates2625* packets in the closing state.2626*/2627if (!ch->conn_close_queued)2628return 0;26292630ch->conn_close_queued = 0;2631}26322633/* Do TXKU if we need to. */2634ch_maybe_trigger_spontaneous_txku(ch);26352636ch->rxku_pending_confirm_done = 0;26372638/* Loop until we stop generating packets to send */2639do {2640/*2641* Send packet, if we need to. Best effort. The TXP consults the CC and2642* applies any limitations imposed by it, so we don't need to do it here.2643*2644* Best effort. In particular if TXP fails for some reason we should2645* still flush any queued packets which we already generated.2646*/2647res = ossl_quic_tx_packetiser_generate(ch->txp, &status);2648if (status.sent_pkt > 0) {2649ch->have_sent_any_pkt = 1; /* Packet(s) were sent */2650ch->port->have_sent_any_pkt = 1;26512652/*2653* RFC 9000 s. 10.1. 'An endpoint also restarts its idle timer when2654* sending an ack-eliciting packet if no other ack-eliciting packets2655* have been sent since last receiving and processing a packet.'2656*/2657if (status.sent_ack_eliciting2658&& !ch->have_sent_ack_eliciting_since_rx) {2659ch_update_idle(ch);2660ch->have_sent_ack_eliciting_since_rx = 1;2661}26622663if (!ch->is_server && status.sent_handshake)2664/*2665* RFC 9001 s. 4.9.1: A client MUST discard Initial keys when it2666* first sends a Handshake packet.2667*/2668ch_discard_el(ch, QUIC_ENC_LEVEL_INITIAL);26692670if (ch->rxku_pending_confirm_done)2671ch->rxku_pending_confirm = 0;26722673ch_update_ping_deadline(ch);2674}26752676if (!res) {2677/*2678* One case where TXP can fail is if we reach a TX PN of 2**62 - 1.2679* As per RFC 9000 s. 12.3, if this happens we MUST close the2680* connection without sending a CONNECTION_CLOSE frame. This is2681* actually handled as an emergent consequence of our design, as the2682* TX packetiser will never transmit another packet when the TX PN2683* reaches the limit.2684*2685* Calling the below function terminates the connection; its attempt2686* to schedule a CONNECTION_CLOSE frame will not actually cause a2687* packet to be transmitted for this reason.2688*/2689ossl_quic_channel_raise_protocol_error(ch, OSSL_QUIC_ERR_INTERNAL_ERROR,26900,2691"internal error (txp generate)");2692break;2693}2694} while (status.sent_pkt > 0);26952696/* Flush packets to network. */2697switch (ossl_qtx_flush_net(ch->qtx)) {2698case QTX_FLUSH_NET_RES_OK:2699case QTX_FLUSH_NET_RES_TRANSIENT_FAIL:2700/* Best effort, done for now. */2701break;27022703case QTX_FLUSH_NET_RES_PERMANENT_FAIL:2704default:2705/* Permanent underlying network BIO, start terminating. */2706ossl_quic_port_raise_net_error(ch->port, ch);2707break;2708}27092710/*2711* If we have datagrams we have yet to successfully transmit, we need to2712* notify other threads so that they can switch to polling on POLLOUT as2713* well as POLLIN.2714*/2715if (ossl_qtx_get_queue_len_datagrams(ch->qtx) > 0)2716*notify_other_threads = 1;27172718return 1;2719}27202721/* Determine next tick deadline. */2722static OSSL_TIME ch_determine_next_tick_deadline(QUIC_CHANNEL *ch)2723{2724OSSL_TIME deadline;2725int i;27262727if (ossl_quic_channel_is_terminated(ch))2728return ossl_time_infinite();27292730deadline = ossl_ackm_get_loss_detection_deadline(ch->ackm);2731if (ossl_time_is_zero(deadline))2732deadline = ossl_time_infinite();27332734/*2735* Check the ack deadline for all enc_levels that are actually provisioned.2736* ACKs aren't restricted by CC.2737*/2738for (i = 0; i < QUIC_ENC_LEVEL_NUM; i++) {2739if (ossl_qtx_is_enc_level_provisioned(ch->qtx, i)) {2740deadline = ossl_time_min(deadline,2741ossl_ackm_get_ack_deadline(ch->ackm,2742ossl_quic_enc_level_to_pn_space(i)));2743}2744}27452746/*2747* When do we need to send an ACK-eliciting packet to reset the idle2748* deadline timer for the peer?2749*/2750if (!ossl_time_is_infinite(ch->ping_deadline))2751deadline = ossl_time_min(deadline, ch->ping_deadline);27522753/* Apply TXP wakeup deadline. */2754deadline = ossl_time_min(deadline,2755ossl_quic_tx_packetiser_get_deadline(ch->txp));27562757/* Is the terminating timer armed? */2758if (ossl_quic_channel_is_terminating(ch))2759deadline = ossl_time_min(deadline,2760ch->terminate_deadline);2761else if (!ossl_time_is_infinite(ch->idle_deadline))2762deadline = ossl_time_min(deadline,2763ch->idle_deadline);27642765/* When does the RXKU process complete? */2766if (ch->rxku_in_progress)2767deadline = ossl_time_min(deadline, ch->rxku_update_end_deadline);27682769return deadline;2770}27712772/*2773* QUIC Channel: Lifecycle Events2774* ==============================2775*/27762777/*2778* Record a state transition. This is not necessarily a change to ch->state but2779* also includes the handshake becoming complete or confirmed, etc.2780*/2781static void ch_record_state_transition(QUIC_CHANNEL *ch, uint32_t new_state)2782{2783uint32_t old_state = ch->state;27842785ch->state = new_state;27862787ossl_qlog_event_connectivity_connection_state_updated(ch_get_qlog(ch),2788old_state,2789new_state,2790ch->handshake_complete,2791ch->handshake_confirmed);2792}27932794static void free_peer_token(const unsigned char *token,2795size_t token_len, void *arg)2796{2797ossl_quic_free_peer_token((QUIC_TOKEN *)arg);2798}27992800int ossl_quic_channel_start(QUIC_CHANNEL *ch)2801{2802QUIC_TOKEN *token;28032804if (ch->is_server)2805/*2806* This is not used by the server. The server moves to active2807* automatically on receiving an incoming connection.2808*/2809return 0;28102811if (ch->state != QUIC_CHANNEL_STATE_IDLE)2812/* Calls to connect are idempotent */2813return 1;28142815/* Inform QTX of peer address. */2816if (!ossl_quic_tx_packetiser_set_peer(ch->txp, &ch->cur_peer_addr))2817return 0;28182819/*2820* Look to see if we have a token, and if so, set it on the packetiser2821*/2822if (!ch->is_server2823&& ossl_quic_get_peer_token(ch->port->channel_ctx,2824&ch->cur_peer_addr,2825&token)2826&& !ossl_quic_tx_packetiser_set_initial_token(ch->txp, token->token,2827token->token_len,2828free_peer_token,2829token))2830free_peer_token(NULL, 0, token);28312832/* Plug in secrets for the Initial EL. */2833if (!ossl_quic_provide_initial_secret(ch->port->engine->libctx,2834ch->port->engine->propq,2835&ch->init_dcid,2836ch->is_server,2837ch->qrx, ch->qtx))2838return 0;28392840/*2841* Determine the QUIC Transport Parameters and serialize the transport2842* parameters block. (For servers, we do this later as we must defer2843* generation until we have received the client's transport parameters.)2844*/2845if (!ch->is_server && !ch->got_local_transport_params2846&& !ch_generate_transport_params(ch))2847return 0;28482849/* Change state. */2850ch_record_state_transition(ch, QUIC_CHANNEL_STATE_ACTIVE);2851ch->doing_proactive_ver_neg = 0; /* not currently supported */28522853ossl_qlog_event_connectivity_connection_started(ch_get_qlog(ch),2854&ch->init_dcid);28552856/* Handshake layer: start (e.g. send CH). */2857if (!ch_tick_tls(ch, /*channel_only=*/0, NULL))2858return 0;28592860ossl_quic_reactor_tick(ossl_quic_port_get0_reactor(ch->port), 0); /* best effort */2861return 1;2862}28632864static void free_token(const unsigned char *token, size_t token_len, void *arg)2865{2866OPENSSL_free((char *)token);2867}28682869/* Start a locally initiated connection shutdown. */2870void ossl_quic_channel_local_close(QUIC_CHANNEL *ch, uint64_t app_error_code,2871const char *app_reason)2872{2873QUIC_TERMINATE_CAUSE tcause = { 0 };28742875if (ossl_quic_channel_is_term_any(ch))2876return;28772878tcause.app = 1;2879tcause.error_code = app_error_code;2880tcause.reason = app_reason;2881tcause.reason_len = app_reason != NULL ? strlen(app_reason) : 0;2882ch_start_terminating(ch, &tcause, 0);2883}28842885/**2886* ch_restart - Restarts the QUIC channel by simulating loss of the initial2887* packet. This forces the packet to be regenerated with the updated protocol2888* version number.2889*2890* @ch: Pointer to the QUIC_CHANNEL structure.2891*2892* Returns 1 on success, 0 on failure.2893*/2894static int ch_restart(QUIC_CHANNEL *ch)2895{2896/*2897* Just pretend we lost our initial packet, so it gets2898* regenerated, with our updated protocol version number2899*/2900return ossl_ackm_mark_packet_pseudo_lost(ch->ackm, QUIC_PN_SPACE_INITIAL,2901/* PN= */ 0);2902}29032904/* Called when a server asks us to do a retry. */2905static int ch_retry(QUIC_CHANNEL *ch,2906const unsigned char *retry_token,2907size_t retry_token_len,2908const QUIC_CONN_ID *retry_scid,2909int drop_later_pn)2910{2911void *buf;2912QUIC_PN pn = 0;29132914/*2915* RFC 9000 s. 17.2.5.1: "A client MUST discard a Retry packet that contains2916* a SCID field that is identical to the DCID field of its initial packet."2917*/2918if (ossl_quic_conn_id_eq(&ch->init_dcid, retry_scid))2919return 1;29202921/* We change to using the SCID in the Retry packet as the DCID. */2922if (!ossl_quic_tx_packetiser_set_cur_dcid(ch->txp, retry_scid))2923return 0;29242925/*2926* Now we retry. We will release the Retry packet immediately, so copy2927* the token.2928*/2929if ((buf = OPENSSL_memdup(retry_token, retry_token_len)) == NULL)2930return 0;29312932if (!ossl_quic_tx_packetiser_set_initial_token(ch->txp, buf,2933retry_token_len,2934free_token, NULL)) {2935/*2936* This may fail if the token we receive is too big for us to ever be2937* able to transmit in an outgoing Initial packet.2938*/2939ossl_quic_channel_raise_protocol_error(ch, OSSL_QUIC_ERR_INVALID_TOKEN, 0,2940"received oversize token");2941OPENSSL_free(buf);2942return 0;2943}29442945ch->retry_scid = *retry_scid;2946ch->doing_retry = 1;29472948/*2949* If a retry isn't our first response, we need to drop packet number2950* one instead (i.e. the case where we did version negotiation first2951*/2952if (drop_later_pn == 1)2953pn = 1;29542955/*2956* We need to stimulate the Initial EL to generate the first CRYPTO frame2957* again. We can do this most cleanly by simply forcing the ACKM to consider2958* the first Initial packet as lost, which it effectively was as the server2959* hasn't processed it. This also maintains the desired behaviour with e.g.2960* PNs not resetting and so on.2961*2962* The PN we used initially is always zero, because QUIC does not allow2963* repeated retries.2964*/2965if (!ossl_ackm_mark_packet_pseudo_lost(ch->ackm, QUIC_PN_SPACE_INITIAL,2966pn))2967return 0;29682969/*2970* Plug in new secrets for the Initial EL. This is the only time we change2971* the secrets for an EL after we already provisioned it.2972*/2973if (!ossl_quic_provide_initial_secret(ch->port->engine->libctx,2974ch->port->engine->propq,2975&ch->retry_scid,2976/*is_server=*/0,2977ch->qrx, ch->qtx))2978return 0;29792980return 1;2981}29822983/* Called when an EL is to be discarded. */2984static int ch_discard_el(QUIC_CHANNEL *ch,2985uint32_t enc_level)2986{2987if (!ossl_assert(enc_level < QUIC_ENC_LEVEL_1RTT))2988return 0;29892990if ((ch->el_discarded & (1U << enc_level)) != 0)2991/* Already done. */2992return 1;29932994/* Best effort for all of these. */2995ossl_quic_tx_packetiser_discard_enc_level(ch->txp, enc_level);2996ossl_qrx_discard_enc_level(ch->qrx, enc_level);2997ossl_qtx_discard_enc_level(ch->qtx, enc_level);29982999if (enc_level != QUIC_ENC_LEVEL_0RTT) {3000uint32_t pn_space = ossl_quic_enc_level_to_pn_space(enc_level);30013002ossl_ackm_on_pkt_space_discarded(ch->ackm, pn_space);30033004/* We should still have crypto streams at this point. */3005if (!ossl_assert(ch->crypto_send[pn_space] != NULL)3006|| !ossl_assert(ch->crypto_recv[pn_space] != NULL))3007return 0;30083009/* Get rid of the crypto stream state for the EL. */3010ossl_quic_sstream_free(ch->crypto_send[pn_space]);3011ch->crypto_send[pn_space] = NULL;30123013ossl_quic_rstream_free(ch->crypto_recv[pn_space]);3014ch->crypto_recv[pn_space] = NULL;3015}30163017ch->el_discarded |= (1U << enc_level);3018return 1;3019}30203021/* Intended to be called by the RXDP. */3022int ossl_quic_channel_on_handshake_confirmed(QUIC_CHANNEL *ch)3023{3024if (ch->handshake_confirmed)3025return 1;30263027if (!ch->handshake_complete) {3028/*3029* Does not make sense for handshake to be confirmed before it is3030* completed.3031*/3032ossl_quic_channel_raise_protocol_error(ch, OSSL_QUIC_ERR_PROTOCOL_VIOLATION,3033OSSL_QUIC_FRAME_TYPE_HANDSHAKE_DONE,3034"handshake cannot be confirmed "3035"before it is completed");3036return 0;3037}30383039ch_discard_el(ch, QUIC_ENC_LEVEL_HANDSHAKE);3040ch->handshake_confirmed = 1;3041ch_record_state_transition(ch, ch->state);3042ossl_ackm_on_handshake_confirmed(ch->ackm);3043return 1;3044}30453046/*3047* Master function used when we want to start tearing down a connection:3048*3049* - If the connection is still IDLE we can go straight to TERMINATED;3050*3051* - If we are already TERMINATED this is a no-op.3052*3053* - If we are TERMINATING - CLOSING and we have now got a CONNECTION_CLOSE3054* from the peer (tcause->remote == 1), we move to TERMINATING - DRAINING.3055*3056* - If we are TERMINATING - DRAINING, we remain here until the terminating3057* timer expires.3058*3059* - Otherwise, we are in ACTIVE and move to TERMINATING - CLOSING.3060* if we caused the termination (e.g. we have sent a CONNECTION_CLOSE). Note3061* that we are considered to have caused a termination if we sent the first3062* CONNECTION_CLOSE frame, even if it is caused by a peer protocol3063* violation. If the peer sent the first CONNECTION_CLOSE frame, we move to3064* TERMINATING - DRAINING.3065*3066* We record the termination cause structure passed on the first call only.3067* Any successive calls have their termination cause data discarded;3068* once we start sending a CONNECTION_CLOSE frame, we don't change the details3069* in it.3070*3071* This conforms to RFC 9000 s. 10.2.1: Closing Connection State:3072* To minimize the state that an endpoint maintains for a closing3073* connection, endpoints MAY send the exact same packet in response3074* to any received packet.3075*3076* We don't drop any connection state (specifically packet protection keys)3077* even though we are permitted to. This conforms to RFC 9000 s. 10.2.1:3078* Closing Connection State:3079* An endpoint MAY retain packet protection keys for incoming3080* packets to allow it to read and process a CONNECTION_CLOSE frame.3081*3082* Note that we do not conform to these two from the same section:3083* An endpoint's selected connection ID and the QUIC version3084* are sufficient information to identify packets for a closing3085* connection; the endpoint MAY discard all other connection state.3086* and:3087* An endpoint MAY drop packet protection keys when entering the3088* closing state and send a packet containing a CONNECTION_CLOSE3089* frame in response to any UDP datagram that is received.3090*/3091static void copy_tcause(QUIC_TERMINATE_CAUSE *dst,3092const QUIC_TERMINATE_CAUSE *src)3093{3094dst->error_code = src->error_code;3095dst->frame_type = src->frame_type;3096dst->app = src->app;3097dst->remote = src->remote;30983099dst->reason = NULL;3100dst->reason_len = 0;31013102if (src->reason != NULL && src->reason_len > 0) {3103size_t l = src->reason_len;3104char *r;31053106if (l >= SIZE_MAX)3107--l;31083109/*3110* If this fails, dst->reason becomes NULL and we simply do not use a3111* reason. This ensures termination is infallible.3112*/3113dst->reason = r = OPENSSL_memdup(src->reason, l + 1);3114if (r == NULL)3115return;31163117r[l] = '\0';3118dst->reason_len = l;3119}3120}31213122static void ch_start_terminating(QUIC_CHANNEL *ch,3123const QUIC_TERMINATE_CAUSE *tcause,3124int force_immediate)3125{3126/* No point sending anything if we haven't sent anything yet. */3127if (!ch->have_sent_any_pkt)3128force_immediate = 1;31293130switch (ch->state) {3131default:3132case QUIC_CHANNEL_STATE_IDLE:3133copy_tcause(&ch->terminate_cause, tcause);3134ch_on_terminating_timeout(ch);3135break;31363137case QUIC_CHANNEL_STATE_ACTIVE:3138copy_tcause(&ch->terminate_cause, tcause);31393140ossl_qlog_event_connectivity_connection_closed(ch_get_qlog(ch), tcause);31413142if (!force_immediate) {3143ch_record_state_transition(ch, tcause->remote ? QUIC_CHANNEL_STATE_TERMINATING_DRAINING : QUIC_CHANNEL_STATE_TERMINATING_CLOSING);3144/*3145* RFC 9000 s. 10.2 Immediate Close3146* These states SHOULD persist for at least three times3147* the current PTO interval as defined in [QUIC-RECOVERY].3148*/3149ch->terminate_deadline3150= ossl_time_add(get_time(ch),3151ossl_time_multiply(ossl_ackm_get_pto_duration(ch->ackm),31523));31533154if (!tcause->remote) {3155OSSL_QUIC_FRAME_CONN_CLOSE f = { 0 };31563157/* best effort */3158f.error_code = ch->terminate_cause.error_code;3159f.frame_type = ch->terminate_cause.frame_type;3160f.is_app = ch->terminate_cause.app;3161f.reason = (char *)ch->terminate_cause.reason;3162f.reason_len = ch->terminate_cause.reason_len;3163ossl_quic_tx_packetiser_schedule_conn_close(ch->txp, &f);3164/*3165* RFC 9000 s. 10.2.2 Draining Connection State:3166* An endpoint that receives a CONNECTION_CLOSE frame MAY3167* send a single packet containing a CONNECTION_CLOSE3168* frame before entering the draining state, using a3169* NO_ERROR code if appropriate3170*/3171ch->conn_close_queued = 1;3172}3173} else {3174ch_on_terminating_timeout(ch);3175}3176break;31773178case QUIC_CHANNEL_STATE_TERMINATING_CLOSING:3179if (force_immediate)3180ch_on_terminating_timeout(ch);3181else if (tcause->remote)3182/*3183* RFC 9000 s. 10.2.2 Draining Connection State:3184* An endpoint MAY enter the draining state from the3185* closing state if it receives a CONNECTION_CLOSE frame,3186* which indicates that the peer is also closing or draining.3187*/3188ch_record_state_transition(ch, QUIC_CHANNEL_STATE_TERMINATING_DRAINING);31893190break;31913192case QUIC_CHANNEL_STATE_TERMINATING_DRAINING:3193/*3194* Other than in the force-immediate case, we remain here until the3195* timeout expires.3196*/3197if (force_immediate)3198ch_on_terminating_timeout(ch);31993200break;32013202case QUIC_CHANNEL_STATE_TERMINATED:3203/* No-op. */3204break;3205}3206}32073208/* For RXDP use. */3209void ossl_quic_channel_on_remote_conn_close(QUIC_CHANNEL *ch,3210OSSL_QUIC_FRAME_CONN_CLOSE *f)3211{3212QUIC_TERMINATE_CAUSE tcause = { 0 };32133214if (!ossl_quic_channel_is_active(ch))3215return;32163217tcause.remote = 1;3218tcause.app = f->is_app;3219tcause.error_code = f->error_code;3220tcause.frame_type = f->frame_type;3221tcause.reason = f->reason;3222tcause.reason_len = f->reason_len;3223ch_start_terminating(ch, &tcause, 0);3224}32253226static void free_frame_data(unsigned char *buf, size_t buf_len, void *arg)3227{3228OPENSSL_free(buf);3229}32303231static int ch_enqueue_retire_conn_id(QUIC_CHANNEL *ch, uint64_t seq_num)3232{3233BUF_MEM *buf_mem = NULL;3234WPACKET wpkt;3235size_t l;32363237ossl_quic_srtm_remove(ch->srtm, ch, seq_num);32383239if ((buf_mem = BUF_MEM_new()) == NULL)3240goto err;32413242if (!WPACKET_init(&wpkt, buf_mem))3243goto err;32443245if (!ossl_quic_wire_encode_frame_retire_conn_id(&wpkt, seq_num)) {3246WPACKET_cleanup(&wpkt);3247goto err;3248}32493250WPACKET_finish(&wpkt);3251if (!WPACKET_get_total_written(&wpkt, &l))3252goto err;32533254if (ossl_quic_cfq_add_frame(ch->cfq, 1, QUIC_PN_SPACE_APP,3255OSSL_QUIC_FRAME_TYPE_RETIRE_CONN_ID, 0,3256(unsigned char *)buf_mem->data, l,3257free_frame_data, NULL)3258== NULL)3259goto err;32603261buf_mem->data = NULL;3262BUF_MEM_free(buf_mem);3263return 1;32643265err:3266ossl_quic_channel_raise_protocol_error(ch,3267OSSL_QUIC_ERR_INTERNAL_ERROR,3268OSSL_QUIC_FRAME_TYPE_NEW_CONN_ID,3269"internal error enqueueing retire conn id");3270BUF_MEM_free(buf_mem);3271return 0;3272}32733274void ossl_quic_channel_on_new_conn_id(QUIC_CHANNEL *ch,3275OSSL_QUIC_FRAME_NEW_CONN_ID *f)3276{3277uint64_t new_remote_seq_num = ch->cur_remote_seq_num;3278uint64_t new_retire_prior_to = ch->cur_retire_prior_to;32793280if (!ossl_quic_channel_is_active(ch))3281return;32823283/* We allow only two active connection ids; first check some constraints */3284if (ch->cur_remote_dcid.id_len == 0) {3285/* Changing from 0 length connection id is disallowed */3286ossl_quic_channel_raise_protocol_error(ch,3287OSSL_QUIC_ERR_PROTOCOL_VIOLATION,3288OSSL_QUIC_FRAME_TYPE_NEW_CONN_ID,3289"zero length connection id in use");32903291return;3292}32933294if (f->seq_num > new_remote_seq_num)3295new_remote_seq_num = f->seq_num;3296if (f->retire_prior_to > new_retire_prior_to)3297new_retire_prior_to = f->retire_prior_to;32983299/*3300* RFC 9000-5.1.1: An endpoint MUST NOT provide more connection IDs3301* than the peer's limit.3302*3303* After processing a NEW_CONNECTION_ID frame and adding and retiring3304* active connection IDs, if the number of active connection IDs exceeds3305* the value advertised in its active_connection_id_limit transport3306* parameter, an endpoint MUST close the connection with an error of3307* type CONNECTION_ID_LIMIT_ERROR.3308*/3309if (new_remote_seq_num - new_retire_prior_to > 1) {3310ossl_quic_channel_raise_protocol_error(ch,3311OSSL_QUIC_ERR_CONNECTION_ID_LIMIT_ERROR,3312OSSL_QUIC_FRAME_TYPE_NEW_CONN_ID,3313"active_connection_id limit violated");3314return;3315}33163317/*3318* RFC 9000-5.1.1: An endpoint MAY send connection IDs that temporarily3319* exceed a peer's limit if the NEW_CONNECTION_ID frame also requires3320* the retirement of any excess, by including a sufficiently large3321* value in the Retire Prior To field.3322*3323* RFC 9000-5.1.2: An endpoint SHOULD allow for sending and tracking3324* a number of RETIRE_CONNECTION_ID frames of at least twice the value3325* of the active_connection_id_limit transport parameter. An endpoint3326* MUST NOT forget a connection ID without retiring it, though it MAY3327* choose to treat having connection IDs in need of retirement that3328* exceed this limit as a connection error of type CONNECTION_ID_LIMIT_ERROR.3329*3330* We are a little bit more liberal than the minimum mandated.3331*/3332if (new_retire_prior_to - ch->cur_retire_prior_to > 10) {3333ossl_quic_channel_raise_protocol_error(ch,3334OSSL_QUIC_ERR_CONNECTION_ID_LIMIT_ERROR,3335OSSL_QUIC_FRAME_TYPE_NEW_CONN_ID,3336"retiring connection id limit violated");33373338return;3339}33403341if (new_remote_seq_num > ch->cur_remote_seq_num) {3342/* Add new stateless reset token */3343if (!ossl_quic_srtm_add(ch->srtm, ch, new_remote_seq_num,3344&f->stateless_reset)) {3345ossl_quic_channel_raise_protocol_error(3346ch, OSSL_QUIC_ERR_CONNECTION_ID_LIMIT_ERROR,3347OSSL_QUIC_FRAME_TYPE_NEW_CONN_ID,3348"unable to store stateless reset token");33493350return;3351}3352ch->cur_remote_seq_num = new_remote_seq_num;3353ch->cur_remote_dcid = f->conn_id;3354ossl_quic_tx_packetiser_set_cur_dcid(ch->txp, &ch->cur_remote_dcid);3355}33563357/*3358* RFC 9000-5.1.2: Upon receipt of an increased Retire Prior To3359* field, the peer MUST stop using the corresponding connection IDs3360* and retire them with RETIRE_CONNECTION_ID frames before adding the3361* newly provided connection ID to the set of active connection IDs.3362*/33633364/*3365* Note: RFC 9000 s. 19.15 says:3366* "An endpoint that receives a NEW_CONNECTION_ID frame with a sequence3367* number smaller than the Retire Prior To field of a previously received3368* NEW_CONNECTION_ID frame MUST send a corresponding3369* RETIRE_CONNECTION_ID frame that retires the newly received connection3370* ID, unless it has already done so for that sequence number."3371*3372* Since we currently always queue RETIRE_CONN_ID frames based on the Retire3373* Prior To field of a NEW_CONNECTION_ID frame immediately upon receiving3374* that NEW_CONNECTION_ID frame, by definition this will always be met.3375* This may change in future when we change our CID handling.3376*/3377while (new_retire_prior_to > ch->cur_retire_prior_to) {3378if (!ch_enqueue_retire_conn_id(ch, ch->cur_retire_prior_to))3379break;3380++ch->cur_retire_prior_to;3381}3382}33833384static void ch_save_err_state(QUIC_CHANNEL *ch)3385{3386if (ch->err_state == NULL)3387ch->err_state = OSSL_ERR_STATE_new();33883389if (ch->err_state == NULL)3390return;33913392OSSL_ERR_STATE_save(ch->err_state);3393}33943395void ossl_quic_channel_inject(QUIC_CHANNEL *ch, QUIC_URXE *e)3396{3397ossl_qrx_inject_urxe(ch->qrx, e);3398}33993400void ossl_quic_channel_inject_pkt(QUIC_CHANNEL *ch, OSSL_QRX_PKT *qpkt)3401{3402ossl_qrx_inject_pkt(ch->qrx, qpkt);3403}34043405void ossl_quic_channel_on_stateless_reset(QUIC_CHANNEL *ch)3406{3407QUIC_TERMINATE_CAUSE tcause = { 0 };34083409tcause.error_code = OSSL_QUIC_ERR_NO_ERROR;3410tcause.remote = 1;3411ch_start_terminating(ch, &tcause, 0);3412}34133414void ossl_quic_channel_raise_net_error(QUIC_CHANNEL *ch)3415{3416QUIC_TERMINATE_CAUSE tcause = { 0 };34173418if (ch->net_error)3419return;34203421ch->net_error = 1;34223423tcause.error_code = OSSL_QUIC_ERR_INTERNAL_ERROR;3424tcause.reason = "network BIO I/O error";3425tcause.reason_len = strlen(tcause.reason);34263427/*3428* Skip Terminating state and go directly to Terminated, no point trying to3429* send CONNECTION_CLOSE if we cannot communicate.3430*/3431ch_start_terminating(ch, &tcause, 1);3432}34333434int ossl_quic_channel_net_error(QUIC_CHANNEL *ch)3435{3436return ch->net_error;3437}34383439void ossl_quic_channel_restore_err_state(QUIC_CHANNEL *ch)3440{3441if (ch == NULL)3442return;34433444if (!ossl_quic_port_is_running(ch->port))3445ossl_quic_port_restore_err_state(ch->port);3446else3447OSSL_ERR_STATE_restore(ch->err_state);3448}34493450void ossl_quic_channel_raise_protocol_error_loc(QUIC_CHANNEL *ch,3451uint64_t error_code,3452uint64_t frame_type,3453const char *reason,3454ERR_STATE *err_state,3455const char *src_file,3456int src_line,3457const char *src_func)3458{3459QUIC_TERMINATE_CAUSE tcause = { 0 };3460int err_reason = error_code == OSSL_QUIC_ERR_INTERNAL_ERROR3461? ERR_R_INTERNAL_ERROR3462: SSL_R_QUIC_PROTOCOL_ERROR;3463const char *err_str = ossl_quic_err_to_string(error_code);3464const char *err_str_pfx = " (", *err_str_sfx = ")";3465const char *ft_str = NULL;3466const char *ft_str_pfx = " (", *ft_str_sfx = ")";34673468if (ch->protocol_error)3469/* Only the first call to this function matters. */3470return;34713472if (err_str == NULL) {3473err_str = "";3474err_str_pfx = "";3475err_str_sfx = "";3476}34773478/*3479* If we were provided an underlying error state, restore it and then append3480* our ERR on top as a "cover letter" error.3481*/3482if (err_state != NULL)3483OSSL_ERR_STATE_restore(err_state);34843485if (frame_type != 0) {3486ft_str = ossl_quic_frame_type_to_string(frame_type);3487if (ft_str == NULL) {3488ft_str = "";3489ft_str_pfx = "";3490ft_str_sfx = "";3491}34923493ERR_raise_data(ERR_LIB_SSL, err_reason,3494"QUIC error code: 0x%llx%s%s%s "3495"(triggered by frame type: 0x%llx%s%s%s), reason: \"%s\"",3496(unsigned long long)error_code,3497err_str_pfx, err_str, err_str_sfx,3498(unsigned long long)frame_type,3499ft_str_pfx, ft_str, ft_str_sfx,3500reason);3501} else {3502ERR_raise_data(ERR_LIB_SSL, err_reason,3503"QUIC error code: 0x%llx%s%s%s, reason: \"%s\"",3504(unsigned long long)error_code,3505err_str_pfx, err_str, err_str_sfx,3506reason);3507}35083509if (src_file != NULL)3510ERR_set_debug(src_file, src_line, src_func);35113512ch_save_err_state(ch);35133514tcause.error_code = error_code;3515tcause.frame_type = frame_type;3516tcause.reason = reason;3517tcause.reason_len = strlen(reason);35183519ch->protocol_error = 1;3520ch_start_terminating(ch, &tcause, 0);3521}35223523/*3524* Called once the terminating timer expires, meaning we move from TERMINATING3525* to TERMINATED.3526*/3527static void ch_on_terminating_timeout(QUIC_CHANNEL *ch)3528{3529ch_record_state_transition(ch, QUIC_CHANNEL_STATE_TERMINATED);3530}35313532/*3533* Determines the effective idle timeout duration. This is based on the idle3534* timeout values that we and our peer signalled in transport parameters3535* but have some limits applied.3536*/3537static OSSL_TIME ch_get_effective_idle_timeout_duration(QUIC_CHANNEL *ch)3538{3539OSSL_TIME pto;35403541if (ch->max_idle_timeout == 0)3542return ossl_time_infinite();35433544/*3545* RFC 9000 s. 10.1: Idle Timeout3546* To avoid excessively small idle timeout periods, endpoints3547* MUST increase the idle timeout period to be at least three3548* times the current Probe Timeout (PTO). This allows for3549* multiple PTOs to expire, and therefore multiple probes to3550* be sent and lost, prior to idle timeout.3551*/3552pto = ossl_ackm_get_pto_duration(ch->ackm);3553return ossl_time_max(ossl_ms2time(ch->max_idle_timeout),3554ossl_time_multiply(pto, 3));3555}35563557/*3558* Updates our idle deadline. Called when an event happens which should bump the3559* idle timeout.3560*/3561static void ch_update_idle(QUIC_CHANNEL *ch)3562{3563ch->idle_deadline = ossl_time_add(get_time(ch),3564ch_get_effective_idle_timeout_duration(ch));3565}35663567/*3568* Updates our ping deadline, which determines when we next generate a ping if3569* we don't have any other ACK-eliciting frames to send.3570*/3571static void ch_update_ping_deadline(QUIC_CHANNEL *ch)3572{3573OSSL_TIME max_span, idle_duration;35743575idle_duration = ch_get_effective_idle_timeout_duration(ch);3576if (ossl_time_is_infinite(idle_duration)) {3577ch->ping_deadline = ossl_time_infinite();3578return;3579}35803581/*3582* Maximum amount of time without traffic before we send a PING to keep3583* the connection open. Usually we use max_idle_timeout/2, but ensure3584* the period never exceeds the assumed NAT interval to ensure NAT3585* devices don't have their state time out (RFC 9000 s. 10.1.2).3586*/3587max_span = ossl_time_divide(idle_duration, 2);3588max_span = ossl_time_min(max_span, MAX_NAT_INTERVAL);3589ch->ping_deadline = ossl_time_add(get_time(ch), max_span);3590}35913592/* Called when the idle timeout expires. */3593static void ch_on_idle_timeout(QUIC_CHANNEL *ch)3594{3595/*3596* Idle timeout does not have an error code associated with it because a3597* CONN_CLOSE is never sent for it. We shouldn't use this data once we reach3598* TERMINATED anyway.3599*/3600ch->terminate_cause.app = 0;3601ch->terminate_cause.error_code = OSSL_QUIC_LOCAL_ERR_IDLE_TIMEOUT;3602ch->terminate_cause.frame_type = 0;36033604ch_record_state_transition(ch, QUIC_CHANNEL_STATE_TERMINATED);3605}36063607/**3608* @brief Common handler for initializing a new QUIC connection.3609*3610* This function configures a QUIC channel (`QUIC_CHANNEL *ch`) for a new3611* connection by setting the peer address, connection IDs, and necessary3612* callbacks. It establishes initial secrets, sets up logging, and performs3613* required transitions for the channel state.3614*3615* @param ch Pointer to the QUIC channel being initialized.3616* @param peer Address of the peer to which the channel connects.3617* @param peer_scid Peer-specified source connection ID.3618* @param peer_dcid Peer-specified destination connection ID.3619* @param peer_odcid Peer-specified original destination connection ID3620* may be NULL if retry frame not sent to client3621* @return 1 on success, 0 on failure to set required elements.3622*/3623static int ch_on_new_conn_common(QUIC_CHANNEL *ch, const BIO_ADDR *peer,3624const QUIC_CONN_ID *peer_scid,3625const QUIC_CONN_ID *peer_dcid,3626const QUIC_CONN_ID *peer_odcid)3627{3628/* Note our newly learnt peer address and CIDs. */3629if (!BIO_ADDR_copy(&ch->cur_peer_addr, peer))3630return 0;36313632ch->init_dcid = *peer_dcid;3633ch->cur_remote_dcid = *peer_scid;3634ch->odcid.id_len = 0;36353636if (peer_odcid != NULL)3637ch->odcid = *peer_odcid;36383639/* Inform QTX of peer address. */3640if (!ossl_quic_tx_packetiser_set_peer(ch->txp, &ch->cur_peer_addr))3641return 0;36423643/* Inform TXP of desired CIDs. */3644if (!ossl_quic_tx_packetiser_set_cur_dcid(ch->txp, &ch->cur_remote_dcid))3645return 0;36463647if (!ossl_quic_tx_packetiser_set_cur_scid(ch->txp, &ch->cur_local_cid))3648return 0;36493650/* Setup QLOG, which did not happen earlier due to lacking an Initial ODCID. */3651ossl_qtx_set_qlog_cb(ch->qtx, ch_get_qlog_cb, ch);3652ossl_quic_tx_packetiser_set_qlog_cb(ch->txp, ch_get_qlog_cb, ch);36533654/*3655* Plug in secrets for the Initial EL. secrets for QRX were created in3656* port_default_packet_handler() already.3657*/3658if (!ossl_quic_provide_initial_secret(ch->port->engine->libctx,3659ch->port->engine->propq,3660&ch->init_dcid,3661/*is_server=*/1,3662NULL, ch->qtx))3663return 0;36643665/* Register the peer ODCID in the LCIDM. */3666if (!ossl_quic_lcidm_enrol_odcid(ch->lcidm, ch, peer_odcid == NULL ? &ch->init_dcid : peer_odcid))3667return 0;36683669/* Change state. */3670ch_record_state_transition(ch, QUIC_CHANNEL_STATE_ACTIVE);3671ch->doing_proactive_ver_neg = 0; /* not currently supported */3672return 1;3673}36743675/* Called when we, as a server, get a new incoming connection. */3676int ossl_quic_channel_on_new_conn(QUIC_CHANNEL *ch, const BIO_ADDR *peer,3677const QUIC_CONN_ID *peer_scid,3678const QUIC_CONN_ID *peer_dcid)3679{3680if (!ossl_assert(ch->state == QUIC_CHANNEL_STATE_IDLE && ch->is_server))3681return 0;36823683/* Generate an Initial LCID we will use for the connection. */3684if (!ossl_quic_lcidm_generate_initial(ch->lcidm, ch, &ch->cur_local_cid))3685return 0;36863687return ch_on_new_conn_common(ch, peer, peer_scid, peer_dcid, NULL);3688}36893690/**3691* Binds a QUIC channel to a specific peer's address and connection IDs.3692*3693* This function is used to establish a binding between a QUIC channel and a3694* peer's address and connection IDs. The binding is performed only if the3695* channel is idle and is on the server side. The peer's destination connection3696* ID (`peer_dcid`) is mandatory, and the channel's current local connection ID3697* is set to this value.3698*3699* @param ch Pointer to the QUIC_CHANNEL structure representing the3700* channel to be bound.3701* @param peer Pointer to a BIO_ADDR structure representing the peer's3702* address.3703* @param peer_scid Pointer to the peer's source connection ID (QUIC_CONN_ID).3704* @param peer_dcid Pointer to the peer's destination connection ID3705* (QUIC_CONN_ID). This must not be NULL.3706* @param peer_odcid Pointer to the original destination connection ID3707* (QUIC_CONN_ID) chosen by the peer in its first initial3708* packet received without a token.3709*3710* @return 1 on success, or 0 on failure if the conditions for binding are not3711* met (e.g., channel is not idle or not a server, or binding fails).3712*/3713int ossl_quic_bind_channel(QUIC_CHANNEL *ch, const BIO_ADDR *peer,3714const QUIC_CONN_ID *peer_scid,3715const QUIC_CONN_ID *peer_dcid,3716const QUIC_CONN_ID *peer_odcid)3717{3718if (peer_dcid == NULL)3719return 0;37203721if (!ossl_assert(ch->state == QUIC_CHANNEL_STATE_IDLE && ch->is_server))3722return 0;37233724ch->cur_local_cid = *peer_dcid;3725if (!ossl_quic_lcidm_bind_channel(ch->lcidm, ch, peer_dcid))3726return 0;37273728/*3729* peer_odcid <=> is initial dst conn id chosen by peer in its3730* first initial packet we received without token.3731*/3732return ch_on_new_conn_common(ch, peer, peer_scid, peer_dcid, peer_odcid);3733}37343735SSL *ossl_quic_channel_get0_ssl(QUIC_CHANNEL *ch)3736{3737return ch->tls;3738}37393740static int ch_init_new_stream(QUIC_CHANNEL *ch, QUIC_STREAM *qs,3741int can_send, int can_recv)3742{3743uint64_t rxfc_wnd;3744int server_init = ossl_quic_stream_is_server_init(qs);3745int local_init = (ch->is_server == server_init);3746int is_uni = !ossl_quic_stream_is_bidi(qs);37473748if (can_send)3749if ((qs->sstream = ossl_quic_sstream_new(INIT_APP_BUF_LEN)) == NULL)3750goto err;37513752if (can_recv)3753if ((qs->rstream = ossl_quic_rstream_new(NULL, NULL, 0)) == NULL)3754goto err;37553756/* TXFC */3757if (!ossl_quic_txfc_init(&qs->txfc, &ch->conn_txfc))3758goto err;37593760if (ch->got_remote_transport_params) {3761/*3762* If we already got peer TPs we need to apply the initial CWM credit3763* now. If we didn't already get peer TPs this will be done3764* automatically for all extant streams when we do.3765*/3766if (can_send) {3767uint64_t cwm;37683769if (is_uni)3770cwm = ch->rx_init_max_stream_data_uni;3771else if (local_init)3772cwm = ch->rx_init_max_stream_data_bidi_local;3773else3774cwm = ch->rx_init_max_stream_data_bidi_remote;37753776ossl_quic_txfc_bump_cwm(&qs->txfc, cwm);3777}3778}37793780/* RXFC */3781if (!can_recv)3782rxfc_wnd = 0;3783else if (is_uni)3784rxfc_wnd = ch->tx_init_max_stream_data_uni;3785else if (local_init)3786rxfc_wnd = ch->tx_init_max_stream_data_bidi_local;3787else3788rxfc_wnd = ch->tx_init_max_stream_data_bidi_remote;37893790if (!ossl_quic_rxfc_init(&qs->rxfc, &ch->conn_rxfc,3791rxfc_wnd,3792DEFAULT_STREAM_RXFC_MAX_WND_MUL * rxfc_wnd,3793get_time, ch))3794goto err;37953796return 1;37973798err:3799ossl_quic_sstream_free(qs->sstream);3800qs->sstream = NULL;3801ossl_quic_rstream_free(qs->rstream);3802qs->rstream = NULL;3803return 0;3804}38053806static uint64_t *ch_get_local_stream_next_ordinal_ptr(QUIC_CHANNEL *ch,3807int is_uni)3808{3809return is_uni ? &ch->next_local_stream_ordinal_uni3810: &ch->next_local_stream_ordinal_bidi;3811}38123813static const uint64_t *ch_get_local_stream_max_ptr(const QUIC_CHANNEL *ch,3814int is_uni)3815{3816return is_uni ? &ch->max_local_streams_uni3817: &ch->max_local_streams_bidi;3818}38193820static const QUIC_RXFC *ch_get_remote_stream_count_rxfc(const QUIC_CHANNEL *ch,3821int is_uni)3822{3823return is_uni ? &ch->max_streams_uni_rxfc3824: &ch->max_streams_bidi_rxfc;3825}38263827int ossl_quic_channel_is_new_local_stream_admissible(QUIC_CHANNEL *ch,3828int is_uni)3829{3830const uint64_t *p_next_ordinal = ch_get_local_stream_next_ordinal_ptr(ch, is_uni);38313832return ossl_quic_stream_map_is_local_allowed_by_stream_limit(&ch->qsm,3833*p_next_ordinal,3834is_uni);3835}38363837uint64_t ossl_quic_channel_get_local_stream_count_avail(const QUIC_CHANNEL *ch,3838int is_uni)3839{3840const uint64_t *p_next_ordinal, *p_max;38413842p_next_ordinal = ch_get_local_stream_next_ordinal_ptr((QUIC_CHANNEL *)ch,3843is_uni);3844p_max = ch_get_local_stream_max_ptr(ch, is_uni);38453846return *p_max - *p_next_ordinal;3847}38483849uint64_t ossl_quic_channel_get_remote_stream_count_avail(const QUIC_CHANNEL *ch,3850int is_uni)3851{3852return ossl_quic_rxfc_get_credit(ch_get_remote_stream_count_rxfc(ch, is_uni));3853}38543855QUIC_STREAM *ossl_quic_channel_new_stream_local(QUIC_CHANNEL *ch, int is_uni)3856{3857QUIC_STREAM *qs;3858int type;3859uint64_t stream_id;3860uint64_t *p_next_ordinal;38613862type = ch->is_server ? QUIC_STREAM_INITIATOR_SERVER3863: QUIC_STREAM_INITIATOR_CLIENT;38643865p_next_ordinal = ch_get_local_stream_next_ordinal_ptr(ch, is_uni);38663867if (is_uni)3868type |= QUIC_STREAM_DIR_UNI;3869else3870type |= QUIC_STREAM_DIR_BIDI;38713872if (*p_next_ordinal >= ((uint64_t)1) << 62)3873return NULL;38743875stream_id = ((*p_next_ordinal) << 2) | type;38763877if ((qs = ossl_quic_stream_map_alloc(&ch->qsm, stream_id, type)) == NULL)3878return NULL;38793880/* Locally-initiated stream, so we always want a send buffer. */3881if (!ch_init_new_stream(ch, qs, /*can_send=*/1, /*can_recv=*/!is_uni))3882goto err;38833884++*p_next_ordinal;3885return qs;38863887err:3888ossl_quic_stream_map_release(&ch->qsm, qs);3889return NULL;3890}38913892QUIC_STREAM *ossl_quic_channel_new_stream_remote(QUIC_CHANNEL *ch,3893uint64_t stream_id)3894{3895uint64_t peer_role;3896int is_uni;3897QUIC_STREAM *qs;38983899peer_role = ch->is_server3900? QUIC_STREAM_INITIATOR_CLIENT3901: QUIC_STREAM_INITIATOR_SERVER;39023903if ((stream_id & QUIC_STREAM_INITIATOR_MASK) != peer_role)3904return NULL;39053906is_uni = ((stream_id & QUIC_STREAM_DIR_MASK) == QUIC_STREAM_DIR_UNI);39073908qs = ossl_quic_stream_map_alloc(&ch->qsm, stream_id,3909stream_id & (QUIC_STREAM_INITIATOR_MASK | QUIC_STREAM_DIR_MASK));3910if (qs == NULL)3911return NULL;39123913if (!ch_init_new_stream(ch, qs, /*can_send=*/!is_uni, /*can_recv=*/1))3914goto err;39153916if (ch->incoming_stream_auto_reject)3917ossl_quic_channel_reject_stream(ch, qs);3918else3919ossl_quic_stream_map_push_accept_queue(&ch->qsm, qs);39203921return qs;39223923err:3924ossl_quic_stream_map_release(&ch->qsm, qs);3925return NULL;3926}39273928void ossl_quic_channel_set_incoming_stream_auto_reject(QUIC_CHANNEL *ch,3929int enable,3930uint64_t aec)3931{3932ch->incoming_stream_auto_reject = (enable != 0);3933ch->incoming_stream_auto_reject_aec = aec;3934}39353936void ossl_quic_channel_reject_stream(QUIC_CHANNEL *ch, QUIC_STREAM *qs)3937{3938ossl_quic_stream_map_stop_sending_recv_part(&ch->qsm, qs,3939ch->incoming_stream_auto_reject_aec);39403941ossl_quic_stream_map_reset_stream_send_part(&ch->qsm, qs,3942ch->incoming_stream_auto_reject_aec);3943qs->deleted = 1;39443945ossl_quic_stream_map_update_state(&ch->qsm, qs);3946}39473948/* Replace local connection ID in TXP and DEMUX for testing purposes. */3949int ossl_quic_channel_replace_local_cid(QUIC_CHANNEL *ch,3950const QUIC_CONN_ID *conn_id)3951{3952/* Remove the current LCID from the LCIDM. */3953if (!ossl_quic_lcidm_debug_remove(ch->lcidm, &ch->cur_local_cid))3954return 0;3955ch->cur_local_cid = *conn_id;3956/* Set in the TXP, used only for long header packets. */3957if (!ossl_quic_tx_packetiser_set_cur_scid(ch->txp, &ch->cur_local_cid))3958return 0;3959/* Add the new LCID to the LCIDM. */3960if (!ossl_quic_lcidm_debug_add(ch->lcidm, ch, &ch->cur_local_cid,3961100))3962return 0;3963return 1;3964}39653966void ossl_quic_channel_set_msg_callback(QUIC_CHANNEL *ch,3967ossl_msg_cb msg_callback,3968SSL *msg_callback_ssl)3969{3970ch->msg_callback = msg_callback;3971ch->msg_callback_ssl = msg_callback_ssl;3972ossl_qtx_set_msg_callback(ch->qtx, msg_callback, msg_callback_ssl);3973ossl_quic_tx_packetiser_set_msg_callback(ch->txp, msg_callback,3974msg_callback_ssl);3975/*3976* postpone msg callback setting for tserver until port calls3977* port_bind_channel().3978*/3979if (ch->is_tserver_ch == 0)3980ossl_qrx_set_msg_callback(ch->qrx, msg_callback, msg_callback_ssl);3981}39823983void ossl_quic_channel_set_msg_callback_arg(QUIC_CHANNEL *ch,3984void *msg_callback_arg)3985{3986ch->msg_callback_arg = msg_callback_arg;3987ossl_qtx_set_msg_callback_arg(ch->qtx, msg_callback_arg);3988ossl_quic_tx_packetiser_set_msg_callback_arg(ch->txp, msg_callback_arg);39893990/*3991* postpone msg callback setting for tserver until port calls3992* port_bind_channel().3993*/3994if (ch->is_tserver_ch == 0)3995ossl_qrx_set_msg_callback_arg(ch->qrx, msg_callback_arg);3996}39973998void ossl_quic_channel_set_txku_threshold_override(QUIC_CHANNEL *ch,3999uint64_t tx_pkt_threshold)4000{4001ch->txku_threshold_override = tx_pkt_threshold;4002}40034004uint64_t ossl_quic_channel_get_tx_key_epoch(QUIC_CHANNEL *ch)4005{4006return ossl_qtx_get_key_epoch(ch->qtx);4007}40084009uint64_t ossl_quic_channel_get_rx_key_epoch(QUIC_CHANNEL *ch)4010{4011return ossl_qrx_get_key_epoch(ch->qrx);4012}40134014int ossl_quic_channel_trigger_txku(QUIC_CHANNEL *ch)4015{4016if (!txku_allowed(ch))4017return 0;40184019ch->ku_locally_initiated = 1;4020ch_trigger_txku(ch);4021return 1;4022}40234024int ossl_quic_channel_ping(QUIC_CHANNEL *ch)4025{4026int pn_space = ossl_quic_enc_level_to_pn_space(ch->tx_enc_level);40274028ossl_quic_tx_packetiser_schedule_ack_eliciting(ch->txp, pn_space);40294030return 1;4031}40324033uint16_t ossl_quic_channel_get_diag_num_rx_ack(QUIC_CHANNEL *ch)4034{4035return ch->diag_num_rx_ack;4036}40374038void ossl_quic_channel_get_diag_local_cid(QUIC_CHANNEL *ch, QUIC_CONN_ID *cid)4039{4040*cid = ch->cur_local_cid;4041}40424043int ossl_quic_channel_have_generated_transport_params(const QUIC_CHANNEL *ch)4044{4045return ch->got_local_transport_params;4046}40474048void ossl_quic_channel_set_max_idle_timeout_request(QUIC_CHANNEL *ch, uint64_t ms)4049{4050ch->max_idle_timeout_local_req = ms;4051}4052uint64_t ossl_quic_channel_get_max_idle_timeout_request(const QUIC_CHANNEL *ch)4053{4054return ch->max_idle_timeout_local_req;4055}40564057uint64_t ossl_quic_channel_get_max_idle_timeout_peer_request(const QUIC_CHANNEL *ch)4058{4059return ch->max_idle_timeout_remote_req;4060}40614062uint64_t ossl_quic_channel_get_max_idle_timeout_actual(const QUIC_CHANNEL *ch)4063{4064return ch->max_idle_timeout;4065}406640674068