summaryrefslogtreecommitdiffstats
path: root/src/ssl/test
diff options
context:
space:
mode:
Diffstat (limited to 'src/ssl/test')
-rw-r--r--src/ssl/test/bssl_shim.cc731
-rw-r--r--src/ssl/test/runner/cipher_suites.go13
-rw-r--r--src/ssl/test/runner/common.go104
-rw-r--r--src/ssl/test/runner/conn.go117
-rw-r--r--src/ssl/test/runner/dtls.go15
-rw-r--r--src/ssl/test/runner/handshake_client.go42
-rw-r--r--src/ssl/test/runner/handshake_messages.go236
-rw-r--r--src/ssl/test/runner/handshake_server.go32
-rw-r--r--src/ssl/test/runner/runner.go2916
-rw-r--r--src/ssl/test/test_config.cc25
-rw-r--r--src/ssl/test/test_config.h22
11 files changed, 1477 insertions, 2776 deletions
diff --git a/src/ssl/test/bssl_shim.cc b/src/ssl/test/bssl_shim.cc
index edae67b..3b95d7e 100644
--- a/src/ssl/test/bssl_shim.cc
+++ b/src/ssl/test/bssl_shim.cc
@@ -38,14 +38,10 @@
#include <openssl/bio.h>
#include <openssl/buf.h>
#include <openssl/bytestring.h>
-#include <openssl/cipher.h>
#include <openssl/err.h>
-#include <openssl/hmac.h>
-#include <openssl/rand.h>
#include <openssl/ssl.h>
#include <memory>
-#include <string>
#include <vector>
#include "../../crypto/test/scoped_types.h"
@@ -94,17 +90,10 @@ struct TestState {
ScopedSSL_SESSION pending_session;
bool early_callback_called = false;
bool handshake_done = false;
- // private_key is the underlying private key used when testing custom keys.
- ScopedEVP_PKEY private_key;
- std::vector<uint8_t> signature;
- // signature_retries is the number of times an asynchronous sign operation has
- // been retried.
- unsigned signature_retries = 0;
- bool got_new_session = false;
};
static void TestStateExFree(void *parent, void *ptr, CRYPTO_EX_DATA *ad,
- int index, long argl, void *argp) {
+ int index, long argl, void *argp) {
delete ((TestState *)ptr);
}
@@ -140,137 +129,18 @@ static ScopedEVP_PKEY LoadPrivateKey(const std::string &file) {
return pkey;
}
-static int AsyncPrivateKeyType(SSL *ssl) {
- return EVP_PKEY_id(GetTestState(ssl)->private_key.get());
-}
-
-static size_t AsyncPrivateKeyMaxSignatureLen(SSL *ssl) {
- return EVP_PKEY_size(GetTestState(ssl)->private_key.get());
-}
-
-static ssl_private_key_result_t AsyncPrivateKeySign(
- SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out,
- const EVP_MD *md, const uint8_t *in, size_t in_len) {
- TestState *test_state = GetTestState(ssl);
- if (!test_state->signature.empty()) {
- fprintf(stderr, "AsyncPrivateKeySign called with operation pending.\n");
- abort();
- }
-
- ScopedEVP_PKEY_CTX ctx(EVP_PKEY_CTX_new(test_state->private_key.get(),
- nullptr));
- if (!ctx) {
- return ssl_private_key_failure;
- }
-
- // Write the signature into |test_state|.
- size_t len = 0;
- if (!EVP_PKEY_sign_init(ctx.get()) ||
- !EVP_PKEY_CTX_set_signature_md(ctx.get(), md) ||
- !EVP_PKEY_sign(ctx.get(), nullptr, &len, in, in_len)) {
- return ssl_private_key_failure;
- }
- test_state->signature.resize(len);
- if (!EVP_PKEY_sign(ctx.get(), bssl::vector_data(&test_state->signature), &len,
- in, in_len)) {
- return ssl_private_key_failure;
- }
- test_state->signature.resize(len);
-
- // The signature will be released asynchronously in |AsyncPrivateKeySignComplete|.
- return ssl_private_key_retry;
-}
-
-static ssl_private_key_result_t AsyncPrivateKeySignComplete(
- SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out) {
- TestState *test_state = GetTestState(ssl);
- if (test_state->signature.empty()) {
- fprintf(stderr,
- "AsyncPrivateKeySignComplete called without operation pending.\n");
- abort();
- }
-
- if (test_state->signature_retries < 2) {
- // Only return the signature on the second attempt, to test both incomplete
- // |sign| and |sign_complete|.
- return ssl_private_key_retry;
- }
-
- if (max_out < test_state->signature.size()) {
- fprintf(stderr, "Output buffer too small.\n");
- return ssl_private_key_failure;
- }
- memcpy(out, bssl::vector_data(&test_state->signature),
- test_state->signature.size());
- *out_len = test_state->signature.size();
-
- test_state->signature.clear();
- test_state->signature_retries = 0;
- return ssl_private_key_success;
-}
-
-static const SSL_PRIVATE_KEY_METHOD g_async_private_key_method = {
- AsyncPrivateKeyType,
- AsyncPrivateKeyMaxSignatureLen,
- AsyncPrivateKeySign,
- AsyncPrivateKeySignComplete,
-};
-
-template<typename T>
-struct Free {
- void operator()(T *buf) {
- free(buf);
- }
-};
-
static bool InstallCertificate(SSL *ssl) {
const TestConfig *config = GetConfigPtr(ssl);
- TestState *test_state = GetTestState(ssl);
-
- if (!config->digest_prefs.empty()) {
- std::unique_ptr<char, Free<char>> digest_prefs(
- strdup(config->digest_prefs.c_str()));
- std::vector<int> digest_list;
-
- for (;;) {
- char *token =
- strtok(digest_list.empty() ? digest_prefs.get() : nullptr, ",");
- if (token == nullptr) {
- break;
- }
-
- digest_list.push_back(EVP_MD_type(EVP_get_digestbyname(token)));
- }
-
- if (!SSL_set_private_key_digest_prefs(ssl, digest_list.data(),
- digest_list.size())) {
- return false;
- }
- }
-
- if (!config->key_file.empty()) {
- if (config->use_async_private_key) {
- test_state->private_key = LoadPrivateKey(config->key_file.c_str());
- if (!test_state->private_key) {
- return false;
- }
- SSL_set_private_key_method(ssl, &g_async_private_key_method);
- } else if (!SSL_use_PrivateKey_file(ssl, config->key_file.c_str(),
- SSL_FILETYPE_PEM)) {
- return false;
- }
+ if (!config->key_file.empty() &&
+ !SSL_use_PrivateKey_file(ssl, config->key_file.c_str(),
+ SSL_FILETYPE_PEM)) {
+ return false;
}
if (!config->cert_file.empty() &&
!SSL_use_certificate_file(ssl, config->cert_file.c_str(),
SSL_FILETYPE_PEM)) {
return false;
}
- if (!config->ocsp_response.empty() &&
- !SSL_CTX_set_ocsp_response(ssl->ctx,
- (const uint8_t *)config->ocsp_response.data(),
- config->ocsp_response.size())) {
- return false;
- }
return true;
}
@@ -326,29 +196,10 @@ static int SelectCertificateCallback(const struct ssl_early_callback_ctx *ctx) {
return 1;
}
-static int VerifySucceed(X509_STORE_CTX *store_ctx, void *arg) {
- SSL* ssl = (SSL*)X509_STORE_CTX_get_ex_data(store_ctx,
- SSL_get_ex_data_X509_STORE_CTX_idx());
- const TestConfig *config = GetConfigPtr(ssl);
-
- if (!config->expected_ocsp_response.empty()) {
- const uint8_t *data;
- size_t len;
- SSL_get0_ocsp_response(ssl, &data, &len);
- if (len == 0) {
- fprintf(stderr, "OCSP response not available in verify callback\n");
- return 0;
- }
- }
-
+static int SkipVerify(int preverify_ok, X509_STORE_CTX *store_ctx) {
return 1;
}
-static int VerifyFail(X509_STORE_CTX *store_ctx, void *arg) {
- store_ctx->error = X509_V_ERR_APPLICATION_VERIFICATION;
- return 0;
-}
-
static int NextProtosAdvertisedCallback(SSL *ssl, const uint8_t **out,
unsigned int *out_len, void *arg) {
const TestConfig *config = GetConfigPtr(ssl);
@@ -490,94 +341,6 @@ static void InfoCallback(const SSL *ssl, int type, int val) {
}
}
-static int NewSessionCallback(SSL *ssl, SSL_SESSION *session) {
- GetTestState(ssl)->got_new_session = true;
- // BoringSSL passes a reference to |session|.
- SSL_SESSION_free(session);
- return 1;
-}
-
-static int TicketKeyCallback(SSL *ssl, uint8_t *key_name, uint8_t *iv,
- EVP_CIPHER_CTX *ctx, HMAC_CTX *hmac_ctx,
- int encrypt) {
- // This is just test code, so use the all-zeros key.
- static const uint8_t kZeros[16] = {0};
-
- if (encrypt) {
- memcpy(key_name, kZeros, sizeof(kZeros));
- RAND_bytes(iv, 16);
- } else if (memcmp(key_name, kZeros, 16) != 0) {
- return 0;
- }
-
- if (!HMAC_Init_ex(hmac_ctx, kZeros, sizeof(kZeros), EVP_sha256(), NULL) ||
- !EVP_CipherInit_ex(ctx, EVP_aes_128_cbc(), NULL, kZeros, iv, encrypt)) {
- return -1;
- }
-
- if (!encrypt) {
- return GetConfigPtr(ssl)->renew_ticket ? 2 : 1;
- }
- return 1;
-}
-
-// kCustomExtensionValue is the extension value that the custom extension
-// callbacks will add.
-static const uint16_t kCustomExtensionValue = 1234;
-static void *const kCustomExtensionAddArg =
- reinterpret_cast<void *>(kCustomExtensionValue);
-static void *const kCustomExtensionParseArg =
- reinterpret_cast<void *>(kCustomExtensionValue + 1);
-static const char kCustomExtensionContents[] = "custom extension";
-
-static int CustomExtensionAddCallback(SSL *ssl, unsigned extension_value,
- const uint8_t **out, size_t *out_len,
- int *out_alert_value, void *add_arg) {
- if (extension_value != kCustomExtensionValue ||
- add_arg != kCustomExtensionAddArg) {
- abort();
- }
-
- if (GetConfigPtr(ssl)->custom_extension_skip) {
- return 0;
- }
- if (GetConfigPtr(ssl)->custom_extension_fail_add) {
- return -1;
- }
-
- *out = reinterpret_cast<const uint8_t*>(kCustomExtensionContents);
- *out_len = sizeof(kCustomExtensionContents) - 1;
-
- return 1;
-}
-
-static void CustomExtensionFreeCallback(SSL *ssl, unsigned extension_value,
- const uint8_t *out, void *add_arg) {
- if (extension_value != kCustomExtensionValue ||
- add_arg != kCustomExtensionAddArg ||
- out != reinterpret_cast<const uint8_t *>(kCustomExtensionContents)) {
- abort();
- }
-}
-
-static int CustomExtensionParseCallback(SSL *ssl, unsigned extension_value,
- const uint8_t *contents,
- size_t contents_len,
- int *out_alert_value, void *parse_arg) {
- if (extension_value != kCustomExtensionValue ||
- parse_arg != kCustomExtensionParseArg) {
- abort();
- }
-
- if (contents_len != sizeof(kCustomExtensionContents) - 1 ||
- memcmp(contents, kCustomExtensionContents, contents_len) != 0) {
- *out_alert_value = SSL_AD_DECODE_ERROR;
- return 0;
- }
-
- return 1;
-}
-
// Connect returns a new socket connected to localhost on |port| or -1 on
// error.
static int Connect(uint16_t port) {
@@ -643,23 +406,7 @@ static ScopedSSL_CTX SetupCtx(const TestConfig *config) {
return nullptr;
}
- std::string cipher_list = "ALL";
- if (!config->cipher.empty()) {
- cipher_list = config->cipher;
- SSL_CTX_set_options(ssl_ctx.get(), SSL_OP_CIPHER_SERVER_PREFERENCE);
- }
- if (!SSL_CTX_set_cipher_list(ssl_ctx.get(), cipher_list.c_str())) {
- return nullptr;
- }
-
- if (!config->cipher_tls10.empty() &&
- !SSL_CTX_set_cipher_list_tls10(ssl_ctx.get(),
- config->cipher_tls10.c_str())) {
- return nullptr;
- }
- if (!config->cipher_tls11.empty() &&
- !SSL_CTX_set_cipher_list_tls11(ssl_ctx.get(),
- config->cipher_tls11.c_str())) {
+ if (!SSL_CTX_set_cipher_list(ssl_ctx.get(), "ALL")) {
return nullptr;
}
@@ -691,46 +438,12 @@ static ScopedSSL_CTX SetupCtx(const TestConfig *config) {
SSL_CTX_set_alpn_select_cb(ssl_ctx.get(), AlpnSelectCallback, NULL);
}
- SSL_CTX_enable_tls_channel_id(ssl_ctx.get());
+ ssl_ctx->tlsext_channel_id_enabled_new = 1;
SSL_CTX_set_channel_id_cb(ssl_ctx.get(), ChannelIdCallback);
ssl_ctx->current_time_cb = CurrentTimeCallback;
SSL_CTX_set_info_callback(ssl_ctx.get(), InfoCallback);
- SSL_CTX_sess_set_new_cb(ssl_ctx.get(), NewSessionCallback);
-
- if (config->use_ticket_callback) {
- SSL_CTX_set_tlsext_ticket_key_cb(ssl_ctx.get(), TicketKeyCallback);
- }
-
- if (config->enable_client_custom_extension &&
- !SSL_CTX_add_client_custom_ext(
- ssl_ctx.get(), kCustomExtensionValue, CustomExtensionAddCallback,
- CustomExtensionFreeCallback, kCustomExtensionAddArg,
- CustomExtensionParseCallback, kCustomExtensionParseArg)) {
- return nullptr;
- }
-
- if (config->enable_server_custom_extension &&
- !SSL_CTX_add_server_custom_ext(
- ssl_ctx.get(), kCustomExtensionValue, CustomExtensionAddCallback,
- CustomExtensionFreeCallback, kCustomExtensionAddArg,
- CustomExtensionParseCallback, kCustomExtensionParseArg)) {
- return nullptr;
- }
-
- if (config->verify_fail) {
- SSL_CTX_set_cert_verify_callback(ssl_ctx.get(), VerifyFail, NULL);
- } else {
- SSL_CTX_set_cert_verify_callback(ssl_ctx.get(), VerifySucceed, NULL);
- }
-
- if (!config->signed_cert_timestamps.empty() &&
- !SSL_CTX_set_signed_cert_timestamp_list(
- ssl_ctx.get(), (const uint8_t *)config->signed_cert_timestamps.data(),
- config->signed_cert_timestamps.size())) {
- return nullptr;
- }
return ssl_ctx;
}
@@ -787,9 +500,6 @@ static bool RetryAsync(SSL *ssl, int ret) {
case SSL_ERROR_PENDING_CERTIFICATE:
// The handshake will resume without a second call to the early callback.
return InstallCertificate(ssl);
- case SSL_ERROR_WANT_PRIVATE_KEY_OPERATION:
- test_state->signature_retries++;
- return true;
default:
return false;
}
@@ -821,177 +531,6 @@ static int WriteAll(SSL *ssl, const uint8_t *in, size_t in_len) {
return ret;
}
-// DoShutdown calls |SSL_shutdown|, resolving any asynchronous operations. It
-// returns the result of the final |SSL_shutdown| call.
-static int DoShutdown(SSL *ssl) {
- const TestConfig *config = GetConfigPtr(ssl);
- int ret;
- do {
- ret = SSL_shutdown(ssl);
- } while (config->async && RetryAsync(ssl, ret));
- return ret;
-}
-
-// CheckHandshakeProperties checks, immediately after |ssl| completes its
-// initial handshake (or False Starts), whether all the properties are
-// consistent with the test configuration and invariants.
-static bool CheckHandshakeProperties(SSL *ssl, bool is_resume) {
- const TestConfig *config = GetConfigPtr(ssl);
-
- if (SSL_get_current_cipher(ssl) == nullptr) {
- fprintf(stderr, "null cipher after handshake\n");
- return false;
- }
-
- if (is_resume &&
- (!!SSL_session_reused(ssl) == config->expect_session_miss)) {
- fprintf(stderr, "session was%s reused\n",
- SSL_session_reused(ssl) ? "" : " not");
- return false;
- }
-
- bool expect_handshake_done = is_resume || !config->false_start;
- if (expect_handshake_done != GetTestState(ssl)->handshake_done) {
- fprintf(stderr, "handshake was%s completed\n",
- GetTestState(ssl)->handshake_done ? "" : " not");
- return false;
- }
-
- if (expect_handshake_done && !config->is_server) {
- bool expect_new_session =
- !config->expect_no_session &&
- (!SSL_session_reused(ssl) || config->expect_ticket_renewal);
- if (expect_new_session != GetTestState(ssl)->got_new_session) {
- fprintf(stderr,
- "new session was%s established, but we expected the opposite\n",
- GetTestState(ssl)->got_new_session ? "" : " not");
- return false;
- }
- }
-
- if (config->is_server && !GetTestState(ssl)->early_callback_called) {
- fprintf(stderr, "early callback not called\n");
- return false;
- }
-
- if (!config->expected_server_name.empty()) {
- const char *server_name =
- SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
- if (server_name != config->expected_server_name) {
- fprintf(stderr, "servername mismatch (got %s; want %s)\n",
- server_name, config->expected_server_name.c_str());
- return false;
- }
- }
-
- if (!config->expected_certificate_types.empty()) {
- const uint8_t *certificate_types;
- size_t certificate_types_len =
- SSL_get0_certificate_types(ssl, &certificate_types);
- if (certificate_types_len != config->expected_certificate_types.size() ||
- memcmp(certificate_types,
- config->expected_certificate_types.data(),
- certificate_types_len) != 0) {
- fprintf(stderr, "certificate types mismatch\n");
- return false;
- }
- }
-
- if (!config->expected_next_proto.empty()) {
- const uint8_t *next_proto;
- unsigned next_proto_len;
- SSL_get0_next_proto_negotiated(ssl, &next_proto, &next_proto_len);
- if (next_proto_len != config->expected_next_proto.size() ||
- memcmp(next_proto, config->expected_next_proto.data(),
- next_proto_len) != 0) {
- fprintf(stderr, "negotiated next proto mismatch\n");
- return false;
- }
- }
-
- if (!config->expected_alpn.empty()) {
- const uint8_t *alpn_proto;
- unsigned alpn_proto_len;
- SSL_get0_alpn_selected(ssl, &alpn_proto, &alpn_proto_len);
- if (alpn_proto_len != config->expected_alpn.size() ||
- memcmp(alpn_proto, config->expected_alpn.data(),
- alpn_proto_len) != 0) {
- fprintf(stderr, "negotiated alpn proto mismatch\n");
- return false;
- }
- }
-
- if (!config->expected_channel_id.empty()) {
- uint8_t channel_id[64];
- if (!SSL_get_tls_channel_id(ssl, channel_id, sizeof(channel_id))) {
- fprintf(stderr, "no channel id negotiated\n");
- return false;
- }
- if (config->expected_channel_id.size() != 64 ||
- memcmp(config->expected_channel_id.data(),
- channel_id, 64) != 0) {
- fprintf(stderr, "channel id mismatch\n");
- return false;
- }
- }
-
- if (config->expect_extended_master_secret) {
- if (!ssl->session->extended_master_secret) {
- fprintf(stderr, "No EMS for session when expected");
- return false;
- }
- }
-
- if (!config->expected_ocsp_response.empty()) {
- const uint8_t *data;
- size_t len;
- SSL_get0_ocsp_response(ssl, &data, &len);
- if (config->expected_ocsp_response.size() != len ||
- memcmp(config->expected_ocsp_response.data(), data, len) != 0) {
- fprintf(stderr, "OCSP response mismatch\n");
- return false;
- }
- }
-
- if (!config->expected_signed_cert_timestamps.empty()) {
- const uint8_t *data;
- size_t len;
- SSL_get0_signed_cert_timestamp_list(ssl, &data, &len);
- if (config->expected_signed_cert_timestamps.size() != len ||
- memcmp(config->expected_signed_cert_timestamps.data(),
- data, len) != 0) {
- fprintf(stderr, "SCT list mismatch\n");
- return false;
- }
- }
-
- if (config->expect_verify_result) {
- int expected_verify_result = config->verify_fail ?
- X509_V_ERR_APPLICATION_VERIFICATION :
- X509_V_OK;
-
- if (SSL_get_verify_result(ssl) != expected_verify_result) {
- fprintf(stderr, "Wrong certificate verification result\n");
- return false;
- }
- }
-
- if (!config->is_server) {
- /* Clients should expect a peer certificate chain iff this was not a PSK
- * cipher suite. */
- if (config->psk.empty()) {
- if (SSL_get_peer_cert_chain(ssl) == nullptr) {
- fprintf(stderr, "Missing peer certificate chain!\n");
- return false;
- }
- } else if (SSL_get_peer_cert_chain(ssl) != nullptr) {
- fprintf(stderr, "Unexpected peer certificate chain!\n");
- return false;
- }
- }
- return true;
-}
-
// DoExchange runs a test SSL exchange against the peer. On success, it returns
// true and sets |*out_session| to the negotiated SSL session. If the test is a
// resumption attempt, |is_resume| is true and |session| is the session from the
@@ -1023,10 +562,7 @@ static bool DoExchange(ScopedSSL_SESSION *out_session, SSL_CTX *ssl_ctx,
}
if (config->require_any_client_certificate) {
SSL_set_verify(ssl.get(), SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
- NULL);
- }
- if (config->verify_peer) {
- SSL_set_verify(ssl.get(), SSL_VERIFY_PEER, NULL);
+ SkipVerify);
}
if (config->false_start) {
SSL_set_mode(ssl.get(), SSL_MODE_ENABLE_FALSE_START);
@@ -1052,8 +588,8 @@ static bool DoExchange(ScopedSSL_SESSION *out_session, SSL_CTX *ssl_ctx,
if (config->tls_d5_bug) {
SSL_set_options(ssl.get(), SSL_OP_TLS_D5_BUG);
}
- if (config->microsoft_big_sslv3_buffer) {
- SSL_set_options(ssl.get(), SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER);
+ if (config->allow_unsafe_legacy_renegotiation) {
+ SSL_set_options(ssl.get(), SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION);
}
if (config->no_legacy_server_connect) {
SSL_clear_options(ssl.get(), SSL_OP_LEGACY_SERVER_CONNECT);
@@ -1101,6 +637,7 @@ static bool DoExchange(ScopedSSL_SESSION *out_session, SSL_CTX *ssl_ctx,
!SSL_enable_signed_cert_timestamps(ssl.get())) {
return false;
}
+ SSL_enable_fastradio_padding(ssl.get(), config->fastradio_padding);
if (config->min_version != 0) {
SSL_set_min_version(ssl.get(), (uint16_t)config->min_version);
}
@@ -1114,13 +651,14 @@ static bool DoExchange(ScopedSSL_SESSION *out_session, SSL_CTX *ssl_ctx,
if (config->install_ddos_callback) {
SSL_CTX_set_dos_protection_cb(ssl_ctx, DDoSCallback);
}
+ if (!config->cipher.empty() &&
+ !SSL_set_cipher_list(ssl.get(), config->cipher.c_str())) {
+ return false;
+ }
if (!config->reject_peer_renegotiations) {
/* Renegotiations are disabled by default. */
SSL_set_reject_peer_renegotiations(ssl.get(), 0);
}
- if (!config->check_close_notify) {
- SSL_set_quiet_shutdown(ssl.get(), 1);
- }
int sock = Connect(config->port);
if (sock == -1) {
@@ -1181,14 +719,139 @@ static bool DoExchange(ScopedSSL_SESSION *out_session, SSL_CTX *ssl_ctx,
ret = SSL_connect(ssl.get());
}
} while (config->async && RetryAsync(ssl.get(), ret));
- if (ret != 1 ||
- !CheckHandshakeProperties(ssl.get(), is_resume)) {
+ if (ret != 1) {
+ return false;
+ }
+
+ if (SSL_get_current_cipher(ssl.get()) == nullptr) {
+ fprintf(stderr, "null cipher after handshake\n");
+ return false;
+ }
+
+ if (is_resume &&
+ (!!SSL_session_reused(ssl.get()) == config->expect_session_miss)) {
+ fprintf(stderr, "session was%s reused\n",
+ SSL_session_reused(ssl.get()) ? "" : " not");
+ return false;
+ }
+
+ bool expect_handshake_done = is_resume || !config->false_start;
+ if (expect_handshake_done != GetTestState(ssl.get())->handshake_done) {
+ fprintf(stderr, "handshake was%s completed\n",
+ GetTestState(ssl.get())->handshake_done ? "" : " not");
+ return false;
+ }
+
+ if (config->is_server && !GetTestState(ssl.get())->early_callback_called) {
+ fprintf(stderr, "early callback not called\n");
return false;
}
- // Reset the state to assert later that the callback isn't called in
- // renegotations.
- GetTestState(ssl.get())->got_new_session = false;
+ if (!config->expected_server_name.empty()) {
+ const char *server_name =
+ SSL_get_servername(ssl.get(), TLSEXT_NAMETYPE_host_name);
+ if (server_name != config->expected_server_name) {
+ fprintf(stderr, "servername mismatch (got %s; want %s)\n",
+ server_name, config->expected_server_name.c_str());
+ return false;
+ }
+ }
+
+ if (!config->expected_certificate_types.empty()) {
+ uint8_t *certificate_types;
+ int num_certificate_types =
+ SSL_get0_certificate_types(ssl.get(), &certificate_types);
+ if (num_certificate_types !=
+ (int)config->expected_certificate_types.size() ||
+ memcmp(certificate_types,
+ config->expected_certificate_types.data(),
+ num_certificate_types) != 0) {
+ fprintf(stderr, "certificate types mismatch\n");
+ return false;
+ }
+ }
+
+ if (!config->expected_next_proto.empty()) {
+ const uint8_t *next_proto;
+ unsigned next_proto_len;
+ SSL_get0_next_proto_negotiated(ssl.get(), &next_proto, &next_proto_len);
+ if (next_proto_len != config->expected_next_proto.size() ||
+ memcmp(next_proto, config->expected_next_proto.data(),
+ next_proto_len) != 0) {
+ fprintf(stderr, "negotiated next proto mismatch\n");
+ return false;
+ }
+ }
+
+ if (!config->expected_alpn.empty()) {
+ const uint8_t *alpn_proto;
+ unsigned alpn_proto_len;
+ SSL_get0_alpn_selected(ssl.get(), &alpn_proto, &alpn_proto_len);
+ if (alpn_proto_len != config->expected_alpn.size() ||
+ memcmp(alpn_proto, config->expected_alpn.data(),
+ alpn_proto_len) != 0) {
+ fprintf(stderr, "negotiated alpn proto mismatch\n");
+ return false;
+ }
+ }
+
+ if (!config->expected_channel_id.empty()) {
+ uint8_t channel_id[64];
+ if (!SSL_get_tls_channel_id(ssl.get(), channel_id, sizeof(channel_id))) {
+ fprintf(stderr, "no channel id negotiated\n");
+ return false;
+ }
+ if (config->expected_channel_id.size() != 64 ||
+ memcmp(config->expected_channel_id.data(),
+ channel_id, 64) != 0) {
+ fprintf(stderr, "channel id mismatch\n");
+ return false;
+ }
+ }
+
+ if (config->expect_extended_master_secret) {
+ if (!ssl->session->extended_master_secret) {
+ fprintf(stderr, "No EMS for session when expected");
+ return false;
+ }
+ }
+
+ if (!config->expected_ocsp_response.empty()) {
+ const uint8_t *data;
+ size_t len;
+ SSL_get0_ocsp_response(ssl.get(), &data, &len);
+ if (config->expected_ocsp_response.size() != len ||
+ memcmp(config->expected_ocsp_response.data(), data, len) != 0) {
+ fprintf(stderr, "OCSP response mismatch\n");
+ return false;
+ }
+ }
+
+ if (!config->expected_signed_cert_timestamps.empty()) {
+ const uint8_t *data;
+ size_t len;
+ SSL_get0_signed_cert_timestamp_list(ssl.get(), &data, &len);
+ if (config->expected_signed_cert_timestamps.size() != len ||
+ memcmp(config->expected_signed_cert_timestamps.data(),
+ data, len) != 0) {
+ fprintf(stderr, "SCT list mismatch\n");
+ return false;
+ }
+ }
+
+ if (!config->is_server) {
+ /* Clients should expect a peer certificate chain iff this was not a PSK
+ * cipher suite. */
+ if (config->psk.empty()) {
+ if (SSL_get_peer_cert_chain(ssl.get()) == nullptr) {
+ fprintf(stderr, "Missing peer certificate chain!\n");
+ return false;
+ }
+ } else if (SSL_get_peer_cert_chain(ssl.get()) != nullptr) {
+ fprintf(stderr, "Unexpected peer certificate chain!\n");
+ return false;
+ }
+ }
}
if (config->export_keying_material > 0) {
@@ -1234,19 +897,18 @@ static bool DoExchange(ScopedSSL_SESSION *out_session, SSL_CTX *ssl_ctx,
}
// This mode writes a number of different record sizes in an attempt to
// trip up the CBC record splitting code.
- static const size_t kBufLen = 32769;
- std::unique_ptr<uint8_t[]> buf(new uint8_t[kBufLen]);
- memset(buf.get(), 0x42, kBufLen);
+ uint8_t buf[32769];
+ memset(buf, 0x42, sizeof(buf));
static const size_t kRecordSizes[] = {
0, 1, 255, 256, 257, 16383, 16384, 16385, 32767, 32768, 32769};
for (size_t i = 0; i < sizeof(kRecordSizes) / sizeof(kRecordSizes[0]);
i++) {
const size_t len = kRecordSizes[i];
- if (len > kBufLen) {
+ if (len > sizeof(buf)) {
fprintf(stderr, "Bad kRecordSizes value.\n");
return false;
}
- if (WriteAll(ssl.get(), buf.get(), len) < 0) {
+ if (WriteAll(ssl.get(), buf, len) < 0) {
return false;
}
}
@@ -1257,82 +919,53 @@ static bool DoExchange(ScopedSSL_SESSION *out_session, SSL_CTX *ssl_ctx,
return false;
}
}
- if (!config->shim_shuts_down) {
- for (;;) {
- static const size_t kBufLen = 16384;
- std::unique_ptr<uint8_t[]> buf(new uint8_t[kBufLen]);
-
- // Read only 512 bytes at a time in TLS to ensure records may be
- // returned in multiple reads.
- int n = DoRead(ssl.get(), buf.get(), config->is_dtls ? kBufLen : 512);
- int err = SSL_get_error(ssl.get(), n);
- if (err == SSL_ERROR_ZERO_RETURN ||
- (n == 0 && err == SSL_ERROR_SYSCALL)) {
- if (n != 0) {
- fprintf(stderr, "Invalid SSL_get_error output\n");
- return false;
- }
- // Stop on either clean or unclean shutdown.
- break;
- } else if (err != SSL_ERROR_NONE) {
- if (n > 0) {
- fprintf(stderr, "Invalid SSL_get_error output\n");
- return false;
- }
+ for (;;) {
+ uint8_t buf[512];
+ int n = DoRead(ssl.get(), buf, sizeof(buf));
+ int err = SSL_get_error(ssl.get(), n);
+ if (err == SSL_ERROR_ZERO_RETURN ||
+ (n == 0 && err == SSL_ERROR_SYSCALL)) {
+ if (n != 0) {
+ fprintf(stderr, "Invalid SSL_get_error output\n");
return false;
}
- // Successfully read data.
- if (n <= 0) {
+ // Accept shutdowns with or without close_notify.
+ // TODO(davidben): Write tests which distinguish these two cases.
+ break;
+ } else if (err != SSL_ERROR_NONE) {
+ if (n > 0) {
fprintf(stderr, "Invalid SSL_get_error output\n");
return false;
}
+ return false;
+ }
+ // Successfully read data.
+ if (n <= 0) {
+ fprintf(stderr, "Invalid SSL_get_error output\n");
+ return false;
+ }
- // After a successful read, with or without False Start, the handshake
- // must be complete.
- if (!GetTestState(ssl.get())->handshake_done) {
- fprintf(stderr, "handshake was not completed after SSL_read\n");
- return false;
- }
+ // After a successful read, with or without False Start, the handshake
+ // must be complete.
+ if (!GetTestState(ssl.get())->handshake_done) {
+ fprintf(stderr, "handshake was not completed after SSL_read\n");
+ return false;
+ }
- for (int i = 0; i < n; i++) {
- buf[i] ^= 0xff;
- }
- if (WriteAll(ssl.get(), buf.get(), n) < 0) {
- return false;
- }
+ for (int i = 0; i < n; i++) {
+ buf[i] ^= 0xff;
+ }
+ if (WriteAll(ssl.get(), buf, n) < 0) {
+ return false;
}
}
}
- if (!config->is_server && !config->false_start &&
- !config->implicit_handshake &&
- GetTestState(ssl.get())->got_new_session) {
- fprintf(stderr, "new session was established after the handshake\n");
- return false;
- }
-
if (out_session) {
out_session->reset(SSL_get1_session(ssl.get()));
}
- ret = DoShutdown(ssl.get());
-
- if (config->shim_shuts_down && config->check_close_notify) {
- // We initiate shutdown, so |SSL_shutdown| will return in two stages. First
- // it returns zero when our close_notify is sent, then one when the peer's
- // is received.
- if (ret != 0) {
- fprintf(stderr, "Unexpected SSL_shutdown result: %d != 0\n", ret);
- return false;
- }
- ret = DoShutdown(ssl.get());
- }
-
- if (ret != 1) {
- fprintf(stderr, "Unexpected SSL_shutdown result: %d != 1\n", ret);
- return false;
- }
-
+ SSL_shutdown(ssl.get());
return true;
}
diff --git a/src/ssl/test/runner/cipher_suites.go b/src/ssl/test/runner/cipher_suites.go
index ffc056d..70c7262 100644
--- a/src/ssl/test/runner/cipher_suites.go
+++ b/src/ssl/test/runner/cipher_suites.go
@@ -102,6 +102,7 @@ var cipherSuites = []*cipherSuite{
{TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, 32, 48, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12 | suiteSHA384, cipherAES, macSHA384, nil},
{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil},
{TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA, cipherAES, macSHA1, nil},
+ {TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 32, 0, 0, dheRSAKA, suiteTLS12, nil, nil, aeadCHACHA20POLY1305},
{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, dheRSAKA, suiteTLS12, nil, nil, aeadAESGCM},
{TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, dheRSAKA, suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
{TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, dheRSAKA, suiteTLS12, cipherAES, macSHA256, nil},
@@ -119,18 +120,12 @@ var cipherSuites = []*cipherSuite{
{TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, ecdheRSAKA, suiteECDHE, cipher3DES, macSHA1, nil},
{TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, dheRSAKA, 0, cipher3DES, macSHA1, nil},
{TLS_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, rsaKA, 0, cipher3DES, macSHA1, nil},
+ {TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256, 16, 0, 4, ecdhePSKKA, suiteECDHE | suiteTLS12 | suitePSK, nil, nil, aeadAESGCM},
{TLS_PSK_WITH_RC4_128_SHA, 16, 20, 0, pskKA, suiteNoDTLS | suitePSK, cipherRC4, macSHA1, nil},
{TLS_PSK_WITH_AES_128_CBC_SHA, 16, 20, 16, pskKA, suitePSK, cipherAES, macSHA1, nil},
{TLS_PSK_WITH_AES_256_CBC_SHA, 32, 20, 16, pskKA, suitePSK, cipherAES, macSHA1, nil},
{TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdhePSKKA, suiteECDHE | suitePSK, cipherAES, macSHA1, nil},
{TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdhePSKKA, suiteECDHE | suitePSK, cipherAES, macSHA1, nil},
- {TLS_RSA_WITH_NULL_SHA, 0, 20, 0, rsaKA, suiteNoDTLS, cipherNull, macSHA1, nil},
-}
-
-type nullCipher struct{}
-
-func cipherNull(key, iv []byte, isRead bool) interface{} {
- return nullCipher{}
}
func cipherRC4(key, iv []byte, isRead bool) interface{} {
@@ -375,7 +370,6 @@ func mutualCipherSuite(have []uint16, want uint16) *cipherSuite {
// A list of the possible cipher suite ids. Taken from
// http://www.iana.org/assignments/tls-parameters/tls-parameters.xml
const (
- TLS_RSA_WITH_NULL_SHA uint16 = 0x0002
TLS_RSA_WITH_RC4_128_MD5 uint16 = 0x0004
TLS_RSA_WITH_RC4_128_SHA uint16 = 0x0005
TLS_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x000a
@@ -412,12 +406,13 @@ const (
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0xc030
TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA uint16 = 0xc035
TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA uint16 = 0xc036
- renegotiationSCSV uint16 = 0x00ff
fallbackSCSV uint16 = 0x5600
)
// Additional cipher suite IDs, not IANA-assigned.
const (
+ TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256 uint16 = 0xcafe
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xcc13
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xcc14
+ TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xcc15
)
diff --git a/src/ssl/test/runner/common.go b/src/ssl/test/runner/common.go
index 77be9f6..edebba1 100644
--- a/src/ssl/test/runner/common.go
+++ b/src/ssl/test/runner/common.go
@@ -82,7 +82,6 @@ const (
extensionSignedCertificateTimestamp uint16 = 18
extensionExtendedMasterSecret uint16 = 23
extensionSessionTicket uint16 = 35
- extensionCustom uint16 = 1234 // not IANA assigned
extensionNextProtoNeg uint16 = 13172 // not IANA assigned
extensionRenegotiationInfo uint16 = 0xff01
extensionChannelID uint16 = 30032 // not IANA assigned
@@ -189,9 +188,7 @@ type ConnectionState struct {
VerifiedChains [][]*x509.Certificate // verified chains built from PeerCertificates
ChannelID *ecdsa.PublicKey // the channel ID for this connection
SRTPProtectionProfile uint16 // the negotiated DTLS-SRTP protection profile
- TLSUnique []byte // the tls-unique channel binding
- SCTList []byte // signed certificate timestamp list
- ClientCertSignatureHash uint8 // TLS id of the hash used by the client to sign the handshake
+ TLSUnique []byte
}
// ClientAuthType declares the policy the server will follow for
@@ -217,8 +214,6 @@ type ClientSessionState struct {
handshakeHash []byte // Handshake hash for Channel ID purposes.
serverCertificates []*x509.Certificate // Certificate chain presented by the server
extendedMasterSecret bool // Whether an extended master secret was used to generate the session
- sctList []byte
- ocspResponse []byte
}
// ClientSessionCache is a cache of ClientSessionState objects that can be used
@@ -404,10 +399,6 @@ type ProtocolBugs struct {
// ServerKeyExchange message should be invalid.
InvalidSKXSignature bool
- // InvalidCertVerifySignature specifies that the signature in a
- // CertificateVerify message should be invalid.
- InvalidCertVerifySignature bool
-
// InvalidSKXCurve causes the curve ID in the ServerKeyExchange message
// to be wrong.
InvalidSKXCurve bool
@@ -485,10 +476,6 @@ type ProtocolBugs struct {
// TLS_FALLBACK_SCSV in the ClientHello.
SendFallbackSCSV bool
- // SendRenegotiationSCSV causes the client to include the renegotiation
- // SCSV in the ClientHello.
- SendRenegotiationSCSV bool
-
// MaxHandshakeRecordLength, if non-zero, is the maximum size of a
// handshake record. Handshake messages will be split into multiple
// records at the specified size, except that the client_version will
@@ -548,14 +535,11 @@ type ProtocolBugs struct {
// must specify in the server_name extension.
ExpectServerName string
- // SwapNPNAndALPN switches the relative order between NPN and ALPN in
- // both ClientHello and ServerHello.
+ // SwapNPNAndALPN switches the relative order between NPN and
+ // ALPN on the server. This is to test that server preference
+ // of ALPN works regardless of their relative order.
SwapNPNAndALPN bool
- // ALPNProtocol, if not nil, sets the ALPN protocol that a server will
- // return.
- ALPNProtocol *string
-
// AllowSessionVersionMismatch causes the server to resume sessions
// regardless of the version associated with the session.
AllowSessionVersionMismatch bool
@@ -588,15 +572,11 @@ type ProtocolBugs struct {
// didn't support the renegotiation info extension.
NoRenegotiationInfo bool
- // RequireRenegotiationInfo, if true, causes the client to return an
- // error if the server doesn't reply with the renegotiation extension.
- RequireRenegotiationInfo bool
-
- // SequenceNumberMapping, if non-nil, is the mapping function to apply
- // to the sequence number of outgoing packets. For both TLS and DTLS,
- // the two most-significant bytes in the resulting sequence number are
- // ignored so that the DTLS epoch cannot be changed.
- SequenceNumberMapping func(uint64) uint64
+ // SequenceNumberIncrement, if non-zero, causes outgoing sequence
+ // numbers in DTLS to increment by that value rather by 1. This is to
+ // stress the replay bitmap window by simulating extreme packet loss and
+ // retransmit at the record layer.
+ SequenceNumberIncrement uint64
// RSAEphemeralKey, if true, causes the server to send a
// ServerKeyExchange message containing an ephemeral key (as in
@@ -629,6 +609,10 @@ type ProtocolBugs struct {
// across a renego.
RequireSameRenegoClientVersion bool
+ // RequireFastradioPadding, if true, requires that ClientHello messages
+ // be at least 1000 bytes long.
+ RequireFastradioPadding bool
+
// ExpectInitialRecordVersion, if non-zero, is the expected
// version of the records before the version is determined.
ExpectInitialRecordVersion uint16
@@ -642,11 +626,7 @@ type ProtocolBugs struct {
// the server believes it has actually negotiated.
SendCipherSuite uint16
- // AppDataBeforeHandshake, if not nil, causes application data to be
- // sent immediately before the first handshake message.
- AppDataBeforeHandshake []byte
-
- // AppDataAfterChangeCipherSpec, if not nil, causes application data to
+ // AppDataAfterChangeCipherSpec, if not null, causes application data to
// be sent immediately after ChangeCipherSpec.
AppDataAfterChangeCipherSpec []byte
@@ -688,10 +668,17 @@ type ProtocolBugs struct {
// handshake fragments in DTLS to have the wrong message length.
FragmentMessageLengthMismatch bool
- // SplitFragments, if non-zero, causes the handshake fragments in DTLS
- // to be split across two records. The value of |SplitFragments| is the
- // number of bytes in the first fragment.
- SplitFragments int
+ // SplitFragmentHeader, if true, causes the handshake fragments in DTLS
+ // to be split across two records.
+ SplitFragmentHeader bool
+
+ // SplitFragmentBody, if true, causes the handshake bodies in DTLS to be
+ // split across two records.
+ //
+ // TODO(davidben): There's one final split to test: when the header and
+ // body are split across two records. But those are (incorrectly)
+ // accepted right now.
+ SplitFragmentBody bool
// SendEmptyFragments, if true, causes handshakes to include empty
// fragments in DTLS.
@@ -718,6 +705,10 @@ type ProtocolBugs struct {
// preferences to be ignored.
IgnorePeerCurvePreferences bool
+ // SendWarningAlerts, if non-zero, causes every record to be prefaced by
+ // a warning alert.
+ SendWarningAlerts alert
+
// BadFinished, if true, causes the Finished hash to be broken.
BadFinished bool
@@ -736,43 +727,6 @@ type ProtocolBugs struct {
// EnableAllCiphersInDTLS, if true, causes RC4 to be enabled in DTLS.
EnableAllCiphersInDTLS bool
-
- // EmptyCertificateList, if true, causes the server to send an empty
- // certificate list in the Certificate message.
- EmptyCertificateList bool
-
- // ExpectNewTicket, if true, causes the client to abort if it does not
- // receive a new ticket.
- ExpectNewTicket bool
-
- // RequireClientHelloSize, if not zero, is the required length in bytes
- // of the ClientHello /record/. This is checked by the server.
- RequireClientHelloSize int
-
- // CustomExtension, if not empty, contains the contents of an extension
- // that will be added to client/server hellos.
- CustomExtension string
-
- // ExpectedCustomExtension, if not nil, contains the expected contents
- // of a custom extension.
- ExpectedCustomExtension *string
-
- // NoCloseNotify, if true, causes the close_notify alert to be skipped
- // on connection shutdown.
- NoCloseNotify bool
-
- // ExpectCloseNotify, if true, requires a close_notify from the peer on
- // shutdown. Records from the peer received after close_notify is sent
- // are not discard.
- ExpectCloseNotify bool
-
- // SendLargeRecords, if true, allows outgoing records to be sent
- // arbitrarily large.
- SendLargeRecords bool
-
- // NegotiateALPNAndNPN, if true, causes the server to negotiate both
- // ALPN and NPN in the same connetion.
- NegotiateALPNAndNPN bool
}
func (c *Config) serverInit() {
diff --git a/src/ssl/test/runner/conn.go b/src/ssl/test/runner/conn.go
index 39bdfda..adbc1c3 100644
--- a/src/ssl/test/runner/conn.go
+++ b/src/ssl/test/runner/conn.go
@@ -12,7 +12,6 @@ import (
"crypto/ecdsa"
"crypto/subtle"
"crypto/x509"
- "encoding/binary"
"errors"
"fmt"
"io"
@@ -40,7 +39,6 @@ type Conn struct {
extendedMasterSecret bool // whether this session used an extended master secret
cipherSuite *cipherSuite
ocspResponse []byte // stapled OCSP response
- sctList []byte // signed certificate timestamp list
peerCertificates []*x509.Certificate
// verifiedChains contains the certificate chains that we built, as
// opposed to the ones presented by the server.
@@ -50,11 +48,6 @@ type Conn struct {
// firstFinished contains the first Finished hash sent during the
// handshake. This is the "tls-unique" channel binding value.
firstFinished [12]byte
- // clientCertSignatureHash contains the TLS hash id for the hash that
- // was used by the client to sign the handshake with a client
- // certificate. This is only set by a server and is zero if no client
- // certificates were used.
- clientCertSignatureHash uint8
clientRandom, serverRandom [32]byte
masterSecret [48]byte
@@ -94,8 +87,6 @@ func (c *Conn) init() {
c.out.isDTLS = c.isDTLS
c.in.config = c.config
c.out.config = c.config
-
- c.out.updateOutSeq()
}
// Access to net.Conn methods.
@@ -143,7 +134,6 @@ type halfConn struct {
cipher interface{} // cipher algorithm
mac macFunction
seq [8]byte // 64-bit sequence number
- outSeq [8]byte // Mapped sequence number
bfree *block // list of free blocks
nextCipher interface{} // next encryption state
@@ -199,6 +189,10 @@ func (hc *halfConn) incSeq(isOutgoing bool) {
if hc.isDTLS {
// Increment up to the epoch in DTLS.
limit = 2
+
+ if isOutgoing && hc.config.Bugs.SequenceNumberIncrement != 0 {
+ increment = hc.config.Bugs.SequenceNumberIncrement
+ }
}
for i := 7; i >= limit; i-- {
increment += uint64(hc.seq[i])
@@ -212,8 +206,6 @@ func (hc *halfConn) incSeq(isOutgoing bool) {
if increment != 0 {
panic("TLS: sequence number wraparound")
}
-
- hc.updateOutSeq()
}
// incNextSeq increments the starting sequence number for the next epoch.
@@ -249,22 +241,6 @@ func (hc *halfConn) incEpoch() {
hc.seq[i] = 0
}
}
-
- hc.updateOutSeq()
-}
-
-func (hc *halfConn) updateOutSeq() {
- if hc.config.Bugs.SequenceNumberMapping != nil {
- seqU64 := binary.BigEndian.Uint64(hc.seq[:])
- seqU64 = hc.config.Bugs.SequenceNumberMapping(seqU64)
- binary.BigEndian.PutUint64(hc.outSeq[:], seqU64)
-
- // The DTLS epoch cannot be changed.
- copy(hc.outSeq[:2], hc.seq[:2])
- return
- }
-
- copy(hc.outSeq[:], hc.seq[:])
}
func (hc *halfConn) recordHeaderLen() int {
@@ -421,8 +397,6 @@ func (hc *halfConn) decrypt(b *block) (ok bool, prefixLen int, alertValue alert)
//
// However, our behavior matches OpenSSL, so we leak
// only as much as they do.
- case nullCipher:
- break
default:
panic("unknown cipher type")
}
@@ -486,7 +460,7 @@ func (hc *halfConn) encrypt(b *block, explicitIVLen int) (bool, alert) {
// mac
if hc.mac != nil {
- mac := hc.mac.MAC(hc.outDigestBuf, hc.outSeq[0:], b.data[:3], b.data[recordHeaderLen-2:recordHeaderLen], b.data[recordHeaderLen+explicitIVLen:])
+ mac := hc.mac.MAC(hc.outDigestBuf, hc.seq[0:], b.data[:3], b.data[recordHeaderLen-2:recordHeaderLen], b.data[recordHeaderLen+explicitIVLen:])
n := len(b.data)
b.resize(n + len(mac))
@@ -504,7 +478,7 @@ func (hc *halfConn) encrypt(b *block, explicitIVLen int) (bool, alert) {
case *tlsAead:
payloadLen := len(b.data) - recordHeaderLen - explicitIVLen
b.resize(len(b.data) + c.Overhead())
- nonce := hc.outSeq[:]
+ nonce := hc.seq[:]
if c.explicitNonce {
nonce = b.data[recordHeaderLen : recordHeaderLen+explicitIVLen]
}
@@ -512,7 +486,7 @@ func (hc *halfConn) encrypt(b *block, explicitIVLen int) (bool, alert) {
payload = payload[:payloadLen]
var additionalData [13]byte
- copy(additionalData[:], hc.outSeq[:])
+ copy(additionalData[:], hc.seq[:])
copy(additionalData[8:], b.data[:3])
additionalData[11] = byte(payloadLen >> 8)
additionalData[12] = byte(payloadLen)
@@ -528,8 +502,6 @@ func (hc *halfConn) encrypt(b *block, explicitIVLen int) (bool, alert) {
b.resize(recordHeaderLen + explicitIVLen + len(prefix) + len(finalBlock))
c.CryptBlocks(b.data[recordHeaderLen+explicitIVLen:], prefix)
c.CryptBlocks(b.data[recordHeaderLen+explicitIVLen+len(prefix):], finalBlock)
- case nullCipher:
- break
default:
panic("unknown cipher type")
}
@@ -658,10 +630,10 @@ func (c *Conn) doReadRecord(want recordType) (recordType, *block, error) {
if err := b.readFromUntil(c.conn, recordHeaderLen); err != nil {
// RFC suggests that EOF without an alertCloseNotify is
// an error, but popular web sites seem to do this,
- // so we can't make it an error, outside of tests.
- if err == io.EOF && c.config.Bugs.ExpectCloseNotify {
- err = io.ErrUnexpectedEOF
- }
+ // so we can't make it an error.
+ // if err == io.EOF {
+ // err = io.ErrUnexpectedEOF
+ // }
if e, ok := err.(net.Error); !ok || !e.Temporary() {
c.in.setErrorLocked(err)
}
@@ -750,10 +722,6 @@ func (c *Conn) readRecord(want recordType) error {
c.sendAlert(alertInternalError)
return c.in.setErrorLocked(errors.New("tls: application data record requested before handshake complete"))
}
- case recordTypeAlert:
- // Looking for a close_notify. Note: unlike a real
- // implementation, this is not tolerant of additional records.
- // See the documentation for ExpectCloseNotify.
}
Again:
@@ -816,7 +784,7 @@ Again:
// A client might need to process a HelloRequest from
// the server, thus receiving a handshake message when
// application data is expected is ok.
- if !c.isClient || want != recordTypeApplicationData {
+ if !c.isClient {
return c.in.setErrorLocked(c.sendAlert(alertNoRenegotiation))
}
}
@@ -831,8 +799,13 @@ Again:
// sendAlert sends a TLS alert message.
// c.out.Mutex <= L.
-func (c *Conn) sendAlertLocked(level byte, err alert) error {
- c.tmp[0] = level
+func (c *Conn) sendAlertLocked(err alert) error {
+ switch err {
+ case alertNoRenegotiation, alertCloseNotify:
+ c.tmp[0] = alertLevelWarning
+ default:
+ c.tmp[0] = alertLevelError
+ }
c.tmp[1] = byte(err)
if c.config.Bugs.FragmentAlert {
c.writeRecord(recordTypeAlert, c.tmp[0:1])
@@ -840,8 +813,8 @@ func (c *Conn) sendAlertLocked(level byte, err alert) error {
} else {
c.writeRecord(recordTypeAlert, c.tmp[0:2])
}
- // Error alerts are fatal to the connection.
- if level == alertLevelError {
+ // closeNotify is a special case in that it isn't an error:
+ if err != alertCloseNotify {
return c.out.setErrorLocked(&net.OpError{Op: "local error", Err: err})
}
return nil
@@ -850,17 +823,9 @@ func (c *Conn) sendAlertLocked(level byte, err alert) error {
// sendAlert sends a TLS alert message.
// L < c.out.Mutex.
func (c *Conn) sendAlert(err alert) error {
- level := byte(alertLevelError)
- if err == alertNoRenegotiation || err == alertCloseNotify {
- level = alertLevelWarning
- }
- return c.SendAlert(level, err)
-}
-
-func (c *Conn) SendAlert(level byte, err alert) error {
c.out.Lock()
defer c.out.Unlock()
- return c.sendAlertLocked(level, err)
+ return c.sendAlertLocked(err)
}
// writeV2Record writes a record for a V2ClientHello.
@@ -876,6 +841,13 @@ func (c *Conn) writeV2Record(data []byte) (n int, err error) {
// to the connection and updates the record layer state.
// c.out.Mutex <= L.
func (c *Conn) writeRecord(typ recordType, data []byte) (n int, err error) {
+ if typ != recordTypeAlert && c.config.Bugs.SendWarningAlerts != 0 {
+ alert := make([]byte, 2)
+ alert[0] = alertLevelWarning
+ alert[1] = byte(c.config.Bugs.SendWarningAlerts)
+ c.writeRecord(recordTypeAlert, alert)
+ }
+
if c.isDTLS {
return c.dtlsWriteRecord(typ, data)
}
@@ -884,9 +856,9 @@ func (c *Conn) writeRecord(typ recordType, data []byte) (n int, err error) {
b := c.out.newBlock()
first := true
isClientHello := typ == recordTypeHandshake && len(data) > 0 && data[0] == typeClientHello
- for len(data) > 0 || first {
+ for len(data) > 0 {
m := len(data)
- if m > maxPlaintext && !c.config.Bugs.SendLargeRecords {
+ if m > maxPlaintext {
m = maxPlaintext
}
if typ == recordTypeHandshake && c.config.Bugs.MaxHandshakeRecordLength > 0 && m > c.config.Bugs.MaxHandshakeRecordLength {
@@ -1066,9 +1038,6 @@ func (c *Conn) readHandshake() (interface{}, error) {
// sequence number expectations but otherwise ignores them.
func (c *Conn) skipPacket(packet []byte) error {
for len(packet) > 0 {
- if len(packet) < 13 {
- return errors.New("tls: bad packet")
- }
// Dropped packets are completely ignored save to update
// expected sequence numbers for this and the next epoch. (We
// don't assert on the contents of the packets both for
@@ -1088,9 +1057,6 @@ func (c *Conn) skipPacket(packet []byte) error {
}
c.in.incNextSeq()
}
- if len(packet) < 13+int(length) {
- return errors.New("tls: bad packet")
- }
packet = packet[13+length:]
}
return nil
@@ -1147,7 +1113,7 @@ func (c *Conn) Write(b []byte) (int, error) {
}
if c.config.Bugs.SendSpuriousAlert != 0 {
- c.sendAlertLocked(alertLevelError, c.config.Bugs.SendSpuriousAlert)
+ c.sendAlertLocked(c.config.Bugs.SendSpuriousAlert)
}
// SSL 3.0 and TLS 1.0 are susceptible to a chosen-plaintext
@@ -1274,22 +1240,10 @@ func (c *Conn) Close() error {
c.handshakeMutex.Lock()
defer c.handshakeMutex.Unlock()
- if c.handshakeComplete && !c.config.Bugs.NoCloseNotify {
+ if c.handshakeComplete {
alertErr = c.sendAlert(alertCloseNotify)
}
- // Consume a close_notify from the peer if one hasn't been received
- // already. This avoids the peer from failing |SSL_shutdown| due to a
- // write failing.
- if c.handshakeComplete && alertErr == nil && c.config.Bugs.ExpectCloseNotify {
- for c.in.error() == nil {
- c.readRecord(recordTypeAlert)
- }
- if c.in.error() != io.EOF {
- alertErr = c.in.error()
- }
- }
-
if err := c.conn.Close(); err != nil {
return err
}
@@ -1319,9 +1273,6 @@ func (c *Conn) Handshake() error {
})
c.conn.Write([]byte{alertLevelError, byte(alertInternalError)})
}
- if data := c.config.Bugs.AppDataBeforeHandshake; data != nil {
- c.writeRecord(recordTypeApplicationData, data)
- }
if c.isClient {
c.handshakeErr = c.clientHandshake()
} else {
@@ -1353,8 +1304,6 @@ func (c *Conn) ConnectionState() ConnectionState {
state.ChannelID = c.channelID
state.SRTPProtectionProfile = c.srtpProtectionProfile
state.TLSUnique = c.firstFinished[:]
- state.SCTList = c.sctList
- state.ClientCertSignatureHash = c.clientCertSignatureHash
}
return state
diff --git a/src/ssl/test/runner/dtls.go b/src/ssl/test/runner/dtls.go
index 5c59dea..50f7786 100644
--- a/src/ssl/test/runner/dtls.go
+++ b/src/ssl/test/runner/dtls.go
@@ -216,10 +216,13 @@ func (c *Conn) dtlsFlushHandshake() error {
// Pack handshake fragments into records.
var records [][]byte
for _, fragment := range fragments {
- if n := c.config.Bugs.SplitFragments; n > 0 {
- if len(fragment) > n {
- records = append(records, fragment[:n])
- records = append(records, fragment[n:])
+ if c.config.Bugs.SplitFragmentHeader {
+ records = append(records, fragment[:2])
+ records = append(records, fragment[2:])
+ } else if c.config.Bugs.SplitFragmentBody {
+ if len(fragment) > 12 {
+ records = append(records, fragment[:13])
+ records = append(records, fragment[13:])
} else {
records = append(records, fragment)
}
@@ -298,13 +301,13 @@ func (c *Conn) dtlsSealRecord(typ recordType, data []byte) (b *block, err error)
b.data[1] = byte(vers >> 8)
b.data[2] = byte(vers)
// DTLS records include an explicit sequence number.
- copy(b.data[3:11], c.out.outSeq[0:])
+ copy(b.data[3:11], c.out.seq[0:])
b.data[11] = byte(len(data) >> 8)
b.data[12] = byte(len(data))
if explicitIVLen > 0 {
explicitIV := b.data[recordHeaderLen : recordHeaderLen+explicitIVLen]
if explicitIVIsSeq {
- copy(explicitIV, c.out.outSeq[:])
+ copy(explicitIV, c.out.seq[:])
} else {
if _, err = io.ReadFull(c.config.rand(), explicitIV); err != nil {
return
diff --git a/src/ssl/test/runner/handshake_client.go b/src/ssl/test/runner/handshake_client.go
index a3ce686..a950313 100644
--- a/src/ssl/test/runner/handshake_client.go
+++ b/src/ssl/test/runner/handshake_client.go
@@ -45,7 +45,7 @@ func (c *Conn) clientHandshake() error {
nextProtosLength := 0
for _, proto := range c.config.NextProtos {
- if l := len(proto); l > 255 {
+ if l := len(proto); l == 0 || l > 255 {
return errors.New("tls: invalid NextProtos value")
} else {
nextProtosLength += 1 + l
@@ -61,7 +61,6 @@ func (c *Conn) clientHandshake() error {
compressionMethods: []uint8{compressionNone},
random: make([]byte, 32),
ocspStapling: true,
- sctListSupported: true,
serverName: c.config.ServerName,
supportedCurves: c.config.curvePreferences(),
supportedPoints: []uint8{pointFormatUncompressed},
@@ -74,7 +73,6 @@ func (c *Conn) clientHandshake() error {
extendedMasterSecret: c.config.maxVersion() >= VersionTLS10,
srtpProtectionProfiles: c.config.SRTPProtectionProfiles,
srtpMasterKeyIdentifier: c.config.Bugs.SRTPMasterKeyIdentifer,
- customExtension: c.config.Bugs.CustomExtension,
}
if c.config.Bugs.SendClientVersion != 0 {
@@ -125,10 +123,6 @@ NextCipherSuite:
}
}
- if c.config.Bugs.SendRenegotiationSCSV {
- hello.cipherSuites = append(hello.cipherSuites, renegotiationSCSV)
- }
-
if c.config.Bugs.SendFallbackSCSV {
hello.cipherSuites = append(hello.cipherSuites, fallbackSCSV)
}
@@ -278,10 +272,6 @@ NextCipherSuite:
return fmt.Errorf("tls: server selected an unsupported cipher suite")
}
- if c.config.Bugs.RequireRenegotiationInfo && serverHello.secureRenegotiation == nil {
- return errors.New("tls: renegotiation extension missing")
- }
-
if len(c.clientVerify) > 0 && !c.config.Bugs.NoRenegotiationInfo {
var expectedRenegInfo []byte
expectedRenegInfo = append(expectedRenegInfo, c.clientVerify...)
@@ -292,12 +282,6 @@ NextCipherSuite:
}
}
- if expected := c.config.Bugs.ExpectedCustomExtension; expected != nil {
- if serverHello.customExtension != *expected {
- return fmt.Errorf("tls: bad custom extension contents %q", serverHello.customExtension)
- }
- }
-
hs := &clientHandshakeState{
c: c,
serverHello: serverHello,
@@ -372,7 +356,6 @@ NextCipherSuite:
copy(c.clientRandom[:], hs.hello.random)
copy(c.serverRandom[:], hs.serverHello.random)
copy(c.masterSecret[:], hs.masterSecret)
-
return nil
}
@@ -624,9 +607,6 @@ func (hs *clientHandshakeState) doFullHandshake() error {
c.sendAlert(alertInternalError)
return err
}
- if c.config.Bugs.InvalidCertVerifySignature {
- digest[0] ^= 0x80
- }
switch key := c.config.Certificates[0].PrivateKey.(type) {
case *ecdsa.PrivateKey:
@@ -750,28 +730,13 @@ func (hs *clientHandshakeState) processServerHello() (bool, error) {
return false, errors.New("tls: server resumed session on renegotiation")
}
- if hs.serverHello.sctList != nil {
- return false, errors.New("tls: server sent SCT extension on session resumption")
- }
-
- if hs.serverHello.ocspStapling {
- return false, errors.New("tls: server sent OCSP extension on session resumption")
- }
-
// Restore masterSecret and peerCerts from previous state
hs.masterSecret = hs.session.masterSecret
c.peerCertificates = hs.session.serverCertificates
c.extendedMasterSecret = hs.session.extendedMasterSecret
- c.sctList = hs.session.sctList
- c.ocspResponse = hs.session.ocspResponse
hs.finishedHash.discardHandshakeBuffer()
return true, nil
}
-
- if hs.serverHello.sctList != nil {
- c.sctList = hs.serverHello.sctList
- }
-
return false, nil
}
@@ -818,14 +783,9 @@ func (hs *clientHandshakeState) readSessionTicket() error {
masterSecret: hs.masterSecret,
handshakeHash: hs.finishedHash.server.Sum(nil),
serverCertificates: c.peerCertificates,
- sctList: c.sctList,
- ocspResponse: c.ocspResponse,
}
if !hs.serverHello.ticketSupported {
- if c.config.Bugs.ExpectNewTicket {
- return errors.New("tls: expected new ticket")
- }
if hs.session == nil && len(hs.serverHello.sessionId) > 0 {
session.sessionId = hs.serverHello.sessionId
hs.session = session
diff --git a/src/ssl/test/runner/handshake_messages.go b/src/ssl/test/runner/handshake_messages.go
index da85e7a..ce214fd 100644
--- a/src/ssl/test/runner/handshake_messages.go
+++ b/src/ssl/test/runner/handshake_messages.go
@@ -32,7 +32,6 @@ type clientHelloMsg struct {
srtpProtectionProfiles []uint16
srtpMasterKeyIdentifier string
sctListSupported bool
- customExtension string
}
func (m *clientHelloMsg) equal(i interface{}) bool {
@@ -66,8 +65,7 @@ func (m *clientHelloMsg) equal(i interface{}) bool {
m.extendedMasterSecret == m1.extendedMasterSecret &&
eqUint16s(m.srtpProtectionProfiles, m1.srtpProtectionProfiles) &&
m.srtpMasterKeyIdentifier == m1.srtpMasterKeyIdentifier &&
- m.sctListSupported == m1.sctListSupported &&
- m.customExtension == m1.customExtension
+ m.sctListSupported == m1.sctListSupported
}
func (m *clientHelloMsg) marshal() []byte {
@@ -121,7 +119,7 @@ func (m *clientHelloMsg) marshal() []byte {
if len(m.alpnProtocols) > 0 {
extensionsLength += 2
for _, s := range m.alpnProtocols {
- if l := len(s); l > 255 {
+ if l := len(s); l == 0 || l > 255 {
panic("invalid ALPN protocol")
}
extensionsLength++
@@ -140,10 +138,6 @@ func (m *clientHelloMsg) marshal() []byte {
if m.sctListSupported {
numExtensions++
}
- if l := len(m.customExtension); l > 0 {
- extensionsLength += l
- numExtensions++
- }
if numExtensions > 0 {
extensionsLength += 4 * numExtensions
length += 2 + extensionsLength
@@ -382,14 +376,6 @@ func (m *clientHelloMsg) marshal() []byte {
z[1] = byte(extensionSignedCertificateTimestamp & 0xff)
z = z[4:]
}
- if l := len(m.customExtension); l > 0 {
- z[0] = byte(extensionCustom >> 8)
- z[1] = byte(extensionCustom & 0xff)
- z[2] = byte(l >> 8)
- z[3] = byte(l & 0xff)
- copy(z[4:], []byte(m.customExtension))
- z = z[4+l:]
- }
m.raw = x
@@ -457,7 +443,6 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool {
m.signatureAndHashes = nil
m.alpnProtocols = nil
m.extendedMasterSecret = false
- m.customExtension = ""
if len(data) == 0 {
// ClientHello is optionally followed by extension data
@@ -619,8 +604,6 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool {
return false
}
m.sctListSupported = true
- case extensionCustom:
- m.customExtension = string(data[:length])
}
data = data[length:]
}
@@ -642,15 +625,40 @@ type serverHelloMsg struct {
ticketSupported bool
secureRenegotiation []byte
alpnProtocol string
- alpnProtocolEmpty bool
duplicateExtension bool
channelIDRequested bool
extendedMasterSecret bool
srtpProtectionProfile uint16
srtpMasterKeyIdentifier string
sctList []byte
- customExtension string
- npnLast bool
+}
+
+func (m *serverHelloMsg) equal(i interface{}) bool {
+ m1, ok := i.(*serverHelloMsg)
+ if !ok {
+ return false
+ }
+
+ return bytes.Equal(m.raw, m1.raw) &&
+ m.isDTLS == m1.isDTLS &&
+ m.vers == m1.vers &&
+ bytes.Equal(m.random, m1.random) &&
+ bytes.Equal(m.sessionId, m1.sessionId) &&
+ m.cipherSuite == m1.cipherSuite &&
+ m.compressionMethod == m1.compressionMethod &&
+ m.nextProtoNeg == m1.nextProtoNeg &&
+ eqStrings(m.nextProtos, m1.nextProtos) &&
+ m.ocspStapling == m1.ocspStapling &&
+ m.ticketSupported == m1.ticketSupported &&
+ bytes.Equal(m.secureRenegotiation, m1.secureRenegotiation) &&
+ (m.secureRenegotiation == nil) == (m1.secureRenegotiation == nil) &&
+ m.alpnProtocol == m1.alpnProtocol &&
+ m.duplicateExtension == m1.duplicateExtension &&
+ m.channelIDRequested == m1.channelIDRequested &&
+ m.extendedMasterSecret == m1.extendedMasterSecret &&
+ m.srtpProtectionProfile == m1.srtpProtectionProfile &&
+ m.srtpMasterKeyIdentifier == m1.srtpMasterKeyIdentifier &&
+ bytes.Equal(m.sctList, m1.sctList)
}
func (m *serverHelloMsg) marshal() []byte {
@@ -687,7 +695,7 @@ func (m *serverHelloMsg) marshal() []byte {
if m.channelIDRequested {
numExtensions++
}
- if alpnLen := len(m.alpnProtocol); alpnLen > 0 || m.alpnProtocolEmpty {
+ if alpnLen := len(m.alpnProtocol); alpnLen > 0 {
if alpnLen >= 256 {
panic("invalid ALPN protocol")
}
@@ -705,10 +713,6 @@ func (m *serverHelloMsg) marshal() []byte {
extensionsLength += len(m.sctList)
numExtensions++
}
- if l := len(m.customExtension); l > 0 {
- extensionsLength += l
- numExtensions++
- }
if numExtensions > 0 {
extensionsLength += 4 * numExtensions
@@ -743,7 +747,7 @@ func (m *serverHelloMsg) marshal() []byte {
z[1] = 0xff
z = z[4:]
}
- if m.nextProtoNeg && !m.npnLast {
+ if m.nextProtoNeg {
z[0] = byte(extensionNextProtoNeg >> 8)
z[1] = byte(extensionNextProtoNeg & 0xff)
z[2] = byte(nextProtoLen >> 8)
@@ -780,7 +784,7 @@ func (m *serverHelloMsg) marshal() []byte {
copy(z, m.secureRenegotiation)
z = z[len(m.secureRenegotiation):]
}
- if alpnLen := len(m.alpnProtocol); alpnLen > 0 || m.alpnProtocolEmpty {
+ if alpnLen := len(m.alpnProtocol); alpnLen > 0 {
z[0] = byte(extensionALPN >> 8)
z[1] = byte(extensionALPN & 0xff)
l := 2 + 1 + alpnLen
@@ -834,31 +838,6 @@ func (m *serverHelloMsg) marshal() []byte {
copy(z[4:], m.sctList)
z = z[4+l:]
}
- if l := len(m.customExtension); l > 0 {
- z[0] = byte(extensionCustom >> 8)
- z[1] = byte(extensionCustom & 0xff)
- z[2] = byte(l >> 8)
- z[3] = byte(l & 0xff)
- copy(z[4:], []byte(m.customExtension))
- z = z[4+l:]
- }
- if m.nextProtoNeg && m.npnLast {
- z[0] = byte(extensionNextProtoNeg >> 8)
- z[1] = byte(extensionNextProtoNeg & 0xff)
- z[2] = byte(nextProtoLen >> 8)
- z[3] = byte(nextProtoLen)
- z = z[4:]
-
- for _, v := range m.nextProtos {
- l := len(v)
- if l > 255 {
- l = 255
- }
- z[0] = byte(l)
- copy(z[1:], []byte(v[0:l]))
- z = z[1+l:]
- }
- }
m.raw = x
@@ -890,9 +869,7 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool {
m.ocspStapling = false
m.ticketSupported = false
m.alpnProtocol = ""
- m.alpnProtocolEmpty = false
m.extendedMasterSecret = false
- m.customExtension = ""
if len(data) == 0 {
// ServerHello is optionally followed by extension data
@@ -963,7 +940,6 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool {
}
d = d[1:]
m.alpnProtocol = string(d)
- m.alpnProtocolEmpty = len(d) == 0
case extensionChannelID:
if length > 0 {
return false
@@ -989,9 +965,14 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool {
}
m.srtpMasterKeyIdentifier = string(d[1:])
case extensionSignedCertificateTimestamp:
- m.sctList = data[:length]
- case extensionCustom:
- m.customExtension = string(data[:length])
+ if length < 2 {
+ return false
+ }
+ l := int(data[0])<<8 | int(data[1])
+ if l != len(data)-2 {
+ return false
+ }
+ m.sctList = data[2:length]
}
data = data[length:]
}
@@ -1004,6 +985,16 @@ type certificateMsg struct {
certificates [][]byte
}
+func (m *certificateMsg) equal(i interface{}) bool {
+ m1, ok := i.(*certificateMsg)
+ if !ok {
+ return false
+ }
+
+ return bytes.Equal(m.raw, m1.raw) &&
+ eqByteSlices(m.certificates, m1.certificates)
+}
+
func (m *certificateMsg) marshal() (x []byte) {
if m.raw != nil {
return m.raw
@@ -1081,6 +1072,16 @@ type serverKeyExchangeMsg struct {
key []byte
}
+func (m *serverKeyExchangeMsg) equal(i interface{}) bool {
+ m1, ok := i.(*serverKeyExchangeMsg)
+ if !ok {
+ return false
+ }
+
+ return bytes.Equal(m.raw, m1.raw) &&
+ bytes.Equal(m.key, m1.key)
+}
+
func (m *serverKeyExchangeMsg) marshal() []byte {
if m.raw != nil {
return m.raw
@@ -1112,6 +1113,17 @@ type certificateStatusMsg struct {
response []byte
}
+func (m *certificateStatusMsg) equal(i interface{}) bool {
+ m1, ok := i.(*certificateStatusMsg)
+ if !ok {
+ return false
+ }
+
+ return bytes.Equal(m.raw, m1.raw) &&
+ m.statusType == m1.statusType &&
+ bytes.Equal(m.response, m1.response)
+}
+
func (m *certificateStatusMsg) marshal() []byte {
if m.raw != nil {
return m.raw
@@ -1163,6 +1175,11 @@ func (m *certificateStatusMsg) unmarshal(data []byte) bool {
type serverHelloDoneMsg struct{}
+func (m *serverHelloDoneMsg) equal(i interface{}) bool {
+ _, ok := i.(*serverHelloDoneMsg)
+ return ok
+}
+
func (m *serverHelloDoneMsg) marshal() []byte {
x := make([]byte, 4)
x[0] = typeServerHelloDone
@@ -1178,6 +1195,16 @@ type clientKeyExchangeMsg struct {
ciphertext []byte
}
+func (m *clientKeyExchangeMsg) equal(i interface{}) bool {
+ m1, ok := i.(*clientKeyExchangeMsg)
+ if !ok {
+ return false
+ }
+
+ return bytes.Equal(m.raw, m1.raw) &&
+ bytes.Equal(m.ciphertext, m1.ciphertext)
+}
+
func (m *clientKeyExchangeMsg) marshal() []byte {
if m.raw != nil {
return m.raw
@@ -1212,6 +1239,16 @@ type finishedMsg struct {
verifyData []byte
}
+func (m *finishedMsg) equal(i interface{}) bool {
+ m1, ok := i.(*finishedMsg)
+ if !ok {
+ return false
+ }
+
+ return bytes.Equal(m.raw, m1.raw) &&
+ bytes.Equal(m.verifyData, m1.verifyData)
+}
+
func (m *finishedMsg) marshal() (x []byte) {
if m.raw != nil {
return m.raw
@@ -1239,6 +1276,16 @@ type nextProtoMsg struct {
proto string
}
+func (m *nextProtoMsg) equal(i interface{}) bool {
+ m1, ok := i.(*nextProtoMsg)
+ if !ok {
+ return false
+ }
+
+ return bytes.Equal(m.raw, m1.raw) &&
+ m.proto == m1.proto
+}
+
func (m *nextProtoMsg) marshal() []byte {
if m.raw != nil {
return m.raw
@@ -1306,6 +1353,18 @@ type certificateRequestMsg struct {
certificateAuthorities [][]byte
}
+func (m *certificateRequestMsg) equal(i interface{}) bool {
+ m1, ok := i.(*certificateRequestMsg)
+ if !ok {
+ return false
+ }
+
+ return bytes.Equal(m.raw, m1.raw) &&
+ bytes.Equal(m.certificateTypes, m1.certificateTypes) &&
+ eqByteSlices(m.certificateAuthorities, m1.certificateAuthorities) &&
+ eqSignatureAndHashes(m.signatureAndHashes, m1.signatureAndHashes)
+}
+
func (m *certificateRequestMsg) marshal() (x []byte) {
if m.raw != nil {
return m.raw
@@ -1448,6 +1507,19 @@ type certificateVerifyMsg struct {
signature []byte
}
+func (m *certificateVerifyMsg) equal(i interface{}) bool {
+ m1, ok := i.(*certificateVerifyMsg)
+ if !ok {
+ return false
+ }
+
+ return bytes.Equal(m.raw, m1.raw) &&
+ m.hasSignatureAndHash == m1.hasSignatureAndHash &&
+ m.signatureAndHash.hash == m1.signatureAndHash.hash &&
+ m.signatureAndHash.signature == m1.signatureAndHash.signature &&
+ bytes.Equal(m.signature, m1.signature)
+}
+
func (m *certificateVerifyMsg) marshal() (x []byte) {
if m.raw != nil {
return m.raw
@@ -1517,6 +1589,16 @@ type newSessionTicketMsg struct {
ticket []byte
}
+func (m *newSessionTicketMsg) equal(i interface{}) bool {
+ m1, ok := i.(*newSessionTicketMsg)
+ if !ok {
+ return false
+ }
+
+ return bytes.Equal(m.raw, m1.raw) &&
+ bytes.Equal(m.ticket, m1.ticket)
+}
+
func (m *newSessionTicketMsg) marshal() (x []byte) {
if m.raw != nil {
return m.raw
@@ -1569,6 +1651,19 @@ type v2ClientHelloMsg struct {
challenge []byte
}
+func (m *v2ClientHelloMsg) equal(i interface{}) bool {
+ m1, ok := i.(*v2ClientHelloMsg)
+ if !ok {
+ return false
+ }
+
+ return bytes.Equal(m.raw, m1.raw) &&
+ m.vers == m1.vers &&
+ eqUint16s(m.cipherSuites, m1.cipherSuites) &&
+ bytes.Equal(m.sessionId, m1.sessionId) &&
+ bytes.Equal(m.challenge, m1.challenge)
+}
+
func (m *v2ClientHelloMsg) marshal() []byte {
if m.raw != nil {
return m.raw
@@ -1608,6 +1703,17 @@ type helloVerifyRequestMsg struct {
cookie []byte
}
+func (m *helloVerifyRequestMsg) equal(i interface{}) bool {
+ m1, ok := i.(*helloVerifyRequestMsg)
+ if !ok {
+ return false
+ }
+
+ return bytes.Equal(m.raw, m1.raw) &&
+ m.vers == m1.vers &&
+ bytes.Equal(m.cookie, m1.cookie)
+}
+
func (m *helloVerifyRequestMsg) marshal() []byte {
if m.raw != nil {
return m.raw
@@ -1649,6 +1755,16 @@ type encryptedExtensionsMsg struct {
channelID []byte
}
+func (m *encryptedExtensionsMsg) equal(i interface{}) bool {
+ m1, ok := i.(*encryptedExtensionsMsg)
+ if !ok {
+ return false
+ }
+
+ return bytes.Equal(m.raw, m1.raw) &&
+ bytes.Equal(m.channelID, m1.channelID)
+}
+
func (m *encryptedExtensionsMsg) marshal() []byte {
if m.raw != nil {
return m.raw
diff --git a/src/ssl/test/runner/handshake_server.go b/src/ssl/test/runner/handshake_server.go
index 068dff9..85cc0d2 100644
--- a/src/ssl/test/runner/handshake_server.go
+++ b/src/ssl/test/runner/handshake_server.go
@@ -139,8 +139,8 @@ func (hs *serverHandshakeState) readClientHello() (isResume bool, err error) {
c.sendAlert(alertUnexpectedMessage)
return false, unexpectedMessageError(hs.clientHello, msg)
}
- if size := config.Bugs.RequireClientHelloSize; size != 0 && len(hs.clientHello.raw) != size {
- return false, fmt.Errorf("tls: ClientHello record size is %d, but expected %d", len(hs.clientHello.raw), size)
+ if config.Bugs.RequireFastradioPadding && len(hs.clientHello.raw) < 1000 {
+ return false, errors.New("tls: ClientHello record size should be larger than 1000 bytes when padding enabled.")
}
if c.isDTLS && !config.Bugs.SkipHelloVerifyRequest {
@@ -210,11 +210,8 @@ func (hs *serverHandshakeState) readClientHello() (isResume bool, err error) {
}
c.haveVers = true
- hs.hello = &serverHelloMsg{
- isDTLS: c.isDTLS,
- customExtension: config.Bugs.CustomExtension,
- npnLast: config.Bugs.SwapNPNAndALPN,
- }
+ hs.hello = new(serverHelloMsg)
+ hs.hello.isDTLS = c.isDTLS
supportedCurve := false
preferredCurves := config.curvePreferences()
@@ -288,18 +285,12 @@ Curves:
}
if len(hs.clientHello.alpnProtocols) > 0 {
- if proto := c.config.Bugs.ALPNProtocol; proto != nil {
- hs.hello.alpnProtocol = *proto
- hs.hello.alpnProtocolEmpty = len(*proto) == 0
- c.clientProtocol = *proto
- c.usedALPN = true
- } else if selectedProto, fallback := mutualProtocol(hs.clientHello.alpnProtocols, c.config.NextProtos); !fallback {
+ if selectedProto, fallback := mutualProtocol(hs.clientHello.alpnProtocols, c.config.NextProtos); !fallback {
hs.hello.alpnProtocol = selectedProto
c.clientProtocol = selectedProto
c.usedALPN = true
}
- }
- if len(hs.clientHello.alpnProtocols) == 0 || c.config.Bugs.NegotiateALPNAndNPN {
+ } else {
// Although sending an empty NPN extension is reasonable, Firefox has
// had a bug around this. Best to send nothing at all if
// config.NextProtos is empty. See
@@ -344,12 +335,6 @@ Curves:
hs.hello.srtpProtectionProfile = c.config.Bugs.SendSRTPProtectionProfile
}
- if expected := c.config.Bugs.ExpectedCustomExtension; expected != nil {
- if hs.clientHello.customExtension != *expected {
- return false, fmt.Errorf("tls: bad custom extension contents %q", hs.clientHello.customExtension)
- }
- }
-
_, hs.ecdsaOk = hs.cert.PrivateKey.(*ecdsa.PrivateKey)
// For test purposes, check that the peer never offers a session when
@@ -531,9 +516,7 @@ func (hs *serverHandshakeState) doFullHandshake() error {
if !isPSK {
certMsg := new(certificateMsg)
- if !config.Bugs.EmptyCertificateList {
- certMsg.certificates = hs.cert.Certificate
- }
+ certMsg.certificates = hs.cert.Certificate
if !config.Bugs.UnauthenticatedECDH {
certMsgBytes := certMsg.marshal()
if config.Bugs.WrongCertificateMessageType {
@@ -685,7 +668,6 @@ func (hs *serverHandshakeState) doFullHandshake() error {
if !isSupportedSignatureAndHash(signatureAndHash, config.signatureAndHashesForServer()) {
return errors.New("tls: unsupported hash function for client certificate")
}
- c.clientCertSignatureHash = signatureAndHash.hash
} else {
// Before TLS 1.2 the signature algorithm was implicit
// from the key type, and only one hash per signature
diff --git a/src/ssl/test/runner/runner.go b/src/ssl/test/runner/runner.go
index 269a955..94c1d32 100644
--- a/src/ssl/test/runner/runner.go
+++ b/src/ssl/test/runner/runner.go
@@ -32,10 +32,6 @@ var (
mallocTestDebug = flag.Bool("malloc-test-debug", false, "If true, ask bssl_shim to abort rather than fail a malloc. This can be used with a specific value for --malloc-test to identity the malloc failing that is causing problems.")
jsonOutput = flag.String("json-output", "", "The file to output JSON results to.")
pipe = flag.Bool("pipe", false, "If true, print status output suitable for piping into another program.")
- testToRun = flag.String("test", "", "The name of a test to run, or empty to run all tests")
- numWorkers = flag.Int("num-workers", runtime.NumCPU(), "The number of workers to run in parallel.")
- shimPath = flag.String("shim-path", "../../../build/ssl/test/bssl_shim", "The location of the shim binary.")
- resourceDir = flag.String("resource-dir", ".", "The directory in which to find certificate and key files.")
)
const (
@@ -58,21 +54,21 @@ var testSCTList = []byte{5, 6, 7, 8}
func initCertificates() {
var err error
- rsaCertificate, err = LoadX509KeyPair(path.Join(*resourceDir, rsaCertificateFile), path.Join(*resourceDir, rsaKeyFile))
+ rsaCertificate, err = LoadX509KeyPair(rsaCertificateFile, rsaKeyFile)
if err != nil {
panic(err)
}
rsaCertificate.OCSPStaple = testOCSPResponse
rsaCertificate.SignedCertificateTimestampList = testSCTList
- ecdsaCertificate, err = LoadX509KeyPair(path.Join(*resourceDir, ecdsaCertificateFile), path.Join(*resourceDir, ecdsaKeyFile))
+ ecdsaCertificate, err = LoadX509KeyPair(ecdsaCertificateFile, ecdsaKeyFile)
if err != nil {
panic(err)
}
ecdsaCertificate.OCSPStaple = testOCSPResponse
ecdsaCertificate.SignedCertificateTimestampList = testSCTList
- channelIDPEMBlock, err := ioutil.ReadFile(path.Join(*resourceDir, channelIDKeyFile))
+ channelIDPEMBlock, err := ioutil.ReadFile(channelIDKeyFile)
if err != nil {
panic(err)
}
@@ -155,21 +151,9 @@ type testCase struct {
// expectedSRTPProtectionProfile is the DTLS-SRTP profile that
// should be negotiated. If zero, none should be negotiated.
expectedSRTPProtectionProfile uint16
- // expectedOCSPResponse, if not nil, is the expected OCSP response to be received.
- expectedOCSPResponse []uint8
- // expectedSCTList, if not nil, is the expected SCT list to be received.
- expectedSCTList []uint8
- // expectedClientCertSignatureHash, if not zero, is the TLS id of the
- // hash function that the client should have used when signing the
- // handshake with a client certificate.
- expectedClientCertSignatureHash uint8
// messageLen is the length, in bytes, of the test message that will be
// sent.
messageLen int
- // messageCount is the number of test messages that will be sent.
- messageCount int
- // digestPrefs is the list of digest preferences from the client.
- digestPrefs string
// certFile is the path to the certificate to use for the server.
certFile string
// keyFile is the path to the private key to use for the server.
@@ -190,19 +174,12 @@ type testCase struct {
// newSessionsOnResume, if true, will cause resumeConfig to
// use a different session resumption context.
newSessionsOnResume bool
- // noSessionCache, if true, will cause the server to run without a
- // session cache.
- noSessionCache bool
// sendPrefix sends a prefix on the socket before actually performing a
// handshake.
sendPrefix string
// shimWritesFirst controls whether the shim sends an initial "hello"
// message before doing a roundtrip with the runner.
shimWritesFirst bool
- // shimShutsDown, if true, runs a test where the shim shuts down the
- // connection immediately after the handshake rather than echoing
- // messages from the runner.
- shimShutsDown bool
// renegotiate indicates the the connection should be renegotiated
// during the exchange.
renegotiate bool
@@ -227,20 +204,941 @@ type testCase struct {
// testTLSUnique, if true, causes the shim to send the tls-unique value
// which will be compared against the expected value.
testTLSUnique bool
- // sendEmptyRecords is the number of consecutive empty records to send
- // before and after the test message.
- sendEmptyRecords int
- // sendWarningAlerts is the number of consecutive warning alerts to send
- // before and after the test message.
- sendWarningAlerts int
- // expectMessageDropped, if true, means the test message is expected to
- // be dropped by the client rather than echoed back.
- expectMessageDropped bool
}
-var testCases []testCase
+var testCases = []testCase{
+ {
+ name: "BadRSASignature",
+ config: Config{
+ CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+ Bugs: ProtocolBugs{
+ InvalidSKXSignature: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":BAD_SIGNATURE:",
+ },
+ {
+ name: "BadECDSASignature",
+ config: Config{
+ CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
+ Bugs: ProtocolBugs{
+ InvalidSKXSignature: true,
+ },
+ Certificates: []Certificate{getECDSACertificate()},
+ },
+ shouldFail: true,
+ expectedError: ":BAD_SIGNATURE:",
+ },
+ {
+ name: "BadECDSACurve",
+ config: Config{
+ CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
+ Bugs: ProtocolBugs{
+ InvalidSKXCurve: true,
+ },
+ Certificates: []Certificate{getECDSACertificate()},
+ },
+ shouldFail: true,
+ expectedError: ":WRONG_CURVE:",
+ },
+ {
+ testType: serverTest,
+ name: "BadRSAVersion",
+ config: Config{
+ CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
+ Bugs: ProtocolBugs{
+ RsaClientKeyExchangeVersion: VersionTLS11,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
+ },
+ {
+ name: "NoFallbackSCSV",
+ config: Config{
+ Bugs: ProtocolBugs{
+ FailIfNotFallbackSCSV: true,
+ },
+ },
+ shouldFail: true,
+ expectedLocalError: "no fallback SCSV found",
+ },
+ {
+ name: "SendFallbackSCSV",
+ config: Config{
+ Bugs: ProtocolBugs{
+ FailIfNotFallbackSCSV: true,
+ },
+ },
+ flags: []string{"-fallback-scsv"},
+ },
+ {
+ name: "ClientCertificateTypes",
+ config: Config{
+ ClientAuth: RequestClientCert,
+ ClientCertificateTypes: []byte{
+ CertTypeDSSSign,
+ CertTypeRSASign,
+ CertTypeECDSASign,
+ },
+ },
+ flags: []string{
+ "-expect-certificate-types",
+ base64.StdEncoding.EncodeToString([]byte{
+ CertTypeDSSSign,
+ CertTypeRSASign,
+ CertTypeECDSASign,
+ }),
+ },
+ },
+ {
+ name: "NoClientCertificate",
+ config: Config{
+ ClientAuth: RequireAnyClientCert,
+ },
+ shouldFail: true,
+ expectedLocalError: "client didn't provide a certificate",
+ },
+ {
+ name: "UnauthenticatedECDH",
+ config: Config{
+ CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+ Bugs: ProtocolBugs{
+ UnauthenticatedECDH: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":UNEXPECTED_MESSAGE:",
+ },
+ {
+ name: "SkipCertificateStatus",
+ config: Config{
+ CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+ Bugs: ProtocolBugs{
+ SkipCertificateStatus: true,
+ },
+ },
+ flags: []string{
+ "-enable-ocsp-stapling",
+ },
+ },
+ {
+ name: "SkipServerKeyExchange",
+ config: Config{
+ CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+ Bugs: ProtocolBugs{
+ SkipServerKeyExchange: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":UNEXPECTED_MESSAGE:",
+ },
+ {
+ name: "SkipChangeCipherSpec-Client",
+ config: Config{
+ Bugs: ProtocolBugs{
+ SkipChangeCipherSpec: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
+ },
+ {
+ testType: serverTest,
+ name: "SkipChangeCipherSpec-Server",
+ config: Config{
+ Bugs: ProtocolBugs{
+ SkipChangeCipherSpec: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
+ },
+ {
+ testType: serverTest,
+ name: "SkipChangeCipherSpec-Server-NPN",
+ config: Config{
+ NextProtos: []string{"bar"},
+ Bugs: ProtocolBugs{
+ SkipChangeCipherSpec: true,
+ },
+ },
+ flags: []string{
+ "-advertise-npn", "\x03foo\x03bar\x03baz",
+ },
+ shouldFail: true,
+ expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
+ },
+ {
+ name: "FragmentAcrossChangeCipherSpec-Client",
+ config: Config{
+ Bugs: ProtocolBugs{
+ FragmentAcrossChangeCipherSpec: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
+ },
+ {
+ testType: serverTest,
+ name: "FragmentAcrossChangeCipherSpec-Server",
+ config: Config{
+ Bugs: ProtocolBugs{
+ FragmentAcrossChangeCipherSpec: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
+ },
+ {
+ testType: serverTest,
+ name: "FragmentAcrossChangeCipherSpec-Server-NPN",
+ config: Config{
+ NextProtos: []string{"bar"},
+ Bugs: ProtocolBugs{
+ FragmentAcrossChangeCipherSpec: true,
+ },
+ },
+ flags: []string{
+ "-advertise-npn", "\x03foo\x03bar\x03baz",
+ },
+ shouldFail: true,
+ expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
+ },
+ {
+ testType: serverTest,
+ name: "Alert",
+ config: Config{
+ Bugs: ProtocolBugs{
+ SendSpuriousAlert: alertRecordOverflow,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
+ },
+ {
+ protocol: dtls,
+ testType: serverTest,
+ name: "Alert-DTLS",
+ config: Config{
+ Bugs: ProtocolBugs{
+ SendSpuriousAlert: alertRecordOverflow,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
+ },
+ {
+ testType: serverTest,
+ name: "FragmentAlert",
+ config: Config{
+ Bugs: ProtocolBugs{
+ FragmentAlert: true,
+ SendSpuriousAlert: alertRecordOverflow,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":BAD_ALERT:",
+ },
+ {
+ protocol: dtls,
+ testType: serverTest,
+ name: "FragmentAlert-DTLS",
+ config: Config{
+ Bugs: ProtocolBugs{
+ FragmentAlert: true,
+ SendSpuriousAlert: alertRecordOverflow,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":BAD_ALERT:",
+ },
+ {
+ testType: serverTest,
+ name: "EarlyChangeCipherSpec-server-1",
+ config: Config{
+ Bugs: ProtocolBugs{
+ EarlyChangeCipherSpec: 1,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":CCS_RECEIVED_EARLY:",
+ },
+ {
+ testType: serverTest,
+ name: "EarlyChangeCipherSpec-server-2",
+ config: Config{
+ Bugs: ProtocolBugs{
+ EarlyChangeCipherSpec: 2,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":CCS_RECEIVED_EARLY:",
+ },
+ {
+ name: "SkipNewSessionTicket",
+ config: Config{
+ Bugs: ProtocolBugs{
+ SkipNewSessionTicket: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":CCS_RECEIVED_EARLY:",
+ },
+ {
+ testType: serverTest,
+ name: "FallbackSCSV",
+ config: Config{
+ MaxVersion: VersionTLS11,
+ Bugs: ProtocolBugs{
+ SendFallbackSCSV: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":INAPPROPRIATE_FALLBACK:",
+ },
+ {
+ testType: serverTest,
+ name: "FallbackSCSV-VersionMatch",
+ config: Config{
+ Bugs: ProtocolBugs{
+ SendFallbackSCSV: true,
+ },
+ },
+ },
+ {
+ testType: serverTest,
+ name: "FragmentedClientVersion",
+ config: Config{
+ Bugs: ProtocolBugs{
+ MaxHandshakeRecordLength: 1,
+ FragmentClientVersion: true,
+ },
+ },
+ expectedVersion: VersionTLS12,
+ },
+ {
+ testType: serverTest,
+ name: "MinorVersionTolerance",
+ config: Config{
+ Bugs: ProtocolBugs{
+ SendClientVersion: 0x03ff,
+ },
+ },
+ expectedVersion: VersionTLS12,
+ },
+ {
+ testType: serverTest,
+ name: "MajorVersionTolerance",
+ config: Config{
+ Bugs: ProtocolBugs{
+ SendClientVersion: 0x0400,
+ },
+ },
+ expectedVersion: VersionTLS12,
+ },
+ {
+ testType: serverTest,
+ name: "VersionTooLow",
+ config: Config{
+ Bugs: ProtocolBugs{
+ SendClientVersion: 0x0200,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":UNSUPPORTED_PROTOCOL:",
+ },
+ {
+ testType: serverTest,
+ name: "HttpGET",
+ sendPrefix: "GET / HTTP/1.0\n",
+ shouldFail: true,
+ expectedError: ":HTTP_REQUEST:",
+ },
+ {
+ testType: serverTest,
+ name: "HttpPOST",
+ sendPrefix: "POST / HTTP/1.0\n",
+ shouldFail: true,
+ expectedError: ":HTTP_REQUEST:",
+ },
+ {
+ testType: serverTest,
+ name: "HttpHEAD",
+ sendPrefix: "HEAD / HTTP/1.0\n",
+ shouldFail: true,
+ expectedError: ":HTTP_REQUEST:",
+ },
+ {
+ testType: serverTest,
+ name: "HttpPUT",
+ sendPrefix: "PUT / HTTP/1.0\n",
+ shouldFail: true,
+ expectedError: ":HTTP_REQUEST:",
+ },
+ {
+ testType: serverTest,
+ name: "HttpCONNECT",
+ sendPrefix: "CONNECT www.google.com:443 HTTP/1.0\n",
+ shouldFail: true,
+ expectedError: ":HTTPS_PROXY_REQUEST:",
+ },
+ {
+ testType: serverTest,
+ name: "Garbage",
+ sendPrefix: "blah",
+ shouldFail: true,
+ expectedError: ":UNKNOWN_PROTOCOL:",
+ },
+ {
+ name: "SkipCipherVersionCheck",
+ config: Config{
+ CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
+ MaxVersion: VersionTLS11,
+ Bugs: ProtocolBugs{
+ SkipCipherVersionCheck: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":WRONG_CIPHER_RETURNED:",
+ },
+ {
+ name: "RSAEphemeralKey",
+ config: Config{
+ CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
+ Bugs: ProtocolBugs{
+ RSAEphemeralKey: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":UNEXPECTED_MESSAGE:",
+ },
+ {
+ name: "DisableEverything",
+ flags: []string{"-no-tls12", "-no-tls11", "-no-tls1", "-no-ssl3"},
+ shouldFail: true,
+ expectedError: ":WRONG_SSL_VERSION:",
+ },
+ {
+ protocol: dtls,
+ name: "DisableEverything-DTLS",
+ flags: []string{"-no-tls12", "-no-tls1"},
+ shouldFail: true,
+ expectedError: ":WRONG_SSL_VERSION:",
+ },
+ {
+ name: "NoSharedCipher",
+ config: Config{
+ CipherSuites: []uint16{},
+ },
+ shouldFail: true,
+ expectedError: ":HANDSHAKE_FAILURE_ON_CLIENT_HELLO:",
+ },
+ {
+ protocol: dtls,
+ testType: serverTest,
+ name: "MTU",
+ config: Config{
+ Bugs: ProtocolBugs{
+ MaxPacketLength: 256,
+ },
+ },
+ flags: []string{"-mtu", "256"},
+ },
+ {
+ protocol: dtls,
+ testType: serverTest,
+ name: "MTUExceeded",
+ config: Config{
+ Bugs: ProtocolBugs{
+ MaxPacketLength: 255,
+ },
+ },
+ flags: []string{"-mtu", "256"},
+ shouldFail: true,
+ expectedLocalError: "dtls: exceeded maximum packet length",
+ },
+ {
+ name: "CertMismatchRSA",
+ config: Config{
+ CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
+ Certificates: []Certificate{getECDSACertificate()},
+ Bugs: ProtocolBugs{
+ SendCipherSuite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":WRONG_CERTIFICATE_TYPE:",
+ },
+ {
+ name: "CertMismatchECDSA",
+ config: Config{
+ CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+ Certificates: []Certificate{getRSACertificate()},
+ Bugs: ProtocolBugs{
+ SendCipherSuite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":WRONG_CERTIFICATE_TYPE:",
+ },
+ {
+ name: "TLSFatalBadPackets",
+ damageFirstWrite: true,
+ shouldFail: true,
+ expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
+ },
+ {
+ protocol: dtls,
+ name: "DTLSIgnoreBadPackets",
+ damageFirstWrite: true,
+ },
+ {
+ protocol: dtls,
+ name: "DTLSIgnoreBadPackets-Async",
+ damageFirstWrite: true,
+ flags: []string{"-async"},
+ },
+ {
+ name: "AppDataAfterChangeCipherSpec",
+ config: Config{
+ Bugs: ProtocolBugs{
+ AppDataAfterChangeCipherSpec: []byte("TEST MESSAGE"),
+ },
+ },
+ shouldFail: true,
+ expectedError: ":DATA_BETWEEN_CCS_AND_FINISHED:",
+ },
+ {
+ protocol: dtls,
+ name: "AppDataAfterChangeCipherSpec-DTLS",
+ config: Config{
+ Bugs: ProtocolBugs{
+ AppDataAfterChangeCipherSpec: []byte("TEST MESSAGE"),
+ },
+ },
+ // BoringSSL's DTLS implementation will drop the out-of-order
+ // application data.
+ },
+ {
+ name: "AlertAfterChangeCipherSpec",
+ config: Config{
+ Bugs: ProtocolBugs{
+ AlertAfterChangeCipherSpec: alertRecordOverflow,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
+ },
+ {
+ protocol: dtls,
+ name: "AlertAfterChangeCipherSpec-DTLS",
+ config: Config{
+ Bugs: ProtocolBugs{
+ AlertAfterChangeCipherSpec: alertRecordOverflow,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
+ },
+ {
+ protocol: dtls,
+ name: "ReorderHandshakeFragments-Small-DTLS",
+ config: Config{
+ Bugs: ProtocolBugs{
+ ReorderHandshakeFragments: true,
+ // Small enough that every handshake message is
+ // fragmented.
+ MaxHandshakeRecordLength: 2,
+ },
+ },
+ },
+ {
+ protocol: dtls,
+ name: "ReorderHandshakeFragments-Large-DTLS",
+ config: Config{
+ Bugs: ProtocolBugs{
+ ReorderHandshakeFragments: true,
+ // Large enough that no handshake message is
+ // fragmented.
+ MaxHandshakeRecordLength: 2048,
+ },
+ },
+ },
+ {
+ protocol: dtls,
+ name: "MixCompleteMessageWithFragments-DTLS",
+ config: Config{
+ Bugs: ProtocolBugs{
+ ReorderHandshakeFragments: true,
+ MixCompleteMessageWithFragments: true,
+ MaxHandshakeRecordLength: 2,
+ },
+ },
+ },
+ {
+ name: "SendInvalidRecordType",
+ config: Config{
+ Bugs: ProtocolBugs{
+ SendInvalidRecordType: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":UNEXPECTED_RECORD:",
+ },
+ {
+ protocol: dtls,
+ name: "SendInvalidRecordType-DTLS",
+ config: Config{
+ Bugs: ProtocolBugs{
+ SendInvalidRecordType: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":UNEXPECTED_RECORD:",
+ },
+ {
+ name: "FalseStart-SkipServerSecondLeg",
+ config: Config{
+ CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+ NextProtos: []string{"foo"},
+ Bugs: ProtocolBugs{
+ SkipNewSessionTicket: true,
+ SkipChangeCipherSpec: true,
+ SkipFinished: true,
+ ExpectFalseStart: true,
+ },
+ },
+ flags: []string{
+ "-false-start",
+ "-handshake-never-done",
+ "-advertise-alpn", "\x03foo",
+ },
+ shimWritesFirst: true,
+ shouldFail: true,
+ expectedError: ":UNEXPECTED_RECORD:",
+ },
+ {
+ name: "FalseStart-SkipServerSecondLeg-Implicit",
+ config: Config{
+ CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+ NextProtos: []string{"foo"},
+ Bugs: ProtocolBugs{
+ SkipNewSessionTicket: true,
+ SkipChangeCipherSpec: true,
+ SkipFinished: true,
+ },
+ },
+ flags: []string{
+ "-implicit-handshake",
+ "-false-start",
+ "-handshake-never-done",
+ "-advertise-alpn", "\x03foo",
+ },
+ shouldFail: true,
+ expectedError: ":UNEXPECTED_RECORD:",
+ },
+ {
+ testType: serverTest,
+ name: "FailEarlyCallback",
+ flags: []string{"-fail-early-callback"},
+ shouldFail: true,
+ expectedError: ":CONNECTION_REJECTED:",
+ expectedLocalError: "remote error: access denied",
+ },
+ {
+ name: "WrongMessageType",
+ config: Config{
+ Bugs: ProtocolBugs{
+ WrongCertificateMessageType: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":UNEXPECTED_MESSAGE:",
+ expectedLocalError: "remote error: unexpected message",
+ },
+ {
+ protocol: dtls,
+ name: "WrongMessageType-DTLS",
+ config: Config{
+ Bugs: ProtocolBugs{
+ WrongCertificateMessageType: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":UNEXPECTED_MESSAGE:",
+ expectedLocalError: "remote error: unexpected message",
+ },
+ {
+ protocol: dtls,
+ name: "FragmentMessageTypeMismatch-DTLS",
+ config: Config{
+ Bugs: ProtocolBugs{
+ MaxHandshakeRecordLength: 2,
+ FragmentMessageTypeMismatch: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":FRAGMENT_MISMATCH:",
+ },
+ {
+ protocol: dtls,
+ name: "FragmentMessageLengthMismatch-DTLS",
+ config: Config{
+ Bugs: ProtocolBugs{
+ MaxHandshakeRecordLength: 2,
+ FragmentMessageLengthMismatch: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":FRAGMENT_MISMATCH:",
+ },
+ {
+ protocol: dtls,
+ name: "SplitFragmentHeader-DTLS",
+ config: Config{
+ Bugs: ProtocolBugs{
+ SplitFragmentHeader: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":UNEXPECTED_MESSAGE:",
+ },
+ {
+ protocol: dtls,
+ name: "SplitFragmentBody-DTLS",
+ config: Config{
+ Bugs: ProtocolBugs{
+ SplitFragmentBody: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":UNEXPECTED_MESSAGE:",
+ },
+ {
+ protocol: dtls,
+ name: "SendEmptyFragments-DTLS",
+ config: Config{
+ Bugs: ProtocolBugs{
+ SendEmptyFragments: true,
+ },
+ },
+ },
+ {
+ name: "UnsupportedCipherSuite",
+ config: Config{
+ CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
+ Bugs: ProtocolBugs{
+ IgnorePeerCipherPreferences: true,
+ },
+ },
+ flags: []string{"-cipher", "DEFAULT:!RC4"},
+ shouldFail: true,
+ expectedError: ":WRONG_CIPHER_RETURNED:",
+ },
+ {
+ name: "UnsupportedCurve",
+ config: Config{
+ CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+ // BoringSSL implements P-224 but doesn't enable it by
+ // default.
+ CurvePreferences: []CurveID{CurveP224},
+ Bugs: ProtocolBugs{
+ IgnorePeerCurvePreferences: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":WRONG_CURVE:",
+ },
+ {
+ name: "SendWarningAlerts",
+ config: Config{
+ Bugs: ProtocolBugs{
+ SendWarningAlerts: alertAccessDenied,
+ },
+ },
+ },
+ {
+ protocol: dtls,
+ name: "SendWarningAlerts-DTLS",
+ config: Config{
+ Bugs: ProtocolBugs{
+ SendWarningAlerts: alertAccessDenied,
+ },
+ },
+ },
+ {
+ name: "BadFinished",
+ config: Config{
+ Bugs: ProtocolBugs{
+ BadFinished: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":DIGEST_CHECK_FAILED:",
+ },
+ {
+ name: "FalseStart-BadFinished",
+ config: Config{
+ CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+ NextProtos: []string{"foo"},
+ Bugs: ProtocolBugs{
+ BadFinished: true,
+ ExpectFalseStart: true,
+ },
+ },
+ flags: []string{
+ "-false-start",
+ "-handshake-never-done",
+ "-advertise-alpn", "\x03foo",
+ },
+ shimWritesFirst: true,
+ shouldFail: true,
+ expectedError: ":DIGEST_CHECK_FAILED:",
+ },
+ {
+ name: "NoFalseStart-NoALPN",
+ config: Config{
+ CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+ Bugs: ProtocolBugs{
+ ExpectFalseStart: true,
+ AlertBeforeFalseStartTest: alertAccessDenied,
+ },
+ },
+ flags: []string{
+ "-false-start",
+ },
+ shimWritesFirst: true,
+ shouldFail: true,
+ expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
+ expectedLocalError: "tls: peer did not false start: EOF",
+ },
+ {
+ name: "NoFalseStart-NoAEAD",
+ config: Config{
+ CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
+ NextProtos: []string{"foo"},
+ Bugs: ProtocolBugs{
+ ExpectFalseStart: true,
+ AlertBeforeFalseStartTest: alertAccessDenied,
+ },
+ },
+ flags: []string{
+ "-false-start",
+ "-advertise-alpn", "\x03foo",
+ },
+ shimWritesFirst: true,
+ shouldFail: true,
+ expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
+ expectedLocalError: "tls: peer did not false start: EOF",
+ },
+ {
+ name: "NoFalseStart-RSA",
+ config: Config{
+ CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
+ NextProtos: []string{"foo"},
+ Bugs: ProtocolBugs{
+ ExpectFalseStart: true,
+ AlertBeforeFalseStartTest: alertAccessDenied,
+ },
+ },
+ flags: []string{
+ "-false-start",
+ "-advertise-alpn", "\x03foo",
+ },
+ shimWritesFirst: true,
+ shouldFail: true,
+ expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
+ expectedLocalError: "tls: peer did not false start: EOF",
+ },
+ {
+ name: "NoFalseStart-DHE_RSA",
+ config: Config{
+ CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
+ NextProtos: []string{"foo"},
+ Bugs: ProtocolBugs{
+ ExpectFalseStart: true,
+ AlertBeforeFalseStartTest: alertAccessDenied,
+ },
+ },
+ flags: []string{
+ "-false-start",
+ "-advertise-alpn", "\x03foo",
+ },
+ shimWritesFirst: true,
+ shouldFail: true,
+ expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
+ expectedLocalError: "tls: peer did not false start: EOF",
+ },
+ {
+ testType: serverTest,
+ name: "NoSupportedCurves",
+ config: Config{
+ CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+ Bugs: ProtocolBugs{
+ NoSupportedCurves: true,
+ },
+ },
+ },
+ {
+ testType: serverTest,
+ name: "NoCommonCurves",
+ config: Config{
+ CipherSuites: []uint16{
+ TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+ TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
+ },
+ CurvePreferences: []CurveID{CurveP224},
+ },
+ expectedCipher: TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
+ },
+ {
+ protocol: dtls,
+ name: "SendSplitAlert-Sync",
+ config: Config{
+ Bugs: ProtocolBugs{
+ SendSplitAlert: true,
+ },
+ },
+ },
+ {
+ protocol: dtls,
+ name: "SendSplitAlert-Async",
+ config: Config{
+ Bugs: ProtocolBugs{
+ SendSplitAlert: true,
+ },
+ },
+ flags: []string{"-async"},
+ },
+ {
+ protocol: dtls,
+ name: "PackDTLSHandshake",
+ config: Config{
+ Bugs: ProtocolBugs{
+ MaxHandshakeRecordLength: 2,
+ PackHandshakeFragments: 20,
+ PackHandshakeRecords: 200,
+ },
+ },
+ },
+ {
+ testType: serverTest,
+ protocol: dtls,
+ name: "NoRC4-DTLS",
+ config: Config{
+ CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_RC4_128_SHA},
+ Bugs: ProtocolBugs{
+ EnableAllCiphersInDTLS: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":NO_SHARED_CIPHER:",
+ },
+}
-func doExchange(test *testCase, config *Config, conn net.Conn, isResume bool) error {
+func doExchange(test *testCase, config *Config, conn net.Conn, messageLen int, isResume bool) error {
var connDebug *recordingConn
var connDamage *damageAdaptor
if *flagDebug {
@@ -285,7 +1183,6 @@ func doExchange(test *testCase, config *Config, conn net.Conn, isResume bool) er
tlsConn = Client(conn, config)
}
}
- defer tlsConn.Close()
if err := tlsConn.Handshake(); err != nil {
return err
@@ -338,18 +1235,6 @@ func doExchange(test *testCase, config *Config, conn net.Conn, isResume bool) er
return fmt.Errorf("SRTP profile mismatch: got %d, wanted %d", p, test.expectedSRTPProtectionProfile)
}
- if test.expectedOCSPResponse != nil && !bytes.Equal(test.expectedOCSPResponse, tlsConn.OCSPResponse()) {
- return fmt.Errorf("OCSP Response mismatch")
- }
-
- if test.expectedSCTList != nil && !bytes.Equal(test.expectedSCTList, connState.SCTList) {
- return fmt.Errorf("SCT list mismatch")
- }
-
- if expected := test.expectedClientCertSignatureHash; expected != 0 && expected != connState.ClientCertSignatureHash {
- return fmt.Errorf("expected client to sign handshake with hash %d, but got %d", expected, connState.ClientCertSignatureHash)
- }
-
if test.exportKeyingMaterial > 0 {
actual := make([]byte, test.exportKeyingMaterial)
if _, err := io.ReadFull(tlsConn, actual); err != nil {
@@ -386,14 +1271,6 @@ func doExchange(test *testCase, config *Config, conn net.Conn, isResume bool) er
}
}
- for i := 0; i < test.sendEmptyRecords; i++ {
- tlsConn.Write(nil)
- }
-
- for i := 0; i < test.sendWarningAlerts; i++ {
- tlsConn.SendAlert(alertLevelWarning, alertUnexpectedMessage)
- }
-
if test.renegotiate {
if test.renegotiateCiphers != nil {
config.CipherSuites = test.renegotiateCiphers
@@ -411,7 +1288,6 @@ func doExchange(test *testCase, config *Config, conn net.Conn, isResume bool) er
connDamage.setDamage(false)
}
- messageLen := test.messageLen
if messageLen < 0 {
if test.protocol == dtls {
return fmt.Errorf("messageLen < 0 not supported for DTLS tests")
@@ -420,57 +1296,37 @@ func doExchange(test *testCase, config *Config, conn net.Conn, isResume bool) er
_, err := io.Copy(ioutil.Discard, tlsConn)
return err
}
+
if messageLen == 0 {
messageLen = 32
}
-
- messageCount := test.messageCount
- if messageCount == 0 {
- messageCount = 1
+ testMessage := make([]byte, messageLen)
+ for i := range testMessage {
+ testMessage[i] = 0x42
}
+ tlsConn.Write(testMessage)
- for j := 0; j < messageCount; j++ {
- testMessage := make([]byte, messageLen)
- for i := range testMessage {
- testMessage[i] = 0x42 ^ byte(j)
- }
- tlsConn.Write(testMessage)
-
- for i := 0; i < test.sendEmptyRecords; i++ {
- tlsConn.Write(nil)
+ buf := make([]byte, len(testMessage))
+ if test.protocol == dtls {
+ bufTmp := make([]byte, len(buf)+1)
+ n, err := tlsConn.Read(bufTmp)
+ if err != nil {
+ return err
}
-
- for i := 0; i < test.sendWarningAlerts; i++ {
- tlsConn.SendAlert(alertLevelWarning, alertUnexpectedMessage)
+ if n != len(buf) {
+ return fmt.Errorf("bad reply; length mismatch (%d vs %d)", n, len(buf))
}
-
- if test.shimShutsDown || test.expectMessageDropped {
- // The shim will not respond.
- continue
- }
-
- buf := make([]byte, len(testMessage))
- if test.protocol == dtls {
- bufTmp := make([]byte, len(buf)+1)
- n, err := tlsConn.Read(bufTmp)
- if err != nil {
- return err
- }
- if n != len(buf) {
- return fmt.Errorf("bad reply; length mismatch (%d vs %d)", n, len(buf))
- }
- copy(buf, bufTmp)
- } else {
- _, err := io.ReadFull(tlsConn, buf)
- if err != nil {
- return err
- }
+ copy(buf, bufTmp)
+ } else {
+ _, err := io.ReadFull(tlsConn, buf)
+ if err != nil {
+ return err
}
+ }
- for i, v := range buf {
- if v != testMessage[i]^0xff {
- return fmt.Errorf("bad reply contents at byte %d", i)
- }
+ for i, v := range buf {
+ if v != testMessage[i]^0xff {
+ return fmt.Errorf("bad reply contents at byte %d", i)
}
}
@@ -526,7 +1382,7 @@ func acceptOrWait(listener net.Listener, waitChan chan error) (net.Conn, error)
}
}
-func runTest(test *testCase, shimPath string, mallocNumToFail int64) error {
+func runTest(test *testCase, buildDir string, mallocNumToFail int64) error {
if !test.shouldFail && (len(test.expectedError) > 0 || len(test.expectedLocalError) > 0) {
panic("Error expected without shouldFail in " + test.name)
}
@@ -535,10 +1391,6 @@ func runTest(test *testCase, shimPath string, mallocNumToFail int64) error {
panic("expectResumeRejected without resumeSession in " + test.name)
}
- if test.testType != clientTest && test.expectedClientCertSignatureHash != 0 {
- panic("expectedClientCertSignatureHash non-zero with serverTest in " + test.name)
- }
-
listener, err := net.ListenTCP("tcp4", &net.TCPAddr{IP: net.IP{127, 0, 0, 1}})
if err != nil {
panic(err)
@@ -549,30 +1401,26 @@ func runTest(test *testCase, shimPath string, mallocNumToFail int64) error {
}
}()
+ shim_path := path.Join(buildDir, "ssl/test/bssl_shim")
flags := []string{"-port", strconv.Itoa(listener.Addr().(*net.TCPAddr).Port)}
if test.testType == serverTest {
flags = append(flags, "-server")
flags = append(flags, "-key-file")
if test.keyFile == "" {
- flags = append(flags, path.Join(*resourceDir, rsaKeyFile))
+ flags = append(flags, rsaKeyFile)
} else {
- flags = append(flags, path.Join(*resourceDir, test.keyFile))
+ flags = append(flags, test.keyFile)
}
flags = append(flags, "-cert-file")
if test.certFile == "" {
- flags = append(flags, path.Join(*resourceDir, rsaCertificateFile))
+ flags = append(flags, rsaCertificateFile)
} else {
- flags = append(flags, path.Join(*resourceDir, test.certFile))
+ flags = append(flags, test.certFile)
}
}
- if test.digestPrefs != "" {
- flags = append(flags, "-digest-prefs")
- flags = append(flags, test.digestPrefs)
- }
-
if test.protocol == dtls {
flags = append(flags, "-dtls")
}
@@ -585,10 +1433,6 @@ func runTest(test *testCase, shimPath string, mallocNumToFail int64) error {
flags = append(flags, "-shim-writes-first")
}
- if test.shimShutsDown {
- flags = append(flags, "-shim-shuts-down")
- }
-
if test.exportKeyingMaterial > 0 {
flags = append(flags, "-export-keying-material", strconv.Itoa(test.exportKeyingMaterial))
flags = append(flags, "-export-label", test.exportLabel)
@@ -609,11 +1453,11 @@ func runTest(test *testCase, shimPath string, mallocNumToFail int64) error {
var shim *exec.Cmd
if *useValgrind {
- shim = valgrindOf(false, shimPath, flags...)
+ shim = valgrindOf(false, shim_path, flags...)
} else if *useGDB {
- shim = gdbOf(shimPath, flags...)
+ shim = gdbOf(shim_path, flags...)
} else {
- shim = exec.Command(shimPath, flags...)
+ shim = exec.Command(shim_path, flags...)
}
shim.Stdin = os.Stdin
var stdoutBuf, stderrBuf bytes.Buffer
@@ -623,7 +1467,7 @@ func runTest(test *testCase, shimPath string, mallocNumToFail int64) error {
shim.Env = os.Environ()
shim.Env = append(shim.Env, "MALLOC_NUMBER_TO_FAIL="+strconv.FormatInt(mallocNumToFail, 10))
if *mallocTestDebug {
- shim.Env = append(shim.Env, "MALLOC_BREAK_ON_FAIL=1")
+ shim.Env = append(shim.Env, "MALLOC_ABORT_ON_FAIL=1")
}
shim.Env = append(shim.Env, "_MALLOC_CHECK=1")
}
@@ -635,10 +1479,8 @@ func runTest(test *testCase, shimPath string, mallocNumToFail int64) error {
go func() { waitChan <- shim.Wait() }()
config := test.config
- if !test.noSessionCache {
- config.ClientSessionCache = NewLRUClientSessionCache(1)
- config.ServerSessionCache = NewLRUServerSessionCache(1)
- }
+ config.ClientSessionCache = NewLRUClientSessionCache(1)
+ config.ServerSessionCache = NewLRUServerSessionCache(1)
if test.testType == clientTest {
if len(config.Certificates) == 0 {
config.Certificates = []Certificate{getRSACertificate()}
@@ -653,7 +1495,7 @@ func runTest(test *testCase, shimPath string, mallocNumToFail int64) error {
conn, err := acceptOrWait(listener, waitChan)
if err == nil {
- err = doExchange(test, &config, conn, false /* not a resumption */)
+ err = doExchange(test, &config, conn, test.messageLen, false /* not a resumption */)
conn.Close()
}
@@ -667,12 +1509,7 @@ func runTest(test *testCase, shimPath string, mallocNumToFail int64) error {
if len(resumeConfig.Certificates) == 0 {
resumeConfig.Certificates = []Certificate{getRSACertificate()}
}
- if test.newSessionsOnResume {
- if !test.noSessionCache {
- resumeConfig.ClientSessionCache = NewLRUClientSessionCache(1)
- resumeConfig.ServerSessionCache = NewLRUServerSessionCache(1)
- }
- } else {
+ if !test.newSessionsOnResume {
resumeConfig.SessionTicketKey = config.SessionTicketKey
resumeConfig.ClientSessionCache = config.ClientSessionCache
resumeConfig.ServerSessionCache = config.ServerSessionCache
@@ -683,7 +1520,7 @@ func runTest(test *testCase, shimPath string, mallocNumToFail int64) error {
var connResume net.Conn
connResume, err = acceptOrWait(listener, waitChan)
if err == nil {
- err = doExchange(test, &resumeConfig, connResume, true /* resumption */)
+ err = doExchange(test, &resumeConfig, connResume, test.messageLen, true /* resumption */)
connResume.Close()
}
}
@@ -769,6 +1606,7 @@ var testCipherSuites = []struct {
{"DHE-RSA-AES256-GCM", TLS_DHE_RSA_WITH_AES_256_GCM_SHA384},
{"DHE-RSA-AES256-SHA", TLS_DHE_RSA_WITH_AES_256_CBC_SHA},
{"DHE-RSA-AES256-SHA256", TLS_DHE_RSA_WITH_AES_256_CBC_SHA256},
+ {"DHE-RSA-CHACHA20-POLY1305", TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
{"ECDHE-ECDSA-AES128-GCM", TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
{"ECDHE-ECDSA-AES128-SHA", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA},
{"ECDHE-ECDSA-AES128-SHA256", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256},
@@ -792,7 +1630,6 @@ var testCipherSuites = []struct {
{"PSK-RC4-SHA", TLS_PSK_WITH_RC4_128_SHA},
{"RC4-MD5", TLS_RSA_WITH_RC4_128_MD5},
{"RC4-SHA", TLS_RSA_WITH_RC4_128_SHA},
- {"NULL-SHA", TLS_RSA_WITH_NULL_SHA},
}
func hasComponent(suiteName, component string) bool {
@@ -807,7 +1644,7 @@ func isTLS12Only(suiteName string) bool {
}
func isDTLSCipher(suiteName string) bool {
- return !hasComponent(suiteName, "RC4") && !hasComponent(suiteName, "NULL")
+ return !hasComponent(suiteName, "RC4")
}
func bigFromHex(hex string) *big.Int {
@@ -818,1152 +1655,6 @@ func bigFromHex(hex string) *big.Int {
return ret
}
-func addBasicTests() {
- basicTests := []testCase{
- {
- name: "BadRSASignature",
- config: Config{
- CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
- Bugs: ProtocolBugs{
- InvalidSKXSignature: true,
- },
- },
- shouldFail: true,
- expectedError: ":BAD_SIGNATURE:",
- },
- {
- name: "BadECDSASignature",
- config: Config{
- CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
- Bugs: ProtocolBugs{
- InvalidSKXSignature: true,
- },
- Certificates: []Certificate{getECDSACertificate()},
- },
- shouldFail: true,
- expectedError: ":BAD_SIGNATURE:",
- },
- {
- testType: serverTest,
- name: "BadRSASignature-ClientAuth",
- config: Config{
- Bugs: ProtocolBugs{
- InvalidCertVerifySignature: true,
- },
- Certificates: []Certificate{getRSACertificate()},
- },
- shouldFail: true,
- expectedError: ":BAD_SIGNATURE:",
- flags: []string{"-require-any-client-certificate"},
- },
- {
- testType: serverTest,
- name: "BadECDSASignature-ClientAuth",
- config: Config{
- Bugs: ProtocolBugs{
- InvalidCertVerifySignature: true,
- },
- Certificates: []Certificate{getECDSACertificate()},
- },
- shouldFail: true,
- expectedError: ":BAD_SIGNATURE:",
- flags: []string{"-require-any-client-certificate"},
- },
- {
- name: "BadECDSACurve",
- config: Config{
- CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
- Bugs: ProtocolBugs{
- InvalidSKXCurve: true,
- },
- Certificates: []Certificate{getECDSACertificate()},
- },
- shouldFail: true,
- expectedError: ":WRONG_CURVE:",
- },
- {
- testType: serverTest,
- name: "BadRSAVersion",
- config: Config{
- CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
- Bugs: ProtocolBugs{
- RsaClientKeyExchangeVersion: VersionTLS11,
- },
- },
- shouldFail: true,
- expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
- },
- {
- name: "NoFallbackSCSV",
- config: Config{
- Bugs: ProtocolBugs{
- FailIfNotFallbackSCSV: true,
- },
- },
- shouldFail: true,
- expectedLocalError: "no fallback SCSV found",
- },
- {
- name: "SendFallbackSCSV",
- config: Config{
- Bugs: ProtocolBugs{
- FailIfNotFallbackSCSV: true,
- },
- },
- flags: []string{"-fallback-scsv"},
- },
- {
- name: "ClientCertificateTypes",
- config: Config{
- ClientAuth: RequestClientCert,
- ClientCertificateTypes: []byte{
- CertTypeDSSSign,
- CertTypeRSASign,
- CertTypeECDSASign,
- },
- },
- flags: []string{
- "-expect-certificate-types",
- base64.StdEncoding.EncodeToString([]byte{
- CertTypeDSSSign,
- CertTypeRSASign,
- CertTypeECDSASign,
- }),
- },
- },
- {
- name: "NoClientCertificate",
- config: Config{
- ClientAuth: RequireAnyClientCert,
- },
- shouldFail: true,
- expectedLocalError: "client didn't provide a certificate",
- },
- {
- name: "UnauthenticatedECDH",
- config: Config{
- CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
- Bugs: ProtocolBugs{
- UnauthenticatedECDH: true,
- },
- },
- shouldFail: true,
- expectedError: ":UNEXPECTED_MESSAGE:",
- },
- {
- name: "SkipCertificateStatus",
- config: Config{
- CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
- Bugs: ProtocolBugs{
- SkipCertificateStatus: true,
- },
- },
- flags: []string{
- "-enable-ocsp-stapling",
- },
- },
- {
- name: "SkipServerKeyExchange",
- config: Config{
- CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
- Bugs: ProtocolBugs{
- SkipServerKeyExchange: true,
- },
- },
- shouldFail: true,
- expectedError: ":UNEXPECTED_MESSAGE:",
- },
- {
- name: "SkipChangeCipherSpec-Client",
- config: Config{
- Bugs: ProtocolBugs{
- SkipChangeCipherSpec: true,
- },
- },
- shouldFail: true,
- expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
- },
- {
- testType: serverTest,
- name: "SkipChangeCipherSpec-Server",
- config: Config{
- Bugs: ProtocolBugs{
- SkipChangeCipherSpec: true,
- },
- },
- shouldFail: true,
- expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
- },
- {
- testType: serverTest,
- name: "SkipChangeCipherSpec-Server-NPN",
- config: Config{
- NextProtos: []string{"bar"},
- Bugs: ProtocolBugs{
- SkipChangeCipherSpec: true,
- },
- },
- flags: []string{
- "-advertise-npn", "\x03foo\x03bar\x03baz",
- },
- shouldFail: true,
- expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
- },
- {
- name: "FragmentAcrossChangeCipherSpec-Client",
- config: Config{
- Bugs: ProtocolBugs{
- FragmentAcrossChangeCipherSpec: true,
- },
- },
- shouldFail: true,
- expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
- },
- {
- testType: serverTest,
- name: "FragmentAcrossChangeCipherSpec-Server",
- config: Config{
- Bugs: ProtocolBugs{
- FragmentAcrossChangeCipherSpec: true,
- },
- },
- shouldFail: true,
- expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
- },
- {
- testType: serverTest,
- name: "FragmentAcrossChangeCipherSpec-Server-NPN",
- config: Config{
- NextProtos: []string{"bar"},
- Bugs: ProtocolBugs{
- FragmentAcrossChangeCipherSpec: true,
- },
- },
- flags: []string{
- "-advertise-npn", "\x03foo\x03bar\x03baz",
- },
- shouldFail: true,
- expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
- },
- {
- testType: serverTest,
- name: "Alert",
- config: Config{
- Bugs: ProtocolBugs{
- SendSpuriousAlert: alertRecordOverflow,
- },
- },
- shouldFail: true,
- expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
- },
- {
- protocol: dtls,
- testType: serverTest,
- name: "Alert-DTLS",
- config: Config{
- Bugs: ProtocolBugs{
- SendSpuriousAlert: alertRecordOverflow,
- },
- },
- shouldFail: true,
- expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
- },
- {
- testType: serverTest,
- name: "FragmentAlert",
- config: Config{
- Bugs: ProtocolBugs{
- FragmentAlert: true,
- SendSpuriousAlert: alertRecordOverflow,
- },
- },
- shouldFail: true,
- expectedError: ":BAD_ALERT:",
- },
- {
- protocol: dtls,
- testType: serverTest,
- name: "FragmentAlert-DTLS",
- config: Config{
- Bugs: ProtocolBugs{
- FragmentAlert: true,
- SendSpuriousAlert: alertRecordOverflow,
- },
- },
- shouldFail: true,
- expectedError: ":BAD_ALERT:",
- },
- {
- testType: serverTest,
- name: "EarlyChangeCipherSpec-server-1",
- config: Config{
- Bugs: ProtocolBugs{
- EarlyChangeCipherSpec: 1,
- },
- },
- shouldFail: true,
- expectedError: ":CCS_RECEIVED_EARLY:",
- },
- {
- testType: serverTest,
- name: "EarlyChangeCipherSpec-server-2",
- config: Config{
- Bugs: ProtocolBugs{
- EarlyChangeCipherSpec: 2,
- },
- },
- shouldFail: true,
- expectedError: ":CCS_RECEIVED_EARLY:",
- },
- {
- name: "SkipNewSessionTicket",
- config: Config{
- Bugs: ProtocolBugs{
- SkipNewSessionTicket: true,
- },
- },
- shouldFail: true,
- expectedError: ":CCS_RECEIVED_EARLY:",
- },
- {
- testType: serverTest,
- name: "FallbackSCSV",
- config: Config{
- MaxVersion: VersionTLS11,
- Bugs: ProtocolBugs{
- SendFallbackSCSV: true,
- },
- },
- shouldFail: true,
- expectedError: ":INAPPROPRIATE_FALLBACK:",
- },
- {
- testType: serverTest,
- name: "FallbackSCSV-VersionMatch",
- config: Config{
- Bugs: ProtocolBugs{
- SendFallbackSCSV: true,
- },
- },
- },
- {
- testType: serverTest,
- name: "FragmentedClientVersion",
- config: Config{
- Bugs: ProtocolBugs{
- MaxHandshakeRecordLength: 1,
- FragmentClientVersion: true,
- },
- },
- expectedVersion: VersionTLS12,
- },
- {
- testType: serverTest,
- name: "MinorVersionTolerance",
- config: Config{
- Bugs: ProtocolBugs{
- SendClientVersion: 0x03ff,
- },
- },
- expectedVersion: VersionTLS12,
- },
- {
- testType: serverTest,
- name: "MajorVersionTolerance",
- config: Config{
- Bugs: ProtocolBugs{
- SendClientVersion: 0x0400,
- },
- },
- expectedVersion: VersionTLS12,
- },
- {
- testType: serverTest,
- name: "VersionTooLow",
- config: Config{
- Bugs: ProtocolBugs{
- SendClientVersion: 0x0200,
- },
- },
- shouldFail: true,
- expectedError: ":UNSUPPORTED_PROTOCOL:",
- },
- {
- testType: serverTest,
- name: "HttpGET",
- sendPrefix: "GET / HTTP/1.0\n",
- shouldFail: true,
- expectedError: ":HTTP_REQUEST:",
- },
- {
- testType: serverTest,
- name: "HttpPOST",
- sendPrefix: "POST / HTTP/1.0\n",
- shouldFail: true,
- expectedError: ":HTTP_REQUEST:",
- },
- {
- testType: serverTest,
- name: "HttpHEAD",
- sendPrefix: "HEAD / HTTP/1.0\n",
- shouldFail: true,
- expectedError: ":HTTP_REQUEST:",
- },
- {
- testType: serverTest,
- name: "HttpPUT",
- sendPrefix: "PUT / HTTP/1.0\n",
- shouldFail: true,
- expectedError: ":HTTP_REQUEST:",
- },
- {
- testType: serverTest,
- name: "HttpCONNECT",
- sendPrefix: "CONNECT www.google.com:443 HTTP/1.0\n",
- shouldFail: true,
- expectedError: ":HTTPS_PROXY_REQUEST:",
- },
- {
- testType: serverTest,
- name: "Garbage",
- sendPrefix: "blah",
- shouldFail: true,
- expectedError: ":WRONG_VERSION_NUMBER:",
- },
- {
- name: "SkipCipherVersionCheck",
- config: Config{
- CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
- MaxVersion: VersionTLS11,
- Bugs: ProtocolBugs{
- SkipCipherVersionCheck: true,
- },
- },
- shouldFail: true,
- expectedError: ":WRONG_CIPHER_RETURNED:",
- },
- {
- name: "RSAEphemeralKey",
- config: Config{
- CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
- Bugs: ProtocolBugs{
- RSAEphemeralKey: true,
- },
- },
- shouldFail: true,
- expectedError: ":UNEXPECTED_MESSAGE:",
- },
- {
- name: "DisableEverything",
- flags: []string{"-no-tls12", "-no-tls11", "-no-tls1", "-no-ssl3"},
- shouldFail: true,
- expectedError: ":WRONG_SSL_VERSION:",
- },
- {
- protocol: dtls,
- name: "DisableEverything-DTLS",
- flags: []string{"-no-tls12", "-no-tls1"},
- shouldFail: true,
- expectedError: ":WRONG_SSL_VERSION:",
- },
- {
- name: "NoSharedCipher",
- config: Config{
- CipherSuites: []uint16{},
- },
- shouldFail: true,
- expectedError: ":HANDSHAKE_FAILURE_ON_CLIENT_HELLO:",
- },
- {
- protocol: dtls,
- testType: serverTest,
- name: "MTU",
- config: Config{
- Bugs: ProtocolBugs{
- MaxPacketLength: 256,
- },
- },
- flags: []string{"-mtu", "256"},
- },
- {
- protocol: dtls,
- testType: serverTest,
- name: "MTUExceeded",
- config: Config{
- Bugs: ProtocolBugs{
- MaxPacketLength: 255,
- },
- },
- flags: []string{"-mtu", "256"},
- shouldFail: true,
- expectedLocalError: "dtls: exceeded maximum packet length",
- },
- {
- name: "CertMismatchRSA",
- config: Config{
- CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
- Certificates: []Certificate{getECDSACertificate()},
- Bugs: ProtocolBugs{
- SendCipherSuite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
- },
- },
- shouldFail: true,
- expectedError: ":WRONG_CERTIFICATE_TYPE:",
- },
- {
- name: "CertMismatchECDSA",
- config: Config{
- CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
- Certificates: []Certificate{getRSACertificate()},
- Bugs: ProtocolBugs{
- SendCipherSuite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
- },
- },
- shouldFail: true,
- expectedError: ":WRONG_CERTIFICATE_TYPE:",
- },
- {
- name: "EmptyCertificateList",
- config: Config{
- CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
- Bugs: ProtocolBugs{
- EmptyCertificateList: true,
- },
- },
- shouldFail: true,
- expectedError: ":DECODE_ERROR:",
- },
- {
- name: "TLSFatalBadPackets",
- damageFirstWrite: true,
- shouldFail: true,
- expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
- },
- {
- protocol: dtls,
- name: "DTLSIgnoreBadPackets",
- damageFirstWrite: true,
- },
- {
- protocol: dtls,
- name: "DTLSIgnoreBadPackets-Async",
- damageFirstWrite: true,
- flags: []string{"-async"},
- },
- {
- name: "AppDataBeforeHandshake",
- config: Config{
- Bugs: ProtocolBugs{
- AppDataBeforeHandshake: []byte("TEST MESSAGE"),
- },
- },
- shouldFail: true,
- expectedError: ":UNEXPECTED_RECORD:",
- },
- {
- name: "AppDataBeforeHandshake-Empty",
- config: Config{
- Bugs: ProtocolBugs{
- AppDataBeforeHandshake: []byte{},
- },
- },
- shouldFail: true,
- expectedError: ":UNEXPECTED_RECORD:",
- },
- {
- protocol: dtls,
- name: "AppDataBeforeHandshake-DTLS",
- config: Config{
- Bugs: ProtocolBugs{
- AppDataBeforeHandshake: []byte("TEST MESSAGE"),
- },
- },
- shouldFail: true,
- expectedError: ":UNEXPECTED_RECORD:",
- },
- {
- protocol: dtls,
- name: "AppDataBeforeHandshake-DTLS-Empty",
- config: Config{
- Bugs: ProtocolBugs{
- AppDataBeforeHandshake: []byte{},
- },
- },
- shouldFail: true,
- expectedError: ":UNEXPECTED_RECORD:",
- },
- {
- name: "AppDataAfterChangeCipherSpec",
- config: Config{
- Bugs: ProtocolBugs{
- AppDataAfterChangeCipherSpec: []byte("TEST MESSAGE"),
- },
- },
- shouldFail: true,
- expectedError: ":DATA_BETWEEN_CCS_AND_FINISHED:",
- },
- {
- name: "AppDataAfterChangeCipherSpec-Empty",
- config: Config{
- Bugs: ProtocolBugs{
- AppDataAfterChangeCipherSpec: []byte{},
- },
- },
- shouldFail: true,
- expectedError: ":DATA_BETWEEN_CCS_AND_FINISHED:",
- },
- {
- protocol: dtls,
- name: "AppDataAfterChangeCipherSpec-DTLS",
- config: Config{
- Bugs: ProtocolBugs{
- AppDataAfterChangeCipherSpec: []byte("TEST MESSAGE"),
- },
- },
- // BoringSSL's DTLS implementation will drop the out-of-order
- // application data.
- },
- {
- protocol: dtls,
- name: "AppDataAfterChangeCipherSpec-DTLS-Empty",
- config: Config{
- Bugs: ProtocolBugs{
- AppDataAfterChangeCipherSpec: []byte{},
- },
- },
- // BoringSSL's DTLS implementation will drop the out-of-order
- // application data.
- },
- {
- name: "AlertAfterChangeCipherSpec",
- config: Config{
- Bugs: ProtocolBugs{
- AlertAfterChangeCipherSpec: alertRecordOverflow,
- },
- },
- shouldFail: true,
- expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
- },
- {
- protocol: dtls,
- name: "AlertAfterChangeCipherSpec-DTLS",
- config: Config{
- Bugs: ProtocolBugs{
- AlertAfterChangeCipherSpec: alertRecordOverflow,
- },
- },
- shouldFail: true,
- expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
- },
- {
- protocol: dtls,
- name: "ReorderHandshakeFragments-Small-DTLS",
- config: Config{
- Bugs: ProtocolBugs{
- ReorderHandshakeFragments: true,
- // Small enough that every handshake message is
- // fragmented.
- MaxHandshakeRecordLength: 2,
- },
- },
- },
- {
- protocol: dtls,
- name: "ReorderHandshakeFragments-Large-DTLS",
- config: Config{
- Bugs: ProtocolBugs{
- ReorderHandshakeFragments: true,
- // Large enough that no handshake message is
- // fragmented.
- MaxHandshakeRecordLength: 2048,
- },
- },
- },
- {
- protocol: dtls,
- name: "MixCompleteMessageWithFragments-DTLS",
- config: Config{
- Bugs: ProtocolBugs{
- ReorderHandshakeFragments: true,
- MixCompleteMessageWithFragments: true,
- MaxHandshakeRecordLength: 2,
- },
- },
- },
- {
- name: "SendInvalidRecordType",
- config: Config{
- Bugs: ProtocolBugs{
- SendInvalidRecordType: true,
- },
- },
- shouldFail: true,
- expectedError: ":UNEXPECTED_RECORD:",
- },
- {
- protocol: dtls,
- name: "SendInvalidRecordType-DTLS",
- config: Config{
- Bugs: ProtocolBugs{
- SendInvalidRecordType: true,
- },
- },
- shouldFail: true,
- expectedError: ":UNEXPECTED_RECORD:",
- },
- {
- name: "FalseStart-SkipServerSecondLeg",
- config: Config{
- CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
- NextProtos: []string{"foo"},
- Bugs: ProtocolBugs{
- SkipNewSessionTicket: true,
- SkipChangeCipherSpec: true,
- SkipFinished: true,
- ExpectFalseStart: true,
- },
- },
- flags: []string{
- "-false-start",
- "-handshake-never-done",
- "-advertise-alpn", "\x03foo",
- },
- shimWritesFirst: true,
- shouldFail: true,
- expectedError: ":UNEXPECTED_RECORD:",
- },
- {
- name: "FalseStart-SkipServerSecondLeg-Implicit",
- config: Config{
- CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
- NextProtos: []string{"foo"},
- Bugs: ProtocolBugs{
- SkipNewSessionTicket: true,
- SkipChangeCipherSpec: true,
- SkipFinished: true,
- },
- },
- flags: []string{
- "-implicit-handshake",
- "-false-start",
- "-handshake-never-done",
- "-advertise-alpn", "\x03foo",
- },
- shouldFail: true,
- expectedError: ":UNEXPECTED_RECORD:",
- },
- {
- testType: serverTest,
- name: "FailEarlyCallback",
- flags: []string{"-fail-early-callback"},
- shouldFail: true,
- expectedError: ":CONNECTION_REJECTED:",
- expectedLocalError: "remote error: access denied",
- },
- {
- name: "WrongMessageType",
- config: Config{
- Bugs: ProtocolBugs{
- WrongCertificateMessageType: true,
- },
- },
- shouldFail: true,
- expectedError: ":UNEXPECTED_MESSAGE:",
- expectedLocalError: "remote error: unexpected message",
- },
- {
- protocol: dtls,
- name: "WrongMessageType-DTLS",
- config: Config{
- Bugs: ProtocolBugs{
- WrongCertificateMessageType: true,
- },
- },
- shouldFail: true,
- expectedError: ":UNEXPECTED_MESSAGE:",
- expectedLocalError: "remote error: unexpected message",
- },
- {
- protocol: dtls,
- name: "FragmentMessageTypeMismatch-DTLS",
- config: Config{
- Bugs: ProtocolBugs{
- MaxHandshakeRecordLength: 2,
- FragmentMessageTypeMismatch: true,
- },
- },
- shouldFail: true,
- expectedError: ":FRAGMENT_MISMATCH:",
- },
- {
- protocol: dtls,
- name: "FragmentMessageLengthMismatch-DTLS",
- config: Config{
- Bugs: ProtocolBugs{
- MaxHandshakeRecordLength: 2,
- FragmentMessageLengthMismatch: true,
- },
- },
- shouldFail: true,
- expectedError: ":FRAGMENT_MISMATCH:",
- },
- {
- protocol: dtls,
- name: "SplitFragments-Header-DTLS",
- config: Config{
- Bugs: ProtocolBugs{
- SplitFragments: 2,
- },
- },
- shouldFail: true,
- expectedError: ":UNEXPECTED_MESSAGE:",
- },
- {
- protocol: dtls,
- name: "SplitFragments-Boundary-DTLS",
- config: Config{
- Bugs: ProtocolBugs{
- SplitFragments: dtlsRecordHeaderLen,
- },
- },
- shouldFail: true,
- expectedError: ":EXCESSIVE_MESSAGE_SIZE:",
- },
- {
- protocol: dtls,
- name: "SplitFragments-Body-DTLS",
- config: Config{
- Bugs: ProtocolBugs{
- SplitFragments: dtlsRecordHeaderLen + 1,
- },
- },
- shouldFail: true,
- expectedError: ":EXCESSIVE_MESSAGE_SIZE:",
- },
- {
- protocol: dtls,
- name: "SendEmptyFragments-DTLS",
- config: Config{
- Bugs: ProtocolBugs{
- SendEmptyFragments: true,
- },
- },
- },
- {
- name: "UnsupportedCipherSuite",
- config: Config{
- CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
- Bugs: ProtocolBugs{
- IgnorePeerCipherPreferences: true,
- },
- },
- flags: []string{"-cipher", "DEFAULT:!RC4"},
- shouldFail: true,
- expectedError: ":WRONG_CIPHER_RETURNED:",
- },
- {
- name: "UnsupportedCurve",
- config: Config{
- CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
- // BoringSSL implements P-224 but doesn't enable it by
- // default.
- CurvePreferences: []CurveID{CurveP224},
- Bugs: ProtocolBugs{
- IgnorePeerCurvePreferences: true,
- },
- },
- shouldFail: true,
- expectedError: ":WRONG_CURVE:",
- },
- {
- name: "BadFinished",
- config: Config{
- Bugs: ProtocolBugs{
- BadFinished: true,
- },
- },
- shouldFail: true,
- expectedError: ":DIGEST_CHECK_FAILED:",
- },
- {
- name: "FalseStart-BadFinished",
- config: Config{
- CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
- NextProtos: []string{"foo"},
- Bugs: ProtocolBugs{
- BadFinished: true,
- ExpectFalseStart: true,
- },
- },
- flags: []string{
- "-false-start",
- "-handshake-never-done",
- "-advertise-alpn", "\x03foo",
- },
- shimWritesFirst: true,
- shouldFail: true,
- expectedError: ":DIGEST_CHECK_FAILED:",
- },
- {
- name: "NoFalseStart-NoALPN",
- config: Config{
- CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
- Bugs: ProtocolBugs{
- ExpectFalseStart: true,
- AlertBeforeFalseStartTest: alertAccessDenied,
- },
- },
- flags: []string{
- "-false-start",
- },
- shimWritesFirst: true,
- shouldFail: true,
- expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
- expectedLocalError: "tls: peer did not false start: EOF",
- },
- {
- name: "NoFalseStart-NoAEAD",
- config: Config{
- CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
- NextProtos: []string{"foo"},
- Bugs: ProtocolBugs{
- ExpectFalseStart: true,
- AlertBeforeFalseStartTest: alertAccessDenied,
- },
- },
- flags: []string{
- "-false-start",
- "-advertise-alpn", "\x03foo",
- },
- shimWritesFirst: true,
- shouldFail: true,
- expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
- expectedLocalError: "tls: peer did not false start: EOF",
- },
- {
- name: "NoFalseStart-RSA",
- config: Config{
- CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
- NextProtos: []string{"foo"},
- Bugs: ProtocolBugs{
- ExpectFalseStart: true,
- AlertBeforeFalseStartTest: alertAccessDenied,
- },
- },
- flags: []string{
- "-false-start",
- "-advertise-alpn", "\x03foo",
- },
- shimWritesFirst: true,
- shouldFail: true,
- expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
- expectedLocalError: "tls: peer did not false start: EOF",
- },
- {
- name: "NoFalseStart-DHE_RSA",
- config: Config{
- CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
- NextProtos: []string{"foo"},
- Bugs: ProtocolBugs{
- ExpectFalseStart: true,
- AlertBeforeFalseStartTest: alertAccessDenied,
- },
- },
- flags: []string{
- "-false-start",
- "-advertise-alpn", "\x03foo",
- },
- shimWritesFirst: true,
- shouldFail: true,
- expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
- expectedLocalError: "tls: peer did not false start: EOF",
- },
- {
- testType: serverTest,
- name: "NoSupportedCurves",
- config: Config{
- CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
- Bugs: ProtocolBugs{
- NoSupportedCurves: true,
- },
- },
- },
- {
- testType: serverTest,
- name: "NoCommonCurves",
- config: Config{
- CipherSuites: []uint16{
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
- TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
- },
- CurvePreferences: []CurveID{CurveP224},
- },
- expectedCipher: TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
- },
- {
- protocol: dtls,
- name: "SendSplitAlert-Sync",
- config: Config{
- Bugs: ProtocolBugs{
- SendSplitAlert: true,
- },
- },
- },
- {
- protocol: dtls,
- name: "SendSplitAlert-Async",
- config: Config{
- Bugs: ProtocolBugs{
- SendSplitAlert: true,
- },
- },
- flags: []string{"-async"},
- },
- {
- protocol: dtls,
- name: "PackDTLSHandshake",
- config: Config{
- Bugs: ProtocolBugs{
- MaxHandshakeRecordLength: 2,
- PackHandshakeFragments: 20,
- PackHandshakeRecords: 200,
- },
- },
- },
- {
- testType: serverTest,
- protocol: dtls,
- name: "NoRC4-DTLS",
- config: Config{
- CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_RC4_128_SHA},
- Bugs: ProtocolBugs{
- EnableAllCiphersInDTLS: true,
- },
- },
- shouldFail: true,
- expectedError: ":NO_SHARED_CIPHER:",
- },
- {
- name: "SendEmptyRecords-Pass",
- sendEmptyRecords: 32,
- },
- {
- name: "SendEmptyRecords",
- sendEmptyRecords: 33,
- shouldFail: true,
- expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:",
- },
- {
- name: "SendEmptyRecords-Async",
- sendEmptyRecords: 33,
- flags: []string{"-async"},
- shouldFail: true,
- expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:",
- },
- {
- name: "SendWarningAlerts-Pass",
- sendWarningAlerts: 4,
- },
- {
- protocol: dtls,
- name: "SendWarningAlerts-DTLS-Pass",
- sendWarningAlerts: 4,
- },
- {
- name: "SendWarningAlerts",
- sendWarningAlerts: 5,
- shouldFail: true,
- expectedError: ":TOO_MANY_WARNING_ALERTS:",
- },
- {
- name: "SendWarningAlerts-Async",
- sendWarningAlerts: 5,
- flags: []string{"-async"},
- shouldFail: true,
- expectedError: ":TOO_MANY_WARNING_ALERTS:",
- },
- {
- name: "EmptySessionID",
- config: Config{
- SessionTicketsDisabled: true,
- },
- noSessionCache: true,
- flags: []string{"-expect-no-session"},
- },
- {
- name: "Unclean-Shutdown",
- config: Config{
- Bugs: ProtocolBugs{
- NoCloseNotify: true,
- ExpectCloseNotify: true,
- },
- },
- shimShutsDown: true,
- flags: []string{"-check-close-notify"},
- shouldFail: true,
- expectedError: "Unexpected SSL_shutdown result: -1 != 1",
- },
- {
- name: "Unclean-Shutdown-Ignored",
- config: Config{
- Bugs: ProtocolBugs{
- NoCloseNotify: true,
- },
- },
- shimShutsDown: true,
- },
- {
- name: "LargePlaintext",
- config: Config{
- Bugs: ProtocolBugs{
- SendLargeRecords: true,
- },
- },
- messageLen: maxPlaintext + 1,
- shouldFail: true,
- expectedError: ":DATA_LENGTH_TOO_LONG:",
- },
- {
- protocol: dtls,
- name: "LargePlaintext-DTLS",
- config: Config{
- Bugs: ProtocolBugs{
- SendLargeRecords: true,
- },
- },
- messageLen: maxPlaintext + 1,
- shouldFail: true,
- expectedError: ":DATA_LENGTH_TOO_LONG:",
- },
- {
- name: "LargeCiphertext",
- config: Config{
- Bugs: ProtocolBugs{
- SendLargeRecords: true,
- },
- },
- messageLen: maxPlaintext * 2,
- shouldFail: true,
- expectedError: ":ENCRYPTED_LENGTH_TOO_LONG:",
- },
- {
- protocol: dtls,
- name: "LargeCiphertext-DTLS",
- config: Config{
- Bugs: ProtocolBugs{
- SendLargeRecords: true,
- },
- },
- messageLen: maxPlaintext * 2,
- // Unlike the other four cases, DTLS drops records which
- // are invalid before authentication, so the connection
- // does not fail.
- expectMessageDropped: true,
- },
- }
- testCases = append(testCases, basicTests...)
-}
-
func addCipherSuiteTests() {
for _, suite := range testCipherSuites {
const psk = "12345"
@@ -1988,10 +1679,6 @@ func addCipherSuiteTests() {
"-psk", psk,
"-psk-identity", pskIdentity)
}
- if hasComponent(suite.name, "NULL") {
- // NULL ciphers must be explicitly enabled.
- flags = append(flags, "-cipher", "DEFAULT:NULL-SHA")
- }
for _, ver := range tlsVersions {
if ver.version < VersionTLS12 && isTLS12Only(suite.name) {
@@ -2065,47 +1752,6 @@ func addCipherSuiteTests() {
})
}
}
-
- // Ensure both TLS and DTLS accept their maximum record sizes.
- testCases = append(testCases, testCase{
- name: suite.name + "-LargeRecord",
- config: Config{
- CipherSuites: []uint16{suite.id},
- Certificates: []Certificate{cert},
- PreSharedKey: []byte(psk),
- PreSharedKeyIdentity: pskIdentity,
- },
- flags: flags,
- messageLen: maxPlaintext,
- })
- testCases = append(testCases, testCase{
- name: suite.name + "-LargeRecord-Extra",
- config: Config{
- CipherSuites: []uint16{suite.id},
- Certificates: []Certificate{cert},
- PreSharedKey: []byte(psk),
- PreSharedKeyIdentity: pskIdentity,
- Bugs: ProtocolBugs{
- SendLargeRecords: true,
- },
- },
- flags: append(flags, "-microsoft-big-sslv3-buffer"),
- messageLen: maxPlaintext + 16384,
- })
- if isDTLSCipher(suite.name) {
- testCases = append(testCases, testCase{
- protocol: dtls,
- name: suite.name + "-LargeRecord-DTLS",
- config: Config{
- CipherSuites: []uint16{suite.id},
- Certificates: []Certificate{cert},
- PreSharedKey: []byte(psk),
- PreSharedKeyIdentity: pskIdentity,
- },
- flags: flags,
- messageLen: maxPlaintext,
- })
- }
}
testCases = append(testCases, testCase{
@@ -2122,94 +1768,6 @@ func addCipherSuiteTests() {
shouldFail: true,
expectedError: "BAD_DH_P_LENGTH",
})
-
- // versionSpecificCiphersTest specifies a test for the TLS 1.0 and TLS
- // 1.1 specific cipher suite settings. A server is setup with the given
- // cipher lists and then a connection is made for each member of
- // expectations. The cipher suite that the server selects must match
- // the specified one.
- var versionSpecificCiphersTest = []struct {
- ciphersDefault, ciphersTLS10, ciphersTLS11 string
- // expectations is a map from TLS version to cipher suite id.
- expectations map[uint16]uint16
- }{
- {
- // Test that the null case (where no version-specific ciphers are set)
- // works as expected.
- "RC4-SHA:AES128-SHA", // default ciphers
- "", // no ciphers specifically for TLS ≥ 1.0
- "", // no ciphers specifically for TLS ≥ 1.1
- map[uint16]uint16{
- VersionSSL30: TLS_RSA_WITH_RC4_128_SHA,
- VersionTLS10: TLS_RSA_WITH_RC4_128_SHA,
- VersionTLS11: TLS_RSA_WITH_RC4_128_SHA,
- VersionTLS12: TLS_RSA_WITH_RC4_128_SHA,
- },
- },
- {
- // With ciphers_tls10 set, TLS 1.0, 1.1 and 1.2 should get a different
- // cipher.
- "RC4-SHA:AES128-SHA", // default
- "AES128-SHA", // these ciphers for TLS ≥ 1.0
- "", // no ciphers specifically for TLS ≥ 1.1
- map[uint16]uint16{
- VersionSSL30: TLS_RSA_WITH_RC4_128_SHA,
- VersionTLS10: TLS_RSA_WITH_AES_128_CBC_SHA,
- VersionTLS11: TLS_RSA_WITH_AES_128_CBC_SHA,
- VersionTLS12: TLS_RSA_WITH_AES_128_CBC_SHA,
- },
- },
- {
- // With ciphers_tls11 set, TLS 1.1 and 1.2 should get a different
- // cipher.
- "RC4-SHA:AES128-SHA", // default
- "", // no ciphers specifically for TLS ≥ 1.0
- "AES128-SHA", // these ciphers for TLS ≥ 1.1
- map[uint16]uint16{
- VersionSSL30: TLS_RSA_WITH_RC4_128_SHA,
- VersionTLS10: TLS_RSA_WITH_RC4_128_SHA,
- VersionTLS11: TLS_RSA_WITH_AES_128_CBC_SHA,
- VersionTLS12: TLS_RSA_WITH_AES_128_CBC_SHA,
- },
- },
- {
- // With both ciphers_tls10 and ciphers_tls11 set, ciphers_tls11 should
- // mask ciphers_tls10 for TLS 1.1 and 1.2.
- "RC4-SHA:AES128-SHA", // default
- "AES128-SHA", // these ciphers for TLS ≥ 1.0
- "AES256-SHA", // these ciphers for TLS ≥ 1.1
- map[uint16]uint16{
- VersionSSL30: TLS_RSA_WITH_RC4_128_SHA,
- VersionTLS10: TLS_RSA_WITH_AES_128_CBC_SHA,
- VersionTLS11: TLS_RSA_WITH_AES_256_CBC_SHA,
- VersionTLS12: TLS_RSA_WITH_AES_256_CBC_SHA,
- },
- },
- }
-
- for i, test := range versionSpecificCiphersTest {
- for version, expectedCipherSuite := range test.expectations {
- flags := []string{"-cipher", test.ciphersDefault}
- if len(test.ciphersTLS10) > 0 {
- flags = append(flags, "-cipher-tls10", test.ciphersTLS10)
- }
- if len(test.ciphersTLS11) > 0 {
- flags = append(flags, "-cipher-tls11", test.ciphersTLS11)
- }
-
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: fmt.Sprintf("VersionSpecificCiphersTest-%d-%x", i, version),
- config: Config{
- MaxVersion: version,
- MinVersion: version,
- CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA},
- },
- flags: flags,
- expectedCipher: expectedCipherSuite,
- })
- }
- }
}
func addBadECDSASignatureTests() {
@@ -2279,8 +1837,7 @@ func addCBCSplittingTests() {
MinVersion: VersionTLS10,
CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
},
- messageLen: -1, // read until EOF
- resumeSession: true,
+ messageLen: -1, // read until EOF
flags: []string{
"-async",
"-write-different-record-sizes",
@@ -2325,8 +1882,8 @@ func addClientAuthTests() {
ClientCAs: certPool,
},
flags: []string{
- "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
- "-key-file", path.Join(*resourceDir, rsaKeyFile),
+ "-cert-file", rsaCertificateFile,
+ "-key-file", rsaKeyFile,
},
})
testCases = append(testCases, testCase{
@@ -2360,8 +1917,8 @@ func addClientAuthTests() {
ClientCAs: certPool,
},
flags: []string{
- "-cert-file", path.Join(*resourceDir, ecdsaCertificateFile),
- "-key-file", path.Join(*resourceDir, ecdsaKeyFile),
+ "-cert-file", ecdsaCertificateFile,
+ "-key-file", ecdsaKeyFile,
},
})
}
@@ -2518,7 +2075,6 @@ func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol)
RenewTicketOnResume: true,
},
},
- flags: []string{"-expect-ticket-renewal"},
resumeSession: true,
})
tests = append(tests, testCase{
@@ -2567,42 +2123,10 @@ func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol)
ClientAuth: RequireAnyClientCert,
},
flags: []string{
- "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
- "-key-file", path.Join(*resourceDir, rsaKeyFile),
+ "-cert-file", rsaCertificateFile,
+ "-key-file", rsaKeyFile,
},
})
- if async {
- tests = append(tests, testCase{
- testType: clientTest,
- name: "ClientAuth-Client-AsyncKey",
- config: Config{
- ClientAuth: RequireAnyClientCert,
- },
- flags: []string{
- "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
- "-key-file", path.Join(*resourceDir, rsaKeyFile),
- "-use-async-private-key",
- },
- })
- tests = append(tests, testCase{
- testType: serverTest,
- name: "Basic-Server-RSAAsyncKey",
- flags: []string{
- "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
- "-key-file", path.Join(*resourceDir, rsaKeyFile),
- "-use-async-private-key",
- },
- })
- tests = append(tests, testCase{
- testType: serverTest,
- name: "Basic-Server-ECDSAAsyncKey",
- flags: []string{
- "-cert-file", path.Join(*resourceDir, ecdsaCertificateFile),
- "-key-file", path.Join(*resourceDir, ecdsaKeyFile),
- "-use-async-private-key",
- },
- })
- }
tests = append(tests, testCase{
testType: serverTest,
name: "ClientAuth-Server",
@@ -2647,57 +2171,6 @@ func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol)
flags: []string{"-psk", "secret"},
})
- tests = append(tests, testCase{
- testType: clientTest,
- name: "OCSPStapling-Client",
- flags: []string{
- "-enable-ocsp-stapling",
- "-expect-ocsp-response",
- base64.StdEncoding.EncodeToString(testOCSPResponse),
- "-verify-peer",
- },
- resumeSession: true,
- })
-
- tests = append(tests, testCase{
- testType: serverTest,
- name: "OCSPStapling-Server",
- expectedOCSPResponse: testOCSPResponse,
- flags: []string{
- "-ocsp-response",
- base64.StdEncoding.EncodeToString(testOCSPResponse),
- },
- resumeSession: true,
- })
-
- tests = append(tests, testCase{
- testType: clientTest,
- name: "CertificateVerificationSucceed",
- flags: []string{
- "-verify-peer",
- },
- })
-
- tests = append(tests, testCase{
- testType: clientTest,
- name: "CertificateVerificationFail",
- flags: []string{
- "-verify-fail",
- "-verify-peer",
- },
- shouldFail: true,
- expectedError: ":CERTIFICATE_VERIFY_FAILED:",
- })
-
- tests = append(tests, testCase{
- testType: clientTest,
- name: "CertificateVerificationSoftFail",
- flags: []string{
- "-verify-fail",
- "-expect-verify-result",
- },
- })
-
if protocol == tls {
tests = append(tests, testCase{
name: "Renegotiate-Client",
@@ -2819,7 +2292,7 @@ func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol)
config: Config{
RequestChannelID: true,
},
- flags: []string{"-send-channel-id", path.Join(*resourceDir, channelIDKeyFile)},
+ flags: []string{"-send-channel-id", channelIDKeyFile},
resumeSession: true,
expectChannelID: true,
})
@@ -2838,33 +2311,6 @@ func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol)
resumeSession: true,
expectChannelID: true,
})
-
- // Bidirectional shutdown with the runner initiating.
- tests = append(tests, testCase{
- name: "Shutdown-Runner",
- config: Config{
- Bugs: ProtocolBugs{
- ExpectCloseNotify: true,
- },
- },
- flags: []string{"-check-close-notify"},
- })
-
- // Bidirectional shutdown with the shim initiating. The runner,
- // in the meantime, sends garbage before the close_notify which
- // the shim must ignore.
- tests = append(tests, testCase{
- name: "Shutdown-Shim",
- config: Config{
- Bugs: ProtocolBugs{
- ExpectCloseNotify: true,
- },
- },
- shimShutsDown: true,
- sendEmptyRecords: 1,
- sendWarningAlerts: 1,
- flags: []string{"-check-close-notify"},
- })
} else {
tests = append(tests, testCase{
name: "SkipHelloVerifyRequest",
@@ -3275,70 +2721,6 @@ func addExtensionTests() {
expectedNextProtoType: alpn,
resumeSession: true,
})
- var emptyString string
- testCases = append(testCases, testCase{
- testType: clientTest,
- name: "ALPNClient-EmptyProtocolName",
- config: Config{
- NextProtos: []string{""},
- Bugs: ProtocolBugs{
- // A server returning an empty ALPN protocol
- // should be rejected.
- ALPNProtocol: &emptyString,
- },
- },
- flags: []string{
- "-advertise-alpn", "\x03foo",
- },
- shouldFail: true,
- expectedError: ":PARSE_TLSEXT:",
- })
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "ALPNServer-EmptyProtocolName",
- config: Config{
- // A ClientHello containing an empty ALPN protocol
- // should be rejected.
- NextProtos: []string{"foo", "", "baz"},
- },
- flags: []string{
- "-select-alpn", "foo",
- },
- shouldFail: true,
- expectedError: ":PARSE_TLSEXT:",
- })
- // Test that negotiating both NPN and ALPN is forbidden.
- testCases = append(testCases, testCase{
- name: "NegotiateALPNAndNPN",
- config: Config{
- NextProtos: []string{"foo", "bar", "baz"},
- Bugs: ProtocolBugs{
- NegotiateALPNAndNPN: true,
- },
- },
- flags: []string{
- "-advertise-alpn", "\x03foo",
- "-select-next-proto", "foo",
- },
- shouldFail: true,
- expectedError: ":NEGOTIATED_BOTH_NPN_AND_ALPN:",
- })
- testCases = append(testCases, testCase{
- name: "NegotiateALPNAndNPN-Swapped",
- config: Config{
- NextProtos: []string{"foo", "bar", "baz"},
- Bugs: ProtocolBugs{
- NegotiateALPNAndNPN: true,
- SwapNPNAndALPN: true,
- },
- },
- flags: []string{
- "-advertise-alpn", "\x03foo",
- "-select-next-proto", "foo",
- },
- shouldFail: true,
- expectedError: ":NEGOTIATED_BOTH_NPN_AND_ALPN:",
- })
// Resume with a corrupt ticket.
testCases = append(testCases, testCase{
testType: serverTest,
@@ -3351,24 +2733,6 @@ func addExtensionTests() {
resumeSession: true,
expectResumeRejected: true,
})
- // Test the ticket callback, with and without renewal.
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "TicketCallback",
- resumeSession: true,
- flags: []string{"-use-ticket-callback"},
- })
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "TicketCallback-Renew",
- config: Config{
- Bugs: ProtocolBugs{
- ExpectNewTicket: true,
- },
- },
- flags: []string{"-use-ticket-callback", "-renew-ticket"},
- resumeSession: true,
- })
// Resume with an oversized session id.
testCases = append(testCases, testCase{
testType: serverTest,
@@ -3458,39 +2822,22 @@ func addExtensionTests() {
shouldFail: true,
expectedError: ":BAD_SRTP_PROTECTION_PROFILE_LIST:",
})
- // Test SCT list.
+ // Test OCSP stapling and SCT list.
testCases = append(testCases, testCase{
- name: "SignedCertificateTimestampList-Client",
- testType: clientTest,
+ name: "OCSPStapling",
flags: []string{
- "-enable-signed-cert-timestamps",
- "-expect-signed-cert-timestamps",
- base64.StdEncoding.EncodeToString(testSCTList),
+ "-enable-ocsp-stapling",
+ "-expect-ocsp-response",
+ base64.StdEncoding.EncodeToString(testOCSPResponse),
},
- resumeSession: true,
})
testCases = append(testCases, testCase{
- name: "SignedCertificateTimestampList-Server",
- testType: serverTest,
+ name: "SignedCertificateTimestampList",
flags: []string{
- "-signed-cert-timestamps",
+ "-enable-signed-cert-timestamps",
+ "-expect-signed-cert-timestamps",
base64.StdEncoding.EncodeToString(testSCTList),
},
- expectedSCTList: testSCTList,
- resumeSession: true,
- })
- testCases = append(testCases, testCase{
- testType: clientTest,
- name: "ClientHelloPadding",
- config: Config{
- Bugs: ProtocolBugs{
- RequireClientHelloSize: 512,
- },
- },
- // This hostname just needs to be long enough to push the
- // ClientHello into F5's danger zone between 256 and 511 bytes
- // long.
- flags: []string{"-host-name", "01234567890123456789012345678901234567890123456789012345678901234567890123456789.com"},
})
}
@@ -3609,33 +2956,7 @@ func addRenegotiationTests() {
expectedError: ":NO_RENEGOTIATION:",
expectedLocalError: "remote error: no renegotiation",
})
- // The server shouldn't echo the renegotiation extension unless
- // requested by the client.
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "Renegotiate-Server-NoExt",
- config: Config{
- Bugs: ProtocolBugs{
- NoRenegotiationInfo: true,
- RequireRenegotiationInfo: true,
- },
- },
- shouldFail: true,
- expectedLocalError: "renegotiation extension missing",
- })
- // The renegotiation SCSV should be sufficient for the server to echo
- // the extension.
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "Renegotiate-Server-NoExt-SCSV",
- config: Config{
- Bugs: ProtocolBugs{
- NoRenegotiationInfo: true,
- SendRenegotiationSCSV: true,
- RequireRenegotiationInfo: true,
- },
- },
- })
+ // TODO(agl): test the renegotiation info SCSV.
testCases = append(testCases, testCase{
name: "Renegotiate-Client",
config: Config{
@@ -3668,7 +2989,8 @@ func addRenegotiationTests() {
expectedError: ":RENEGOTIATION_MISMATCH:",
})
testCases = append(testCases, testCase{
- name: "Renegotiate-Client-NoExt",
+ name: "Renegotiate-Client-NoExt",
+ renegotiate: true,
config: Config{
Bugs: ProtocolBugs{
NoRenegotiationInfo: true,
@@ -3721,19 +3043,6 @@ func addRenegotiationTests() {
},
},
})
- testCases = append(testCases, testCase{
- name: "Renegotiate-FalseStart",
- renegotiate: true,
- config: Config{
- CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
- NextProtos: []string{"foo"},
- },
- flags: []string{
- "-false-start",
- "-select-next-proto", "foo",
- },
- shimWritesFirst: true,
- })
}
func addDTLSReplayTests() {
@@ -3741,39 +3050,43 @@ func addDTLSReplayTests() {
testCases = append(testCases, testCase{
protocol: dtls,
name: "DTLS-Replay",
- messageCount: 200,
replayWrites: true,
})
- // Test the incoming sequence number skipping by values larger
+ // Test the outgoing sequence number skipping by values larger
// than the retransmit window.
testCases = append(testCases, testCase{
protocol: dtls,
name: "DTLS-Replay-LargeGaps",
config: Config{
Bugs: ProtocolBugs{
- SequenceNumberMapping: func(in uint64) uint64 {
- return in * 127
- },
+ SequenceNumberIncrement: 127,
},
},
- messageCount: 200,
replayWrites: true,
})
+}
- // Test the incoming sequence number changing non-monotonically.
+func addFastRadioPaddingTests() {
+ testCases = append(testCases, testCase{
+ protocol: tls,
+ name: "FastRadio-Padding",
+ config: Config{
+ Bugs: ProtocolBugs{
+ RequireFastradioPadding: true,
+ },
+ },
+ flags: []string{"-fastradio-padding"},
+ })
testCases = append(testCases, testCase{
protocol: dtls,
- name: "DTLS-Replay-NonMonotonic",
+ name: "FastRadio-Padding-DTLS",
config: Config{
Bugs: ProtocolBugs{
- SequenceNumberMapping: func(in uint64) uint64 {
- return in ^ 31
- },
+ RequireFastradioPadding: true,
},
},
- messageCount: 200,
- replayWrites: true,
+ flags: []string{"-fastradio-padding"},
})
}
@@ -3803,8 +3116,8 @@ func addSigningHashTests() {
},
},
flags: []string{
- "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
- "-key-file", path.Join(*resourceDir, rsaKeyFile),
+ "-cert-file", rsaCertificateFile,
+ "-key-file", rsaKeyFile,
},
})
@@ -3834,8 +3147,8 @@ func addSigningHashTests() {
},
},
flags: []string{
- "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
- "-key-file", path.Join(*resourceDir, rsaKeyFile),
+ "-cert-file", rsaCertificateFile,
+ "-key-file", rsaKeyFile,
},
})
@@ -3865,8 +3178,8 @@ func addSigningHashTests() {
},
},
flags: []string{
- "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
- "-key-file", path.Join(*resourceDir, rsaKeyFile),
+ "-cert-file", rsaCertificateFile,
+ "-key-file", rsaKeyFile,
},
})
@@ -3922,73 +3235,6 @@ func addSigningHashTests() {
shouldFail: true,
expectedError: ":WRONG_SIGNATURE_TYPE:",
})
-
- // Test that the agreed upon digest respects the client preferences and
- // the server digests.
- testCases = append(testCases, testCase{
- name: "Agree-Digest-Fallback",
- config: Config{
- ClientAuth: RequireAnyClientCert,
- SignatureAndHashes: []signatureAndHash{
- {signatureRSA, hashSHA512},
- {signatureRSA, hashSHA1},
- },
- },
- flags: []string{
- "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
- "-key-file", path.Join(*resourceDir, rsaKeyFile),
- },
- digestPrefs: "SHA256",
- expectedClientCertSignatureHash: hashSHA1,
- })
- testCases = append(testCases, testCase{
- name: "Agree-Digest-SHA256",
- config: Config{
- ClientAuth: RequireAnyClientCert,
- SignatureAndHashes: []signatureAndHash{
- {signatureRSA, hashSHA1},
- {signatureRSA, hashSHA256},
- },
- },
- flags: []string{
- "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
- "-key-file", path.Join(*resourceDir, rsaKeyFile),
- },
- digestPrefs: "SHA256,SHA1",
- expectedClientCertSignatureHash: hashSHA256,
- })
- testCases = append(testCases, testCase{
- name: "Agree-Digest-SHA1",
- config: Config{
- ClientAuth: RequireAnyClientCert,
- SignatureAndHashes: []signatureAndHash{
- {signatureRSA, hashSHA1},
- },
- },
- flags: []string{
- "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
- "-key-file", path.Join(*resourceDir, rsaKeyFile),
- },
- digestPrefs: "SHA512,SHA256,SHA1",
- expectedClientCertSignatureHash: hashSHA1,
- })
- testCases = append(testCases, testCase{
- name: "Agree-Digest-Default",
- config: Config{
- ClientAuth: RequireAnyClientCert,
- SignatureAndHashes: []signatureAndHash{
- {signatureRSA, hashSHA256},
- {signatureECDSA, hashSHA256},
- {signatureRSA, hashSHA1},
- {signatureECDSA, hashSHA1},
- },
- },
- flags: []string{
- "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
- "-key-file", path.Join(*resourceDir, rsaKeyFile),
- },
- expectedClientCertSignatureHash: hashSHA256,
- })
}
// timeouts is the retransmit schedule for BoringSSL. It doubles and
@@ -4195,111 +3441,7 @@ func addTLSUniqueTests() {
}
}
-func addCustomExtensionTests() {
- expectedContents := "custom extension"
- emptyString := ""
-
- for _, isClient := range []bool{false, true} {
- suffix := "Server"
- flag := "-enable-server-custom-extension"
- testType := serverTest
- if isClient {
- suffix = "Client"
- flag = "-enable-client-custom-extension"
- testType = clientTest
- }
-
- testCases = append(testCases, testCase{
- testType: testType,
- name: "CustomExtensions-" + suffix,
- config: Config{
- Bugs: ProtocolBugs{
- CustomExtension: expectedContents,
- ExpectedCustomExtension: &expectedContents,
- },
- },
- flags: []string{flag},
- })
-
- // If the parse callback fails, the handshake should also fail.
- testCases = append(testCases, testCase{
- testType: testType,
- name: "CustomExtensions-ParseError-" + suffix,
- config: Config{
- Bugs: ProtocolBugs{
- CustomExtension: expectedContents + "foo",
- ExpectedCustomExtension: &expectedContents,
- },
- },
- flags: []string{flag},
- shouldFail: true,
- expectedError: ":CUSTOM_EXTENSION_ERROR:",
- })
-
- // If the add callback fails, the handshake should also fail.
- testCases = append(testCases, testCase{
- testType: testType,
- name: "CustomExtensions-FailAdd-" + suffix,
- config: Config{
- Bugs: ProtocolBugs{
- CustomExtension: expectedContents,
- ExpectedCustomExtension: &expectedContents,
- },
- },
- flags: []string{flag, "-custom-extension-fail-add"},
- shouldFail: true,
- expectedError: ":CUSTOM_EXTENSION_ERROR:",
- })
-
- // If the add callback returns zero, no extension should be
- // added.
- skipCustomExtension := expectedContents
- if isClient {
- // For the case where the client skips sending the
- // custom extension, the server must not “echo” it.
- skipCustomExtension = ""
- }
- testCases = append(testCases, testCase{
- testType: testType,
- name: "CustomExtensions-Skip-" + suffix,
- config: Config{
- Bugs: ProtocolBugs{
- CustomExtension: skipCustomExtension,
- ExpectedCustomExtension: &emptyString,
- },
- },
- flags: []string{flag, "-custom-extension-skip"},
- })
- }
-
- // The custom extension add callback should not be called if the client
- // doesn't send the extension.
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "CustomExtensions-NotCalled-Server",
- config: Config{
- Bugs: ProtocolBugs{
- ExpectedCustomExtension: &emptyString,
- },
- },
- flags: []string{"-enable-server-custom-extension", "-custom-extension-fail-add"},
- })
-
- // Test an unknown extension from the server.
- testCases = append(testCases, testCase{
- testType: clientTest,
- name: "UnknownExtension-Client",
- config: Config{
- Bugs: ProtocolBugs{
- CustomExtension: expectedContents,
- },
- },
- shouldFail: true,
- expectedError: ":UNEXPECTED_EXTENSION:",
- })
-}
-
-func worker(statusChan chan statusMsg, c chan *testCase, shimPath string, wg *sync.WaitGroup) {
+func worker(statusChan chan statusMsg, c chan *testCase, buildDir string, wg *sync.WaitGroup) {
defer wg.Done()
for test := range c {
@@ -4307,11 +3449,11 @@ func worker(statusChan chan statusMsg, c chan *testCase, shimPath string, wg *sy
if *mallocTest < 0 {
statusChan <- statusMsg{test: test, started: true}
- err = runTest(test, shimPath, -1)
+ err = runTest(test, buildDir, -1)
} else {
for mallocNumToFail := int64(*mallocTest); ; mallocNumToFail++ {
statusChan <- statusMsg{test: test, started: true}
- if err = runTest(test, shimPath, mallocNumToFail); err != errMoreMallocs {
+ if err = runTest(test, buildDir, mallocNumToFail); err != errMoreMallocs {
if err != nil {
fmt.Printf("\n\nmalloc test failed at %d: %s\n", mallocNumToFail, err)
}
@@ -4373,10 +3515,12 @@ func statusPrinter(doneChan chan *testOutput, statusChan chan statusMsg, total i
}
func main() {
+ var flagTest *string = flag.String("test", "", "The name of a test to run, or empty to run all tests")
+ var flagNumWorkers *int = flag.Int("num-workers", runtime.NumCPU(), "The number of workers to run in parallel.")
+ var flagBuildDir *string = flag.String("build-dir", "../../../build", "The build directory to run the shim from.")
+
flag.Parse()
- *resourceDir = path.Clean(*resourceDir)
- addBasicTests()
addCipherSuiteTests()
addBadECDSASignatureTests()
addCBCPaddingTests()
@@ -4392,10 +3536,10 @@ func main() {
addRenegotiationTests()
addDTLSReplayTests()
addSigningHashTests()
+ addFastRadioPaddingTests()
addDTLSRetransmitTests()
addExportKeyingMaterialTests()
addTLSUniqueTests()
- addCustomExtensionTests()
for _, async := range []bool{false, true} {
for _, splitHandshake := range []bool{false, true} {
for _, protocol := range []protocol{tls, dtls} {
@@ -4406,19 +3550,21 @@ func main() {
var wg sync.WaitGroup
- statusChan := make(chan statusMsg, *numWorkers)
- testChan := make(chan *testCase, *numWorkers)
+ numWorkers := *flagNumWorkers
+
+ statusChan := make(chan statusMsg, numWorkers)
+ testChan := make(chan *testCase, numWorkers)
doneChan := make(chan *testOutput)
go statusPrinter(doneChan, statusChan, len(testCases))
- for i := 0; i < *numWorkers; i++ {
+ for i := 0; i < numWorkers; i++ {
wg.Add(1)
- go worker(statusChan, testChan, *shimPath, &wg)
+ go worker(statusChan, testChan, *flagBuildDir, &wg)
}
for i := range testCases {
- if len(*testToRun) == 0 || *testToRun == testCases[i].name {
+ if len(*flagTest) == 0 || *flagTest == testCases[i].name {
testChan <- &testCases[i]
}
}
diff --git a/src/ssl/test/test_config.cc b/src/ssl/test/test_config.cc
index 1c42b2e..363b6f3 100644
--- a/src/ssl/test/test_config.cc
+++ b/src/ssl/test/test_config.cc
@@ -65,9 +65,12 @@ const Flag<bool> kBoolFlags[] = {
{ "-expect-session-miss", &TestConfig::expect_session_miss },
{ "-expect-extended-master-secret",
&TestConfig::expect_extended_master_secret },
+ { "-allow-unsafe-legacy-renegotiation",
+ &TestConfig::allow_unsafe_legacy_renegotiation },
{ "-enable-ocsp-stapling", &TestConfig::enable_ocsp_stapling },
{ "-enable-signed-cert-timestamps",
&TestConfig::enable_signed_cert_timestamps },
+ { "-fastradio-padding", &TestConfig::fastradio_padding },
{ "-implicit-handshake", &TestConfig::implicit_handshake },
{ "-use-early-callback", &TestConfig::use_early_callback },
{ "-fail-early-callback", &TestConfig::fail_early_callback },
@@ -79,27 +82,9 @@ const Flag<bool> kBoolFlags[] = {
{ "-reject-peer-renegotiations", &TestConfig::reject_peer_renegotiations },
{ "-no-legacy-server-connect", &TestConfig::no_legacy_server_connect },
{ "-tls-unique", &TestConfig::tls_unique },
- { "-use-async-private-key", &TestConfig::use_async_private_key },
- { "-expect-ticket-renewal", &TestConfig::expect_ticket_renewal },
- { "-expect-no-session", &TestConfig::expect_no_session },
- { "-use-ticket-callback", &TestConfig::use_ticket_callback },
- { "-renew-ticket", &TestConfig::renew_ticket },
- { "-enable-client-custom-extension",
- &TestConfig::enable_client_custom_extension },
- { "-enable-server-custom-extension",
- &TestConfig::enable_server_custom_extension },
- { "-custom-extension-skip", &TestConfig::custom_extension_skip },
- { "-custom-extension-fail-add", &TestConfig::custom_extension_fail_add },
- { "-check-close-notify", &TestConfig::check_close_notify },
- { "-shim-shuts-down", &TestConfig::shim_shuts_down },
- { "-microsoft-big-sslv3-buffer", &TestConfig::microsoft_big_sslv3_buffer },
- { "-verify-fail", &TestConfig::verify_fail },
- { "-verify-peer", &TestConfig::verify_peer },
- { "-expect-verify-result", &TestConfig::expect_verify_result }
};
const Flag<std::string> kStringFlags[] = {
- { "-digest-prefs", &TestConfig::digest_prefs },
{ "-key-file", &TestConfig::key_file },
{ "-cert-file", &TestConfig::cert_file },
{ "-expect-server-name", &TestConfig::expected_server_name },
@@ -116,8 +101,6 @@ const Flag<std::string> kStringFlags[] = {
{ "-psk-identity", &TestConfig::psk_identity },
{ "-srtp-profiles", &TestConfig::srtp_profiles },
{ "-cipher", &TestConfig::cipher },
- { "-cipher-tls10", &TestConfig::cipher_tls10 },
- { "-cipher-tls11", &TestConfig::cipher_tls11 },
{ "-export-label", &TestConfig::export_label },
{ "-export-context", &TestConfig::export_context },
};
@@ -128,8 +111,6 @@ const Flag<std::string> kBase64Flags[] = {
{ "-expect-ocsp-response", &TestConfig::expected_ocsp_response },
{ "-expect-signed-cert-timestamps",
&TestConfig::expected_signed_cert_timestamps },
- { "-ocsp-response", &TestConfig::ocsp_response },
- { "-signed-cert-timestamps", &TestConfig::signed_cert_timestamps },
};
const Flag<int> kIntFlags[] = {
diff --git a/src/ssl/test/test_config.h b/src/ssl/test/test_config.h
index 9dea8e9..5d753c8 100644
--- a/src/ssl/test/test_config.h
+++ b/src/ssl/test/test_config.h
@@ -24,7 +24,6 @@ struct TestConfig {
bool is_dtls = false;
bool resume = false;
bool fallback_scsv = false;
- std::string digest_prefs;
std::string key_file;
std::string cert_file;
std::string expected_server_name;
@@ -55,11 +54,13 @@ struct TestConfig {
bool expect_extended_master_secret = false;
std::string psk;
std::string psk_identity;
+ bool allow_unsafe_legacy_renegotiation = false;
std::string srtp_profiles;
bool enable_ocsp_stapling = false;
std::string expected_ocsp_response;
bool enable_signed_cert_timestamps = false;
std::string expected_signed_cert_timestamps;
+ bool fastradio_padding = false;
int min_version = 0;
int max_version = 0;
int mtu = 0;
@@ -70,8 +71,6 @@ struct TestConfig {
bool fail_ddos_callback = false;
bool fail_second_ddos_callback = false;
std::string cipher;
- std::string cipher_tls10;
- std::string cipher_tls11;
bool handshake_never_done = false;
int export_keying_material = 0;
std::string export_label;
@@ -80,23 +79,6 @@ struct TestConfig {
bool reject_peer_renegotiations = false;
bool no_legacy_server_connect = false;
bool tls_unique = false;
- bool use_async_private_key = false;
- bool expect_ticket_renewal = false;
- bool expect_no_session = false;
- bool use_ticket_callback = false;
- bool renew_ticket = false;
- bool enable_client_custom_extension = false;
- bool enable_server_custom_extension = false;
- bool custom_extension_skip = false;
- bool custom_extension_fail_add = false;
- std::string ocsp_response;
- bool check_close_notify = false;
- bool shim_shuts_down = false;
- bool microsoft_big_sslv3_buffer = false;
- bool verify_fail = false;
- bool verify_peer = false;
- bool expect_verify_result = false;
- std::string signed_cert_timestamps;
};
bool ParseConfig(int argc, char **argv, TestConfig *out_config);