Path: blob/main/crypto/openssl/ssl/quic/quic_tserver.c
107436 views
/*1* Copyright 2022-2025 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 "internal/quic_tserver.h"10#include "internal/quic_channel.h"11#include "internal/quic_statm.h"12#include "internal/quic_port.h"13#include "internal/quic_engine.h"14#include "internal/common.h"15#include "internal/time.h"16#include "quic_local.h"1718/*19* QUIC Test Server Module20* =======================21*/22struct quic_tserver_st {23QUIC_TSERVER_ARGS args;2425/* Dummy SSL object for this QUIC connection for use by msg_callback */26SSL *ssl;2728/*29* The QUIC engine, port and channel providing the core QUIC connection30* implementation.31*/32QUIC_ENGINE *engine;33QUIC_PORT *port;34QUIC_CHANNEL *ch;3536/* The mutex we give to the QUIC channel. */37CRYPTO_MUTEX *mutex;3839/* SSL_CTX for creating the underlying TLS connection */40SSL_CTX *ctx;4142/* SSL for the underlying TLS connection */43SSL *tls;4445/* Are we connected to a peer? */46unsigned int connected : 1;47};4849static int alpn_select_cb(SSL *ssl, const unsigned char **out,50unsigned char *outlen, const unsigned char *in,51unsigned int inlen, void *arg)52{53QUIC_TSERVER *srv = arg;54static const unsigned char alpndeflt[] = {558, 'o', 's', 's', 'l', 't', 'e', 's', 't'56};57const unsigned char *alpn;58size_t alpnlen;5960if (srv->args.alpn == NULL) {61alpn = alpndeflt;62alpnlen = sizeof(alpndeflt);63} else {64alpn = srv->args.alpn;65alpnlen = srv->args.alpnlen;66}6768if (SSL_select_next_proto((unsigned char **)out, outlen, alpn, alpnlen,69in, inlen)70!= OPENSSL_NPN_NEGOTIATED)71return SSL_TLSEXT_ERR_ALERT_FATAL;7273return SSL_TLSEXT_ERR_OK;74}7576QUIC_TSERVER *ossl_quic_tserver_new(const QUIC_TSERVER_ARGS *args,77const char *certfile, const char *keyfile)78{79QUIC_TSERVER *srv = NULL;80QUIC_ENGINE_ARGS engine_args = { 0 };81QUIC_PORT_ARGS port_args = { 0 };82QUIC_CONNECTION *qc = NULL;8384if (args->net_rbio == NULL || args->net_wbio == NULL)85goto err;8687if ((srv = OPENSSL_zalloc(sizeof(*srv))) == NULL)88goto err;8990srv->args = *args;9192#if defined(OPENSSL_THREADS)93if ((srv->mutex = ossl_crypto_mutex_new()) == NULL)94goto err;95#endif9697if (args->ctx != NULL)98srv->ctx = args->ctx;99else100srv->ctx = SSL_CTX_new_ex(srv->args.libctx, srv->args.propq,101TLS_method());102if (srv->ctx == NULL)103goto err;104105if (certfile != NULL106&& SSL_CTX_use_certificate_file(srv->ctx, certfile, SSL_FILETYPE_PEM) <= 0)107goto err;108109if (keyfile != NULL110&& SSL_CTX_use_PrivateKey_file(srv->ctx, keyfile, SSL_FILETYPE_PEM) <= 0)111goto err;112113SSL_CTX_set_alpn_select_cb(srv->ctx, alpn_select_cb, srv);114115srv->tls = SSL_new(srv->ctx);116if (srv->tls == NULL)117goto err;118119engine_args.libctx = srv->args.libctx;120engine_args.propq = srv->args.propq;121engine_args.mutex = srv->mutex;122123if ((srv->engine = ossl_quic_engine_new(&engine_args)) == NULL)124goto err;125126ossl_quic_engine_set_time_cb(srv->engine, srv->args.now_cb,127srv->args.now_cb_arg);128129port_args.channel_ctx = srv->ctx;130port_args.is_multi_conn = 1;131port_args.do_addr_validation = 1;132if ((srv->port = ossl_quic_engine_create_port(srv->engine, &port_args)) == NULL)133goto err;134135if ((srv->ch = ossl_quic_port_create_incoming(srv->port, srv->tls)) == NULL)136goto err;137138if (!ossl_quic_port_set_net_rbio(srv->port, srv->args.net_rbio)139|| !ossl_quic_port_set_net_wbio(srv->port, srv->args.net_wbio))140goto err;141142qc = OPENSSL_zalloc(sizeof(*qc));143if (qc == NULL)144goto err;145srv->ssl = (SSL *)qc;146qc->ch = srv->ch;147srv->ssl->type = SSL_TYPE_QUIC_CONNECTION;148149return srv;150151err:152if (srv != NULL) {153if (args->ctx == NULL)154SSL_CTX_free(srv->ctx);155SSL_free(srv->tls);156ossl_quic_channel_free(srv->ch);157ossl_quic_port_free(srv->port);158ossl_quic_engine_free(srv->engine);159#if defined(OPENSSL_THREADS)160ossl_crypto_mutex_free(&srv->mutex);161#endif162OPENSSL_free(qc);163}164165OPENSSL_free(srv);166return NULL;167}168169void ossl_quic_tserver_free(QUIC_TSERVER *srv)170{171if (srv == NULL)172return;173174SSL_free(srv->tls);175ossl_quic_channel_free(srv->ch);176ossl_quic_port_free(srv->port);177ossl_quic_engine_free(srv->engine);178BIO_free_all(srv->args.net_rbio);179BIO_free_all(srv->args.net_wbio);180OPENSSL_free(srv->ssl);181SSL_CTX_free(srv->ctx);182#if defined(OPENSSL_THREADS)183ossl_crypto_mutex_free(&srv->mutex);184#endif185OPENSSL_free(srv);186}187188/* Set mutator callbacks for test framework support */189int ossl_quic_tserver_set_plain_packet_mutator(QUIC_TSERVER *srv,190ossl_mutate_packet_cb mutatecb,191ossl_finish_mutate_cb finishmutatecb,192void *mutatearg)193{194return ossl_quic_channel_set_mutator(srv->ch, mutatecb, finishmutatecb,195mutatearg);196}197198int ossl_quic_tserver_set_handshake_mutator(QUIC_TSERVER *srv,199ossl_statem_mutate_handshake_cb mutate_handshake_cb,200ossl_statem_finish_mutate_handshake_cb finish_mutate_handshake_cb,201void *mutatearg)202{203return ossl_statem_set_mutator(ossl_quic_channel_get0_ssl(srv->ch),204mutate_handshake_cb,205finish_mutate_handshake_cb,206mutatearg);207}208209int ossl_quic_tserver_tick(QUIC_TSERVER *srv)210{211ossl_quic_reactor_tick(ossl_quic_channel_get_reactor(srv->ch), 0);212213if (ossl_quic_channel_is_active(srv->ch))214srv->connected = 1;215216return 1;217}218219int ossl_quic_tserver_is_connected(QUIC_TSERVER *srv)220{221return ossl_quic_channel_is_active(srv->ch);222}223224/* Returns 1 if the server is in any terminating or terminated state */225int ossl_quic_tserver_is_term_any(const QUIC_TSERVER *srv)226{227return ossl_quic_channel_is_term_any(srv->ch);228}229230const QUIC_TERMINATE_CAUSE *231ossl_quic_tserver_get_terminate_cause(const QUIC_TSERVER *srv)232{233return ossl_quic_channel_get_terminate_cause(srv->ch);234}235236/* Returns 1 if the server is in a terminated state */237int ossl_quic_tserver_is_terminated(const QUIC_TSERVER *srv)238{239return ossl_quic_channel_is_terminated(srv->ch);240}241242size_t ossl_quic_tserver_get_short_header_conn_id_len(const QUIC_TSERVER *srv)243{244return ossl_quic_channel_get_short_header_conn_id_len(srv->ch);245}246247int ossl_quic_tserver_is_handshake_confirmed(const QUIC_TSERVER *srv)248{249return ossl_quic_channel_is_handshake_confirmed(srv->ch);250}251252int ossl_quic_tserver_read(QUIC_TSERVER *srv,253uint64_t stream_id,254unsigned char *buf,255size_t buf_len,256size_t *bytes_read)257{258int is_fin = 0;259QUIC_STREAM *qs;260261qs = ossl_quic_stream_map_get_by_id(ossl_quic_channel_get_qsm(srv->ch),262stream_id);263if (qs == NULL) {264int is_client_init265= ((stream_id & QUIC_STREAM_INITIATOR_MASK)266== QUIC_STREAM_INITIATOR_CLIENT);267268/*269* A client-initiated stream might spontaneously come into existence, so270* allow trying to read on a client-initiated stream before it exists,271* assuming the connection is still active.272* Otherwise, fail.273*/274if (!is_client_init || !ossl_quic_channel_is_active(srv->ch))275return 0;276277*bytes_read = 0;278return 1;279}280281if (qs->recv_state == QUIC_RSTREAM_STATE_DATA_READ282|| !ossl_quic_stream_has_recv_buffer(qs))283return 0;284285if (!ossl_quic_rstream_read(qs->rstream, buf, buf_len,286bytes_read, &is_fin))287return 0;288289if (*bytes_read > 0) {290/*291* We have read at least one byte from the stream. Inform stream-level292* RXFC of the retirement of controlled bytes. Update the active stream293* status (the RXFC may now want to emit a frame granting more credit to294* the peer).295*/296OSSL_RTT_INFO rtt_info;297298ossl_statm_get_rtt_info(ossl_quic_channel_get_statm(srv->ch), &rtt_info);299300if (!ossl_quic_rxfc_on_retire(&qs->rxfc, *bytes_read,301rtt_info.smoothed_rtt))302return 0;303}304305if (is_fin)306ossl_quic_stream_map_notify_totally_read(ossl_quic_channel_get_qsm(srv->ch),307qs);308309if (*bytes_read > 0)310ossl_quic_stream_map_update_state(ossl_quic_channel_get_qsm(srv->ch), qs);311312return 1;313}314315int ossl_quic_tserver_has_read_ended(QUIC_TSERVER *srv, uint64_t stream_id)316{317QUIC_STREAM *qs;318unsigned char buf[1];319size_t bytes_read = 0;320int is_fin = 0;321322qs = ossl_quic_stream_map_get_by_id(ossl_quic_channel_get_qsm(srv->ch),323stream_id);324325if (qs == NULL)326return 0;327328if (qs->recv_state == QUIC_RSTREAM_STATE_DATA_READ)329return 1;330331if (!ossl_quic_stream_has_recv_buffer(qs))332return 0;333334/*335* If we do not have the DATA_READ, it is possible we should still return 1336* if there is a lone FIN (but no more data) remaining to be retired from337* the RSTREAM, for example because ossl_quic_tserver_read() has not been338* called since the FIN was received.339*/340if (!ossl_quic_rstream_peek(qs->rstream, buf, sizeof(buf),341&bytes_read, &is_fin))342return 0;343344if (is_fin && bytes_read == 0) {345/* If we have a FIN awaiting retirement and no data before it... */346/* Let RSTREAM know we've consumed this FIN. */347if (!ossl_quic_rstream_read(qs->rstream, buf, sizeof(buf),348&bytes_read, &is_fin))349return 0;350351assert(is_fin && bytes_read == 0);352assert(qs->recv_state == QUIC_RSTREAM_STATE_DATA_RECVD);353354ossl_quic_stream_map_notify_totally_read(ossl_quic_channel_get_qsm(srv->ch),355qs);356ossl_quic_stream_map_update_state(ossl_quic_channel_get_qsm(srv->ch), qs);357return 1;358}359360return 0;361}362363int ossl_quic_tserver_write(QUIC_TSERVER *srv,364uint64_t stream_id,365const unsigned char *buf,366size_t buf_len,367size_t *bytes_written)368{369QUIC_STREAM *qs;370371if (!ossl_quic_channel_is_active(srv->ch))372return 0;373374qs = ossl_quic_stream_map_get_by_id(ossl_quic_channel_get_qsm(srv->ch),375stream_id);376if (qs == NULL || !ossl_quic_stream_has_send_buffer(qs))377return 0;378379if (!ossl_quic_sstream_append(qs->sstream,380buf, buf_len, bytes_written))381return 0;382383if (*bytes_written > 0)384/*385* We have appended at least one byte to the stream. Potentially mark386* the stream as active, depending on FC.387*/388ossl_quic_stream_map_update_state(ossl_quic_channel_get_qsm(srv->ch), qs);389390/* Try and send. */391ossl_quic_tserver_tick(srv);392return 1;393}394395int ossl_quic_tserver_conclude(QUIC_TSERVER *srv, uint64_t stream_id)396{397QUIC_STREAM *qs;398399if (!ossl_quic_channel_is_active(srv->ch))400return 0;401402qs = ossl_quic_stream_map_get_by_id(ossl_quic_channel_get_qsm(srv->ch),403stream_id);404if (qs == NULL || !ossl_quic_stream_has_send_buffer(qs))405return 0;406407if (!ossl_quic_sstream_get_final_size(qs->sstream, NULL)) {408ossl_quic_sstream_fin(qs->sstream);409ossl_quic_stream_map_update_state(ossl_quic_channel_get_qsm(srv->ch), qs);410}411412ossl_quic_tserver_tick(srv);413return 1;414}415416int ossl_quic_tserver_stream_new(QUIC_TSERVER *srv,417int is_uni,418uint64_t *stream_id)419{420QUIC_STREAM *qs;421422if (!ossl_quic_channel_is_active(srv->ch))423return 0;424425if ((qs = ossl_quic_channel_new_stream_local(srv->ch, is_uni)) == NULL)426return 0;427428*stream_id = qs->id;429return 1;430}431432BIO *ossl_quic_tserver_get0_rbio(QUIC_TSERVER *srv)433{434return srv->args.net_rbio;435}436437SSL_CTX *ossl_quic_tserver_get0_ssl_ctx(QUIC_TSERVER *srv)438{439return srv->ctx;440}441442int ossl_quic_tserver_stream_has_peer_stop_sending(QUIC_TSERVER *srv,443uint64_t stream_id,444uint64_t *app_error_code)445{446QUIC_STREAM *qs;447448qs = ossl_quic_stream_map_get_by_id(ossl_quic_channel_get_qsm(srv->ch),449stream_id);450if (qs == NULL)451return 0;452453if (qs->peer_stop_sending && app_error_code != NULL)454*app_error_code = qs->peer_stop_sending_aec;455456return qs->peer_stop_sending;457}458459int ossl_quic_tserver_stream_has_peer_reset_stream(QUIC_TSERVER *srv,460uint64_t stream_id,461uint64_t *app_error_code)462{463QUIC_STREAM *qs;464465qs = ossl_quic_stream_map_get_by_id(ossl_quic_channel_get_qsm(srv->ch),466stream_id);467if (qs == NULL)468return 0;469470if (ossl_quic_stream_recv_is_reset(qs) && app_error_code != NULL)471*app_error_code = qs->peer_reset_stream_aec;472473return ossl_quic_stream_recv_is_reset(qs);474}475476int ossl_quic_tserver_set_new_local_cid(QUIC_TSERVER *srv,477const QUIC_CONN_ID *conn_id)478{479/* Replace existing local connection ID in the QUIC_CHANNEL */480return ossl_quic_channel_replace_local_cid(srv->ch, conn_id);481}482483uint64_t ossl_quic_tserver_pop_incoming_stream(QUIC_TSERVER *srv)484{485QUIC_STREAM_MAP *qsm = ossl_quic_channel_get_qsm(srv->ch);486QUIC_STREAM *qs = ossl_quic_stream_map_peek_accept_queue(qsm);487488if (qs == NULL)489return UINT64_MAX;490491ossl_quic_stream_map_remove_from_accept_queue(qsm, qs, ossl_time_zero());492493return qs->id;494}495496int ossl_quic_tserver_is_stream_totally_acked(QUIC_TSERVER *srv,497uint64_t stream_id)498{499QUIC_STREAM *qs;500501qs = ossl_quic_stream_map_get_by_id(ossl_quic_channel_get_qsm(srv->ch),502stream_id);503if (qs == NULL)504return 1;505506return ossl_quic_sstream_is_totally_acked(qs->sstream);507}508509int ossl_quic_tserver_get_net_read_desired(QUIC_TSERVER *srv)510{511return ossl_quic_reactor_net_read_desired(512ossl_quic_channel_get_reactor(srv->ch));513}514515int ossl_quic_tserver_get_net_write_desired(QUIC_TSERVER *srv)516{517return ossl_quic_reactor_net_write_desired(518ossl_quic_channel_get_reactor(srv->ch));519}520521OSSL_TIME ossl_quic_tserver_get_deadline(QUIC_TSERVER *srv)522{523return ossl_quic_reactor_get_tick_deadline(524ossl_quic_channel_get_reactor(srv->ch));525}526527int ossl_quic_tserver_shutdown(QUIC_TSERVER *srv, uint64_t app_error_code)528{529ossl_quic_channel_local_close(srv->ch, app_error_code, NULL);530531if (ossl_quic_channel_is_terminated(srv->ch))532return 1;533534ossl_quic_reactor_tick(ossl_quic_channel_get_reactor(srv->ch), 0);535536return ossl_quic_channel_is_terminated(srv->ch);537}538539int ossl_quic_tserver_ping(QUIC_TSERVER *srv)540{541if (ossl_quic_channel_is_terminated(srv->ch))542return 0;543544if (!ossl_quic_channel_ping(srv->ch))545return 0;546547ossl_quic_reactor_tick(ossl_quic_channel_get_reactor(srv->ch), 0);548return 1;549}550551QUIC_CHANNEL *ossl_quic_tserver_get_channel(QUIC_TSERVER *srv)552{553return srv->ch;554}555556void ossl_quic_tserver_set_msg_callback(QUIC_TSERVER *srv,557void (*f)(int write_p, int version,558int content_type,559const void *buf, size_t len,560SSL *ssl, void *arg),561void *arg)562{563ossl_quic_channel_set_msg_callback(srv->ch, f, srv->ssl);564ossl_quic_channel_set_msg_callback_arg(srv->ch, arg);565SSL_set_msg_callback(srv->tls, f);566SSL_set_msg_callback_arg(srv->tls, arg);567}568569int ossl_quic_tserver_new_ticket(QUIC_TSERVER *srv)570{571return SSL_new_session_ticket(srv->tls);572}573574int ossl_quic_tserver_set_max_early_data(QUIC_TSERVER *srv,575uint32_t max_early_data)576{577return SSL_set_max_early_data(srv->tls, max_early_data);578}579580void ossl_quic_tserver_set_psk_find_session_cb(QUIC_TSERVER *srv,581SSL_psk_find_session_cb_func cb)582{583SSL_set_psk_find_session_callback(srv->tls, cb);584}585586587