Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(178)

Unified Diff: net/socket/ssl_client_socket_openssl.cc

Issue 338093012: Fix SSLClientSocketOpenSSL error-handling for Channel ID. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: wtc comment Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/socket/ssl_client_socket_openssl.h ('k') | net/socket/ssl_client_socket_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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..68d7e5f50d0ec4469b0d44195c60efa275078e25 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,13 +822,15 @@ 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_;
- } else {
- net_error = MapOpenSSLError(ssl_error, err_tracer);
+ // The server supports channel ID. Stop to look one up before returning to
+ // the handshake.
+ channel_id_xtn_negotiated_ = true;
+ GotoState(STATE_CHANNEL_ID_LOOKUP);
+ return OK;
}
+ net_error = MapOpenSSLError(ssl_error, err_tracer);
+
// If not done, stay in this state
if (net_error == ERR_IO_PENDING) {
GotoState(STATE_HANDSHAKE);
@@ -849,6 +846,57 @@ int SSLClientSocketOpenSSL::DoHandshake() {
return net_error;
}
+int SSLClientSocketOpenSSL::DoChannelIDLookup() {
+ 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));
+ if (!ec_private_key) {
+ LOG(ERROR) << "Failed to import Channel ID.";
+ return ERR_CHANNEL_ID_IMPORT_FAILED;
+ }
+
+ // Hand the key to OpenSSL. Check for error in case OpenSSL rejects the key
+ // type.
+ crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
+ int rv = SSL_set1_tls_channel_id(ssl_, ec_private_key->key());
+ if (!rv) {
+ LOG(ERROR) << "Failed to set Channel ID.";
+ int err = SSL_get_error(ssl_, rv);
+ return MapOpenSSLError(err, err_tracer);
+ }
+
+ // Return to the handshake.
+ set_channel_id_sent(true);
+ GotoState(STATE_HANDSHAKE);
+ return OK;
+}
+
int SSLClientSocketOpenSSL::DoVerifyCert(int result) {
DCHECK(server_cert_.get());
GotoState(STATE_VERIFY_CERT_COMPLETE);
@@ -993,8 +1041,15 @@ 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);
+ DCHECK_EQ(OK, rv);
rv = DoVerifyCert(rv);
break;
case STATE_VERIFY_CERT_COMPLETE:
@@ -1321,46 +1376,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
« no previous file with comments | « net/socket/ssl_client_socket_openssl.h ('k') | net/socket/ssl_client_socket_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698