Separate test function to perform an SSL connection

Split mbedtls_test_ssl_perform_connection() out of
mbedtls_test_ssl_perform_handshake().

No behavior change.

Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
diff --git a/tests/include/test/ssl_helpers.h b/tests/include/test/ssl_helpers.h
index 4a64b0f..dc2ab78 100644
--- a/tests/include/test/ssl_helpers.h
+++ b/tests/include/test/ssl_helpers.h
@@ -624,6 +624,49 @@
 #endif /* defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) */
 
 #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
+/** Perform an SSL handshake and exchange data over the connection.
+ *
+ * This function also handles cases where the handshake is expected to fail.
+ *
+ * If the handshake succeeds as expected, this function validates that
+ * connection parameters are as expected, exchanges data over the
+ * connection, and exercises some optional protocol features if they
+ * are enabled. See the code to see what features are validated and exercised.
+ *
+ * The handshake is expected to fail in the following cases:
+ * - If `options->expected_handshake_result != 0`.
+ * - If `options->expected_negotiated_version == MBEDTLS_SSL_VERSION_UNKNOWN`.
+ *
+ * \param[in] options   Options for the connection.
+ * \param client        The client endpoint. It must have been set up with
+ *                      mbedtls_test_ssl_endpoint_init() with \p options
+ *                      and #MBEDTLS_SSL_IS_CLIENT.
+ * \param server        The server endpoint. It must have been set up with
+ *                      mbedtls_test_ssl_endpoint_init() with \p options
+ *                      and #MBEDTLS_SSL_IS_CLIENT.
+ *
+ * \return              1 on success, 0 on failure. On failure, this function
+ *                      calls mbedtls_test_fail(), indicating the failure
+ *                      reason and location. The causes of failure are:
+ *                      - Inconsistent options or bad endpoint state.
+ *                      - Operational problem during the handshake.
+ *                      - The handshake was expected to pass, but failed.
+ *                      - The handshake was expected to fail, but passed or
+ *                        failed with a different result.
+ *                      - The handshake passed as expected, but some connection
+ *                        parameter (e.g. protocol version, cipher suite, ...)
+ *                        is not as expected.
+ *                      - The handshake passed as expected, but something
+ *                        went wrong when attempting to exchange data.
+ *                      - The handshake passed as expected, but something
+ *                        went wrong when exercising other features
+ *                        (e.g. renegotiation, serialization, ...).
+ */
+int mbedtls_test_ssl_perform_connection(
+    const mbedtls_test_handshake_test_options *options,
+    mbedtls_test_ssl_endpoint *client,
+    mbedtls_test_ssl_endpoint *server);
+
 void mbedtls_test_ssl_perform_handshake(
     const mbedtls_test_handshake_test_options *options);
 #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
diff --git a/tests/src/test_helpers/ssl_helpers.c b/tests/src/test_helpers/ssl_helpers.c
index b11ca88..dbea090 100644
--- a/tests/src/test_helpers/ssl_helpers.c
+++ b/tests/src/test_helpers/ssl_helpers.c
@@ -2272,10 +2272,111 @@
 }
 #endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */
 
+int mbedtls_test_ssl_perform_connection(
+    const mbedtls_test_handshake_test_options *options,
+    mbedtls_test_ssl_endpoint *client,
+    mbedtls_test_ssl_endpoint *server)
+{
+    enum { BUFFSIZE = 17000 };
+    int expected_handshake_result = options->expected_handshake_result;
+    int ok = 0;
+
+    TEST_EQUAL(mbedtls_test_mock_socket_connect(&(client->socket),
+                                                &(server->socket),
+                                                BUFFSIZE), 0);
+
+#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
+    if (options->resize_buffers != 0) {
+        /* Ensure that the buffer sizes are appropriate before resizes */
+        TEST_EQUAL(client->ssl.out_buf_len, MBEDTLS_SSL_OUT_BUFFER_LEN);
+        TEST_EQUAL(client->ssl.in_buf_len, MBEDTLS_SSL_IN_BUFFER_LEN);
+        TEST_EQUAL(server->ssl.out_buf_len, MBEDTLS_SSL_OUT_BUFFER_LEN);
+        TEST_EQUAL(server->ssl.in_buf_len, MBEDTLS_SSL_IN_BUFFER_LEN);
+    }
+#endif
+
+    if (options->expected_negotiated_version == MBEDTLS_SSL_VERSION_UNKNOWN) {
+        expected_handshake_result = MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION;
+    }
+
+    TEST_EQUAL(mbedtls_test_move_handshake_to_state(&(client->ssl),
+                                                    &(server->ssl),
+                                                    MBEDTLS_SSL_HANDSHAKE_OVER),
+               expected_handshake_result);
+
+    if (expected_handshake_result != 0) {
+        /* Connection will have failed by this point, skip to cleanup */
+        ok = 1;
+        goto exit;
+    }
+
+    TEST_EQUAL(mbedtls_ssl_is_handshake_over(&client->ssl), 1);
+
+    /* Make sure server state is moved to HANDSHAKE_OVER also. */
+    TEST_EQUAL(mbedtls_test_move_handshake_to_state(&(server->ssl),
+                                                    &(client->ssl),
+                                                    MBEDTLS_SSL_HANDSHAKE_OVER),
+               0);
+
+    TEST_EQUAL(mbedtls_ssl_is_handshake_over(&server->ssl), 1);
+
+    /* Check that both sides have negotiated the expected version. */
+    TEST_ASSERT(check_ssl_version(options->expected_negotiated_version,
+                                  &client->ssl,
+                                  &server->ssl));
+
+    if (options->expected_ciphersuite != 0) {
+        TEST_EQUAL(server->ssl.session->ciphersuite,
+                   options->expected_ciphersuite);
+    }
+
+#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
+    if (options->resize_buffers != 0) {
+        /* A server, when using DTLS, might delay a buffer resize to happen
+         * after it receives a message, so we force it. */
+        TEST_EQUAL(exchange_data(&(client->ssl), &(server->ssl)), 0);
+
+        TEST_EQUAL(client->ssl.out_buf_len,
+                   mbedtls_ssl_get_output_buflen(&client->ssl));
+        TEST_EQUAL(client->ssl.in_buf_len,
+                   mbedtls_ssl_get_input_buflen(&client->ssl));
+        TEST_EQUAL(server->ssl.out_buf_len,
+                   mbedtls_ssl_get_output_buflen(&server->ssl));
+        TEST_EQUAL(server->ssl.in_buf_len,
+                   mbedtls_ssl_get_input_buflen(&server->ssl));
+    }
+#endif
+
+    if (options->cli_msg_len != 0 || options->srv_msg_len != 0) {
+        /* Start data exchanging test */
+        TEST_EQUAL(mbedtls_test_ssl_exchange_data(
+                       &(client->ssl), options->cli_msg_len,
+                       options->expected_cli_fragments,
+                       &(server->ssl), options->srv_msg_len,
+                       options->expected_srv_fragments),
+                   0);
+    }
+#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION)
+    if (options->serialize == 1) {
+        TEST_ASSERT(test_serialization(options, client, server));
+    }
+#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */
+
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+    if (options->renegotiate) {
+        TEST_ASSERT(test_renegotiation(options, client, server));
+    }
+#endif /* MBEDTLS_SSL_RENEGOTIATION */
+
+    ok = 1;
+
+exit:
+    return ok;
+}
+
 void mbedtls_test_ssl_perform_handshake(
     const mbedtls_test_handshake_test_options *options)
 {
-    enum { BUFFSIZE = 17000 };
     mbedtls_test_ssl_endpoint client_struct;
     memset(&client_struct, 0, sizeof(client_struct));
     mbedtls_test_ssl_endpoint *const client = &client_struct;
@@ -2285,7 +2386,6 @@
 #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED)
     const char *psk_identity = "foo";
 #endif
-    int expected_handshake_result = options->expected_handshake_result;
 
     MD_OR_USE_PSA_INIT();
 
@@ -2354,91 +2454,7 @@
     }
 #endif /* MBEDTLS_SSL_RENEGOTIATION */
 
-    TEST_EQUAL(mbedtls_test_mock_socket_connect(&(client->socket),
-                                                &(server->socket),
-                                                BUFFSIZE), 0);
-
-#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
-    if (options->resize_buffers != 0) {
-        /* Ensure that the buffer sizes are appropriate before resizes */
-        TEST_EQUAL(client->ssl.out_buf_len, MBEDTLS_SSL_OUT_BUFFER_LEN);
-        TEST_EQUAL(client->ssl.in_buf_len, MBEDTLS_SSL_IN_BUFFER_LEN);
-        TEST_EQUAL(server->ssl.out_buf_len, MBEDTLS_SSL_OUT_BUFFER_LEN);
-        TEST_EQUAL(server->ssl.in_buf_len, MBEDTLS_SSL_IN_BUFFER_LEN);
-    }
-#endif
-
-    if (options->expected_negotiated_version == MBEDTLS_SSL_VERSION_UNKNOWN) {
-        expected_handshake_result = MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION;
-    }
-
-    TEST_EQUAL(mbedtls_test_move_handshake_to_state(&(client->ssl),
-                                                    &(server->ssl),
-                                                    MBEDTLS_SSL_HANDSHAKE_OVER),
-               expected_handshake_result);
-
-    if (expected_handshake_result != 0) {
-        /* Connection will have failed by this point, skip to cleanup */
-        goto exit;
-    }
-
-    TEST_EQUAL(mbedtls_ssl_is_handshake_over(&client->ssl), 1);
-
-    /* Make sure server state is moved to HANDSHAKE_OVER also. */
-    TEST_EQUAL(mbedtls_test_move_handshake_to_state(&(server->ssl),
-                                                    &(client->ssl),
-                                                    MBEDTLS_SSL_HANDSHAKE_OVER),
-               0);
-
-    TEST_EQUAL(mbedtls_ssl_is_handshake_over(&server->ssl), 1);
-
-    /* Check that both sides have negotiated the expected version. */
-    TEST_ASSERT(check_ssl_version(options->expected_negotiated_version,
-                                  &client->ssl,
-                                  &server->ssl));
-
-    if (options->expected_ciphersuite != 0) {
-        TEST_EQUAL(server->ssl.session->ciphersuite,
-                   options->expected_ciphersuite);
-    }
-
-#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
-    if (options->resize_buffers != 0) {
-        /* A server, when using DTLS, might delay a buffer resize to happen
-         * after it receives a message, so we force it. */
-        TEST_EQUAL(exchange_data(&(client->ssl), &(server->ssl)), 0);
-
-        TEST_EQUAL(client->ssl.out_buf_len,
-                   mbedtls_ssl_get_output_buflen(&client->ssl));
-        TEST_EQUAL(client->ssl.in_buf_len,
-                   mbedtls_ssl_get_input_buflen(&client->ssl));
-        TEST_EQUAL(server->ssl.out_buf_len,
-                   mbedtls_ssl_get_output_buflen(&server->ssl));
-        TEST_EQUAL(server->ssl.in_buf_len,
-                   mbedtls_ssl_get_input_buflen(&server->ssl));
-    }
-#endif
-
-    if (options->cli_msg_len != 0 || options->srv_msg_len != 0) {
-        /* Start data exchanging test */
-        TEST_EQUAL(mbedtls_test_ssl_exchange_data(
-                       &(client->ssl), options->cli_msg_len,
-                       options->expected_cli_fragments,
-                       &(server->ssl), options->srv_msg_len,
-                       options->expected_srv_fragments),
-                   0);
-    }
-#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION)
-    if (options->serialize == 1) {
-        TEST_ASSERT(test_serialization(options, client, server));
-    }
-#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */
-
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-    if (options->renegotiate) {
-        TEST_ASSERT(test_renegotiation(options, client, server));
-    }
-#endif /* MBEDTLS_SSL_RENEGOTIATION */
+    TEST_ASSERT(mbedtls_test_ssl_perform_connection(options, client, server));
 
     TEST_ASSERT(mbedtls_ssl_conf_get_user_data_p(&client->conf) == client);
     TEST_ASSERT(mbedtls_ssl_get_user_data_p(&client->ssl) == client);