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

Side by Side 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: Add error code. 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // OpenSSL binding for SSLClientSocket. The class layout and general principle 5 // OpenSSL binding for SSLClientSocket. The class layout and general principle
6 // of operation is derived from SSLClientSocketNSS. 6 // of operation is derived from SSLClientSocketNSS.
7 7
8 #include "net/socket/ssl_client_socket_openssl.h" 8 #include "net/socket/ssl_client_socket_openssl.h"
9 9
10 #include <openssl/err.h> 10 #include <openssl/err.h>
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
120 friend struct DefaultSingletonTraits<SSLContext>; 120 friend struct DefaultSingletonTraits<SSLContext>;
121 121
122 SSLContext() { 122 SSLContext() {
123 crypto::EnsureOpenSSLInit(); 123 crypto::EnsureOpenSSLInit();
124 ssl_socket_data_index_ = SSL_get_ex_new_index(0, 0, 0, 0, 0); 124 ssl_socket_data_index_ = SSL_get_ex_new_index(0, 0, 0, 0, 0);
125 DCHECK_NE(ssl_socket_data_index_, -1); 125 DCHECK_NE(ssl_socket_data_index_, -1);
126 ssl_ctx_.reset(SSL_CTX_new(SSLv23_client_method())); 126 ssl_ctx_.reset(SSL_CTX_new(SSLv23_client_method()));
127 session_cache_.Reset(ssl_ctx_.get(), kDefaultSessionCacheConfig); 127 session_cache_.Reset(ssl_ctx_.get(), kDefaultSessionCacheConfig);
128 SSL_CTX_set_cert_verify_callback(ssl_ctx_.get(), CertVerifyCallback, NULL); 128 SSL_CTX_set_cert_verify_callback(ssl_ctx_.get(), CertVerifyCallback, NULL);
129 SSL_CTX_set_client_cert_cb(ssl_ctx_.get(), ClientCertCallback); 129 SSL_CTX_set_client_cert_cb(ssl_ctx_.get(), ClientCertCallback);
130 SSL_CTX_set_channel_id_cb(ssl_ctx_.get(), ChannelIDCallback);
131 SSL_CTX_set_verify(ssl_ctx_.get(), SSL_VERIFY_PEER, NULL); 130 SSL_CTX_set_verify(ssl_ctx_.get(), SSL_VERIFY_PEER, NULL);
132 // TODO(kristianm): Only select this if ssl_config_.next_proto is not empty. 131 // TODO(kristianm): Only select this if ssl_config_.next_proto is not empty.
133 // It would be better if the callback were not a global setting, 132 // It would be better if the callback were not a global setting,
134 // but that is an OpenSSL issue. 133 // but that is an OpenSSL issue.
135 SSL_CTX_set_next_proto_select_cb(ssl_ctx_.get(), SelectNextProtoCallback, 134 SSL_CTX_set_next_proto_select_cb(ssl_ctx_.get(), SelectNextProtoCallback,
136 NULL); 135 NULL);
137 } 136 }
138 137
139 static std::string GetSessionCacheKey(const SSL* ssl) { 138 static std::string GetSessionCacheKey(const SSL* ssl) {
140 SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl); 139 SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl);
141 DCHECK(socket); 140 DCHECK(socket);
142 return GetSocketSessionCacheKey(*socket); 141 return GetSocketSessionCacheKey(*socket);
143 } 142 }
144 143
145 static SSLSessionCacheOpenSSL::Config kDefaultSessionCacheConfig; 144 static SSLSessionCacheOpenSSL::Config kDefaultSessionCacheConfig;
146 145
147 static int ClientCertCallback(SSL* ssl, X509** x509, EVP_PKEY** pkey) { 146 static int ClientCertCallback(SSL* ssl, X509** x509, EVP_PKEY** pkey) {
148 SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl); 147 SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl);
149 CHECK(socket); 148 CHECK(socket);
150 return socket->ClientCertRequestCallback(ssl, x509, pkey); 149 return socket->ClientCertRequestCallback(ssl, x509, pkey);
151 } 150 }
152 151
153 static void ChannelIDCallback(SSL* ssl, EVP_PKEY** pkey) {
154 SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl);
155 CHECK(socket);
156 socket->ChannelIDRequestCallback(ssl, pkey);
157 }
158
159 static int CertVerifyCallback(X509_STORE_CTX *store_ctx, void *arg) { 152 static int CertVerifyCallback(X509_STORE_CTX *store_ctx, void *arg) {
160 SSL* ssl = reinterpret_cast<SSL*>(X509_STORE_CTX_get_ex_data( 153 SSL* ssl = reinterpret_cast<SSL*>(X509_STORE_CTX_get_ex_data(
161 store_ctx, SSL_get_ex_data_X509_STORE_CTX_idx())); 154 store_ctx, SSL_get_ex_data_X509_STORE_CTX_idx()));
162 SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl); 155 SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl);
163 CHECK(socket); 156 CHECK(socket);
164 157
165 return socket->CertVerifyCallback(store_ctx); 158 return socket->CertVerifyCallback(store_ctx);
166 } 159 }
167 160
168 static int SelectNextProtoCallback(SSL* ssl, 161 static int SelectNextProtoCallback(SSL* ssl,
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
351 server_bound_cert_service_(context.server_bound_cert_service), 344 server_bound_cert_service_(context.server_bound_cert_service),
352 ssl_(NULL), 345 ssl_(NULL),
353 transport_bio_(NULL), 346 transport_bio_(NULL),
354 transport_(transport_socket.Pass()), 347 transport_(transport_socket.Pass()),
355 host_and_port_(host_and_port), 348 host_and_port_(host_and_port),
356 ssl_config_(ssl_config), 349 ssl_config_(ssl_config),
357 ssl_session_cache_shard_(context.ssl_session_cache_shard), 350 ssl_session_cache_shard_(context.ssl_session_cache_shard),
358 trying_cached_session_(false), 351 trying_cached_session_(false),
359 next_handshake_state_(STATE_NONE), 352 next_handshake_state_(STATE_NONE),
360 npn_status_(kNextProtoUnsupported), 353 npn_status_(kNextProtoUnsupported),
361 channel_id_request_return_value_(ERR_UNEXPECTED),
362 channel_id_xtn_negotiated_(false), 354 channel_id_xtn_negotiated_(false),
363 net_log_(transport_->socket()->NetLog()) {} 355 net_log_(transport_->socket()->NetLog()) {}
364 356
365 SSLClientSocketOpenSSL::~SSLClientSocketOpenSSL() { 357 SSLClientSocketOpenSSL::~SSLClientSocketOpenSSL() {
366 Disconnect(); 358 Disconnect();
367 } 359 }
368 360
369 void SSLClientSocketOpenSSL::GetSSLCertRequestInfo( 361 void SSLClientSocketOpenSSL::GetSSLCertRequestInfo(
370 SSLCertRequestInfo* cert_request_info) { 362 SSLCertRequestInfo* cert_request_info) {
371 cert_request_info->host_and_port = host_and_port_; 363 cert_request_info->host_and_port = host_and_port_;
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
469 461
470 pending_read_error_ = kNoPendingReadResult; 462 pending_read_error_ = kNoPendingReadResult;
471 transport_write_error_ = OK; 463 transport_write_error_ = OK;
472 464
473 server_cert_verify_result_.Reset(); 465 server_cert_verify_result_.Reset();
474 completed_handshake_ = false; 466 completed_handshake_ = false;
475 467
476 cert_authorities_.clear(); 468 cert_authorities_.clear();
477 cert_key_types_.clear(); 469 cert_key_types_.clear();
478 client_auth_cert_needed_ = false; 470 client_auth_cert_needed_ = false;
471
472 channel_id_xtn_negotiated_ = false;
473 channel_id_request_handle_.Cancel();
479 } 474 }
480 475
481 bool SSLClientSocketOpenSSL::IsConnected() const { 476 bool SSLClientSocketOpenSSL::IsConnected() const {
482 // If the handshake has not yet completed. 477 // If the handshake has not yet completed.
483 if (!completed_handshake_) 478 if (!completed_handshake_)
484 return false; 479 return false;
485 // If an asynchronous operation is still pending. 480 // If an asynchronous operation is still pending.
486 if (user_read_buf_.get() || user_write_buf_.get()) 481 if (user_read_buf_.get() || user_write_buf_.get())
487 return true; 482 return true;
488 483
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after
820 DCHECK(got_cert); 815 DCHECK(got_cert);
821 net_log_.AddEvent( 816 net_log_.AddEvent(
822 NetLog::TYPE_SSL_CERTIFICATES_RECEIVED, 817 NetLog::TYPE_SSL_CERTIFICATES_RECEIVED,
823 base::Bind(&NetLogX509CertificateCallback, 818 base::Bind(&NetLogX509CertificateCallback,
824 base::Unretained(server_cert_.get()))); 819 base::Unretained(server_cert_.get())));
825 GotoState(STATE_VERIFY_CERT); 820 GotoState(STATE_VERIFY_CERT);
826 } else { 821 } else {
827 int ssl_error = SSL_get_error(ssl_, rv); 822 int ssl_error = SSL_get_error(ssl_, rv);
828 823
829 if (ssl_error == SSL_ERROR_WANT_CHANNEL_ID_LOOKUP) { 824 if (ssl_error == SSL_ERROR_WANT_CHANNEL_ID_LOOKUP) {
830 // The server supports TLS channel id and the lookup is asynchronous. 825 // The server supports channel ID. Stop to look one up before returning to
831 // Retrieve the error from the call to |server_bound_cert_service_|. 826 // the handshake.
832 net_error = channel_id_request_return_value_; 827 GotoState(STATE_CHANNEL_ID_LOOKUP);
828 return OK;
833 } else { 829 } 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.
834 net_error = MapOpenSSLError(ssl_error, err_tracer); 830 net_error = MapOpenSSLError(ssl_error, err_tracer);
835 } 831 }
836 832
837 // If not done, stay in this state 833 // If not done, stay in this state
838 if (net_error == ERR_IO_PENDING) { 834 if (net_error == ERR_IO_PENDING) {
839 GotoState(STATE_HANDSHAKE); 835 GotoState(STATE_HANDSHAKE);
840 } else { 836 } else {
841 LOG(ERROR) << "handshake failed; returned " << rv 837 LOG(ERROR) << "handshake failed; returned " << rv
842 << ", SSL error code " << ssl_error 838 << ", SSL error code " << ssl_error
843 << ", net_error " << net_error; 839 << ", net_error " << net_error;
844 net_log_.AddEvent( 840 net_log_.AddEvent(
845 NetLog::TYPE_SSL_HANDSHAKE_ERROR, 841 NetLog::TYPE_SSL_HANDSHAKE_ERROR,
846 CreateNetLogSSLErrorCallback(net_error, ssl_error)); 842 CreateNetLogSSLErrorCallback(net_error, ssl_error));
847 } 843 }
848 } 844 }
849 return net_error; 845 return net_error;
850 } 846 }
851 847
848 int SSLClientSocketOpenSSL::DoChannelIDLookup() {
849 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.
850
851 GotoState(STATE_CHANNEL_ID_LOOKUP_COMPLETE);
852 return server_bound_cert_service_->GetOrCreateDomainBoundCert(
853 host_and_port_.host(),
854 &channel_id_private_key_,
855 &channel_id_cert_,
856 base::Bind(&SSLClientSocketOpenSSL::OnHandshakeIOComplete,
857 base::Unretained(this)),
858 &channel_id_request_handle_);
859 }
860
861 int SSLClientSocketOpenSSL::DoChannelIDLookupComplete(int result) {
862 if (result < 0)
863 return result;
864
865 DCHECK_LT(0u, channel_id_private_key_.size());
866 // Decode key.
867 std::vector<uint8> encrypted_private_key_info;
868 std::vector<uint8> subject_public_key_info;
869 encrypted_private_key_info.assign(
870 channel_id_private_key_.data(),
871 channel_id_private_key_.data() + channel_id_private_key_.size());
872 subject_public_key_info.assign(
873 channel_id_cert_.data(),
874 channel_id_cert_.data() + channel_id_cert_.size());
875 scoped_ptr<crypto::ECPrivateKey> ec_private_key(
876 crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo(
877 ServerBoundCertService::kEPKIPassword,
878 encrypted_private_key_info,
879 subject_public_key_info));
wtc 2014/06/19 22:00:11 Nit: indentation is wrong.
davidben 2014/06/19 22:36:38 Done.
880 if (!ec_private_key) {
881 LOG(ERROR) << "Failed to import Channel ID.";
882 return ERR_CHANNEL_ID_IMPORT_FAILED;
883 }
884 set_channel_id_sent(true);
885 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
886
887 // Return to the handshake.
888 GotoState(STATE_HANDSHAKE);
889 return OK;
890 }
891
852 int SSLClientSocketOpenSSL::DoVerifyCert(int result) { 892 int SSLClientSocketOpenSSL::DoVerifyCert(int result) {
853 DCHECK(server_cert_.get()); 893 DCHECK(server_cert_.get());
854 GotoState(STATE_VERIFY_CERT_COMPLETE); 894 GotoState(STATE_VERIFY_CERT_COMPLETE);
855 895
856 CertStatus cert_status; 896 CertStatus cert_status;
857 if (ssl_config_.IsAllowedBadCert(server_cert_.get(), &cert_status)) { 897 if (ssl_config_.IsAllowedBadCert(server_cert_.get(), &cert_status)) {
858 VLOG(1) << "Received an expected bad cert with status: " << cert_status; 898 VLOG(1) << "Received an expected bad cert with status: " << cert_status;
859 server_cert_verify_result_.Reset(); 899 server_cert_verify_result_.Reset();
860 server_cert_verify_result_.cert_status = cert_status; 900 server_cert_verify_result_.cert_status = cert_status;
861 server_cert_verify_result_.verified_cert = server_cert_; 901 server_cert_verify_result_.verified_cert = server_cert_;
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
986 // (This is a quirk carried over from the windows 1026 // (This is a quirk carried over from the windows
987 // implementation. It makes reading the logs a bit harder.) 1027 // implementation. It makes reading the logs a bit harder.)
988 // State handlers can and often do call GotoState just 1028 // State handlers can and often do call GotoState just
989 // to stay in the current state. 1029 // to stay in the current state.
990 State state = next_handshake_state_; 1030 State state = next_handshake_state_;
991 GotoState(STATE_NONE); 1031 GotoState(STATE_NONE);
992 switch (state) { 1032 switch (state) {
993 case STATE_HANDSHAKE: 1033 case STATE_HANDSHAKE:
994 rv = DoHandshake(); 1034 rv = DoHandshake();
995 break; 1035 break;
1036 case STATE_CHANNEL_ID_LOOKUP:
1037 DCHECK_EQ(OK, rv);
1038 rv = DoChannelIDLookup();
1039 break;
1040 case STATE_CHANNEL_ID_LOOKUP_COMPLETE:
1041 rv = DoChannelIDLookupComplete(rv);
1042 break;
996 case STATE_VERIFY_CERT: 1043 case STATE_VERIFY_CERT:
997 DCHECK(rv == OK); 1044 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.
998 rv = DoVerifyCert(rv); 1045 rv = DoVerifyCert(rv);
999 break; 1046 break;
1000 case STATE_VERIFY_CERT_COMPLETE: 1047 case STATE_VERIFY_CERT_COMPLETE:
1001 rv = DoVerifyCertComplete(rv); 1048 rv = DoVerifyCertComplete(rv);
1002 break; 1049 break;
1003 case STATE_NONE: 1050 case STATE_NONE:
1004 default: 1051 default:
1005 rv = ERR_UNEXPECTED; 1052 rv = ERR_UNEXPECTED;
1006 NOTREACHED() << "unexpected state" << state; 1053 NOTREACHED() << "unexpected state" << state;
1007 break; 1054 break;
(...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after
1314 #else // !defined(USE_OPENSSL_CERTS) 1361 #else // !defined(USE_OPENSSL_CERTS)
1315 // OS handling of client certificates is not yet implemented. 1362 // OS handling of client certificates is not yet implemented.
1316 NOTIMPLEMENTED(); 1363 NOTIMPLEMENTED();
1317 #endif // defined(USE_OPENSSL_CERTS) 1364 #endif // defined(USE_OPENSSL_CERTS)
1318 } 1365 }
1319 1366
1320 // Send no client certificate. 1367 // Send no client certificate.
1321 return 0; 1368 return 0;
1322 } 1369 }
1323 1370
1324 void SSLClientSocketOpenSSL::ChannelIDRequestCallback(SSL* ssl,
1325 EVP_PKEY** pkey) {
1326 DVLOG(3) << "OpenSSL ChannelIDRequestCallback called";
1327 DCHECK_EQ(ssl, ssl_);
1328 DCHECK(!*pkey);
1329
1330 channel_id_xtn_negotiated_ = true;
1331 if (!channel_id_private_key_.size()) {
1332 channel_id_request_return_value_ =
1333 server_bound_cert_service_->GetOrCreateDomainBoundCert(
1334 host_and_port_.host(),
1335 &channel_id_private_key_,
1336 &channel_id_cert_,
1337 base::Bind(&SSLClientSocketOpenSSL::OnHandshakeIOComplete,
1338 base::Unretained(this)),
1339 &channel_id_request_handle_);
1340 if (channel_id_request_return_value_ != OK)
1341 return;
1342 }
1343
1344 // Decode key.
1345 std::vector<uint8> encrypted_private_key_info;
1346 std::vector<uint8> subject_public_key_info;
1347 encrypted_private_key_info.assign(
1348 channel_id_private_key_.data(),
1349 channel_id_private_key_.data() + channel_id_private_key_.size());
1350 subject_public_key_info.assign(
1351 channel_id_cert_.data(),
1352 channel_id_cert_.data() + channel_id_cert_.size());
1353 scoped_ptr<crypto::ECPrivateKey> ec_private_key(
1354 crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo(
1355 ServerBoundCertService::kEPKIPassword,
1356 encrypted_private_key_info,
1357 subject_public_key_info));
1358 if (!ec_private_key)
1359 return;
1360 set_channel_id_sent(true);
1361 *pkey = EVP_PKEY_dup(ec_private_key->key());
1362 }
1363
1364 int SSLClientSocketOpenSSL::CertVerifyCallback(X509_STORE_CTX* store_ctx) { 1371 int SSLClientSocketOpenSSL::CertVerifyCallback(X509_STORE_CTX* store_ctx) {
1365 if (!completed_handshake_) { 1372 if (!completed_handshake_) {
1366 // If the first handshake hasn't completed then we accept any certificates 1373 // If the first handshake hasn't completed then we accept any certificates
1367 // because we verify after the handshake. 1374 // because we verify after the handshake.
1368 return 1; 1375 return 1;
1369 } 1376 }
1370 1377
1371 CHECK(server_cert_.get()); 1378 CHECK(server_cert_.get());
1372 1379
1373 PeerCertificateChain chain(store_ctx->untrusted); 1380 PeerCertificateChain chain(store_ctx->untrusted);
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
1430 DVLOG(2) << "next protocol: '" << npn_proto_ << "' status: " << npn_status_; 1437 DVLOG(2) << "next protocol: '" << npn_proto_ << "' status: " << npn_status_;
1431 return SSL_TLSEXT_ERR_OK; 1438 return SSL_TLSEXT_ERR_OK;
1432 } 1439 }
1433 1440
1434 scoped_refptr<X509Certificate> 1441 scoped_refptr<X509Certificate>
1435 SSLClientSocketOpenSSL::GetUnverifiedServerCertificateChain() const { 1442 SSLClientSocketOpenSSL::GetUnverifiedServerCertificateChain() const {
1436 return server_cert_; 1443 return server_cert_;
1437 } 1444 }
1438 1445
1439 } // namespace net 1446 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698