Path: blob/main/crypto/openssl/ssl/quic/quic_tserver.c
48266 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) != OPENSSL_NPN_NEGOTIATED)70return SSL_TLSEXT_ERR_ALERT_FATAL;7172return SSL_TLSEXT_ERR_OK;73}7475QUIC_TSERVER *ossl_quic_tserver_new(const QUIC_TSERVER_ARGS *args,76const char *certfile, const char *keyfile)77{78QUIC_TSERVER *srv = NULL;79QUIC_ENGINE_ARGS engine_args = {0};80QUIC_PORT_ARGS port_args = {0};81QUIC_CONNECTION *qc = NULL;8283if (args->net_rbio == NULL || args->net_wbio == NULL)84goto err;8586if ((srv = OPENSSL_zalloc(sizeof(*srv))) == NULL)87goto err;8889srv->args = *args;9091#if defined(OPENSSL_THREADS)92if ((srv->mutex = ossl_crypto_mutex_new()) == NULL)93goto err;94#endif9596if (args->ctx != NULL)97srv->ctx = args->ctx;98else99srv->ctx = SSL_CTX_new_ex(srv->args.libctx, srv->args.propq,100TLS_method());101if (srv->ctx == NULL)102goto err;103104if (certfile != NULL105&& SSL_CTX_use_certificate_file(srv->ctx, certfile, SSL_FILETYPE_PEM) <= 0)106goto err;107108if (keyfile != NULL109&& SSL_CTX_use_PrivateKey_file(srv->ctx, keyfile, SSL_FILETYPE_PEM) <= 0)110goto err;111112SSL_CTX_set_alpn_select_cb(srv->ctx, alpn_select_cb, srv);113114srv->tls = SSL_new(srv->ctx);115if (srv->tls == NULL)116goto err;117118engine_args.libctx = srv->args.libctx;119engine_args.propq = srv->args.propq;120engine_args.mutex = srv->mutex;121122if ((srv->engine = ossl_quic_engine_new(&engine_args)) == NULL)123goto err;124125ossl_quic_engine_set_time_cb(srv->engine, srv->args.now_cb,126srv->args.now_cb_arg);127128port_args.channel_ctx = srv->ctx;129port_args.is_multi_conn = 1;130port_args.do_addr_validation = 1;131if ((srv->port = ossl_quic_engine_create_port(srv->engine, &port_args)) == NULL)132goto err;133134if ((srv->ch = ossl_quic_port_create_incoming(srv->port, srv->tls)) == NULL)135goto err;136137if (!ossl_quic_port_set_net_rbio(srv->port, srv->args.net_rbio)138|| !ossl_quic_port_set_net_wbio(srv->port, srv->args.net_wbio))139goto err;140141qc = OPENSSL_zalloc(sizeof(*qc));142if (qc == NULL)143goto err;144srv->ssl = (SSL *)qc;145qc->ch = srv->ch;146srv->ssl->type = SSL_TYPE_QUIC_CONNECTION;147148return srv;149150err:151if (srv != NULL) {152if (args->ctx == NULL)153SSL_CTX_free(srv->ctx);154SSL_free(srv->tls);155ossl_quic_channel_free(srv->ch);156ossl_quic_port_free(srv->port);157ossl_quic_engine_free(srv->engine);158#if defined(OPENSSL_THREADS)159ossl_crypto_mutex_free(&srv->mutex);160#endif161OPENSSL_free(qc);162}163164OPENSSL_free(srv);165return NULL;166}167168void ossl_quic_tserver_free(QUIC_TSERVER *srv)169{170if (srv == NULL)171return;172173SSL_free(srv->tls);174ossl_quic_channel_free(srv->ch);175ossl_quic_port_free(srv->port);176ossl_quic_engine_free(srv->engine);177BIO_free_all(srv->args.net_rbio);178BIO_free_all(srv->args.net_wbio);179OPENSSL_free(srv->ssl);180SSL_CTX_free(srv->ctx);181#if defined(OPENSSL_THREADS)182ossl_crypto_mutex_free(&srv->mutex);183#endif184OPENSSL_free(srv);185}186187/* Set mutator callbacks for test framework support */188int ossl_quic_tserver_set_plain_packet_mutator(QUIC_TSERVER *srv,189ossl_mutate_packet_cb mutatecb,190ossl_finish_mutate_cb finishmutatecb,191void *mutatearg)192{193return ossl_quic_channel_set_mutator(srv->ch, mutatecb, finishmutatecb,194mutatearg);195}196197int ossl_quic_tserver_set_handshake_mutator(QUIC_TSERVER *srv,198ossl_statem_mutate_handshake_cb mutate_handshake_cb,199ossl_statem_finish_mutate_handshake_cb finish_mutate_handshake_cb,200void *mutatearg)201{202return ossl_statem_set_mutator(ossl_quic_channel_get0_ssl(srv->ch),203mutate_handshake_cb,204finish_mutate_handshake_cb,205mutatearg);206}207208int ossl_quic_tserver_tick(QUIC_TSERVER *srv)209{210ossl_quic_reactor_tick(ossl_quic_channel_get_reactor(srv->ch), 0);211212if (ossl_quic_channel_is_active(srv->ch))213srv->connected = 1;214215return 1;216}217218int ossl_quic_tserver_is_connected(QUIC_TSERVER *srv)219{220return ossl_quic_channel_is_active(srv->ch);221}222223/* Returns 1 if the server is in any terminating or terminated state */224int ossl_quic_tserver_is_term_any(const QUIC_TSERVER *srv)225{226return ossl_quic_channel_is_term_any(srv->ch);227}228229const QUIC_TERMINATE_CAUSE *230ossl_quic_tserver_get_terminate_cause(const QUIC_TSERVER *srv)231{232return ossl_quic_channel_get_terminate_cause(srv->ch);233}234235/* Returns 1 if the server is in a terminated state */236int ossl_quic_tserver_is_terminated(const QUIC_TSERVER *srv)237{238return ossl_quic_channel_is_terminated(srv->ch);239}240241size_t ossl_quic_tserver_get_short_header_conn_id_len(const QUIC_TSERVER *srv)242{243return ossl_quic_channel_get_short_header_conn_id_len(srv->ch);244}245246int ossl_quic_tserver_is_handshake_confirmed(const QUIC_TSERVER *srv)247{248return ossl_quic_channel_is_handshake_confirmed(srv->ch);249}250251int ossl_quic_tserver_read(QUIC_TSERVER *srv,252uint64_t stream_id,253unsigned char *buf,254size_t buf_len,255size_t *bytes_read)256{257int is_fin = 0;258QUIC_STREAM *qs;259260qs = ossl_quic_stream_map_get_by_id(ossl_quic_channel_get_qsm(srv->ch),261stream_id);262if (qs == NULL) {263int is_client_init264= ((stream_id & QUIC_STREAM_INITIATOR_MASK)265== QUIC_STREAM_INITIATOR_CLIENT);266267/*268* A client-initiated stream might spontaneously come into existence, so269* allow trying to read on a client-initiated stream before it exists,270* assuming the connection is still active.271* Otherwise, fail.272*/273if (!is_client_init || !ossl_quic_channel_is_active(srv->ch))274return 0;275276*bytes_read = 0;277return 1;278}279280if (qs->recv_state == QUIC_RSTREAM_STATE_DATA_READ281|| !ossl_quic_stream_has_recv_buffer(qs))282return 0;283284if (!ossl_quic_rstream_read(qs->rstream, buf, buf_len,285bytes_read, &is_fin))286return 0;287288if (*bytes_read > 0) {289/*290* We have read at least one byte from the stream. Inform stream-level291* RXFC of the retirement of controlled bytes. Update the active stream292* status (the RXFC may now want to emit a frame granting more credit to293* the peer).294*/295OSSL_RTT_INFO rtt_info;296297ossl_statm_get_rtt_info(ossl_quic_channel_get_statm(srv->ch), &rtt_info);298299if (!ossl_quic_rxfc_on_retire(&qs->rxfc, *bytes_read,300rtt_info.smoothed_rtt))301return 0;302}303304if (is_fin)305ossl_quic_stream_map_notify_totally_read(ossl_quic_channel_get_qsm(srv->ch),306qs);307308if (*bytes_read > 0)309ossl_quic_stream_map_update_state(ossl_quic_channel_get_qsm(srv->ch), qs);310311return 1;312}313314int ossl_quic_tserver_has_read_ended(QUIC_TSERVER *srv, uint64_t stream_id)315{316QUIC_STREAM *qs;317unsigned char buf[1];318size_t bytes_read = 0;319int is_fin = 0;320321qs = ossl_quic_stream_map_get_by_id(ossl_quic_channel_get_qsm(srv->ch),322stream_id);323324if (qs == NULL)325return 0;326327if (qs->recv_state == QUIC_RSTREAM_STATE_DATA_READ)328return 1;329330if (!ossl_quic_stream_has_recv_buffer(qs))331return 0;332333/*334* If we do not have the DATA_READ, it is possible we should still return 1335* if there is a lone FIN (but no more data) remaining to be retired from336* the RSTREAM, for example because ossl_quic_tserver_read() has not been337* called since the FIN was received.338*/339if (!ossl_quic_rstream_peek(qs->rstream, buf, sizeof(buf),340&bytes_read, &is_fin))341return 0;342343if (is_fin && bytes_read == 0) {344/* If we have a FIN awaiting retirement and no data before it... */345/* Let RSTREAM know we've consumed this FIN. */346if (!ossl_quic_rstream_read(qs->rstream, buf, sizeof(buf),347&bytes_read, &is_fin))348return 0;349350assert(is_fin && bytes_read == 0);351assert(qs->recv_state == QUIC_RSTREAM_STATE_DATA_RECVD);352353ossl_quic_stream_map_notify_totally_read(ossl_quic_channel_get_qsm(srv->ch),354qs);355ossl_quic_stream_map_update_state(ossl_quic_channel_get_qsm(srv->ch), qs);356return 1;357}358359return 0;360}361362int ossl_quic_tserver_write(QUIC_TSERVER *srv,363uint64_t stream_id,364const unsigned char *buf,365size_t buf_len,366size_t *bytes_written)367{368QUIC_STREAM *qs;369370if (!ossl_quic_channel_is_active(srv->ch))371return 0;372373qs = ossl_quic_stream_map_get_by_id(ossl_quic_channel_get_qsm(srv->ch),374stream_id);375if (qs == NULL || !ossl_quic_stream_has_send_buffer(qs))376return 0;377378if (!ossl_quic_sstream_append(qs->sstream,379buf, buf_len, bytes_written))380return 0;381382if (*bytes_written > 0)383/*384* We have appended at least one byte to the stream. Potentially mark385* the stream as active, depending on FC.386*/387ossl_quic_stream_map_update_state(ossl_quic_channel_get_qsm(srv->ch), qs);388389/* Try and send. */390ossl_quic_tserver_tick(srv);391return 1;392}393394int ossl_quic_tserver_conclude(QUIC_TSERVER *srv, uint64_t stream_id)395{396QUIC_STREAM *qs;397398if (!ossl_quic_channel_is_active(srv->ch))399return 0;400401qs = ossl_quic_stream_map_get_by_id(ossl_quic_channel_get_qsm(srv->ch),402stream_id);403if (qs == NULL || !ossl_quic_stream_has_send_buffer(qs))404return 0;405406if (!ossl_quic_sstream_get_final_size(qs->sstream, NULL)) {407ossl_quic_sstream_fin(qs->sstream);408ossl_quic_stream_map_update_state(ossl_quic_channel_get_qsm(srv->ch), qs);409}410411ossl_quic_tserver_tick(srv);412return 1;413}414415int ossl_quic_tserver_stream_new(QUIC_TSERVER *srv,416int is_uni,417uint64_t *stream_id)418{419QUIC_STREAM *qs;420421if (!ossl_quic_channel_is_active(srv->ch))422return 0;423424if ((qs = ossl_quic_channel_new_stream_local(srv->ch, is_uni)) == NULL)425return 0;426427*stream_id = qs->id;428return 1;429}430431BIO *ossl_quic_tserver_get0_rbio(QUIC_TSERVER *srv)432{433return srv->args.net_rbio;434}435436SSL_CTX *ossl_quic_tserver_get0_ssl_ctx(QUIC_TSERVER *srv)437{438return srv->ctx;439}440441int ossl_quic_tserver_stream_has_peer_stop_sending(QUIC_TSERVER *srv,442uint64_t stream_id,443uint64_t *app_error_code)444{445QUIC_STREAM *qs;446447qs = ossl_quic_stream_map_get_by_id(ossl_quic_channel_get_qsm(srv->ch),448stream_id);449if (qs == NULL)450return 0;451452if (qs->peer_stop_sending && app_error_code != NULL)453*app_error_code = qs->peer_stop_sending_aec;454455return qs->peer_stop_sending;456}457458int ossl_quic_tserver_stream_has_peer_reset_stream(QUIC_TSERVER *srv,459uint64_t stream_id,460uint64_t *app_error_code)461{462QUIC_STREAM *qs;463464qs = ossl_quic_stream_map_get_by_id(ossl_quic_channel_get_qsm(srv->ch),465stream_id);466if (qs == NULL)467return 0;468469if (ossl_quic_stream_recv_is_reset(qs) && app_error_code != NULL)470*app_error_code = qs->peer_reset_stream_aec;471472return ossl_quic_stream_recv_is_reset(qs);473}474475int ossl_quic_tserver_set_new_local_cid(QUIC_TSERVER *srv,476const QUIC_CONN_ID *conn_id)477{478/* Replace existing local connection ID in the QUIC_CHANNEL */479return ossl_quic_channel_replace_local_cid(srv->ch, conn_id);480}481482uint64_t ossl_quic_tserver_pop_incoming_stream(QUIC_TSERVER *srv)483{484QUIC_STREAM_MAP *qsm = ossl_quic_channel_get_qsm(srv->ch);485QUIC_STREAM *qs = ossl_quic_stream_map_peek_accept_queue(qsm);486487if (qs == NULL)488return UINT64_MAX;489490ossl_quic_stream_map_remove_from_accept_queue(qsm, qs, ossl_time_zero());491492return qs->id;493}494495int ossl_quic_tserver_is_stream_totally_acked(QUIC_TSERVER *srv,496uint64_t stream_id)497{498QUIC_STREAM *qs;499500qs = ossl_quic_stream_map_get_by_id(ossl_quic_channel_get_qsm(srv->ch),501stream_id);502if (qs == NULL)503return 1;504505return ossl_quic_sstream_is_totally_acked(qs->sstream);506}507508int ossl_quic_tserver_get_net_read_desired(QUIC_TSERVER *srv)509{510return ossl_quic_reactor_net_read_desired(511ossl_quic_channel_get_reactor(srv->ch));512}513514int ossl_quic_tserver_get_net_write_desired(QUIC_TSERVER *srv)515{516return ossl_quic_reactor_net_write_desired(517ossl_quic_channel_get_reactor(srv->ch));518}519520OSSL_TIME ossl_quic_tserver_get_deadline(QUIC_TSERVER *srv)521{522return ossl_quic_reactor_get_tick_deadline(523ossl_quic_channel_get_reactor(srv->ch));524}525526int ossl_quic_tserver_shutdown(QUIC_TSERVER *srv, uint64_t app_error_code)527{528ossl_quic_channel_local_close(srv->ch, app_error_code, NULL);529530if (ossl_quic_channel_is_terminated(srv->ch))531return 1;532533ossl_quic_reactor_tick(ossl_quic_channel_get_reactor(srv->ch), 0);534535return ossl_quic_channel_is_terminated(srv->ch);536}537538int ossl_quic_tserver_ping(QUIC_TSERVER *srv)539{540if (ossl_quic_channel_is_terminated(srv->ch))541return 0;542543if (!ossl_quic_channel_ping(srv->ch))544return 0;545546ossl_quic_reactor_tick(ossl_quic_channel_get_reactor(srv->ch), 0);547return 1;548}549550QUIC_CHANNEL *ossl_quic_tserver_get_channel(QUIC_TSERVER *srv)551{552return srv->ch;553}554555void ossl_quic_tserver_set_msg_callback(QUIC_TSERVER *srv,556void (*f)(int write_p, int version,557int content_type,558const void *buf, size_t len,559SSL *ssl, void *arg),560void *arg)561{562ossl_quic_channel_set_msg_callback(srv->ch, f, srv->ssl);563ossl_quic_channel_set_msg_callback_arg(srv->ch, arg);564SSL_set_msg_callback(srv->tls, f);565SSL_set_msg_callback_arg(srv->tls, arg);566}567568int ossl_quic_tserver_new_ticket(QUIC_TSERVER *srv)569{570return SSL_new_session_ticket(srv->tls);571}572573int ossl_quic_tserver_set_max_early_data(QUIC_TSERVER *srv,574uint32_t max_early_data)575{576return SSL_set_max_early_data(srv->tls, max_early_data);577}578579void ossl_quic_tserver_set_psk_find_session_cb(QUIC_TSERVER *srv,580SSL_psk_find_session_cb_func cb)581{582SSL_set_psk_find_session_callback(srv->tls, cb);583}584585586