summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormattm@chromium.org <mattm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-26 02:13:49 +0000
committermattm@chromium.org <mattm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-26 02:13:49 +0000
commit6b4903fd14ab76dfbe872f6c6d7184c428d67260 (patch)
treebc76f151a44c88e1f35ae79df1dfb9ef7e4c3bae
parent9cd45640442bb7b639d2675363b2239ff183a092 (diff)
downloadchromium_src-6b4903fd14ab76dfbe872f6c6d7184c428d67260.zip
chromium_src-6b4903fd14ab76dfbe872f6c6d7184c428d67260.tar.gz
chromium_src-6b4903fd14ab76dfbe872f6c6d7184c428d67260.tar.bz2
Convert SSLClientSocketNSS to use the NSS Channel ID callback.
BUG=129174,127506 TEST=run a TLS Channel ID supporting server, try connecting to it. TBR=joi@chromium.org Review URL: https://chromiumcodereview.appspot.com/10560020 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@144093 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/app/generated_resources.grd16
-rw-r--r--chrome/browser/net/ssl_config_service_manager_pref.cc9
-rw-r--r--chrome/common/chrome_switches.cc4
-rw-r--r--chrome/common/chrome_switches.h1
-rw-r--r--content/public/common/content_switches.cc3
-rw-r--r--content/public/common/content_switches.h1
-rw-r--r--crypto/ec_private_key_nss.cc2
-rw-r--r--net/base/net_log_event_type_list.h6
-rw-r--r--net/base/server_bound_cert_service.cc7
-rw-r--r--net/base/ssl_config_service.cc8
-rw-r--r--net/base/ssl_config_service.h5
-rw-r--r--net/base/ssl_info.cc4
-rw-r--r--net/base/ssl_info.h5
-rw-r--r--net/socket/socket_test_util.cc19
-rw-r--r--net/socket/socket_test_util.h8
-rw-r--r--net/socket/ssl_client_socket.cc15
-rw-r--r--net/socket/ssl_client_socket.h18
-rw-r--r--net/socket/ssl_client_socket_mac.cc5
-rw-r--r--net/socket/ssl_client_socket_nss.cc290
-rw-r--r--net/socket/ssl_client_socket_openssl.cc5
-rw-r--r--net/socket/ssl_client_socket_pool_unittest.cc33
-rw-r--r--net/socket/ssl_client_socket_win.cc5
-rw-r--r--net/socket/ssl_server_socket_unittest.cc2
-rw-r--r--net/spdy/spdy_http_stream_spdy3_unittest.cc11
-rw-r--r--net/spdy/spdy_session.cc13
-rw-r--r--net/spdy/spdy_session.h9
-rw-r--r--net/spdy/spdy_session_spdy2_unittest.cc2
-rw-r--r--net/spdy/spdy_session_spdy3_unittest.cc4
-rw-r--r--net/spdy/spdy_stream.cc2
29 files changed, 254 insertions, 258 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index ddeb86c..26c198e 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -9786,22 +9786,22 @@ experiment id: "<ph name="EXPERIMENT_ID">$5<ex>ar1</ex></ph>"
<message name="IDS_COOKIES_LAST_ACCESSED_LABEL" desc="The last access date label">
Last accessed:
</message>
- <message name="IDS_COOKIES_SERVER_BOUND_CERT" desc="The text shown when there is a server bound cert in the Cookies table">
- Domain Bound Certificate
+ <message name="IDS_COOKIES_SERVER_BOUND_CERT" desc="The text shown when there is a channel id in the Cookies table">
+ Channel ID
</message>
- <message name="IDS_COOKIES_SERVER_BOUND_CERTS" desc="Label for the folder under which a list of server bound certs (name of an internet standard) are displayed">
- Domain Bound Certificates
+ <message name="IDS_COOKIES_SERVER_BOUND_CERTS" desc="Label for the folder under which a list of TLS Channel IDs (name of an internet standard) are displayed">
+ Channel IDs
</message>
- <message name="IDS_COOKIES_SERVER_BOUND_CERT_ORIGIN_LABEL" desc="The server bound certificate label for the server domain">
+ <message name="IDS_COOKIES_SERVER_BOUND_CERT_ORIGIN_LABEL" desc="The channel id label for the server domain">
Domain:
</message>
- <message name="IDS_COOKIES_SERVER_BOUND_CERT_TYPE_LABEL" desc="The server bound certificate Type label">
+ <message name="IDS_COOKIES_SERVER_BOUND_CERT_TYPE_LABEL" desc="The channel id Type label">
Certificate Type:
</message>
- <message name="IDS_COOKIES_SERVER_BOUND_CERT_CREATED_LABEL" desc="The server bound certificate Created label">
+ <message name="IDS_COOKIES_SERVER_BOUND_CERT_CREATED_LABEL" desc="The channel id Created label">
Created:
</message>
- <message name="IDS_COOKIES_SERVER_BOUND_CERT_EXPIRES_LABEL" desc="The server bound certificate Expires label">
+ <message name="IDS_COOKIES_SERVER_BOUND_CERT_EXPIRES_LABEL" desc="The channel id Expires label">
Expires:
</message>
<message name="IDS_CLIENT_CERT_RSA_SIGN" translateable="false" desc="">
diff --git a/chrome/browser/net/ssl_config_service_manager_pref.cc b/chrome/browser/net/ssl_config_service_manager_pref.cc
index fc9389f..c8ac927 100644
--- a/chrome/browser/net/ssl_config_service_manager_pref.cc
+++ b/chrome/browser/net/ssl_config_service_manager_pref.cc
@@ -174,7 +174,7 @@ class SSLConfigServiceManagerPref
BooleanPrefMember rev_checking_enabled_;
StringPrefMember ssl_version_min_;
StringPrefMember ssl_version_max_;
- BooleanPrefMember domain_bound_certs_enabled_;
+ BooleanPrefMember channel_id_enabled_;
BooleanPrefMember ssl_record_splitting_disabled_;
// The cached list of disabled SSL cipher suites.
@@ -194,8 +194,7 @@ SSLConfigServiceManagerPref::SSLConfigServiceManagerPref(
local_state, this);
ssl_version_min_.Init(prefs::kSSLVersionMin, local_state, this);
ssl_version_max_.Init(prefs::kSSLVersionMax, local_state, this);
- domain_bound_certs_enabled_.Init(prefs::kEnableOriginBoundCerts,
- local_state, this);
+ channel_id_enabled_.Init(prefs::kEnableOriginBoundCerts, local_state, this);
ssl_record_splitting_disabled_.Init(prefs::kDisableSSLRecordSplitting,
local_state, this);
pref_change_registrar_.Init(local_state);
@@ -219,7 +218,7 @@ void SSLConfigServiceManagerPref::RegisterPrefs(PrefService* prefs) {
prefs->RegisterStringPref(prefs::kSSLVersionMin, version_min_str);
prefs->RegisterStringPref(prefs::kSSLVersionMax, version_max_str);
prefs->RegisterBooleanPref(prefs::kEnableOriginBoundCerts,
- default_config.domain_bound_certs_enabled);
+ default_config.channel_id_enabled);
prefs->RegisterBooleanPref(prefs::kDisableSSLRecordSplitting,
!default_config.false_start_enabled);
prefs->RegisterListPref(prefs::kCipherSuiteBlacklist);
@@ -280,7 +279,7 @@ void SSLConfigServiceManagerPref::GetSSLConfigFromPrefs(
config->version_max = std::min(supported_version_max, version_max);
}
config->disabled_cipher_suites = disabled_cipher_suites_;
- config->domain_bound_certs_enabled = domain_bound_certs_enabled_.GetValue();
+ config->channel_id_enabled = channel_id_enabled_.GetValue();
// disabling False Start also happens to disable record splitting.
config->false_start_enabled = !ssl_record_splitting_disabled_.GetValue();
SSLConfigServicePref::SetSSLConfigFlags(config);
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index 449feab..b755c0e 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -570,6 +570,10 @@ const char kEnableNpn[] = "enable-npn";
// HTTP is still used for all requests.
const char kEnableNpnHttpOnly[] = "enable-npn-http";
+// Enables TLS Channel ID extension. (The switch is still called
+// "enable-origin-bound-certs" for backwards compatability.)
+const char kEnableOriginBoundCerts[] = "enable-origin-bound-certs";
+
// Enables panels (always on-top docked pop-up windows).
const char kEnablePanels[] = "enable-panels";
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index 2a48ba1..0b64bdd 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -163,6 +163,7 @@ extern const char kEnableNaClIPCProxy[];
extern const char kEnableNpn[];
extern const char kDisableSyncTabs[];
extern const char kEnableNpnHttpOnly[];
+extern const char kEnableOriginBoundCerts[];
extern const char kEnablePanels[];
extern const char kEnablePasswordGeneration[];
extern const char kEnablePnacl[];
diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc
index cba155d..7368f5f 100644
--- a/content/public/common/content_switches.cc
+++ b/content/public/common/content_switches.cc
@@ -300,9 +300,6 @@ const char kEnablePeerConnection[] = "enable-peer-connection";
// assumed to be sRGB.
const char kEnableMonitorProfile[] = "enable-monitor-profile";
-// Enables TLS domain bound certificate extension.
-const char kEnableOriginBoundCerts[] = "enable-origin-bound-certs";
-
// Enables partial swaps in the WK compositor on platforms that support it.
const char kEnablePartialSwap[] = "enable-partial-swap";
diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h
index 96b216d..bc45d11 100644
--- a/content/public/common/content_switches.h
+++ b/content/public/common/content_switches.h
@@ -101,7 +101,6 @@ CONTENT_EXPORT extern const char kEnableLogging[];
extern const char kEnableMediaSource[];
extern const char kEnablePeerConnection[];
extern const char kEnableMonitorProfile[];
-extern const char kEnableOriginBoundCerts[];
extern const char kEnablePartialSwap[];
extern const char kEnablePinch[];
extern const char kEnablePreparsedJsCaching[];
diff --git a/crypto/ec_private_key_nss.cc b/crypto/ec_private_key_nss.cc
index a799285..c6c4763 100644
--- a/crypto/ec_private_key_nss.cc
+++ b/crypto/ec_private_key_nss.cc
@@ -114,7 +114,7 @@ bool ECPrivateKey::ImportFromEncryptedPrivateKeyInfo(
bool sensitive,
SECKEYPrivateKey** key,
SECKEYPublicKey** public_key) {
- ScopedPK11Slot slot(GetPrivateNSSKeySlot());
+ ScopedPK11Slot slot(GetPublicNSSKeySlot());
if (!slot.get())
return false;
diff --git a/net/base/net_log_event_type_list.h b/net/base/net_log_event_type_list.h
index 70c4a90..a127b59 100644
--- a/net/base/net_log_event_type_list.h
+++ b/net/base/net_log_event_type_list.h
@@ -466,6 +466,12 @@ EVENT_TYPE(SSL_CLIENT_CERT_REQUESTED)
// }
EVENT_TYPE(SSL_GET_DOMAIN_BOUND_CERT)
+// The SSL server requested a channel id.
+EVENT_TYPE(SSL_CHANNEL_ID_REQUESTED)
+
+// A channel ID was provided to the SSL library to be sent to the SSL server.
+EVENT_TYPE(SSL_CHANNEL_ID_PROVIDED)
+
// A client certificate (or none) was provided to the SSL library to be sent
// to the SSL server.
// The following parameters are attached to the event:
diff --git a/net/base/server_bound_cert_service.cc b/net/base/server_bound_cert_service.cc
index 58c28e8..b2d3bc8 100644
--- a/net/base/server_bound_cert_service.cc
+++ b/net/base/server_bound_cert_service.cc
@@ -206,6 +206,8 @@ class ServerBoundCertServiceWorker {
&expiration_time_,
&private_key_,
&cert_);
+ DVLOG(1) << "GenerateCert " << server_identifier_ << " " << type_
+ << " returned " << error_;
#if defined(USE_NSS)
// Detach the thread from NSPR.
// Calling NSS functions attaches the thread to NSPR, which stores
@@ -382,6 +384,9 @@ int ServerBoundCertService::GetDomainBoundCert(
std::string* cert,
const CompletionCallback& callback,
RequestHandle* out_req) {
+ DVLOG(1) << __FUNCTION__ << " " << origin << " "
+ << (requested_types.empty() ? -1 : requested_types[0])
+ << (requested_types.size() > 1 ? "..." : "");
DCHECK(CalledOnValidThread());
base::TimeTicks request_start = base::TimeTicks::Now();
@@ -433,6 +438,8 @@ int ServerBoundCertService::GetDomainBoundCert(
DVLOG(1) << "Cert store had cert of wrong type " << *type << " for "
<< domain;
} else {
+ DVLOG(1) << "Cert store had valid cert for " << domain
+ << " of type " << *type;
cert_store_hits_++;
RecordGetDomainBoundCertResult(SYNC_SUCCESS);
base::TimeDelta request_time = base::TimeTicks::Now() - request_start;
diff --git a/net/base/ssl_config_service.cc b/net/base/ssl_config_service.cc
index d713c11..ad2928e16 100644
--- a/net/base/ssl_config_service.cc
+++ b/net/base/ssl_config_service.cc
@@ -38,7 +38,7 @@ SSLConfig::SSLConfig()
version_min(g_default_version_min),
version_max(g_default_version_max),
cached_info_enabled(false),
- domain_bound_certs_enabled(false),
+ channel_id_enabled(false),
false_start_enabled(true),
send_client_cert(false),
verify_ev_cert(false),
@@ -156,10 +156,8 @@ void SSLConfigService::ProcessConfigUpdate(const SSLConfig& orig_config,
(orig_config.version_max != new_config.version_max) ||
(orig_config.disabled_cipher_suites !=
new_config.disabled_cipher_suites) ||
- (orig_config.domain_bound_certs_enabled !=
- new_config.domain_bound_certs_enabled) ||
- (orig_config.false_start_enabled !=
- new_config.false_start_enabled);
+ (orig_config.channel_id_enabled != new_config.channel_id_enabled) ||
+ (orig_config.false_start_enabled != new_config.false_start_enabled);
if (config_changed)
FOR_EACH_OBSERVER(Observer, observer_list_, OnSSLConfigChanged());
diff --git a/net/base/ssl_config_service.h b/net/base/ssl_config_service.h
index d76f96a..b4ba45a 100644
--- a/net/base/ssl_config_service.h
+++ b/net/base/ssl_config_service.h
@@ -88,8 +88,7 @@ struct NET_EXPORT SSLConfig {
std::vector<uint16> disabled_cipher_suites;
bool cached_info_enabled; // True if TLS cached info extension is enabled.
- bool domain_bound_certs_enabled; // True if TLS origin bound cert extension
- // is enabled.
+ bool channel_id_enabled; // True if TLS channel ID extension is enabled.
bool false_start_enabled; // True if we'll use TLS False Start.
// TODO(wtc): move the following members to a new SSLParams structure. They
@@ -153,7 +152,7 @@ class NET_EXPORT SSLConfigService
// version_min
// version_max
// disabled_cipher_suites
- // domain_bound_certs_enabled
+ // channel_id_enabled
// false_start_enabled
virtual void OnSSLConfigChanged() = 0;
diff --git a/net/base/ssl_info.cc b/net/base/ssl_info.cc
index 11ade52..db4ac67 100644
--- a/net/base/ssl_info.cc
+++ b/net/base/ssl_info.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -27,6 +27,7 @@ SSLInfo& SSLInfo::operator=(const SSLInfo& info) {
connection_status = info.connection_status;
is_issued_by_known_root = info.is_issued_by_known_root;
client_cert_sent = info.client_cert_sent;
+ channel_id_sent = info.channel_id_sent;
handshake_type = info.handshake_type;
public_key_hashes = info.public_key_hashes;
return *this;
@@ -39,6 +40,7 @@ void SSLInfo::Reset() {
connection_status = 0;
is_issued_by_known_root = false;
client_cert_sent = false;
+ channel_id_sent = false;
handshake_type = HANDSHAKE_UNKNOWN;
public_key_hashes.clear();
}
diff --git a/net/base/ssl_info.h b/net/base/ssl_info.h
index 54217a6..f69557e 100644
--- a/net/base/ssl_info.h
+++ b/net/base/ssl_info.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -67,6 +67,9 @@ class NET_EXPORT SSLInfo {
// a Certificate message with no client certificate in it does not count.
bool client_cert_sent;
+ // True if a channel ID was sent to the server.
+ bool channel_id_sent;
+
HandshakeType handshake_type;
// The hashes of the SubjectPublicKeyInfos from each certificate in the chain.
diff --git a/net/socket/socket_test_util.cc b/net/socket/socket_test_util.cc
index 8aeec46..b33fa1b 100644
--- a/net/socket/socket_test_util.cc
+++ b/net/socket/socket_test_util.cc
@@ -262,7 +262,7 @@ SSLSocketDataProvider::SSLSocketDataProvider(IoMode mode, int result)
protocol_negotiated(kProtoUnknown),
client_cert_sent(false),
cert_request_info(NULL),
- domain_bound_cert_type(CLIENT_CERT_INVALID_TYPE) {
+ channel_id_sent(false) {
}
SSLSocketDataProvider::~SSLSocketDataProvider() {
@@ -1157,8 +1157,8 @@ base::TimeDelta MockSSLClientSocket::GetConnectTimeMicros() const {
void MockSSLClientSocket::GetSSLInfo(SSLInfo* ssl_info) {
ssl_info->Reset();
ssl_info->cert = data_->cert;
- ssl_info->client_cert_sent = WasDomainBoundCertSent() ||
- data_->client_cert_sent;
+ ssl_info->client_cert_sent = data_->client_cert_sent;
+ ssl_info->channel_id_sent = data_->channel_id_sent;
}
void MockSSLClientSocket::GetSSLCertRequestInfo(
@@ -1203,17 +1203,12 @@ void MockSSLClientSocket::set_protocol_negotiated(
protocol_negotiated_ = protocol_negotiated;
}
-bool MockSSLClientSocket::WasDomainBoundCertSent() const {
- return data_->domain_bound_cert_type != CLIENT_CERT_INVALID_TYPE;
+bool MockSSLClientSocket::WasChannelIDSent() const {
+ return data_->channel_id_sent;
}
-SSLClientCertType MockSSLClientSocket::domain_bound_cert_type() const {
- return data_->domain_bound_cert_type;
-}
-
-SSLClientCertType MockSSLClientSocket::set_domain_bound_cert_type(
- SSLClientCertType type) {
- return data_->domain_bound_cert_type = type;
+void MockSSLClientSocket::set_channel_id_sent(bool channel_id_sent) {
+ data_->channel_id_sent = channel_id_sent;
}
ServerBoundCertService* MockSSLClientSocket::GetServerBoundCertService() const {
diff --git a/net/socket/socket_test_util.h b/net/socket/socket_test_util.h
index 22b0af2..df542c9 100644
--- a/net/socket/socket_test_util.h
+++ b/net/socket/socket_test_util.h
@@ -287,7 +287,7 @@ struct SSLSocketDataProvider {
bool client_cert_sent;
SSLCertRequestInfo* cert_request_info;
scoped_refptr<X509Certificate> cert;
- SSLClientCertType domain_bound_cert_type;
+ bool channel_id_sent;
ServerBoundCertService* server_bound_cert_service;
};
@@ -772,10 +772,8 @@ class MockSSLClientSocket : public MockClientSocket, public AsyncSocket {
// This MockSocket does not implement the manual async IO feature.
virtual void OnReadComplete(const MockRead& data) OVERRIDE;
- virtual bool WasDomainBoundCertSent() const OVERRIDE;
- virtual SSLClientCertType domain_bound_cert_type() const OVERRIDE;
- virtual SSLClientCertType set_domain_bound_cert_type(
- SSLClientCertType type) OVERRIDE;
+ virtual bool WasChannelIDSent() const OVERRIDE;
+ virtual void set_channel_id_sent(bool channel_id_sent) OVERRIDE;
virtual ServerBoundCertService* GetServerBoundCertService() const OVERRIDE;
private:
diff --git a/net/socket/ssl_client_socket.cc b/net/socket/ssl_client_socket.cc
index 77002d0..6bcc96e 100644
--- a/net/socket/ssl_client_socket.cc
+++ b/net/socket/ssl_client_socket.cc
@@ -12,7 +12,7 @@ SSLClientSocket::SSLClientSocket()
: was_npn_negotiated_(false),
was_spdy_negotiated_(false),
protocol_negotiated_(kProtoUnknown),
- domain_bound_cert_type_(CLIENT_CERT_INVALID_TYPE) {
+ channel_id_sent_(false) {
}
// static
@@ -120,17 +120,12 @@ void SSLClientSocket::set_protocol_negotiated(NextProto protocol_negotiated) {
protocol_negotiated_ = protocol_negotiated;
}
-bool SSLClientSocket::WasDomainBoundCertSent() const {
- return domain_bound_cert_type_ != CLIENT_CERT_INVALID_TYPE;
+bool SSLClientSocket::WasChannelIDSent() const {
+ return channel_id_sent_;
}
-SSLClientCertType SSLClientSocket::domain_bound_cert_type() const {
- return domain_bound_cert_type_;
-}
-
-SSLClientCertType SSLClientSocket::set_domain_bound_cert_type(
- SSLClientCertType type) {
- return domain_bound_cert_type_ = type;
+void SSLClientSocket::set_channel_id_sent(bool channel_id_sent) {
+ channel_id_sent_ = channel_id_sent;
}
} // namespace net
diff --git a/net/socket/ssl_client_socket.h b/net/socket/ssl_client_socket.h
index 14cf163..06ed692 100644
--- a/net/socket/ssl_client_socket.h
+++ b/net/socket/ssl_client_socket.h
@@ -11,7 +11,6 @@
#include "net/base/completion_callback.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
-#include "net/base/ssl_client_cert_type.h"
#include "net/socket/ssl_socket.h"
#include "net/socket/stream_socket.h"
@@ -132,17 +131,13 @@ class NET_EXPORT SSLClientSocket : public SSLSocket {
// server bound certificates are not supported.
virtual ServerBoundCertService* GetServerBoundCertService() const = 0;
- // Returns true if a domain bound certificate was sent on this connection.
+ // Returns true if a channel ID was sent on this connection.
// This may be useful for protocols, like SPDY, which allow the same
// connection to be shared between multiple domains, each of which need
- // a domain bound certificate.
- virtual bool WasDomainBoundCertSent() const;
+ // a channel ID.
+ virtual bool WasChannelIDSent() const;
- // Returns the type of the domain bound cert that was sent, or
- // CLIENT_CERT_INVALID_TYPE if none was sent.
- virtual SSLClientCertType domain_bound_cert_type() const;
-
- virtual SSLClientCertType set_domain_bound_cert_type(SSLClientCertType type);
+ virtual void set_channel_id_sent(bool channel_id_sent);
private:
// True if NPN was responded to, independent of selecting SPDY or HTTP.
@@ -151,9 +146,8 @@ class NET_EXPORT SSLClientSocket : public SSLSocket {
bool was_spdy_negotiated_;
// Protocol that we negotiated with the server.
NextProto protocol_negotiated_;
- // Type of the domain bound cert that was sent, or CLIENT_CERT_INVALID_TYPE
- // if none was sent.
- SSLClientCertType domain_bound_cert_type_;
+ // True if a channel ID was sent.
+ bool channel_id_sent_;
};
} // namespace net
diff --git a/net/socket/ssl_client_socket_mac.cc b/net/socket/ssl_client_socket_mac.cc
index f51079f..bdca223 100644
--- a/net/socket/ssl_client_socket_mac.cc
+++ b/net/socket/ssl_client_socket_mac.cc
@@ -725,8 +725,9 @@ void SSLClientSocketMac::GetSSLInfo(SSLInfo* ssl_info) {
ssl_info->public_key_hashes = server_cert_verify_result_.public_key_hashes;
ssl_info->is_issued_by_known_root =
server_cert_verify_result_.is_issued_by_known_root;
- ssl_info->client_cert_sent = WasDomainBoundCertSent() ||
- (ssl_config_.send_client_cert && ssl_config_.client_cert);
+ ssl_info->client_cert_sent =
+ ssl_config_.send_client_cert && ssl_config_.client_cert;
+ ssl_info->channel_id_sent = WasChannelIDSent();
// security info
SSLCipherSuite suite;
diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc
index d60547f..af08f71 100644
--- a/net/socket/ssl_client_socket_nss.cc
+++ b/net/socket/ssl_client_socket_nss.cc
@@ -81,6 +81,7 @@
#include "base/threading/thread_restrictions.h"
#include "base/values.h"
#include "crypto/ec_private_key.h"
+#include "crypto/nss_util_internal.h"
#include "crypto/rsa_private_key.h"
#include "crypto/scoped_nss_types.h"
#include "net/base/address_list.h"
@@ -205,6 +206,15 @@ namespace net {
namespace {
+class FreeCERTCertificate {
+ public:
+ inline void operator()(CERTCertificate* x) const {
+ CERT_DestroyCertificate(x);
+ }
+};
+typedef scoped_ptr_malloc<CERTCertificate, FreeCERTCertificate>
+ ScopedCERTCertificate;
+
#if defined(OS_WIN)
// This callback is intended to be used with CertFindChainInStore. In addition
@@ -371,12 +381,6 @@ DNSValidationResult CheckDNSSECChain(
return r;
}
-bool DomainBoundCertNegotiated(PRFileDesc* socket) {
- // TODO(wtc,mattm): this is temporary while DBC support is changed into
- // Channel ID.
- return false;
-}
-
void DestroyCertificates(CERTCertificate** certs, size_t len) {
for (size_t i = 0; i < len; i++)
CERT_DestroyCertificate(certs[i]);
@@ -523,7 +527,7 @@ struct HandshakeState {
next_proto_status = SSLClientSocket::kNextProtoUnsupported;
next_proto.clear();
server_protos.clear();
- domain_bound_cert_type = CLIENT_CERT_INVALID_TYPE;
+ channel_id_sent = false;
client_certs.clear();
server_cert_chain.Reset(NULL);
server_cert = NULL;
@@ -539,9 +543,8 @@ struct HandshakeState {
// If the server supports NPN, the protocols supported by the server.
std::string server_protos;
- // The type of domain bound cert that was exchanged, or
- // CLIENT_CERT_INVALID_TYPE if no domain bound cert was negotiated or sent.
- SSLClientCertType domain_bound_cert_type;
+ // True if a channel ID was sent.
+ bool channel_id_sent;
// If the peer requests client certificate authentication, the set of
// certificates that matched the peer's criteria.
@@ -856,28 +859,28 @@ class SSLClientSocketNSS::Core : public base::RefCountedThreadSafe<Core> {
void DoReadCallback(int result);
void DoWriteCallback(int result);
- // Domain bound cert client auth handler.
- // Returns the value the ClientAuthHandler function should return.
- SECStatus DomainBoundClientAuthHandler(
- const SECItem* cert_types,
- CERTCertificate** result_certificate,
- SECKEYPrivateKey** result_private_key);
+ // Client channel ID handler.
+ static SECStatus ClientChannelIDHandler(
+ void* arg,
+ PRFileDesc* socket,
+ SECKEYPublicKey **out_public_key,
+ SECKEYPrivateKey **out_private_key);
- // ImportDBCertAndKey is a helper function for turning a DER-encoded cert and
- // key into a CERTCertificate and SECKEYPrivateKey. Returns OK upon success
+ // ImportChannelIDKeys is a helper function for turning a DER-encoded cert and
+ // key into a SECKEYPublicKey and SECKEYPrivateKey. Returns OK upon success
// and an error code otherwise.
// Requires |domain_bound_private_key_| and |domain_bound_cert_| to have been
// set by a call to ServerBoundCertService->GetDomainBoundCert. The caller
// takes ownership of the |*cert| and |*key|.
- int ImportDBCertAndKey(CERTCertificate** cert, SECKEYPrivateKey** key);
+ int ImportChannelIDKeys(SECKEYPublicKey** public_key, SECKEYPrivateKey** key);
// Updates the NSS and platform specific certificates.
void UpdateServerCert();
// Updates the nss_handshake_state_ with the negotiated security parameters.
void UpdateConnectionStatus();
- // Record histograms for DBC support during full handshakes - resumed
+ // Record histograms for channel id support during full handshakes - resumed
// handshakes are ignored.
- void RecordDomainBoundCertSupport() const;
+ void RecordChannelIDSupport() const;
////////////////////////////////////////////////////////////////////////////
// Methods that are ONLY called on the network task runner:
@@ -908,6 +911,10 @@ class SSLClientSocketNSS::Core : public base::RefCountedThreadSafe<Core> {
// SSL_CLIENT_CERT_PROVIDED event, with the indicated count.
void AddCertProvidedEvent(int cert_count);
+ // Sets the handshake state |channel_id_sent| flag and logs the
+ // SSL_CHANNEL_ID_PROVIDED event.
+ void SetChannelIDProvided();
+
////////////////////////////////////////////////////////////////////////////
// Members that are ONLY accessed on the network task runner:
////////////////////////////////////////////////////////////////////////////
@@ -945,8 +952,10 @@ class SSLClientSocketNSS::Core : public base::RefCountedThreadSafe<Core> {
State next_handshake_state_;
- // True if domain bound certs were negotiated.
- bool domain_bound_cert_xtn_negotiated_;
+ // True if channel ID extension was negotiated.
+ bool channel_id_xtn_negotiated_;
+ // True if the handshake state machine was interrupted for channel ID.
+ bool channel_id_needed_;
// True if the handshake state machine was interrupted for client auth.
bool client_auth_cert_needed_;
// True if NSS has called HandshakeCallback.
@@ -1010,7 +1019,8 @@ SSLClientSocketNSS::Core::Core(
nss_fd_(NULL),
nss_bufs_(NULL),
next_handshake_state_(STATE_NONE),
- domain_bound_cert_xtn_negotiated_(false),
+ channel_id_xtn_negotiated_(false),
+ channel_id_needed_(false),
client_auth_cert_needed_(false),
handshake_callback_called_(false),
transport_recv_busy_(false),
@@ -1070,6 +1080,24 @@ bool SSLClientSocketNSS::Core::Init(PRFileDesc* socket,
return false;
}
+ if (ssl_config_.channel_id_enabled) {
+ // TODO(mattm): we can do this check on the network task runner only because
+ // we use the NSS internal slot. If we support other slots in the future,
+ // checking whether they support ECDSA may block NSS, and thus this check
+ // would have to be moved to the NSS task runner.
+ crypto::ScopedPK11Slot slot(crypto::GetPublicNSSKeySlot());
+ if (PK11_DoesMechanism(slot.get(), CKM_EC_KEY_PAIR_GEN) &&
+ PK11_DoesMechanism(slot.get(), CKM_ECDSA)) {
+ rv = SSL_SetClientChannelIDCallback(
+ nss_fd_, SSLClientSocketNSS::Core::ClientChannelIDHandler, this);
+ if (rv != SECSuccess)
+ LogFailedNSSFunction(*weak_net_log_, "SSL_SetClientChannelIDCallback",
+ "");
+ } else {
+ DVLOG(1) << "Elliptic Curve not supported, not enabling channel ID.";
+ }
+ }
+
rv = SSL_HandshakeCallback(
nss_fd_, SSLClientSocketNSS::Core::HandshakeCallback, this);
if (rv != SECSuccess) {
@@ -1317,15 +1345,6 @@ SECStatus SSLClientSocketNSS::Core::PlatformClientAuthHandler(
base::Bind(&AddLogEvent, core->weak_net_log_,
NetLog::TYPE_SSL_CLIENT_CERT_REQUESTED));
- const SECItem* cert_types = SSL_GetRequestedClientCertificateTypes(socket);
-
- // Check if a domain-bound certificate is requested.
- if (DomainBoundCertNegotiated(socket)) {
- return core->DomainBoundClientAuthHandler(cert_types,
- result_nss_certificate,
- result_nss_private_key);
- }
-
core->client_auth_cert_needed_ = !core->ssl_config_.send_client_cert;
#if defined(OS_WIN)
if (core->ssl_config_.send_client_cert) {
@@ -1631,14 +1650,6 @@ SECStatus SSLClientSocketNSS::Core::ClientAuthHandler(
base::Bind(&AddLogEvent, core->weak_net_log_,
NetLog::TYPE_SSL_CLIENT_CERT_REQUESTED));
- const SECItem* cert_types = SSL_GetRequestedClientCertificateTypes(socket);
-
- // Check if a domain-bound certificate is requested.
- if (DomainBoundCertNegotiated(socket)) {
- return core->DomainBoundClientAuthHandler(
- cert_types, result_certificate, result_private_key);
- }
-
// Regular client certificate requested.
core->client_auth_cert_needed_ = !core->ssl_config_.send_client_cert;
void* wincx = SSL_RevealPinArg(socket);
@@ -1731,7 +1742,7 @@ void SSLClientSocketNSS::Core::HandshakeCallback(
nss_state->resumed_handshake = false;
}
- core->RecordDomainBoundCertSupport();
+ core->RecordChannelIDSupport();
core->UpdateServerCert();
core->UpdateConnectionStatus();
@@ -1964,30 +1975,27 @@ int SSLClientSocketNSS::Core::DoHandshake() {
int net_error = net::OK;
SECStatus rv = SSL_ForceHandshake(nss_fd_);
- // TODO(rkn): Handle the case in which server-bound cert generation takes
- // too long and the server has closed the connection. Report some new error
- // code so that the higher level code will attempt to delete the socket and
- // redo the handshake.
- if (client_auth_cert_needed_) {
- if (domain_bound_cert_xtn_negotiated_) {
- GotoState(STATE_GET_DOMAIN_BOUND_CERT_COMPLETE);
- net_error = ERR_IO_PENDING;
- } else {
- net_error = ERR_SSL_CLIENT_AUTH_CERT_NEEDED;
- PostOrRunCallback(
- FROM_HERE,
- base::Bind(&AddLogEventWithCallback, weak_net_log_,
- NetLog::TYPE_SSL_HANDSHAKE_ERROR,
- CreateNetLogSSLErrorCallback(net_error, 0)));
-
- // If the handshake already succeeded (because the server requests but
- // doesn't require a client cert), we need to invalidate the SSL session
- // so that we won't try to resume the non-client-authenticated session in
- // the next handshake. This will cause the server to ask for a client
- // cert again.
- if (rv == SECSuccess && SSL_InvalidateSession(nss_fd_) != SECSuccess)
- LOG(WARNING) << "Couldn't invalidate SSL session: " << PR_GetError();
- }
+ // Note: this function may be called multiple times during the handshake, so
+ // even though channel id and client auth are separate else cases, they can
+ // both be used during a single SSL handshake.
+ if (channel_id_needed_) {
+ GotoState(STATE_GET_DOMAIN_BOUND_CERT_COMPLETE);
+ net_error = ERR_IO_PENDING;
+ } else if (client_auth_cert_needed_) {
+ net_error = ERR_SSL_CLIENT_AUTH_CERT_NEEDED;
+ PostOrRunCallback(
+ FROM_HERE,
+ base::Bind(&AddLogEventWithCallback, weak_net_log_,
+ NetLog::TYPE_SSL_HANDSHAKE_ERROR,
+ CreateNetLogSSLErrorCallback(net_error, 0)));
+
+ // If the handshake already succeeded (because the server requests but
+ // doesn't require a client cert), we need to invalidate the SSL session
+ // so that we won't try to resume the non-client-authenticated session in
+ // the next handshake. This will cause the server to ask for a client
+ // cert again.
+ if (rv == SECSuccess && SSL_InvalidateSession(nss_fd_) != SECSuccess)
+ LOG(WARNING) << "Couldn't invalidate SSL session: " << PR_GetError();
} else if (rv == SECSuccess) {
if (!handshake_callback_called_) {
// Workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=562434 -
@@ -2072,34 +2080,22 @@ int SSLClientSocketNSS::Core::DoGetDBCertComplete(int result) {
base::Bind(&BoundNetLog::EndEventWithNetErrorCode, weak_net_log_,
NetLog::TYPE_SSL_GET_DOMAIN_BOUND_CERT, result));
- client_auth_cert_needed_ = false;
- domain_bound_cert_type_ = CLIENT_CERT_INVALID_TYPE;
-
- if (result != OK) {
- // Failed to get a DBC. Proceed without.
- rv = SSL_RestartHandshakeAfterCertReq(nss_fd_, NULL, NULL, NULL);
- if (rv != SECSuccess)
- return MapNSSError(PORT_GetError());
+ channel_id_needed_ = false;
- GotoState(STATE_HANDSHAKE);
- return OK;
- }
+ if (result != OK)
+ return result;
- CERTCertificate* cert;
- SECKEYPrivateKey* key;
- int error = ImportDBCertAndKey(&cert, &key);
+ SECKEYPublicKey* public_key;
+ SECKEYPrivateKey* private_key;
+ int error = ImportChannelIDKeys(&public_key, &private_key);
if (error != OK)
return error;
- CERTCertificateList* cert_chain =
- CERT_CertChainFromCert(cert, certUsageSSLClient, PR_FALSE);
-
- AddCertProvidedEvent(cert_chain->len);
-
- rv = SSL_RestartHandshakeAfterCertReq(nss_fd_, cert, key, cert_chain);
+ rv = SSL_RestartHandshakeAfterChannelIDReq(nss_fd_, public_key, private_key);
if (rv != SECSuccess)
return MapNSSError(PORT_GetError());
+ SetChannelIDProvided();
GotoState(STATE_HANDSHAKE);
return OK;
}
@@ -2363,90 +2359,91 @@ void SSLClientSocketNSS::Core::DoWriteCallback(int rv) {
PostOrRunCallback(FROM_HERE, c);
}
-SECStatus SSLClientSocketNSS::Core::DomainBoundClientAuthHandler(
- const SECItem* cert_types,
- CERTCertificate** result_certificate,
- SECKEYPrivateKey** result_private_key) {
- DCHECK(OnNSSTaskRunner());
+SECStatus SSLClientSocketNSS::Core::ClientChannelIDHandler(
+ void* arg,
+ PRFileDesc* socket,
+ SECKEYPublicKey **out_public_key,
+ SECKEYPrivateKey **out_private_key) {
+ Core* core = reinterpret_cast<Core*>(arg);
+ DCHECK(core->OnNSSTaskRunner());
- domain_bound_cert_xtn_negotiated_ = true;
+ core->PostOrRunCallback(
+ FROM_HERE,
+ base::Bind(&AddLogEvent, core->weak_net_log_,
+ NetLog::TYPE_SSL_CHANNEL_ID_REQUESTED));
- // We have negotiated the domain-bound certificate extension.
- std::string origin = "https://" + host_and_port_.ToString();
- std::vector<uint8> requested_cert_types(cert_types->data,
- cert_types->data + cert_types->len);
+ // We have negotiated the TLS channel ID extension.
+ core->channel_id_xtn_negotiated_ = true;
+ std::string origin = "https://" + core->host_and_port_.ToString();
+ std::vector<uint8> requested_cert_types;
+ requested_cert_types.push_back(CLIENT_CERT_ECDSA_SIGN);
int error = ERR_UNEXPECTED;
- if (OnNetworkTaskRunner()) {
- error = DoGetDomainBoundCert(origin, requested_cert_types);
+ if (core->OnNetworkTaskRunner()) {
+ error = core->DoGetDomainBoundCert(origin, requested_cert_types);
} else {
- bool posted = network_task_runner_->PostTask(
+ bool posted = core->network_task_runner_->PostTask(
FROM_HERE,
- base::Bind(IgnoreResult(&Core::DoGetDomainBoundCert), this, origin,
- requested_cert_types));
+ base::Bind(
+ IgnoreResult(&Core::DoGetDomainBoundCert),
+ core, origin, requested_cert_types));
error = posted ? ERR_IO_PENDING : ERR_ABORTED;
}
if (error == ERR_IO_PENDING) {
// Asynchronous case.
- client_auth_cert_needed_ = true;
+ core->channel_id_needed_ = true;
return SECWouldBlock;
}
- PostOrRunCallback(
+ core->PostOrRunCallback(
FROM_HERE,
- base::Bind(&BoundNetLog::EndEventWithNetErrorCode, weak_net_log_,
+ base::Bind(&BoundNetLog::EndEventWithNetErrorCode, core->weak_net_log_,
NetLog::TYPE_SSL_GET_DOMAIN_BOUND_CERT, error));
SECStatus rv = SECSuccess;
if (error == OK) {
// Synchronous success.
- int result = ImportDBCertAndKey(result_certificate, result_private_key);
- if (result != OK) {
- domain_bound_cert_type_ = CLIENT_CERT_INVALID_TYPE;
+ int result = core->ImportChannelIDKeys(out_public_key, out_private_key);
+ if (result == OK)
+ core->SetChannelIDProvided();
+ else
rv = SECFailure;
- }
} else {
rv = SECFailure;
}
- int cert_count = (rv == SECSuccess) ? 1 : 0;
- AddCertProvidedEvent(cert_count);
return rv;
}
-int SSLClientSocketNSS::Core::ImportDBCertAndKey(CERTCertificate** cert,
- SECKEYPrivateKey** key) {
+int SSLClientSocketNSS::Core::ImportChannelIDKeys(SECKEYPublicKey** public_key,
+ SECKEYPrivateKey** key) {
// Set the certificate.
SECItem cert_item;
cert_item.data = (unsigned char*) domain_bound_cert_.data();
cert_item.len = domain_bound_cert_.size();
- *cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
- &cert_item,
- NULL,
- PR_FALSE,
- PR_TRUE);
- if (*cert == NULL)
+ ScopedCERTCertificate cert(CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
+ &cert_item,
+ NULL,
+ PR_FALSE,
+ PR_TRUE));
+ if (cert == NULL)
return MapNSSError(PORT_GetError());
// Set the private key.
switch (domain_bound_cert_type_) {
case CLIENT_CERT_ECDSA_SIGN: {
- SECKEYPublicKey* public_key = NULL;
if (!crypto::ECPrivateKey::ImportFromEncryptedPrivateKeyInfo(
ServerBoundCertService::kEPKIPassword,
reinterpret_cast<const unsigned char*>(
domain_bound_private_key_.data()),
domain_bound_private_key_.size(),
- &(*cert)->subjectPublicKeyInfo,
+ &cert->subjectPublicKeyInfo,
false,
false,
key,
- &public_key)) {
+ public_key)) {
int error = MapNSSError(PORT_GetError());
- CERT_DestroyCertificate(*cert);
- *cert = NULL;
return error;
}
- SECKEY_DestroyPublicKey(public_key);
break;
}
@@ -2541,7 +2538,7 @@ void SSLClientSocketNSS::Core::UpdateConnectionStatus() {
}
}
-void SSLClientSocketNSS::Core::RecordDomainBoundCertSupport() const {
+void SSLClientSocketNSS::Core::RecordChannelIDSupport() const {
if (nss_handshake_state_.resumed_handshake)
return;
@@ -2552,12 +2549,10 @@ void SSLClientSocketNSS::Core::RecordDomainBoundCertSupport() const {
CLIENT_AND_SERVER = 2,
DOMAIN_BOUND_CERT_USAGE_MAX
} supported = DISABLED;
-#ifdef SSL_ENABLE_OB_CERTS
- if (domain_bound_cert_xtn_negotiated_)
+ if (channel_id_xtn_negotiated_)
supported = CLIENT_AND_SERVER;
- else if (ssl_config_.domain_bound_certs_enabled)
+ else if (ssl_config_.channel_id_enabled)
supported = CLIENT_ONLY;
-#endif
UMA_HISTOGRAM_ENUMERATION("DomainBoundCerts.Support", supported,
DOMAIN_BOUND_CERT_USAGE_MAX);
}
@@ -2675,6 +2670,7 @@ void SSLClientSocketNSS::Core::OnHandshakeIOComplete(int result) {
}
void SSLClientSocketNSS::Core::OnGetDomainBoundCertComplete(int result) {
+ DVLOG(1) << __FUNCTION__ << " " << result;
DCHECK(OnNetworkTaskRunner());
domain_bound_cert_request_handle_ = NULL;
@@ -2735,6 +2731,18 @@ void SSLClientSocketNSS::Core::AddCertProvidedEvent(int cert_count) {
NetLog::IntegerCallback("cert_count", cert_count)));
}
+void SSLClientSocketNSS::Core::SetChannelIDProvided() {
+ PostOrRunCallback(
+ FROM_HERE, base::Bind(&AddLogEvent, weak_net_log_,
+ NetLog::TYPE_SSL_CHANNEL_ID_PROVIDED));
+ nss_handshake_state_.channel_id_sent = true;
+ // Update the network task runner's view of the handshake state now that
+ // channel id has been sent.
+ PostOrRunCallback(
+ FROM_HERE, base::Bind(&Core::OnHandshakeStateUpdated, this,
+ nss_handshake_state_));
+}
+
SSLClientSocketNSS::SSLClientSocketNSS(
base::SingleThreadTaskRunner* nss_task_runner,
ClientSocketHandle* transport_socket,
@@ -2798,8 +2806,9 @@ void SSLClientSocketNSS::GetSSLInfo(SSLInfo* ssl_info) {
}
ssl_info->is_issued_by_known_root =
server_cert_verify_result_->is_issued_by_known_root;
- ssl_info->client_cert_sent = WasDomainBoundCertSent() ||
- (ssl_config_.send_client_cert && ssl_config_.client_cert);
+ ssl_info->client_cert_sent =
+ ssl_config_.send_client_cert && ssl_config_.client_cert;
+ ssl_info->channel_id_sent = WasChannelIDSent();
PRUint16 cipher_suite = SSLConnectionStatusToCipherSuite(
core_->state().ssl_connection_status);
@@ -3196,22 +3205,6 @@ int SSLClientSocketNSS::InitializeSSLOptions() {
LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_CACHED_INFO");
#endif
-#ifdef SSL_ENABLE_OB_CERTS
- rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_OB_CERTS,
- ssl_config_.domain_bound_certs_enabled);
- if (rv != SECSuccess)
- LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_OB_CERTS");
-#endif
-
-#ifdef SSL_ENCRYPT_CLIENT_CERTS
- // For now, enable the encrypted client certificates extension only if
- // server-bound certificates are enabled.
- rv = SSL_OptionSet(nss_fd_, SSL_ENCRYPT_CLIENT_CERTS,
- ssl_config_.domain_bound_certs_enabled);
- if (rv != SECSuccess)
- LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENCRYPT_CLIENT_CERTS");
-#endif
-
rv = SSL_OptionSet(nss_fd_, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE);
if (rv != SECSuccess) {
LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_HANDSHAKE_AS_CLIENT");
@@ -3384,8 +3377,7 @@ int SSLClientSocketNSS::DoHandshakeComplete(int result) {
GotoState(STATE_VERIFY_DNSSEC);
// Done!
}
- if (core_->state().domain_bound_cert_type != CLIENT_CERT_INVALID_TYPE)
- set_domain_bound_cert_type(core_->state().domain_bound_cert_type);
+ set_channel_id_sent(core_->state().channel_id_sent);
LeaveFunction(result);
return result;
diff --git a/net/socket/ssl_client_socket_openssl.cc b/net/socket/ssl_client_socket_openssl.cc
index dc8cdff..e350ded 100644
--- a/net/socket/ssl_client_socket_openssl.cc
+++ b/net/socket/ssl_client_socket_openssl.cc
@@ -602,8 +602,9 @@ void SSLClientSocketOpenSSL::GetSSLInfo(SSLInfo* ssl_info) {
server_cert_verify_result_.is_issued_by_known_root;
ssl_info->public_key_hashes =
server_cert_verify_result_.public_key_hashes;
- ssl_info->client_cert_sent = WasDomainBoundCertSent() ||
- (ssl_config_.send_client_cert && ssl_config_.client_cert);
+ ssl_info->client_cert_sent =
+ ssl_config_.send_client_cert && ssl_config_.client_cert;
+ ssl_info->channel_id_sent = WasChannelIDSent();
const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl_);
CHECK(cipher);
diff --git a/net/socket/ssl_client_socket_pool_unittest.cc b/net/socket/ssl_client_socket_pool_unittest.cc
index a725438..3eb05fa 100644
--- a/net/socket/ssl_client_socket_pool_unittest.cc
+++ b/net/socket/ssl_client_socket_pool_unittest.cc
@@ -147,6 +147,8 @@ class SSLClientSocketPoolTest : public testing::Test {
return new HttpNetworkSession(params);
}
+ void TestIPPoolingDisabled(SSLSocketDataProvider* ssl);
+
MockClientSocketFactory socket_factory_;
MockCachingHostResolver host_resolver_;
scoped_ptr<CertVerifier> cert_verifier_;
@@ -738,9 +740,8 @@ TEST_F(SSLClientSocketPoolTest, IPPooling) {
session_->spdy_session_pool()->CloseAllSessions();
}
-// Verifies that an SSL connection with client authentication disables SPDY IP
-// pooling.
-TEST_F(SSLClientSocketPoolTest, IPPoolingClientCert) {
+void SSLClientSocketPoolTest::TestIPPoolingDisabled(
+ SSLSocketDataProvider* ssl) {
const int kTestPort = 80;
struct TestHosts {
std::string name;
@@ -775,12 +776,7 @@ TEST_F(SSLClientSocketPoolTest, IPPoolingClientCert) {
};
StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
socket_factory_.AddSocketDataProvider(&data);
- SSLSocketDataProvider ssl(ASYNC, OK);
- ssl.cert = X509Certificate::CreateFromBytes(
- reinterpret_cast<const char*>(webkit_der), sizeof(webkit_der));
- ssl.client_cert_sent = true;
- ssl.SetNextProto(kProtoSPDY2);
- socket_factory_.AddSSLSocketDataProvider(&ssl);
+ socket_factory_.AddSSLSocketDataProvider(ssl);
CreatePool(true /* tcp pool */, false, false);
scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_DIRECT,
@@ -822,6 +818,25 @@ TEST_F(SSLClientSocketPoolTest, IPPoolingClientCert) {
session_->spdy_session_pool()->CloseAllSessions();
}
+// Verifies that an SSL connection with client authentication disables SPDY IP
+// pooling.
+TEST_F(SSLClientSocketPoolTest, IPPoolingClientCert) {
+ SSLSocketDataProvider ssl(ASYNC, OK);
+ ssl.cert = X509Certificate::CreateFromBytes(
+ reinterpret_cast<const char*>(webkit_der), sizeof(webkit_der));
+ ssl.client_cert_sent = true;
+ ssl.SetNextProto(kProtoSPDY2);
+ TestIPPoolingDisabled(&ssl);
+}
+
+// Verifies that an SSL connection with channel ID disables SPDY IP pooling.
+TEST_F(SSLClientSocketPoolTest, IPPoolingChannelID) {
+ SSLSocketDataProvider ssl(ASYNC, OK);
+ ssl.channel_id_sent = true;
+ ssl.SetNextProto(kProtoSPDY2);
+ TestIPPoolingDisabled(&ssl);
+}
+
// It would be nice to also test the timeouts in SSLClientSocketPool.
} // namespace
diff --git a/net/socket/ssl_client_socket_win.cc b/net/socket/ssl_client_socket_win.cc
index ce24192..3edad6b 100644
--- a/net/socket/ssl_client_socket_win.cc
+++ b/net/socket/ssl_client_socket_win.cc
@@ -414,8 +414,9 @@ void SSLClientSocketWin::GetSSLInfo(SSLInfo* ssl_info) {
ssl_info->public_key_hashes = server_cert_verify_result_.public_key_hashes;
ssl_info->is_issued_by_known_root =
server_cert_verify_result_.is_issued_by_known_root;
- ssl_info->client_cert_sent = WasDomainBoundCertSent() ||
- (ssl_config_.send_client_cert && ssl_config_.client_cert);
+ ssl_info->client_cert_sent =
+ ssl_config_.send_client_cert && ssl_config_.client_cert;
+ ssl_info->channel_id_sent = WasChannelIDSent();
SecPkgContext_ConnectionInfo connection_info;
SECURITY_STATUS status = QueryContextAttributes(
&ctxt_, SECPKG_ATTR_CONNECTION_INFO, &connection_info);
diff --git a/net/socket/ssl_server_socket_unittest.cc b/net/socket/ssl_server_socket_unittest.cc
index 9cbbb42..b7aae96 100644
--- a/net/socket/ssl_server_socket_unittest.cc
+++ b/net/socket/ssl_server_socket_unittest.cc
@@ -325,7 +325,7 @@ class SSLServerSocketTest : public PlatformTest {
net::SSLConfig ssl_config;
ssl_config.cached_info_enabled = false;
ssl_config.false_start_enabled = false;
- ssl_config.domain_bound_certs_enabled = false;
+ ssl_config.channel_id_enabled = false;
ssl_config.version_min = SSL_PROTOCOL_VERSION_SSL3;
ssl_config.version_max = SSL_PROTOCOL_VERSION_TLS1_1;
diff --git a/net/spdy/spdy_http_stream_spdy3_unittest.cc b/net/spdy/spdy_http_stream_spdy3_unittest.cc
index 6d81a97..06bf475 100644
--- a/net/spdy/spdy_http_stream_spdy3_unittest.cc
+++ b/net/spdy/spdy_http_stream_spdy3_unittest.cc
@@ -65,8 +65,7 @@ class SpdyHttpStreamSpdy3Test : public testing::Test {
void TestSendCredentials(
ServerBoundCertService* server_bound_cert_service,
const std::string& cert,
- const std::string& proof,
- SSLClientCertType type);
+ const std::string& proof);
SpdySessionDependencies session_deps_;
scoped_ptr<OrderedSocketData> data_;
@@ -346,8 +345,7 @@ SpdyFrame* ConstructCredentialRequestFrame(int slot, const GURL& url,
void SpdyHttpStreamSpdy3Test::TestSendCredentials(
ServerBoundCertService* server_bound_cert_service,
const std::string& cert,
- const std::string& proof,
- SSLClientCertType type) {
+ const std::string& proof) {
const char* kUrl1 = "https://www.google.com/";
const char* kUrl2 = "https://www.gmail.com/";
@@ -385,7 +383,7 @@ void SpdyHttpStreamSpdy3Test::TestSendCredentials(
writes, arraysize(writes)));
socket_factory->AddSocketDataProvider(data.get());
SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
- ssl.domain_bound_cert_type = type;
+ ssl.channel_id_sent = true;
ssl.server_bound_cert_service = server_bound_cert_service;
ssl.protocol_negotiated = kProtoSPDY3;
socket_factory->AddSSLSocketDataProvider(&ssl);
@@ -524,8 +522,7 @@ TEST_F(SpdyHttpStreamSpdy3Test, SendCredentialsEC) {
server_bound_cert_service.get(),
&cert, &proof);
- TestSendCredentials(server_bound_cert_service.get(), cert, proof,
- CLIENT_CERT_ECDSA_SIGN);
+ TestSendCredentials(server_bound_cert_service.get(), cert, proof);
sequenced_worker_pool->Shutdown();
}
diff --git a/net/spdy/spdy_session.cc b/net/spdy/spdy_session.cc
index d273291..fb1a653 100644
--- a/net/spdy/spdy_session.cc
+++ b/net/spdy/spdy_session.cc
@@ -315,7 +315,7 @@ net::Error SpdySession::InitializeWithSocket(
}
SSLClientSocket* ssl_socket = GetSSLClientSocket();
- if (ssl_socket && ssl_socket->WasDomainBoundCertSent()) {
+ if (ssl_socket && ssl_socket->WasChannelIDSent()) {
// According to the SPDY spec, the credential associated with the TLS
// connection is stored in slot[1].
credential_state_.SetHasCredential(GURL("https://" +
@@ -352,7 +352,8 @@ bool SpdySession::VerifyDomainAuthentication(const std::string& domain) {
if (!GetSSLInfo(&ssl_info, &was_npn_negotiated, &protocol_negotiated))
return true; // This is not a secure session, so all domains are okay.
- return !ssl_info.client_cert_sent && ssl_info.cert->VerifyNameMatch(domain);
+ return !ssl_info.channel_id_sent && !ssl_info.client_cert_sent &&
+ ssl_info.cert->VerifyNameMatch(domain);
}
int SpdySession::GetPushStream(
@@ -512,7 +513,7 @@ bool SpdySession::NeedsCredentials() const {
SSLClientSocket* ssl_socket = GetSSLClientSocket();
if (ssl_socket->GetNegotiatedProtocol() < kProtoSPDY3)
return false;
- return ssl_socket->WasDomainBoundCertSent();
+ return ssl_socket->WasChannelIDSent();
}
void SpdySession::AddPooledAlias(const HostPortProxyPair& alias) {
@@ -1193,12 +1194,6 @@ ServerBoundCertService* SpdySession::GetServerBoundCertService() const {
return GetSSLClientSocket()->GetServerBoundCertService();
}
-SSLClientCertType SpdySession::GetDomainBoundCertType() const {
- if (!is_secure_)
- return CLIENT_CERT_INVALID_TYPE;
- return GetSSLClientSocket()->domain_bound_cert_type();
-}
-
void SpdySession::OnError(SpdyFramer::SpdyError error_code) {
RecordProtocolErrorHistogram(
static_cast<SpdyProtocolErrorDetails>(error_code));
diff --git a/net/spdy/spdy_session.h b/net/spdy/spdy_session.h
index 5cdf65b..cd2d37c 100644
--- a/net/spdy/spdy_session.h
+++ b/net/spdy/spdy_session.h
@@ -150,8 +150,9 @@ class NET_EXPORT SpdySession : public base::RefCounted<SpdySession>,
// If the session is un-authenticated, then this call always returns true.
// For SSL-based sessions, verifies that the server certificate in use by
// this session provides authentication for the domain and no client
- // certificate was sent to the original server during the SSL handshake.
- // NOTE: This function can have false negatives on some platforms.
+ // certificate or channel ID was sent to the original server during the SSL
+ // handshake. NOTE: This function can have false negatives on some
+ // platforms.
// TODO(wtc): rename this function and the Net.SpdyIPPoolDomainMatch
// histogram because this function does more than verifying domain
// authentication now.
@@ -209,10 +210,6 @@ class NET_EXPORT SpdySession : public base::RefCounted<SpdySession>,
// if server bound certs are not supported in this session.
ServerBoundCertService* GetServerBoundCertService() const;
- // Returns the type of the domain bound cert that was sent, or
- // CLIENT_CERT_INVALID_TYPE if none was sent.
- SSLClientCertType GetDomainBoundCertType() const;
-
// Reset all static settings to initialized values. Used to init test suite.
static void ResetStaticSettingsToInit();
diff --git a/net/spdy/spdy_session_spdy2_unittest.cc b/net/spdy/spdy_session_spdy2_unittest.cc
index eb26194..53720fd 100644
--- a/net/spdy/spdy_session_spdy2_unittest.cc
+++ b/net/spdy/spdy_session_spdy2_unittest.cc
@@ -981,7 +981,7 @@ TEST_F(SpdySessionSpdy2Test, NeedsCredentials) {
session_deps.socket_factory->AddSocketDataProvider(&data);
SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
- ssl.domain_bound_cert_type = CLIENT_CERT_ECDSA_SIGN;
+ ssl.channel_id_sent = true;
ssl.protocol_negotiated = kProtoSPDY2;
session_deps.socket_factory->AddSSLSocketDataProvider(&ssl);
diff --git a/net/spdy/spdy_session_spdy3_unittest.cc b/net/spdy/spdy_session_spdy3_unittest.cc
index 3b8a10f..b43e17e 100644
--- a/net/spdy/spdy_session_spdy3_unittest.cc
+++ b/net/spdy/spdy_session_spdy3_unittest.cc
@@ -986,7 +986,7 @@ TEST_F(SpdySessionSpdy3Test, NeedsCredentials) {
session_deps.socket_factory->AddSocketDataProvider(&data);
SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
- ssl.domain_bound_cert_type = CLIENT_CERT_ECDSA_SIGN;
+ ssl.channel_id_sent = true;
ssl.protocol_negotiated = kProtoSPDY3;
session_deps.socket_factory->AddSSLSocketDataProvider(&ssl);
@@ -1057,7 +1057,7 @@ TEST_F(SpdySessionSpdy3Test, SendCredentials) {
session_deps.socket_factory->AddSocketDataProvider(&data);
SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
- ssl.domain_bound_cert_type = CLIENT_CERT_ECDSA_SIGN;
+ ssl.channel_id_sent = true;
ssl.protocol_negotiated = kProtoSPDY3;
session_deps.socket_factory->AddSSLSocketDataProvider(&ssl);
diff --git a/net/spdy/spdy_stream.cc b/net/spdy/spdy_stream.cc
index 9d0f552..09a184b 100644
--- a/net/spdy/spdy_stream.cc
+++ b/net/spdy/spdy_stream.cc
@@ -621,7 +621,7 @@ int SpdyStream::DoGetDomainBoundCert() {
ServerBoundCertService* sbc_service = session_->GetServerBoundCertService();
DCHECK(sbc_service != NULL);
std::vector<uint8> requested_cert_types;
- requested_cert_types.push_back(session_->GetDomainBoundCertType());
+ requested_cert_types.push_back(CLIENT_CERT_ECDSA_SIGN);
int rv = sbc_service->GetDomainBoundCert(
GetUrl().GetOrigin().spec(), requested_cert_types,
&domain_bound_cert_type_, &domain_bound_private_key_, &domain_bound_cert_,