summaryrefslogtreecommitdiff
path: root/src/ssl/ssl_test.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/ssl/ssl_test.cc')
-rw-r--r--src/ssl/ssl_test.cc407
1 files changed, 252 insertions, 155 deletions
diff --git a/src/ssl/ssl_test.cc b/src/ssl/ssl_test.cc
index 03760b6e..2df005a2 100644
--- a/src/ssl/ssl_test.cc
+++ b/src/ssl/ssl_test.cc
@@ -4698,7 +4698,9 @@ static_assert(ssl_encryption_application < kNumQUICLevels,
class MockQUICTransport {
public:
- MockQUICTransport() {
+ enum class Role { kClient, kServer };
+
+ explicit MockQUICTransport(Role role) : role_(role) {
// The caller is expected to configure initial secrets.
levels_[ssl_encryption_initial].write_secret = {1};
levels_[ssl_encryption_initial].read_secret = {1};
@@ -4735,18 +4737,38 @@ class MockQUICTransport {
return false;
}
- if (level != ssl_encryption_early_data &&
- (read_secret == nullptr || write_secret == nullptr)) {
- ADD_FAILURE() << "key was unexpectedly null";
- return false;
+ bool expect_read_secret = true, expect_write_secret = true;
+ if (level == ssl_encryption_early_data) {
+ if (role_ == Role::kClient) {
+ expect_read_secret = false;
+ } else {
+ expect_write_secret = false;
+ }
}
- if (read_secret != nullptr) {
+
+ if (expect_read_secret) {
+ if (read_secret == nullptr) {
+ ADD_FAILURE() << "read secret was unexpectedly null";
+ return false;
+ }
levels_[level].read_secret.assign(read_secret, read_secret + secret_len);
+ } else if (read_secret != nullptr) {
+ ADD_FAILURE() << "unexpected read secret";
+ return false;
}
- if (write_secret != nullptr) {
+
+ if (expect_write_secret) {
+ if (write_secret == nullptr) {
+ ADD_FAILURE() << "write secret was unexpectedly null";
+ return false;
+ }
levels_[level].write_secret.assign(write_secret,
write_secret + secret_len);
+ } else if (write_secret != nullptr) {
+ ADD_FAILURE() << "unexpected write secret";
+ return false;
}
+
levels_[level].cipher = SSL_CIPHER_get_id(cipher);
return true;
}
@@ -4783,20 +4805,22 @@ class MockQUICTransport {
ssl_encryption_level_t level,
size_t num = std::numeric_limits<size_t>::max()) {
if (levels_[level].read_secret.empty()) {
- ADD_FAILURE() << "data read before keys configured";
+ ADD_FAILURE() << "data read before keys configured in level " << level;
return false;
}
// The peer may not have configured any keys yet.
if (peer_->levels_[level].write_secret.empty()) {
+ out->clear();
return true;
}
// Check the peer computed the same key.
if (peer_->levels_[level].write_secret != levels_[level].read_secret) {
- ADD_FAILURE() << "peer write key does not match read key";
+ ADD_FAILURE() << "peer write key does not match read key in level "
+ << level;
return false;
}
if (peer_->levels_[level].cipher != levels_[level].cipher) {
- ADD_FAILURE() << "peer cipher does not match";
+ ADD_FAILURE() << "peer cipher does not match in level " << level;
return false;
}
std::vector<uint8_t> *peer_data = &peer_->levels_[level].write_data;
@@ -4807,6 +4831,7 @@ class MockQUICTransport {
}
private:
+ Role role_;
MockQUICTransport *peer_ = nullptr;
bool has_alert_ = false;
@@ -4824,21 +4849,24 @@ class MockQUICTransport {
class MockQUICTransportPair {
public:
- MockQUICTransportPair() {
- server_.set_peer(&client_);
+ MockQUICTransportPair()
+ : client_(MockQUICTransport::Role::kClient),
+ server_(MockQUICTransport::Role::kServer) {
client_.set_peer(&server_);
+ server_.set_peer(&client_);
}
~MockQUICTransportPair() {
- server_.set_peer(nullptr);
client_.set_peer(nullptr);
+ server_.set_peer(nullptr);
}
MockQUICTransport *client() { return &client_; }
MockQUICTransport *server() { return &server_; }
bool SecretsMatch(ssl_encryption_level_t level) const {
- return client_.PeerSecretsMatch(level);
+ return client_.HasSecrets(level) && server_.HasSecrets(level) &&
+ client_.PeerSecretsMatch(level);
}
private:
@@ -4890,24 +4918,80 @@ class QUICMethodTest : public testing::Test {
SSL_set_connect_state(client_.get());
SSL_set_accept_state(server_.get());
- ex_data_.Set(client_.get(), transport_.client());
- ex_data_.Set(server_.get(), transport_.server());
+ transport_.reset(new MockQUICTransportPair);
+ ex_data_.Set(client_.get(), transport_->client());
+ ex_data_.Set(server_.get(), transport_->server());
return true;
}
- bool CreateSecondClientAndServer() {
- client_.reset(SSL_new(client_ctx_.get()));
- server_.reset(SSL_new(server_ctx_.get()));
- if (!client_ || !server_) {
- return false;
+ // CompleteHandshakesForQUIC runs |SSL_do_handshake| on |client_| and
+ // |server_| until each completes once. It returns true on success and false
+ // on failure.
+ bool CompleteHandshakesForQUIC() {
+ bool client_done = false, server_done = false;
+ while (!client_done || !server_done) {
+ if (!client_done) {
+ if (!ProvideHandshakeData(client_.get())) {
+ ADD_FAILURE() << "ProvideHandshakeData(client_) failed";
+ return false;
+ }
+ int client_ret = SSL_do_handshake(client_.get());
+ if (client_ret == 1) {
+ client_done = true;
+ } else {
+ EXPECT_EQ(client_ret, -1);
+ EXPECT_EQ(SSL_get_error(client_.get(), client_ret),
+ SSL_ERROR_WANT_READ);
+ }
+ }
+
+ if (!server_done) {
+ if (!ProvideHandshakeData(server_.get())) {
+ ADD_FAILURE() << "ProvideHandshakeData(server_) failed";
+ return false;
+ }
+ int server_ret = SSL_do_handshake(server_.get());
+ if (server_ret == 1) {
+ server_done = true;
+ } else {
+ EXPECT_EQ(server_ret, -1);
+ EXPECT_EQ(SSL_get_error(server_.get(), server_ret),
+ SSL_ERROR_WANT_READ);
+ }
+ }
}
+ return true;
+ }
- SSL_set_connect_state(client_.get());
- SSL_set_accept_state(server_.get());
+ bssl::UniquePtr<SSL_SESSION> CreateClientSessionForQUIC() {
+ g_last_session = nullptr;
+ SSL_CTX_sess_set_new_cb(client_ctx_.get(), SaveLastSession);
+ if (!CreateClientAndServer() ||
+ !CompleteHandshakesForQUIC()) {
+ return nullptr;
+ }
- ex_data_.Set(client_.get(), second_transport_.client());
- ex_data_.Set(server_.get(), second_transport_.server());
- return true;
+ // The server sent NewSessionTicket messages in the handshake.
+ if (!ProvideHandshakeData(client_.get()) ||
+ !SSL_process_quic_post_handshake(client_.get())) {
+ return nullptr;
+ }
+
+ return std::move(g_last_session);
+ }
+
+ void ExpectHandshakeSuccess() {
+ EXPECT_TRUE(transport_->SecretsMatch(ssl_encryption_application));
+ EXPECT_EQ(ssl_encryption_application, SSL_quic_read_level(client_.get()));
+ EXPECT_EQ(ssl_encryption_application, SSL_quic_write_level(client_.get()));
+ EXPECT_EQ(ssl_encryption_application, SSL_quic_read_level(server_.get()));
+ EXPECT_EQ(ssl_encryption_application, SSL_quic_write_level(server_.get()));
+ EXPECT_FALSE(transport_->client()->has_alert());
+ EXPECT_FALSE(transport_->server()->has_alert());
+
+ // SSL_do_handshake is now idempotent.
+ EXPECT_EQ(SSL_do_handshake(client_.get()), 1);
+ EXPECT_EQ(SSL_do_handshake(server_.get()), 1);
}
// The following functions may be configured on an |SSL_QUIC_METHOD| as
@@ -4942,8 +5026,7 @@ class QUICMethodTest : public testing::Test {
bssl::UniquePtr<SSL_CTX> server_ctx_;
static UnownedSSLExData<MockQUICTransport> ex_data_;
- MockQUICTransportPair transport_;
- MockQUICTransportPair second_transport_;
+ std::unique_ptr<MockQUICTransportPair> transport_;
bssl::UniquePtr<SSL> client_;
bssl::UniquePtr<SSL> server_;
@@ -4966,33 +5049,13 @@ TEST_F(QUICMethodTest, Basic) {
SSL_CTX_sess_set_new_cb(client_ctx_.get(), SaveLastSession);
ASSERT_TRUE(SSL_CTX_set_quic_method(client_ctx_.get(), &quic_method));
ASSERT_TRUE(SSL_CTX_set_quic_method(server_ctx_.get(), &quic_method));
- ASSERT_TRUE(CreateClientAndServer());
- for (;;) {
- ASSERT_TRUE(ProvideHandshakeData(client_.get()));
- int client_ret = SSL_do_handshake(client_.get());
- if (client_ret != 1) {
- ASSERT_EQ(client_ret, -1);
- ASSERT_EQ(SSL_get_error(client_.get(), client_ret), SSL_ERROR_WANT_READ);
- }
-
- ASSERT_TRUE(ProvideHandshakeData(server_.get()));
- int server_ret = SSL_do_handshake(server_.get());
- if (server_ret != 1) {
- ASSERT_EQ(server_ret, -1);
- ASSERT_EQ(SSL_get_error(server_.get(), server_ret), SSL_ERROR_WANT_READ);
- }
-
- if (client_ret == 1 && server_ret == 1) {
- break;
- }
- }
+ ASSERT_TRUE(CreateClientAndServer());
+ ASSERT_TRUE(CompleteHandshakesForQUIC());
- EXPECT_EQ(SSL_do_handshake(client_.get()), 1);
- EXPECT_EQ(SSL_do_handshake(server_.get()), 1);
- EXPECT_TRUE(transport_.SecretsMatch(ssl_encryption_application));
- EXPECT_FALSE(transport_.client()->has_alert());
- EXPECT_FALSE(transport_.server()->has_alert());
+ ExpectHandshakeSuccess();
+ EXPECT_FALSE(SSL_session_reused(client_.get()));
+ EXPECT_FALSE(SSL_session_reused(server_.get()));
// The server sent NewSessionTicket messages in the handshake.
EXPECT_FALSE(g_last_session);
@@ -5001,35 +5064,13 @@ TEST_F(QUICMethodTest, Basic) {
EXPECT_TRUE(g_last_session);
// Create a second connection to verify resumption works.
- ASSERT_TRUE(CreateSecondClientAndServer());
+ ASSERT_TRUE(CreateClientAndServer());
bssl::UniquePtr<SSL_SESSION> session = std::move(g_last_session);
SSL_set_session(client_.get(), session.get());
- for (;;) {
- ASSERT_TRUE(ProvideHandshakeData(client_.get()));
- int client_ret = SSL_do_handshake(client_.get());
- if (client_ret != 1) {
- ASSERT_EQ(client_ret, -1);
- ASSERT_EQ(SSL_get_error(client_.get(), client_ret), SSL_ERROR_WANT_READ);
- }
-
- ASSERT_TRUE(ProvideHandshakeData(server_.get()));
- int server_ret = SSL_do_handshake(server_.get());
- if (server_ret != 1) {
- ASSERT_EQ(server_ret, -1);
- ASSERT_EQ(SSL_get_error(server_.get(), server_ret), SSL_ERROR_WANT_READ);
- }
-
- if (client_ret == 1 && server_ret == 1) {
- break;
- }
- }
+ ASSERT_TRUE(CompleteHandshakesForQUIC());
- EXPECT_EQ(SSL_do_handshake(client_.get()), 1);
- EXPECT_EQ(SSL_do_handshake(server_.get()), 1);
- EXPECT_TRUE(transport_.SecretsMatch(ssl_encryption_application));
- EXPECT_FALSE(transport_.client()->has_alert());
- EXPECT_FALSE(transport_.server()->has_alert());
+ ExpectHandshakeSuccess();
EXPECT_TRUE(SSL_session_reused(client_.get()));
EXPECT_TRUE(SSL_session_reused(server_.get()));
}
@@ -5056,32 +5097,133 @@ TEST_F(QUICMethodTest, HelloRetryRequest) {
OPENSSL_ARRAY_SIZE(kServerPrefs)));
ASSERT_TRUE(CreateClientAndServer());
+ ASSERT_TRUE(CompleteHandshakesForQUIC());
+ ExpectHandshakeSuccess();
+}
- for (;;) {
- ASSERT_TRUE(ProvideHandshakeData(client_.get()));
- int client_ret = SSL_do_handshake(client_.get());
- if (client_ret != 1) {
- ASSERT_EQ(client_ret, -1);
- ASSERT_EQ(SSL_get_error(client_.get(), client_ret), SSL_ERROR_WANT_READ);
+TEST_F(QUICMethodTest, ZeroRTTAccept) {
+ const SSL_QUIC_METHOD quic_method = {
+ SetEncryptionSecretsCallback,
+ AddHandshakeDataCallback,
+ FlushFlightCallback,
+ SendAlertCallback,
+ };
+
+ SSL_CTX_set_session_cache_mode(client_ctx_.get(), SSL_SESS_CACHE_BOTH);
+ SSL_CTX_set_early_data_enabled(client_ctx_.get(), 1);
+ SSL_CTX_set_early_data_enabled(server_ctx_.get(), 1);
+ ASSERT_TRUE(SSL_CTX_set_quic_method(client_ctx_.get(), &quic_method));
+ ASSERT_TRUE(SSL_CTX_set_quic_method(server_ctx_.get(), &quic_method));
+
+ bssl::UniquePtr<SSL_SESSION> session = CreateClientSessionForQUIC();
+ ASSERT_TRUE(session);
+
+ ASSERT_TRUE(CreateClientAndServer());
+ SSL_set_session(client_.get(), session.get());
+
+ // The client handshake should return immediately into the early data state.
+ ASSERT_EQ(SSL_do_handshake(client_.get()), 1);
+ EXPECT_TRUE(SSL_in_early_data(client_.get()));
+ // The transport should have keys for sending 0-RTT data.
+ EXPECT_TRUE(
+ transport_->client()->HasSecrets(ssl_encryption_early_data));
+
+ // The server will consume the ClientHello and also enter the early data
+ // state.
+ ASSERT_TRUE(ProvideHandshakeData(server_.get()));
+ ASSERT_EQ(SSL_do_handshake(server_.get()), 1);
+ EXPECT_TRUE(SSL_in_early_data(server_.get()));
+ EXPECT_TRUE(transport_->SecretsMatch(ssl_encryption_early_data));
+ // The transport should have keys for sending half-RTT data.
+ EXPECT_TRUE(
+ transport_->server()->HasSecrets(ssl_encryption_application));
+
+ // Finish up the client and server handshakes.
+ ASSERT_TRUE(CompleteHandshakesForQUIC());
+
+ // Both sides can now exchange 1-RTT data.
+ ExpectHandshakeSuccess();
+ EXPECT_TRUE(SSL_session_reused(client_.get()));
+ EXPECT_TRUE(SSL_session_reused(server_.get()));
+ EXPECT_FALSE(SSL_in_early_data(client_.get()));
+ EXPECT_FALSE(SSL_in_early_data(server_.get()));
+ EXPECT_TRUE(SSL_early_data_accepted(client_.get()));
+ EXPECT_TRUE(SSL_early_data_accepted(server_.get()));
+}
+
+TEST_F(QUICMethodTest, ZeroRTTReject) {
+ const SSL_QUIC_METHOD quic_method = {
+ SetEncryptionSecretsCallback,
+ AddHandshakeDataCallback,
+ FlushFlightCallback,
+ SendAlertCallback,
+ };
+
+ SSL_CTX_set_session_cache_mode(client_ctx_.get(), SSL_SESS_CACHE_BOTH);
+ SSL_CTX_set_early_data_enabled(client_ctx_.get(), 1);
+ SSL_CTX_set_early_data_enabled(server_ctx_.get(), 1);
+ ASSERT_TRUE(SSL_CTX_set_quic_method(client_ctx_.get(), &quic_method));
+ ASSERT_TRUE(SSL_CTX_set_quic_method(server_ctx_.get(), &quic_method));
+
+ bssl::UniquePtr<SSL_SESSION> session = CreateClientSessionForQUIC();
+ ASSERT_TRUE(session);
+
+ for (bool reject_hrr : {false, true}) {
+ SCOPED_TRACE(reject_hrr);
+
+ ASSERT_TRUE(CreateClientAndServer());
+ if (reject_hrr) {
+ // Configure the server to prefer P-256, which will reject 0-RTT via
+ // HelloRetryRequest.
+ int p256 = NID_X9_62_prime256v1;
+ ASSERT_TRUE(SSL_set1_curves(server_.get(), &p256, 1));
+ } else {
+ // Disable 0-RTT on the server, so it will reject it.
+ SSL_set_early_data_enabled(server_.get(), 0);
}
+ SSL_set_session(client_.get(), session.get());
+
+ // The client handshake should return immediately into the early data state.
+ ASSERT_EQ(SSL_do_handshake(client_.get()), 1);
+ EXPECT_TRUE(SSL_in_early_data(client_.get()));
+ // The transport should have keys for sending 0-RTT data.
+ EXPECT_TRUE(transport_->client()->HasSecrets(ssl_encryption_early_data));
+ // The server will consume the ClientHello, but it will not accept 0-RTT.
ASSERT_TRUE(ProvideHandshakeData(server_.get()));
- int server_ret = SSL_do_handshake(server_.get());
- if (server_ret != 1) {
- ASSERT_EQ(server_ret, -1);
- ASSERT_EQ(SSL_get_error(server_.get(), server_ret), SSL_ERROR_WANT_READ);
- }
+ ASSERT_EQ(SSL_do_handshake(server_.get()), -1);
+ EXPECT_EQ(SSL_ERROR_WANT_READ, SSL_get_error(server_.get(), -1));
+ EXPECT_FALSE(SSL_in_early_data(server_.get()));
+ EXPECT_FALSE(transport_->server()->HasSecrets(ssl_encryption_early_data));
- if (client_ret == 1 && server_ret == 1) {
- break;
+ // The client consumes the server response and signals 0-RTT rejection.
+ for (;;) {
+ ASSERT_TRUE(ProvideHandshakeData(client_.get()));
+ ASSERT_EQ(-1, SSL_do_handshake(client_.get()));
+ int err = SSL_get_error(client_.get(), -1);
+ if (err == SSL_ERROR_EARLY_DATA_REJECTED) {
+ break;
+ }
+ ASSERT_EQ(SSL_ERROR_WANT_READ, err);
}
- }
- EXPECT_EQ(SSL_do_handshake(client_.get()), 1);
- EXPECT_EQ(SSL_do_handshake(server_.get()), 1);
- EXPECT_TRUE(transport_.SecretsMatch(ssl_encryption_application));
- EXPECT_FALSE(transport_.client()->has_alert());
- EXPECT_FALSE(transport_.server()->has_alert());
+ // As in TLS over TCP, 0-RTT rejection is sticky.
+ ASSERT_EQ(-1, SSL_do_handshake(client_.get()));
+ ASSERT_EQ(SSL_ERROR_EARLY_DATA_REJECTED, SSL_get_error(client_.get(), -1));
+
+ // Finish up the client and server handshakes.
+ SSL_reset_early_data_reject(client_.get());
+ ASSERT_TRUE(CompleteHandshakesForQUIC());
+
+ // Both sides can now exchange 1-RTT data.
+ ExpectHandshakeSuccess();
+ EXPECT_TRUE(SSL_session_reused(client_.get()));
+ EXPECT_TRUE(SSL_session_reused(server_.get()));
+ EXPECT_FALSE(SSL_in_early_data(client_.get()));
+ EXPECT_FALSE(SSL_in_early_data(server_.get()));
+ EXPECT_FALSE(SSL_early_data_accepted(client_.get()));
+ EXPECT_FALSE(SSL_early_data_accepted(server_.get()));
+ }
}
// Test only releasing data to QUIC one byte at a time on request, to maximize
@@ -5137,11 +5279,7 @@ TEST_F(QUICMethodTest, Async) {
}
}
- EXPECT_EQ(SSL_do_handshake(client_.get()), 1);
- EXPECT_EQ(SSL_do_handshake(server_.get()), 1);
- EXPECT_TRUE(transport_.SecretsMatch(ssl_encryption_application));
- EXPECT_FALSE(transport_.client()->has_alert());
- EXPECT_FALSE(transport_.server()->has_alert());
+ ExpectHandshakeSuccess();
}
// Test buffering write data until explicit flushes.
@@ -5188,31 +5326,9 @@ TEST_F(QUICMethodTest, Buffered) {
buffered_flights.Set(client_.get(), &client_flight);
buffered_flights.Set(server_.get(), &server_flight);
- for (;;) {
- ASSERT_TRUE(ProvideHandshakeData(client_.get()));
- int client_ret = SSL_do_handshake(client_.get());
- if (client_ret != 1) {
- ASSERT_EQ(client_ret, -1);
- ASSERT_EQ(SSL_get_error(client_.get(), client_ret), SSL_ERROR_WANT_READ);
- }
-
- ASSERT_TRUE(ProvideHandshakeData(server_.get()));
- int server_ret = SSL_do_handshake(server_.get());
- if (server_ret != 1) {
- ASSERT_EQ(server_ret, -1);
- ASSERT_EQ(SSL_get_error(server_.get(), server_ret), SSL_ERROR_WANT_READ);
- }
-
- if (client_ret == 1 && server_ret == 1) {
- break;
- }
- }
+ ASSERT_TRUE(CompleteHandshakesForQUIC());
- EXPECT_EQ(SSL_do_handshake(client_.get()), 1);
- EXPECT_EQ(SSL_do_handshake(server_.get()), 1);
- EXPECT_TRUE(transport_.SecretsMatch(ssl_encryption_application));
- EXPECT_FALSE(transport_.client()->has_alert());
- EXPECT_FALSE(transport_.server()->has_alert());
+ ExpectHandshakeSuccess();
}
// Test that excess data at one level is rejected. That is, if a single
@@ -5262,13 +5378,13 @@ TEST_F(QUICMethodTest, ExcessProvidedData) {
EXPECT_EQ(ERR_GET_REASON(err), SSL_R_BUFFERED_MESSAGES_ON_CIPHER_CHANGE);
// The client sends an alert in response to this.
- ASSERT_TRUE(transport_.client()->has_alert());
- EXPECT_EQ(transport_.client()->alert_level(), ssl_encryption_initial);
- EXPECT_EQ(transport_.client()->alert(), SSL_AD_UNEXPECTED_MESSAGE);
+ ASSERT_TRUE(transport_->client()->has_alert());
+ EXPECT_EQ(transport_->client()->alert_level(), ssl_encryption_initial);
+ EXPECT_EQ(transport_->client()->alert(), SSL_AD_UNEXPECTED_MESSAGE);
// Sanity-check client did get far enough to process the ServerHello and
// install keys.
- EXPECT_TRUE(transport_.client()->HasSecrets(ssl_encryption_handshake));
+ EXPECT_TRUE(transport_->client()->HasSecrets(ssl_encryption_handshake));
}
// Test that |SSL_provide_quic_data| will reject data at the wrong level.
@@ -5298,7 +5414,7 @@ TEST_F(QUICMethodTest, ProvideWrongLevel) {
// Data cannot be provided at the next level.
std::vector<uint8_t> data;
ASSERT_TRUE(
- transport_.client()->ReadHandshakeData(&data, ssl_encryption_initial));
+ transport_->client()->ReadHandshakeData(&data, ssl_encryption_initial));
ASSERT_FALSE(SSL_provide_quic_data(client_.get(), ssl_encryption_handshake,
data.data(), data.size()));
ERR_clear_error();
@@ -5312,7 +5428,7 @@ TEST_F(QUICMethodTest, ProvideWrongLevel) {
// Data cannot be provided at the previous level.
ASSERT_TRUE(
- transport_.client()->ReadHandshakeData(&data, ssl_encryption_handshake));
+ transport_->client()->ReadHandshakeData(&data, ssl_encryption_handshake));
ASSERT_FALSE(SSL_provide_quic_data(client_.get(), ssl_encryption_initial,
data.data(), data.size()));
}
@@ -5357,32 +5473,13 @@ TEST_F(QUICMethodTest, BadPostHandshake) {
ASSERT_TRUE(SSL_CTX_set_quic_method(client_ctx_.get(), &quic_method));
ASSERT_TRUE(SSL_CTX_set_quic_method(server_ctx_.get(), &quic_method));
ASSERT_TRUE(CreateClientAndServer());
-
- for (;;) {
- ASSERT_TRUE(ProvideHandshakeData(client_.get()));
- int client_ret = SSL_do_handshake(client_.get());
- if (client_ret != 1) {
- ASSERT_EQ(client_ret, -1);
- ASSERT_EQ(SSL_get_error(client_.get(), client_ret), SSL_ERROR_WANT_READ);
- }
-
- ASSERT_TRUE(ProvideHandshakeData(server_.get()));
- int server_ret = SSL_do_handshake(server_.get());
- if (server_ret != 1) {
- ASSERT_EQ(server_ret, -1);
- ASSERT_EQ(SSL_get_error(server_.get(), server_ret), SSL_ERROR_WANT_READ);
- }
-
- if (client_ret == 1 && server_ret == 1) {
- break;
- }
- }
+ ASSERT_TRUE(CompleteHandshakesForQUIC());
EXPECT_EQ(SSL_do_handshake(client_.get()), 1);
EXPECT_EQ(SSL_do_handshake(server_.get()), 1);
- EXPECT_TRUE(transport_.SecretsMatch(ssl_encryption_application));
- EXPECT_FALSE(transport_.client()->has_alert());
- EXPECT_FALSE(transport_.server()->has_alert());
+ EXPECT_TRUE(transport_->SecretsMatch(ssl_encryption_application));
+ EXPECT_FALSE(transport_->client()->has_alert());
+ EXPECT_FALSE(transport_->server()->has_alert());
// Junk sent as part of post-handshake data should cause an error.
uint8_t kJunk[] = {0x17, 0x0, 0x0, 0x4, 0xB, 0xE, 0xE, 0xF};