diff --git a/ssl/test/bssl_shim.cc b/ssl/test/bssl_shim.cc index 89553244..0459afc7 100644 --- a/ssl/test/bssl_shim.cc +++ b/ssl/test/bssl_shim.cc @@ -316,6 +316,9 @@ static int do_exchange(SSL_SESSION **out_session, if (config->cookie_exchange) { SSL_set_options(ssl, SSL_OP_COOKIE_EXCHANGE); } + if (config->tls_d5_bug) { + SSL_set_options(ssl, SSL_OP_TLS_D5_BUG); + } if (!config->expected_channel_id.empty()) { SSL_enable_tls_channel_id(ssl); } diff --git a/ssl/test/runner/common.go b/ssl/test/runner/common.go index 78e484f3..fa0e6d88 100644 --- a/ssl/test/runner/common.go +++ b/ssl/test/runner/common.go @@ -440,6 +440,11 @@ type ProtocolBugs struct { // isn't sent until we receive an application data record // from the peer. ExpectFalseStart bool + + // SSL3RSAKeyExchange causes the client to always send an RSA + // ClientKeyExchange message without the two-byte length + // prefix, as if it were SSL3. + SSL3RSAKeyExchange bool } func (c *Config) serverInit() { diff --git a/ssl/test/runner/key_agreement.go b/ssl/test/runner/key_agreement.go index 2e2eff4a..f8ba1f8b 100644 --- a/ssl/test/runner/key_agreement.go +++ b/ssl/test/runner/key_agreement.go @@ -87,7 +87,7 @@ func (ka rsaKeyAgreement) generateClientKeyExchange(config *Config, clientHello return nil, nil, err } ckx := new(clientKeyExchangeMsg) - if clientHello.vers != VersionSSL30 { + if clientHello.vers != VersionSSL30 && !config.Bugs.SSL3RSAKeyExchange { ckx.ciphertext = make([]byte, len(encrypted)+2) ckx.ciphertext[0] = byte(len(encrypted) >> 8) ckx.ciphertext[1] = byte(len(encrypted)) diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go index 79bf99c8..d238e8ac 100644 --- a/ssl/test/runner/runner.go +++ b/ssl/test/runner/runner.go @@ -1311,6 +1311,40 @@ func addVersionNegotiationTests() { } } +func addD5BugTests() { + testCases = append(testCases, testCase{ + testType: serverTest, + name: "D5Bug-NoQuirk-Reject", + config: Config{ + CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256}, + Bugs: ProtocolBugs{ + SSL3RSAKeyExchange: true, + }, + }, + shouldFail: true, + expectedError: ":TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG:", + }) + testCases = append(testCases, testCase{ + testType: serverTest, + name: "D5Bug-Quirk-Normal", + config: Config{ + CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256}, + }, + flags: []string{"-tls-d5-bug"}, + }) + testCases = append(testCases, testCase{ + testType: serverTest, + name: "D5Bug-Quirk-Bug", + config: Config{ + CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256}, + Bugs: ProtocolBugs{ + SSL3RSAKeyExchange: true, + }, + }, + flags: []string{"-tls-d5-bug"}, + }) +} + func worker(statusChan chan statusMsg, c chan *testCase, buildDir string, wg *sync.WaitGroup) { defer wg.Done() @@ -1363,6 +1397,7 @@ func main() { addCBCSplittingTests() addClientAuthTests() addVersionNegotiationTests() + addD5BugTests() for _, async := range []bool{false, true} { for _, splitHandshake := range []bool{false, true} { for _, protocol := range []protocol{tls, dtls} { diff --git a/ssl/test/test_config.cc b/ssl/test/test_config.cc index 9d1ffc94..41188afa 100644 --- a/ssl/test/test_config.cc +++ b/ssl/test/test_config.cc @@ -54,6 +54,7 @@ const BoolFlag kBoolFlags[] = { { "-no-ssl3", &TestConfig::no_ssl3 }, { "-cookie-exchange", &TestConfig::cookie_exchange }, { "-shim-writes-first", &TestConfig::shim_writes_first }, + { "-tls-d5-bug", &TestConfig::tls_d5_bug }, }; const size_t kNumBoolFlags = sizeof(kBoolFlags) / sizeof(kBoolFlags[0]); @@ -95,7 +96,8 @@ TestConfig::TestConfig() no_tls1(false), no_ssl3(false), cookie_exchange(false), - shim_writes_first(false) { + shim_writes_first(false), + tls_d5_bug(false) { } bool ParseConfig(int argc, char **argv, TestConfig *out_config) { diff --git a/ssl/test/test_config.h b/ssl/test/test_config.h index d79b7f4e..208f19b1 100644 --- a/ssl/test/test_config.h +++ b/ssl/test/test_config.h @@ -46,6 +46,7 @@ struct TestConfig { std::string expected_channel_id; std::string send_channel_id; bool shim_writes_first; + bool tls_d5_bug; }; bool ParseConfig(int argc, char **argv, TestConfig *out_config);