diff options
author | mattm@chromium.org <mattm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-26 02:13:49 +0000 |
---|---|---|
committer | mattm@chromium.org <mattm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-26 02:13:49 +0000 |
commit | 6b4903fd14ab76dfbe872f6c6d7184c428d67260 (patch) | |
tree | bc76f151a44c88e1f35ae79df1dfb9ef7e4c3bae | |
parent | 9cd45640442bb7b639d2675363b2239ff183a092 (diff) | |
download | chromium_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
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_, |