quic_impl.c: Add QUIC_RAISE_NON_IO_ERROR() and use it
authorTomas Mraz <tomas@openssl.org>
Fri, 18 Aug 2023 16:32:21 +0000 (18:32 +0200)
committerTomas Mraz <tomas@openssl.org>
Wed, 23 Aug 2023 15:18:48 +0000 (17:18 +0200)
Reviewed-by: Hugo Landau <hlandau@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/21700)

ssl/quic/quic_impl.c

index 919affc0ae9b8cc8a5bab9acefdbe19eaab77d44..6bb6b465838e7d8cb15130c951a43e272fa5f129 100644 (file)
@@ -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;
     }