// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This file includes code SSLClientSocketNSS::DoVerifyCertComplete() derived
// from AuthCertificateCallback() in
// mozilla/security/manager/ssl/src/nsNSSCallbacks.cpp.

/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is the Netscape security libraries.
 *
 * The Initial Developer of the Original Code is
 * Netscape Communications Corporation.
 * Portions created by the Initial Developer are Copyright (C) 2000
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *   Ian McGreer <mcgreer@netscape.com>
 *   Javier Delgadillo <javi@netscape.com>
 *   Kai Engert <kengert@redhat.com>
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

#include "net/socket/ssl_client_socket_nss.h"

#include <certdb.h>
#include <hasht.h>
#include <keyhi.h>
#include <nspr.h>
#include <nss.h>
#include <ocsp.h>
#include <pk11pub.h>
#include <secerr.h>
#include <sechash.h>
#include <ssl.h>
#include <sslerr.h>
#include <sslproto.h>

#include <algorithm>
#include <limits>
#include <map>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback_helpers.h"
#include "base/compiler_specific.h"
#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"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/thread_task_runner_handle.h"
#include "base/threading/thread_restrictions.h"
#include "base/values.h"
#include "crypto/ec_private_key.h"
#include "crypto/nss_util.h"
#include "crypto/nss_util_internal.h"
#include "crypto/rsa_private_key.h"
#include "crypto/scoped_nss_types.h"
#include "net/base/address_list.h"
#include "net/base/dns_util.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/base/net_log.h"
#include "net/cert/asn1_util.h"
#include "net/cert/cert_policy_enforcer.h"
#include "net/cert/cert_status_flags.h"
#include "net/cert/cert_verifier.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"
#include "net/cert/sct_status_flags.h"
#include "net/cert/single_request_cert_verifier.h"
#include "net/cert/x509_certificate_net_log_param.h"
#include "net/cert/x509_util.h"
#include "net/http/transport_security_state.h"
#include "net/ocsp/nss_ocsp.h"
#include "net/socket/client_socket_handle.h"
#include "net/socket/nss_ssl_util.h"
#include "net/ssl/ssl_cert_request_info.h"
#include "net/ssl/ssl_connection_status_flags.h"
#include "net/ssl/ssl_info.h"

#if defined(OS_WIN)
#include <windows.h>
#include <wincrypt.h>

#include "base/win/windows_version.h"
#elif defined(OS_MACOSX)
#include <Security/SecBase.h>
#include <Security/SecCertificate.h>
#include <Security/SecIdentity.h>

#include "base/mac/mac_logging.h"
#include "base/synchronization/lock.h"
#include "crypto/mac_security_services_lock.h"
#elif defined(USE_NSS)
#include <dlfcn.h>
#endif

namespace net {

// State machines are easier to debug if you log state transitions.
// Enable these if you want to see what's going on.
#if 1
#define EnterFunction(x)
#define LeaveFunction(x)
#define GotoState(s) next_handshake_state_ = s
#else
#define EnterFunction(x)\
    VLOG(1) << (void *)this << " " << __FUNCTION__ << " enter " << x\
            << "; next_handshake_state " << next_handshake_state_
#define LeaveFunction(x)\
    VLOG(1) << (void *)this << " " << __FUNCTION__ << " leave " << x\
            << "; next_handshake_state " << next_handshake_state_
#define GotoState(s)\
    do {\
      VLOG(1) << (void *)this << " " << __FUNCTION__ << " jump to state " << s;\
      next_handshake_state_ = s;\
    } while (0)
#endif

#if !defined(CKM_AES_GCM)
#define CKM_AES_GCM 0x00001087
#endif

#if !defined(CKM_NSS_CHACHA20_POLY1305)
#define CKM_NSS_CHACHA20_POLY1305 (CKM_NSS + 26)
#endif

namespace {

// SSL plaintext fragments are shorter than 16KB. Although the record layer
// overhead is allowed to be 2K + 5 bytes, in practice the overhead is much
// smaller than 1KB. So a 17KB buffer should be large enough to hold an
// entire SSL record.
const int kRecvBufferSize = 17 * 1024;
const int kSendBufferSize = 17 * 1024;

// Used by SSLClientSocketNSS::Core to indicate there is no read result
// obtained by a previous operation waiting to be returned to the caller.
// This constant can be any non-negative/non-zero value (eg: it does not
// overlap with any value of the net::Error range, including net::OK).
const int kNoPendingReadResult = 1;

#if defined(OS_WIN)
// CERT_OCSP_RESPONSE_PROP_ID is only implemented on Vista+, but it can be
// set on Windows XP without error. There is some overhead from the server
// sending the OCSP response if it supports the extension, for the subset of
// XP clients who will request it but be unable to use it, but this is an
// acceptable trade-off for simplicity of implementation.
bool IsOCSPStaplingSupported() {
  return true;
}
#elif defined(USE_NSS)
typedef SECStatus
(*CacheOCSPResponseFromSideChannelFunction)(
    CERTCertDBHandle *handle, CERTCertificate *cert, PRTime time,
    SECItem *encodedResponse, void *pwArg);

// On Linux, we dynamically link against the system version of libnss3.so. In
// order to continue working on systems without up-to-date versions of NSS we
// lookup CERT_CacheOCSPResponseFromSideChannel with dlsym.

// RuntimeLibNSSFunctionPointers is a singleton which caches the results of any
// runtime symbol resolution that we need.
class RuntimeLibNSSFunctionPointers {
 public:
  CacheOCSPResponseFromSideChannelFunction
  GetCacheOCSPResponseFromSideChannelFunction() {
    return cache_ocsp_response_from_side_channel_;
  }

  static RuntimeLibNSSFunctionPointers* GetInstance() {
    return Singleton<RuntimeLibNSSFunctionPointers>::get();
  }

 private:
  friend struct DefaultSingletonTraits<RuntimeLibNSSFunctionPointers>;

  RuntimeLibNSSFunctionPointers() {
    cache_ocsp_response_from_side_channel_ =
        (CacheOCSPResponseFromSideChannelFunction)
        dlsym(RTLD_DEFAULT, "CERT_CacheOCSPResponseFromSideChannel");
  }

  CacheOCSPResponseFromSideChannelFunction
      cache_ocsp_response_from_side_channel_;
};

CacheOCSPResponseFromSideChannelFunction
GetCacheOCSPResponseFromSideChannelFunction() {
  return RuntimeLibNSSFunctionPointers::GetInstance()
    ->GetCacheOCSPResponseFromSideChannelFunction();
}

bool IsOCSPStaplingSupported() {
  return GetCacheOCSPResponseFromSideChannelFunction() != NULL;
}
#else
bool IsOCSPStaplingSupported() {
  return false;
}
#endif

#if defined(OS_WIN)

// This callback is intended to be used with CertFindChainInStore. In addition
// to filtering by extended/enhanced key usage, we do not show expired
// certificates and require digital signature usage in the key usage
// extension.
//
// This matches our behavior on Mac OS X and that of NSS. It also matches the
// default behavior of IE8. See http://support.microsoft.com/kb/890326 and
// http://blogs.msdn.com/b/askie/archive/2009/06/09/my-expired-client-certificates-no-longer-display-when-connecting-to-my-web-server-using-ie8.aspx
BOOL WINAPI ClientCertFindCallback(PCCERT_CONTEXT cert_context,
                                   void* find_arg) {
  VLOG(1) << "Calling ClientCertFindCallback from _nss";
  // Verify the certificate's KU is good.
  BYTE key_usage;
  if (CertGetIntendedKeyUsage(X509_ASN_ENCODING, cert_context->pCertInfo,
                              &key_usage, 1)) {
    if (!(key_usage & CERT_DIGITAL_SIGNATURE_KEY_USAGE))
      return FALSE;
  } else {
    DWORD err = GetLastError();
    // If |err| is non-zero, it's an actual error. Otherwise the extension
    // just isn't present, and we treat it as if everything was allowed.
    if (err) {
      DLOG(ERROR) << "CertGetIntendedKeyUsage failed: " << err;
      return FALSE;
    }
  }

  // Verify the current time is within the certificate's validity period.
  if (CertVerifyTimeValidity(NULL, cert_context->pCertInfo) != 0)
    return FALSE;

  // Verify private key metadata is associated with this certificate.
  DWORD size = 0;
  if (!CertGetCertificateContextProperty(
          cert_context, CERT_KEY_PROV_INFO_PROP_ID, NULL, &size)) {
    return FALSE;
  }

  return TRUE;
}

#endif

// Helper functions to make it possible to log events from within the
// SSLClientSocketNSS::Core.
void AddLogEvent(const base::WeakPtr<BoundNetLog>& net_log,
                 NetLog::EventType event_type) {
  if (!net_log)
    return;
  net_log->AddEvent(event_type);
}

// Helper function to make it possible to log events from within the
// SSLClientSocketNSS::Core.
void AddLogEventWithCallback(const base::WeakPtr<BoundNetLog>& net_log,
                             NetLog::EventType event_type,
                             const NetLog::ParametersCallback& callback) {
  if (!net_log)
    return;
  net_log->AddEvent(event_type, callback);
}

// Helper function to make it easier to call BoundNetLog::AddByteTransferEvent
// from within the SSLClientSocketNSS::Core.
// AddByteTransferEvent expects to receive a const char*, which within the
// Core is backed by an IOBuffer. If the "const char*" is bound via
// base::Bind and posted to another thread, and the IOBuffer that backs that
// pointer then goes out of scope on the origin thread, this would result in
// an invalid read of a stale pointer.
// Instead, provide a signature that accepts an IOBuffer*, so that a reference
// to the owning IOBuffer can be bound to the Callback. This ensures that the
// IOBuffer will stay alive long enough to cross threads if needed.
void LogByteTransferEvent(
    const base::WeakPtr<BoundNetLog>& net_log, NetLog::EventType event_type,
    int len, IOBuffer* buffer) {
  if (!net_log)
    return;
  net_log->AddByteTransferEvent(event_type, len, buffer->data());
}

// PeerCertificateChain is a helper object which extracts the certificate
// chain, as given by the server, from an NSS socket and performs the needed
// resource management. The first element of the chain is the leaf certificate
// and the other elements are in the order given by the server.
class PeerCertificateChain {
 public:
  PeerCertificateChain() {}
  PeerCertificateChain(const PeerCertificateChain& other);
  ~PeerCertificateChain();
  PeerCertificateChain& operator=(const PeerCertificateChain& other);

  // Resets the current chain, freeing any resources, and updates the current
  // chain to be a copy of the chain stored in |nss_fd|.
  // If |nss_fd| is NULL, then the current certificate chain will be freed.
  void Reset(PRFileDesc* nss_fd);

  // Returns the current certificate chain as a vector of DER-encoded
  // base::StringPieces. The returned vector remains valid until Reset is
  // called.
  std::vector<base::StringPiece> AsStringPieceVector() const;

  bool empty() const { return certs_.empty(); }

  CERTCertificate* operator[](size_t index) const {
    DCHECK_LT(index, certs_.size());
    return certs_[index];
  }

 private:
  std::vector<CERTCertificate*> certs_;
};

PeerCertificateChain::PeerCertificateChain(
    const PeerCertificateChain& other) {
  *this = other;
}

PeerCertificateChain::~PeerCertificateChain() {
  Reset(NULL);
}

PeerCertificateChain& PeerCertificateChain::operator=(
    const PeerCertificateChain& other) {
  if (this == &other)
    return *this;

  Reset(NULL);
  certs_.reserve(other.certs_.size());
  for (size_t i = 0; i < other.certs_.size(); ++i)
    certs_.push_back(CERT_DupCertificate(other.certs_[i]));

  return *this;
}

void PeerCertificateChain::Reset(PRFileDesc* nss_fd) {
  for (size_t i = 0; i < certs_.size(); ++i)
    CERT_DestroyCertificate(certs_[i]);
  certs_.clear();

  if (nss_fd == NULL)
    return;

  CERTCertList* list = SSL_PeerCertificateChain(nss_fd);
  // The handshake on |nss_fd| may not have completed.
  if (list == NULL)
    return;

  for (CERTCertListNode* node = CERT_LIST_HEAD(list);
       !CERT_LIST_END(node, list); node = CERT_LIST_NEXT(node)) {
    certs_.push_back(CERT_DupCertificate(node->cert));
  }
  CERT_DestroyCertList(list);
}

std::vector<base::StringPiece>
PeerCertificateChain::AsStringPieceVector() const {
  std::vector<base::StringPiece> v(certs_.size());
  for (unsigned i = 0; i < certs_.size(); i++) {
    v[i] = base::StringPiece(
        reinterpret_cast<const char*>(certs_[i]->derCert.data),
        certs_[i]->derCert.len);
  }

  return v;
}

// HandshakeState is a helper struct used to pass handshake state between
// the NSS task runner and the network task runner.
//
// It contains members that may be read or written on the NSS task runner,
// but which also need to be read from the network task runner. The NSS task
// runner will notify the network task runner whenever this state changes, so
// that the network task runner can safely make a copy, which avoids the need
// for locking.
struct HandshakeState {
  HandshakeState() { Reset(); }

  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;
    sct_list_from_tls_extension.clear();
    stapled_ocsp_response.clear();
    resumed_handshake = false;
    ssl_connection_status = 0;
  }

  // Set to kNextProtoNegotiated if NPN was successfully negotiated, with the
  // negotiated protocol stored in |next_proto|.
  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;

  // List of DER-encoded X.509 DistinguishedName of certificate authorities
  // allowed by the server.
  std::vector<std::string> cert_authorities;

  // Set when the handshake fully completes.
  //
  // The server certificate is first received from NSS as an NSS certificate
  // chain (|server_cert_chain|) and then converted into a platform-specific
  // X509Certificate object (|server_cert|). It's possible for some
  // certificates to be successfully parsed by NSS, and not by the platform
  // libraries (i.e.: when running within a sandbox, different parsing
  // algorithms, etc), so it's not safe to assume that |server_cert| will
  // always be non-NULL.
  PeerCertificateChain server_cert_chain;
  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;

  // The negotiated security parameters (TLS version, cipher, extensions) of
  // the SSL connection.
  int ssl_connection_status;
};

// Client-side error mapping functions.

// Map NSS error code to network error code.
int MapNSSClientError(PRErrorCode err) {
  switch (err) {
    case SSL_ERROR_BAD_CERT_ALERT:
    case SSL_ERROR_UNSUPPORTED_CERT_ALERT:
    case SSL_ERROR_REVOKED_CERT_ALERT:
    case SSL_ERROR_EXPIRED_CERT_ALERT:
    case SSL_ERROR_CERTIFICATE_UNKNOWN_ALERT:
    case SSL_ERROR_UNKNOWN_CA_ALERT:
    case SSL_ERROR_ACCESS_DENIED_ALERT:
      return ERR_BAD_SSL_CLIENT_AUTH_CERT;
    default:
      return MapNSSError(err);
  }
}

}  // namespace

// SSLClientSocketNSS::Core provides a thread-safe, ref-counted core that is
// able to marshal data between NSS functions and an underlying transport
// socket.
//
// All public functions are meant to be called from the network task runner,
// and any callbacks supplied will be invoked there as well, provided that
// Detach() has not been called yet.
//
/////////////////////////////////////////////////////////////////////////////
//
// Threading within SSLClientSocketNSS and SSLClientSocketNSS::Core:
//
// Because NSS may block on either hardware or user input during operations
// such as signing, creating certificates, or locating private keys, the Core
// handles all of the interactions with the underlying NSS SSL socket, so
// that these blocking calls can be executed on a dedicated task runner.
//
// Note that the network task runner and the NSS task runner may be executing
// on the same thread. If that happens, then it's more performant to try to
// complete as much work as possible synchronously, even if it might block,
// rather than continually PostTask-ing to the same thread.
//
// Because NSS functions should only be called on the NSS task runner, while
// I/O resources should only be accessed on the network task runner, most
// public functions are implemented via three methods, each with different
// task runner affinities.
//
// In the single-threaded mode (where the network and NSS task runners run on
// the same thread), these are all attempted synchronously, while in the
// multi-threaded mode, message passing is used.
//
// 1) NSS Task Runner: Execute NSS function (DoPayloadRead, DoPayloadWrite,
//    DoHandshake)
// 2) NSS Task Runner: Prepare data to go from NSS to an IO function:
//    (BufferRecv, BufferSend)
// 3) Network Task Runner: Perform IO on that data (DoBufferRecv,
//    DoBufferSend, DoGetChannelID, OnGetChannelIDComplete)
// 4) Both Task Runners: Callback for asynchronous completion or to marshal
//    data from the network task runner back to NSS (BufferRecvComplete,
//    BufferSendComplete, OnHandshakeIOComplete)
//
/////////////////////////////////////////////////////////////////////////////
// Single-threaded example
//
// |--------------------------Network Task Runner--------------------------|
//  SSLClientSocketNSS              Core               (Transport Socket)
//       Read()
//         |-------------------------V
//                                 Read()
//                                   |
//                            DoPayloadRead()
//                                   |
//                               BufferRecv()
//                                   |
//                              DoBufferRecv()
//                                   |-------------------------V
//                                                           Read()
//                                   V-------------------------|
//                          BufferRecvComplete()
//                                   |
//                           PostOrRunCallback()
//         V-------------------------|
//    (Read Callback)
//
/////////////////////////////////////////////////////////////////////////////
// Multi-threaded example:
//
// |--------------------Network Task Runner-------------|--NSS Task Runner--|
//  SSLClientSocketNSS          Core            Socket         Core
//       Read()
//         |---------------------V
//                             Read()
//                               |-------------------------------V
//                                                             Read()
//                                                               |
//                                                         DoPayloadRead()
//                                                               |
//                                                          BufferRecv
//                               V-------------------------------|
//                          DoBufferRecv
//                               |----------------V
//                                              Read()
//                               V----------------|
//                        BufferRecvComplete()
//                               |-------------------------------V
//                                                      BufferRecvComplete()
//                                                               |
//                                                       PostOrRunCallback()
//                               V-------------------------------|
//                        PostOrRunCallback()
//         V---------------------|
//    (Read Callback)
//
/////////////////////////////////////////////////////////////////////////////
class SSLClientSocketNSS::Core : public base::RefCountedThreadSafe<Core> {
 public:
  // Creates a new Core.
  //
  // Any calls to NSS are executed on the |nss_task_runner|, while any calls
  // that need to operate on the underlying transport, net log, or server
  // bound certificate fetching will happen on the |network_task_runner|, so
  // that their lifetimes match that of the owning SSLClientSocketNSS.
  //
  // The caller retains ownership of |transport|, |net_log|, and
  // |channel_id_service|, and they will not be accessed once Detach()
  // has been called.
  Core(base::SequencedTaskRunner* network_task_runner,
       base::SequencedTaskRunner* nss_task_runner,
       ClientSocketHandle* transport,
       const HostPortPair& host_and_port,
       const SSLConfig& ssl_config,
       BoundNetLog* net_log,
       ChannelIDService* channel_id_service);

  // Called on the network task runner.
  // Transfers ownership of |socket|, an NSS SSL socket, and |buffers|, the
  // underlying memio implementation, to the Core. Returns true if the Core
  // was successfully registered with the socket.
  bool Init(PRFileDesc* socket, memio_Private* buffers);

  // Called on the network task runner.
  //
  // Attempts to perform an SSL handshake. If the handshake cannot be
  // completed synchronously, returns ERR_IO_PENDING, invoking |callback| on
  // the network task runner once the handshake has completed. Otherwise,
  // returns OK on success or a network error code on failure.
  int Connect(const CompletionCallback& callback);

  // Called on the network task runner.
  // Signals that the resources owned by the network task runner are going
  // away. No further callbacks will be invoked on the network task runner.
  // May be called at any time.
  void Detach();

  // Called on the network task runner.
  // Returns the current state of the underlying SSL socket. May be called at
  // any time.
  const HandshakeState& state() const { return network_handshake_state_; }

  // Called on the network task runner.
  // Read() and Write() mirror the net::Socket functions of the same name.
  // If ERR_IO_PENDING is returned, |callback| will be invoked on the network
  // task runner at a later point, unless the caller calls Detach().
  int Read(IOBuffer* buf, int buf_len, const CompletionCallback& callback);
  int Write(IOBuffer* buf, int buf_len, const CompletionCallback& callback);

  // Called on the network task runner.
  bool IsConnected() const;
  bool HasPendingAsyncOperation() const;
  bool HasUnhandledReceivedData() const;
  bool WasEverUsed() const;

  // Called on the network task runner.
  // Causes the associated SSL/TLS session ID to be added to NSS's session
  // cache, but only if the connection has not been False Started.
  //
  // This should only be called after the server's certificate has been
  // verified, and may not be called within an NSS callback.
  void CacheSessionIfNecessary();

 private:
  friend class base::RefCountedThreadSafe<Core>;
  ~Core();

  enum State {
    STATE_NONE,
    STATE_HANDSHAKE,
    STATE_GET_DOMAIN_BOUND_CERT_COMPLETE,
  };

  bool OnNSSTaskRunner() const;
  bool OnNetworkTaskRunner() const;

  ////////////////////////////////////////////////////////////////////////////
  // Methods that are ONLY called on the NSS task runner:
  ////////////////////////////////////////////////////////////////////////////

  // Called by NSS during full handshakes to allow the application to
  // verify the certificate. Instead of verifying the certificate in the midst
  // of the handshake, SECSuccess is always returned and the peer's certificate
  // is verified afterwards.
  // This behaviour is an artifact of the original SSLClientSocketWin
  // implementation, which could not verify the peer's certificate until after
  // the handshake had completed, as well as bugs in NSS that prevent
  // SSL_RestartHandshakeAfterCertReq from working.
  static SECStatus OwnAuthCertHandler(void* arg,
                                      PRFileDesc* socket,
                                      PRBool checksig,
                                      PRBool is_server);

  // Callbacks called by NSS when the peer requests client certificate
  // authentication.
  // See the documentation in third_party/nss/ssl/ssl.h for the meanings of
  // the arguments.
#if defined(NSS_PLATFORM_CLIENT_AUTH)
  // When NSS has been integrated with awareness of the underlying system
  // cryptographic libraries, this callback allows the caller to supply a
  // native platform certificate and key for use by NSS. At most, one of
  // either (result_certs, result_private_key) or (result_nss_certificate,
  // result_nss_private_key) should be set.
  // |arg| contains a pointer to the current SSLClientSocketNSS::Core.
  static SECStatus PlatformClientAuthHandler(
      void* arg,
      PRFileDesc* socket,
      CERTDistNames* ca_names,
      CERTCertList** result_certs,
      void** result_private_key,
      CERTCertificate** result_nss_certificate,
      SECKEYPrivateKey** result_nss_private_key);
#else
  static SECStatus ClientAuthHandler(void* arg,
                                     PRFileDesc* socket,
                                     CERTDistNames* ca_names,
                                     CERTCertificate** result_certificate,
                                     SECKEYPrivateKey** result_private_key);
#endif

  // Called by NSS to determine if we can False Start.
  // |arg| contains a pointer to the current SSLClientSocketNSS::Core.
  static SECStatus CanFalseStartCallback(PRFileDesc* socket,
                                         void* arg,
                                         PRBool* can_false_start);

  // Called by NSS once the handshake has completed.
  // |arg| contains a pointer to the current SSLClientSocketNSS::Core.
  static void HandshakeCallback(PRFileDesc* socket, void* arg);

  // Called once the handshake has succeeded.
  void HandshakeSucceeded();

  // Handles an NSS error generated while handshaking or performing IO.
  // Returns a network error code mapped from the original NSS error.
  int HandleNSSError(PRErrorCode error);

  int DoHandshakeLoop(int last_io_result);
  int DoReadLoop(int result);
  int DoWriteLoop(int result);

  int DoHandshake();
  int DoGetDBCertComplete(int result);

  int DoPayloadRead();
  int DoPayloadWrite();

  bool DoTransportIO();
  int BufferRecv();
  int BufferSend();

  void OnRecvComplete(int result);
  void OnSendComplete(int result);

  void DoConnectCallback(int result);
  void DoReadCallback(int result);
  void DoWriteCallback(int result);

  // Client channel ID handler.
  static SECStatus ClientChannelIDHandler(
      void* arg,
      PRFileDesc* socket,
      SECKEYPublicKey **out_public_key,
      SECKEYPrivateKey **out_private_key);

  // ImportChannelIDKeys is a helper function for turning a DER-encoded cert and
  // key into a SECKEYPublicKey and SECKEYPrivateKey. Returns OK upon success
  // and an error code otherwise.
  // Requires |domain_bound_private_key_| and |domain_bound_cert_| to have been
  // set by a call to ChannelIDService->GetChannelID. The caller
  // takes ownership of the |*cert| and |*key|.
  int ImportChannelIDKeys(SECKEYPublicKey** public_key, SECKEYPrivateKey** key);

  // Updates the NSS and platform specific certificates.
  void UpdateServerCert();
  // 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
  // handshakes are ignored.
  void RecordChannelIDSupportOnNSSTaskRunner();
  // 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:
  ////////////////////////////////////////////////////////////////////////////
  int DoBufferRecv(IOBuffer* buffer, int len);
  int DoBufferSend(IOBuffer* buffer, int len);
  int DoGetChannelID(const std::string& host);

  void OnGetChannelIDComplete(int result);
  void OnHandshakeStateUpdated(const HandshakeState& state);
  void OnNSSBufferUpdated(int amount_in_read_buffer);
  void DidNSSRead(int result);
  void DidNSSWrite(int result);
  void RecordChannelIDSupportOnNetworkTaskRunner(
      bool negotiated_channel_id,
      bool channel_id_enabled,
      bool supports_ecc) const;

  ////////////////////////////////////////////////////////////////////////////
  // Methods that are called on both the network task runner and the NSS
  // task runner.
  ////////////////////////////////////////////////////////////////////////////
  void OnHandshakeIOComplete(int result);
  void BufferRecvComplete(IOBuffer* buffer, int result);
  void BufferSendComplete(int result);

  // PostOrRunCallback is a helper function to ensure that |callback| is
  // invoked on the network task runner, but only if Detach() has not yet
  // been called.
  void PostOrRunCallback(const tracked_objects::Location& location,
                         const base::Closure& callback);

  // Uses PostOrRunCallback and |weak_net_log_| to try and log a
  // SSL_CLIENT_CERT_PROVIDED event, with the indicated count.
  void AddCertProvidedEvent(int cert_count);

  // Sets the handshake state |channel_id_sent| flag and logs the
  // SSL_CHANNEL_ID_PROVIDED event.
  void SetChannelIDProvided();

  ////////////////////////////////////////////////////////////////////////////
  // Members that are ONLY accessed on the network task runner:
  ////////////////////////////////////////////////////////////////////////////

  // True if the owning SSLClientSocketNSS has called Detach(). No further
  // callbacks will be invoked nor access to members owned by the network
  // task runner.
  bool detached_;

  // The underlying transport to use for network IO.
  ClientSocketHandle* transport_;
  base::WeakPtrFactory<BoundNetLog> weak_net_log_factory_;

  // The current handshake state. Mirrors |nss_handshake_state_|.
  HandshakeState network_handshake_state_;

  // The service for retrieving Channel ID keys.  May be NULL.
  ChannelIDService* channel_id_service_;
  ChannelIDService::RequestHandle domain_bound_cert_request_handle_;

  // The information about NSS task runner.
  int unhandled_buffer_size_;
  bool nss_waiting_read_;
  bool nss_waiting_write_;
  bool nss_is_closed_;

  // Set when Read() or Write() successfully reads or writes data to or from the
  // network.
  bool was_ever_used_;

  ////////////////////////////////////////////////////////////////////////////
  // Members that are ONLY accessed on the NSS task runner:
  ////////////////////////////////////////////////////////////////////////////
  HostPortPair host_and_port_;
  SSLConfig ssl_config_;

  // NSS SSL socket.
  PRFileDesc* nss_fd_;

  // Buffers for the network end of the SSL state machine
  memio_Private* nss_bufs_;

  // Used by DoPayloadRead() when attempting to fill the caller's buffer with
  // as much data as possible, without blocking.
  // If DoPayloadRead() encounters an error after having read some data, stores
  // the results to return on the *next* call to DoPayloadRead(). A value of
  // kNoPendingReadResult indicates there is no pending result, otherwise 0
  // indicates EOF and < 0 indicates an error.
  int pending_read_result_;
  // Contains the previously observed NSS error. Only valid when
  // pending_read_result_ != kNoPendingReadResult.
  PRErrorCode pending_read_nss_error_;

  // The certificate chain, in DER form, that is expected to be received from
  // the server.
  std::vector<std::string> predicted_certs_;

  State next_handshake_state_;

  // True if channel ID extension was negotiated.
  bool channel_id_xtn_negotiated_;
  // True if the handshake state machine was interrupted for channel ID.
  bool channel_id_needed_;
  // True if the handshake state machine was interrupted for client auth.
  bool client_auth_cert_needed_;
  // True if NSS has False Started.
  bool false_started_;
  // True if NSS has called HandshakeCallback.
  bool handshake_callback_called_;

  HandshakeState nss_handshake_state_;

  bool transport_recv_busy_;
  bool transport_recv_eof_;
  bool transport_send_busy_;

  // Used by Read function.
  scoped_refptr<IOBuffer> user_read_buf_;
  int user_read_buf_len_;

  // Used by Write function.
  scoped_refptr<IOBuffer> user_write_buf_;
  int user_write_buf_len_;

  CompletionCallback user_connect_callback_;
  CompletionCallback user_read_callback_;
  CompletionCallback user_write_callback_;

  ////////////////////////////////////////////////////////////////////////////
  // Members that are accessed on both the network task runner and the NSS
  // task runner.
  ////////////////////////////////////////////////////////////////////////////
  scoped_refptr<base::SequencedTaskRunner> network_task_runner_;
  scoped_refptr<base::SequencedTaskRunner> nss_task_runner_;

  // Dereferenced only on the network task runner, but bound to tasks destined
  // for the network task runner from the NSS task runner.
  base::WeakPtr<BoundNetLog> weak_net_log_;

  // Written on the network task runner by the |channel_id_service_|,
  // prior to invoking OnHandshakeIOComplete.
  // Read on the NSS task runner when once OnHandshakeIOComplete is invoked
  // on the NSS task runner.
  std::string domain_bound_private_key_;
  std::string domain_bound_cert_;

  DISALLOW_COPY_AND_ASSIGN(Core);
};

SSLClientSocketNSS::Core::Core(
    base::SequencedTaskRunner* network_task_runner,
    base::SequencedTaskRunner* nss_task_runner,
    ClientSocketHandle* transport,
    const HostPortPair& host_and_port,
    const SSLConfig& ssl_config,
    BoundNetLog* net_log,
    ChannelIDService* channel_id_service)
    : detached_(false),
      transport_(transport),
      weak_net_log_factory_(net_log),
      channel_id_service_(channel_id_service),
      unhandled_buffer_size_(0),
      nss_waiting_read_(false),
      nss_waiting_write_(false),
      nss_is_closed_(false),
      was_ever_used_(false),
      host_and_port_(host_and_port),
      ssl_config_(ssl_config),
      nss_fd_(NULL),
      nss_bufs_(NULL),
      pending_read_result_(kNoPendingReadResult),
      pending_read_nss_error_(0),
      next_handshake_state_(STATE_NONE),
      channel_id_xtn_negotiated_(false),
      channel_id_needed_(false),
      client_auth_cert_needed_(false),
      false_started_(false),
      handshake_callback_called_(false),
      transport_recv_busy_(false),
      transport_recv_eof_(false),
      transport_send_busy_(false),
      user_read_buf_len_(0),
      user_write_buf_len_(0),
      network_task_runner_(network_task_runner),
      nss_task_runner_(nss_task_runner),
      weak_net_log_(weak_net_log_factory_.GetWeakPtr()) {
}

SSLClientSocketNSS::Core::~Core() {
  // TODO(wtc): Send SSL close_notify alert.
  if (nss_fd_ != NULL) {
    PR_Close(nss_fd_);
    nss_fd_ = NULL;
  }
  nss_bufs_ = NULL;
}

bool SSLClientSocketNSS::Core::Init(PRFileDesc* socket,
                                    memio_Private* buffers) {
  DCHECK(OnNetworkTaskRunner());
  DCHECK(!nss_fd_);
  DCHECK(!nss_bufs_);

  nss_fd_ = socket;
  nss_bufs_ = buffers;

  SECStatus rv = SECSuccess;

  if (!ssl_config_.next_protos.empty()) {
    // TODO(bnc): Check ssl_config_.disabled_cipher_suites.
    const bool adequate_encryption =
        PK11_TokenExists(CKM_AES_GCM) ||
        PK11_TokenExists(CKM_NSS_CHACHA20_POLY1305);
    const bool adequate_key_agreement = PK11_TokenExists(CKM_DH_PKCS_DERIVE) ||
                                        PK11_TokenExists(CKM_ECDH1_DERIVE);
    std::vector<uint8_t> wire_protos =
        SerializeNextProtos(ssl_config_.next_protos,
                            adequate_encryption && adequate_key_agreement &&
                                IsTLSVersionAdequateForHTTP2(ssl_config_));
    rv = SSL_SetNextProtoNego(
        nss_fd_, wire_protos.empty() ? NULL : &wire_protos[0],
        wire_protos.size());
    if (rv != SECSuccess)
      LogFailedNSSFunction(*weak_net_log_, "SSL_SetNextProtoNego", "");
    rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_ALPN, PR_TRUE);
    if (rv != SECSuccess)
      LogFailedNSSFunction(*weak_net_log_, "SSL_OptionSet", "SSL_ENABLE_ALPN");
    rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_NPN, PR_TRUE);
    if (rv != SECSuccess)
      LogFailedNSSFunction(*weak_net_log_, "SSL_OptionSet", "SSL_ENABLE_NPN");
  }

  rv = SSL_AuthCertificateHook(
      nss_fd_, SSLClientSocketNSS::Core::OwnAuthCertHandler, this);
  if (rv != SECSuccess) {
    LogFailedNSSFunction(*weak_net_log_, "SSL_AuthCertificateHook", "");
    return false;
  }

#if defined(NSS_PLATFORM_CLIENT_AUTH)
  rv = SSL_GetPlatformClientAuthDataHook(
      nss_fd_, SSLClientSocketNSS::Core::PlatformClientAuthHandler,
      this);
#else
  rv = SSL_GetClientAuthDataHook(
      nss_fd_, SSLClientSocketNSS::Core::ClientAuthHandler, this);
#endif
  if (rv != SECSuccess) {
    LogFailedNSSFunction(*weak_net_log_, "SSL_GetClientAuthDataHook", "");
    return false;
  }

  if (IsChannelIDEnabled(ssl_config_, channel_id_service_)) {
    rv = SSL_SetClientChannelIDCallback(
        nss_fd_, SSLClientSocketNSS::Core::ClientChannelIDHandler, this);
    if (rv != SECSuccess) {
      LogFailedNSSFunction(
          *weak_net_log_, "SSL_SetClientChannelIDCallback", "");
    }
  }

  rv = SSL_SetCanFalseStartCallback(
      nss_fd_, SSLClientSocketNSS::Core::CanFalseStartCallback, this);
  if (rv != SECSuccess) {
    LogFailedNSSFunction(*weak_net_log_, "SSL_SetCanFalseStartCallback", "");
    return false;
  }

  rv = SSL_HandshakeCallback(
      nss_fd_, SSLClientSocketNSS::Core::HandshakeCallback, this);
  if (rv != SECSuccess) {
    LogFailedNSSFunction(*weak_net_log_, "SSL_HandshakeCallback", "");
    return false;
  }

  return true;
}

int SSLClientSocketNSS::Core::Connect(const CompletionCallback& callback) {
  if (!OnNSSTaskRunner()) {
    DCHECK(!detached_);
    bool posted = nss_task_runner_->PostTask(
        FROM_HERE,
        base::Bind(IgnoreResult(&Core::Connect), this, callback));
    return posted ? ERR_IO_PENDING : ERR_ABORTED;
  }

  DCHECK(OnNSSTaskRunner());
  DCHECK_EQ(STATE_NONE, next_handshake_state_);
  DCHECK(user_read_callback_.is_null());
  DCHECK(user_write_callback_.is_null());
  DCHECK(user_connect_callback_.is_null());
  DCHECK(!user_read_buf_.get());
  DCHECK(!user_write_buf_.get());

  next_handshake_state_ = STATE_HANDSHAKE;
  int rv = DoHandshakeLoop(OK);
  if (rv == ERR_IO_PENDING) {
    user_connect_callback_ = callback;
  } else if (rv > OK) {
    rv = OK;
  }
  if (rv != ERR_IO_PENDING && !OnNetworkTaskRunner()) {
    PostOrRunCallback(FROM_HERE, base::Bind(callback, rv));
    return ERR_IO_PENDING;
  }

  return rv;
}

void SSLClientSocketNSS::Core::Detach() {
  DCHECK(OnNetworkTaskRunner());

  detached_ = true;
  transport_ = NULL;
  weak_net_log_factory_.InvalidateWeakPtrs();

  network_handshake_state_.Reset();

  domain_bound_cert_request_handle_.Cancel();
}

int SSLClientSocketNSS::Core::Read(IOBuffer* buf, int buf_len,
                                   const CompletionCallback& callback) {
  if (!OnNSSTaskRunner()) {
    DCHECK(OnNetworkTaskRunner());
    DCHECK(!detached_);
    DCHECK(transport_);
    DCHECK(!nss_waiting_read_);

    nss_waiting_read_ = true;
    bool posted = nss_task_runner_->PostTask(
        FROM_HERE,
        base::Bind(IgnoreResult(&Core::Read), this, make_scoped_refptr(buf),
                   buf_len, callback));
    if (!posted) {
      nss_is_closed_ = true;
      nss_waiting_read_ = false;
    }
    return posted ? ERR_IO_PENDING : ERR_ABORTED;
  }

  DCHECK(OnNSSTaskRunner());
  DCHECK(false_started_ || handshake_callback_called_);
  DCHECK_EQ(STATE_NONE, next_handshake_state_);
  DCHECK(user_read_callback_.is_null());
  DCHECK(user_connect_callback_.is_null());
  DCHECK(!user_read_buf_.get());
  DCHECK(nss_bufs_);

  user_read_buf_ = buf;
  user_read_buf_len_ = buf_len;

  int rv = DoReadLoop(OK);
  if (rv == ERR_IO_PENDING) {
    if (OnNetworkTaskRunner())
      nss_waiting_read_ = true;
    user_read_callback_ = callback;
  } else {
    user_read_buf_ = NULL;
    user_read_buf_len_ = 0;

    if (!OnNetworkTaskRunner()) {
      PostOrRunCallback(FROM_HERE, base::Bind(&Core::DidNSSRead, this, rv));
      PostOrRunCallback(FROM_HERE, base::Bind(callback, rv));
      return ERR_IO_PENDING;
    } else {
      DCHECK(!nss_waiting_read_);
      if (rv <= 0) {
        nss_is_closed_ = true;
      } else {
        was_ever_used_ = true;
      }
    }
  }

  return rv;
}

int SSLClientSocketNSS::Core::Write(IOBuffer* buf, int buf_len,
                                    const CompletionCallback& callback) {
  if (!OnNSSTaskRunner()) {
    DCHECK(OnNetworkTaskRunner());
    DCHECK(!detached_);
    DCHECK(transport_);
    DCHECK(!nss_waiting_write_);

    nss_waiting_write_ = true;
    bool posted = nss_task_runner_->PostTask(
        FROM_HERE,
        base::Bind(IgnoreResult(&Core::Write), this, make_scoped_refptr(buf),
                   buf_len, callback));
    if (!posted) {
      nss_is_closed_ = true;
      nss_waiting_write_ = false;
    }
    return posted ? ERR_IO_PENDING : ERR_ABORTED;
  }

  DCHECK(OnNSSTaskRunner());
  DCHECK(false_started_ || handshake_callback_called_);
  DCHECK_EQ(STATE_NONE, next_handshake_state_);
  DCHECK(user_write_callback_.is_null());
  DCHECK(user_connect_callback_.is_null());
  DCHECK(!user_write_buf_.get());
  DCHECK(nss_bufs_);

  user_write_buf_ = buf;
  user_write_buf_len_ = buf_len;

  int rv = DoWriteLoop(OK);
  if (rv == ERR_IO_PENDING) {
    if (OnNetworkTaskRunner())
      nss_waiting_write_ = true;
    user_write_callback_ = callback;
  } else {
    user_write_buf_ = NULL;
    user_write_buf_len_ = 0;

    if (!OnNetworkTaskRunner()) {
      PostOrRunCallback(FROM_HERE, base::Bind(&Core::DidNSSWrite, this, rv));
      PostOrRunCallback(FROM_HERE, base::Bind(callback, rv));
      return ERR_IO_PENDING;
    } else {
      DCHECK(!nss_waiting_write_);
      if (rv < 0) {
        nss_is_closed_ = true;
      } else if (rv > 0) {
        was_ever_used_ = true;
      }
    }
  }

  return rv;
}

bool SSLClientSocketNSS::Core::IsConnected() const {
  DCHECK(OnNetworkTaskRunner());
  return !nss_is_closed_;
}

bool SSLClientSocketNSS::Core::HasPendingAsyncOperation() const {
  DCHECK(OnNetworkTaskRunner());
  return nss_waiting_read_ || nss_waiting_write_;
}

bool SSLClientSocketNSS::Core::HasUnhandledReceivedData() const {
  DCHECK(OnNetworkTaskRunner());
  return unhandled_buffer_size_ != 0;
}

bool SSLClientSocketNSS::Core::WasEverUsed() const {
  DCHECK(OnNetworkTaskRunner());
  return was_ever_used_;
}

void SSLClientSocketNSS::Core::CacheSessionIfNecessary() {
  // TODO(rsleevi): This should occur on the NSS task runner, due to the use of
  // nss_fd_. However, it happens on the network task runner in order to match
  // the buggy behavior of ExportKeyingMaterial.
  //
  // Once http://crbug.com/330360 is fixed, this should be moved to an
  // implementation that exclusively does this work on the NSS TaskRunner. This
  // is "safe" because it is only called during the certificate verification
  // state machine of the main socket, which is safe because no underlying
  // transport IO will be occuring in that state, and NSS will not be blocking
  // on any PKCS#11 related locks that might block the Network TaskRunner.
  DCHECK(OnNetworkTaskRunner());

  // Only cache the session if the connection was not False Started, because
  // sessions should only be cached *after* the peer's Finished message is
  // processed.
  // In the case of False Start, the session will be cached once the
  // HandshakeCallback is called, which signals the receipt and processing of
  // the Finished message, and which will happen during a call to
  // PR_Read/PR_Write.
  if (!false_started_)
    SSL_CacheSession(nss_fd_);
}

bool SSLClientSocketNSS::Core::OnNSSTaskRunner() const {
  return nss_task_runner_->RunsTasksOnCurrentThread();
}

bool SSLClientSocketNSS::Core::OnNetworkTaskRunner() const {
  return network_task_runner_->RunsTasksOnCurrentThread();
}

// static
SECStatus SSLClientSocketNSS::Core::OwnAuthCertHandler(
    void* arg,
    PRFileDesc* socket,
    PRBool checksig,
    PRBool is_server) {
  Core* core = reinterpret_cast<Core*>(arg);
  if (core->handshake_callback_called_) {
    // Disallow the server certificate to change in a renegotiation.
    CERTCertificate* old_cert = core->nss_handshake_state_.server_cert_chain[0];
    ScopedCERTCertificate new_cert(SSL_PeerCertificate(socket));
    if (new_cert->derCert.len != old_cert->derCert.len ||
        memcmp(new_cert->derCert.data, old_cert->derCert.data,
               new_cert->derCert.len) != 0) {
      // NSS doesn't have an error code that indicates the server certificate
      // changed. Borrow SSL_ERROR_WRONG_CERTIFICATE (which NSS isn't using)
      // for this purpose.
      PORT_SetError(SSL_ERROR_WRONG_CERTIFICATE);
      return SECFailure;
    }
  }

  // Tell NSS to not verify the certificate.
  return SECSuccess;
}

#if defined(NSS_PLATFORM_CLIENT_AUTH)
// static
SECStatus SSLClientSocketNSS::Core::PlatformClientAuthHandler(
    void* arg,
    PRFileDesc* socket,
    CERTDistNames* ca_names,
    CERTCertList** result_certs,
    void** result_private_key,
    CERTCertificate** result_nss_certificate,
    SECKEYPrivateKey** result_nss_private_key) {
  Core* core = reinterpret_cast<Core*>(arg);
  DCHECK(core->OnNSSTaskRunner());

  core->PostOrRunCallback(
      FROM_HERE,
      base::Bind(&AddLogEvent, core->weak_net_log_,
                 NetLog::TYPE_SSL_CLIENT_CERT_REQUESTED));

  core->client_auth_cert_needed_ = !core->ssl_config_.send_client_cert;
#if defined(OS_WIN)
  if (core->ssl_config_.send_client_cert) {
    if (core->ssl_config_.client_cert.get()) {
      PCCERT_CONTEXT cert_context =
          core->ssl_config_.client_cert->os_cert_handle();

      HCRYPTPROV_OR_NCRYPT_KEY_HANDLE crypt_prov = 0;
      DWORD key_spec = 0;
      BOOL must_free = FALSE;
      DWORD flags = 0;
      if (base::win::GetVersion() >= base::win::VERSION_VISTA)
        flags |= CRYPT_ACQUIRE_PREFER_NCRYPT_KEY_FLAG;

      BOOL acquired_key = CryptAcquireCertificatePrivateKey(
          cert_context, flags, NULL, &crypt_prov, &key_spec, &must_free);

      if (acquired_key) {
        // Should never get a cached handle back - ownership must always be
        // transferred.
        CHECK_EQ(must_free, TRUE);

        SECItem der_cert;
        der_cert.type = siDERCertBuffer;
        der_cert.data = cert_context->pbCertEncoded;
        der_cert.len  = cert_context->cbCertEncoded;

        // TODO(rsleevi): Error checking for NSS allocation errors.
        CERTCertDBHandle* db_handle = CERT_GetDefaultCertDB();
        CERTCertificate* user_cert = CERT_NewTempCertificate(
            db_handle, &der_cert, NULL, PR_FALSE, PR_TRUE);
        if (!user_cert) {
          // Importing the certificate can fail for reasons including a serial
          // number collision. See crbug.com/97355.
          core->AddCertProvidedEvent(0);
          return SECFailure;
        }
        CERTCertList* cert_chain = CERT_NewCertList();
        CERT_AddCertToListTail(cert_chain, user_cert);

        // Add the intermediates.
        X509Certificate::OSCertHandles intermediates =
            core->ssl_config_.client_cert->GetIntermediateCertificates();
        for (X509Certificate::OSCertHandles::const_iterator it =
            intermediates.begin(); it != intermediates.end(); ++it) {
          der_cert.data = (*it)->pbCertEncoded;
          der_cert.len = (*it)->cbCertEncoded;

          CERTCertificate* intermediate = CERT_NewTempCertificate(
              db_handle, &der_cert, NULL, PR_FALSE, PR_TRUE);
          if (!intermediate) {
            CERT_DestroyCertList(cert_chain);
            core->AddCertProvidedEvent(0);
            return SECFailure;
          }
          CERT_AddCertToListTail(cert_chain, intermediate);
        }
        PCERT_KEY_CONTEXT key_context = reinterpret_cast<PCERT_KEY_CONTEXT>(
            PORT_ZAlloc(sizeof(CERT_KEY_CONTEXT)));
        key_context->cbSize = sizeof(*key_context);
        // NSS will free this context when no longer in use.
        key_context->hCryptProv = crypt_prov;
        key_context->dwKeySpec = key_spec;
        *result_private_key = key_context;
        *result_certs = cert_chain;

        int cert_count = 1 + intermediates.size();
        core->AddCertProvidedEvent(cert_count);
        return SECSuccess;
      }
      LOG(WARNING) << "Client cert found without private key";
    }

    // Send no client certificate.
    core->AddCertProvidedEvent(0);
    return SECFailure;
  }

  core->nss_handshake_state_.cert_authorities.clear();

  std::vector<CERT_NAME_BLOB> issuer_list(ca_names->nnames);
  for (int i = 0; i < ca_names->nnames; ++i) {
    issuer_list[i].cbData = ca_names->names[i].len;
    issuer_list[i].pbData = ca_names->names[i].data;
    core->nss_handshake_state_.cert_authorities.push_back(std::string(
        reinterpret_cast<const char*>(ca_names->names[i].data),
        static_cast<size_t>(ca_names->names[i].len)));
  }

  // Update the network task runner's view of the handshake state now that
  // server certificate request has been recorded.
  core->PostOrRunCallback(
      FROM_HERE, base::Bind(&Core::OnHandshakeStateUpdated, core,
                            core->nss_handshake_state_));

  // Tell NSS to suspend the client authentication.  We will then abort the
  // handshake by returning ERR_SSL_CLIENT_AUTH_CERT_NEEDED.
  return SECWouldBlock;
#elif defined(OS_MACOSX)
  if (core->ssl_config_.send_client_cert) {
    if (core->ssl_config_.client_cert.get()) {
      OSStatus os_error = noErr;
      SecIdentityRef identity = NULL;
      SecKeyRef private_key = NULL;
      X509Certificate::OSCertHandles chain;
      {
        base::AutoLock lock(crypto::GetMacSecurityServicesLock());
        os_error = SecIdentityCreateWithCertificate(
            NULL, core->ssl_config_.client_cert->os_cert_handle(), &identity);
      }
      if (os_error == noErr) {
        os_error = SecIdentityCopyPrivateKey(identity, &private_key);
        CFRelease(identity);
      }

      if (os_error == noErr) {
        // TODO(rsleevi): Error checking for NSS allocation errors.
        *result_certs = CERT_NewCertList();
        *result_private_key = private_key;

        chain.push_back(core->ssl_config_.client_cert->os_cert_handle());
        const X509Certificate::OSCertHandles& intermediates =
            core->ssl_config_.client_cert->GetIntermediateCertificates();
        if (!intermediates.empty())
          chain.insert(chain.end(), intermediates.begin(), intermediates.end());

        for (size_t i = 0, chain_count = chain.size(); i < chain_count; ++i) {
          CSSM_DATA cert_data;
          SecCertificateRef cert_ref = chain[i];
          os_error = SecCertificateGetData(cert_ref, &cert_data);
          if (os_error != noErr)
            break;

          SECItem der_cert;
          der_cert.type = siDERCertBuffer;
          der_cert.data = cert_data.Data;
          der_cert.len = cert_data.Length;
          CERTCertificate* nss_cert = CERT_NewTempCertificate(
              CERT_GetDefaultCertDB(), &der_cert, NULL, PR_FALSE, PR_TRUE);
          if (!nss_cert) {
            // In the event of an NSS error, make up an OS error and reuse
            // the error handling below.
            os_error = errSecCreateChainFailed;
            break;
          }
          CERT_AddCertToListTail(*result_certs, nss_cert);
        }
      }

      if (os_error == noErr) {
        core->AddCertProvidedEvent(chain.size());
        return SECSuccess;
      }

      OSSTATUS_LOG(WARNING, os_error)
          << "Client cert found, but could not be used";
      if (*result_certs) {
        CERT_DestroyCertList(*result_certs);
        *result_certs = NULL;
      }
      if (*result_private_key)
        *result_private_key = NULL;
      if (private_key)
        CFRelease(private_key);
    }

    // Send no client certificate.
    core->AddCertProvidedEvent(0);
    return SECFailure;
  }

  core->nss_handshake_state_.cert_authorities.clear();

  // Retrieve the cert issuers accepted by the server.
  std::vector<CertPrincipal> valid_issuers;
  int n = ca_names->nnames;
  for (int i = 0; i < n; i++) {
    core->nss_handshake_state_.cert_authorities.push_back(std::string(
        reinterpret_cast<const char*>(ca_names->names[i].data),
        static_cast<size_t>(ca_names->names[i].len)));
  }

  // Update the network task runner's view of the handshake state now that
  // server certificate request has been recorded.
  core->PostOrRunCallback(
      FROM_HERE, base::Bind(&Core::OnHandshakeStateUpdated, core,
                            core->nss_handshake_state_));

  // Tell NSS to suspend the client authentication.  We will then abort the
  // handshake by returning ERR_SSL_CLIENT_AUTH_CERT_NEEDED.
  return SECWouldBlock;
#else
  return SECFailure;
#endif
}

#elif defined(OS_IOS)

SECStatus SSLClientSocketNSS::Core::ClientAuthHandler(
    void* arg,
    PRFileDesc* socket,
    CERTDistNames* ca_names,
    CERTCertificate** result_certificate,
    SECKEYPrivateKey** result_private_key) {
  Core* core = reinterpret_cast<Core*>(arg);
  DCHECK(core->OnNSSTaskRunner());

  core->PostOrRunCallback(
      FROM_HERE,
      base::Bind(&AddLogEvent, core->weak_net_log_,
                 NetLog::TYPE_SSL_CLIENT_CERT_REQUESTED));

  // TODO(droger): Support client auth on iOS. See http://crbug.com/145954).
  LOG(WARNING) << "Client auth is not supported";

  // Never send a certificate.
  core->AddCertProvidedEvent(0);
  return SECFailure;
}

#else  // NSS_PLATFORM_CLIENT_AUTH

// static
// Based on Mozilla's NSS_GetClientAuthData.
SECStatus SSLClientSocketNSS::Core::ClientAuthHandler(
    void* arg,
    PRFileDesc* socket,
    CERTDistNames* ca_names,
    CERTCertificate** result_certificate,
    SECKEYPrivateKey** result_private_key) {
  Core* core = reinterpret_cast<Core*>(arg);
  DCHECK(core->OnNSSTaskRunner());

  core->PostOrRunCallback(
      FROM_HERE,
      base::Bind(&AddLogEvent, core->weak_net_log_,
                 NetLog::TYPE_SSL_CLIENT_CERT_REQUESTED));

  // Regular client certificate requested.
  core->client_auth_cert_needed_ = !core->ssl_config_.send_client_cert;
  void* wincx  = SSL_RevealPinArg(socket);

  if (core->ssl_config_.send_client_cert) {
    // Second pass: a client certificate should have been selected.
    if (core->ssl_config_.client_cert.get()) {
      CERTCertificate* cert =
          CERT_DupCertificate(core->ssl_config_.client_cert->os_cert_handle());
      SECKEYPrivateKey* privkey = PK11_FindKeyByAnyCert(cert, wincx);
      if (privkey) {
        // TODO(jsorianopastor): We should wait for server certificate
        // verification before sending our credentials.  See
        // http://crbug.com/13934.
        *result_certificate = cert;
        *result_private_key = privkey;
        // A cert_count of -1 means the number of certificates is unknown.
        // NSS will construct the certificate chain.
        core->AddCertProvidedEvent(-1);

        return SECSuccess;
      }
      LOG(WARNING) << "Client cert found without private key";
    }
    // Send no client certificate.
    core->AddCertProvidedEvent(0);
    return SECFailure;
  }

  // First pass: client certificate is needed.
  core->nss_handshake_state_.cert_authorities.clear();

  // Retrieve the DER-encoded DistinguishedName of the cert issuers accepted by
  // the server and save them in |cert_authorities|.
  for (int i = 0; i < ca_names->nnames; i++) {
    core->nss_handshake_state_.cert_authorities.push_back(std::string(
        reinterpret_cast<const char*>(ca_names->names[i].data),
        static_cast<size_t>(ca_names->names[i].len)));
  }

  // Update the network task runner's view of the handshake state now that
  // server certificate request has been recorded.
  core->PostOrRunCallback(
      FROM_HERE, base::Bind(&Core::OnHandshakeStateUpdated, core,
                            core->nss_handshake_state_));

  // Tell NSS to suspend the client authentication.  We will then abort the
  // handshake by returning ERR_SSL_CLIENT_AUTH_CERT_NEEDED.
  return SECWouldBlock;
}
#endif  // NSS_PLATFORM_CLIENT_AUTH

// static
SECStatus SSLClientSocketNSS::Core::CanFalseStartCallback(
    PRFileDesc* socket,
    void* arg,
    PRBool* can_false_start) {
  // If the server doesn't support NPN or ALPN, then we don't do False
  // Start with it.
  PRBool negotiated_extension;
  SECStatus rv = SSL_HandshakeNegotiatedExtension(socket,
                                                  ssl_app_layer_protocol_xtn,
                                                  &negotiated_extension);
  if (rv != SECSuccess || !negotiated_extension) {
    rv = SSL_HandshakeNegotiatedExtension(socket,
                                          ssl_next_proto_nego_xtn,
                                          &negotiated_extension);
  }
  if (rv != SECSuccess || !negotiated_extension) {
    *can_false_start = PR_FALSE;
    return SECSuccess;
  }

  return SSL_RecommendedCanFalseStart(socket, can_false_start);
}

// static
void SSLClientSocketNSS::Core::HandshakeCallback(
    PRFileDesc* socket,
    void* arg) {
  Core* core = reinterpret_cast<Core*>(arg);
  DCHECK(core->OnNSSTaskRunner());

  core->handshake_callback_called_ = true;
  if (core->false_started_) {
    core->false_started_ = false;
    // If the connection was False Started, then at the time of this callback,
    // the peer's certificate will have been verified or the caller will have
    // accepted the error.
    // This is guaranteed when using False Start because this callback will
    // not be invoked until processing the peer's Finished message, which
    // will only happen in a PR_Read/PR_Write call, which can only happen
    // after the peer's certificate is verified.
    SSL_CacheSessionUnlocked(socket);

    // Additionally, when False Starting, DoHandshake() will have already
    // called HandshakeSucceeded(), so return now.
    return;
  }
  core->HandshakeSucceeded();
}

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;
  SECStatus rv = SSL_HandshakeResumedSession(nss_fd_, &last_handshake_resumed);
  if (rv == SECSuccess && last_handshake_resumed) {
    nss_handshake_state_.resumed_handshake = true;
  } else {
    nss_handshake_state_.resumed_handshake = false;
  }

  RecordChannelIDSupportOnNSSTaskRunner();
  UpdateServerCert();
  UpdateSignedCertTimestamps();
  UpdateStapledOCSPResponse();
  UpdateConnectionStatus();
  UpdateNextProto();
  UpdateExtensionUsed();

  // Update the network task runners view of the handshake state whenever
  // a handshake has completed.
  PostOrRunCallback(
      FROM_HERE, base::Bind(&Core::OnHandshakeStateUpdated, this,
                            nss_handshake_state_));
}

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);

#if defined(OS_WIN)
  // On Windows, a handle to the HCRYPTPROV is cached in the X509Certificate
  // os_cert_handle() as an optimization. However, if the certificate
  // private key is stored on a smart card, and the smart card is removed,
  // the cached HCRYPTPROV will not be able to obtain the HCRYPTKEY again,
  // preventing client certificate authentication. Because the
  // X509Certificate may outlive the individual SSLClientSocketNSS, due to
  // caching in X509Certificate, this failure ends up preventing client
  // certificate authentication with the same certificate for all future
  // attempts, even after the smart card has been re-inserted. By setting
  // the CERT_KEY_PROV_HANDLE_PROP_ID to NULL, the cached HCRYPTPROV will
  // typically be freed. This allows a new HCRYPTPROV to be obtained from
  // the certificate on the next attempt, which should succeed if the smart
  // card has been re-inserted, or will typically prompt the user to
  // re-insert the smart card if not.
  if ((net_error == ERR_SSL_CLIENT_AUTH_CERT_NO_PRIVATE_KEY ||
       net_error == ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED) &&
      ssl_config_.send_client_cert && ssl_config_.client_cert.get()) {
    CertSetCertificateContextProperty(
        ssl_config_.client_cert->os_cert_handle(),
        CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
  }
#endif

  return net_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;
  do {
    // Default to STATE_NONE for next state.
    State state = next_handshake_state_;
    GotoState(STATE_NONE);

    switch (state) {
      case STATE_HANDSHAKE:
        rv = DoHandshake();
        break;
      case STATE_GET_DOMAIN_BOUND_CERT_COMPLETE:
        rv = DoGetDBCertComplete(rv);
        break;
      case STATE_NONE:
      default:
        rv = ERR_UNEXPECTED;
        LOG(DFATAL) << "unexpected state " << state;
        break;
    }

    // Do the actual network I/O
    bool network_moved = DoTransportIO();
    if (network_moved && next_handshake_state_ == STATE_HANDSHAKE) {
      // In general we exit the loop if rv is ERR_IO_PENDING.  In this
      // special case we keep looping even if rv is ERR_IO_PENDING because
      // the transport IO may allow DoHandshake to make progress.
      DCHECK(rv == OK || rv == ERR_IO_PENDING);
      rv = OK;  // This causes us to stay in the loop.
    }
  } while (rv != ERR_IO_PENDING && next_handshake_state_ != STATE_NONE);
  return rv;
}

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_);

  if (result < 0)
    return result;

  if (!nss_bufs_) {
    LOG(DFATAL) << "!nss_bufs_";
    int rv = ERR_UNEXPECTED;
    PostOrRunCallback(
        FROM_HERE,
        base::Bind(&AddLogEventWithCallback, weak_net_log_,
                   NetLog::TYPE_SSL_READ_ERROR,
                   CreateNetLogSSLErrorCallback(rv, 0)));
    return rv;
  }

  bool network_moved;
  int rv;
  do {
    rv = DoPayloadRead();
    network_moved = DoTransportIO();
  } while (rv == ERR_IO_PENDING && network_moved);

  return rv;
}

int SSLClientSocketNSS::Core::DoWriteLoop(int result) {
  DCHECK(OnNSSTaskRunner());
  DCHECK(false_started_ || handshake_callback_called_);
  DCHECK_EQ(STATE_NONE, next_handshake_state_);

  if (result < 0)
    return result;

  if (!nss_bufs_) {
    LOG(DFATAL) << "!nss_bufs_";
    int rv = ERR_UNEXPECTED;
    PostOrRunCallback(
        FROM_HERE,
        base::Bind(&AddLogEventWithCallback, weak_net_log_,
                   NetLog::TYPE_SSL_READ_ERROR,
                   CreateNetLogSSLErrorCallback(rv, 0)));
    return rv;
  }

  bool network_moved;
  int rv;
  do {
    rv = DoPayloadWrite();
    network_moved = DoTransportIO();
  } while (rv == ERR_IO_PENDING && network_moved);

  LeaveFunction(rv);
  return rv;
}

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.
  if (channel_id_needed_) {
    GotoState(STATE_GET_DOMAIN_BOUND_CERT_COMPLETE);
    net_error = ERR_IO_PENDING;
  } else if (client_auth_cert_needed_) {
    net_error = ERR_SSL_CLIENT_AUTH_CERT_NEEDED;
    PostOrRunCallback(
        FROM_HERE,
        base::Bind(&AddLogEventWithCallback, weak_net_log_,
                   NetLog::TYPE_SSL_HANDSHAKE_ERROR,
                   CreateNetLogSSLErrorCallback(net_error, 0)));

    // If the handshake already succeeded (because the server requests but
    // doesn't require a client cert), we need to invalidate the SSL session
    // so that we won't try to resume the non-client-authenticated session in
    // the next handshake.  This will cause the server to ask for a client
    // cert again.
    if (rv == SECSuccess && SSL_InvalidateSession(nss_fd_) != SECSuccess)
      LOG(WARNING) << "Couldn't invalidate SSL session: " << PR_GetError();
  } else if (rv == SECSuccess) {
    if (!handshake_callback_called_) {
      false_started_ = true;
      HandshakeSucceeded();
    }
  } else {
    PRErrorCode prerr = PR_GetError();
    net_error = HandleNSSError(prerr);

    // If not done, stay in this state
    if (net_error == ERR_IO_PENDING) {
      GotoState(STATE_HANDSHAKE);
    } else {
      PostOrRunCallback(
          FROM_HERE,
          base::Bind(&AddLogEventWithCallback, weak_net_log_,
                     NetLog::TYPE_SSL_HANDSHAKE_ERROR,
                     CreateNetLogSSLErrorCallback(net_error, prerr)));
    }
  }

  return net_error;
}

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,
      base::Bind(&BoundNetLog::EndEventWithNetErrorCode, weak_net_log_,
                 NetLog::TYPE_SSL_GET_DOMAIN_BOUND_CERT, result));

  channel_id_needed_ = false;

  if (result != OK)
    return result;

  SECKEYPublicKey* public_key;
  SECKEYPrivateKey* private_key;
  int error = ImportChannelIDKeys(&public_key, &private_key);
  if (error != OK)
    return error;

  rv = SSL_RestartHandshakeAfterChannelIDReq(nss_fd_, public_key, private_key);
  if (rv != SECSuccess)
    return MapNSSError(PORT_GetError());

  SetChannelIDProvided();
  GotoState(STATE_HANDSHAKE);
  return OK;
}

int SSLClientSocketNSS::Core::DoPayloadRead() {
  DCHECK(OnNSSTaskRunner());
  DCHECK(user_read_buf_.get());
  DCHECK_GT(user_read_buf_len_, 0);

  int rv;
  // If a previous greedy read resulted in an error that was not consumed (eg:
  // due to the caller having read some data successfully), then return that
  // pending error now.
  if (pending_read_result_ != kNoPendingReadResult) {
    rv = pending_read_result_;
    PRErrorCode prerr = pending_read_nss_error_;
    pending_read_result_ = kNoPendingReadResult;
    pending_read_nss_error_ = 0;

    if (rv == 0) {
      PostOrRunCallback(
          FROM_HERE,
          base::Bind(&LogByteTransferEvent, weak_net_log_,
                     NetLog::TYPE_SSL_SOCKET_BYTES_RECEIVED, rv,
                     scoped_refptr<IOBuffer>(user_read_buf_)));
    } else {
      PostOrRunCallback(
          FROM_HERE,
          base::Bind(&AddLogEventWithCallback, weak_net_log_,
                     NetLog::TYPE_SSL_READ_ERROR,
                     CreateNetLogSSLErrorCallback(rv, prerr)));
    }
    return rv;
  }

  // Perform a greedy read, attempting to read as much as the caller has
  // requested. In the current NSS implementation, PR_Read will return
  // exactly one SSL application data record's worth of data per invocation.
  // The record size is dictated by the server, and may be noticeably smaller
  // than the caller's buffer. This may be as little as a single byte, if the
  // server is performing 1/n-1 record splitting.
  //
  // However, this greedy read may result in renegotiations/re-handshakes
  // happening or may lead to some data being read, followed by an EOF (such as
  // a TLS close-notify). If at least some data was read, then that result
  // should be deferred until the next call to DoPayloadRead(). Otherwise, if no
  // data was read, it's safe to return the error or EOF immediately.
  int total_bytes_read = 0;
  do {
    rv = PR_Read(nss_fd_, user_read_buf_->data() + total_bytes_read,
                 user_read_buf_len_ - total_bytes_read);
    if (rv > 0)
      total_bytes_read += rv;
  } while (total_bytes_read < user_read_buf_len_ && rv > 0);
  int amount_in_read_buffer = memio_GetReadableBufferSize(nss_bufs_);
  PostOrRunCallback(FROM_HERE, base::Bind(&Core::OnNSSBufferUpdated, this,
                                          amount_in_read_buffer));

  if (total_bytes_read == user_read_buf_len_) {
    // The caller's entire request was satisfied without error. No further
    // processing needed.
    rv = total_bytes_read;
  } else {
    // Otherwise, an error occurred (rv <= 0). The error needs to be handled
    // immediately, while the NSPR/NSS errors are still available in
    // thread-local storage. However, the handled/remapped error code should
    // only be returned if no application data was already read; if it was, the
    // error code should be deferred until the next call of DoPayloadRead.
    //
    // If no data was read, |*next_result| will point to the return value of
    // this function. If at least some data was read, |*next_result| will point
    // to |pending_read_error_|, to be returned in a future call to
    // DoPayloadRead() (e.g.: after the current data is handled).
    int* next_result = &rv;
    if (total_bytes_read > 0) {
      pending_read_result_ = rv;
      rv = total_bytes_read;
      next_result = &pending_read_result_;
    }

    if (client_auth_cert_needed_) {
      *next_result = ERR_SSL_CLIENT_AUTH_CERT_NEEDED;
      pending_read_nss_error_ = 0;
    } else if (*next_result < 0) {
      // If *next_result == 0, then that indicates EOF, and no special error
      // handling is needed.
      pending_read_nss_error_ = PR_GetError();
      *next_result = HandleNSSError(pending_read_nss_error_);
      if (rv > 0 && *next_result == ERR_IO_PENDING) {
        // If at least some data was read from PR_Read(), do not treat
        // insufficient data as an error to return in the next call to
        // DoPayloadRead() - instead, let the call fall through to check
        // PR_Read() again. This is because DoTransportIO() may complete
        // in between the next call to DoPayloadRead(), and thus it is
        // important to check PR_Read() on subsequent invocations to see
        // if a complete record may now be read.
        pending_read_nss_error_ = 0;
        pending_read_result_ = kNoPendingReadResult;
      }
    }
  }

  DCHECK_NE(ERR_IO_PENDING, pending_read_result_);

  if (rv >= 0) {
    PostOrRunCallback(
        FROM_HERE,
        base::Bind(&LogByteTransferEvent, weak_net_log_,
                   NetLog::TYPE_SSL_SOCKET_BYTES_RECEIVED, rv,
                   scoped_refptr<IOBuffer>(user_read_buf_)));
  } else if (rv != ERR_IO_PENDING) {
    PostOrRunCallback(
        FROM_HERE,
        base::Bind(&AddLogEventWithCallback, weak_net_log_,
                   NetLog::TYPE_SSL_READ_ERROR,
                   CreateNetLogSSLErrorCallback(rv, pending_read_nss_error_)));
    pending_read_nss_error_ = 0;
  }
  return rv;
}

int SSLClientSocketNSS::Core::DoPayloadWrite() {
  DCHECK(OnNSSTaskRunner());

  DCHECK(user_write_buf_.get());

  int old_amount_in_read_buffer = memio_GetReadableBufferSize(nss_bufs_);
  int rv = PR_Write(nss_fd_, user_write_buf_->data(), user_write_buf_len_);
  int new_amount_in_read_buffer = memio_GetReadableBufferSize(nss_bufs_);
  // PR_Write could potentially consume the unhandled data in the memio read
  // buffer if a renegotiation is in progress. If the buffer is consumed,
  // notify the latest buffer size to NetworkRunner.
  if (old_amount_in_read_buffer != new_amount_in_read_buffer) {
    PostOrRunCallback(
        FROM_HERE,
        base::Bind(&Core::OnNSSBufferUpdated, this, new_amount_in_read_buffer));
  }
  if (rv >= 0) {
    PostOrRunCallback(
        FROM_HERE,
        base::Bind(&LogByteTransferEvent, weak_net_log_,
                   NetLog::TYPE_SSL_SOCKET_BYTES_SENT, rv,
                   scoped_refptr<IOBuffer>(user_write_buf_)));
    return rv;
  }
  PRErrorCode prerr = PR_GetError();
  if (prerr == PR_WOULD_BLOCK_ERROR)
    return ERR_IO_PENDING;

  rv = HandleNSSError(prerr);
  PostOrRunCallback(
      FROM_HERE,
      base::Bind(&AddLogEventWithCallback, weak_net_log_,
                 NetLog::TYPE_SSL_WRITE_ERROR,
                 CreateNetLogSSLErrorCallback(rv, prerr)));
  return rv;
}

// Do as much network I/O as possible between the buffer and the
// 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;
  if (nss_bufs_ != NULL) {
    int rv;
    // Read and write as much data as we can. The loop is neccessary
    // because Write() may return synchronously.
    do {
      rv = BufferSend();
      if (rv != ERR_IO_PENDING && rv != 0)
        network_moved = true;
    } while (rv > 0);
    if (!transport_recv_eof_ && BufferRecv() != ERR_IO_PENDING)
      network_moved = true;
  }
  return network_moved;
}

int SSLClientSocketNSS::Core::BufferRecv() {
  DCHECK(OnNSSTaskRunner());

  if (transport_recv_busy_)
    return ERR_IO_PENDING;

  // If NSS is blocked on reading from |nss_bufs_|, because it is empty,
  // determine how much data NSS wants to read. If NSS was not blocked,
  // this will return 0.
  int requested = memio_GetReadRequest(nss_bufs_);
  if (requested == 0) {
    // This is not a perfect match of error codes, as no operation is
    // actually pending. However, returning 0 would be interpreted as a
    // possible sign of EOF, which is also an inappropriate match.
    return ERR_IO_PENDING;
  }

  char* buf;
  int nb = memio_GetReadParams(nss_bufs_, &buf);
  int rv;
  if (!nb) {
    // buffer too full to read into, so no I/O possible at moment
    rv = ERR_IO_PENDING;
  } else {
    scoped_refptr<IOBuffer> read_buffer(new IOBuffer(nb));
    if (OnNetworkTaskRunner()) {
      rv = DoBufferRecv(read_buffer.get(), nb);
    } else {
      bool posted = network_task_runner_->PostTask(
          FROM_HERE,
          base::Bind(IgnoreResult(&Core::DoBufferRecv), this, read_buffer,
                     nb));
      rv = posted ? ERR_IO_PENDING : ERR_ABORTED;
    }

    if (rv == ERR_IO_PENDING) {
      transport_recv_busy_ = true;
    } else {
      if (rv > 0) {
        memcpy(buf, read_buffer->data(), rv);
      } else if (rv == 0) {
        transport_recv_eof_ = true;
      }
      memio_PutReadResult(nss_bufs_, MapErrorToNSS(rv));
    }
  }
  return rv;
}

// Return 0 if nss_bufs_ was empty,
// > 0 for bytes transferred immediately,
// < 0 for error (or the non-error ERR_IO_PENDING).
int SSLClientSocketNSS::Core::BufferSend() {
  DCHECK(OnNSSTaskRunner());

  if (transport_send_busy_)
    return ERR_IO_PENDING;

  const char* buf1;
  const char* buf2;
  unsigned int len1, len2;
  if (memio_GetWriteParams(nss_bufs_, &buf1, &len1, &buf2, &len2)) {
    // It is important this return synchronously to prevent spinning infinitely
    // in the off-thread NSS case. The error code itself is ignored, so just
    // return ERR_ABORTED. See https://crbug.com/381160.
    return ERR_ABORTED;
  }
  const unsigned int len = len1 + len2;

  int rv = 0;
  if (len) {
    scoped_refptr<IOBuffer> send_buffer(new IOBuffer(len));
    memcpy(send_buffer->data(), buf1, len1);
    memcpy(send_buffer->data() + len1, buf2, len2);

    if (OnNetworkTaskRunner()) {
      rv = DoBufferSend(send_buffer.get(), len);
    } else {
      bool posted = network_task_runner_->PostTask(
          FROM_HERE,
          base::Bind(IgnoreResult(&Core::DoBufferSend), this, send_buffer,
                     len));
      rv = posted ? ERR_IO_PENDING : ERR_ABORTED;
    }

    if (rv == ERR_IO_PENDING) {
      transport_send_busy_ = true;
    } else {
      memio_PutWriteResult(nss_bufs_, MapErrorToNSS(rv));
    }
  }

  return rv;
}

void SSLClientSocketNSS::Core::OnRecvComplete(int result) {
  DCHECK(OnNSSTaskRunner());

  if (next_handshake_state_ == STATE_HANDSHAKE) {
    OnHandshakeIOComplete(result);
    return;
  }

  // Network layer received some data, check if client requested to read
  // decrypted data.
  if (!user_read_buf_.get())
    return;

  int rv = DoReadLoop(result);
  if (rv != ERR_IO_PENDING)
    DoReadCallback(rv);
}

void SSLClientSocketNSS::Core::OnSendComplete(int result) {
  DCHECK(OnNSSTaskRunner());

  if (next_handshake_state_ == STATE_HANDSHAKE) {
    OnHandshakeIOComplete(result);
    return;
  }

  // OnSendComplete may need to call DoPayloadRead while the renegotiation
  // handshake is in progress.
  int rv_read = ERR_IO_PENDING;
  int rv_write = ERR_IO_PENDING;
  bool network_moved;
  do {
    if (user_read_buf_.get())
      rv_read = DoPayloadRead();
    if (user_write_buf_.get())
      rv_write = DoPayloadWrite();
    network_moved = DoTransportIO();
  } while (rv_read == ERR_IO_PENDING && rv_write == ERR_IO_PENDING &&
           (user_read_buf_.get() || user_write_buf_.get()) && network_moved);

  // If the parent SSLClientSocketNSS is deleted during the processing of the
  // Read callback and OnNSSTaskRunner() == OnNetworkTaskRunner(), then the Core
  // will be detached (and possibly deleted). Guard against deletion by taking
  // an extra reference, then check if the Core was detached before invoking the
  // next callback.
  scoped_refptr<Core> guard(this);
  if (user_read_buf_.get() && rv_read != ERR_IO_PENDING)
    DoReadCallback(rv_read);

  if (OnNetworkTaskRunner() && detached_)
    return;

  if (user_write_buf_.get() && rv_write != ERR_IO_PENDING)
    DoWriteCallback(rv_write);
}

// As part of Connect(), the SSLClientSocketNSS object performs an SSL
// handshake. This requires network IO, which in turn calls
// BufferRecvComplete() with a non-zero byte count. This byte count eventually
// winds its way through the state machine and ends up being passed to the
// 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());

  base::Closure c = base::Bind(
      base::ResetAndReturn(&user_connect_callback_),
      rv > OK ? OK : rv);
  PostOrRunCallback(FROM_HERE, c);
}

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());

  user_read_buf_ = NULL;
  user_read_buf_len_ = 0;
  int amount_in_read_buffer = memio_GetReadableBufferSize(nss_bufs_);
  // This is used to curry the |amount_int_read_buffer| and |user_cb| back to
  // the network task runner.
  PostOrRunCallback(
      FROM_HERE,
      base::Bind(&Core::OnNSSBufferUpdated, this, amount_in_read_buffer));
  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(
          "418183 SSLClientSocketNSS::Core::DoReadCallback"));
  PostOrRunCallback(
      FROM_HERE,
      base::Bind(base::ResetAndReturn(&user_read_callback_), rv));
}

void SSLClientSocketNSS::Core::DoWriteCallback(int rv) {
  DCHECK(OnNSSTaskRunner());
  DCHECK_NE(ERR_IO_PENDING, rv);
  DCHECK(!user_write_callback_.is_null());

  // Since Run may result in Write being called, clear |user_write_callback_|
  // up front.
  user_write_buf_ = NULL;
  user_write_buf_len_ = 0;
  // Update buffer status because DoWriteLoop called DoTransportIO which may
  // perform read operations.
  int amount_in_read_buffer = memio_GetReadableBufferSize(nss_bufs_);
  // This is used to curry the |amount_int_read_buffer| and |user_cb| back to
  // the network task runner.
  PostOrRunCallback(
      FROM_HERE,
      base::Bind(&Core::OnNSSBufferUpdated, this, amount_in_read_buffer));
  PostOrRunCallback(
      FROM_HERE,
      base::Bind(&Core::DidNSSWrite, this, rv));
  PostOrRunCallback(
      FROM_HERE,
      base::Bind(base::ResetAndReturn(&user_write_callback_), rv));
}

SECStatus SSLClientSocketNSS::Core::ClientChannelIDHandler(
    void* arg,
    PRFileDesc* socket,
    SECKEYPublicKey **out_public_key,
    SECKEYPrivateKey **out_private_key) {
  Core* core = reinterpret_cast<Core*>(arg);
  DCHECK(core->OnNSSTaskRunner());

  core->PostOrRunCallback(
      FROM_HERE,
      base::Bind(&AddLogEvent, core->weak_net_log_,
                 NetLog::TYPE_SSL_CHANNEL_ID_REQUESTED));

  // We have negotiated the TLS channel ID extension.
  core->channel_id_xtn_negotiated_ = true;
  std::string host = core->host_and_port_.host();
  int error = ERR_UNEXPECTED;
  if (core->OnNetworkTaskRunner()) {
    error = core->DoGetChannelID(host);
  } else {
    bool posted = core->network_task_runner_->PostTask(
        FROM_HERE,
        base::Bind(
            IgnoreResult(&Core::DoGetChannelID),
            core, host));
    error = posted ? ERR_IO_PENDING : ERR_ABORTED;
  }

  if (error == ERR_IO_PENDING) {
    // Asynchronous case.
    core->channel_id_needed_ = true;
    return SECWouldBlock;
  }

  core->PostOrRunCallback(
      FROM_HERE,
      base::Bind(&BoundNetLog::EndEventWithNetErrorCode, core->weak_net_log_,
                 NetLog::TYPE_SSL_GET_DOMAIN_BOUND_CERT, error));
  SECStatus rv = SECSuccess;
  if (error == OK) {
    // Synchronous success.
    int result = core->ImportChannelIDKeys(out_public_key, out_private_key);
    if (result == OK)
      core->SetChannelIDProvided();
    else
      rv = SECFailure;
  } else {
    rv = SECFailure;
  }

  return rv;
}

int SSLClientSocketNSS::Core::ImportChannelIDKeys(SECKEYPublicKey** public_key,
                                                  SECKEYPrivateKey** key) {
  // Set the certificate.
  SECItem cert_item;
  cert_item.data = (unsigned char*) domain_bound_cert_.data();
  cert_item.len = domain_bound_cert_.size();
  ScopedCERTCertificate cert(CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
                                                     &cert_item,
                                                     NULL,
                                                     PR_FALSE,
                                                     PR_TRUE));
  if (cert == NULL)
    return MapNSSError(PORT_GetError());

  crypto::ScopedPK11Slot slot(PK11_GetInternalSlot());
  // Set the private key.
  if (!crypto::ECPrivateKey::ImportFromEncryptedPrivateKeyInfo(
          slot.get(),
          ChannelIDService::kEPKIPassword,
          reinterpret_cast<const unsigned char*>(
              domain_bound_private_key_.data()),
          domain_bound_private_key_.size(),
          &cert->subjectPublicKeyInfo,
          false,
          false,
          key,
          public_key)) {
    int error = MapNSSError(PORT_GetError());
    return error;
  }

  return OK;
}

void SSLClientSocketNSS::Core::UpdateServerCert() {
  nss_handshake_state_.server_cert_chain.Reset(nss_fd_);
  nss_handshake_state_.server_cert = X509Certificate::CreateFromDERCertChain(
      nss_handshake_state_.server_cert_chain.AsStringPieceVector());
  if (nss_handshake_state_.server_cert.get()) {
    // Since this will be called asynchronously on another thread, it needs to
    // own a reference to the certificate.
    NetLog::ParametersCallback net_log_callback =
        base::Bind(&NetLogX509CertificateCallback,
                   nss_handshake_state_.server_cert);
    PostOrRunCallback(
        FROM_HERE,
        base::Bind(&AddLogEventWithCallback, weak_net_log_,
                   NetLog::TYPE_SSL_CERTIFICATES_RECEIVED,
                   net_log_callback));
  }
}

void SSLClientSocketNSS::Core::UpdateSignedCertTimestamps() {
  const SECItem* signed_cert_timestamps =
      SSL_PeerSignedCertTimestamps(nss_fd_);

  if (!signed_cert_timestamps || !signed_cert_timestamps->len)
    return;

  nss_handshake_state_.sct_list_from_tls_extension = std::string(
      reinterpret_cast<char*>(signed_cert_timestamps->data),
      signed_cert_timestamps->len);
}

void SSLClientSocketNSS::Core::UpdateStapledOCSPResponse() {
  PRBool ocsp_requested = PR_FALSE;
  SSL_OptionGet(nss_fd_, SSL_ENABLE_OCSP_STAPLING, &ocsp_requested);
  const SECItemArray* ocsp_responses =
      SSL_PeerStapledOCSPResponses(nss_fd_);
  bool ocsp_responses_present = ocsp_responses && ocsp_responses->len;
  if (ocsp_requested)
    UMA_HISTOGRAM_BOOLEAN("Net.OCSPResponseStapled", ocsp_responses_present);
  if (!ocsp_responses_present)
    return;

  nss_handshake_state_.stapled_ocsp_response = std::string(
      reinterpret_cast<char*>(ocsp_responses->items[0].data),
      ocsp_responses->items[0].len);

  if (IsOCSPStaplingSupported()) {
  #if defined(OS_WIN)
    if (nss_handshake_state_.server_cert.get()) {
      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() {
  // 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));
  if (ok == SECSuccess &&
      channel_info.length == sizeof(channel_info) &&
      channel_info.cipherSuite) {
    nss_handshake_state_.ssl_connection_status |= channel_info.cipherSuite;

    nss_handshake_state_.ssl_connection_status |=
        (static_cast<int>(channel_info.compressionMethod) &
         SSL_CONNECTION_COMPRESSION_MASK) <<
        SSL_CONNECTION_COMPRESSION_SHIFT;

    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
      // version 2.
      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_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 == SSL_LIBRARY_VERSION_TLS_1_2) {
      version = SSL_CONNECTION_VERSION_TLS1_2;
    }
    nss_handshake_state_.ssl_connection_status |=
        (version & SSL_CONNECTION_VERSION_MASK) <<
        SSL_CONNECTION_VERSION_SHIFT;
  }

  PRBool peer_supports_renego_ext;
  ok = SSL_HandshakeNegotiatedExtension(nss_fd_, ssl_renegotiation_info_xtn,
                                        &peer_supports_renego_ext);
  if (ok == SECSuccess) {
    if (!peer_supports_renego_ext) {
      nss_handshake_state_.ssl_connection_status |=
          SSL_CONNECTION_NO_RENEGOTIATION_EXTENSION;
      // Log an informational message if the server does not support secure
      // renegotiation (RFC 5746).
      VLOG(1) << "The server " << host_and_port_.ToString()
              << " does not support the TLS renegotiation_info extension.";
    }
  }

  if (ssl_config_.version_fallback) {
    nss_handshake_state_.ssl_connection_status |=
        SSL_CONNECTION_VERSION_FALLBACK;
  }
}

void SSLClientSocketNSS::Core::UpdateNextProto() {
  uint8 buf[256];
  SSLNextProtoState state;
  unsigned buf_len;

  SECStatus rv = SSL_GetNextProto(nss_fd_, &state, buf, &buf_len, sizeof(buf));
  if (rv != SECSuccess)
    return;

  nss_handshake_state_.next_proto =
      std::string(reinterpret_cast<char*>(buf), buf_len);
  switch (state) {
    case SSL_NEXT_PROTO_NEGOTIATED:
    case SSL_NEXT_PROTO_SELECTED:
      nss_handshake_state_.next_proto_status = kNextProtoNegotiated;
      break;
    case SSL_NEXT_PROTO_NO_OVERLAP:
      nss_handshake_state_.next_proto_status = kNextProtoNoOverlap;
      break;
    case SSL_NEXT_PROTO_NO_SUPPORT:
      nss_handshake_state_.next_proto_status = kNextProtoUnsupported;
      break;
    default:
      NOTREACHED();
      break;
  }
}

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)
    return;

  // Copy the NSS task runner-only state to the network task runner and
  // log histograms from there, since the histograms also need access to the
  // network task runner state.
  PostOrRunCallback(
      FROM_HERE,
      base::Bind(&Core::RecordChannelIDSupportOnNetworkTaskRunner,
                 this,
                 channel_id_xtn_negotiated_,
                 ssl_config_.channel_id_enabled,
                 crypto::ECPrivateKey::IsSupported()));
}

void SSLClientSocketNSS::Core::RecordChannelIDSupportOnNetworkTaskRunner(
    bool negotiated_channel_id,
    bool channel_id_enabled,
    bool supports_ecc) const {
  DCHECK(OnNetworkTaskRunner());

  RecordChannelIDSupport(channel_id_service_,
                         negotiated_channel_id,
                         channel_id_enabled,
                         supports_ecc);
}

int SSLClientSocketNSS::Core::DoBufferRecv(IOBuffer* read_buffer, int len) {
  DCHECK(OnNetworkTaskRunner());
  DCHECK_GT(len, 0);

  if (detached_)
    return ERR_ABORTED;

  int rv = transport_->socket()->Read(
      read_buffer, len,
      base::Bind(&Core::BufferRecvComplete, base::Unretained(this),
                 scoped_refptr<IOBuffer>(read_buffer)));

  if (!OnNSSTaskRunner() && rv != ERR_IO_PENDING) {
    nss_task_runner_->PostTask(
        FROM_HERE, base::Bind(&Core::BufferRecvComplete, this,
                              scoped_refptr<IOBuffer>(read_buffer), rv));
    return rv;
  }

  return rv;
}

int SSLClientSocketNSS::Core::DoBufferSend(IOBuffer* send_buffer, int len) {
  DCHECK(OnNetworkTaskRunner());
  DCHECK_GT(len, 0);

  if (detached_)
    return ERR_ABORTED;

  int rv = transport_->socket()->Write(
      send_buffer, len,
      base::Bind(&Core::BufferSendComplete,
                 base::Unretained(this)));

  if (!OnNSSTaskRunner() && rv != ERR_IO_PENDING) {
    nss_task_runner_->PostTask(
        FROM_HERE,
        base::Bind(&Core::BufferSendComplete, this, rv));
    return rv;
  }

  return rv;
}

int SSLClientSocketNSS::Core::DoGetChannelID(const std::string& host) {
  DCHECK(OnNetworkTaskRunner());

  if (detached_)
    return ERR_ABORTED;

  weak_net_log_->BeginEvent(NetLog::TYPE_SSL_GET_DOMAIN_BOUND_CERT);

  int rv = channel_id_service_->GetOrCreateChannelID(
      host,
      &domain_bound_private_key_,
      &domain_bound_cert_,
      base::Bind(&Core::OnGetChannelIDComplete, base::Unretained(this)),
      &domain_bound_cert_request_handle_);

  if (rv != ERR_IO_PENDING && !OnNSSTaskRunner()) {
    nss_task_runner_->PostTask(
        FROM_HERE,
        base::Bind(&Core::OnHandshakeIOComplete, this, rv));
    return ERR_IO_PENDING;
  }

  return rv;
}

void SSLClientSocketNSS::Core::OnHandshakeStateUpdated(
    const HandshakeState& state) {
  DCHECK(OnNetworkTaskRunner());
  network_handshake_state_ = state;
}

void SSLClientSocketNSS::Core::OnNSSBufferUpdated(int amount_in_read_buffer) {
  DCHECK(OnNetworkTaskRunner());
  unhandled_buffer_size_ = amount_in_read_buffer;
}

void SSLClientSocketNSS::Core::DidNSSRead(int result) {
  DCHECK(OnNetworkTaskRunner());
  DCHECK(nss_waiting_read_);
  nss_waiting_read_ = false;
  if (result <= 0) {
    nss_is_closed_ = true;
  } else {
    was_ever_used_ = true;
  }
}

void SSLClientSocketNSS::Core::DidNSSWrite(int result) {
  DCHECK(OnNetworkTaskRunner());
  DCHECK(nss_waiting_write_);
  nss_waiting_write_ = false;
  if (result < 0) {
    nss_is_closed_ = true;
  } else if (result > 0) {
    was_ever_used_ = true;
  }
}

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;

    nss_task_runner_->PostTask(
        FROM_HERE, base::Bind(&Core::BufferSendComplete, this, result));
    return;
  }

  DCHECK(OnNSSTaskRunner());

  memio_PutWriteResult(nss_bufs_, MapErrorToNSS(result));
  transport_send_busy_ = false;
  OnSendComplete(result);
}

void SSLClientSocketNSS::Core::OnHandshakeIOComplete(int result) {
  if (!OnNSSTaskRunner()) {
    if (detached_)
      return;

    nss_task_runner_->PostTask(
        FROM_HERE, base::Bind(&Core::OnHandshakeIOComplete, this, result));
    return;
  }

  DCHECK(OnNSSTaskRunner());

  int rv = DoHandshakeLoop(result);
  if (rv != ERR_IO_PENDING)
    DoConnectCallback(rv);
}

void SSLClientSocketNSS::Core::OnGetChannelIDComplete(int result) {
  DVLOG(1) << __FUNCTION__ << " " << result;
  DCHECK(OnNetworkTaskRunner());

  OnHandshakeIOComplete(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()) {
    if (detached_)
      return;

    nss_task_runner_->PostTask(
        FROM_HERE, base::Bind(&Core::BufferRecvComplete, this,
                              scoped_refptr<IOBuffer>(read_buffer), result));
    return;
  }

  DCHECK(OnNSSTaskRunner());

  if (result > 0) {
    char* buf;
    int nb = memio_GetReadParams(nss_bufs_, &buf);
    CHECK_GE(nb, result);
    memcpy(buf, read_buffer->data(), result);
  } else if (result == 0) {
    transport_recv_eof_ = true;
  }

  memio_PutReadResult(nss_bufs_, MapErrorToNSS(result));
  transport_recv_busy_ = false;
  OnRecvComplete(result);
}

void SSLClientSocketNSS::Core::PostOrRunCallback(
    const tracked_objects::Location& location,
    const base::Closure& task) {
  if (!OnNetworkTaskRunner()) {
    network_task_runner_->PostTask(
        FROM_HERE,
        base::Bind(&Core::PostOrRunCallback, this, location, task));
    return;
  }

  if (detached_ || task.is_null())
    return;
  task.Run();
}

void SSLClientSocketNSS::Core::AddCertProvidedEvent(int cert_count) {
  PostOrRunCallback(
      FROM_HERE,
      base::Bind(&AddLogEventWithCallback, weak_net_log_,
                 NetLog::TYPE_SSL_CLIENT_CERT_PROVIDED,
                 NetLog::IntegerCallback("cert_count", cert_count)));
}

void SSLClientSocketNSS::Core::SetChannelIDProvided() {
  PostOrRunCallback(
      FROM_HERE, base::Bind(&AddLogEvent, weak_net_log_,
                            NetLog::TYPE_SSL_CHANNEL_ID_PROVIDED));
  nss_handshake_state_.channel_id_sent = true;
  // Update the network task runner's view of the handshake state now that
  // channel id has been sent.
  PostOrRunCallback(
      FROM_HERE, base::Bind(&Core::OnHandshakeStateUpdated, this,
                            nss_handshake_state_));
}

SSLClientSocketNSS::SSLClientSocketNSS(
    base::SequencedTaskRunner* nss_task_runner,
    scoped_ptr<ClientSocketHandle> transport_socket,
    const HostPortPair& host_and_port,
    const SSLConfig& ssl_config,
    const SSLClientSocketContext& context)
    : nss_task_runner_(nss_task_runner),
      transport_(transport_socket.Pass()),
      host_and_port_(host_and_port),
      ssl_config_(ssl_config),
      cert_verifier_(context.cert_verifier),
      cert_transparency_verifier_(context.cert_transparency_verifier),
      channel_id_service_(context.channel_id_service),
      ssl_session_cache_shard_(context.ssl_session_cache_shard),
      completed_handshake_(false),
      next_handshake_state_(STATE_NONE),
      nss_fd_(NULL),
      net_log_(transport_->socket()->NetLog()),
      transport_security_state_(context.transport_security_state),
      policy_enforcer_(context.cert_policy_enforcer),
      valid_thread_id_(base::kInvalidThreadId) {
  EnterFunction("");
  InitCore();
  LeaveFunction("");
}

SSLClientSocketNSS::~SSLClientSocketNSS() {
  EnterFunction("");
  Disconnect();
  LeaveFunction("");
}

// static
void SSLClientSocket::ClearSessionCache() {
  // SSL_ClearSessionCache can't be called before NSS is initialized.  Don't
  // bother initializing NSS just to clear an empty SSL session cache.
  if (!NSS_IsInitialized())
    return;

  SSL_ClearSessionCache();
}

#if !defined(CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256)
#define CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256 (CKM_NSS + 24)
#endif

// static
uint16 SSLClientSocket::GetMaxSupportedSSLVersion() {
  crypto::EnsureNSSInit();
  if (PK11_TokenExists(CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256)) {
    return SSL_PROTOCOL_VERSION_TLS1_2;
  } else {
    return SSL_PROTOCOL_VERSION_TLS1_1;
  }
}

bool SSLClientSocketNSS::GetSSLInfo(SSLInfo* ssl_info) {
  EnterFunction("");
  ssl_info->Reset();
  if (core_->state().server_cert_chain.empty() ||
      !core_->state().server_cert_chain[0]) {
    return false;
  }

  ssl_info->cert_status = server_cert_verify_result_.cert_status;
  ssl_info->cert = server_cert_verify_result_.verified_cert;

  AddSCTInfoToSSLInfo(ssl_info);

  ssl_info->connection_status =
      core_->state().ssl_connection_status;
  ssl_info->public_key_hashes = server_cert_verify_result_.public_key_hashes;
  ssl_info->is_issued_by_known_root =
      server_cert_verify_result_.is_issued_by_known_root;
  ssl_info->client_cert_sent =
      ssl_config_.send_client_cert && ssl_config_.client_cert.get();
  ssl_info->channel_id_sent = WasChannelIDSent();
  ssl_info->pinning_failure_log = pinning_failure_log_;

  PRUint16 cipher_suite = SSLConnectionStatusToCipherSuite(
      core_->state().ssl_connection_status);
  SSLCipherSuiteInfo cipher_info;
  SECStatus ok = SSL_GetCipherSuiteInfo(cipher_suite,
                                        &cipher_info, sizeof(cipher_info));
  if (ok == SECSuccess) {
    ssl_info->security_bits = cipher_info.effectiveKeyBits;
  } else {
    ssl_info->security_bits = -1;
    LOG(DFATAL) << "SSL_GetCipherSuiteInfo returned " << PR_GetError()
                << " for cipherSuite " << cipher_suite;
  }

  ssl_info->handshake_type = core_->state().resumed_handshake ?
      SSLInfo::HANDSHAKE_RESUME : SSLInfo::HANDSHAKE_FULL;

  LeaveFunction("");
  return true;
}

std::string SSLClientSocketNSS::GetSessionCacheKey() const {
  NOTIMPLEMENTED();
  return std::string();
}

bool SSLClientSocketNSS::InSessionCache() const {
  // For now, always return true so that SSLConnectJobs are never held back.
  return true;
}

void SSLClientSocketNSS::SetHandshakeCompletionCallback(
    const base::Closure& callback) {
  NOTIMPLEMENTED();
}

void SSLClientSocketNSS::GetSSLCertRequestInfo(
    SSLCertRequestInfo* cert_request_info) {
  EnterFunction("");
  cert_request_info->host_and_port = host_and_port_;
  cert_request_info->cert_authorities = core_->state().cert_authorities;
  LeaveFunction("");
}

int SSLClientSocketNSS::ExportKeyingMaterial(const base::StringPiece& label,
                                             bool has_context,
                                             const base::StringPiece& context,
                                             unsigned char* out,
                                             unsigned int outlen) {
  if (!IsConnected())
    return ERR_SOCKET_NOT_CONNECTED;

  // SSL_ExportKeyingMaterial may block the current thread if |core_| is in
  // the midst of a handshake.
  SECStatus result = SSL_ExportKeyingMaterial(
      nss_fd_, label.data(), label.size(), has_context,
      reinterpret_cast<const unsigned char*>(context.data()),
      context.length(), out, outlen);
  if (result != SECSuccess) {
    LogFailedNSSFunction(net_log_, "SSL_ExportKeyingMaterial", "");
    return MapNSSError(PORT_GetError());
  }
  return OK;
}

int SSLClientSocketNSS::GetTLSUniqueChannelBinding(std::string* out) {
  if (!IsConnected())
    return ERR_SOCKET_NOT_CONNECTED;
  unsigned char buf[64];
  unsigned int len;
  SECStatus result = SSL_GetChannelBinding(nss_fd_,
                                           SSL_CHANNEL_BINDING_TLS_UNIQUE,
                                           buf, &len, arraysize(buf));
  if (result != SECSuccess) {
    LogFailedNSSFunction(net_log_, "SSL_GetChannelBinding", "");
    return MapNSSError(PORT_GetError());
  }
  out->assign(reinterpret_cast<char*>(buf), len);
  return OK;
}

SSLClientSocket::NextProtoStatus
SSLClientSocketNSS::GetNextProto(std::string* proto) {
  *proto = core_->state().next_proto;
  return core_->state().next_proto_status;
}

int SSLClientSocketNSS::Connect(const CompletionCallback& callback) {
  EnterFunction("");
  DCHECK(transport_.get());
  // It is an error to create an SSLClientSocket whose context has no
  // TransportSecurityState.
  DCHECK(transport_security_state_);
  DCHECK_EQ(STATE_NONE, next_handshake_state_);
  DCHECK(user_connect_callback_.is_null());
  DCHECK(!callback.is_null());

  EnsureThreadIdAssigned();

  net_log_.BeginEvent(NetLog::TYPE_SSL_CONNECT);

  int rv = Init();
  if (rv != OK) {
    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
    return rv;
  }

  rv = InitializeSSLOptions();
  if (rv != OK) {
    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
    return rv;
  }

  rv = InitializeSSLPeerName();
  if (rv != OK) {
    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
    return rv;
  }

  GotoState(STATE_HANDSHAKE);

  rv = DoHandshakeLoop(OK);
  if (rv == ERR_IO_PENDING) {
    user_connect_callback_ = callback;
  } else {
    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
  }

  LeaveFunction("");
  return rv > OK ? OK : rv;
}

void SSLClientSocketNSS::Disconnect() {
  EnterFunction("");

  CHECK(CalledOnValidThread());

  // Shut down anything that may call us back.
  core_->Detach();
  verifier_.reset();
  transport_->socket()->Disconnect();

  // Reset object state.
  user_connect_callback_.Reset();
  server_cert_verify_result_.Reset();
  completed_handshake_   = false;
  start_cert_verification_time_ = base::TimeTicks();
  InitCore();

  LeaveFunction("");
}

bool SSLClientSocketNSS::IsConnected() const {
  EnterFunction("");
  bool ret = completed_handshake_ &&
             (core_->HasPendingAsyncOperation() ||
              (core_->IsConnected() && core_->HasUnhandledReceivedData()) ||
              transport_->socket()->IsConnected());
  LeaveFunction("");
  return ret;
}

bool SSLClientSocketNSS::IsConnectedAndIdle() const {
  EnterFunction("");
  bool ret = completed_handshake_ &&
             !core_->HasPendingAsyncOperation() &&
             !(core_->IsConnected() && core_->HasUnhandledReceivedData()) &&
             transport_->socket()->IsConnectedAndIdle();
  LeaveFunction("");
  return ret;
}

int SSLClientSocketNSS::GetPeerAddress(IPEndPoint* address) const {
  return transport_->socket()->GetPeerAddress(address);
}

int SSLClientSocketNSS::GetLocalAddress(IPEndPoint* address) const {
  return transport_->socket()->GetLocalAddress(address);
}

const BoundNetLog& SSLClientSocketNSS::NetLog() const {
  return net_log_;
}

void SSLClientSocketNSS::SetSubresourceSpeculation() {
  if (transport_.get() && transport_->socket()) {
    transport_->socket()->SetSubresourceSpeculation();
  } else {
    NOTREACHED();
  }
}

void SSLClientSocketNSS::SetOmniboxSpeculation() {
  if (transport_.get() && transport_->socket()) {
    transport_->socket()->SetOmniboxSpeculation();
  } else {
    NOTREACHED();
  }
}

bool SSLClientSocketNSS::WasEverUsed() const {
  DCHECK(core_.get());

  return core_->WasEverUsed();
}

bool SSLClientSocketNSS::UsingTCPFastOpen() const {
  if (transport_.get() && transport_->socket()) {
    return transport_->socket()->UsingTCPFastOpen();
  }
  NOTREACHED();
  return false;
}

int SSLClientSocketNSS::Read(IOBuffer* buf, int buf_len,
                             const CompletionCallback& callback) {
  DCHECK(core_.get());
  DCHECK(!callback.is_null());

  EnterFunction(buf_len);
  int rv = core_->Read(buf, buf_len, callback);
  LeaveFunction(rv);

  return rv;
}

int SSLClientSocketNSS::Write(IOBuffer* buf, int buf_len,
                              const CompletionCallback& callback) {
  DCHECK(core_.get());
  DCHECK(!callback.is_null());

  EnterFunction(buf_len);
  int rv = core_->Write(buf, buf_len, callback);
  LeaveFunction(rv);

  return rv;
}

int SSLClientSocketNSS::SetReceiveBufferSize(int32 size) {
  return transport_->socket()->SetReceiveBufferSize(size);
}

int SSLClientSocketNSS::SetSendBufferSize(int32 size) {
  return transport_->socket()->SetSendBufferSize(size);
}

int SSLClientSocketNSS::Init() {
  EnterFunction("");
  // Initialize the NSS SSL library in a threadsafe way.  This also
  // initializes the NSS base library.
  EnsureNSSSSLInit();
  if (!NSS_IsInitialized())
    return ERR_UNEXPECTED;
#if defined(USE_NSS) || defined(OS_IOS)
  if (ssl_config_.cert_io_enabled) {
    // We must call EnsureNSSHttpIOInit() here, on the IO thread, to get the IO
    // loop by MessageLoopForIO::current().
    // X509Certificate::Verify() runs on a worker thread of CertVerifier.
    EnsureNSSHttpIOInit();
  }
#endif

  LeaveFunction("");
  return OK;
}

void SSLClientSocketNSS::InitCore() {
  core_ = new Core(base::ThreadTaskRunnerHandle::Get().get(),
                   nss_task_runner_.get(),
                   transport_.get(),
                   host_and_port_,
                   ssl_config_,
                   &net_log_,
                   channel_id_service_);
}

int SSLClientSocketNSS::InitializeSSLOptions() {
  // Transport connected, now hook it up to nss
  nss_fd_ = memio_CreateIOLayer(kRecvBufferSize, kSendBufferSize);
  if (nss_fd_ == NULL) {
    return ERR_OUT_OF_MEMORY;  // TODO(port): map NSPR error code.
  }

  // Grab pointer to buffers
  memio_Private* nss_bufs = memio_GetSecret(nss_fd_);

  /* Create SSL state machine */
  /* Push SSL onto our fake I/O socket */
  if (SSL_ImportFD(GetNSSModelSocket(), nss_fd_) == NULL) {
    LogFailedNSSFunction(net_log_, "SSL_ImportFD", "");
    PR_Close(nss_fd_);
    nss_fd_ = NULL;
    return ERR_OUT_OF_MEMORY;  // TODO(port): map NSPR/NSS error code.
  }
  // TODO(port): set more ssl options!  Check errors!

  int rv;

  rv = SSL_OptionSet(nss_fd_, SSL_SECURITY, PR_TRUE);
  if (rv != SECSuccess) {
    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_SECURITY");
    return ERR_UNEXPECTED;
  }

  rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SSL2, PR_FALSE);
  if (rv != SECSuccess) {
    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_SSL2");
    return ERR_UNEXPECTED;
  }

  // Don't do V2 compatible hellos because they don't support TLS extensions.
  rv = SSL_OptionSet(nss_fd_, SSL_V2_COMPATIBLE_HELLO, PR_FALSE);
  if (rv != SECSuccess) {
    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_V2_COMPATIBLE_HELLO");
    return ERR_UNEXPECTED;
  }

  SSLVersionRange version_range;
  version_range.min = ssl_config_.version_min;
  version_range.max = ssl_config_.version_max;
  rv = SSL_VersionRangeSet(nss_fd_, &version_range);
  if (rv != SECSuccess) {
    LogFailedNSSFunction(net_log_, "SSL_VersionRangeSet", "");
    return ERR_NO_SSL_VERSIONS_ENABLED;
  }

  if (ssl_config_.version_fallback) {
    rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_FALLBACK_SCSV, PR_TRUE);
    if (rv != SECSuccess) {
      LogFailedNSSFunction(
          net_log_, "SSL_OptionSet", "SSL_ENABLE_FALLBACK_SCSV");
    }
  }

  for (std::vector<uint16>::const_iterator it =
           ssl_config_.disabled_cipher_suites.begin();
       it != ssl_config_.disabled_cipher_suites.end(); ++it) {
    // This will fail if the specified cipher is not implemented by NSS, but
    // the failure is harmless.
    SSL_CipherPrefSet(nss_fd_, *it, PR_FALSE);
  }

  // Support RFC 5077
  rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SESSION_TICKETS, PR_TRUE);
  if (rv != SECSuccess) {
    LogFailedNSSFunction(
        net_log_, "SSL_OptionSet", "SSL_ENABLE_SESSION_TICKETS");
  }

  rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_FALSE_START,
                     ssl_config_.false_start_enabled);
  if (rv != SECSuccess)
    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_FALSE_START");

  // We allow servers to request renegotiation. Since we're a client,
  // prohibiting this is rather a waste of time. Only servers are in a
  // position to prevent renegotiation attacks.
  // http://extendedsubset.com/?p=8

  rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_RENEGOTIATION,
                     SSL_RENEGOTIATE_TRANSITIONAL);
  if (rv != SECSuccess) {
    LogFailedNSSFunction(
        net_log_, "SSL_OptionSet", "SSL_ENABLE_RENEGOTIATION");
  }

  rv = SSL_OptionSet(nss_fd_, SSL_CBC_RANDOM_IV, PR_TRUE);
  if (rv != SECSuccess)
    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_CBC_RANDOM_IV");

// Added in NSS 3.15
#ifdef 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

  rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SIGNED_CERT_TIMESTAMPS,
                     ssl_config_.signed_cert_timestamps_enabled);
  if (rv != SECSuccess) {
    LogFailedNSSFunction(net_log_, "SSL_OptionSet",
                         "SSL_ENABLE_SIGNED_CERT_TIMESTAMPS");
  }

  rv = SSL_OptionSet(nss_fd_, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE);
  if (rv != SECSuccess) {
    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_HANDSHAKE_AS_CLIENT");
    return ERR_UNEXPECTED;
  }

  if (!core_->Init(nss_fd_, nss_bufs))
    return ERR_UNEXPECTED;

  // Tell SSL the hostname we're trying to connect to.
  SSL_SetURL(nss_fd_, host_and_port_.host().c_str());

  // Tell SSL we're a client; needed if not letting NSPR do socket I/O
  SSL_ResetHandshake(nss_fd_, PR_FALSE);

  return OK;
}

int SSLClientSocketNSS::InitializeSSLPeerName() {
  // Tell NSS who we're connected to
  IPEndPoint peer_address;
  int err = transport_->socket()->GetPeerAddress(&peer_address);
  if (err != OK)
    return err;

  SockaddrStorage storage;
  if (!peer_address.ToSockAddr(storage.addr, &storage.addr_len))
    return ERR_ADDRESS_INVALID;

  PRNetAddr peername;
  memset(&peername, 0, sizeof(peername));
  DCHECK_LE(static_cast<size_t>(storage.addr_len), sizeof(peername));
  size_t len = std::min(static_cast<size_t>(storage.addr_len),
                        sizeof(peername));
  memcpy(&peername, storage.addr, len);

  // Adjust the address family field for BSD, whose sockaddr
  // structure has a one-byte length and one-byte address family
  // field at the beginning.  PRNetAddr has a two-byte address
  // family field at the beginning.
  peername.raw.family = storage.addr->sa_family;

  memio_SetPeerName(nss_fd_, &peername);

  // Set the peer ID for session reuse.  This is necessary when we create an
  // SSL tunnel through a proxy -- GetPeerName returns the proxy's address
  // rather than the destination server's address in that case.
  std::string peer_id = host_and_port_.ToString();
  // If the ssl_session_cache_shard_ is non-empty, we append it to the peer id.
  // This will cause session cache misses between sockets with different values
  // of ssl_session_cache_shard_ and this is used to partition the session cache
  // for incognito mode.
  if (!ssl_session_cache_shard_.empty()) {
    peer_id += "/" + ssl_session_cache_shard_;
  }
  SECStatus rv = SSL_SetSockPeerID(nss_fd_, const_cast<char*>(peer_id.c_str()));
  if (rv != SECSuccess)
    LogFailedNSSFunction(net_log_, "SSL_SetSockPeerID", peer_id.c_str());

  return OK;
}

void SSLClientSocketNSS::DoConnectCallback(int rv) {
  EnterFunction(rv);
  DCHECK_NE(ERR_IO_PENDING, rv);
  DCHECK(!user_connect_callback_.is_null());

  base::ResetAndReturn(&user_connect_callback_).Run(rv > OK ? OK : rv);
  LeaveFunction("");
}

void SSLClientSocketNSS::OnHandshakeIOComplete(int result) {
  EnterFunction(result);
  int rv = DoHandshakeLoop(result);
  if (rv != ERR_IO_PENDING) {
    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
    DoConnectCallback(rv);
  }
  LeaveFunction("");
}

int SSLClientSocketNSS::DoHandshakeLoop(int last_io_result) {
  EnterFunction(last_io_result);
  int rv = last_io_result;
  do {
    // Default to STATE_NONE for next state.
    // (This is a quirk carried over from the windows
    // implementation.  It makes reading the logs a bit harder.)
    // State handlers can and often do call GotoState just
    // to stay in the current state.
    State state = next_handshake_state_;
    GotoState(STATE_NONE);
    switch (state) {
      case STATE_HANDSHAKE:
        rv = DoHandshake();
        break;
      case STATE_HANDSHAKE_COMPLETE:
        rv = DoHandshakeComplete(rv);
        break;
      case STATE_VERIFY_CERT:
        DCHECK(rv == OK);
        rv = DoVerifyCert(rv);
        break;
      case STATE_VERIFY_CERT_COMPLETE:
        rv = DoVerifyCertComplete(rv);
        break;
      case STATE_NONE:
      default:
        rv = ERR_UNEXPECTED;
        LOG(DFATAL) << "unexpected state " << state;
        break;
    }
  } while (rv != ERR_IO_PENDING && next_handshake_state_ != STATE_NONE);
  LeaveFunction("");
  return rv;
}

int SSLClientSocketNSS::DoHandshake() {
  EnterFunction("");
  int rv = core_->Connect(
      base::Bind(&SSLClientSocketNSS::OnHandshakeIOComplete,
                 base::Unretained(this)));
  GotoState(STATE_HANDSHAKE_COMPLETE);

  LeaveFunction(rv);
  return rv;
}

int SSLClientSocketNSS::DoHandshakeComplete(int result) {
  EnterFunction(result);

  if (result == OK) {
    if (ssl_config_.version_fallback &&
        ssl_config_.version_max < ssl_config_.version_fallback_min) {
      return ERR_SSL_FALLBACK_BEYOND_MINIMUM_VERSION;
    }

    // SSL handshake is completed. Let's verify the certificate.
    GotoState(STATE_VERIFY_CERT);
    // Done!
  }
  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());
  set_negotiation_extension(core_->state().negotiation_extension_);

  LeaveFunction(result);
  return result;
}

int SSLClientSocketNSS::DoVerifyCert(int result) {
  DCHECK(!core_->state().server_cert_chain.empty());
  DCHECK(core_->state().server_cert_chain[0]);

  GotoState(STATE_VERIFY_CERT_COMPLETE);

  // If the certificate is expected to be bad we can use the expectation as
  // the cert status.
  base::StringPiece der_cert(
      reinterpret_cast<char*>(
          core_->state().server_cert_chain[0]->derCert.data),
      core_->state().server_cert_chain[0]->derCert.len);
  CertStatus cert_status;
  if (ssl_config_.IsAllowedBadCert(der_cert, &cert_status)) {
    DCHECK(start_cert_verification_time_.is_null());
    VLOG(1) << "Received an expected bad cert with status: " << cert_status;
    server_cert_verify_result_.Reset();
    server_cert_verify_result_.cert_status = cert_status;
    server_cert_verify_result_.verified_cert = core_->state().server_cert;
    return OK;
  }

  // We may have failed to create X509Certificate object if we are
  // running inside sandbox.
  if (!core_->state().server_cert.get()) {
    server_cert_verify_result_.Reset();
    server_cert_verify_result_.cert_status = CERT_STATUS_INVALID;
    return ERR_CERT_INVALID;
  }

  start_cert_verification_time_ = base::TimeTicks::Now();

  int flags = 0;
  if (ssl_config_.rev_checking_enabled)
    flags |= CertVerifier::VERIFY_REV_CHECKING_ENABLED;
  if (ssl_config_.verify_ev_cert)
    flags |= CertVerifier::VERIFY_EV_CERT;
  if (ssl_config_.cert_io_enabled)
    flags |= CertVerifier::VERIFY_CERT_IO_ENABLED;
  if (ssl_config_.rev_checking_required_local_anchors)
    flags |= CertVerifier::VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS;
  verifier_.reset(new SingleRequestCertVerifier(cert_verifier_));
  return verifier_->Verify(
      core_->state().server_cert.get(),
      host_and_port_.host(),
      flags,
      SSLConfigService::GetCRLSet().get(),
      &server_cert_verify_result_,
      base::Bind(&SSLClientSocketNSS::OnHandshakeIOComplete,
                 base::Unretained(this)),
      net_log_);
}

// Derived from AuthCertificateCallback() in
// mozilla/source/security/manager/ssl/src/nsNSSCallbacks.cpp.
int SSLClientSocketNSS::DoVerifyCertComplete(int result) {
  verifier_.reset();

  if (!start_cert_verification_time_.is_null()) {
    base::TimeDelta verify_time =
        base::TimeTicks::Now() - start_cert_verification_time_;
    if (result == OK)
        UMA_HISTOGRAM_TIMES("Net.SSLCertVerificationTime", verify_time);
    else
        UMA_HISTOGRAM_TIMES("Net.SSLCertVerificationTimeError", verify_time);
  }

  // We used to remember the intermediate CA certs in the NSS database
  // persistently.  However, NSS opens a connection to the SQLite database
  // during NSS initialization and doesn't close the connection until NSS
  // shuts down.  If the file system where the database resides is gone,
  // the database connection goes bad.  What's worse, the connection won't
  // recover when the file system comes back.  Until this NSS or SQLite bug
  // is fixed, we need to  avoid using the NSS database for non-essential
  // purposes.  See https://bugzilla.mozilla.org/show_bug.cgi?id=508081 and
  // http://crbug.com/15630 for more info.

  // 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) {
    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_ &&
      (result == OK ||
       (IsCertificateError(result) && IsCertStatusMinorError(cert_status))) &&
      !transport_security_state_->CheckPublicKeyPins(
          host_and_port_.host(),
          server_cert_verify_result_.is_issued_by_known_root,
          server_cert_verify_result_.public_key_hashes,
          &pinning_failure_log_)) {
    result = ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN;
  }

  if (result == OK) {
    // Only check Certificate Transparency if there were no other errors with
    // the connection.
    VerifyCT();

    // Only cache the session if the certificate verified successfully.
    core_->CacheSessionIfNecessary();
  }

  completed_handshake_ = true;

  // Exit DoHandshakeLoop and return the result to the caller to Connect.
  DCHECK_EQ(STATE_NONE, next_handshake_state_);
  return result;
}

void SSLClientSocketNSS::VerifyCT() {
  if (!cert_transparency_verifier_)
    return;

  // Note that this is a completely synchronous operation: The CT Log Verifier
  // gets all the data it needs for SCT verification and does not do any
  // external communication.
  cert_transparency_verifier_->Verify(
      server_cert_verify_result_.verified_cert.get(),
      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.

  if (!policy_enforcer_) {
    server_cert_verify_result_.cert_status &= ~CERT_STATUS_IS_EV;
  } else {
    if (server_cert_verify_result_.cert_status & CERT_STATUS_IS_EV) {
      scoped_refptr<ct::EVCertsWhitelist> ev_whitelist =
          SSLConfigService::GetEVCertsWhitelist();
      if (!policy_enforcer_->DoesConformToCTEVPolicy(
              server_cert_verify_result_.verified_cert.get(),
              ev_whitelist.get(), ct_verify_result_, net_log_)) {
        // TODO(eranm): Log via the BoundNetLog, see crbug.com/437766
        VLOG(1) << "EV certificate for "
                << server_cert_verify_result_.verified_cert->subject()
                       .GetDisplayName()
                << " does not conform to CT policy, removing EV status.";
        server_cert_verify_result_.cert_status &= ~CERT_STATUS_IS_EV;
      }
    }
  }
}

void SSLClientSocketNSS::EnsureThreadIdAssigned() const {
  base::AutoLock auto_lock(lock_);
  if (valid_thread_id_ != base::kInvalidThreadId)
    return;
  valid_thread_id_ = base::PlatformThread::CurrentId();
}

bool SSLClientSocketNSS::CalledOnValidThread() const {
  EnsureThreadIdAssigned();
  base::AutoLock auto_lock(lock_);
  return valid_thread_id_ == base::PlatformThread::CurrentId();
}

void SSLClientSocketNSS::AddSCTInfoToSSLInfo(SSLInfo* ssl_info) const {
  for (ct::SCTList::const_iterator iter =
       ct_verify_result_.verified_scts.begin();
       iter != ct_verify_result_.verified_scts.end(); ++iter) {
    ssl_info->signed_certificate_timestamps.push_back(
        SignedCertificateTimestampAndStatus(*iter, ct::SCT_STATUS_OK));
  }
  for (ct::SCTList::const_iterator iter =
       ct_verify_result_.invalid_scts.begin();
       iter != ct_verify_result_.invalid_scts.end(); ++iter) {
    ssl_info->signed_certificate_timestamps.push_back(
        SignedCertificateTimestampAndStatus(*iter, ct::SCT_STATUS_INVALID));
  }
  for (ct::SCTList::const_iterator iter =
       ct_verify_result_.unknown_logs_scts.begin();
       iter != ct_verify_result_.unknown_logs_scts.end(); ++iter) {
    ssl_info->signed_certificate_timestamps.push_back(
        SignedCertificateTimestampAndStatus(*iter,
                                            ct::SCT_STATUS_LOG_UNKNOWN));
  }
}

scoped_refptr<X509Certificate>
SSLClientSocketNSS::GetUnverifiedServerCertificateChain() const {
  return core_->state().server_cert.get();
}

ChannelIDService* SSLClientSocketNSS::GetChannelIDService() const {
  return channel_id_service_;
}

}  // namespace net
