Index: net/socket/ssl_client_socket_openssl.cc |
diff --git a/net/socket/ssl_client_socket_openssl.cc b/net/socket/ssl_client_socket_openssl.cc |
index 4ff8d438e965b1fdf0b5b7f8b4ecdb75e1d14d66..26c6a1e0ec22f3a7afe90a3bc72751fc98fd8002 100644 |
--- a/net/socket/ssl_client_socket_openssl.cc |
+++ b/net/socket/ssl_client_socket_openssl.cc |
@@ -127,7 +127,6 @@ class SSLClientSocketOpenSSL::SSLContext { |
session_cache_.Reset(ssl_ctx_.get(), kDefaultSessionCacheConfig); |
SSL_CTX_set_cert_verify_callback(ssl_ctx_.get(), CertVerifyCallback, NULL); |
SSL_CTX_set_client_cert_cb(ssl_ctx_.get(), ClientCertCallback); |
- SSL_CTX_set_channel_id_cb(ssl_ctx_.get(), ChannelIDCallback); |
SSL_CTX_set_verify(ssl_ctx_.get(), SSL_VERIFY_PEER, NULL); |
// TODO(kristianm): Only select this if ssl_config_.next_proto is not empty. |
// It would be better if the callback were not a global setting, |
@@ -150,12 +149,6 @@ class SSLClientSocketOpenSSL::SSLContext { |
return socket->ClientCertRequestCallback(ssl, x509, pkey); |
} |
- static void ChannelIDCallback(SSL* ssl, EVP_PKEY** pkey) { |
- SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl); |
- CHECK(socket); |
- socket->ChannelIDRequestCallback(ssl, pkey); |
- } |
- |
static int CertVerifyCallback(X509_STORE_CTX *store_ctx, void *arg) { |
SSL* ssl = reinterpret_cast<SSL*>(X509_STORE_CTX_get_ex_data( |
store_ctx, SSL_get_ex_data_X509_STORE_CTX_idx())); |
@@ -358,7 +351,6 @@ SSLClientSocketOpenSSL::SSLClientSocketOpenSSL( |
trying_cached_session_(false), |
next_handshake_state_(STATE_NONE), |
npn_status_(kNextProtoUnsupported), |
- channel_id_request_return_value_(ERR_UNEXPECTED), |
channel_id_xtn_negotiated_(false), |
net_log_(transport_->socket()->NetLog()) {} |
@@ -476,6 +468,9 @@ void SSLClientSocketOpenSSL::Disconnect() { |
cert_authorities_.clear(); |
cert_key_types_.clear(); |
client_auth_cert_needed_ = false; |
+ |
+ channel_id_xtn_negotiated_ = false; |
+ channel_id_request_handle_.Cancel(); |
} |
bool SSLClientSocketOpenSSL::IsConnected() const { |
@@ -827,9 +822,10 @@ int SSLClientSocketOpenSSL::DoHandshake() { |
int ssl_error = SSL_get_error(ssl_, rv); |
if (ssl_error == SSL_ERROR_WANT_CHANNEL_ID_LOOKUP) { |
- // The server supports TLS channel id and the lookup is asynchronous. |
- // Retrieve the error from the call to |server_bound_cert_service_|. |
- net_error = channel_id_request_return_value_; |
+ // The server supports channel ID. Stop to look one up before returning to |
+ // the handshake. |
+ GotoState(STATE_CHANNEL_ID_LOOKUP); |
+ return OK; |
} else { |
wtc
2014/06/19 22:00:11
Nit: remove the "else" because now the "if" branch
davidben
2014/06/19 22:36:38
Done.
|
net_error = MapOpenSSLError(ssl_error, err_tracer); |
} |
@@ -849,6 +845,50 @@ int SSLClientSocketOpenSSL::DoHandshake() { |
return net_error; |
} |
+int SSLClientSocketOpenSSL::DoChannelIDLookup() { |
+ channel_id_xtn_negotiated_ = true; |
wtc
2014/06/19 22:00:11
Nit: this probably can be moved to line 827.
davidben
2014/06/19 22:36:38
Done.
|
+ |
+ GotoState(STATE_CHANNEL_ID_LOOKUP_COMPLETE); |
+ return server_bound_cert_service_->GetOrCreateDomainBoundCert( |
+ host_and_port_.host(), |
+ &channel_id_private_key_, |
+ &channel_id_cert_, |
+ base::Bind(&SSLClientSocketOpenSSL::OnHandshakeIOComplete, |
+ base::Unretained(this)), |
+ &channel_id_request_handle_); |
+} |
+ |
+int SSLClientSocketOpenSSL::DoChannelIDLookupComplete(int result) { |
+ if (result < 0) |
+ return result; |
+ |
+ DCHECK_LT(0u, channel_id_private_key_.size()); |
+ // Decode key. |
+ std::vector<uint8> encrypted_private_key_info; |
+ std::vector<uint8> subject_public_key_info; |
+ encrypted_private_key_info.assign( |
+ channel_id_private_key_.data(), |
+ channel_id_private_key_.data() + channel_id_private_key_.size()); |
+ subject_public_key_info.assign( |
+ channel_id_cert_.data(), |
+ channel_id_cert_.data() + channel_id_cert_.size()); |
+ scoped_ptr<crypto::ECPrivateKey> ec_private_key( |
+ crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( |
+ ServerBoundCertService::kEPKIPassword, |
+ encrypted_private_key_info, |
+ subject_public_key_info)); |
wtc
2014/06/19 22:00:11
Nit: indentation is wrong.
davidben
2014/06/19 22:36:38
Done.
|
+ if (!ec_private_key) { |
+ LOG(ERROR) << "Failed to import Channel ID."; |
+ return ERR_CHANNEL_ID_IMPORT_FAILED; |
+ } |
+ set_channel_id_sent(true); |
+ SSL_set1_tls_channel_id(ssl_, ec_private_key->key()); |
wtc
2014/06/19 22:00:11
I assume SSL_set1_tls_channel_id will call EVP_PKE
davidben
2014/06/19 22:36:38
Yeah. I think set1 vs set may be the OpenSSL conve
|
+ |
+ // Return to the handshake. |
+ GotoState(STATE_HANDSHAKE); |
+ return OK; |
+} |
+ |
int SSLClientSocketOpenSSL::DoVerifyCert(int result) { |
DCHECK(server_cert_.get()); |
GotoState(STATE_VERIFY_CERT_COMPLETE); |
@@ -993,6 +1033,13 @@ int SSLClientSocketOpenSSL::DoHandshakeLoop(int last_io_result) { |
case STATE_HANDSHAKE: |
rv = DoHandshake(); |
break; |
+ case STATE_CHANNEL_ID_LOOKUP: |
+ DCHECK_EQ(OK, rv); |
+ rv = DoChannelIDLookup(); |
+ break; |
+ case STATE_CHANNEL_ID_LOOKUP_COMPLETE: |
+ rv = DoChannelIDLookupComplete(rv); |
+ break; |
case STATE_VERIFY_CERT: |
DCHECK(rv == OK); |
wtc
2014/06/19 22:00:11
Please also change this to DCHECK_EQ(OK, rv) for c
davidben
2014/06/19 22:36:38
Done.
|
rv = DoVerifyCert(rv); |
@@ -1321,46 +1368,6 @@ int SSLClientSocketOpenSSL::ClientCertRequestCallback(SSL* ssl, |
return 0; |
} |
-void SSLClientSocketOpenSSL::ChannelIDRequestCallback(SSL* ssl, |
- EVP_PKEY** pkey) { |
- DVLOG(3) << "OpenSSL ChannelIDRequestCallback called"; |
- DCHECK_EQ(ssl, ssl_); |
- DCHECK(!*pkey); |
- |
- channel_id_xtn_negotiated_ = true; |
- if (!channel_id_private_key_.size()) { |
- channel_id_request_return_value_ = |
- server_bound_cert_service_->GetOrCreateDomainBoundCert( |
- host_and_port_.host(), |
- &channel_id_private_key_, |
- &channel_id_cert_, |
- base::Bind(&SSLClientSocketOpenSSL::OnHandshakeIOComplete, |
- base::Unretained(this)), |
- &channel_id_request_handle_); |
- if (channel_id_request_return_value_ != OK) |
- return; |
- } |
- |
- // Decode key. |
- std::vector<uint8> encrypted_private_key_info; |
- std::vector<uint8> subject_public_key_info; |
- encrypted_private_key_info.assign( |
- channel_id_private_key_.data(), |
- channel_id_private_key_.data() + channel_id_private_key_.size()); |
- subject_public_key_info.assign( |
- channel_id_cert_.data(), |
- channel_id_cert_.data() + channel_id_cert_.size()); |
- scoped_ptr<crypto::ECPrivateKey> ec_private_key( |
- crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( |
- ServerBoundCertService::kEPKIPassword, |
- encrypted_private_key_info, |
- subject_public_key_info)); |
- if (!ec_private_key) |
- return; |
- set_channel_id_sent(true); |
- *pkey = EVP_PKEY_dup(ec_private_key->key()); |
-} |
- |
int SSLClientSocketOpenSSL::CertVerifyCallback(X509_STORE_CTX* store_ctx) { |
if (!completed_handshake_) { |
// If the first handshake hasn't completed then we accept any certificates |