Commit 8ecc3071 authored by davidben's avatar davidben Committed by Commit bot

OpenSSL: Disable ECDSA cipher suites on Windows XP.

This matches the logic in nss_ssl_util.cc.

Note: this CL has a test which only affects Windows XP. We
have no try coverage on XP, so if the XP bots break, please
revert.

BUG=405630

Review URL: https://codereview.chromium.org/495663002

Cr-Commit-Position: refs/heads/master@{#293214}
parent d734d197
...@@ -30,6 +30,10 @@ ...@@ -30,6 +30,10 @@
#include "net/ssl/ssl_connection_status_flags.h" #include "net/ssl/ssl_connection_status_flags.h"
#include "net/ssl/ssl_info.h" #include "net/ssl/ssl_info.h"
#if defined(OS_WIN)
#include "base/win/windows_version.h"
#endif
#if defined(USE_OPENSSL_CERTS) #if defined(USE_OPENSSL_CERTS)
#include "net/ssl/openssl_client_key_store.h" #include "net/ssl/openssl_client_key_store.h"
#else #else
...@@ -786,6 +790,15 @@ int SSLClientSocketOpenSSL::Init() { ...@@ -786,6 +790,15 @@ int SSLClientSocketOpenSSL::Init() {
command.append(name); command.append(name);
} }
} }
// Disable ECDSA cipher suites on platforms that do not support ECDSA
// signed certificates, as servers may use the presence of such
// ciphersuites as a hint to send an ECDSA certificate.
#if defined(OS_WIN)
if (base::win::GetVersion() < base::win::VERSION_VISTA)
command.append(":!ECDSA");
#endif
int rv = SSL_set_cipher_list(ssl_, command.c_str()); int rv = SSL_set_cipher_list(ssl_, command.c_str());
// If this fails (rv = 0) it means there are no ciphers enabled on this SSL. // If this fails (rv = 0) it means there are no ciphers enabled on this SSL.
// This will almost certainly result in the socket failing to complete the // This will almost certainly result in the socket failing to complete the
......
...@@ -335,6 +335,7 @@ class TestPageHandler(testserver_base.BasePageHandler): ...@@ -335,6 +335,7 @@ class TestPageHandler(testserver_base.BasePageHandler):
self.GetSSLSessionCacheHandler, self.GetSSLSessionCacheHandler,
self.SSLManySmallRecords, self.SSLManySmallRecords,
self.GetChannelID, self.GetChannelID,
self.ClientCipherListHandler,
self.CloseSocketHandler, self.CloseSocketHandler,
self.RangeResetHandler, self.RangeResetHandler,
self.DefaultResponseHandler] self.DefaultResponseHandler]
...@@ -1492,6 +1493,23 @@ class TestPageHandler(testserver_base.BasePageHandler): ...@@ -1492,6 +1493,23 @@ class TestPageHandler(testserver_base.BasePageHandler):
self.wfile.write(hashlib.sha256(channel_id).digest().encode('base64')) self.wfile.write(hashlib.sha256(channel_id).digest().encode('base64'))
return True return True
def ClientCipherListHandler(self):
"""Send a reply containing the cipher suite list that the client
provided. Each cipher suite value is serialized in decimal, followed by a
newline."""
if not self._ShouldHandleRequest('/client-cipher-list'):
return False
self.send_response(200)
self.send_header('Content-Type', 'text/plain')
self.end_headers()
for cipher_suite in self.server.tlsConnection.clientHello.cipher_suites:
self.wfile.write(str(cipher_suite))
self.wfile.write('\n')
return True
def CloseSocketHandler(self): def CloseSocketHandler(self):
"""Closes the socket without sending anything.""" """Closes the socket without sending anything."""
......
...@@ -61,6 +61,7 @@ ...@@ -61,6 +61,7 @@
#include "net/ocsp/nss_ocsp.h" #include "net/ocsp/nss_ocsp.h"
#include "net/proxy/proxy_service.h" #include "net/proxy/proxy_service.h"
#include "net/socket/ssl_client_socket.h" #include "net/socket/ssl_client_socket.h"
#include "net/ssl/ssl_cipher_suite_names.h"
#include "net/ssl/ssl_connection_status_flags.h" #include "net/ssl/ssl_connection_status_flags.h"
#include "net/test/cert_test_util.h" #include "net/test/cert_test_util.h"
#include "net/test/spawned_test_server/spawned_test_server.h" #include "net/test/spawned_test_server/spawned_test_server.h"
...@@ -6931,6 +6932,57 @@ TEST_F(HTTPSRequestTest, SSLSessionCacheShardTest) { ...@@ -6931,6 +6932,57 @@ TEST_F(HTTPSRequestTest, SSLSessionCacheShardTest) {
} }
} }
#if defined(OS_WIN)
namespace {
bool IsECDSACipherSuite(uint16_t cipher_suite) {
const char* key_exchange;
const char* cipher;
const char* mac;
bool is_aead;
SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead, cipher_suite);
return std::string(key_exchange).find("ECDSA") != std::string::npos;
}
} // namespace
// Test that ECDSA is disabled on Windows XP, where ECDSA certificates cannot be
// verified.
TEST_F(HTTPSRequestTest, DisableECDSAOnXP) {
if (base::win::GetVersion() >= base::win::VERSION_VISTA) {
LOG(INFO) << "Skipping test on this version.";
return;
}
SpawnedTestServer test_server(
SpawnedTestServer::TYPE_HTTPS,
SpawnedTestServer::kLocalhost,
base::FilePath(FILE_PATH_LITERAL("net/data/ssl")));
ASSERT_TRUE(test_server.Start());
TestDelegate d;
scoped_ptr<URLRequest> r(default_context_.CreateRequest(
test_server.GetURL("client-cipher-list"), DEFAULT_PRIORITY, &d, NULL));
r->Start();
EXPECT_TRUE(r->is_pending());
base::RunLoop().Run();
EXPECT_EQ(1, d.response_started_count());
std::vector<std::string> lines;
base::SplitString(d.data_received(), '\n', &lines);
for (size_t i = 0; i < lines.size(); i++) {
int cipher_suite;
ASSERT_TRUE(base::StringToInt(lines[i], &cipher_suite));
EXPECT_FALSE(IsECDSACipherSuite(cipher_suite))
<< "ClientHello advertised " << cipher_suite;
}
}
#endif // OS_WIN
class HTTPSFallbackTest : public testing::Test { class HTTPSFallbackTest : public testing::Test {
public: public:
HTTPSFallbackTest() : context_(true) { HTTPSFallbackTest() : context_(true) {
......
...@@ -37,3 +37,5 @@ Local Modifications: ...@@ -37,3 +37,5 @@ Local Modifications:
failures. failures.
- patches/intolerance_options.patch: Add an option to further control - patches/intolerance_options.patch: Add an option to further control
simulated TLS version intolerance. simulated TLS version intolerance.
- patches/save_client_hello.patch: Save the parsed ClientHello on TLSConnection
so tests can query it.
diff --git a/third_party/tlslite/tlslite/tlsconnection.py b/third_party/tlslite/tlslite/tlsconnection.py
index 996b7e9..06aa0c9 100644
--- a/third_party/tlslite/tlslite/tlsconnection.py
+++ b/third_party/tlslite/tlslite/tlsconnection.py
@@ -1261,6 +1261,9 @@ class TLSConnection(TLSRecordLayer):
return # Handshake was resumed, we're done
else: break
(clientHello, cipherSuite) = result
+
+ # Save the ClientHello for external code to query.
+ self.clientHello = clientHello
#If not a resumption...
...@@ -1261,6 +1261,9 @@ class TLSConnection(TLSRecordLayer): ...@@ -1261,6 +1261,9 @@ class TLSConnection(TLSRecordLayer):
return # Handshake was resumed, we're done return # Handshake was resumed, we're done
else: break else: break
(clientHello, cipherSuite) = result (clientHello, cipherSuite) = result
# Save the ClientHello for external code to query.
self.clientHello = clientHello
#If not a resumption... #If not a resumption...
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment