Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / net / socket / ssl_client_socket_nss.cc
index 826c94b..08cf2c5 100644 (file)
@@ -71,6 +71,7 @@
 #include "base/logging.h"
 #include "base/memory/singleton.h"
 #include "base/metrics/histogram.h"
+#include "base/profiler/scoped_tracker.h"
 #include "base/single_thread_task_runner.h"
 #include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
@@ -85,7 +86,6 @@
 #include "crypto/rsa_private_key.h"
 #include "crypto/scoped_nss_types.h"
 #include "net/base/address_list.h"
-#include "net/base/connection_type_histograms.h"
 #include "net/base/dns_util.h"
 #include "net/base/io_buffer.h"
 #include "net/base/net_errors.h"
@@ -93,7 +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_ev_whitelist.h"
 #include "net/cert/ct_verifier.h"
 #include "net/cert/ct_verify_result.h"
 #include "net/cert/scoped_nss_types.h"
@@ -407,6 +407,7 @@ struct HandshakeState {
   void Reset() {
     next_proto_status = SSLClientSocket::kNextProtoUnsupported;
     next_proto.clear();
+    negotiation_extension_ = SSLClientSocket::kExtensionUnknown;
     channel_id_sent = false;
     server_cert_chain.Reset(NULL);
     server_cert = NULL;
@@ -421,6 +422,9 @@ struct HandshakeState {
   SSLClientSocket::NextProtoStatus next_proto_status;
   std::string next_proto;
 
+  // TLS extension used for protocol negotiation.
+  SSLClientSocket::SSLNegotiationExtension negotiation_extension_;
+
   // True if a channel ID was sent.
   bool channel_id_sent;
 
@@ -759,6 +763,8 @@ class SSLClientSocketNSS::Core : public base::RefCountedThreadSafe<Core> {
   // UpdateNextProto gets any application-layer protocol that may have been
   // negotiated by the TLS connection.
   void UpdateNextProto();
+  // Record TLS extension used for protocol negotiation (NPN or ALPN).
+  void UpdateExtensionUsed();
 
   ////////////////////////////////////////////////////////////////////////////
   // Methods that are ONLY called on the network task runner:
@@ -1624,6 +1630,11 @@ void SSLClientSocketNSS::Core::HandshakeCallback(
 }
 
 void SSLClientSocketNSS::Core::HandshakeSucceeded() {
+  // TODO(vadimt): Remove ScopedTracker below once crbug.com/424386 is fixed.
+  tracked_objects::ScopedTracker tracking_profile(
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+          "424386 SSLClientSocketNSS::Core::HandshakeSucceeded"));
+
   DCHECK(OnNSSTaskRunner());
 
   PRBool last_handshake_resumed;
@@ -1640,6 +1651,7 @@ void SSLClientSocketNSS::Core::HandshakeSucceeded() {
   UpdateStapledOCSPResponse();
   UpdateConnectionStatus();
   UpdateNextProto();
+  UpdateExtensionUsed();
 
   // Update the network task runners view of the handshake state whenever
   // a handshake has completed.
@@ -1649,6 +1661,11 @@ void SSLClientSocketNSS::Core::HandshakeSucceeded() {
 }
 
 int SSLClientSocketNSS::Core::HandleNSSError(PRErrorCode nss_error) {
+  // TODO(vadimt): Remove ScopedTracker below once crbug.com/424386 is fixed.
+  tracked_objects::ScopedTracker tracking_profile(
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+          "424386 SSLClientSocketNSS::Core::HandleNSSError"));
+
   DCHECK(OnNSSTaskRunner());
 
   int net_error = MapNSSClientError(nss_error);
@@ -1681,6 +1698,11 @@ int SSLClientSocketNSS::Core::HandleNSSError(PRErrorCode nss_error) {
 }
 
 int SSLClientSocketNSS::Core::DoHandshakeLoop(int last_io_result) {
+  // TODO(vadimt): Remove ScopedTracker below once crbug.com/424386 is fixed.
+  tracked_objects::ScopedTracker tracking_profile(
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+          "424386 SSLClientSocketNSS::Core::DoHandshakeLoop"));
+
   DCHECK(OnNSSTaskRunner());
 
   int rv = last_io_result;
@@ -1717,6 +1739,11 @@ int SSLClientSocketNSS::Core::DoHandshakeLoop(int last_io_result) {
 }
 
 int SSLClientSocketNSS::Core::DoReadLoop(int result) {
+  // TODO(vadimt): Remove ScopedTracker below once crbug.com/424386 is fixed.
+  tracked_objects::ScopedTracker tracking_profile(
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+          "424386 SSLClientSocketNSS::Core::DoReadLoop"));
+
   DCHECK(OnNSSTaskRunner());
   DCHECK(false_started_ || handshake_callback_called_);
   DCHECK_EQ(STATE_NONE, next_handshake_state_);
@@ -1776,11 +1803,21 @@ int SSLClientSocketNSS::Core::DoWriteLoop(int result) {
 }
 
 int SSLClientSocketNSS::Core::DoHandshake() {
+  // TODO(vadimt): Remove ScopedTracker below once crbug.com/424386 is fixed.
+  tracked_objects::ScopedTracker tracking_profile(
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+          "424386 SSLClientSocketNSS::Core::DoHandshake"));
+
   DCHECK(OnNSSTaskRunner());
 
   int net_error = OK;
   SECStatus rv = SSL_ForceHandshake(nss_fd_);
 
+  // TODO(vadimt): Remove ScopedTracker below once crbug.com/424386 is fixed.
+  tracked_objects::ScopedTracker tracking_profile1(
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+          "424386 SSLClientSocketNSS::Core::DoHandshake 1"));
+
   // Note: this function may be called multiple times during the handshake, so
   // even though channel id and client auth are separate else cases, they can
   // both be used during a single SSL handshake.
@@ -1827,6 +1864,11 @@ int SSLClientSocketNSS::Core::DoHandshake() {
 }
 
 int SSLClientSocketNSS::Core::DoGetDBCertComplete(int result) {
+  // TODO(vadimt): Remove ScopedTracker below once crbug.com/424386 is fixed.
+  tracked_objects::ScopedTracker tracking_profile(
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+          "424386 SSLClientSocketNSS::Core::DoGetDBCertComplete"));
+
   SECStatus rv;
   PostOrRunCallback(
       FROM_HERE,
@@ -2011,6 +2053,11 @@ int SSLClientSocketNSS::Core::DoPayloadWrite() {
 // transport socket. Return true if some I/O performed, false
 // otherwise (error or ERR_IO_PENDING).
 bool SSLClientSocketNSS::Core::DoTransportIO() {
+  // TODO(vadimt): Remove ScopedTracker below once crbug.com/424386 is fixed.
+  tracked_objects::ScopedTracker tracking_profile(
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+          "424386 SSLClientSocketNSS::Core::DoTransportIO"));
+
   DCHECK(OnNSSTaskRunner());
 
   bool network_moved = false;
@@ -2187,6 +2234,11 @@ void SSLClientSocketNSS::Core::OnSendComplete(int result) {
 // callback. For Read() and Write(), that's what we want. But for Connect(),
 // the caller expects OK (i.e. 0) for success.
 void SSLClientSocketNSS::Core::DoConnectCallback(int rv) {
+  // TODO(vadimt): Remove ScopedTracker below once crbug.com/424386 is fixed.
+  tracked_objects::ScopedTracker tracking_profile(
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+          "424386 SSLClientSocketNSS::Core::DoConnectCallback"));
+
   DCHECK(OnNSSTaskRunner());
   DCHECK_NE(rv, ERR_IO_PENDING);
   DCHECK(!user_connect_callback_.is_null());
@@ -2198,6 +2250,11 @@ void SSLClientSocketNSS::Core::DoConnectCallback(int rv) {
 }
 
 void SSLClientSocketNSS::Core::DoReadCallback(int rv) {
+  // TODO(vadimt): Remove ScopedTracker below once crbug.com/424386 is fixed.
+  tracked_objects::ScopedTracker tracking_profile(
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+          "424386 SSLClientSocketNSS::Core::DoReadCallback"));
+
   DCHECK(OnNSSTaskRunner());
   DCHECK_NE(ERR_IO_PENDING, rv);
   DCHECK(!user_read_callback_.is_null());
@@ -2213,6 +2270,10 @@ void SSLClientSocketNSS::Core::DoReadCallback(int rv) {
   PostOrRunCallback(
       FROM_HERE,
       base::Bind(&Core::DidNSSRead, this, rv));
+  // TODO(vadimt): Remove ScopedTracker below once crbug.com/418183 is fixed.
+  tracked_objects::ScopedTracker tracking_profile1(
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+          "SSLClientSocketNSS::Core::DoReadCallback"));
   PostOrRunCallback(
       FROM_HERE,
       base::Bind(base::ResetAndReturn(&user_read_callback_), rv));
@@ -2406,6 +2467,10 @@ void SSLClientSocketNSS::Core::UpdateStapledOCSPResponse() {
 }
 
 void SSLClientSocketNSS::Core::UpdateConnectionStatus() {
+  // Note: This function may be called multiple times for a single connection
+  // if renegotiations occur.
+  nss_handshake_state_.ssl_connection_status = 0;
+
   SSLChannelInfo channel_info;
   SECStatus ok = SSL_GetChannelInfo(nss_fd_,
                                     &channel_info, sizeof(channel_info));
@@ -2422,8 +2487,6 @@ void SSLClientSocketNSS::Core::UpdateConnectionStatus() {
          SSL_CONNECTION_COMPRESSION_MASK) <<
         SSL_CONNECTION_COMPRESSION_SHIFT;
 
-    // NSS 3.14.x doesn't have a version macro for TLS 1.2 (because NSS didn't
-    // support it yet), so use 0x0303 directly.
     int version = SSL_CONNECTION_VERSION_UNKNOWN;
     if (channel_info.protocolVersion < SSL_LIBRARY_VERSION_3_0) {
       // All versions less than SSL_LIBRARY_VERSION_3_0 are treated as SSL
@@ -2431,11 +2494,11 @@ void SSLClientSocketNSS::Core::UpdateConnectionStatus() {
       version = SSL_CONNECTION_VERSION_SSL2;
     } else if (channel_info.protocolVersion == SSL_LIBRARY_VERSION_3_0) {
       version = SSL_CONNECTION_VERSION_SSL3;
-    } else if (channel_info.protocolVersion == SSL_LIBRARY_VERSION_3_1_TLS) {
+    } else if (channel_info.protocolVersion == SSL_LIBRARY_VERSION_TLS_1_0) {
       version = SSL_CONNECTION_VERSION_TLS1;
     } else if (channel_info.protocolVersion == SSL_LIBRARY_VERSION_TLS_1_1) {
       version = SSL_CONNECTION_VERSION_TLS1_1;
-    } else if (channel_info.protocolVersion == 0x0303) {
+    } else if (channel_info.protocolVersion == SSL_LIBRARY_VERSION_TLS_1_2) {
       version = SSL_CONNECTION_VERSION_TLS1_2;
     }
     nss_handshake_state_.ssl_connection_status |=
@@ -2491,6 +2554,23 @@ void SSLClientSocketNSS::Core::UpdateNextProto() {
   }
 }
 
+void SSLClientSocketNSS::Core::UpdateExtensionUsed() {
+  PRBool negotiated_extension;
+  SECStatus rv = SSL_HandshakeNegotiatedExtension(nss_fd_,
+                                                  ssl_app_layer_protocol_xtn,
+                                                  &negotiated_extension);
+  if (rv == SECSuccess && negotiated_extension) {
+    nss_handshake_state_.negotiation_extension_ = kExtensionALPN;
+  } else {
+    rv = SSL_HandshakeNegotiatedExtension(nss_fd_,
+                                          ssl_next_proto_nego_xtn,
+                                          &negotiated_extension);
+    if (rv == SECSuccess && negotiated_extension) {
+      nss_handshake_state_.negotiation_extension_ = kExtensionNPN;
+    }
+  }
+}
+
 void SSLClientSocketNSS::Core::RecordChannelIDSupportOnNSSTaskRunner() {
   DCHECK(OnNSSTaskRunner());
   if (nss_handshake_state_.resumed_handshake)
@@ -2623,6 +2703,11 @@ void SSLClientSocketNSS::Core::DidNSSWrite(int result) {
 }
 
 void SSLClientSocketNSS::Core::BufferSendComplete(int result) {
+  // TODO(vadimt): Remove ScopedTracker below once crbug.com/418183 is fixed.
+  tracked_objects::ScopedTracker tracking_profile(
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+          "418183 DidCompleteReadWrite => Core::BufferSendComplete"));
+
   if (!OnNSSTaskRunner()) {
     if (detached_)
       return;
@@ -2666,6 +2751,11 @@ void SSLClientSocketNSS::Core::OnGetChannelIDComplete(int result) {
 void SSLClientSocketNSS::Core::BufferRecvComplete(
     IOBuffer* read_buffer,
     int result) {
+  // TODO(vadimt): Remove ScopedTracker below once crbug.com/418183 is fixed.
+  tracked_objects::ScopedTracker tracking_profile(
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+          "418183 DidCompleteReadWrite => SSLClientSocketNSS::Core::..."));
+
   DCHECK(read_buffer);
 
   if (!OnNSSTaskRunner()) {
@@ -3328,6 +3418,7 @@ int SSLClientSocketNSS::DoHandshakeComplete(int result) {
       !core_->state().sct_list_from_tls_extension.empty());
   set_stapled_ocsp_response_received(
       !core_->state().stapled_ocsp_response.empty());
+  set_negotiation_extension(core_->state().negotiation_extension_);
 
   LeaveFunction(result);
   return result;
@@ -3413,8 +3504,11 @@ int SSLClientSocketNSS::DoVerifyCertComplete(int result) {
   // TODO(hclam): Skip logging if server cert was expected to be bad because
   // |server_cert_verify_result_| doesn't contain all the information about
   // the cert.
-  if (result == OK)
-    LogConnectionTypeMetrics();
+  if (result == OK) {
+    int ssl_version =
+        SSLConnectionStatusToVersion(core_->state().ssl_connection_status);
+    RecordConnectionTypeMetrics(ssl_version);
+  }
 
   const CertStatus cert_status = server_cert_verify_result_.cert_status;
   if (transport_security_state_ &&
@@ -3428,6 +3522,21 @@ int SSLClientSocketNSS::DoVerifyCertComplete(int result) {
     result = ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN;
   }
 
+  scoped_refptr<ct::EVCertsWhitelist> ev_whitelist =
+      SSLConfigService::GetEVCertsWhitelist();
+  if (server_cert_verify_result_.cert_status & CERT_STATUS_IS_EV) {
+    if (ev_whitelist.get() && ev_whitelist->IsValid()) {
+      const SHA256HashValue fingerprint(
+          X509Certificate::CalculateFingerprint256(
+              server_cert_verify_result_.verified_cert->os_cert_handle()));
+
+      UMA_HISTOGRAM_BOOLEAN(
+          "Net.SSL_EVCertificateInWhitelist",
+          ev_whitelist->ContainsCertificateHash(
+              std::string(reinterpret_cast<const char*>(fingerprint.data), 8)));
+    }
+  }
+
   if (result == OK) {
     // Only check Certificate Transparency if there were no other errors with
     // the connection.
@@ -3467,29 +3576,6 @@ void SSLClientSocketNSS::VerifyCT() {
           << ct_verify_result_.unknown_logs_scts.size();
 }
 
-void SSLClientSocketNSS::LogConnectionTypeMetrics() const {
-  UpdateConnectionTypeHistograms(CONNECTION_SSL);
-  int ssl_version = SSLConnectionStatusToVersion(
-      core_->state().ssl_connection_status);
-  switch (ssl_version) {
-    case SSL_CONNECTION_VERSION_SSL2:
-      UpdateConnectionTypeHistograms(CONNECTION_SSL_SSL2);
-      break;
-    case SSL_CONNECTION_VERSION_SSL3:
-      UpdateConnectionTypeHistograms(CONNECTION_SSL_SSL3);
-      break;
-    case SSL_CONNECTION_VERSION_TLS1:
-      UpdateConnectionTypeHistograms(CONNECTION_SSL_TLS1);
-      break;
-    case SSL_CONNECTION_VERSION_TLS1_1:
-      UpdateConnectionTypeHistograms(CONNECTION_SSL_TLS1_1);
-      break;
-    case SSL_CONNECTION_VERSION_TLS1_2:
-      UpdateConnectionTypeHistograms(CONNECTION_SSL_TLS1_2);
-      break;
-  };
-}
-
 void SSLClientSocketNSS::EnsureThreadIdAssigned() const {
   base::AutoLock auto_lock(lock_);
   if (valid_thread_id_ != base::kInvalidThreadId)