Add a QUIC test for HelloRetryRequest. There's no reason to believe it doesn't work, but as it's a slightly different flow (two unencrypted ClientHellos), it makes sense to test it. Change-Id: Ic230f7720b459c99b9662cbab847d730d772ab2c Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/37064 Commit-Queue: David Benjamin <davidben@google.com> Commit-Queue: Steven Valdez <svaldez@google.com> Reviewed-by: Steven Valdez <svaldez@google.com>
diff --git a/ssl/ssl_test.cc b/ssl/ssl_test.cc index 6f180c7..03760b6 100644 --- a/ssl/ssl_test.cc +++ b/ssl/ssl_test.cc
@@ -4951,7 +4951,7 @@ UnownedSSLExData<MockQUICTransport> QUICMethodTest::ex_data_; -// Test a full handshake works. +// Test a full handshake and resumption work. TEST_F(QUICMethodTest, Basic) { const SSL_QUIC_METHOD quic_method = { SetEncryptionSecretsCallback, @@ -5034,6 +5034,56 @@ EXPECT_TRUE(SSL_session_reused(server_.get())); } +// Test that HelloRetryRequest in QUIC works. +TEST_F(QUICMethodTest, HelloRetryRequest) { + const SSL_QUIC_METHOD quic_method = { + SetEncryptionSecretsCallback, + AddHandshakeDataCallback, + FlushFlightCallback, + SendAlertCallback, + }; + + ASSERT_TRUE(SSL_CTX_set_quic_method(client_ctx_.get(), &quic_method)); + ASSERT_TRUE(SSL_CTX_set_quic_method(server_ctx_.get(), &quic_method)); + + // BoringSSL predicts the most preferred curve, so using different preferences + // will trigger HelloRetryRequest. + static const int kClientPrefs[] = {NID_X25519, NID_X9_62_prime256v1}; + ASSERT_TRUE(SSL_CTX_set1_curves(client_ctx_.get(), kClientPrefs, + OPENSSL_ARRAY_SIZE(kClientPrefs))); + static const int kServerPrefs[] = {NID_X9_62_prime256v1, NID_X25519}; + ASSERT_TRUE(SSL_CTX_set1_curves(server_ctx_.get(), kServerPrefs, + OPENSSL_ARRAY_SIZE(kServerPrefs))); + + 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; + } + } + + 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()); +} + // Test only releasing data to QUIC one byte at a time on request, to maximize // state machine pauses. Additionally, test that existing asynchronous callbacks // still work.