shim: extract a |DoSplitHandshake| helper function.
This makes the shim code read more naturally, in that the split-
handshake special case now lives in its own file.
This helps with creating a separate binary to perform split
handshakes.
Change-Id: I7970a8f368417791d18d4d44eeb379ef4b46c960
Reviewed-on: https://boringssl-review.googlesource.com/29347
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Adam Langley <agl@google.com>
diff --git a/ssl/test/bssl_shim.cc b/ssl/test/bssl_shim.cc
index 5044915..161d64b 100644
--- a/ssl/test/bssl_shim.cc
+++ b/ssl/test/bssl_shim.cc
@@ -90,20 +90,6 @@
return 1;
}
-// MoveBIOs moves the |BIO|s of |src| to |dst|. It is used for handoff.
-static void MoveBIOs(SSL *dest, SSL *src) {
- BIO *rbio = SSL_get_rbio(src);
- BIO_up_ref(rbio);
- SSL_set0_rbio(dest, rbio);
-
- BIO *wbio = SSL_get_wbio(src);
- BIO_up_ref(wbio);
- SSL_set0_wbio(dest, wbio);
-
- SSL_set0_rbio(src, nullptr);
- SSL_set0_wbio(src, nullptr);
-}
-
template<typename T>
struct Free {
void operator()(T *buf) {
@@ -759,14 +745,6 @@
return true;
}
-static bool HandoffReady(SSL *ssl, int ret) {
- return ret < 0 && SSL_get_error(ssl, ret) == SSL_ERROR_HANDOFF;
-}
-
-static bool HandbackReady(SSL *ssl, int ret) {
- return ret < 0 && SSL_get_error(ssl, ret) == SSL_ERROR_HANDBACK;
-}
-
static bool DoExchange(bssl::UniquePtr<SSL_SESSION> *out_session,
bssl::UniquePtr<SSL> *ssl_uniqueptr,
const TestConfig *config, bool is_resume, bool is_retry,
@@ -777,57 +755,10 @@
if (!config->implicit_handshake) {
if (config->handoff) {
- bssl::UniquePtr<SSL_CTX> ctx_handoff =
- config->SetupCtx(SSL_get_SSL_CTX(ssl));
- if (!ctx_handoff) {
+ if (!DoSplitHandshake(ssl_uniqueptr, writer, is_resume)) {
return false;
}
- bssl::SSL_CTX_set_handoff_mode(ctx_handoff.get(), 1);
-
- bssl::UniquePtr<SSL> ssl_handoff =
- config->NewSSL(ctx_handoff.get(), nullptr, false, nullptr);
- if (!ssl_handoff) {
- return false;
- }
- SSL_set_accept_state(ssl_handoff.get());
- if (!MoveTestState(ssl_handoff.get(), ssl)) {
- return false;
- }
- MoveBIOs(ssl_handoff.get(), ssl);
-
- do {
- ret = CheckIdempotentError("SSL_do_handshake", ssl_handoff.get(),
- [&]() -> int {
- return SSL_do_handshake(ssl_handoff.get());
- });
- } while (!HandoffReady(ssl_handoff.get(), ret) &&
- config->async &&
- RetryAsync(ssl_handoff.get(), ret));
-
- if (!HandoffReady(ssl_handoff.get(), ret)) {
- fprintf(stderr, "Handshake failed while waiting for handoff.\n");
- return false;
- }
-
- bssl::ScopedCBB cbb;
- bssl::Array<uint8_t> handoff;
- if (!CBB_init(cbb.get(), 512) ||
- !bssl::SSL_serialize_handoff(ssl_handoff.get(), cbb.get()) ||
- !CBBFinishArray(cbb.get(), &handoff) ||
- !writer->WriteHandoff(handoff)) {
- fprintf(stderr, "Handoff serialisation failed.\n");
- return false;
- }
-
- MoveBIOs(ssl, ssl_handoff.get());
- if (!MoveTestState(ssl, ssl_handoff.get())) {
- return false;
- }
-
- if (!SSL_apply_handoff(ssl, handoff)) {
- fprintf(stderr, "Handoff application failed.\n");
- return false;
- }
+ ssl = ssl_uniqueptr->get();
}
do {
@@ -836,52 +767,6 @@
});
} while (config->async && RetryAsync(ssl, ret));
- if (config->handoff) {
- if (!HandbackReady(ssl, ret)) {
- fprintf(stderr, "Connection failed to handback.\n");
- return false;
- }
-
- bssl::ScopedCBB cbb;
- bssl::Array<uint8_t> handback;
- if (!CBB_init(cbb.get(), 512) ||
- !bssl::SSL_serialize_handback(ssl, cbb.get()) ||
- !CBBFinishArray(cbb.get(), &handback) ||
- !writer->WriteHandback(handback)) {
- fprintf(stderr, "Handback serialisation failed.\n");
- return false;
- }
-
- bssl::UniquePtr<SSL_CTX> ctx_handback =
- config->SetupCtx(SSL_get_SSL_CTX(ssl));
- if (!ctx_handback) {
- return false;
- }
- bssl::UniquePtr<SSL> ssl_handback =
- config->NewSSL(ctx_handback.get(), nullptr, false, nullptr);
- if (!ssl_handback) {
- return false;
- }
- MoveBIOs(ssl_handback.get(), ssl);
- if (!MoveTestState(ssl_handback.get(), ssl)) {
- return false;
- }
-
- if (!SSL_apply_handback(ssl_handback.get(), handback)) {
- fprintf(stderr, "Applying handback failed.\n");
- return false;
- }
-
- *ssl_uniqueptr = std::move(ssl_handback);
- ssl = ssl_uniqueptr->get();
-
- do {
- ret = CheckIdempotentError("SSL_do_handshake", ssl, [&]() -> int {
- return SSL_do_handshake(ssl);
- });
- } while (config->async && RetryAsync(ssl, ret));
- }
-
if (config->forbid_renegotiation_after_handshake) {
SSL_set_renegotiate_mode(ssl, ssl_renegotiate_never);
}
diff --git a/ssl/test/handshake_util.cc b/ssl/test/handshake_util.cc
index b3d39f4..b1440fc 100644
--- a/ssl/test/handshake_util.cc
+++ b/ssl/test/handshake_util.cc
@@ -25,6 +25,8 @@
#include <openssl/ssl.h>
+using namespace bssl;
+
bool RetryAsync(SSL *ssl, int ret) {
// No error; don't retry.
if (ret >= 0) {
@@ -59,7 +61,7 @@
AsyncBioAllowWrite(test_state->async_bio, 1);
return true;
case SSL_ERROR_WANT_CHANNEL_ID_LOOKUP: {
- bssl::UniquePtr<EVP_PKEY> pkey =
+ UniquePtr<EVP_PKEY> pkey =
LoadPrivateKey(GetTestConfig(ssl)->send_channel_id);
if (!pkey) {
return false;
@@ -110,3 +112,100 @@
}
return ret;
}
+
+// MoveBIOs moves the |BIO|s of |src| to |dst|. It is used for handoff.
+static void MoveBIOs(SSL *dest, SSL *src) {
+ BIO *rbio = SSL_get_rbio(src);
+ BIO_up_ref(rbio);
+ SSL_set0_rbio(dest, rbio);
+
+ BIO *wbio = SSL_get_wbio(src);
+ BIO_up_ref(wbio);
+ SSL_set0_wbio(dest, wbio);
+
+ SSL_set0_rbio(src, nullptr);
+ SSL_set0_wbio(src, nullptr);
+}
+
+static bool HandoffReady(SSL *ssl, int ret) {
+ return ret < 0 && SSL_get_error(ssl, ret) == SSL_ERROR_HANDOFF;
+}
+
+static bool HandbackReady(SSL *ssl, int ret) {
+ return ret < 0 && SSL_get_error(ssl, ret) == SSL_ERROR_HANDBACK;
+}
+
+bool DoSplitHandshake(UniquePtr<SSL> *ssl_uniqueptr, SettingsWriter *writer,
+ bool is_resume) {
+ SSL *ssl = ssl_uniqueptr->get();
+ SSL_set_handoff_mode(ssl, 1);
+
+ const TestConfig *config = GetTestConfig(ssl);
+ int ret = -1;
+ do {
+ ret = CheckIdempotentError("SSL_do_handshake", ssl,
+ [&]() -> int { return SSL_do_handshake(ssl); });
+ } while (!HandoffReady(ssl, ret) &&
+ config->async &&
+ RetryAsync(ssl, ret));
+
+ ScopedCBB cbb;
+ Array<uint8_t> handoff;
+ if (!HandoffReady(ssl, ret) ||
+ !CBB_init(cbb.get(), 512) ||
+ !SSL_serialize_handoff(ssl, cbb.get()) ||
+ !CBBFinishArray(cbb.get(), &handoff) ||
+ !writer->WriteHandoff(handoff)) {
+ fprintf(stderr, "Handoff failed.\n");
+ return false;
+ }
+
+ UniquePtr<SSL_CTX> ctx = config->SetupCtx(ssl->ctx.get());
+ if (!ctx) {
+ return false;
+ }
+ UniquePtr<SSL> ssl_handshaker =
+ config->NewSSL(ctx.get(), nullptr, false, nullptr);
+ if (!ssl_handshaker) {
+ return false;
+ }
+ MoveBIOs(ssl_handshaker.get(), ssl);
+
+ if (!MoveTestState(ssl_handshaker.get(), ssl) ||
+ !SSL_apply_handoff(ssl_handshaker.get(), handoff)) {
+ fprintf(stderr, "Handoff application failed.\n");
+ return false;
+ }
+
+ do {
+ ret = CheckIdempotentError(
+ "SSL_do_handshake", ssl_handshaker.get(),
+ [&]() -> int { return SSL_do_handshake(ssl_handshaker.get()); });
+ } while (config->async && RetryAsync(ssl_handshaker.get(), ret));
+
+ Array<uint8_t> handback;
+ if (!HandbackReady(ssl_handshaker.get(), ret) ||
+ !CBB_init(cbb.get(), 512) ||
+ !SSL_serialize_handback(ssl_handshaker.get(), cbb.get()) ||
+ !CBBFinishArray(cbb.get(), &handback) ||
+ !writer->WriteHandback(handback)) {
+ fprintf(stderr, "Handback failed.\n");
+ return false;
+ }
+
+ UniquePtr<SSL> ssl_handback =
+ config->NewSSL(ctx.get(), nullptr, false, nullptr);
+ if (!ssl_handback) {
+ return false;
+ }
+ MoveBIOs(ssl_handback.get(), ssl_handshaker.get());
+
+ if (!MoveTestState(ssl_handback.get(), ssl_handshaker.get()) ||
+ !SSL_apply_handback(ssl_handback.get(), handback)) {
+ fprintf(stderr, "Handback application failed.\n");
+ return false;
+ }
+
+ *ssl_uniqueptr = std::move(ssl_handback);
+ return true;
+}
diff --git a/ssl/test/handshake_util.h b/ssl/test/handshake_util.h
index 2798695..ec86b8e 100644
--- a/ssl/test/handshake_util.h
+++ b/ssl/test/handshake_util.h
@@ -19,6 +19,8 @@
#include <openssl/base.h>
+#include "settings_writer.h"
+
// RetryAsync is called after a failed operation on |ssl| with return code
// |ret|. If the operation should be retried, it simulates one asynchronous
// event and returns true. Otherwise it returns false.
@@ -28,4 +30,9 @@
// errors are idempotent.
int CheckIdempotentError(const char *name, SSL *ssl, std::function<int()> func);
+// DoSplitHandshake performs a handoff and handback of an in-progress handshake,
+// updating |ssl_uniqueptr| in place.
+bool DoSplitHandshake(bssl::UniquePtr<SSL> *ssl_uniqueptr,
+ SettingsWriter *writer, bool is_resume);
+
#endif // HEADER_TEST_HANDSHAKE