1*e7be843bSPierre Pronchery /* 2*e7be843bSPierre Pronchery * Copyright 2022-2025 The OpenSSL Project Authors. All Rights Reserved. 3*e7be843bSPierre Pronchery * 4*e7be843bSPierre Pronchery * Licensed under the Apache License 2.0 (the "License"). You may not use 5*e7be843bSPierre Pronchery * this file except in compliance with the License. You can obtain a copy 6*e7be843bSPierre Pronchery * in the file LICENSE in the source distribution or at 7*e7be843bSPierre Pronchery * https://www.openssl.org/source/license.html 8*e7be843bSPierre Pronchery */ 9*e7be843bSPierre Pronchery 10*e7be843bSPierre Pronchery #ifndef OSSL_QUIC_LOCAL_H 11*e7be843bSPierre Pronchery # define OSSL_QUIC_LOCAL_H 12*e7be843bSPierre Pronchery 13*e7be843bSPierre Pronchery # include <openssl/ssl.h> 14*e7be843bSPierre Pronchery # include "internal/quic_ssl.h" /* QUIC_CONNECTION */ 15*e7be843bSPierre Pronchery # include "internal/quic_txp.h" 16*e7be843bSPierre Pronchery # include "internal/quic_statm.h" 17*e7be843bSPierre Pronchery # include "internal/quic_demux.h" 18*e7be843bSPierre Pronchery # include "internal/quic_record_rx.h" 19*e7be843bSPierre Pronchery # include "internal/quic_tls.h" 20*e7be843bSPierre Pronchery # include "internal/quic_fc.h" 21*e7be843bSPierre Pronchery # include "internal/quic_stream.h" 22*e7be843bSPierre Pronchery # include "internal/quic_channel.h" 23*e7be843bSPierre Pronchery # include "internal/quic_reactor.h" 24*e7be843bSPierre Pronchery # include "internal/quic_thread_assist.h" 25*e7be843bSPierre Pronchery # include "../ssl_local.h" 26*e7be843bSPierre Pronchery # include "quic_obj_local.h" 27*e7be843bSPierre Pronchery 28*e7be843bSPierre Pronchery # ifndef OPENSSL_NO_QUIC 29*e7be843bSPierre Pronchery 30*e7be843bSPierre Pronchery /* 31*e7be843bSPierre Pronchery * QUIC stream SSL object (QSSO) type. This implements the API personality layer 32*e7be843bSPierre Pronchery * for QSSO objects, wrapping the QUIC-native QUIC_STREAM object and tracking 33*e7be843bSPierre Pronchery * state required by the libssl API personality. 34*e7be843bSPierre Pronchery */ 35*e7be843bSPierre Pronchery struct quic_xso_st { 36*e7be843bSPierre Pronchery /* QUIC_OBJ common header, including SSL object common header. */ 37*e7be843bSPierre Pronchery QUIC_OBJ obj; 38*e7be843bSPierre Pronchery 39*e7be843bSPierre Pronchery /* The connection this stream is associated with. Always non-NULL. */ 40*e7be843bSPierre Pronchery QUIC_CONNECTION *conn; 41*e7be843bSPierre Pronchery 42*e7be843bSPierre Pronchery /* The stream object. Always non-NULL for as long as the XSO exists. */ 43*e7be843bSPierre Pronchery QUIC_STREAM *stream; 44*e7be843bSPierre Pronchery 45*e7be843bSPierre Pronchery /* The application has retired a FIN (i.e. SSL_ERROR_ZERO_RETURN). */ 46*e7be843bSPierre Pronchery unsigned int retired_fin : 1; 47*e7be843bSPierre Pronchery 48*e7be843bSPierre Pronchery /* 49*e7be843bSPierre Pronchery * The application has requested a reset. Not set for reflexive 50*e7be843bSPierre Pronchery * STREAM_RESETs caused by peer STOP_SENDING. 51*e7be843bSPierre Pronchery */ 52*e7be843bSPierre Pronchery unsigned int requested_reset : 1; 53*e7be843bSPierre Pronchery 54*e7be843bSPierre Pronchery /* 55*e7be843bSPierre Pronchery * This state tracks SSL_write all-or-nothing (AON) write semantics 56*e7be843bSPierre Pronchery * emulation. 57*e7be843bSPierre Pronchery * 58*e7be843bSPierre Pronchery * Example chronology: 59*e7be843bSPierre Pronchery * 60*e7be843bSPierre Pronchery * t=0: aon_write_in_progress=0 61*e7be843bSPierre Pronchery * t=1: SSL_write(ssl, b1, l1) called; 62*e7be843bSPierre Pronchery * too big to enqueue into sstream at once, SSL_ERROR_WANT_WRITE; 63*e7be843bSPierre Pronchery * aon_write_in_progress=1; aon_buf_base=b1; aon_buf_len=l1; 64*e7be843bSPierre Pronchery * aon_buf_pos < l1 (depends on how much room was in sstream); 65*e7be843bSPierre Pronchery * t=2: SSL_write(ssl, b2, l2); 66*e7be843bSPierre Pronchery * b2 must equal b1 (validated unless ACCEPT_MOVING_WRITE_BUFFER) 67*e7be843bSPierre Pronchery * l2 must equal l1 (always validated) 68*e7be843bSPierre Pronchery * append into sstream from [b2 + aon_buf_pos, b2 + aon_buf_len) 69*e7be843bSPierre Pronchery * if done, aon_write_in_progress=0 70*e7be843bSPierre Pronchery * 71*e7be843bSPierre Pronchery */ 72*e7be843bSPierre Pronchery /* Is an AON write in progress? */ 73*e7be843bSPierre Pronchery unsigned int aon_write_in_progress : 1; 74*e7be843bSPierre Pronchery 75*e7be843bSPierre Pronchery /* 76*e7be843bSPierre Pronchery * The base buffer pointer the caller passed us for the initial AON write 77*e7be843bSPierre Pronchery * call. We use this for validation purposes unless 78*e7be843bSPierre Pronchery * ACCEPT_MOVING_WRITE_BUFFER is enabled. 79*e7be843bSPierre Pronchery * 80*e7be843bSPierre Pronchery * NOTE: We never dereference this, as the caller might pass a different 81*e7be843bSPierre Pronchery * (but identical) buffer if using ACCEPT_MOVING_WRITE_BUFFER. It is for 82*e7be843bSPierre Pronchery * validation by pointer comparison only. 83*e7be843bSPierre Pronchery */ 84*e7be843bSPierre Pronchery const unsigned char *aon_buf_base; 85*e7be843bSPierre Pronchery /* The total length of the AON buffer being sent, in bytes. */ 86*e7be843bSPierre Pronchery size_t aon_buf_len; 87*e7be843bSPierre Pronchery /* 88*e7be843bSPierre Pronchery * The position in the AON buffer up to which we have successfully sent data 89*e7be843bSPierre Pronchery * so far. 90*e7be843bSPierre Pronchery */ 91*e7be843bSPierre Pronchery size_t aon_buf_pos; 92*e7be843bSPierre Pronchery 93*e7be843bSPierre Pronchery /* SSL_set_mode */ 94*e7be843bSPierre Pronchery uint32_t ssl_mode; 95*e7be843bSPierre Pronchery 96*e7be843bSPierre Pronchery /* SSL_set_options */ 97*e7be843bSPierre Pronchery uint64_t ssl_options; 98*e7be843bSPierre Pronchery 99*e7be843bSPierre Pronchery /* 100*e7be843bSPierre Pronchery * Last 'normal' error during an app-level I/O operation, used by 101*e7be843bSPierre Pronchery * SSL_get_error(); used to track data-path errors like SSL_ERROR_WANT_READ 102*e7be843bSPierre Pronchery * and SSL_ERROR_WANT_WRITE. 103*e7be843bSPierre Pronchery */ 104*e7be843bSPierre Pronchery int last_error; 105*e7be843bSPierre Pronchery }; 106*e7be843bSPierre Pronchery 107*e7be843bSPierre Pronchery /* 108*e7be843bSPierre Pronchery * QUIC connection SSL object (QCSO) type. This implements the API personality 109*e7be843bSPierre Pronchery * layer for QCSO objects, wrapping the QUIC-native QUIC_CHANNEL object. 110*e7be843bSPierre Pronchery */ 111*e7be843bSPierre Pronchery struct quic_conn_st { 112*e7be843bSPierre Pronchery /* 113*e7be843bSPierre Pronchery * QUIC_OBJ is a common header for QUIC APL objects, allowing objects of 114*e7be843bSPierre Pronchery * these different types to be disambiguated at runtime and providing some 115*e7be843bSPierre Pronchery * common fields. 116*e7be843bSPierre Pronchery * 117*e7be843bSPierre Pronchery * Note: This must come first in the QUIC_CONNECTION structure. 118*e7be843bSPierre Pronchery */ 119*e7be843bSPierre Pronchery QUIC_OBJ obj; 120*e7be843bSPierre Pronchery 121*e7be843bSPierre Pronchery SSL *tls; 122*e7be843bSPierre Pronchery 123*e7be843bSPierre Pronchery /* The QLSO this connection belongs to, if any. */ 124*e7be843bSPierre Pronchery QUIC_LISTENER *listener; 125*e7be843bSPierre Pronchery 126*e7be843bSPierre Pronchery /* The QDSO this connection belongs to, if any. */ 127*e7be843bSPierre Pronchery QUIC_DOMAIN *domain; 128*e7be843bSPierre Pronchery 129*e7be843bSPierre Pronchery /* The QUIC engine representing the QUIC event domain. */ 130*e7be843bSPierre Pronchery QUIC_ENGINE *engine; 131*e7be843bSPierre Pronchery 132*e7be843bSPierre Pronchery /* The QUIC port representing the QUIC listener and socket. */ 133*e7be843bSPierre Pronchery QUIC_PORT *port; 134*e7be843bSPierre Pronchery 135*e7be843bSPierre Pronchery /* 136*e7be843bSPierre Pronchery * The QUIC channel providing the core QUIC connection implementation. Note 137*e7be843bSPierre Pronchery * that this is not instantiated until we actually start trying to do the 138*e7be843bSPierre Pronchery * handshake. This is to allow us to gather information like whether we are 139*e7be843bSPierre Pronchery * going to be in client or server mode before committing to instantiating 140*e7be843bSPierre Pronchery * the channel, since we want to determine the channel arguments based on 141*e7be843bSPierre Pronchery * that. 142*e7be843bSPierre Pronchery * 143*e7be843bSPierre Pronchery * The channel remains available after connection termination until the SSL 144*e7be843bSPierre Pronchery * object is freed, thus (ch != NULL) iff (started == 1). 145*e7be843bSPierre Pronchery */ 146*e7be843bSPierre Pronchery QUIC_CHANNEL *ch; 147*e7be843bSPierre Pronchery 148*e7be843bSPierre Pronchery /* 149*e7be843bSPierre Pronchery * The mutex used to synchronise access to the QUIC_CHANNEL. We own this but 150*e7be843bSPierre Pronchery * provide it to the channel. 151*e7be843bSPierre Pronchery */ 152*e7be843bSPierre Pronchery #if defined(OPENSSL_THREADS) 153*e7be843bSPierre Pronchery CRYPTO_MUTEX *mutex; 154*e7be843bSPierre Pronchery #endif 155*e7be843bSPierre Pronchery 156*e7be843bSPierre Pronchery /* 157*e7be843bSPierre Pronchery * If we have a default stream attached, this is the internal XSO 158*e7be843bSPierre Pronchery * object. If there is no default stream, this is NULL. 159*e7be843bSPierre Pronchery */ 160*e7be843bSPierre Pronchery QUIC_XSO *default_xso; 161*e7be843bSPierre Pronchery 162*e7be843bSPierre Pronchery /* Initial peer L4 address. */ 163*e7be843bSPierre Pronchery BIO_ADDR init_peer_addr; 164*e7be843bSPierre Pronchery 165*e7be843bSPierre Pronchery # ifndef OPENSSL_NO_QUIC_THREAD_ASSIST 166*e7be843bSPierre Pronchery /* Manages thread for QUIC thread assisted mode. */ 167*e7be843bSPierre Pronchery QUIC_THREAD_ASSIST thread_assist; 168*e7be843bSPierre Pronchery # endif 169*e7be843bSPierre Pronchery 170*e7be843bSPierre Pronchery /* Number of XSOs allocated. Includes the default XSO, if any. */ 171*e7be843bSPierre Pronchery size_t num_xso; 172*e7be843bSPierre Pronchery 173*e7be843bSPierre Pronchery /* Have we started? */ 174*e7be843bSPierre Pronchery unsigned int started : 1; 175*e7be843bSPierre Pronchery 176*e7be843bSPierre Pronchery /* 177*e7be843bSPierre Pronchery * This is 1 if we were instantiated using a QUIC server method 178*e7be843bSPierre Pronchery * (for future use). 179*e7be843bSPierre Pronchery */ 180*e7be843bSPierre Pronchery unsigned int as_server : 1; 181*e7be843bSPierre Pronchery 182*e7be843bSPierre Pronchery /* 183*e7be843bSPierre Pronchery * Has the application called SSL_set_accept_state? We require this to be 184*e7be843bSPierre Pronchery * congruent with the value of as_server. 185*e7be843bSPierre Pronchery */ 186*e7be843bSPierre Pronchery unsigned int as_server_state : 1; 187*e7be843bSPierre Pronchery 188*e7be843bSPierre Pronchery /* Are we using thread assisted mode? Never changes after init. */ 189*e7be843bSPierre Pronchery unsigned int is_thread_assisted : 1; 190*e7be843bSPierre Pronchery 191*e7be843bSPierre Pronchery /* Have we created a default XSO yet? */ 192*e7be843bSPierre Pronchery unsigned int default_xso_created : 1; 193*e7be843bSPierre Pronchery 194*e7be843bSPierre Pronchery /* 195*e7be843bSPierre Pronchery * Pre-TERMINATING shutdown phase in which we are flushing streams. 196*e7be843bSPierre Pronchery * Monotonically transitions to 1. 197*e7be843bSPierre Pronchery * New streams cannot be created in this state. 198*e7be843bSPierre Pronchery */ 199*e7be843bSPierre Pronchery unsigned int shutting_down : 1; 200*e7be843bSPierre Pronchery 201*e7be843bSPierre Pronchery /* Have we probed the BIOs for addressing support? */ 202*e7be843bSPierre Pronchery unsigned int addressing_probe_done : 1; 203*e7be843bSPierre Pronchery 204*e7be843bSPierre Pronchery /* Are we using addressed mode (BIO_sendmmsg with non-NULL peer)? */ 205*e7be843bSPierre Pronchery unsigned int addressed_mode_w : 1; 206*e7be843bSPierre Pronchery unsigned int addressed_mode_r : 1; 207*e7be843bSPierre Pronchery 208*e7be843bSPierre Pronchery /* Flag to indicate waiting on accept queue */ 209*e7be843bSPierre Pronchery unsigned int pending : 1; 210*e7be843bSPierre Pronchery 211*e7be843bSPierre Pronchery /* Default stream type. Defaults to SSL_DEFAULT_STREAM_MODE_AUTO_BIDI. */ 212*e7be843bSPierre Pronchery uint32_t default_stream_mode; 213*e7be843bSPierre Pronchery 214*e7be843bSPierre Pronchery /* SSL_set_mode. This is not used directly but inherited by new XSOs. */ 215*e7be843bSPierre Pronchery uint32_t default_ssl_mode; 216*e7be843bSPierre Pronchery 217*e7be843bSPierre Pronchery /* SSL_set_options. This is not used directly but inherited by new XSOs. */ 218*e7be843bSPierre Pronchery uint64_t default_ssl_options; 219*e7be843bSPierre Pronchery 220*e7be843bSPierre Pronchery /* SSL_set_incoming_stream_policy. */ 221*e7be843bSPierre Pronchery int incoming_stream_policy; 222*e7be843bSPierre Pronchery uint64_t incoming_stream_aec; 223*e7be843bSPierre Pronchery 224*e7be843bSPierre Pronchery /* 225*e7be843bSPierre Pronchery * Last 'normal' error during an app-level I/O operation, used by 226*e7be843bSPierre Pronchery * SSL_get_error(); used to track data-path errors like SSL_ERROR_WANT_READ 227*e7be843bSPierre Pronchery * and SSL_ERROR_WANT_WRITE. 228*e7be843bSPierre Pronchery */ 229*e7be843bSPierre Pronchery int last_error; 230*e7be843bSPierre Pronchery }; 231*e7be843bSPierre Pronchery 232*e7be843bSPierre Pronchery /* 233*e7be843bSPierre Pronchery * QUIC listener SSL object (QLSO) type. This implements the API personality 234*e7be843bSPierre Pronchery * layer for QLSO objects, wrapping the QUIC-native QUIC_PORT object. 235*e7be843bSPierre Pronchery */ 236*e7be843bSPierre Pronchery struct quic_listener_st { 237*e7be843bSPierre Pronchery /* QUIC_OBJ common header, including SSL object common header. */ 238*e7be843bSPierre Pronchery QUIC_OBJ obj; 239*e7be843bSPierre Pronchery 240*e7be843bSPierre Pronchery /* The QDSO this connection belongs to, if any. */ 241*e7be843bSPierre Pronchery QUIC_DOMAIN *domain; 242*e7be843bSPierre Pronchery 243*e7be843bSPierre Pronchery /* The QUIC engine representing the QUIC event domain. */ 244*e7be843bSPierre Pronchery QUIC_ENGINE *engine; 245*e7be843bSPierre Pronchery 246*e7be843bSPierre Pronchery /* The QUIC port representing the QUIC listener and socket. */ 247*e7be843bSPierre Pronchery QUIC_PORT *port; 248*e7be843bSPierre Pronchery 249*e7be843bSPierre Pronchery #if defined(OPENSSL_THREADS) 250*e7be843bSPierre Pronchery /* 251*e7be843bSPierre Pronchery * The mutex used to synchronise access to the QUIC_ENGINE. We own this but 252*e7be843bSPierre Pronchery * provide it to the engine. 253*e7be843bSPierre Pronchery */ 254*e7be843bSPierre Pronchery CRYPTO_MUTEX *mutex; 255*e7be843bSPierre Pronchery #endif 256*e7be843bSPierre Pronchery 257*e7be843bSPierre Pronchery /* Have we started listening yet? */ 258*e7be843bSPierre Pronchery unsigned int listening : 1; 259*e7be843bSPierre Pronchery }; 260*e7be843bSPierre Pronchery 261*e7be843bSPierre Pronchery /* 262*e7be843bSPierre Pronchery * QUIC domain SSL object (QDSO) type. This implements the API personality layer 263*e7be843bSPierre Pronchery * for QDSO objects, wrapping the QUIC-native QUIC_ENGINE object. 264*e7be843bSPierre Pronchery */ 265*e7be843bSPierre Pronchery struct quic_domain_st { 266*e7be843bSPierre Pronchery /* QUIC_OBJ common header, including SSL object common header. */ 267*e7be843bSPierre Pronchery QUIC_OBJ obj; 268*e7be843bSPierre Pronchery 269*e7be843bSPierre Pronchery /* The QUIC engine representing the QUIC event domain. */ 270*e7be843bSPierre Pronchery QUIC_ENGINE *engine; 271*e7be843bSPierre Pronchery 272*e7be843bSPierre Pronchery #if defined(OPENSSL_THREADS) 273*e7be843bSPierre Pronchery /* 274*e7be843bSPierre Pronchery * The mutex used to synchronise access to the QUIC_ENGINE. We own this but 275*e7be843bSPierre Pronchery * provide it to the engine. 276*e7be843bSPierre Pronchery */ 277*e7be843bSPierre Pronchery CRYPTO_MUTEX *mutex; 278*e7be843bSPierre Pronchery #endif 279*e7be843bSPierre Pronchery }; 280*e7be843bSPierre Pronchery 281*e7be843bSPierre Pronchery /* Internal calls to the QUIC CSM which come from various places. */ 282*e7be843bSPierre Pronchery int ossl_quic_conn_on_handshake_confirmed(QUIC_CONNECTION *qc); 283*e7be843bSPierre Pronchery 284*e7be843bSPierre Pronchery /* 285*e7be843bSPierre Pronchery * To be called when a protocol violation occurs. The connection is torn down 286*e7be843bSPierre Pronchery * with the given error code, which should be a OSSL_QUIC_ERR_* value. Reason 287*e7be843bSPierre Pronchery * string is optional and copied if provided. frame_type should be 0 if not 288*e7be843bSPierre Pronchery * applicable. 289*e7be843bSPierre Pronchery */ 290*e7be843bSPierre Pronchery void ossl_quic_conn_raise_protocol_error(QUIC_CONNECTION *qc, 291*e7be843bSPierre Pronchery uint64_t error_code, 292*e7be843bSPierre Pronchery uint64_t frame_type, 293*e7be843bSPierre Pronchery const char *reason); 294*e7be843bSPierre Pronchery 295*e7be843bSPierre Pronchery void ossl_quic_conn_on_remote_conn_close(QUIC_CONNECTION *qc, 296*e7be843bSPierre Pronchery OSSL_QUIC_FRAME_CONN_CLOSE *f); 297*e7be843bSPierre Pronchery 298*e7be843bSPierre Pronchery # define OSSL_QUIC_ANY_VERSION 0xFFFFF 299*e7be843bSPierre Pronchery # endif 300*e7be843bSPierre Pronchery 301*e7be843bSPierre Pronchery # define IMPLEMENT_quic_meth_func(version, func_name, q_accept, \ 302*e7be843bSPierre Pronchery q_connect, enc_data) \ 303*e7be843bSPierre Pronchery const SSL_METHOD *func_name(void) \ 304*e7be843bSPierre Pronchery { \ 305*e7be843bSPierre Pronchery static const SSL_METHOD func_name##_data= { \ 306*e7be843bSPierre Pronchery version, \ 307*e7be843bSPierre Pronchery 0, \ 308*e7be843bSPierre Pronchery 0, \ 309*e7be843bSPierre Pronchery ossl_quic_new, \ 310*e7be843bSPierre Pronchery ossl_quic_free, \ 311*e7be843bSPierre Pronchery ossl_quic_reset, \ 312*e7be843bSPierre Pronchery ossl_quic_init, \ 313*e7be843bSPierre Pronchery NULL /* clear */, \ 314*e7be843bSPierre Pronchery ossl_quic_deinit, \ 315*e7be843bSPierre Pronchery q_accept, \ 316*e7be843bSPierre Pronchery q_connect, \ 317*e7be843bSPierre Pronchery ossl_quic_read, \ 318*e7be843bSPierre Pronchery ossl_quic_peek, \ 319*e7be843bSPierre Pronchery ossl_quic_write, \ 320*e7be843bSPierre Pronchery NULL /* shutdown */, \ 321*e7be843bSPierre Pronchery NULL /* renegotiate */, \ 322*e7be843bSPierre Pronchery ossl_quic_renegotiate_check, \ 323*e7be843bSPierre Pronchery NULL /* read_bytes */, \ 324*e7be843bSPierre Pronchery NULL /* write_bytes */, \ 325*e7be843bSPierre Pronchery NULL /* dispatch_alert */, \ 326*e7be843bSPierre Pronchery ossl_quic_ctrl, \ 327*e7be843bSPierre Pronchery ossl_quic_ctx_ctrl, \ 328*e7be843bSPierre Pronchery ossl_quic_get_cipher_by_char, \ 329*e7be843bSPierre Pronchery NULL /* put_cipher_by_char */, \ 330*e7be843bSPierre Pronchery ossl_quic_pending, \ 331*e7be843bSPierre Pronchery ossl_quic_num_ciphers, \ 332*e7be843bSPierre Pronchery ossl_quic_get_cipher, \ 333*e7be843bSPierre Pronchery tls1_default_timeout, \ 334*e7be843bSPierre Pronchery &enc_data, \ 335*e7be843bSPierre Pronchery ssl_undefined_void_function, \ 336*e7be843bSPierre Pronchery ossl_quic_callback_ctrl, \ 337*e7be843bSPierre Pronchery ossl_quic_ctx_callback_ctrl, \ 338*e7be843bSPierre Pronchery }; \ 339*e7be843bSPierre Pronchery return &func_name##_data; \ 340*e7be843bSPierre Pronchery } 341*e7be843bSPierre Pronchery 342*e7be843bSPierre Pronchery #endif 343