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

Side by Side Diff: net/socket/ssl_client_socket_impl.cc

Issue 2076363002: Introduce the ability to require CT for specific hosts (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@require_ct_enforcer
Patch Set: Android is weird Created 4 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
« no previous file with comments | « net/socket/ssl_client_socket_impl.h ('k') | net/socket/ssl_client_socket_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 #include "net/socket/ssl_client_socket_impl.h" 5 #include "net/socket/ssl_client_socket_impl.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <openssl/bio.h> 8 #include <openssl/bio.h>
9 #include <openssl/bytestring.h> 9 #include <openssl/bytestring.h>
10 #include <openssl/err.h> 10 #include <openssl/err.h>
(...skipping 1309 matching lines...) Expand 10 before | Expand all | Expand 10 after
1320 if (!start_cert_verification_time_.is_null()) { 1320 if (!start_cert_verification_time_.is_null()) {
1321 base::TimeDelta verify_time = 1321 base::TimeDelta verify_time =
1322 base::TimeTicks::Now() - start_cert_verification_time_; 1322 base::TimeTicks::Now() - start_cert_verification_time_;
1323 if (result == OK) { 1323 if (result == OK) {
1324 UMA_HISTOGRAM_TIMES("Net.SSLCertVerificationTime", verify_time); 1324 UMA_HISTOGRAM_TIMES("Net.SSLCertVerificationTime", verify_time);
1325 } else { 1325 } else {
1326 UMA_HISTOGRAM_TIMES("Net.SSLCertVerificationTimeError", verify_time); 1326 UMA_HISTOGRAM_TIMES("Net.SSLCertVerificationTimeError", verify_time);
1327 } 1327 }
1328 } 1328 }
1329 1329
1330 // If the connection was good, check HPKP and CT status simultaneously,
1331 // but prefer to treat the HPKP error as more serious, if there was one.
1330 const CertStatus cert_status = server_cert_verify_result_.cert_status; 1332 const CertStatus cert_status = server_cert_verify_result_.cert_status;
1331 if (transport_security_state_ && 1333 if ((result == OK ||
1332 (result == OK ||
1333 (IsCertificateError(result) && IsCertStatusMinorError(cert_status)))) { 1334 (IsCertificateError(result) && IsCertStatusMinorError(cert_status)))) {
1335 int ct_result = VerifyCT();
1334 TransportSecurityState::PKPStatus pin_validity = 1336 TransportSecurityState::PKPStatus pin_validity =
1335 transport_security_state_->CheckPublicKeyPins( 1337 transport_security_state_->CheckPublicKeyPins(
1336 host_and_port_, server_cert_verify_result_.is_issued_by_known_root, 1338 host_and_port_, server_cert_verify_result_.is_issued_by_known_root,
1337 server_cert_verify_result_.public_key_hashes, server_cert_.get(), 1339 server_cert_verify_result_.public_key_hashes, server_cert_.get(),
1338 server_cert_verify_result_.verified_cert.get(), 1340 server_cert_verify_result_.verified_cert.get(),
1339 TransportSecurityState::ENABLE_PIN_REPORTS, &pinning_failure_log_); 1341 TransportSecurityState::ENABLE_PIN_REPORTS, &pinning_failure_log_);
1340 switch (pin_validity) { 1342 switch (pin_validity) {
1341 case TransportSecurityState::PKPStatus::VIOLATED: 1343 case TransportSecurityState::PKPStatus::VIOLATED:
1342 server_cert_verify_result_.cert_status |= 1344 server_cert_verify_result_.cert_status |=
1343 CERT_STATUS_PINNED_KEY_MISSING; 1345 CERT_STATUS_PINNED_KEY_MISSING;
1344 result = ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN; 1346 result = ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN;
1345 break; 1347 break;
1346 case TransportSecurityState::PKPStatus::BYPASSED: 1348 case TransportSecurityState::PKPStatus::BYPASSED:
1347 pkp_bypassed_ = true; 1349 pkp_bypassed_ = true;
1348 // Fall through. 1350 // Fall through.
1349 case TransportSecurityState::PKPStatus::OK: 1351 case TransportSecurityState::PKPStatus::OK:
1350 // Do nothing. 1352 // Do nothing.
1351 break; 1353 break;
1352 } 1354 }
1355 if (result != ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN && ct_result != OK)
1356 result = ct_result;
1353 } 1357 }
1354 1358
1355 if (result == OK) { 1359 if (result == OK) {
1356 // Only check Certificate Transparency if there were no other errors with
1357 // the connection.
1358 VerifyCT();
1359
1360 DCHECK(!certificate_verified_); 1360 DCHECK(!certificate_verified_);
1361 certificate_verified_ = true; 1361 certificate_verified_ = true;
1362 MaybeCacheSession(); 1362 MaybeCacheSession();
1363 } 1363 }
1364 1364
1365 completed_connect_ = true; 1365 completed_connect_ = true;
1366 // Exit DoHandshakeLoop and return the result to the caller to Connect. 1366 // Exit DoHandshakeLoop and return the result to the caller to Connect.
1367 DCHECK_EQ(STATE_NONE, next_handshake_state_); 1367 DCHECK_EQ(STATE_NONE, next_handshake_state_);
1368 return result; 1368 return result;
1369 } 1369 }
1370 1370
1371 void SSLClientSocketImpl::DoConnectCallback(int rv) { 1371 void SSLClientSocketImpl::DoConnectCallback(int rv) {
1372 if (!user_connect_callback_.is_null()) { 1372 if (!user_connect_callback_.is_null()) {
1373 CompletionCallback c = user_connect_callback_; 1373 CompletionCallback c = user_connect_callback_;
1374 user_connect_callback_.Reset(); 1374 user_connect_callback_.Reset();
1375 c.Run(rv > OK ? OK : rv); 1375 c.Run(rv > OK ? OK : rv);
1376 } 1376 }
1377 } 1377 }
1378 1378
1379 void SSLClientSocketImpl::UpdateServerCert() { 1379 void SSLClientSocketImpl::UpdateServerCert() {
1380 server_cert_chain_->Reset(SSL_get_peer_cert_chain(ssl_)); 1380 server_cert_chain_->Reset(SSL_get_peer_cert_chain(ssl_));
1381 server_cert_ = server_cert_chain_->AsOSChain(); 1381 server_cert_ = server_cert_chain_->AsOSChain();
1382 if (server_cert_.get()) { 1382 if (server_cert_.get()) {
1383 net_log_.AddEvent(NetLog::TYPE_SSL_CERTIFICATES_RECEIVED, 1383 net_log_.AddEvent(NetLog::TYPE_SSL_CERTIFICATES_RECEIVED,
1384 base::Bind(&NetLogX509CertificateCallback, 1384 base::Bind(&NetLogX509CertificateCallback,
1385 base::Unretained(server_cert_.get()))); 1385 base::Unretained(server_cert_.get())));
1386 } 1386 }
1387 } 1387 }
1388 1388
1389 void SSLClientSocketImpl::VerifyCT() {
1390 const uint8_t* ocsp_response_raw;
1391 size_t ocsp_response_len;
1392 SSL_get0_ocsp_response(ssl_, &ocsp_response_raw, &ocsp_response_len);
1393 std::string ocsp_response;
1394 if (ocsp_response_len > 0) {
1395 ocsp_response.assign(reinterpret_cast<const char*>(ocsp_response_raw),
1396 ocsp_response_len);
1397 }
1398
1399 const uint8_t* sct_list_raw;
1400 size_t sct_list_len;
1401 SSL_get0_signed_cert_timestamp_list(ssl_, &sct_list_raw, &sct_list_len);
1402 std::string sct_list;
1403 if (sct_list_len > 0)
1404 sct_list.assign(reinterpret_cast<const char*>(sct_list_raw), sct_list_len);
1405
1406 // Note that this is a completely synchronous operation: The CT Log Verifier
1407 // gets all the data it needs for SCT verification and does not do any
1408 // external communication.
1409 cert_transparency_verifier_->Verify(
1410 server_cert_verify_result_.verified_cert.get(), ocsp_response, sct_list,
1411 &ct_verify_result_, net_log_);
1412
1413 ct_verify_result_.ct_policies_applied = true;
1414 ct_verify_result_.ev_policy_compliance =
1415 ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY;
1416 if (server_cert_verify_result_.cert_status & CERT_STATUS_IS_EV) {
1417 scoped_refptr<ct::EVCertsWhitelist> ev_whitelist =
1418 SSLConfigService::GetEVCertsWhitelist();
1419 ct::EVPolicyCompliance ev_policy_compliance =
1420 policy_enforcer_->DoesConformToCTEVPolicy(
1421 server_cert_verify_result_.verified_cert.get(), ev_whitelist.get(),
1422 ct_verify_result_.verified_scts, net_log_);
1423 ct_verify_result_.ev_policy_compliance = ev_policy_compliance;
1424 if (ev_policy_compliance !=
1425 ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY &&
1426 ev_policy_compliance !=
1427 ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_WHITELIST &&
1428 ev_policy_compliance !=
1429 ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_SCTS) {
1430 server_cert_verify_result_.cert_status |=
1431 CERT_STATUS_CT_COMPLIANCE_FAILED;
1432 server_cert_verify_result_.cert_status &= ~CERT_STATUS_IS_EV;
1433 }
1434 }
1435 ct_verify_result_.cert_policy_compliance =
1436 policy_enforcer_->DoesConformToCertPolicy(
1437 server_cert_verify_result_.verified_cert.get(),
1438 ct_verify_result_.verified_scts, net_log_);
1439 }
1440
1441 void SSLClientSocketImpl::OnHandshakeIOComplete(int result) { 1389 void SSLClientSocketImpl::OnHandshakeIOComplete(int result) {
1442 int rv = DoHandshakeLoop(result); 1390 int rv = DoHandshakeLoop(result);
1443 if (rv != ERR_IO_PENDING) { 1391 if (rv != ERR_IO_PENDING) {
1444 LogConnectEndEvent(rv); 1392 LogConnectEndEvent(rv);
1445 DoConnectCallback(rv); 1393 DoConnectCallback(rv);
1446 } 1394 }
1447 } 1395 }
1448 1396
1449 void SSLClientSocketImpl::OnSendComplete(int result) { 1397 void SSLClientSocketImpl::OnSendComplete(int result) {
1450 if (next_handshake_state_ == STATE_HANDSHAKE) { 1398 if (next_handshake_state_ == STATE_HANDSHAKE) {
(...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after
1819 } else { 1767 } else {
1820 bytes_read = result; 1768 bytes_read = result;
1821 } 1769 }
1822 DCHECK_GE(recv_buffer_->RemainingCapacity(), bytes_read); 1770 DCHECK_GE(recv_buffer_->RemainingCapacity(), bytes_read);
1823 int ret = BIO_zero_copy_get_write_buf_done(transport_bio_, bytes_read); 1771 int ret = BIO_zero_copy_get_write_buf_done(transport_bio_, bytes_read);
1824 DCHECK_EQ(1, ret); 1772 DCHECK_EQ(1, ret);
1825 transport_recv_busy_ = false; 1773 transport_recv_busy_ = false;
1826 return result; 1774 return result;
1827 } 1775 }
1828 1776
1777 int SSLClientSocketImpl::VerifyCT() {
1778 const uint8_t* ocsp_response_raw;
1779 size_t ocsp_response_len;
1780 SSL_get0_ocsp_response(ssl_, &ocsp_response_raw, &ocsp_response_len);
1781 std::string ocsp_response;
1782 if (ocsp_response_len > 0) {
1783 ocsp_response.assign(reinterpret_cast<const char*>(ocsp_response_raw),
1784 ocsp_response_len);
1785 }
1786
1787 const uint8_t* sct_list_raw;
1788 size_t sct_list_len;
1789 SSL_get0_signed_cert_timestamp_list(ssl_, &sct_list_raw, &sct_list_len);
1790 std::string sct_list;
1791 if (sct_list_len > 0)
1792 sct_list.assign(reinterpret_cast<const char*>(sct_list_raw), sct_list_len);
1793
1794 // Note that this is a completely synchronous operation: The CT Log Verifier
1795 // gets all the data it needs for SCT verification and does not do any
1796 // external communication.
1797 cert_transparency_verifier_->Verify(
1798 server_cert_verify_result_.verified_cert.get(), ocsp_response, sct_list,
1799 &ct_verify_result_, net_log_);
1800
1801 ct_verify_result_.ct_policies_applied = true;
1802 ct_verify_result_.ev_policy_compliance =
1803 ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY;
1804 if (server_cert_verify_result_.cert_status & CERT_STATUS_IS_EV) {
1805 scoped_refptr<ct::EVCertsWhitelist> ev_whitelist =
1806 SSLConfigService::GetEVCertsWhitelist();
1807 ct::EVPolicyCompliance ev_policy_compliance =
1808 policy_enforcer_->DoesConformToCTEVPolicy(
1809 server_cert_verify_result_.verified_cert.get(), ev_whitelist.get(),
1810 ct_verify_result_.verified_scts, net_log_);
1811 ct_verify_result_.ev_policy_compliance = ev_policy_compliance;
1812 if (ev_policy_compliance !=
1813 ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY &&
1814 ev_policy_compliance !=
1815 ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_WHITELIST &&
1816 ev_policy_compliance !=
1817 ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_SCTS) {
1818 server_cert_verify_result_.cert_status |=
1819 CERT_STATUS_CT_COMPLIANCE_FAILED;
1820 server_cert_verify_result_.cert_status &= ~CERT_STATUS_IS_EV;
1821 }
1822 }
1823 ct_verify_result_.cert_policy_compliance =
1824 policy_enforcer_->DoesConformToCertPolicy(
1825 server_cert_verify_result_.verified_cert.get(),
1826 ct_verify_result_.verified_scts, net_log_);
1827
1828 if (ct_verify_result_.cert_policy_compliance !=
1829 ct::CertPolicyCompliance::CERT_POLICY_COMPLIES_VIA_SCTS &&
1830 transport_security_state_->ShouldRequireCT(
1831 host_and_port_.host(), server_cert_verify_result_.verified_cert.get(),
1832 server_cert_verify_result_.public_key_hashes)) {
1833 server_cert_verify_result_.cert_status |=
1834 CERT_STATUS_CERTIFICATE_TRANSPARENCY_REQUIRED;
1835 return ERR_CERTIFICATE_TRANSPARENCY_REQUIRED;
1836 }
1837
1838 return OK;
1839 }
1840
1829 int SSLClientSocketImpl::ClientCertRequestCallback(SSL* ssl) { 1841 int SSLClientSocketImpl::ClientCertRequestCallback(SSL* ssl) {
1830 DCHECK(ssl == ssl_); 1842 DCHECK(ssl == ssl_);
1831 1843
1832 net_log_.AddEvent(NetLog::TYPE_SSL_CLIENT_CERT_REQUESTED); 1844 net_log_.AddEvent(NetLog::TYPE_SSL_CLIENT_CERT_REQUESTED);
1833 1845
1834 // Clear any currently configured certificates. 1846 // Clear any currently configured certificates.
1835 SSL_certs_clear(ssl_); 1847 SSL_certs_clear(ssl_);
1836 1848
1837 #if defined(OS_IOS) 1849 #if defined(OS_IOS)
1838 // TODO(droger): Support client auth on iOS. See http://crbug.com/145954). 1850 // TODO(droger): Support client auth on iOS. See http://crbug.com/145954).
(...skipping 474 matching lines...) Expand 10 before | Expand all | Expand 10 after
2313 if (rv != OK) { 2325 if (rv != OK) {
2314 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv); 2326 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
2315 return; 2327 return;
2316 } 2328 }
2317 2329
2318 net_log_.EndEvent(NetLog::TYPE_SSL_CONNECT, 2330 net_log_.EndEvent(NetLog::TYPE_SSL_CONNECT,
2319 base::Bind(&NetLogSSLInfoCallback, base::Unretained(this))); 2331 base::Bind(&NetLogSSLInfoCallback, base::Unretained(this)));
2320 } 2332 }
2321 2333
2322 } // namespace net 2334 } // namespace net
OLDNEW
« no previous file with comments | « net/socket/ssl_client_socket_impl.h ('k') | net/socket/ssl_client_socket_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698