From 8ee3ee10e39fd6fe1323187c63ce41460bd4f9d4 Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Fri, 18 Aug 2023 18:32:21 +0200 Subject: [PATCH] quic_impl.c: Add QUIC_RAISE_NON_IO_ERROR() and use it Reviewed-by: Hugo Landau Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/21700) --- ssl/quic/quic_impl.c | 146 +++++++++++++++++++++++++------------------ 1 file changed, 86 insertions(+), 60 deletions(-) diff --git a/ssl/quic/quic_impl.c b/ssl/quic/quic_impl.c index 919affc0ae..6bb6b46583 100644 --- a/ssl/quic/quic_impl.c +++ b/ssl/quic/quic_impl.c @@ -128,7 +128,7 @@ static int quic_raise_normal_error(QCTX *ctx, * * ctx should be NULL if the connection lock is not held. */ -static int quic_raise_non_normal_error(QCTX *ctx, +static int quic_raise_non_normal_error(QCTX *ctx, int set_last_error, const char *file, int line, const char *func, @@ -139,9 +139,9 @@ static int quic_raise_non_normal_error(QCTX *ctx, va_list args; if (ctx != NULL) { - if (ctx->is_stream && ctx->xso != NULL) + if (set_last_error && ctx->is_stream && ctx->xso != NULL) ctx->xso->last_error = SSL_ERROR_SSL; - else if (!ctx->is_stream && ctx->qc != NULL) + else if (set_last_error && !ctx->is_stream && ctx->qc != NULL) ctx->qc->last_error = SSL_ERROR_SSL; if (reason == SSL_R_PROTOCOL_IS_SHUTDOWN && ctx->qc != NULL) @@ -162,7 +162,14 @@ static int quic_raise_non_normal_error(QCTX *ctx, quic_raise_normal_error((ctx), (err)) #define QUIC_RAISE_NON_NORMAL_ERROR(ctx, reason, msg) \ - quic_raise_non_normal_error((ctx), \ + quic_raise_non_normal_error((ctx), 1, \ + OPENSSL_FILE, OPENSSL_LINE, \ + OPENSSL_FUNC, \ + (reason), \ + (msg)) + +#define QUIC_RAISE_NON_IO_ERROR(ctx, reason, msg) \ + quic_raise_non_normal_error((ctx), 0, \ OPENSSL_FILE, OPENSSL_LINE, \ OPENSSL_FUNC, \ (reason), \ @@ -186,7 +193,7 @@ static int expect_quic(const SSL *s, QCTX *ctx) ctx->is_stream = 0; if (s == NULL) - return QUIC_RAISE_NON_NORMAL_ERROR(NULL, ERR_R_PASSED_NULL_PARAMETER, NULL); + return QUIC_RAISE_NON_IO_ERROR(NULL, ERR_R_PASSED_NULL_PARAMETER, NULL); switch (s->type) { case SSL_TYPE_QUIC_CONNECTION: @@ -204,7 +211,7 @@ static int expect_quic(const SSL *s, QCTX *ctx) return 1; default: - return QUIC_RAISE_NON_NORMAL_ERROR(NULL, ERR_R_INTERNAL_ERROR, NULL); + return QUIC_RAISE_NON_IO_ERROR(NULL, ERR_R_INTERNAL_ERROR, NULL); } } @@ -250,7 +257,7 @@ static int ossl_unused expect_quic_with_stream_lock(const SSL *s, int remote_ini } if (ctx->xso == NULL) { - QUIC_RAISE_NON_NORMAL_ERROR(ctx, SSL_R_NO_STREAM, NULL); + QUIC_RAISE_NON_IO_ERROR(ctx, SSL_R_NO_STREAM, NULL); goto err; } @@ -271,7 +278,7 @@ static int ossl_unused expect_quic_conn_only(const SSL *s, QCTX *ctx) return 0; if (ctx->is_stream) - return QUIC_RAISE_NON_NORMAL_ERROR(ctx, SSL_R_CONN_USE_ONLY, NULL); + return QUIC_RAISE_NON_IO_ERROR(ctx, SSL_R_CONN_USE_ONLY, NULL); return 1; } @@ -344,19 +351,24 @@ SSL *ossl_quic_new(SSL_CTX *ctx) SSL_CONNECTION *sc = NULL; qc = OPENSSL_zalloc(sizeof(*qc)); - if (qc == NULL) + if (qc == NULL) { + QUIC_RAISE_NON_IO_ERROR(NULL, ERR_R_CRYPTO_LIB, NULL); goto err; + } /* Initialise the QUIC_CONNECTION's stub header. */ ssl_base = &qc->ssl; if (!ossl_ssl_init(ssl_base, ctx, ctx->method, SSL_TYPE_QUIC_CONNECTION)) { ssl_base = NULL; + QUIC_RAISE_NON_IO_ERROR(NULL, ERR_R_INTERNAL_ERROR, NULL); goto err; } qc->tls = ossl_ssl_connection_new_int(ctx, TLS_method()); - if (qc->tls == NULL || (sc = SSL_CONNECTION_FROM_SSL(qc->tls)) == NULL) - goto err; + if (qc->tls == NULL || (sc = SSL_CONNECTION_FROM_SSL(qc->tls)) == NULL) { + QUIC_RAISE_NON_IO_ERROR(NULL, ERR_R_INTERNAL_ERROR, NULL); + goto err; + } /* override the user_ssl of the inner connection */ sc->s3.flags |= TLS1_FLAGS_QUIC; @@ -366,8 +378,10 @@ SSL *ossl_quic_new(SSL_CTX *ctx) sc->pha_enabled = 0; #if defined(OPENSSL_THREADS) - if ((qc->mutex = ossl_crypto_mutex_new()) == NULL) + if ((qc->mutex = ossl_crypto_mutex_new()) == NULL) { + QUIC_RAISE_NON_IO_ERROR(NULL, ERR_R_CRYPTO_LIB, NULL); goto err; + } #endif #if !defined(OPENSSL_NO_QUIC_THREAD_ASSIST) @@ -923,7 +937,7 @@ int ossl_quic_conn_set_blocking_mode(SSL *s, int blocking) /* Cannot enable blocking mode if we do not have pollable FDs. */ if (blocking != 0 && (!ctx.qc->can_poll_net_rbio || !ctx.qc->can_poll_net_wbio)) - return QUIC_RAISE_NON_NORMAL_ERROR(&ctx, ERR_R_UNSUPPORTED, NULL); + return QUIC_RAISE_NON_IO_ERROR(&ctx, ERR_R_UNSUPPORTED, NULL); if (!ctx.is_stream) { /* @@ -953,8 +967,8 @@ int ossl_quic_conn_set_initial_peer_addr(SSL *s, return 0; if (ctx.qc->started) - return QUIC_RAISE_NON_NORMAL_ERROR(&ctx, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED, - NULL); + return QUIC_RAISE_NON_IO_ERROR(&ctx, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED, + NULL); if (peer_addr == NULL) { BIO_ADDR_clear(&ctx.qc->init_peer_addr); @@ -1052,10 +1066,9 @@ int ossl_quic_get_rpoll_descriptor(SSL *s, BIO_POLL_DESCRIPTOR *desc) if (!expect_quic(s, &ctx)) return 0; - if (desc == NULL || ctx.qc->net_rbio == NULL) { - ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT); - return 0; - } + if (desc == NULL || ctx.qc->net_rbio == NULL) + return QUIC_RAISE_NON_IO_ERROR(&ctx, ERR_R_PASSED_INVALID_ARGUMENT, + NULL); return BIO_get_rpoll_descriptor(ctx.qc->net_rbio, desc); } @@ -1068,10 +1081,9 @@ int ossl_quic_get_wpoll_descriptor(SSL *s, BIO_POLL_DESCRIPTOR *desc) if (!expect_quic(s, &ctx)) return 0; - if (desc == NULL || ctx.qc->net_wbio == NULL) { - ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT); - return 0; - } + if (desc == NULL || ctx.qc->net_wbio == NULL) + return QUIC_RAISE_NON_IO_ERROR(&ctx, ERR_R_PASSED_INVALID_ARGUMENT, + NULL); return BIO_get_wpoll_descriptor(ctx.qc->net_wbio, desc); } @@ -1175,8 +1187,10 @@ int ossl_quic_conn_shutdown(SSL *s, uint64_t flags, if (!expect_quic(s, &ctx)) return -1; - if (ctx.is_stream) + if (ctx.is_stream) { + QUIC_RAISE_NON_IO_ERROR(&ctx, SSL_R_CONN_USE_ONLY, NULL); return -1; + } quic_lock(ctx.qc); @@ -1372,8 +1386,10 @@ static int create_channel(QUIC_CONNECTION *qc) args.now_cb_arg = qc; qc->ch = ossl_quic_channel_new(&args); - if (qc->ch == NULL) + if (qc->ch == NULL) { + QUIC_RAISE_NON_IO_ERROR(NULL, ERR_R_INTERNAL_ERROR, NULL); return 0; + } return 1; } @@ -1422,18 +1438,18 @@ static int quic_do_handshake(QCTX *ctx) if (BIO_ADDR_family(&qc->init_peer_addr) == AF_UNSPEC) { /* Peer address must have been set. */ - QUIC_RAISE_NON_NORMAL_ERROR(ctx, SSL_R_REMOTE_PEER_ADDRESS_NOT_SET, NULL); + QUIC_RAISE_NON_IO_ERROR(ctx, SSL_R_REMOTE_PEER_ADDRESS_NOT_SET, NULL); return -1; /* Non-protocol error */ } if (qc->as_server != qc->as_server_state) { - QUIC_RAISE_NON_NORMAL_ERROR(ctx, ERR_R_PASSED_INVALID_ARGUMENT, NULL); + QUIC_RAISE_NON_IO_ERROR(ctx, ERR_R_PASSED_INVALID_ARGUMENT, NULL); return -1; /* Non-protocol error */ } if (qc->net_rbio == NULL || qc->net_wbio == NULL) { /* Need read and write BIOs. */ - QUIC_RAISE_NON_NORMAL_ERROR(ctx, SSL_R_BIO_NOT_SET, NULL); + QUIC_RAISE_NON_IO_ERROR(ctx, SSL_R_BIO_NOT_SET, NULL); return -1; /* Non-protocol error */ } @@ -1442,7 +1458,7 @@ static int quic_do_handshake(QCTX *ctx) * non-blocking mode, which is fine. */ if (!ensure_channel_started(qc)) { - QUIC_RAISE_NON_NORMAL_ERROR(ctx, ERR_R_INTERNAL_ERROR, NULL); + QUIC_RAISE_NON_IO_ERROR(ctx, ERR_R_INTERNAL_ERROR, NULL); return -1; /* Non-protocol error */ } @@ -1461,7 +1477,7 @@ static int quic_do_handshake(QCTX *ctx) QUIC_RAISE_NON_NORMAL_ERROR(ctx, SSL_R_PROTOCOL_IS_SHUTDOWN, NULL); return 0; /* Shutdown before completion */ } else if (ret <= 0) { - QUIC_RAISE_NON_NORMAL_ERROR(ctx, ERR_R_INTERNAL_ERROR, NULL); + QUIC_RAISE_NON_IO_ERROR(ctx, ERR_R_INTERNAL_ERROR, NULL); return -1; /* Non-protocol error */ } @@ -1656,7 +1672,7 @@ static int qc_wait_for_default_xso_for_read(QCTX *ctx) */ qc_set_default_xso(qc, create_xso_from_stream(qc, qs), /*touch=*/0); if (qc->default_xso == NULL) - return QUIC_RAISE_NON_NORMAL_ERROR(ctx, ERR_R_INTERNAL_ERROR, NULL); + return QUIC_RAISE_NON_IO_ERROR(ctx, ERR_R_INTERNAL_ERROR, NULL); qc_touch_default_xso(qc); /* inhibits default XSO */ return 1; @@ -1667,15 +1683,21 @@ static QUIC_XSO *create_xso_from_stream(QUIC_CONNECTION *qc, QUIC_STREAM *qs) { QUIC_XSO *xso = NULL; - if ((xso = OPENSSL_zalloc(sizeof(*xso))) == NULL) + if ((xso = OPENSSL_zalloc(sizeof(*xso))) == NULL) { + QUIC_RAISE_NON_IO_ERROR(NULL, ERR_R_CRYPTO_LIB, NULL); goto err; + } - if (!ossl_ssl_init(&xso->ssl, qc->ssl.ctx, qc->ssl.method, SSL_TYPE_QUIC_XSO)) + if (!ossl_ssl_init(&xso->ssl, qc->ssl.ctx, qc->ssl.method, SSL_TYPE_QUIC_XSO)) { + QUIC_RAISE_NON_IO_ERROR(NULL, ERR_R_INTERNAL_ERROR, NULL); goto err; + } /* XSO refs QC */ - if (!SSL_up_ref(&qc->ssl)) + if (!SSL_up_ref(&qc->ssl)) { + QUIC_RAISE_NON_IO_ERROR(NULL, ERR_R_SSL_LIB, NULL); goto err; + } xso->conn = qc; xso->blocking = qc->default_blocking; @@ -1707,21 +1729,19 @@ static SSL *quic_conn_stream_new(QCTX *ctx, uint64_t flags, int need_lock) quic_lock(qc); if (!quic_mutation_allowed(qc, /*req_active=*/0)) { - QUIC_RAISE_NON_NORMAL_ERROR(ctx, SSL_R_PROTOCOL_IS_SHUTDOWN, NULL); + QUIC_RAISE_NON_IO_ERROR(ctx, SSL_R_PROTOCOL_IS_SHUTDOWN, NULL); goto err; } qs = ossl_quic_channel_new_stream_local(qc->ch, is_uni); if (qs == NULL) { - ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR); + QUIC_RAISE_NON_IO_ERROR(ctx, ERR_R_INTERNAL_ERROR, NULL); goto err; } xso = create_xso_from_stream(qc, qs); - if (xso == NULL) { - ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR); + if (xso == NULL) goto err; - } qc_touch_default_xso(qc); /* inhibits default XSO */ if (need_lock) @@ -2401,13 +2421,16 @@ static size_t ossl_quic_pending_int(const SSL *s, int check_channel) quic_lock(ctx.qc); - if (ctx.xso == NULL) + if (ctx.xso == NULL) { + QUIC_RAISE_NON_IO_ERROR(&ctx, SSL_R_NO_STREAM, NULL); goto out; + } if (ctx.xso->stream == NULL - || !ossl_quic_stream_has_recv_buffer(ctx.xso->stream)) - /* Cannot raise errors here because we are const, just fail. */ + || !ossl_quic_stream_has_recv_buffer(ctx.xso->stream)) { + QUIC_RAISE_NON_IO_ERROR(&ctx, ERR_R_INTERNAL_ERROR, NULL); goto out; + } if (!ossl_quic_rstream_available(ctx.xso->stream->rstream, &avail, &fin)) avail = 0; @@ -2578,8 +2601,8 @@ int ossl_quic_set_default_stream_mode(SSL *s, uint32_t mode) if (ctx.qc->default_xso_created) { quic_unlock(ctx.qc); - return QUIC_RAISE_NON_NORMAL_ERROR(&ctx, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED, - "too late to change default stream mode"); + return QUIC_RAISE_NON_IO_ERROR(&ctx, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED, + "too late to change default stream mode"); } switch (mode) { @@ -2590,8 +2613,8 @@ int ossl_quic_set_default_stream_mode(SSL *s, uint32_t mode) break; default: quic_unlock(ctx.qc); - return QUIC_RAISE_NON_NORMAL_ERROR(&ctx, ERR_R_PASSED_INVALID_ARGUMENT, - "bad default stream type"); + return QUIC_RAISE_NON_IO_ERROR(&ctx, ERR_R_PASSED_INVALID_ARGUMENT, + "bad default stream type"); } quic_unlock(ctx.qc); @@ -2637,8 +2660,8 @@ int ossl_quic_attach_stream(SSL *conn, SSL *stream) return 0; if (stream == NULL || stream->type != SSL_TYPE_QUIC_XSO) - return QUIC_RAISE_NON_NORMAL_ERROR(&ctx, ERR_R_PASSED_NULL_PARAMETER, - "stream to attach must be a valid QUIC stream"); + return QUIC_RAISE_NON_IO_ERROR(&ctx, ERR_R_PASSED_NULL_PARAMETER, + "stream to attach must be a valid QUIC stream"); xso = (QUIC_XSO *)stream; @@ -2646,8 +2669,8 @@ int ossl_quic_attach_stream(SSL *conn, SSL *stream) if (ctx.qc->default_xso != NULL) { quic_unlock(ctx.qc); - return QUIC_RAISE_NON_NORMAL_ERROR(&ctx, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED, - "connection already has a default stream"); + return QUIC_RAISE_NON_IO_ERROR(&ctx, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED, + "connection already has a default stream"); } /* @@ -2656,15 +2679,15 @@ int ossl_quic_attach_stream(SSL *conn, SSL *stream) */ if (!CRYPTO_GET_REF(&xso->ssl.references, &nref)) { quic_unlock(ctx.qc); - return QUIC_RAISE_NON_NORMAL_ERROR(&ctx, ERR_R_INTERNAL_ERROR, - "ref"); + return QUIC_RAISE_NON_IO_ERROR(&ctx, ERR_R_INTERNAL_ERROR, + "ref"); } if (nref != 1) { quic_unlock(ctx.qc); - return QUIC_RAISE_NON_NORMAL_ERROR(&ctx, ERR_R_PASSED_INVALID_ARGUMENT, - "stream being attached must have " - "only 1 reference"); + return QUIC_RAISE_NON_IO_ERROR(&ctx, ERR_R_PASSED_INVALID_ARGUMENT, + "stream being attached must have " + "only 1 reference"); } /* Caller's reference to the XSO is transferred to us. */ @@ -2727,7 +2750,7 @@ int ossl_quic_set_incoming_stream_policy(SSL *s, int policy, break; default: - ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT); + QUIC_RAISE_NON_IO_ERROR(&ctx, ERR_R_PASSED_INVALID_ARGUMENT, NULL); ret = 0; break; } @@ -2783,8 +2806,10 @@ SSL *ossl_quic_accept_stream(SSL *s, uint64_t flags) quic_lock(ctx.qc); if (qc_get_effective_incoming_stream_policy(ctx.qc) - == SSL_INCOMING_STREAM_POLICY_REJECT) + == SSL_INCOMING_STREAM_POLICY_REJECT) { + QUIC_RAISE_NON_IO_ERROR(&ctx, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED, NULL); goto out; + } qsm = ossl_quic_channel_get_qsm(ctx.qc->ch); @@ -3029,7 +3054,7 @@ int ossl_quic_set_write_buffer_size(SSL *ssl, size_t size) if (!ossl_quic_stream_has_send(ctx.xso->stream)) { /* Called on a unidirectional receive-only stream - error. */ - ERR_raise(ERR_LIB_SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + QUIC_RAISE_NON_IO_ERROR(&ctx, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED, NULL); goto out; } @@ -3043,7 +3068,7 @@ int ossl_quic_set_write_buffer_size(SSL *ssl, size_t size) } if (!ossl_quic_sstream_set_buffer_size(ctx.xso->stream->sstream, size)) { - ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR); + QUIC_RAISE_NON_IO_ERROR(&ctx, ERR_R_INTERNAL_ERROR, NULL); goto out; } @@ -3101,7 +3126,7 @@ int ossl_quic_key_update(SSL *ssl, int update_type) break; default: - ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT); + QUIC_RAISE_NON_IO_ERROR(&ctx, ERR_R_PASSED_INVALID_ARGUMENT, NULL); return 0; } @@ -3109,6 +3134,7 @@ int ossl_quic_key_update(SSL *ssl, int update_type) /* Attempt to perform a TXKU. */ if (!ossl_quic_channel_trigger_txku(ctx.qc->ch)) { + QUIC_RAISE_NON_IO_ERROR(&ctx, SSL_R_TOO_MANY_KEY_UPDATES, NULL); quic_unlock(ctx.qc); return 0; }