openssl-quic.7ossl - Man Page

OpenSSL QUIC

Description

OpenSSL 3.2 and later features support for the QUIC transport protocol. You can use OpenSSL's QUIC capabilities for both client and server applications. This man page describes how to let applications use the QUIC protocol using the libssl API.

The QUIC protocol maps to the standard SSL API. A QUIC connection is represented by an SSL object in the same way that a TLS connection is. Only minimal changes are needed to existing applications which use libssl API to bring QUIC protocol support in. QUIC clients can use OSSL_QUIC_client_method(3) or OSSL_QUIC_client_thread_method(3) with SSL_CTX_new(3). See below for more details about the difference between the two. For servers, there is only one option: SSL method OSSL_QUIC_server_method(3) with SSL_CTX_new(3).

The remainder of this man page discusses, in order:

Client Modes of Operation

When a client creates a QUIC connection, by default, it operates in default stream mode, which is intended to provide compatibility with existing non-QUIC application usage patterns. In this mode, the connection has a single stream associated with it. Calls to SSL_read(3) and SSL_write(3) on the QUIC connection SSL object read and write from that stream. Whether the stream is client-initiated or server-initiated from a QUIC perspective depends on whether SSL_read(3) or SSL_write(3) is called first.

Default stream mode is primarily for compatibility with existing applications. For new applications utilizing QUIC, it's recommended to disable this mode and instead adopt the multi-stream API. See the RECOMMENDATIONS FOR NEW APPLICATIONS section for more details.

Default Stream Mode

A QUIC client connection can be used in either default stream mode or multi-stream mode. By default, a newly created QUIC connection SSL object uses default stream mode.

In default stream mode, a stream is implicitly created and bound to the QUIC connection SSL object; SSL_read(3) and SSL_write(3) calls to the QUIC connection SSL object work by default and are mapped to that stream.

When default stream mode is used, any API function which can be called on a QUIC stream SSL object can also be called on a QUIC connection SSL object, in which case it affects the default stream bound to the connection.

The identity of a QUIC stream, including its stream ID, varies depending on whether a stream is client-initiated or server-initiated. In default stream mode, if a client application calls SSL_read(3) first before any call to SSL_write(3) on the connection, it is assumed that the application protocol is using a server-initiated stream, and the SSL_read(3) call will not complete (either blocking, or failing appropriately if nonblocking mode is configured) until the server initiates a stream. Conversely, if the client application calls SSL_write(3) before any call to SSL_read(3) on the connection, it is assumed that a client-initiated stream is to be used and such a stream is created automatically.

Default stream mode is intended to aid compatibility with legacy applications. New applications adopting QUIC should use multi-stream mode, described below, and avoid use of the default stream functionality.

It is possible to use additional streams in default stream mode using SSL_new_stream(3) and SSL_accept_stream(3); note that the default incoming stream policy will need to be changed using SSL_set_incoming_stream_policy(3) in order to use SSL_accept_stream(3) in this case. However, applications using additional streams are strongly recommended to use multi-stream mode instead.

Calling SSL_new_stream(3) or SSL_accept_stream(3) before a default stream has been associated with the QUIC connection SSL object will inhibit future creation of a default stream.

Multi-Stream Mode

The recommended usage mode for new applications adopting QUIC is multi-stream mode, in which no default stream is attached to the QUIC connection SSL object and attempts to call SSL_read(3) and SSL_write(3) on the QUIC connection SSL object fail. Instead, an application calls SSL_new_stream(3) or SSL_accept_stream(3) to create individual stream SSL objects for sending and receiving application data using SSL_read(3) and SSL_write(3).

To use multi-stream mode, call SSL_set_default_stream_mode(3) with an argument of SSL_DEFAULT_STREAM_MODE_NONE; this function must be called prior to initiating the connection. The default stream mode cannot be changed after initiating a connection.

When multi-stream mode is used, meaning that no default stream is associated with the connection, calls to API functions which are defined as operating on a QUIC stream fail if called on the QUIC connection SSL object. For example, calls such as SSL_write(3) or SSL_get_stream_id(3) will fail.

Changes to Existing Apis

Most SSL APIs, such as SSL_read(3) and SSL_write(3), function as they do for TLS connections and do not have changed semantics, with some exceptions. The changes to the semantics of existing APIs are as follows:

Considerations for Existing Applications

Existing applications seeking to adopt QUIC should apply the following list to determine what changes they will need to make:

Quic-Specific Apis

This section details new APIs which are directly or indirectly related to QUIC. For details on the operation of each API, see the referenced man pages.

The following SSL APIs are new but relevant to both QUIC and DTLS:

SSL_get_event_timeout(3)

Determines when the QUIC implementation should next be woken up via a call to SSL_handle_events(3) (or another I/O function such as SSL_read(3) or SSL_write(3)), if ever.

This can also be used with DTLS and supersedes DTLSv1_get_timeout(3) for new usage.

SSL_handle_events(3)

This is a non-specific I/O operation which makes a best effort attempt to perform any pending I/O or timeout processing. It can be used to advance the QUIC state machine by processing incoming network traffic, generating outgoing network traffic and handling any expired timeout events. Most other I/O functions on an SSL object, such as SSL_read(3) and SSL_write(3), implicitly perform event handling on the SSL object, so calling this function is only needed if no other I/O function is to be called.

This can also be used with DTLS and supersedes DTLSv1_handle_timeout(3) for new usage.

The following SSL APIs are specific to QUIC:

SSL_new_listener(3)

Creates a listener SSL object, which differs from an ordinary SSL object in that it is used to provide an abstraction for the acceptance of network connections in a protocol-agnostic manner.

Currently, listener SSL objects are only supported for QUIC server usage or client-only usage. The listener interface may expand to support additional protocols in the future.

SSL_new_listener_from(3)

Creates a listener SSL object which is subordinate to a QUIC domain SSL object ssl. See SSL_new_domain(3) and openssl-quic-concurrency(7) for details on QUIC domain SSL objects.

SSL_is_listener(3)

Returns 1 if and only if an SSL object is a listener SSL object.

SSL_get0_listener(3)

Returns an SSL object pointer (potentially to the same object on which it is called) or NULL.

SSL_listen(3)

Begin listening after a listener has been created. It is ordinarily not needed to call this because it will be called automatically on the first call to SSL_accept_connection(3).

SSL_accept_connection(3)

Accepts a new incoming connection for a listner SSL object. A new SSL object representing the accepted connection is created and returned on success. If no incoming connection is available and the listener SSL object is configured in nonblocking mode, NULL is returned.

SSL_get_accept_connection_queue_len(3)

Returns an informational value listing the number of connections waiting to be popped from the queue via calls to SSL_accept_connection().

SSL_new_from_listener(3)

Creates a client connection under a given listener SSL object. For QUIC, it is also possible to use SSL_new_from_listener() in conjunction with a listener which does accept incoming connections (i.e., which was not created using SSL_LISTENER_FLAG_NO_ACCEPT), leading to a UDP network endpoint which has both incoming and outgoing connections.

SSL_new_domain(3)

Creates a new QUIC event domain, represented as an SSL object. This is known as a QUIC domain SSL object. The concept of a QUIC event domain is discussed in detail in openssl-quic-concurrency(7).

SSL_is_domain(3)

Returns 1 if an SSL object is a QUIC domain SSL object.

SSL_get0_domain(3)

SSL_get0_domain() obtains a pointer to the QUIC domain SSL object in an SSL object hierarchy (if any).

SSL_set_blocking_mode(3), SSL_get_blocking_mode(3)

Configures whether blocking semantics are used at the application level. This determines whether calls to functions such as SSL_read(3) and SSL_write(3) will block.

SSL_get_rpoll_descriptor(3), SSL_get_wpoll_descriptor(3)

These functions facilitate operation in nonblocking mode.

When an SSL object is being used with an underlying network read BIO which supports polling, SSL_get_rpoll_descriptor(3) outputs an OS resource which can be used to synchronise on network readability events which should result in a call to SSL_handle_events(3). SSL_get_wpoll_descriptor(3) works in an analogous fashion for the underlying network write BIO.

The poll descriptors provided by these functions should be used only when SSL_net_read_desired(3) and SSL_net_write_desired(3) return 1, respectively.

SSL_net_read_desired(3), SSL_net_write_desired(3)

These functions facilitate operation in nonblocking mode and are used in conjunction with SSL_get_rpoll_descriptor(3) and SSL_get_wpoll_descriptor(3) respectively. They determine whether the respective poll descriptor is currently relevant for the purposes of polling.

SSL_set1_initial_peer_addr(3)

This function can be used to set the initial peer address for an outgoing QUIC connection. This function must be used in the general case when creating an outgoing QUIC connection; however, the correct initial peer address can be autodetected in some cases. See SSL_set1_initial_peer_addr(3) for details.

SSL_shutdown_ex(3)

This augments SSL_shutdown(3) by allowing an application error code to be specified. It also allows an application to decide how quickly it wants a shutdown to be performed, potentially by trading off strict RFC compliance.

SSL_stream_conclude(3)

This allows an application to indicate the normal end of the sending part of a QUIC stream. This corresponds to the FIN flag in the QUIC RFC. The receiving part of a stream remains usable.

SSL_stream_reset(3)

This allows an application to indicate the non-normal termination of the sending part of a stream. This corresponds to the RESET_STREAM frame in the QUIC RFC.

SSL_get_stream_write_state(3) and SSL_get_stream_read_state(3)

This allows an application to determine the current stream states for the sending and receiving parts of a stream respectively.

SSL_get_stream_write_error_code(3) and SSL_get_stream_read_error_code(3)

This allows an application to determine the application error code which was signalled by a peer which has performed a non-normal stream termination of the respective sending or receiving part of a stream, if any.

SSL_get_conn_close_info(3)

This allows an application to determine the error code which was signalled when the local or remote endpoint terminated the QUIC connection.

SSL_get0_connection(3)

Gets the QUIC connection SSL object from a QUIC stream SSL object.

SSL_is_connection(3)

Returns 1 if an SSL object is not a QUIC stream SSL object.

SSL_get_stream_type(3)

Provides information on the kind of QUIC stream which is attached to the SSL object.

SSL_get_stream_id(3)

Returns the QUIC stream ID which the QUIC protocol has associated with a QUIC stream.

SSL_new_stream(3)

Creates a new QUIC stream SSL object representing a new, locally-initiated QUIC stream.

SSL_accept_stream(3)

Potentially yields a new QUIC stream SSL object representing a new remotely-initiated QUIC stream, blocking until one is available if the connection is configured to do so.

SSL_get_accept_stream_queue_len(3)

Provides information on the number of pending remotely-initiated streams.

SSL_set_incoming_stream_policy(3)

Configures how incoming, remotely-initiated streams are handled. The incoming stream policy can be used to automatically reject streams created by the peer, or allow them to be handled using SSL_accept_stream(3).

SSL_set_default_stream_mode(3)

Used to configure or disable default stream mode; see the MODES OF OPERATION section for details.

The following BIO APIs are not specific to QUIC but have been added to facilitate QUIC-specific requirements and are closely associated with its use:

BIO_s_dgram_pair(3)

This is a new BIO method which is similar to a conventional BIO pair but provides datagram semantics.

BIO_get_rpoll_descriptor(3), BIO_get_wpoll_descriptor(3)

This is a new BIO API which allows a BIO to expose a poll descriptor. This API is used to implement the corresponding SSL APIs SSL_get_rpoll_descriptor(3) and SSL_get_wpoll_descriptor(3).

BIO_sendmmsg(3), BIO_recvmmsg(3)

This is a new BIO API which can be implemented by BIOs which implement datagram semantics. It is implemented by BIO_s_datagram(3) and BIO_s_dgram_pair(3). It is used by the QUIC implementation to send and receive UDP datagrams.

BIO_dgram_set_no_trunc(3), BIO_dgram_get_no_trunc(3)

By default, BIO_s_dgram_pair(3) has semantics comparable to those of Berkeley sockets being used with datagram semantics. This allows an alternative mode to be enabled in which datagrams will not be silently truncated if they are too large.

BIO_dgram_set_caps(3), BIO_dgram_get_caps(3)

These functions are used to allow the user of one end of a BIO_s_dgram_pair(3) to indicate its capabilities to the other end of a BIO_s_dgram_pair(3). In particular, this allows an application to inform the QUIC implementation of whether it is prepared to handle local and/or peer addresses in transmitted datagrams and to provide the applicable information in received datagrams.

BIO_dgram_get_local_addr_cap(3), BIO_dgram_set_local_addr_enable(3), BIO_dgram_get_local_addr_enable(3)

Local addressing support refers to the ability of a BIO with datagram semantics to allow a source address to be specified on transmission and to report the destination address on reception. These functions can be used to determine if a BIO can support local addressing and to enable local addressing support if it can.

BIO_err_is_non_fatal(3)

This is used to determine if an error while calling BIO_sendmmsg(3) or BIO_recvmmsg(3) is ephemeral in nature, such as "would block" errors.

Thread Assisted Mode

The optional thread assisted mode for clients can be used with OSSL_QUIC_client_thread_method(3). In this mode, a background thread is created automatically. The OpenSSL QUIC implementation then takes responsibility for ensuring that timeout events are handled on a timely basis even if no SSL I/O function such as SSL_read(3) or SSL_write(3) is called by the application for a long time.

All necessary locking is handled automatically internally, but the thread safety guarantees for the public SSL API are unchanged. Therefore, an application must still do its own locking if it wishes to make concurrent use of the public SSL APIs.

Because this method relies on threads, it is not available on platforms where threading support is not available or not supported by OpenSSL. However, it does provide the simplest mode of usage for an application.

The implementation may or may not use a common thread or thread pool to service multiple SSL objects in the same SSL_CTX.

Application-Driven Event Loops

OpenSSL's QUIC implementation is designed to facilitate applications which wish to use the SSL APIs in a blocking fashion, but is also designed to facilitate applications which wish to use the SSL APIs in a nonblocking fashion and manage their own event loops and polling directly. This is useful when it is desirable to host OpenSSL's QUIC implementation on top of an application's existing nonblocking I/O infrastructure.

This is supported via the concept of poll descriptors; see BIO_get_rpoll_descriptor(3) for details. Broadly, a BIO_POLL_DESCRIPTOR is a structure which expresses some kind of OS resource which can be used to synchronise on I/O events. The QUIC implementation provides a BIO_POLL_DESCRIPTOR based on the poll descriptor provided by the underlying network BIO. This is typically an OS socket handle, though custom BIOs could choose to implement their own custom poll descriptor format.

Broadly, an application which wishes to manage its own event loop should interact with the SSL object as follows:

See Also

SSL_handle_events(3), SSL_get_event_timeout(3), SSL_net_read_desired(3), SSL_net_write_desired(3), SSL_get_rpoll_descriptor(3), SSL_get_wpoll_descriptor(3), SSL_set_blocking_mode(3), SSL_shutdown_ex(3), SSL_set1_initial_peer_addr(3), SSL_stream_conclude(3), SSL_stream_reset(3), SSL_get_stream_read_state(3), SSL_get_stream_read_error_code(3), SSL_get_conn_close_info(3), SSL_get0_connection(3), SSL_get_stream_type(3), SSL_get_stream_id(3), SSL_new_stream(3), SSL_accept_stream(3), SSL_set_incoming_stream_policy(3), SSL_set_default_stream_mode(3), SSL_new_listener(3), SSL_new_listener_from(3), SSL_is_listener(3), SSL_get0_listener(3), SSL_listen(3), SSL_accept_connection(3), SSL_get_accept_connection_queue_len(3), SSL_new_domain(3), SSL_is_domain(3), SSL_get0_domain(3)

Referenced By

openssl-qlog.7ossl(7), openssl-quic-concurrency.7ossl(7), SSL_accept_stream.3ossl(3), SSL_new_stream.3ossl(3), SSL_read.3ossl(3), SSL_set_blocking_mode.3ossl(3), SSL_shutdown.3ossl(3), SSL_stream_conclude.3ossl(3), SSL_write.3ossl(3).

2025-04-15 3.5.0 OpenSSL