aboutsummaryrefslogtreecommitdiffstats
path: root/test/sslapitest.c
diff options
context:
space:
mode:
authorMatt Caswell <matt@openssl.org>2023-10-23 12:16:44 +0100
committerMatt Caswell <matt@openssl.org>2023-10-24 17:37:19 +0100
commitdbbdb940d421daca4a65e765b5244bde6aed3f61 (patch)
tree4fd346b4aeb4567efabb382f3a91bef609c1d643 /test/sslapitest.c
parentb9b9f4886f87abd39535721243d4297fd45e558a (diff)
downloadopenssl-dbbdb940d421daca4a65e765b5244bde6aed3f61.tar.gz
Add a test for retries when sending app data
Reviewed-by: Hugo Landau <hlandau@openssl.org> Reviewed-by: Tomas Mraz <tomas@openssl.org> (Merged from https://github.com/openssl/openssl/pull/22473)
Diffstat (limited to 'test/sslapitest.c')
-rw-r--r--test/sslapitest.c98
1 files changed, 98 insertions, 0 deletions
diff --git a/test/sslapitest.c b/test/sslapitest.c
index 9539b4cf3a..2fbe76f979 100644
--- a/test/sslapitest.c
+++ b/test/sslapitest.c
@@ -11138,6 +11138,102 @@ end:
return testresult;
}
+/*
+ * Test that receiving retries when writing application data works as expected
+ */
+static int test_data_retry(void)
+{
+ SSL_CTX *cctx = NULL, *sctx = NULL;
+ SSL *clientssl = NULL, *serverssl = NULL;
+ int testresult = 0;
+ unsigned char inbuf[1200], outbuf[1200];
+ size_t i;
+ BIO *tmp = NULL;
+ BIO *bretry = BIO_new(bio_s_maybe_retry());
+ size_t written, readbytes, totread = 0;
+
+ if (!TEST_ptr(bretry))
+ goto end;
+
+ for (i = 0; i < sizeof(inbuf); i++)
+ inbuf[i] = i;
+ memset(outbuf, 0, sizeof(outbuf));
+
+ if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
+ TLS_client_method(), 0, 0, &sctx, &cctx,
+ cert, privkey)))
+ goto end;
+
+ if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, NULL,
+ NULL)))
+ goto end;
+
+ if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)))
+ goto end;
+
+ /* Smallest possible max send fragment is 512 */
+ if (!TEST_true(SSL_set_max_send_fragment(clientssl, 512)))
+ goto end;
+
+ tmp = SSL_get_wbio(clientssl);
+ if (!TEST_ptr(tmp))
+ goto end;
+ if (!TEST_true(BIO_up_ref(tmp)))
+ goto end;
+ BIO_push(bretry, tmp);
+ tmp = NULL;
+ SSL_set0_wbio(clientssl, bretry);
+ if (!BIO_up_ref(bretry)) {
+ bretry = NULL;
+ goto end;
+ }
+
+ for (i = 0; i < 3; i++) {
+ /* We expect this call to make no progress and indicate retry */
+ if (!TEST_false(SSL_write_ex(clientssl, inbuf, sizeof(inbuf), &written)))
+ goto end;
+ if (!TEST_int_eq(SSL_get_error(clientssl, 0), SSL_ERROR_WANT_WRITE))
+ goto end;
+
+ /* Allow one write to progess, but the next one to signal retry */
+ if (!TEST_true(BIO_ctrl(bretry, MAYBE_RETRY_CTRL_SET_RETRY_AFTER_CNT, 1,
+ NULL)))
+ goto end;
+
+ if (i == 2)
+ break;
+
+ /*
+ * This call will hopefully make progress but will still indicate retry
+ * because there is more data than will fit into a single record.
+ */
+ if (!TEST_false(SSL_write_ex(clientssl, inbuf, sizeof(inbuf), &written)))
+ goto end;
+ if (!TEST_int_eq(SSL_get_error(clientssl, 0), SSL_ERROR_WANT_WRITE))
+ goto end;
+ }
+
+ /* The final call should write the last chunk of data and succeed */
+ if (!TEST_true(SSL_write_ex(clientssl, inbuf, sizeof(inbuf), &written)))
+ goto end;
+ /* Read all the data available */
+ while (SSL_read_ex(serverssl, outbuf + totread, sizeof(outbuf) - totread,
+ &readbytes))
+ totread += readbytes;
+ if (!TEST_mem_eq(inbuf, sizeof(inbuf), outbuf, totread))
+ goto end;
+
+ testresult = 1;
+end:
+ SSL_free(serverssl);
+ SSL_free(clientssl);
+ SSL_CTX_free(sctx);
+ SSL_CTX_free(cctx);
+ BIO_free_all(bretry);
+ BIO_free(tmp);
+ return testresult;
+}
+
OPT_TEST_DECLARE_USAGE("certfile privkeyfile srpvfile tmpfile provider config dhfile\n")
int setup_tests(void)
@@ -11444,6 +11540,7 @@ int setup_tests(void)
ADD_ALL_TESTS(test_version, 6);
ADD_TEST(test_rstate_string);
ADD_ALL_TESTS(test_handshake_retry, 16);
+ ADD_TEST(test_data_retry);
return 1;
err:
@@ -11473,6 +11570,7 @@ void cleanup_tests(void)
OPENSSL_free(privkey8192);
bio_s_mempacket_test_free();
bio_s_always_retry_free();
+ bio_s_maybe_retry_free();
OSSL_PROVIDER_unload(defctxnull);
OSSL_LIB_CTX_free(libctx);
}