aboutsummaryrefslogtreecommitdiff
path: root/deps/boringssl/src/ssl/test/bssl_shim.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/boringssl/src/ssl/test/bssl_shim.cc')
-rw-r--r--deps/boringssl/src/ssl/test/bssl_shim.cc152
1 files changed, 123 insertions, 29 deletions
diff --git a/deps/boringssl/src/ssl/test/bssl_shim.cc b/deps/boringssl/src/ssl/test/bssl_shim.cc
index 31c0a01..f4e7fff 100644
--- a/deps/boringssl/src/ssl/test/bssl_shim.cc
+++ b/deps/boringssl/src/ssl/test/bssl_shim.cc
@@ -66,10 +66,6 @@ OPENSSL_MSVC_PRAGMA(comment(lib, "Ws2_32.lib"))
#include "test_config.h"
#include "test_state.h"
-#if defined(OPENSSL_LINUX) && !defined(OPENSSL_ANDROID)
-#define HANDSHAKER_SUPPORTED
-#endif
-
#if !defined(OPENSSL_WINDOWS)
static int closesocket(int sock) {
@@ -550,18 +546,6 @@ static bool CheckHandshakeProperties(SSL *ssl, bool is_resume,
}
}
- if (config->expect_token_binding_param != -1) {
- if (!SSL_is_token_binding_negotiated(ssl)) {
- fprintf(stderr, "no Token Binding negotiated\n");
- return false;
- }
- if (SSL_get_negotiated_token_binding_param(ssl) !=
- static_cast<uint8_t>(config->expect_token_binding_param)) {
- fprintf(stderr, "Token Binding param mismatch\n");
- return false;
- }
- }
-
if (config->expect_extended_master_secret && !SSL_get_extms_support(ssl)) {
fprintf(stderr, "No EMS for connection when expected\n");
return false;
@@ -675,6 +659,33 @@ static bool CheckHandshakeProperties(SSL *ssl, bool is_resume,
SSL_used_hello_retry_request(ssl) ? "" : "no ");
return false;
}
+
+ if (config->expect_ech_accept != !!SSL_ech_accepted(ssl)) {
+ fprintf(stderr, "ECH was %saccepted, but wanted opposite.\n",
+ SSL_ech_accepted(ssl) ? "" : "not ");
+ return false;
+ }
+
+ // Test that handshake hints correctly skipped the expected operations.
+ //
+ // TODO(davidben): Add support for TLS 1.2 hints and remove the version check.
+ // Also add a check for the session cache lookup.
+ if (config->handshake_hints && !config->allow_hint_mismatch &&
+ SSL_version(ssl) == TLS1_3_VERSION) {
+ const TestState *state = GetTestState(ssl);
+ if (!SSL_used_hello_retry_request(ssl) && state->used_private_key) {
+ fprintf(
+ stderr,
+ "Performed private key operation, but hint should have skipped it\n");
+ return false;
+ }
+
+ if (state->ticket_decrypt_done) {
+ fprintf(stderr,
+ "Performed ticket decryption, but hint should have skipped it\n");
+ return false;
+ }
+ }
return true;
}
@@ -692,7 +703,7 @@ static bool DoConnection(bssl::UniquePtr<SSL_SESSION> *out_session,
const TestConfig *retry_config, bool is_resume,
SSL_SESSION *session, SettingsWriter *writer) {
bssl::UniquePtr<SSL> ssl = config->NewSSL(
- ssl_ctx, session, is_resume, std::unique_ptr<TestState>(new TestState));
+ ssl_ctx, session, std::unique_ptr<TestState>(new TestState));
if (!ssl) {
return false;
}
@@ -701,6 +712,17 @@ static bool DoConnection(bssl::UniquePtr<SSL_SESSION> *out_session,
} else {
SSL_set_connect_state(ssl.get());
}
+ if (config->handshake_hints) {
+#if defined(HANDSHAKER_SUPPORTED)
+ GetTestState(ssl.get())->get_handshake_hints_cb =
+ [&](const SSL_CLIENT_HELLO *client_hello) {
+ return GetHandshakeHint(ssl.get(), writer, is_resume, client_hello);
+ };
+#else
+ fprintf(stderr, "The external handshaker can only be used on Linux\n");
+ return false;
+#endif
+ }
int sock = Connect(config->port);
if (sock == -1) {
@@ -787,9 +809,44 @@ static bool DoConnection(bssl::UniquePtr<SSL_SESSION> *out_session,
}
assert(!config->handoff);
+ config = retry_config;
ret = DoExchange(out_session, &ssl, retry_config, is_resume, true, writer);
}
+ // An ECH rejection appears as a failed connection. Note |ssl| may use a
+ // different config on ECH rejection.
+ if (config->expect_no_ech_retry_configs ||
+ !config->expect_ech_retry_configs.empty()) {
+ bssl::Span<const uint8_t> expected =
+ config->expect_no_ech_retry_configs
+ ? bssl::Span<const uint8_t>()
+ : bssl::MakeConstSpan(reinterpret_cast<const uint8_t *>(
+ config->expect_ech_retry_configs.data()),
+ config->expect_ech_retry_configs.size());
+ if (ret) {
+ fprintf(stderr, "Expected ECH rejection, but connection succeeded.\n");
+ return false;
+ }
+ uint32_t err = ERR_peek_error();
+ if (SSL_get_error(ssl.get(), -1) != SSL_ERROR_SSL ||
+ ERR_GET_LIB(err) != ERR_LIB_SSL ||
+ ERR_GET_REASON(err) != SSL_R_ECH_REJECTED) {
+ fprintf(stderr, "Expected ECH rejection, but connection succeeded.\n");
+ return false;
+ }
+ const uint8_t *retry_configs;
+ size_t retry_configs_len;
+ SSL_get0_ech_retry_configs(ssl.get(), &retry_configs, &retry_configs_len);
+ if (bssl::MakeConstSpan(retry_configs, retry_configs_len) != expected) {
+ fprintf(stderr, "ECH retry configs did not match expectations.\n");
+ // Clear the error queue. Otherwise |SSL_R_ECH_REJECTED| will be printed
+ // to stderr and the test framework will think the test had the expected
+ // expectations.
+ ERR_clear_error();
+ return false;
+ }
+ }
+
if (!ret) {
// Print the |SSL_get_error| code. Otherwise, some failures are silent and
// hard to debug.
@@ -823,6 +880,7 @@ static bool DoExchange(bssl::UniquePtr<SSL_SESSION> *out_session,
int ret;
SSL *ssl = ssl_uniqueptr->get();
SSL_CTX *session_ctx = SSL_get_SSL_CTX(ssl);
+ TestState *test_state = GetTestState(ssl);
if (!config->implicit_handshake) {
if (config->handoff) {
@@ -831,6 +889,7 @@ static bool DoExchange(bssl::UniquePtr<SSL_SESSION> *out_session,
return false;
}
ssl = ssl_uniqueptr->get();
+ test_state = GetTestState(ssl);
#else
fprintf(stderr, "The external handshaker can only be used on Linux\n");
return false;
@@ -875,9 +934,44 @@ static bool DoExchange(bssl::UniquePtr<SSL_SESSION> *out_session,
return false;
}
+ if (config->early_write_after_message != 0) {
+ if (!SSL_in_early_data(ssl) || config->is_server) {
+ fprintf(stderr,
+ "-early-write-after-message only works for 0-RTT connections "
+ "on servers.\n");
+ return false;
+ }
+ if (!config->shim_writes_first || !config->async) {
+ fprintf(stderr,
+ "-early-write-after-message requires -shim-writes-first and "
+ "-async.\n");
+ return false;
+ }
+ // Run the handshake until the specified message. Note that, if a
+ // handshake record contains multiple messages, |SSL_do_handshake| usually
+ // processes both atomically. The test must ensure there is a record
+ // boundary after the desired message. Checking |last_message_received|
+ // confirms this.
+ do {
+ ret = SSL_do_handshake(ssl);
+ } while (test_state->last_message_received !=
+ config->early_write_after_message &&
+ RetryAsync(ssl, ret));
+ if (ret == 1) {
+ fprintf(stderr, "Handshake unexpectedly succeeded.\n");
+ return false;
+ }
+ if (test_state->last_message_received !=
+ config->early_write_after_message) {
+ // The handshake failed before we saw the target message. The generic
+ // error-handling logic in the caller will print the error.
+ return false;
+ }
+ }
+
// Reset the state to assert later that the callback isn't called in
// renegotations.
- GetTestState(ssl)->got_new_session = false;
+ test_state->got_new_session = false;
}
if (config->export_keying_material > 0) {
@@ -977,7 +1071,7 @@ static bool DoExchange(bssl::UniquePtr<SSL_SESSION> *out_session,
}
// Let only one byte of the record through.
- AsyncBioAllowWrite(GetTestState(ssl)->async_bio, 1);
+ AsyncBioAllowWrite(test_state->async_bio, 1);
int write_ret =
SSL_write(ssl, kInitialWrite, strlen(kInitialWrite));
if (SSL_get_error(ssl, write_ret) != SSL_ERROR_WANT_WRITE) {
@@ -1032,7 +1126,7 @@ static bool DoExchange(bssl::UniquePtr<SSL_SESSION> *out_session,
// After a successful read, with or without False Start, the handshake
// must be complete unless we are doing early data.
- if (!GetTestState(ssl)->handshake_done &&
+ if (!test_state->handshake_done &&
!SSL_early_data_accepted(ssl)) {
fprintf(stderr, "handshake was not completed after SSL_read\n");
return false;
@@ -1066,7 +1160,7 @@ static bool DoExchange(bssl::UniquePtr<SSL_SESSION> *out_session,
!config->implicit_handshake &&
// Session tickets are sent post-handshake in TLS 1.3.
GetProtocolVersion(ssl) < TLS1_3_VERSION &&
- GetTestState(ssl)->got_new_session) {
+ test_state->got_new_session) {
fprintf(stderr, "new session was established after the handshake\n");
return false;
}
@@ -1074,16 +1168,16 @@ static bool DoExchange(bssl::UniquePtr<SSL_SESSION> *out_session,
if (GetProtocolVersion(ssl) >= TLS1_3_VERSION && !config->is_server) {
bool expect_new_session =
!config->expect_no_session && !config->shim_shuts_down;
- if (expect_new_session != GetTestState(ssl)->got_new_session) {
+ if (expect_new_session != test_state->got_new_session) {
fprintf(stderr,
"new session was%s cached, but we expected the opposite\n",
- GetTestState(ssl)->got_new_session ? "" : " not");
+ test_state->got_new_session ? "" : " not");
return false;
}
if (expect_new_session) {
bool got_early_data =
- GetTestState(ssl)->new_session->ticket_max_early_data != 0;
+ test_state->new_session->ticket_max_early_data != 0;
if (config->expect_ticket_supports_early_data != got_early_data) {
fprintf(stderr,
"new session did%s support early data, but we expected the "
@@ -1095,7 +1189,7 @@ static bool DoExchange(bssl::UniquePtr<SSL_SESSION> *out_session,
}
if (out_session) {
- *out_session = std::move(GetTestState(ssl)->new_session);
+ *out_session = std::move(test_state->new_session);
}
ret = DoShutdown(ssl);
@@ -1144,10 +1238,10 @@ static bool DoExchange(bssl::UniquePtr<SSL_SESSION> *out_session,
if (config->renegotiate_explicit &&
SSL_total_renegotiations(ssl) !=
- GetTestState(ssl)->explicit_renegotiates) {
+ test_state->explicit_renegotiates) {
fprintf(stderr, "Performed %d renegotiations, but triggered %d of them\n",
SSL_total_renegotiations(ssl),
- GetTestState(ssl)->explicit_renegotiates);
+ test_state->explicit_renegotiates);
return false;
}
@@ -1184,8 +1278,8 @@ int main(int argc, char **argv) {
CRYPTO_library_init();
TestConfig initial_config, resume_config, retry_config;
- if (!ParseConfig(argc - 1, argv + 1, &initial_config, &resume_config,
- &retry_config)) {
+ if (!ParseConfig(argc - 1, argv + 1, /*is_shim=*/true, &initial_config,
+ &resume_config, &retry_config)) {
return Usage(argv[0]);
}