Rework options handling

Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/20061)
This commit is contained in:
Hugo Landau 2023-07-03 16:24:54 +01:00 committed by Pauli
parent 9562842b33
commit db2f98c4eb
5 changed files with 87 additions and 36 deletions

View File

@ -469,8 +469,6 @@ These options apply to SSL objects referencing a QUIC connection:
=back
Other options do not have an effect and will be ignored.
These options apply to SSL objects referencing a QUIC stream:
=over 4
@ -479,14 +477,20 @@ These options apply to SSL objects referencing a QUIC stream:
=back
Other options do not have an effect and will be ignored.
Options on QUIC connections are initialized from the options set on SSL_CTX
before a QUIC connection SSL object is created. Options on QUIC streams are
initialised from the options configured on the QUIC connection SSL object
they are created from.
If an SSL object is a QUIC connection object with a default stream attached,
only the stream-relevant options are applied. If it is a QUIC connection
without a default stream, the stream-relevant options are ignored.
Setting options which relate to QUIC streams on a QUIC connection SSL object has
no direct effect on the QUIC connection SSL object itself, but will change the
options set on the default stream (if there is one) and will also determine the
default options set on any future streams which are created.
Connection and stream relevant options are initialized from the options
set on SSL_CTX before the connection or stream objects are created.
Other options not mentioned above do not have an effect and will be ignored.
Options which relate to QUIC streams may also be set directly on QUIC stream SSL
objects. Setting connection-related options on such an object has no effect.
=head1 RETURN VALUES

View File

@ -2700,19 +2700,14 @@ static int ch_init_new_stream(QUIC_CHANNEL *ch, QUIC_STREAM *qs,
int server_init = ossl_quic_stream_is_server_init(qs);
int local_init = (ch->is_server == server_init);
int is_uni = !ossl_quic_stream_is_bidi(qs);
int cleanse = (ch->tls->ctx->options & SSL_OP_CLEANSE_PLAINTEXT) != 0;
if (can_send) {
if (can_send)
if ((qs->sstream = ossl_quic_sstream_new(INIT_APP_BUF_LEN)) == NULL)
goto err;
ossl_quic_sstream_set_cleanse(qs->sstream, cleanse);
}
if (can_recv) {
if (can_recv)
if ((qs->rstream = ossl_quic_rstream_new(NULL, NULL, 0)) == NULL)
goto err;
ossl_quic_rstream_set_cleanse(qs->rstream, cleanse);
}
/* TXFC */
if (!ossl_quic_txfc_init(&qs->txfc, &ch->conn_txfc))

View File

@ -331,7 +331,7 @@ SSL *ossl_quic_new(SSL_CTX *ctx)
sc->s3.flags |= TLS1_FLAGS_QUIC;
/* Restrict options derived from the SSL_CTX. */
sc->options &= OSSL_QUIC_PERMITTED_OPTIONS;
sc->options &= OSSL_QUIC_PERMITTED_OPTIONS_CONN;
sc->pha_enabled = 0;
#if defined(OPENSSL_THREADS)
@ -349,6 +349,7 @@ SSL *ossl_quic_new(SSL_CTX *ctx)
qc->default_stream_mode = SSL_DEFAULT_STREAM_MODE_AUTO_BIDI;
qc->default_ssl_mode = qc->ssl.ctx->mode;
qc->default_ssl_options = qc->ssl.ctx->options & OSSL_QUIC_PERMITTED_OPTIONS;
qc->default_blocking = 1;
qc->blocking = 1;
qc->incoming_stream_policy = SSL_INCOMING_STREAM_POLICY_AUTO;
@ -616,38 +617,70 @@ static void qc_set_default_xso(QUIC_CONNECTION *qc, QUIC_XSO *xso, int touch)
SSL_free(&old_xso->ssl);
}
/* SSL_set_options */
QUIC_NEEDS_LOCK
static void xso_update_options(QUIC_XSO *xso)
{
int cleanse = ((xso->ssl_options & SSL_OP_CLEANSE_PLAINTEXT) != 0);
if (xso->stream->rstream != NULL)
ossl_quic_rstream_set_cleanse(xso->stream->rstream, cleanse);
if (xso->stream->sstream != NULL)
ossl_quic_sstream_set_cleanse(xso->stream->sstream, cleanse);
}
/*
* SSL_set_options
* ---------------
*
* Setting options on a QCSO
* - configures the handshake-layer options;
* - configures the default data-plane options for new streams;
* - configures the data-plane options on the default XSO, if there is one.
*
* Setting options on a QSSO
* - configures data-plane options for that stream only.
*/
QUIC_TAKES_LOCK
static uint64_t quic_mask_or_options(SSL *ssl, uint64_t mask_value, uint64_t or_value)
{
QCTX ctx;
uint64_t options;
uint64_t hs_mask_value, hs_or_value, ret;
if (!expect_quic(ssl, &ctx))
return 0;
quic_lock(ctx.qc);
/*
* Currently most options that we permit are handled in the handshake
* layer.
*/
or_value &= OSSL_QUIC_PERMITTED_OPTIONS;
if (!ctx.is_stream) {
/*
* If we were called on the connection, we apply any handshake option
* changes.
*/
hs_mask_value = (mask_value & OSSL_QUIC_PERMITTED_OPTIONS_CONN);
hs_or_value = (or_value & OSSL_QUIC_PERMITTED_OPTIONS_CONN);
SSL_clear_options(ctx.qc->tls, mask_value);
options = SSL_set_options(ctx.qc->tls, or_value);
SSL_clear_options(ctx.qc->tls, hs_mask_value);
SSL_set_options(ctx.qc->tls, hs_or_value);
if (ctx.xso != NULL && ctx.xso->stream != NULL) {
int cleanse = ((options & SSL_OP_CLEANSE_PLAINTEXT) != 0);
if (ctx.xso->stream->rstream != NULL)
ossl_quic_rstream_set_cleanse(ctx.xso->stream->rstream, cleanse);
if (ctx.xso->stream->sstream != NULL)
ossl_quic_sstream_set_cleanse(ctx.xso->stream->sstream, cleanse);
/* Update defaults for new streams. */
ctx.qc->default_ssl_options
= ((ctx.qc->default_ssl_options & ~mask_value) | or_value)
& OSSL_QUIC_PERMITTED_OPTIONS;
}
if (ctx.xso != NULL) {
ctx.xso->ssl_options
= ((ctx.xso->ssl_options & ~mask_value) | or_value)
& OSSL_QUIC_PERMITTED_OPTIONS_STREAM;
xso_update_options(ctx.xso);
}
ret = ctx.is_stream ? ctx.xso->ssl_options : ctx.qc->default_ssl_options;
quic_unlock(ctx.qc);
return options;
return ret;
}
uint64_t ossl_quic_set_options(SSL *ssl, uint64_t options)
@ -1542,11 +1575,14 @@ static QUIC_XSO *create_xso_from_stream(QUIC_CONNECTION *qc, QUIC_STREAM *qs)
xso->conn = qc;
xso->blocking = qc->default_blocking;
xso->ssl_mode = qc->default_ssl_mode;
xso->ssl_options
= qc->default_ssl_options & OSSL_QUIC_PERMITTED_OPTIONS_STREAM;
xso->last_error = SSL_ERROR_NONE;
xso->stream = qs;
++qc->num_xso;
xso_update_options(xso);
return xso;
err:

View File

@ -85,6 +85,9 @@ struct quic_xso_st {
/* SSL_set_mode */
uint32_t ssl_mode;
/* SSL_set_options */
uint64_t ssl_options;
/*
* Last 'normal' error during an app-level I/O operation, used by
* SSL_get_error(); used to track data-path errors like SSL_ERROR_WANT_READ
@ -185,6 +188,9 @@ struct quic_conn_st {
/* SSL_set_mode. This is not used directly but inherited by new XSOs. */
uint32_t default_ssl_mode;
/* SSL_set_options. This is not used directly but inherited by new XSOs. */
uint64_t default_ssl_options;
/* SSL_set_incoming_stream_policy. */
int incoming_stream_policy;
uint64_t incoming_stream_aec;

View File

@ -3044,8 +3044,8 @@ void ossl_ssl_set_custom_record_layer(SSL_CONNECTION *s,
SSL_OP_LEGACY_SERVER_CONNECT | \
SSL_OP_IGNORE_UNEXPECTED_EOF )
/* Total mask of options permitted or ignored under QUIC. */
#define OSSL_QUIC_PERMITTED_OPTIONS \
/* Total mask of connection-level options permitted or ignored under QUIC. */
#define OSSL_QUIC_PERMITTED_OPTIONS_CONN \
(OSSL_LEGACY_SSL_OPTIONS | \
OSSL_TLS1_2_OPTIONS | \
SSL_OP_CIPHER_SERVER_PREFERENCE | \
@ -3053,9 +3053,19 @@ void ossl_ssl_set_custom_record_layer(SSL_CONNECTION *s,
SSL_OP_NO_TX_CERTIFICATE_COMPRESSION | \
SSL_OP_NO_RX_CERTIFICATE_COMPRESSION | \
SSL_OP_PRIORITIZE_CHACHA | \
SSL_OP_CLEANSE_PLAINTEXT | \
SSL_OP_NO_QUERY_MTU | \
SSL_OP_NO_TICKET | \
SSL_OP_NO_ANTI_REPLAY )
/* Total mask of stream-level options permitted or ignored under QUIC. */
#define OSSL_QUIC_PERMITTED_OPTIONS_STREAM \
(OSSL_LEGACY_SSL_OPTIONS | \
OSSL_TLS1_2_OPTIONS | \
SSL_OP_CLEANSE_PLAINTEXT )
/* Total mask of options permitted on either connections or streams. */
#define OSSL_QUIC_PERMITTED_OPTIONS \
(OSSL_QUIC_PERMITTED_OPTIONS_CONN | \
OSSL_QUIC_PERMITTED_OPTIONS_STREAM)
#endif