Index: net/socket/ssl_client_socket_nss.cc |
diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc |
index 081596237ae76923ab97bd97bb48a8df8876bf7a..dbf64afad1ded2566bd92f598b5bef87e8f44fde 100644 |
--- a/net/socket/ssl_client_socket_nss.cc |
+++ b/net/socket/ssl_client_socket_nss.cc |
@@ -93,6 +93,7 @@ |
#include "net/cert/asn1_util.h" |
#include "net/cert/cert_status_flags.h" |
#include "net/cert/cert_verifier.h" |
+#include "net/cert/ct_objects_extractor.h" |
#include "net/cert/ct_verifier.h" |
#include "net/cert/ct_verify_result.h" |
#include "net/cert/scoped_nss_types.h" |
@@ -418,6 +419,7 @@ struct HandshakeState { |
server_cert_chain.Reset(NULL); |
server_cert = NULL; |
sct_list_from_tls_extension.clear(); |
+ stapled_ocsp_response.clear(); |
resumed_handshake = false; |
ssl_connection_status = 0; |
} |
@@ -449,6 +451,8 @@ struct HandshakeState { |
scoped_refptr<X509Certificate> server_cert; |
// SignedCertificateTimestampList received via TLS extension (RFC 6962). |
std::string sct_list_from_tls_extension; |
+ // Stapled OCSP response received. |
+ std::string stapled_ocsp_response; |
// True if the current handshake was the result of TLS session resumption. |
bool resumed_handshake; |
@@ -760,10 +764,13 @@ class SSLClientSocketNSS::Core : public base::RefCountedThreadSafe<Core> { |
// Updates the NSS and platform specific certificates. |
void UpdateServerCert(); |
- // Update the nss_handshake_state_ with SignedCertificateTimestampLists |
- // received in the handshake, via a TLS extension or (to be implemented) |
- // OCSP stapling. |
+ // Update the nss_handshake_state_ with the SignedCertificateTimestampList |
+ // received in the handshake via a TLS extension. |
void UpdateSignedCertTimestamps(); |
+ // Update the OCSP response cache with the stapled response received in the |
+ // handshake, and update nss_handshake_state_ with |
+ // the SignedCertificateTimestampList received in the stapled OCSP response. |
+ void UpdateStapledOCSPResponse(); |
// Updates the nss_handshake_state_ with the negotiated security parameters. |
void UpdateConnectionStatus(); |
// Record histograms for channel id support during full handshakes - resumed |
@@ -1663,6 +1670,7 @@ void SSLClientSocketNSS::Core::HandshakeSucceeded() { |
RecordChannelIDSupportOnNSSTaskRunner(); |
UpdateServerCert(); |
UpdateSignedCertTimestamps(); |
+ UpdateStapledOCSPResponse(); |
UpdateConnectionStatus(); |
UpdateNextProto(); |
@@ -1834,43 +1842,6 @@ int SSLClientSocketNSS::Core::DoHandshake() { |
false_started_ = true; |
HandshakeSucceeded(); |
} |
- |
- // TODO(wtc): move this block of code to OwnAuthCertHandler. |
- #if defined(SSL_ENABLE_OCSP_STAPLING) |
- // TODO(agl): figure out how to plumb an OCSP response into the Mac |
- // system library and update IsOCSPStaplingSupported for Mac. |
- if (IsOCSPStaplingSupported()) { |
- const SECItemArray* ocsp_responses = |
- SSL_PeerStapledOCSPResponses(nss_fd_); |
- if (ocsp_responses->len) { |
- #if defined(OS_WIN) |
- if (nss_handshake_state_.server_cert) { |
- CRYPT_DATA_BLOB ocsp_response_blob; |
- ocsp_response_blob.cbData = ocsp_responses->items[0].len; |
- ocsp_response_blob.pbData = ocsp_responses->items[0].data; |
- BOOL ok = CertSetCertificateContextProperty( |
- nss_handshake_state_.server_cert->os_cert_handle(), |
- CERT_OCSP_RESPONSE_PROP_ID, |
- CERT_SET_PROPERTY_IGNORE_PERSIST_ERROR_FLAG, |
- &ocsp_response_blob); |
- if (!ok) { |
- VLOG(1) << "Failed to set OCSP response property: " |
- << GetLastError(); |
- } |
- } |
- #elif defined(USE_NSS) |
- CacheOCSPResponseFromSideChannelFunction cache_ocsp_response = |
- GetCacheOCSPResponseFromSideChannelFunction(); |
- |
- cache_ocsp_response( |
- CERT_GetDefaultCertDB(), |
- nss_handshake_state_.server_cert_chain[0], PR_Now(), |
- &ocsp_responses->items[0], NULL); |
- #endif |
- } |
- } |
- #endif |
- // Done! |
} else { |
PRErrorCode prerr = PR_GetError(); |
net_error = HandleNSSError(prerr, true); |
@@ -2436,6 +2407,46 @@ void SSLClientSocketNSS::Core::UpdateSignedCertTimestamps() { |
signed_cert_timestamps->len); |
} |
+void SSLClientSocketNSS::Core::UpdateStapledOCSPResponse() { |
+ const SECItemArray* ocsp_responses = |
+ SSL_PeerStapledOCSPResponses(nss_fd_); |
+ if (!ocsp_responses || !ocsp_responses->len) |
+ return; |
+ |
+ nss_handshake_state_.stapled_ocsp_response = std::string( |
+ reinterpret_cast<char*>(ocsp_responses->items[0].data), |
+ ocsp_responses->items[0].len); |
+ |
+ // TODO(agl): figure out how to plumb an OCSP response into the Mac |
+ // system library and update IsOCSPStaplingSupported for Mac. |
+ if (IsOCSPStaplingSupported()) { |
+ #if defined(OS_WIN) |
+ if (nss_handshake_state_.server_cert) { |
+ CRYPT_DATA_BLOB ocsp_response_blob; |
+ ocsp_response_blob.cbData = ocsp_responses->items[0].len; |
+ ocsp_response_blob.pbData = ocsp_responses->items[0].data; |
+ BOOL ok = CertSetCertificateContextProperty( |
+ nss_handshake_state_.server_cert->os_cert_handle(), |
+ CERT_OCSP_RESPONSE_PROP_ID, |
+ CERT_SET_PROPERTY_IGNORE_PERSIST_ERROR_FLAG, |
+ &ocsp_response_blob); |
+ if (!ok) { |
+ VLOG(1) << "Failed to set OCSP response property: " |
+ << GetLastError(); |
+ } |
+ } |
+ #elif defined(USE_NSS) |
+ CacheOCSPResponseFromSideChannelFunction cache_ocsp_response = |
+ GetCacheOCSPResponseFromSideChannelFunction(); |
+ |
+ cache_ocsp_response( |
+ CERT_GetDefaultCertDB(), |
+ nss_handshake_state_.server_cert_chain[0], PR_Now(), |
+ &ocsp_responses->items[0], NULL); |
+ #endif |
+ } // IsOCSPStaplingSupported() |
+} |
+ |
void SSLClientSocketNSS::Core::UpdateConnectionStatus() { |
SSLChannelInfo channel_info; |
SECStatus ok = SSL_GetChannelInfo(nss_fd_, |
@@ -3202,12 +3213,14 @@ int SSLClientSocketNSS::InitializeSSLOptions() { |
// Added in NSS 3.15 |
#ifdef SSL_ENABLE_OCSP_STAPLING |
- if (IsOCSPStaplingSupported()) { |
- rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_OCSP_STAPLING, PR_TRUE); |
- if (rv != SECSuccess) { |
- LogFailedNSSFunction(net_log_, "SSL_OptionSet", |
- "SSL_ENABLE_OCSP_STAPLING"); |
- } |
+ // Request OCSP stapling even on platforms that don't support it, in |
+ // order to extract Certificate Transparency information. |
+ rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_OCSP_STAPLING, |
+ (IsOCSPStaplingSupported() || |
+ ssl_config_.signed_cert_timestamps_enabled)); |
+ if (rv != SECSuccess) { |
+ LogFailedNSSFunction(net_log_, "SSL_OptionSet", |
+ "SSL_ENABLE_OCSP_STAPLING"); |
} |
#endif |
@@ -3365,6 +3378,8 @@ int SSLClientSocketNSS::DoHandshakeComplete(int result) { |
set_channel_id_sent(core_->state().channel_id_sent); |
set_signed_cert_timestamps_received( |
!core_->state().sct_list_from_tls_extension.empty()); |
+ set_stapled_ocsp_response_received( |
+ !core_->state().stapled_ocsp_response.empty()); |
LeaveFunction(result); |
return result; |
@@ -3522,10 +3537,12 @@ void SSLClientSocketNSS::VerifyCT() { |
// external communication. |
int result = cert_transparency_verifier_->Verify( |
server_cert_verify_result_.verified_cert, |
- std::string(), // SCT list from OCSP response |
+ core_->state().stapled_ocsp_response, |
core_->state().sct_list_from_tls_extension, |
&ct_verify_result_, |
net_log_); |
+ // TODO(ekasper): wipe stapled_ocsp_response and sct_list_from_tls_extension |
+ // from the state after verification is complete, to conserve memory. |
VLOG(1) << "CT Verification complete: result " << result |
<< " Invalid scts: " << ct_verify_result_.invalid_scts.size() |