15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file includes code SSLClientSocketNSS::DoVerifyCertComplete() derived
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// from AuthCertificateCallback() in
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// mozilla/security/manager/ssl/src/nsNSSCallbacks.cpp.
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* ***** BEGIN LICENSE BLOCK *****
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Version: MPL 1.1/GPL 2.0/LGPL 2.1
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The contents of this file are subject to the Mozilla Public License Version
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1.1 (the "License"); you may not use this file except in compliance with
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the License. You may obtain a copy of the License at
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * http://www.mozilla.org/MPL/
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Software distributed under the License is distributed on an "AS IS" basis,
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * for the specific language governing rights and limitations under the
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * License.
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The Original Code is the Netscape security libraries.
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The Initial Developer of the Original Code is
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Netscape Communications Corporation.
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Portions created by the Initial Developer are Copyright (C) 2000
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the Initial Developer. All Rights Reserved.
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Contributor(s):
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *   Ian McGreer <mcgreer@netscape.com>
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *   Javier Delgadillo <javi@netscape.com>
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *   Kai Engert <kengert@redhat.com>
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Alternatively, the contents of this file may be used under the terms of
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * either the GNU General Public License Version 2 or later (the "GPL"), or
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * in which case the provisions of the GPL or the LGPL are applicable instead
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * of those above. If you wish to allow use of your version of this file only
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * under the terms of either the GPL or the LGPL, and not to allow others to
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * use your version of this file under the terms of the MPL, indicate your
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * decision by deleting the provisions above and replace them with the notice
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * and other provisions required by the GPL or the LGPL. If you do not delete
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the provisions above, a recipient may use your version of this file under
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the terms of any one of the MPL, the GPL or the LGPL.
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ***** END LICENSE BLOCK ***** */
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/ssl_client_socket_nss.h"
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <certdb.h>
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <hasht.h>
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <keyhi.h>
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <nspr.h>
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <nss.h>
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <ocsp.h>
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <pk11pub.h>
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <secerr.h>
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sechash.h>
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <ssl.h>
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sslerr.h>
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sslproto.h>
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <limits>
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map>
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h"
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback_helpers.h"
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/singleton.h"
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h"
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/single_thread_task_runner.h"
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
765e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
775e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h"
785e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/stringprintf.h"
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/thread_task_runner_handle.h"
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread_restrictions.h"
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/ec_private_key.h"
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/nss_util.h"
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/nss_util_internal.h"
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/rsa_private_key.h"
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/scoped_nss_types.h"
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/address_list.h"
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/connection_type_histograms.h"
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/dns_util.h"
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/io_buffer.h"
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h"
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_log.h"
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/asn1_util.h"
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/cert_status_flags.h"
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/cert_verifier.h"
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/cert/ct_objects_extractor.h"
97a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/cert/ct_verifier.h"
98a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/cert/ct_verify_result.h"
99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "net/cert/scoped_nss_types.h"
100a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/cert/sct_status_flags.h"
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/single_request_cert_verifier.h"
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/x509_certificate_net_log_param.h"
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/x509_util.h"
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/http/transport_security_state.h"
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/ocsp/nss_ocsp.h"
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/client_socket_handle.h"
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/nss_ssl_util.h"
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/ssl/ssl_cert_request_info.h"
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/ssl/ssl_connection_status_flags.h"
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/ssl/ssl_info.h"
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h>
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <wincrypt.h>
11590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
11690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/win/windows_version.h"
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_MACOSX)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <Security/SecBase.h>
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <Security/SecCertificate.h>
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <Security/SecIdentity.h>
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/mac/mac_logging.h"
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/synchronization/lock.h"
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "crypto/mac_security_services_lock.h"
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(USE_NSS)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <dlfcn.h>
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace net {
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// State machines are easier to debug if you log state transitions.
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Enable these if you want to see what's going on.
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if 1
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define EnterFunction(x)
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define LeaveFunction(x)
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define GotoState(s) next_handshake_state_ = s
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define EnterFunction(x)\
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VLOG(1) << (void *)this << " " << __FUNCTION__ << " enter " << x\
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            << "; next_handshake_state " << next_handshake_state_
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define LeaveFunction(x)\
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VLOG(1) << (void *)this << " " << __FUNCTION__ << " leave " << x\
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            << "; next_handshake_state " << next_handshake_state_
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define GotoState(s)\
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    do {\
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      VLOG(1) << (void *)this << " " << __FUNCTION__ << " jump to state " << s;\
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      next_handshake_state_ = s;\
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } while (0)
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SSL plaintext fragments are shorter than 16KB. Although the record layer
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// overhead is allowed to be 2K + 5 bytes, in practice the overhead is much
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// smaller than 1KB. So a 17KB buffer should be large enough to hold an
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// entire SSL record.
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kRecvBufferSize = 17 * 1024;
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kSendBufferSize = 17 * 1024;
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Used by SSLClientSocketNSS::Core to indicate there is no read result
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// obtained by a previous operation waiting to be returned to the caller.
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This constant can be any non-negative/non-zero value (eg: it does not
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// overlap with any value of the net::Error range, including net::OK).
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kNoPendingReadResult = 1;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CERT_OCSP_RESPONSE_PROP_ID is only implemented on Vista+, but it can be
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// set on Windows XP without error. There is some overhead from the server
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// sending the OCSP response if it supports the extension, for the subset of
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// XP clients who will request it but be unable to use it, but this is an
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// acceptable trade-off for simplicity of implementation.
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool IsOCSPStaplingSupported() {
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(USE_NSS)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef SECStatus
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)(*CacheOCSPResponseFromSideChannelFunction)(
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CERTCertDBHandle *handle, CERTCertificate *cert, PRTime time,
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECItem *encodedResponse, void *pwArg);
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// On Linux, we dynamically link against the system version of libnss3.so. In
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// order to continue working on systems without up-to-date versions of NSS we
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// lookup CERT_CacheOCSPResponseFromSideChannel with dlsym.
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// RuntimeLibNSSFunctionPointers is a singleton which caches the results of any
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// runtime symbol resolution that we need.
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class RuntimeLibNSSFunctionPointers {
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CacheOCSPResponseFromSideChannelFunction
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetCacheOCSPResponseFromSideChannelFunction() {
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return cache_ocsp_response_from_side_channel_;
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static RuntimeLibNSSFunctionPointers* GetInstance() {
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return Singleton<RuntimeLibNSSFunctionPointers>::get();
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend struct DefaultSingletonTraits<RuntimeLibNSSFunctionPointers>;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RuntimeLibNSSFunctionPointers() {
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cache_ocsp_response_from_side_channel_ =
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (CacheOCSPResponseFromSideChannelFunction)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dlsym(RTLD_DEFAULT, "CERT_CacheOCSPResponseFromSideChannel");
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CacheOCSPResponseFromSideChannelFunction
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cache_ocsp_response_from_side_channel_;
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)CacheOCSPResponseFromSideChannelFunction
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GetCacheOCSPResponseFromSideChannelFunction() {
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return RuntimeLibNSSFunctionPointers::GetInstance()
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ->GetCacheOCSPResponseFromSideChannelFunction();
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool IsOCSPStaplingSupported() {
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetCacheOCSPResponseFromSideChannelFunction() != NULL;
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(agl): Figure out if we can plumb the OCSP response into Mac's system
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// certificate validation functions.
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool IsOCSPStaplingSupported() {
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This callback is intended to be used with CertFindChainInStore. In addition
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to filtering by extended/enhanced key usage, we do not show expired
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// certificates and require digital signature usage in the key usage
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// extension.
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This matches our behavior on Mac OS X and that of NSS. It also matches the
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// default behavior of IE8. See http://support.microsoft.com/kb/890326 and
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 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
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BOOL WINAPI ClientCertFindCallback(PCCERT_CONTEXT cert_context,
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   void* find_arg) {
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "Calling ClientCertFindCallback from _nss";
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify the certificate's KU is good.
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BYTE key_usage;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (CertGetIntendedKeyUsage(X509_ASN_ENCODING, cert_context->pCertInfo,
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              &key_usage, 1)) {
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!(key_usage & CERT_DIGITAL_SIGNATURE_KEY_USAGE))
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return FALSE;
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DWORD err = GetLastError();
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If |err| is non-zero, it's an actual error. Otherwise the extension
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // just isn't present, and we treat it as if everything was allowed.
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (err) {
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DLOG(ERROR) << "CertGetIntendedKeyUsage failed: " << err;
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return FALSE;
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify the current time is within the certificate's validity period.
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (CertVerifyTimeValidity(NULL, cert_context->pCertInfo) != 0)
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return FALSE;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify private key metadata is associated with this certificate.
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD size = 0;
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!CertGetCertificateContextProperty(
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          cert_context, CERT_KEY_PROV_INFO_PROP_ID, NULL, &size)) {
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return FALSE;
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TRUE;
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper functions to make it possible to log events from within the
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SSLClientSocketNSS::Core.
275868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void AddLogEvent(const base::WeakPtr<BoundNetLog>& net_log,
276868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                 NetLog::EventType event_type) {
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!net_log)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log->AddEvent(event_type);
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper function to make it possible to log events from within the
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SSLClientSocketNSS::Core.
284868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void AddLogEventWithCallback(const base::WeakPtr<BoundNetLog>& net_log,
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             NetLog::EventType event_type,
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const NetLog::ParametersCallback& callback) {
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!net_log)
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log->AddEvent(event_type, callback);
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper function to make it easier to call BoundNetLog::AddByteTransferEvent
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// from within the SSLClientSocketNSS::Core.
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// AddByteTransferEvent expects to receive a const char*, which within the
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Core is backed by an IOBuffer. If the "const char*" is bound via
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// base::Bind and posted to another thread, and the IOBuffer that backs that
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// pointer then goes out of scope on the origin thread, this would result in
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// an invalid read of a stale pointer.
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Instead, provide a signature that accepts an IOBuffer*, so that a reference
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to the owning IOBuffer can be bound to the Callback. This ensures that the
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// IOBuffer will stay alive long enough to cross threads if needed.
302868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void LogByteTransferEvent(
303868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const base::WeakPtr<BoundNetLog>& net_log, NetLog::EventType event_type,
304868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int len, IOBuffer* buffer) {
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!net_log)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log->AddByteTransferEvent(event_type, len, buffer->data());
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// PeerCertificateChain is a helper object which extracts the certificate
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// chain, as given by the server, from an NSS socket and performs the needed
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// resource management. The first element of the chain is the leaf certificate
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and the other elements are in the order given by the server.
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PeerCertificateChain {
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PeerCertificateChain() {}
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PeerCertificateChain(const PeerCertificateChain& other);
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~PeerCertificateChain();
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PeerCertificateChain& operator=(const PeerCertificateChain& other);
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Resets the current chain, freeing any resources, and updates the current
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // chain to be a copy of the chain stored in |nss_fd|.
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If |nss_fd| is NULL, then the current certificate chain will be freed.
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Reset(PRFileDesc* nss_fd);
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns the current certificate chain as a vector of DER-encoded
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // base::StringPieces. The returned vector remains valid until Reset is
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // called.
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<base::StringPiece> AsStringPieceVector() const;
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool empty() const { return certs_.empty(); }
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CERTCertificate* operator[](size_t index) const {
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_LT(index, certs_.size());
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return certs_[index];
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<CERTCertificate*> certs_;
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PeerCertificateChain::PeerCertificateChain(
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const PeerCertificateChain& other) {
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *this = other;
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PeerCertificateChain::~PeerCertificateChain() {
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Reset(NULL);
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PeerCertificateChain& PeerCertificateChain::operator=(
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const PeerCertificateChain& other) {
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (this == &other)
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return *this;
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Reset(NULL);
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  certs_.reserve(other.certs_.size());
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < other.certs_.size(); ++i)
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    certs_.push_back(CERT_DupCertificate(other.certs_[i]));
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return *this;
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PeerCertificateChain::Reset(PRFileDesc* nss_fd) {
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < certs_.size(); ++i)
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CERT_DestroyCertificate(certs_[i]);
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  certs_.clear();
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (nss_fd == NULL)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  CERTCertList* list = SSL_PeerCertificateChain(nss_fd);
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The handshake on |nss_fd| may not have completed.
3744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (list == NULL)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  for (CERTCertListNode* node = CERT_LIST_HEAD(list);
3784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)       !CERT_LIST_END(node, list); node = CERT_LIST_NEXT(node)) {
3794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    certs_.push_back(CERT_DupCertificate(node->cert));
3804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
3814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  CERT_DestroyCertList(list);
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::vector<base::StringPiece>
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PeerCertificateChain::AsStringPieceVector() const {
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<base::StringPiece> v(certs_.size());
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (unsigned i = 0; i < certs_.size(); i++) {
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v[i] = base::StringPiece(
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        reinterpret_cast<const char*>(certs_[i]->derCert.data),
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        certs_[i]->derCert.len);
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return v;
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// HandshakeState is a helper struct used to pass handshake state between
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the NSS task runner and the network task runner.
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// It contains members that may be read or written on the NSS task runner,
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// but which also need to be read from the network task runner. The NSS task
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// runner will notify the network task runner whenever this state changes, so
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that the network task runner can safely make a copy, which avoids the need
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// for locking.
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct HandshakeState {
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HandshakeState() { Reset(); }
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Reset() {
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_proto_status = SSLClientSocket::kNextProtoUnsupported;
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_proto.clear();
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    channel_id_sent = false;
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_cert_chain.Reset(NULL);
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_cert = NULL;
413a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    sct_list_from_tls_extension.clear();
4145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    stapled_ocsp_response.clear();
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    resumed_handshake = false;
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ssl_connection_status = 0;
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set to kNextProtoNegotiated if NPN was successfully negotiated, with the
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // negotiated protocol stored in |next_proto|.
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLClientSocket::NextProtoStatus next_proto_status;
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string next_proto;
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // True if a channel ID was sent.
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool channel_id_sent;
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // List of DER-encoded X.509 DistinguishedName of certificate authorities
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // allowed by the server.
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<std::string> cert_authorities;
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set when the handshake fully completes.
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The server certificate is first received from NSS as an NSS certificate
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // chain (|server_cert_chain|) and then converted into a platform-specific
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // X509Certificate object (|server_cert|). It's possible for some
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // certificates to be successfully parsed by NSS, and not by the platform
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // libraries (i.e.: when running within a sandbox, different parsing
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // algorithms, etc), so it's not safe to assume that |server_cert| will
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // always be non-NULL.
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PeerCertificateChain server_cert_chain;
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<X509Certificate> server_cert;
442a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // SignedCertificateTimestampList received via TLS extension (RFC 6962).
443a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  std::string sct_list_from_tls_extension;
4445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Stapled OCSP response received.
4455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string stapled_ocsp_response;
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // True if the current handshake was the result of TLS session resumption.
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool resumed_handshake;
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The negotiated security parameters (TLS version, cipher, extensions) of
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the SSL connection.
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ssl_connection_status;
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Client-side error mapping functions.
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Map NSS error code to network error code.
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int MapNSSClientError(PRErrorCode err) {
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (err) {
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_ERROR_BAD_CERT_ALERT:
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_ERROR_UNSUPPORTED_CERT_ALERT:
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_ERROR_REVOKED_CERT_ALERT:
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_ERROR_EXPIRED_CERT_ALERT:
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_ERROR_CERTIFICATE_UNKNOWN_ALERT:
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_ERROR_UNKNOWN_CA_ALERT:
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_ERROR_ACCESS_DENIED_ALERT:
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ERR_BAD_SSL_CLIENT_AUTH_CERT;
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return MapNSSError(err);
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SSLClientSocketNSS::Core provides a thread-safe, ref-counted core that is
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// able to marshal data between NSS functions and an underlying transport
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// socket.
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// All public functions are meant to be called from the network task runner,
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and any callbacks supplied will be invoked there as well, provided that
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Detach() has not been called yet.
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Threading within SSLClientSocketNSS and SSLClientSocketNSS::Core:
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Because NSS may block on either hardware or user input during operations
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// such as signing, creating certificates, or locating private keys, the Core
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// handles all of the interactions with the underlying NSS SSL socket, so
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that these blocking calls can be executed on a dedicated task runner.
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note that the network task runner and the NSS task runner may be executing
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// on the same thread. If that happens, then it's more performant to try to
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// complete as much work as possible synchronously, even if it might block,
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// rather than continually PostTask-ing to the same thread.
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Because NSS functions should only be called on the NSS task runner, while
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// I/O resources should only be accessed on the network task runner, most
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// public functions are implemented via three methods, each with different
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// task runner affinities.
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// In the single-threaded mode (where the network and NSS task runners run on
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the same thread), these are all attempted synchronously, while in the
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// multi-threaded mode, message passing is used.
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1) NSS Task Runner: Execute NSS function (DoPayloadRead, DoPayloadWrite,
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    DoHandshake)
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 2) NSS Task Runner: Prepare data to go from NSS to an IO function:
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    (BufferRecv, BufferSend)
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 3) Network Task Runner: Perform IO on that data (DoBufferRecv,
5115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//    DoBufferSend, DoGetChannelID, OnGetChannelIDComplete)
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 4) Both Task Runners: Callback for asynchronous completion or to marshal
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    data from the network task runner back to NSS (BufferRecvComplete,
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    BufferSendComplete, OnHandshakeIOComplete)
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Single-threaded example
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |--------------------------Network Task Runner--------------------------|
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  SSLClientSocketNSS              Core               (Transport Socket)
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//       Read()
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//         |-------------------------V
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                 Read()
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                   |
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                            DoPayloadRead()
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                   |
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                               BufferRecv()
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                   |
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                              DoBufferRecv()
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                   |-------------------------V
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                                           Read()
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                   V-------------------------|
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                          BufferRecvComplete()
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                   |
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                           PostOrRunCallback()
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//         V-------------------------|
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    (Read Callback)
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Multi-threaded example:
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |--------------------Network Task Runner-------------|--NSS Task Runner--|
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  SSLClientSocketNSS          Core            Socket         Core
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//       Read()
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//         |---------------------V
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                             Read()
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                               |-------------------------------V
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                                             Read()
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                                               |
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                                         DoPayloadRead()
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                                               |
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                                          BufferRecv
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                               V-------------------------------|
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                          DoBufferRecv
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                               |----------------V
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                              Read()
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                               V----------------|
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                        BufferRecvComplete()
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                               |-------------------------------V
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                                      BufferRecvComplete()
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                                               |
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                                       PostOrRunCallback()
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                               V-------------------------------|
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                        PostOrRunCallback()
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//         V---------------------|
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    (Read Callback)
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SSLClientSocketNSS::Core : public base::RefCountedThreadSafe<Core> {
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Creates a new Core.
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Any calls to NSS are executed on the |nss_task_runner|, while any calls
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // that need to operate on the underlying transport, net log, or server
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // bound certificate fetching will happen on the |network_task_runner|, so
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // that their lifetimes match that of the owning SSLClientSocketNSS.
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The caller retains ownership of |transport|, |net_log|, and
5795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // |channel_id_service|, and they will not be accessed once Detach()
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // has been called.
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Core(base::SequencedTaskRunner* network_task_runner,
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       base::SequencedTaskRunner* nss_task_runner,
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ClientSocketHandle* transport,
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       const HostPortPair& host_and_port,
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       const SSLConfig& ssl_config,
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       BoundNetLog* net_log,
5875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)       ChannelIDService* channel_id_service);
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called on the network task runner.
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Transfers ownership of |socket|, an NSS SSL socket, and |buffers|, the
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // underlying memio implementation, to the Core. Returns true if the Core
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // was successfully registered with the socket.
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool Init(PRFileDesc* socket, memio_Private* buffers);
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called on the network task runner.
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Attempts to perform an SSL handshake. If the handshake cannot be
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // completed synchronously, returns ERR_IO_PENDING, invoking |callback| on
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the network task runner once the handshake has completed. Otherwise,
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // returns OK on success or a network error code on failure.
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int Connect(const CompletionCallback& callback);
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called on the network task runner.
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Signals that the resources owned by the network task runner are going
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // away. No further callbacks will be invoked on the network task runner.
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // May be called at any time.
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Detach();
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called on the network task runner.
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns the current state of the underlying SSL socket. May be called at
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // any time.
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HandshakeState& state() const { return network_handshake_state_; }
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called on the network task runner.
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read() and Write() mirror the net::Socket functions of the same name.
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If ERR_IO_PENDING is returned, |callback| will be invoked on the network
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // task runner at a later point, unless the caller calls Detach().
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int Read(IOBuffer* buf, int buf_len, const CompletionCallback& callback);
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int Write(IOBuffer* buf, int buf_len, const CompletionCallback& callback);
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Called on the network task runner.
622effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  bool IsConnected() const;
623effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  bool HasPendingAsyncOperation() const;
624effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  bool HasUnhandledReceivedData() const;
625effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  bool WasEverUsed() const;
6262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Called on the network task runner.
6285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Causes the associated SSL/TLS session ID to be added to NSS's session
6295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // cache, but only if the connection has not been False Started.
6305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  //
6315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // This should only be called after the server's certificate has been
6325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // verified, and may not be called within an NSS callback.
6335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void CacheSessionIfNecessary();
6345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class base::RefCountedThreadSafe<Core>;
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~Core();
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum State {
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    STATE_NONE,
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    STATE_HANDSHAKE,
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    STATE_GET_DOMAIN_BOUND_CERT_COMPLETE,
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool OnNSSTaskRunner() const;
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool OnNetworkTaskRunner() const;
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////////////////////////////////////////
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Methods that are ONLY called on the NSS task runner:
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////////////////////////////////////////
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called by NSS during full handshakes to allow the application to
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // verify the certificate. Instead of verifying the certificate in the midst
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // of the handshake, SECSuccess is always returned and the peer's certificate
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is verified afterwards.
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This behaviour is an artifact of the original SSLClientSocketWin
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // implementation, which could not verify the peer's certificate until after
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the handshake had completed, as well as bugs in NSS that prevent
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SSL_RestartHandshakeAfterCertReq from working.
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static SECStatus OwnAuthCertHandler(void* arg,
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      PRFileDesc* socket,
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      PRBool checksig,
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      PRBool is_server);
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Callbacks called by NSS when the peer requests client certificate
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // authentication.
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // See the documentation in third_party/nss/ssl/ssl.h for the meanings of
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the arguments.
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(NSS_PLATFORM_CLIENT_AUTH)
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // When NSS has been integrated with awareness of the underlying system
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // cryptographic libraries, this callback allows the caller to supply a
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // native platform certificate and key for use by NSS. At most, one of
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // either (result_certs, result_private_key) or (result_nss_certificate,
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // result_nss_private_key) should be set.
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |arg| contains a pointer to the current SSLClientSocketNSS::Core.
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static SECStatus PlatformClientAuthHandler(
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      void* arg,
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PRFileDesc* socket,
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CERTDistNames* ca_names,
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CERTCertList** result_certs,
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      void** result_private_key,
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CERTCertificate** result_nss_certificate,
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SECKEYPrivateKey** result_nss_private_key);
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static SECStatus ClientAuthHandler(void* arg,
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     PRFileDesc* socket,
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     CERTDistNames* ca_names,
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     CERTCertificate** result_certificate,
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     SECKEYPrivateKey** result_private_key);
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
692f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Called by NSS to determine if we can False Start.
693f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // |arg| contains a pointer to the current SSLClientSocketNSS::Core.
694f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  static SECStatus CanFalseStartCallback(PRFileDesc* socket,
695f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                         void* arg,
696f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                         PRBool* can_false_start);
697f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called by NSS once the handshake has completed.
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |arg| contains a pointer to the current SSLClientSocketNSS::Core.
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void HandshakeCallback(PRFileDesc* socket, void* arg);
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
702f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Called once the handshake has succeeded.
703f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  void HandshakeSucceeded();
704f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Handles an NSS error generated while handshaking or performing IO.
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns a network error code mapped from the original NSS error.
707116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  int HandleNSSError(PRErrorCode error);
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int DoHandshakeLoop(int last_io_result);
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int DoReadLoop(int result);
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int DoWriteLoop(int result);
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int DoHandshake();
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int DoGetDBCertComplete(int result);
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int DoPayloadRead();
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int DoPayloadWrite();
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool DoTransportIO();
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int BufferRecv();
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int BufferSend();
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnRecvComplete(int result);
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnSendComplete(int result);
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DoConnectCallback(int result);
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DoReadCallback(int result);
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DoWriteCallback(int result);
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Client channel ID handler.
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static SECStatus ClientChannelIDHandler(
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      void* arg,
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PRFileDesc* socket,
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SECKEYPublicKey **out_public_key,
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SECKEYPrivateKey **out_private_key);
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ImportChannelIDKeys is a helper function for turning a DER-encoded cert and
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // key into a SECKEYPublicKey and SECKEYPrivateKey. Returns OK upon success
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and an error code otherwise.
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Requires |domain_bound_private_key_| and |domain_bound_cert_| to have been
7415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // set by a call to ChannelIDService->GetChannelID. The caller
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // takes ownership of the |*cert| and |*key|.
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ImportChannelIDKeys(SECKEYPublicKey** public_key, SECKEYPrivateKey** key);
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Updates the NSS and platform specific certificates.
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void UpdateServerCert();
7475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Update the nss_handshake_state_ with the SignedCertificateTimestampList
7485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // received in the handshake via a TLS extension.
749a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  void UpdateSignedCertTimestamps();
7505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Update the OCSP response cache with the stapled response received in the
7515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // handshake, and update nss_handshake_state_ with
7525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // the SignedCertificateTimestampList received in the stapled OCSP response.
7535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void UpdateStapledOCSPResponse();
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Updates the nss_handshake_state_ with the negotiated security parameters.
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void UpdateConnectionStatus();
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Record histograms for channel id support during full handshakes - resumed
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // handshakes are ignored.
7581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  void RecordChannelIDSupportOnNSSTaskRunner();
759eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // UpdateNextProto gets any application-layer protocol that may have been
760eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // negotiated by the TLS connection.
761eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  void UpdateNextProto();
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////////////////////////////////////////
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Methods that are ONLY called on the network task runner:
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////////////////////////////////////////
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int DoBufferRecv(IOBuffer* buffer, int len);
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int DoBufferSend(IOBuffer* buffer, int len);
7685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  int DoGetChannelID(const std::string& host);
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  void OnGetChannelIDComplete(int result);
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnHandshakeStateUpdated(const HandshakeState& state);
7722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void OnNSSBufferUpdated(int amount_in_read_buffer);
7732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void DidNSSRead(int result);
7742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void DidNSSWrite(int result);
775b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  void RecordChannelIDSupportOnNetworkTaskRunner(
776b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      bool negotiated_channel_id,
777b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      bool channel_id_enabled,
778b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      bool supports_ecc) const;
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////////////////////////////////////////
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Methods that are called on both the network task runner and the NSS
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // task runner.
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////////////////////////////////////////
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnHandshakeIOComplete(int result);
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void BufferRecvComplete(IOBuffer* buffer, int result);
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void BufferSendComplete(int result);
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // PostOrRunCallback is a helper function to ensure that |callback| is
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // invoked on the network task runner, but only if Detach() has not yet
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // been called.
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void PostOrRunCallback(const tracked_objects::Location& location,
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         const base::Closure& callback);
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Uses PostOrRunCallback and |weak_net_log_| to try and log a
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SSL_CLIENT_CERT_PROVIDED event, with the indicated count.
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AddCertProvidedEvent(int cert_count);
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Sets the handshake state |channel_id_sent| flag and logs the
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SSL_CHANNEL_ID_PROVIDED event.
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetChannelIDProvided();
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////////////////////////////////////////
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Members that are ONLY accessed on the network task runner:
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////////////////////////////////////////
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // True if the owning SSLClientSocketNSS has called Detach(). No further
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // callbacks will be invoked nor access to members owned by the network
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // task runner.
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool detached_;
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The underlying transport to use for network IO.
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClientSocketHandle* transport_;
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WeakPtrFactory<BoundNetLog> weak_net_log_factory_;
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The current handshake state. Mirrors |nss_handshake_state_|.
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HandshakeState network_handshake_state_;
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The service for retrieving Channel ID keys.  May be NULL.
8195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ChannelIDService* channel_id_service_;
8205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ChannelIDService::RequestHandle domain_bound_cert_request_handle_;
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The information about NSS task runner.
8232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int unhandled_buffer_size_;
8242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool nss_waiting_read_;
8252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool nss_waiting_write_;
8262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool nss_is_closed_;
8272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
828effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Set when Read() or Write() successfully reads or writes data to or from the
829effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // network.
830effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  bool was_ever_used_;
831effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////////////////////////////////////////
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Members that are ONLY accessed on the NSS task runner:
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////////////////////////////////////////
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HostPortPair host_and_port_;
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLConfig ssl_config_;
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NSS SSL socket.
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PRFileDesc* nss_fd_;
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Buffers for the network end of the SSL state machine
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memio_Private* nss_bufs_;
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Used by DoPayloadRead() when attempting to fill the caller's buffer with
8452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // as much data as possible, without blocking.
8462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If DoPayloadRead() encounters an error after having read some data, stores
8472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the results to return on the *next* call to DoPayloadRead(). A value of
8482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // kNoPendingReadResult indicates there is no pending result, otherwise 0
8492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // indicates EOF and < 0 indicates an error.
8502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int pending_read_result_;
8512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Contains the previously observed NSS error. Only valid when
8522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // pending_read_result_ != kNoPendingReadResult.
8532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PRErrorCode pending_read_nss_error_;
8542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The certificate chain, in DER form, that is expected to be received from
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the server.
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> predicted_certs_;
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  State next_handshake_state_;
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // True if channel ID extension was negotiated.
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool channel_id_xtn_negotiated_;
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // True if the handshake state machine was interrupted for channel ID.
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool channel_id_needed_;
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // True if the handshake state machine was interrupted for client auth.
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool client_auth_cert_needed_;
867f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // True if NSS has False Started.
868f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  bool false_started_;
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // True if NSS has called HandshakeCallback.
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool handshake_callback_called_;
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HandshakeState nss_handshake_state_;
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool transport_recv_busy_;
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool transport_recv_eof_;
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool transport_send_busy_;
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Used by Read function.
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<IOBuffer> user_read_buf_;
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int user_read_buf_len_;
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Used by Write function.
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<IOBuffer> user_write_buf_;
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int user_write_buf_len_;
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CompletionCallback user_connect_callback_;
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CompletionCallback user_read_callback_;
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CompletionCallback user_write_callback_;
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////////////////////////////////////////
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Members that are accessed on both the network task runner and the NSS
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // task runner.
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////////////////////////////////////////
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<base::SequencedTaskRunner> network_task_runner_;
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<base::SequencedTaskRunner> nss_task_runner_;
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Dereferenced only on the network task runner, but bound to tasks destined
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // for the network task runner from the NSS task runner.
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WeakPtr<BoundNetLog> weak_net_log_;
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Written on the network task runner by the |channel_id_service_|,
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // prior to invoking OnHandshakeIOComplete.
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read on the NSS task runner when once OnHandshakeIOComplete is invoked
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // on the NSS task runner.
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string domain_bound_private_key_;
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string domain_bound_cert_;
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(Core);
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SSLClientSocketNSS::Core::Core(
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::SequencedTaskRunner* network_task_runner,
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::SequencedTaskRunner* nss_task_runner,
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ClientSocketHandle* transport,
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const HostPortPair& host_and_port,
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SSLConfig& ssl_config,
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BoundNetLog* net_log,
9185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ChannelIDService* channel_id_service)
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : detached_(false),
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      transport_(transport),
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      weak_net_log_factory_(net_log),
9225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      channel_id_service_(channel_id_service),
9232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      unhandled_buffer_size_(0),
9242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      nss_waiting_read_(false),
9252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      nss_waiting_write_(false),
9262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      nss_is_closed_(false),
927effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      was_ever_used_(false),
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      host_and_port_(host_and_port),
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ssl_config_(ssl_config),
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nss_fd_(NULL),
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nss_bufs_(NULL),
9322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      pending_read_result_(kNoPendingReadResult),
9332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      pending_read_nss_error_(0),
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next_handshake_state_(STATE_NONE),
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      channel_id_xtn_negotiated_(false),
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      channel_id_needed_(false),
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      client_auth_cert_needed_(false),
938f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      false_started_(false),
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      handshake_callback_called_(false),
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      transport_recv_busy_(false),
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      transport_recv_eof_(false),
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      transport_send_busy_(false),
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      user_read_buf_len_(0),
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      user_write_buf_len_(0),
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      network_task_runner_(network_task_runner),
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nss_task_runner_(nss_task_runner),
947bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      weak_net_log_(weak_net_log_factory_.GetWeakPtr()) {
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SSLClientSocketNSS::Core::~Core() {
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(wtc): Send SSL close_notify alert.
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (nss_fd_ != NULL) {
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PR_Close(nss_fd_);
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nss_fd_ = NULL;
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
956116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  nss_bufs_ = NULL;
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketNSS::Core::Init(PRFileDesc* socket,
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    memio_Private* buffers) {
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNetworkTaskRunner());
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!nss_fd_);
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!nss_bufs_);
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nss_fd_ = socket;
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nss_bufs_ = buffers;
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECStatus rv = SECSuccess;
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ssl_config_.next_protos.empty()) {
9715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    std::vector<uint8_t> wire_protos =
9725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        SerializeNextProtos(ssl_config_.next_protos);
9735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    rv = SSL_SetNextProtoNego(
9745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        nss_fd_, wire_protos.empty() ? NULL : &wire_protos[0],
9755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        wire_protos.size());
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv != SECSuccess)
9775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      LogFailedNSSFunction(*weak_net_log_, "SSL_SetNextProtoNego", "");
9785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_ALPN, PR_TRUE);
9795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (rv != SECSuccess)
9805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      LogFailedNSSFunction(*weak_net_log_, "SSL_OptionSet", "SSL_ENABLE_ALPN");
9815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_NPN, PR_TRUE);
9825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (rv != SECSuccess)
9835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      LogFailedNSSFunction(*weak_net_log_, "SSL_OptionSet", "SSL_ENABLE_NPN");
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_AuthCertificateHook(
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nss_fd_, SSLClientSocketNSS::Core::OwnAuthCertHandler, this);
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess) {
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(*weak_net_log_, "SSL_AuthCertificateHook", "");
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(NSS_PLATFORM_CLIENT_AUTH)
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_GetPlatformClientAuthDataHook(
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nss_fd_, SSLClientSocketNSS::Core::PlatformClientAuthHandler,
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this);
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_GetClientAuthDataHook(
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nss_fd_, SSLClientSocketNSS::Core::ClientAuthHandler, this);
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess) {
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(*weak_net_log_, "SSL_GetClientAuthDataHook", "");
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (IsChannelIDEnabled(ssl_config_, channel_id_service_)) {
10071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    rv = SSL_SetClientChannelIDCallback(
10081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        nss_fd_, SSLClientSocketNSS::Core::ClientChannelIDHandler, this);
10091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (rv != SECSuccess) {
10101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      LogFailedNSSFunction(
10111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          *weak_net_log_, "SSL_SetClientChannelIDCallback", "");
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  rv = SSL_SetCanFalseStartCallback(
1016f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      nss_fd_, SSLClientSocketNSS::Core::CanFalseStartCallback, this);
1017f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (rv != SECSuccess) {
1018f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    LogFailedNSSFunction(*weak_net_log_, "SSL_SetCanFalseStartCallback", "");
1019f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return false;
1020f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
1021f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_HandshakeCallback(
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nss_fd_, SSLClientSocketNSS::Core::HandshakeCallback, this);
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess) {
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(*weak_net_log_, "SSL_HandshakeCallback", "");
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Core::Connect(const CompletionCallback& callback) {
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!OnNSSTaskRunner()) {
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!detached_);
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool posted = nss_task_runner_->PostTask(
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(IgnoreResult(&Core::Connect), this, callback));
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return posted ? ERR_IO_PENDING : ERR_ABORTED;
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(STATE_NONE, next_handshake_state_);
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(user_read_callback_.is_null());
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(user_write_callback_.is_null());
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(user_connect_callback_.is_null());
1046868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!user_read_buf_.get());
1047868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!user_write_buf_.get());
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_handshake_state_ = STATE_HANDSHAKE;
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = DoHandshakeLoop(OK);
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv == ERR_IO_PENDING) {
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_connect_callback_ = callback;
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (rv > OK) {
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = OK;
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != ERR_IO_PENDING && !OnNetworkTaskRunner()) {
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PostOrRunCallback(FROM_HERE, base::Bind(callback, rv));
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_IO_PENDING;
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::Detach() {
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNetworkTaskRunner());
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  detached_ = true;
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transport_ = NULL;
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  weak_net_log_factory_.InvalidateWeakPtrs();
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  network_handshake_state_.Reset();
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  domain_bound_cert_request_handle_.Cancel();
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Core::Read(IOBuffer* buf, int buf_len,
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   const CompletionCallback& callback) {
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!OnNSSTaskRunner()) {
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(OnNetworkTaskRunner());
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!detached_);
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(transport_);
10822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(!nss_waiting_read_);
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    nss_waiting_read_ = true;
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool posted = nss_task_runner_->PostTask(
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(IgnoreResult(&Core::Read), this, make_scoped_refptr(buf),
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   buf_len, callback));
10892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!posted) {
10902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      nss_is_closed_ = true;
10912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      nss_waiting_read_ = false;
10922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return posted ? ERR_IO_PENDING : ERR_ABORTED;
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
1097f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(false_started_ || handshake_callback_called_);
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(STATE_NONE, next_handshake_state_);
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(user_read_callback_.is_null());
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(user_connect_callback_.is_null());
1101868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!user_read_buf_.get());
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(nss_bufs_);
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_read_buf_ = buf;
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_read_buf_len_ = buf_len;
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = DoReadLoop(OK);
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv == ERR_IO_PENDING) {
11092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (OnNetworkTaskRunner())
11102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      nss_waiting_read_ = true;
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_read_callback_ = callback;
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_read_buf_ = NULL;
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_read_buf_len_ = 0;
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!OnNetworkTaskRunner()) {
11172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      PostOrRunCallback(FROM_HERE, base::Bind(&Core::DidNSSRead, this, rv));
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PostOrRunCallback(FROM_HERE, base::Bind(callback, rv));
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ERR_IO_PENDING;
11202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
11212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DCHECK(!nss_waiting_read_);
1122effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      if (rv <= 0) {
11232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        nss_is_closed_ = true;
1124effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      } else {
1125effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        was_ever_used_ = true;
1126effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      }
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Core::Write(IOBuffer* buf, int buf_len,
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    const CompletionCallback& callback) {
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!OnNSSTaskRunner()) {
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(OnNetworkTaskRunner());
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!detached_);
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(transport_);
11392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(!nss_waiting_write_);
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    nss_waiting_write_ = true;
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool posted = nss_task_runner_->PostTask(
11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(IgnoreResult(&Core::Write), this, make_scoped_refptr(buf),
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   buf_len, callback));
11462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!posted) {
11472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      nss_is_closed_ = true;
11482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      nss_waiting_write_ = false;
11492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
11502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return posted ? ERR_IO_PENDING : ERR_ABORTED;
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
1154f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(false_started_ || handshake_callback_called_);
11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(STATE_NONE, next_handshake_state_);
11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(user_write_callback_.is_null());
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(user_connect_callback_.is_null());
1158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!user_write_buf_.get());
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(nss_bufs_);
11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_write_buf_ = buf;
11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_write_buf_len_ = buf_len;
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = DoWriteLoop(OK);
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv == ERR_IO_PENDING) {
11662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (OnNetworkTaskRunner())
11672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      nss_waiting_write_ = true;
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_write_callback_ = callback;
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_write_buf_ = NULL;
11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_write_buf_len_ = 0;
11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!OnNetworkTaskRunner()) {
11742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      PostOrRunCallback(FROM_HERE, base::Bind(&Core::DidNSSWrite, this, rv));
11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PostOrRunCallback(FROM_HERE, base::Bind(callback, rv));
11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ERR_IO_PENDING;
11772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
11782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DCHECK(!nss_waiting_write_);
1179effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      if (rv < 0) {
11802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        nss_is_closed_ = true;
1181effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      } else if (rv > 0) {
1182effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        was_ever_used_ = true;
1183effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      }
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1190effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochbool SSLClientSocketNSS::Core::IsConnected() const {
11912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(OnNetworkTaskRunner());
11922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return !nss_is_closed_;
11932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
11942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1195effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochbool SSLClientSocketNSS::Core::HasPendingAsyncOperation() const {
11962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(OnNetworkTaskRunner());
11972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return nss_waiting_read_ || nss_waiting_write_;
11982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
11992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1200effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochbool SSLClientSocketNSS::Core::HasUnhandledReceivedData() const {
12012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(OnNetworkTaskRunner());
12022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return unhandled_buffer_size_ != 0;
12032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
12042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1205effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochbool SSLClientSocketNSS::Core::WasEverUsed() const {
1206effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK(OnNetworkTaskRunner());
1207effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return was_ever_used_;
1208effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
1209effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
12105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SSLClientSocketNSS::Core::CacheSessionIfNecessary() {
12115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // TODO(rsleevi): This should occur on the NSS task runner, due to the use of
12125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // nss_fd_. However, it happens on the network task runner in order to match
12135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // the buggy behavior of ExportKeyingMaterial.
12145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  //
12155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Once http://crbug.com/330360 is fixed, this should be moved to an
12165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // implementation that exclusively does this work on the NSS TaskRunner. This
12175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // is "safe" because it is only called during the certificate verification
12185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // state machine of the main socket, which is safe because no underlying
12195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // transport IO will be occuring in that state, and NSS will not be blocking
12205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // on any PKCS#11 related locks that might block the Network TaskRunner.
12215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(OnNetworkTaskRunner());
12225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
12235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Only cache the session if the connection was not False Started, because
12245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // sessions should only be cached *after* the peer's Finished message is
12255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // processed.
12265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // In the case of False Start, the session will be cached once the
12275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // HandshakeCallback is called, which signals the receipt and processing of
12285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // the Finished message, and which will happen during a call to
12295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // PR_Read/PR_Write.
12305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!false_started_)
12315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    SSL_CacheSession(nss_fd_);
12325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
12335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketNSS::Core::OnNSSTaskRunner() const {
12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return nss_task_runner_->RunsTasksOnCurrentThread();
12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketNSS::Core::OnNetworkTaskRunner() const {
12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return network_task_runner_->RunsTasksOnCurrentThread();
12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus SSLClientSocketNSS::Core::OwnAuthCertHandler(
12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* arg,
12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRFileDesc* socket,
12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRBool checksig,
12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRBool is_server) {
12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Core* core = reinterpret_cast<Core*>(arg);
1249f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (core->handshake_callback_called_) {
12508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // Disallow the server certificate to change in a renegotiation.
12518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    CERTCertificate* old_cert = core->nss_handshake_state_.server_cert_chain[0];
1252f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    ScopedCERTCertificate new_cert(SSL_PeerCertificate(socket));
12538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (new_cert->derCert.len != old_cert->derCert.len ||
12548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        memcmp(new_cert->derCert.data, old_cert->derCert.data,
12558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)               new_cert->derCert.len) != 0) {
12568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      // NSS doesn't have an error code that indicates the server certificate
12578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      // changed. Borrow SSL_ERROR_WRONG_CERTIFICATE (which NSS isn't using)
12588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      // for this purpose.
12598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      PORT_SetError(SSL_ERROR_WRONG_CERTIFICATE);
12608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      return SECFailure;
12618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Tell NSS to not verify the certificate.
12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SECSuccess;
12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(NSS_PLATFORM_CLIENT_AUTH)
12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus SSLClientSocketNSS::Core::PlatformClientAuthHandler(
12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* arg,
12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRFileDesc* socket,
12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CERTDistNames* ca_names,
12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CERTCertList** result_certs,
12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void** result_private_key,
12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CERTCertificate** result_nss_certificate,
12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECKEYPrivateKey** result_nss_private_key) {
12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Core* core = reinterpret_cast<Core*>(arg);
12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(core->OnNSSTaskRunner());
12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core->PostOrRunCallback(
12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&AddLogEvent, core->weak_net_log_,
12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 NetLog::TYPE_SSL_CLIENT_CERT_REQUESTED));
12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core->client_auth_cert_needed_ = !core->ssl_config_.send_client_cert;
12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (core->ssl_config_.send_client_cert) {
12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (core->ssl_config_.client_cert) {
12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PCCERT_CONTEXT cert_context =
12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          core->ssl_config_.client_cert->os_cert_handle();
12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HCRYPTPROV_OR_NCRYPT_KEY_HANDLE crypt_prov = 0;
12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DWORD key_spec = 0;
12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BOOL must_free = FALSE;
129690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      DWORD flags = 0;
129790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (base::win::GetVersion() >= base::win::VERSION_VISTA)
1298868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        flags |= CRYPT_ACQUIRE_PREFER_NCRYPT_KEY_FLAG;
129990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BOOL acquired_key = CryptAcquireCertificatePrivateKey(
130190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          cert_context, flags, NULL, &crypt_prov, &key_spec, &must_free);
13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (acquired_key) {
130490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        // Should never get a cached handle back - ownership must always be
130590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        // transferred.
130690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        CHECK_EQ(must_free, TRUE);
13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SECItem der_cert;
13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        der_cert.type = siDERCertBuffer;
13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        der_cert.data = cert_context->pbCertEncoded;
13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        der_cert.len  = cert_context->cbCertEncoded;
13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // TODO(rsleevi): Error checking for NSS allocation errors.
13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CERTCertDBHandle* db_handle = CERT_GetDefaultCertDB();
13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CERTCertificate* user_cert = CERT_NewTempCertificate(
13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            db_handle, &der_cert, NULL, PR_FALSE, PR_TRUE);
13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!user_cert) {
13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // Importing the certificate can fail for reasons including a serial
13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // number collision. See crbug.com/97355.
13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          core->AddCertProvidedEvent(0);
13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return SECFailure;
13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CERTCertList* cert_chain = CERT_NewCertList();
13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CERT_AddCertToListTail(cert_chain, user_cert);
13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Add the intermediates.
13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        X509Certificate::OSCertHandles intermediates =
13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            core->ssl_config_.client_cert->GetIntermediateCertificates();
13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (X509Certificate::OSCertHandles::const_iterator it =
13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            intermediates.begin(); it != intermediates.end(); ++it) {
13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          der_cert.data = (*it)->pbCertEncoded;
13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          der_cert.len = (*it)->cbCertEncoded;
13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          CERTCertificate* intermediate = CERT_NewTempCertificate(
13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              db_handle, &der_cert, NULL, PR_FALSE, PR_TRUE);
13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (!intermediate) {
13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            CERT_DestroyCertList(cert_chain);
13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            core->AddCertProvidedEvent(0);
13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return SECFailure;
13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          CERT_AddCertToListTail(cert_chain, intermediate);
13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        PCERT_KEY_CONTEXT key_context = reinterpret_cast<PCERT_KEY_CONTEXT>(
13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            PORT_ZAlloc(sizeof(CERT_KEY_CONTEXT)));
13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        key_context->cbSize = sizeof(*key_context);
134690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        // NSS will free this context when no longer in use.
13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        key_context->hCryptProv = crypt_prov;
13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        key_context->dwKeySpec = key_spec;
13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *result_private_key = key_context;
13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *result_certs = cert_chain;
13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int cert_count = 1 + intermediates.size();
13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        core->AddCertProvidedEvent(cert_count);
13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return SECSuccess;
13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(WARNING) << "Client cert found without private key";
13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Send no client certificate.
13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    core->AddCertProvidedEvent(0);
13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SECFailure;
13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  core->nss_handshake_state_.cert_authorities.clear();
13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<CERT_NAME_BLOB> issuer_list(ca_names->nnames);
13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < ca_names->nnames; ++i) {
13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    issuer_list[i].cbData = ca_names->names[i].len;
13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    issuer_list[i].pbData = ca_names->names[i].data;
13702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    core->nss_handshake_state_.cert_authorities.push_back(std::string(
13712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        reinterpret_cast<const char*>(ca_names->names[i].data),
13722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        static_cast<size_t>(ca_names->names[i].len)));
13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Update the network task runner's view of the handshake state now that
13762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // server certificate request has been recorded.
13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core->PostOrRunCallback(
13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE, base::Bind(&Core::OnHandshakeStateUpdated, core,
13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            core->nss_handshake_state_));
13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Tell NSS to suspend the client authentication.  We will then abort the
13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // handshake by returning ERR_SSL_CLIENT_AUTH_CERT_NEEDED.
13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SECWouldBlock;
13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_MACOSX)
13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (core->ssl_config_.send_client_cert) {
13867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (core->ssl_config_.client_cert.get()) {
13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OSStatus os_error = noErr;
13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SecIdentityRef identity = NULL;
13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SecKeyRef private_key = NULL;
1390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      X509Certificate::OSCertHandles chain;
1391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      {
1392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        base::AutoLock lock(crypto::GetMacSecurityServicesLock());
1393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        os_error = SecIdentityCreateWithCertificate(
1394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            NULL, core->ssl_config_.client_cert->os_cert_handle(), &identity);
13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1396c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (os_error == noErr) {
13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        os_error = SecIdentityCopyPrivateKey(identity, &private_key);
1398c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        CFRelease(identity);
1399c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
14005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1401c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (os_error == noErr) {
14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // TODO(rsleevi): Error checking for NSS allocation errors.
14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *result_certs = CERT_NewCertList();
14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *result_private_key = private_key;
14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1406c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        chain.push_back(core->ssl_config_.client_cert->os_cert_handle());
1407c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        const X509Certificate::OSCertHandles& intermediates =
1408c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            core->ssl_config_.client_cert->GetIntermediateCertificates();
1409c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (!intermediates.empty())
1410c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          chain.insert(chain.end(), intermediates.begin(), intermediates.end());
1411c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1412c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        for (size_t i = 0, chain_count = chain.size(); i < chain_count; ++i) {
14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          CSSM_DATA cert_data;
1414c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          SecCertificateRef cert_ref = chain[i];
14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          os_error = SecCertificateGetData(cert_ref, &cert_data);
14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (os_error != noErr)
14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          SECItem der_cert;
14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          der_cert.type = siDERCertBuffer;
14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          der_cert.data = cert_data.Data;
14225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          der_cert.len = cert_data.Length;
14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          CERTCertificate* nss_cert = CERT_NewTempCertificate(
14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              CERT_GetDefaultCertDB(), &der_cert, NULL, PR_FALSE, PR_TRUE);
14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (!nss_cert) {
1426c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            // In the event of an NSS error, make up an OS error and reuse
1427c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            // the error handling below.
14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            os_error = errSecCreateChainFailed;
14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
14305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
14315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          CERT_AddCertToListTail(*result_certs, nss_cert);
14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
14335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1434c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
14355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (os_error == noErr) {
1436c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        core->AddCertProvidedEvent(chain.size());
14375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return SECSuccess;
14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1439c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
14405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OSSTATUS_LOG(WARNING, os_error)
14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << "Client cert found, but could not be used";
14425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (*result_certs) {
14435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CERT_DestroyCertList(*result_certs);
14445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *result_certs = NULL;
14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
14465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (*result_private_key)
14475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *result_private_key = NULL;
14485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (private_key)
14495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CFRelease(private_key);
14505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
14515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Send no client certificate.
14535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    core->AddCertProvidedEvent(0);
14545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SECFailure;
14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  core->nss_handshake_state_.cert_authorities.clear();
14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Retrieve the cert issuers accepted by the server.
14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<CertPrincipal> valid_issuers;
14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int n = ca_names->nnames;
14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < n; i++) {
14632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    core->nss_handshake_state_.cert_authorities.push_back(std::string(
14642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        reinterpret_cast<const char*>(ca_names->names[i].data),
14652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        static_cast<size_t>(ca_names->names[i].len)));
14665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Update the network task runner's view of the handshake state now that
14692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // server certificate request has been recorded.
14705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core->PostOrRunCallback(
14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE, base::Bind(&Core::OnHandshakeStateUpdated, core,
14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            core->nss_handshake_state_));
14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Tell NSS to suspend the client authentication.  We will then abort the
14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // handshake by returning ERR_SSL_CLIENT_AUTH_CERT_NEEDED.
14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SECWouldBlock;
14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SECFailure;
14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_IOS)
14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus SSLClientSocketNSS::Core::ClientAuthHandler(
14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* arg,
14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRFileDesc* socket,
14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CERTDistNames* ca_names,
14885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CERTCertificate** result_certificate,
14895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECKEYPrivateKey** result_private_key) {
14905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Core* core = reinterpret_cast<Core*>(arg);
14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(core->OnNSSTaskRunner());
14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core->PostOrRunCallback(
14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
14955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&AddLogEvent, core->weak_net_log_,
14965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 NetLog::TYPE_SSL_CLIENT_CERT_REQUESTED));
14975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(droger): Support client auth on iOS. See http://crbug.com/145954).
14995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG(WARNING) << "Client auth is not supported";
15005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Never send a certificate.
15025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core->AddCertProvidedEvent(0);
15035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SECFailure;
15045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else  // NSS_PLATFORM_CLIENT_AUTH
15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Based on Mozilla's NSS_GetClientAuthData.
15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus SSLClientSocketNSS::Core::ClientAuthHandler(
15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* arg,
15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRFileDesc* socket,
15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CERTDistNames* ca_names,
15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CERTCertificate** result_certificate,
15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECKEYPrivateKey** result_private_key) {
15165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Core* core = reinterpret_cast<Core*>(arg);
15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(core->OnNSSTaskRunner());
15185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core->PostOrRunCallback(
15205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
15215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&AddLogEvent, core->weak_net_log_,
15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 NetLog::TYPE_SSL_CLIENT_CERT_REQUESTED));
15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Regular client certificate requested.
15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core->client_auth_cert_needed_ = !core->ssl_config_.send_client_cert;
15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* wincx  = SSL_RevealPinArg(socket);
15275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (core->ssl_config_.send_client_cert) {
15292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Second pass: a client certificate should have been selected.
1530868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (core->ssl_config_.client_cert.get()) {
1531868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      CERTCertificate* cert =
1532868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          CERT_DupCertificate(core->ssl_config_.client_cert->os_cert_handle());
15335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SECKEYPrivateKey* privkey = PK11_FindKeyByAnyCert(cert, wincx);
15345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (privkey) {
15355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // TODO(jsorianopastor): We should wait for server certificate
15365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // verification before sending our credentials.  See
15375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // http://crbug.com/13934.
15385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *result_certificate = cert;
15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *result_private_key = privkey;
15405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // A cert_count of -1 means the number of certificates is unknown.
15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // NSS will construct the certificate chain.
15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        core->AddCertProvidedEvent(-1);
15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return SECSuccess;
15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(WARNING) << "Client cert found without private key";
15475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
15485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Send no client certificate.
15495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    core->AddCertProvidedEvent(0);
15505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SECFailure;
15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // First pass: client certificate is needed.
15542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  core->nss_handshake_state_.cert_authorities.clear();
15555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Retrieve the DER-encoded DistinguishedName of the cert issuers accepted by
15572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the server and save them in |cert_authorities|.
15582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int i = 0; i < ca_names->nnames; i++) {
15592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    core->nss_handshake_state_.cert_authorities.push_back(std::string(
15602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        reinterpret_cast<const char*>(ca_names->names[i].data),
15612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        static_cast<size_t>(ca_names->names[i].len)));
15625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Update the network task runner's view of the handshake state now that
15652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // server certificate request has been recorded.
15665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core->PostOrRunCallback(
15675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE, base::Bind(&Core::OnHandshakeStateUpdated, core,
15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            core->nss_handshake_state_));
15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Tell NSS to suspend the client authentication.  We will then abort the
15715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // handshake by returning ERR_SSL_CLIENT_AUTH_CERT_NEEDED.
15725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SECWouldBlock;
15735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // NSS_PLATFORM_CLIENT_AUTH
15755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1577f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)SECStatus SSLClientSocketNSS::Core::CanFalseStartCallback(
1578f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    PRFileDesc* socket,
1579f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    void* arg,
1580f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    PRBool* can_false_start) {
1581f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // If the server doesn't support NPN or ALPN, then we don't do False
1582f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Start with it.
1583f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  PRBool negotiated_extension;
1584f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SECStatus rv = SSL_HandshakeNegotiatedExtension(socket,
1585f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                                  ssl_app_layer_protocol_xtn,
1586f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                                  &negotiated_extension);
1587f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (rv != SECSuccess || !negotiated_extension) {
1588f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    rv = SSL_HandshakeNegotiatedExtension(socket,
1589f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                          ssl_next_proto_nego_xtn,
1590f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                          &negotiated_extension);
1591f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
1592f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (rv != SECSuccess || !negotiated_extension) {
1593f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    *can_false_start = PR_FALSE;
1594f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return SECSuccess;
1595f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
1596f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1597f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return SSL_RecommendedCanFalseStart(socket, can_false_start);
1598f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
1599f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1600f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// static
16015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::HandshakeCallback(
16025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRFileDesc* socket,
16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* arg) {
16045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Core* core = reinterpret_cast<Core*>(arg);
16055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(core->OnNSSTaskRunner());
16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core->handshake_callback_called_ = true;
1608f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (core->false_started_) {
1609f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    core->false_started_ = false;
16105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // If the connection was False Started, then at the time of this callback,
16115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // the peer's certificate will have been verified or the caller will have
16125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // accepted the error.
16135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // This is guaranteed when using False Start because this callback will
16145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // not be invoked until processing the peer's Finished message, which
16155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // will only happen in a PR_Read/PR_Write call, which can only happen
16165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // after the peer's certificate is verified.
16175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    SSL_CacheSessionUnlocked(socket);
16185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
16195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Additionally, when False Starting, DoHandshake() will have already
16205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // called HandshakeSucceeded(), so return now.
1621f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
1622f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
1623f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  core->HandshakeSucceeded();
1624f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
16255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1626f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void SSLClientSocketNSS::Core::HandshakeSucceeded() {
1627f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(OnNSSTaskRunner());
16285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PRBool last_handshake_resumed;
1630f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SECStatus rv = SSL_HandshakeResumedSession(nss_fd_, &last_handshake_resumed);
16315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv == SECSuccess && last_handshake_resumed) {
1632f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    nss_handshake_state_.resumed_handshake = true;
16335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1634f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    nss_handshake_state_.resumed_handshake = false;
16355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1637f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  RecordChannelIDSupportOnNSSTaskRunner();
1638f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  UpdateServerCert();
1639a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  UpdateSignedCertTimestamps();
16405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  UpdateStapledOCSPResponse();
1641f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  UpdateConnectionStatus();
1642f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  UpdateNextProto();
16435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Update the network task runners view of the handshake state whenever
16455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a handshake has completed.
1646f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  PostOrRunCallback(
1647f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      FROM_HERE, base::Bind(&Core::OnHandshakeStateUpdated, this,
1648f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                            nss_handshake_state_));
16495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1651116680a4aac90f2aa7413d9095a592090648e557Ben Murdochint SSLClientSocketNSS::Core::HandleNSSError(PRErrorCode nss_error) {
16525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
16535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1654116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  int net_error = MapNSSClientError(nss_error);
16555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
16575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // On Windows, a handle to the HCRYPTPROV is cached in the X509Certificate
16585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // os_cert_handle() as an optimization. However, if the certificate
16595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // private key is stored on a smart card, and the smart card is removed,
16605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the cached HCRYPTPROV will not be able to obtain the HCRYPTKEY again,
16615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // preventing client certificate authentication. Because the
16625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // X509Certificate may outlive the individual SSLClientSocketNSS, due to
16635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // caching in X509Certificate, this failure ends up preventing client
16645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // certificate authentication with the same certificate for all future
16655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // attempts, even after the smart card has been re-inserted. By setting
16665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the CERT_KEY_PROV_HANDLE_PROP_ID to NULL, the cached HCRYPTPROV will
16675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // typically be freed. This allows a new HCRYPTPROV to be obtained from
16685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the certificate on the next attempt, which should succeed if the smart
16695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // card has been re-inserted, or will typically prompt the user to
16705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // re-insert the smart card if not.
16715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((net_error == ERR_SSL_CLIENT_AUTH_CERT_NO_PRIVATE_KEY ||
16725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       net_error == ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED) &&
16735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ssl_config_.send_client_cert && ssl_config_.client_cert) {
16745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CertSetCertificateContextProperty(
16755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ssl_config_.client_cert->os_cert_handle(),
16765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
16775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
16795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return net_error;
16815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Core::DoHandshakeLoop(int last_io_result) {
16845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
16855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = last_io_result;
16875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
16885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Default to STATE_NONE for next state.
16895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    State state = next_handshake_state_;
16905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GotoState(STATE_NONE);
16915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (state) {
16935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_HANDSHAKE:
16945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoHandshake();
16955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
16965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_GET_DOMAIN_BOUND_CERT_COMPLETE:
16975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoGetDBCertComplete(rv);
16985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
16995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_NONE:
17005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
17015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = ERR_UNEXPECTED;
17025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(DFATAL) << "unexpected state " << state;
17035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
17045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
17055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Do the actual network I/O
17075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool network_moved = DoTransportIO();
17085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (network_moved && next_handshake_state_ == STATE_HANDSHAKE) {
17095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // In general we exit the loop if rv is ERR_IO_PENDING.  In this
17105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // special case we keep looping even if rv is ERR_IO_PENDING because
17115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // the transport IO may allow DoHandshake to make progress.
17125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(rv == OK || rv == ERR_IO_PENDING);
17135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rv = OK;  // This causes us to stay in the loop.
17145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
17155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (rv != ERR_IO_PENDING && next_handshake_state_ != STATE_NONE);
17165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
17175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Core::DoReadLoop(int result) {
17205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
1721f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(false_started_ || handshake_callback_called_);
17225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(STATE_NONE, next_handshake_state_);
17235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result < 0)
17255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
17265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!nss_bufs_) {
17285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(DFATAL) << "!nss_bufs_";
17295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rv = ERR_UNEXPECTED;
17305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PostOrRunCallback(
17315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
17325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&AddLogEventWithCallback, weak_net_log_,
17335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   NetLog::TYPE_SSL_READ_ERROR,
17345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   CreateNetLogSSLErrorCallback(rv, 0)));
17355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
17365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool network_moved;
17395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv;
17405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
17415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = DoPayloadRead();
17425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    network_moved = DoTransportIO();
17435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (rv == ERR_IO_PENDING && network_moved);
17445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
17465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Core::DoWriteLoop(int result) {
17495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
1750f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(false_started_ || handshake_callback_called_);
17515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(STATE_NONE, next_handshake_state_);
17525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result < 0)
17545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
17555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!nss_bufs_) {
17575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(DFATAL) << "!nss_bufs_";
17585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rv = ERR_UNEXPECTED;
17595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PostOrRunCallback(
17605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
17615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&AddLogEventWithCallback, weak_net_log_,
17625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   NetLog::TYPE_SSL_READ_ERROR,
17635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   CreateNetLogSSLErrorCallback(rv, 0)));
17645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
17655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool network_moved;
17685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv;
17695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
17705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = DoPayloadWrite();
17715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    network_moved = DoTransportIO();
17725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (rv == ERR_IO_PENDING && network_moved);
17735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LeaveFunction(rv);
17755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
17765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Core::DoHandshake() {
17795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
17805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1781116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  int net_error = OK;
17825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECStatus rv = SSL_ForceHandshake(nss_fd_);
17835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note: this function may be called multiple times during the handshake, so
17855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // even though channel id and client auth are separate else cases, they can
17865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // both be used during a single SSL handshake.
17875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (channel_id_needed_) {
17885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GotoState(STATE_GET_DOMAIN_BOUND_CERT_COMPLETE);
17895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_error = ERR_IO_PENDING;
17905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (client_auth_cert_needed_) {
17915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_error = ERR_SSL_CLIENT_AUTH_CERT_NEEDED;
17925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PostOrRunCallback(
17935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
17945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&AddLogEventWithCallback, weak_net_log_,
17955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   NetLog::TYPE_SSL_HANDSHAKE_ERROR,
17965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   CreateNetLogSSLErrorCallback(net_error, 0)));
17975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If the handshake already succeeded (because the server requests but
17995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // doesn't require a client cert), we need to invalidate the SSL session
18005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // so that we won't try to resume the non-client-authenticated session in
18015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the next handshake.  This will cause the server to ask for a client
18025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // cert again.
18035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv == SECSuccess && SSL_InvalidateSession(nss_fd_) != SECSuccess)
18045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(WARNING) << "Couldn't invalidate SSL session: " << PR_GetError();
18055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (rv == SECSuccess) {
18065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!handshake_callback_called_) {
1807f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      false_started_ = true;
1808f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      HandshakeSucceeded();
1809f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
18105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
18115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRErrorCode prerr = PR_GetError();
1812116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    net_error = HandleNSSError(prerr);
18132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If not done, stay in this state
18155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (net_error == ERR_IO_PENDING) {
18165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GotoState(STATE_HANDSHAKE);
18175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
18185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PostOrRunCallback(
18195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          FROM_HERE,
18205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Bind(&AddLogEventWithCallback, weak_net_log_,
18215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     NetLog::TYPE_SSL_HANDSHAKE_ERROR,
18225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     CreateNetLogSSLErrorCallback(net_error, prerr)));
18235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
18245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return net_error;
18275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
18285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Core::DoGetDBCertComplete(int result) {
18305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECStatus rv;
18315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PostOrRunCallback(
18325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
18335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&BoundNetLog::EndEventWithNetErrorCode, weak_net_log_,
18345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 NetLog::TYPE_SSL_GET_DOMAIN_BOUND_CERT, result));
18355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  channel_id_needed_ = false;
18375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != OK)
18395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
18405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECKEYPublicKey* public_key;
18425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECKEYPrivateKey* private_key;
18435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int error = ImportChannelIDKeys(&public_key, &private_key);
18445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (error != OK)
18455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return error;
18465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_RestartHandshakeAfterChannelIDReq(nss_fd_, public_key, private_key);
18485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess)
18495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return MapNSSError(PORT_GetError());
18505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetChannelIDProvided();
18525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GotoState(STATE_HANDSHAKE);
18535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
18545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
18555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Core::DoPayloadRead() {
18575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
1858868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(user_read_buf_.get());
18595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GT(user_read_buf_len_, 0);
18605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int rv;
18622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If a previous greedy read resulted in an error that was not consumed (eg:
18632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // due to the caller having read some data successfully), then return that
18642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // pending error now.
18652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (pending_read_result_ != kNoPendingReadResult) {
18662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    rv = pending_read_result_;
18672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PRErrorCode prerr = pending_read_nss_error_;
18682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    pending_read_result_ = kNoPendingReadResult;
18692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    pending_read_nss_error_ = 0;
18702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (rv == 0) {
18722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      PostOrRunCallback(
18732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          FROM_HERE,
18742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::Bind(&LogByteTransferEvent, weak_net_log_,
18752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     NetLog::TYPE_SSL_SOCKET_BYTES_RECEIVED, rv,
18762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     scoped_refptr<IOBuffer>(user_read_buf_)));
18772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
18782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      PostOrRunCallback(
18792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          FROM_HERE,
18802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::Bind(&AddLogEventWithCallback, weak_net_log_,
18812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     NetLog::TYPE_SSL_READ_ERROR,
18822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CreateNetLogSSLErrorCallback(rv, prerr)));
18832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
18845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
18855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Perform a greedy read, attempting to read as much as the caller has
18882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // requested. In the current NSS implementation, PR_Read will return
18892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // exactly one SSL application data record's worth of data per invocation.
18902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The record size is dictated by the server, and may be noticeably smaller
18912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // than the caller's buffer. This may be as little as a single byte, if the
18922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // server is performing 1/n-1 record splitting.
18932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
18942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // However, this greedy read may result in renegotiations/re-handshakes
18952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // happening or may lead to some data being read, followed by an EOF (such as
18962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // a TLS close-notify). If at least some data was read, then that result
18972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // should be deferred until the next call to DoPayloadRead(). Otherwise, if no
18982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // data was read, it's safe to return the error or EOF immediately.
18992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int total_bytes_read = 0;
19002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  do {
19012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    rv = PR_Read(nss_fd_, user_read_buf_->data() + total_bytes_read,
19022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 user_read_buf_len_ - total_bytes_read);
19032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (rv > 0)
19042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      total_bytes_read += rv;
19052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } while (total_bytes_read < user_read_buf_len_ && rv > 0);
19062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int amount_in_read_buffer = memio_GetReadableBufferSize(nss_bufs_);
19072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PostOrRunCallback(FROM_HERE, base::Bind(&Core::OnNSSBufferUpdated, this,
19082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                          amount_in_read_buffer));
19092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (total_bytes_read == user_read_buf_len_) {
19112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // The caller's entire request was satisfied without error. No further
19122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // processing needed.
19132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    rv = total_bytes_read;
19142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
19152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Otherwise, an error occurred (rv <= 0). The error needs to be handled
19162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // immediately, while the NSPR/NSS errors are still available in
19172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // thread-local storage. However, the handled/remapped error code should
19182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // only be returned if no application data was already read; if it was, the
19192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // error code should be deferred until the next call of DoPayloadRead.
19202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    //
19212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // If no data was read, |*next_result| will point to the return value of
19222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // this function. If at least some data was read, |*next_result| will point
19232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // to |pending_read_error_|, to be returned in a future call to
19242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // DoPayloadRead() (e.g.: after the current data is handled).
19252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int* next_result = &rv;
19262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (total_bytes_read > 0) {
19272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      pending_read_result_ = rv;
19282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      rv = total_bytes_read;
19292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      next_result = &pending_read_result_;
19302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
19312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (client_auth_cert_needed_) {
19332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *next_result = ERR_SSL_CLIENT_AUTH_CERT_NEEDED;
19342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      pending_read_nss_error_ = 0;
19352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else if (*next_result < 0) {
19362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // If *next_result == 0, then that indicates EOF, and no special error
19372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // handling is needed.
19382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      pending_read_nss_error_ = PR_GetError();
1939116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      *next_result = HandleNSSError(pending_read_nss_error_);
19402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (rv > 0 && *next_result == ERR_IO_PENDING) {
19412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // If at least some data was read from PR_Read(), do not treat
19422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // insufficient data as an error to return in the next call to
19432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // DoPayloadRead() - instead, let the call fall through to check
19442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // PR_Read() again. This is because DoTransportIO() may complete
19452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // in between the next call to DoPayloadRead(), and thus it is
19462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // important to check PR_Read() on subsequent invocations to see
19472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // if a complete record may now be read.
19482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        pending_read_nss_error_ = 0;
19492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        pending_read_result_ = kNoPendingReadResult;
19502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
19512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
19522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
19532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_NE(ERR_IO_PENDING, pending_read_result_);
19552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv >= 0) {
19575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PostOrRunCallback(
19585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
19595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&LogByteTransferEvent, weak_net_log_,
19605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   NetLog::TYPE_SSL_SOCKET_BYTES_RECEIVED, rv,
19615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   scoped_refptr<IOBuffer>(user_read_buf_)));
19622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else if (rv != ERR_IO_PENDING) {
19632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PostOrRunCallback(
19642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FROM_HERE,
19652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&AddLogEventWithCallback, weak_net_log_,
19662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   NetLog::TYPE_SSL_READ_ERROR,
19672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   CreateNetLogSSLErrorCallback(rv, pending_read_nss_error_)));
19682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    pending_read_nss_error_ = 0;
19695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
19715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Core::DoPayloadWrite() {
19745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
19755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1976868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(user_write_buf_.get());
19775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int old_amount_in_read_buffer = memio_GetReadableBufferSize(nss_bufs_);
19795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = PR_Write(nss_fd_, user_write_buf_->data(), user_write_buf_len_);
19802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int new_amount_in_read_buffer = memio_GetReadableBufferSize(nss_bufs_);
19812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // PR_Write could potentially consume the unhandled data in the memio read
19822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // buffer if a renegotiation is in progress. If the buffer is consumed,
19832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // notify the latest buffer size to NetworkRunner.
19842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (old_amount_in_read_buffer != new_amount_in_read_buffer) {
19852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PostOrRunCallback(
19862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FROM_HERE,
19872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&Core::OnNSSBufferUpdated, this, new_amount_in_read_buffer));
19882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
19895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv >= 0) {
19905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PostOrRunCallback(
19915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
19925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&LogByteTransferEvent, weak_net_log_,
19935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   NetLog::TYPE_SSL_SOCKET_BYTES_SENT, rv,
19945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   scoped_refptr<IOBuffer>(user_write_buf_)));
19955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
19965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PRErrorCode prerr = PR_GetError();
19985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (prerr == PR_WOULD_BLOCK_ERROR)
19995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_IO_PENDING;
20005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2001116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  rv = HandleNSSError(prerr);
20025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PostOrRunCallback(
20035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
20045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&AddLogEventWithCallback, weak_net_log_,
20055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 NetLog::TYPE_SSL_WRITE_ERROR,
20065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 CreateNetLogSSLErrorCallback(rv, prerr)));
20075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
20085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
20095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Do as much network I/O as possible between the buffer and the
20115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// transport socket. Return true if some I/O performed, false
20125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// otherwise (error or ERR_IO_PENDING).
20135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketNSS::Core::DoTransportIO() {
20145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
20155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool network_moved = false;
20175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (nss_bufs_ != NULL) {
20185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rv;
20195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Read and write as much data as we can. The loop is neccessary
20205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // because Write() may return synchronously.
20215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    do {
20225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rv = BufferSend();
2023b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      if (rv != ERR_IO_PENDING && rv != 0)
20245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        network_moved = true;
20255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } while (rv > 0);
2026b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if (!transport_recv_eof_ && BufferRecv() != ERR_IO_PENDING)
20275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      network_moved = true;
20285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
20295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return network_moved;
20305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
20315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Core::BufferRecv() {
20335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
20345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (transport_recv_busy_)
20365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_IO_PENDING;
20375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If NSS is blocked on reading from |nss_bufs_|, because it is empty,
20392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // determine how much data NSS wants to read. If NSS was not blocked,
20402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // this will return 0.
20412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int requested = memio_GetReadRequest(nss_bufs_);
20422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (requested == 0) {
20432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // This is not a perfect match of error codes, as no operation is
20442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // actually pending. However, returning 0 would be interpreted as a
20452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // possible sign of EOF, which is also an inappropriate match.
20462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return ERR_IO_PENDING;
20472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
20482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
20495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* buf;
20505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nb = memio_GetReadParams(nss_bufs_, &buf);
20515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv;
20525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!nb) {
20535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // buffer too full to read into, so no I/O possible at moment
20545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = ERR_IO_PENDING;
20555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
20565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<IOBuffer> read_buffer(new IOBuffer(nb));
20575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (OnNetworkTaskRunner()) {
2058868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      rv = DoBufferRecv(read_buffer.get(), nb);
20595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
20605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool posted = network_task_runner_->PostTask(
20615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          FROM_HERE,
20625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Bind(IgnoreResult(&Core::DoBufferRecv), this, read_buffer,
20635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     nb));
20645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rv = posted ? ERR_IO_PENDING : ERR_ABORTED;
20655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
20665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv == ERR_IO_PENDING) {
20685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      transport_recv_busy_ = true;
20695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
20705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (rv > 0) {
20715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        memcpy(buf, read_buffer->data(), rv);
20725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (rv == 0) {
20735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        transport_recv_eof_ = true;
20745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
20755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memio_PutReadResult(nss_bufs_, MapErrorToNSS(rv));
20765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
20775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
20785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
20795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
20805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2081b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// Return 0 if nss_bufs_ was empty,
20825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// > 0 for bytes transferred immediately,
20835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// < 0 for error (or the non-error ERR_IO_PENDING).
20845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Core::BufferSend() {
20855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
20865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (transport_send_busy_)
20885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_IO_PENDING;
20895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* buf1;
20915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* buf2;
20925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int len1, len2;
2093f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (memio_GetWriteParams(nss_bufs_, &buf1, &len1, &buf2, &len2)) {
2094f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // It is important this return synchronously to prevent spinning infinitely
2095f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // in the off-thread NSS case. The error code itself is ignored, so just
2096f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // return ERR_ABORTED. See https://crbug.com/381160.
2097f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return ERR_ABORTED;
2098f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
20995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const unsigned int len = len1 + len2;
21005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = 0;
21025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (len) {
21035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<IOBuffer> send_buffer(new IOBuffer(len));
21045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(send_buffer->data(), buf1, len1);
21055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(send_buffer->data() + len1, buf2, len2);
21065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (OnNetworkTaskRunner()) {
2108868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      rv = DoBufferSend(send_buffer.get(), len);
21095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
21105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool posted = network_task_runner_->PostTask(
21115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          FROM_HERE,
21125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Bind(IgnoreResult(&Core::DoBufferSend), this, send_buffer,
21135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     len));
21145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rv = posted ? ERR_IO_PENDING : ERR_ABORTED;
21155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
21165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv == ERR_IO_PENDING) {
21185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      transport_send_busy_ = true;
21195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
21205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memio_PutWriteResult(nss_bufs_, MapErrorToNSS(rv));
21215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
21225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
21255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
21265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::OnRecvComplete(int result) {
21285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
21295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (next_handshake_state_ == STATE_HANDSHAKE) {
21315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnHandshakeIOComplete(result);
21325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
21335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Network layer received some data, check if client requested to read
21365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // decrypted data.
2137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!user_read_buf_.get())
21385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
21395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = DoReadLoop(result);
21415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != ERR_IO_PENDING)
21425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DoReadCallback(rv);
21435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
21445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::OnSendComplete(int result) {
21465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
21475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (next_handshake_state_ == STATE_HANDSHAKE) {
21495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnHandshakeIOComplete(result);
21505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
21515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // OnSendComplete may need to call DoPayloadRead while the renegotiation
21545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // handshake is in progress.
21555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv_read = ERR_IO_PENDING;
21565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv_write = ERR_IO_PENDING;
21575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool network_moved;
21585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
2159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (user_read_buf_.get())
2160a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      rv_read = DoPayloadRead();
2161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (user_write_buf_.get())
2162a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      rv_write = DoPayloadWrite();
2163a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    network_moved = DoTransportIO();
2164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } while (rv_read == ERR_IO_PENDING && rv_write == ERR_IO_PENDING &&
2165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           (user_read_buf_.get() || user_write_buf_.get()) && network_moved);
21665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2167a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // If the parent SSLClientSocketNSS is deleted during the processing of the
2168a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Read callback and OnNSSTaskRunner() == OnNetworkTaskRunner(), then the Core
2169a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // will be detached (and possibly deleted). Guard against deletion by taking
2170a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // an extra reference, then check if the Core was detached before invoking the
2171a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // next callback.
2172a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  scoped_refptr<Core> guard(this);
2173868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (user_read_buf_.get() && rv_read != ERR_IO_PENDING)
2174a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    DoReadCallback(rv_read);
2175a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
2176a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (OnNetworkTaskRunner() && detached_)
2177a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return;
2178a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
2179868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (user_write_buf_.get() && rv_write != ERR_IO_PENDING)
2180a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    DoWriteCallback(rv_write);
21815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
21825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// As part of Connect(), the SSLClientSocketNSS object performs an SSL
21845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// handshake. This requires network IO, which in turn calls
21855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BufferRecvComplete() with a non-zero byte count. This byte count eventually
21865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// winds its way through the state machine and ends up being passed to the
21875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// callback. For Read() and Write(), that's what we want. But for Connect(),
21885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the caller expects OK (i.e. 0) for success.
21895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::DoConnectCallback(int rv) {
21905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
21915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(rv, ERR_IO_PENDING);
21925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!user_connect_callback_.is_null());
21935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Closure c = base::Bind(
21955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::ResetAndReturn(&user_connect_callback_),
21965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rv > OK ? OK : rv);
21975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PostOrRunCallback(FROM_HERE, c);
21985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
21995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::DoReadCallback(int rv) {
22015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
22025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(ERR_IO_PENDING, rv);
22035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!user_read_callback_.is_null());
22045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_read_buf_ = NULL;
22065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_read_buf_len_ = 0;
22072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int amount_in_read_buffer = memio_GetReadableBufferSize(nss_bufs_);
22082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This is used to curry the |amount_int_read_buffer| and |user_cb| back to
22092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the network task runner.
22102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PostOrRunCallback(
22112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE,
22122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&Core::OnNSSBufferUpdated, this, amount_in_read_buffer));
22132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PostOrRunCallback(
22142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE,
22152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&Core::DidNSSRead, this, rv));
22162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PostOrRunCallback(
22172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE,
22182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(base::ResetAndReturn(&user_read_callback_), rv));
22195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
22205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::DoWriteCallback(int rv) {
22225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
22235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(ERR_IO_PENDING, rv);
22245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!user_write_callback_.is_null());
22255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Since Run may result in Write being called, clear |user_write_callback_|
22275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // up front.
22285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_write_buf_ = NULL;
22295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_write_buf_len_ = 0;
22302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Update buffer status because DoWriteLoop called DoTransportIO which may
22312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // perform read operations.
22322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int amount_in_read_buffer = memio_GetReadableBufferSize(nss_bufs_);
22332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This is used to curry the |amount_int_read_buffer| and |user_cb| back to
22342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the network task runner.
22352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PostOrRunCallback(
22362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE,
22372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&Core::OnNSSBufferUpdated, this, amount_in_read_buffer));
22382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PostOrRunCallback(
22392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE,
22402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&Core::DidNSSWrite, this, rv));
22412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PostOrRunCallback(
22422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE,
22432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(base::ResetAndReturn(&user_write_callback_), rv));
22445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
22455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus SSLClientSocketNSS::Core::ClientChannelIDHandler(
22475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* arg,
22485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRFileDesc* socket,
22495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECKEYPublicKey **out_public_key,
22505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECKEYPrivateKey **out_private_key) {
22515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Core* core = reinterpret_cast<Core*>(arg);
22525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(core->OnNSSTaskRunner());
22535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core->PostOrRunCallback(
22555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
22565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&AddLogEvent, core->weak_net_log_,
22575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 NetLog::TYPE_SSL_CHANNEL_ID_REQUESTED));
22585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We have negotiated the TLS channel ID extension.
22605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core->channel_id_xtn_negotiated_ = true;
2261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string host = core->host_and_port_.host();
22625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int error = ERR_UNEXPECTED;
22635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (core->OnNetworkTaskRunner()) {
22645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    error = core->DoGetChannelID(host);
22655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
22665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool posted = core->network_task_runner_->PostTask(
22675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
22685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(
22695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            IgnoreResult(&Core::DoGetChannelID),
2270bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch            core, host));
22715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error = posted ? ERR_IO_PENDING : ERR_ABORTED;
22725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (error == ERR_IO_PENDING) {
22755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Asynchronous case.
22765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    core->channel_id_needed_ = true;
22775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SECWouldBlock;
22785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core->PostOrRunCallback(
22815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
22825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&BoundNetLog::EndEventWithNetErrorCode, core->weak_net_log_,
22835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 NetLog::TYPE_SSL_GET_DOMAIN_BOUND_CERT, error));
22845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECStatus rv = SECSuccess;
22855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (error == OK) {
22865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Synchronous success.
22875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int result = core->ImportChannelIDKeys(out_public_key, out_private_key);
22885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (result == OK)
22895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      core->SetChannelIDProvided();
22905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
22915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rv = SECFailure;
22925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
22935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = SECFailure;
22945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
22975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
22985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Core::ImportChannelIDKeys(SECKEYPublicKey** public_key,
23005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  SECKEYPrivateKey** key) {
23015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set the certificate.
23025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECItem cert_item;
23035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cert_item.data = (unsigned char*) domain_bound_cert_.data();
23045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cert_item.len = domain_bound_cert_.size();
23055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedCERTCertificate cert(CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
23065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                     &cert_item,
23075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                     NULL,
23085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                     PR_FALSE,
23095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                     PR_TRUE));
23105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cert == NULL)
23115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return MapNSSError(PORT_GetError());
23125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2313f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  crypto::ScopedPK11Slot slot(PK11_GetInternalSlot());
23145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set the private key.
2315bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  if (!crypto::ECPrivateKey::ImportFromEncryptedPrivateKeyInfo(
2316f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          slot.get(),
23175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          ChannelIDService::kEPKIPassword,
23185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          reinterpret_cast<const unsigned char*>(
23195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              domain_bound_private_key_.data()),
23205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          domain_bound_private_key_.size(),
23215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          &cert->subjectPublicKeyInfo,
23225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          false,
23235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          false,
23245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          key,
23255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          public_key)) {
2326bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    int error = MapNSSError(PORT_GetError());
2327bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return error;
23285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
23295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
23315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
23325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::UpdateServerCert() {
23345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nss_handshake_state_.server_cert_chain.Reset(nss_fd_);
23355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nss_handshake_state_.server_cert = X509Certificate::CreateFromDERCertChain(
23365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nss_handshake_state_.server_cert_chain.AsStringPieceVector());
2337868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (nss_handshake_state_.server_cert.get()) {
23385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Since this will be called asynchronously on another thread, it needs to
23395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // own a reference to the certificate.
23405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NetLog::ParametersCallback net_log_callback =
23415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&NetLogX509CertificateCallback,
23425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   nss_handshake_state_.server_cert);
23435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PostOrRunCallback(
23445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
23455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&AddLogEventWithCallback, weak_net_log_,
23465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   NetLog::TYPE_SSL_CERTIFICATES_RECEIVED,
23475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   net_log_callback));
23485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
23495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
23505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2351a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void SSLClientSocketNSS::Core::UpdateSignedCertTimestamps() {
2352a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  const SECItem* signed_cert_timestamps =
2353a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      SSL_PeerSignedCertTimestamps(nss_fd_);
2354a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
2355a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!signed_cert_timestamps || !signed_cert_timestamps->len)
2356a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return;
2357a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
2358a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  nss_handshake_state_.sct_list_from_tls_extension = std::string(
2359a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      reinterpret_cast<char*>(signed_cert_timestamps->data),
2360a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      signed_cert_timestamps->len);
2361a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
2362a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
23635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SSLClientSocketNSS::Core::UpdateStapledOCSPResponse() {
2364a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  PRBool ocsp_requested = PR_FALSE;
2365a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  SSL_OptionGet(nss_fd_, SSL_ENABLE_OCSP_STAPLING, &ocsp_requested);
23665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const SECItemArray* ocsp_responses =
23675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      SSL_PeerStapledOCSPResponses(nss_fd_);
2368a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bool ocsp_responses_present = ocsp_responses && ocsp_responses->len;
2369a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (ocsp_requested)
2370a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    UMA_HISTOGRAM_BOOLEAN("Net.OCSPResponseStapled", ocsp_responses_present);
2371a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!ocsp_responses_present)
23725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
23735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
23745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  nss_handshake_state_.stapled_ocsp_response = std::string(
23755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      reinterpret_cast<char*>(ocsp_responses->items[0].data),
23765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ocsp_responses->items[0].len);
23775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
23785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // TODO(agl): figure out how to plumb an OCSP response into the Mac
23795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // system library and update IsOCSPStaplingSupported for Mac.
23805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (IsOCSPStaplingSupported()) {
23815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  #if defined(OS_WIN)
23825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (nss_handshake_state_.server_cert) {
23835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      CRYPT_DATA_BLOB ocsp_response_blob;
23845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ocsp_response_blob.cbData = ocsp_responses->items[0].len;
23855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ocsp_response_blob.pbData = ocsp_responses->items[0].data;
23865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      BOOL ok = CertSetCertificateContextProperty(
23875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          nss_handshake_state_.server_cert->os_cert_handle(),
23885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          CERT_OCSP_RESPONSE_PROP_ID,
23895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          CERT_SET_PROPERTY_IGNORE_PERSIST_ERROR_FLAG,
23905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          &ocsp_response_blob);
23915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (!ok) {
23925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        VLOG(1) << "Failed to set OCSP response property: "
23935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                << GetLastError();
23945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
23955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
23965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  #elif defined(USE_NSS)
23975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CacheOCSPResponseFromSideChannelFunction cache_ocsp_response =
23985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        GetCacheOCSPResponseFromSideChannelFunction();
23995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
24005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    cache_ocsp_response(
24015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        CERT_GetDefaultCertDB(),
24025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        nss_handshake_state_.server_cert_chain[0], PR_Now(),
24035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        &ocsp_responses->items[0], NULL);
24045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  #endif
24055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }  // IsOCSPStaplingSupported()
24065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
24075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
24085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::UpdateConnectionStatus() {
24095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLChannelInfo channel_info;
24105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECStatus ok = SSL_GetChannelInfo(nss_fd_,
24115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    &channel_info, sizeof(channel_info));
24125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ok == SECSuccess &&
24135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      channel_info.length == sizeof(channel_info) &&
24145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      channel_info.cipherSuite) {
24155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nss_handshake_state_.ssl_connection_status |=
24165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (static_cast<int>(channel_info.cipherSuite) &
24175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         SSL_CONNECTION_CIPHERSUITE_MASK) <<
24185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SSL_CONNECTION_CIPHERSUITE_SHIFT;
24195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nss_handshake_state_.ssl_connection_status |=
24215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (static_cast<int>(channel_info.compressionMethod) &
24225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         SSL_CONNECTION_COMPRESSION_MASK) <<
24235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SSL_CONNECTION_COMPRESSION_SHIFT;
24245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    // NSS 3.14.x doesn't have a version macro for TLS 1.2 (because NSS didn't
2426bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    // support it yet), so use 0x0303 directly.
24275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int version = SSL_CONNECTION_VERSION_UNKNOWN;
24285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (channel_info.protocolVersion < SSL_LIBRARY_VERSION_3_0) {
24295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // All versions less than SSL_LIBRARY_VERSION_3_0 are treated as SSL
24305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // version 2.
24315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      version = SSL_CONNECTION_VERSION_SSL2;
24325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (channel_info.protocolVersion == SSL_LIBRARY_VERSION_3_0) {
24335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      version = SSL_CONNECTION_VERSION_SSL3;
24345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (channel_info.protocolVersion == SSL_LIBRARY_VERSION_3_1_TLS) {
24355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      version = SSL_CONNECTION_VERSION_TLS1;
2436bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    } else if (channel_info.protocolVersion == SSL_LIBRARY_VERSION_TLS_1_1) {
24375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      version = SSL_CONNECTION_VERSION_TLS1_1;
24385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (channel_info.protocolVersion == 0x0303) {
24395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      version = SSL_CONNECTION_VERSION_TLS1_2;
24405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
24415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nss_handshake_state_.ssl_connection_status |=
24425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (version & SSL_CONNECTION_VERSION_MASK) <<
24435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SSL_CONNECTION_VERSION_SHIFT;
24445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
24455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PRBool peer_supports_renego_ext;
24475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ok = SSL_HandshakeNegotiatedExtension(nss_fd_, ssl_renegotiation_info_xtn,
24485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        &peer_supports_renego_ext);
24495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ok == SECSuccess) {
24505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!peer_supports_renego_ext) {
24515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nss_handshake_state_.ssl_connection_status |=
24525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          SSL_CONNECTION_NO_RENEGOTIATION_EXTENSION;
24535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Log an informational message if the server does not support secure
24545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // renegotiation (RFC 5746).
24555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VLOG(1) << "The server " << host_and_port_.ToString()
24565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              << " does not support the TLS renegotiation_info extension.";
24575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
24585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
24595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ssl_config_.version_fallback) {
24615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nss_handshake_state_.ssl_connection_status |=
24625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SSL_CONNECTION_VERSION_FALLBACK;
24635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
24645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
24655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2466eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid SSLClientSocketNSS::Core::UpdateNextProto() {
2467eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  uint8 buf[256];
2468eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SSLNextProtoState state;
2469eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  unsigned buf_len;
2470eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2471eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SECStatus rv = SSL_GetNextProto(nss_fd_, &state, buf, &buf_len, sizeof(buf));
2472eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (rv != SECSuccess)
2473eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
2474eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2475eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  nss_handshake_state_.next_proto =
2476eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      std::string(reinterpret_cast<char*>(buf), buf_len);
2477eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  switch (state) {
2478eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case SSL_NEXT_PROTO_NEGOTIATED:
2479eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case SSL_NEXT_PROTO_SELECTED:
2480eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      nss_handshake_state_.next_proto_status = kNextProtoNegotiated;
2481eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
2482eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case SSL_NEXT_PROTO_NO_OVERLAP:
2483eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      nss_handshake_state_.next_proto_status = kNextProtoNoOverlap;
2484eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
2485eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case SSL_NEXT_PROTO_NO_SUPPORT:
2486eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      nss_handshake_state_.next_proto_status = kNextProtoUnsupported;
2487eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
2488eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    default:
2489eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      NOTREACHED();
2490eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
2491eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
2492eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
2493eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
24941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void SSLClientSocketNSS::Core::RecordChannelIDSupportOnNSSTaskRunner() {
2495b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  DCHECK(OnNSSTaskRunner());
24965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (nss_handshake_state_.resumed_handshake)
24975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
24985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2499b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // Copy the NSS task runner-only state to the network task runner and
2500b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // log histograms from there, since the histograms also need access to the
2501b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // network task runner state.
2502b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  PostOrRunCallback(
2503b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      FROM_HERE,
2504b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      base::Bind(&Core::RecordChannelIDSupportOnNetworkTaskRunner,
2505b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                 this,
2506b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                 channel_id_xtn_negotiated_,
2507b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                 ssl_config_.channel_id_enabled,
2508b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                 crypto::ECPrivateKey::IsSupported()));
2509b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
2510b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
2511b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void SSLClientSocketNSS::Core::RecordChannelIDSupportOnNetworkTaskRunner(
2512b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    bool negotiated_channel_id,
2513b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    bool channel_id_enabled,
2514b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    bool supports_ecc) const {
2515b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  DCHECK(OnNetworkTaskRunner());
2516b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
25175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  RecordChannelIDSupport(channel_id_service_,
25181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                         negotiated_channel_id,
25191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                         channel_id_enabled,
25201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                         supports_ecc);
25215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
25225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Core::DoBufferRecv(IOBuffer* read_buffer, int len) {
25245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNetworkTaskRunner());
25255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GT(len, 0);
25265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (detached_)
25285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_ABORTED;
25295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = transport_->socket()->Read(
25315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      read_buffer, len,
25325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&Core::BufferRecvComplete, base::Unretained(this),
25335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 scoped_refptr<IOBuffer>(read_buffer)));
25345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!OnNSSTaskRunner() && rv != ERR_IO_PENDING) {
25365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nss_task_runner_->PostTask(
25375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE, base::Bind(&Core::BufferRecvComplete, this,
25385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              scoped_refptr<IOBuffer>(read_buffer), rv));
25395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
25405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
25415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
25435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
25445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Core::DoBufferSend(IOBuffer* send_buffer, int len) {
25465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNetworkTaskRunner());
25475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GT(len, 0);
25485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (detached_)
25505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_ABORTED;
25515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = transport_->socket()->Write(
25532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      send_buffer, len,
25542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&Core::BufferSendComplete,
25552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 base::Unretained(this)));
25565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!OnNSSTaskRunner() && rv != ERR_IO_PENDING) {
25585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nss_task_runner_->PostTask(
25595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
25605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&Core::BufferSendComplete, this, rv));
25615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
25625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
25635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
25655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
25665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)int SSLClientSocketNSS::Core::DoGetChannelID(const std::string& host) {
25685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNetworkTaskRunner());
25695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (detached_)
2571116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return ERR_ABORTED;
25725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  weak_net_log_->BeginEvent(NetLog::TYPE_SSL_GET_DOMAIN_BOUND_CERT);
25745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  int rv = channel_id_service_->GetOrCreateChannelID(
2576c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      host,
25775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &domain_bound_private_key_,
25785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &domain_bound_cert_,
25795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      base::Bind(&Core::OnGetChannelIDComplete, base::Unretained(this)),
25805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &domain_bound_cert_request_handle_);
25815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != ERR_IO_PENDING && !OnNSSTaskRunner()) {
25835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nss_task_runner_->PostTask(
25845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
25855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&Core::OnHandshakeIOComplete, this, rv));
25865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_IO_PENDING;
25875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
25885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
25905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
25915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::OnHandshakeStateUpdated(
25935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const HandshakeState& state) {
25942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(OnNetworkTaskRunner());
25955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  network_handshake_state_ = state;
25965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
25975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SSLClientSocketNSS::Core::OnNSSBufferUpdated(int amount_in_read_buffer) {
25992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(OnNetworkTaskRunner());
26002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  unhandled_buffer_size_ = amount_in_read_buffer;
26012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
26022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
26032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SSLClientSocketNSS::Core::DidNSSRead(int result) {
26042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(OnNetworkTaskRunner());
26052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(nss_waiting_read_);
26062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  nss_waiting_read_ = false;
2607effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (result <= 0) {
26082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    nss_is_closed_ = true;
2609effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  } else {
2610effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    was_ever_used_ = true;
2611effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
26122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
26132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
26142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SSLClientSocketNSS::Core::DidNSSWrite(int result) {
26152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(OnNetworkTaskRunner());
26162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(nss_waiting_write_);
26172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  nss_waiting_write_ = false;
2618effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (result < 0) {
26192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    nss_is_closed_ = true;
2620effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  } else if (result > 0) {
2621effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    was_ever_used_ = true;
2622effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
26232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
26242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
26255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::BufferSendComplete(int result) {
26265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!OnNSSTaskRunner()) {
26275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (detached_)
26285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
26295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nss_task_runner_->PostTask(
26315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE, base::Bind(&Core::BufferSendComplete, this, result));
26325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
26335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
26345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
26365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memio_PutWriteResult(nss_bufs_, MapErrorToNSS(result));
26385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transport_send_busy_ = false;
26395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OnSendComplete(result);
26405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
26415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::OnHandshakeIOComplete(int result) {
26435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!OnNSSTaskRunner()) {
26445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (detached_)
26455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
26465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nss_task_runner_->PostTask(
26485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE, base::Bind(&Core::OnHandshakeIOComplete, this, result));
26495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
26505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
26515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
26535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = DoHandshakeLoop(result);
26555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != ERR_IO_PENDING)
26565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DoConnectCallback(rv);
26575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
26585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void SSLClientSocketNSS::Core::OnGetChannelIDComplete(int result) {
26605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << __FUNCTION__ << " " << result;
26615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNetworkTaskRunner());
26625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OnHandshakeIOComplete(result);
26645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
26655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::BufferRecvComplete(
26675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IOBuffer* read_buffer,
26685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int result) {
26695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(read_buffer);
26705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!OnNSSTaskRunner()) {
26725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (detached_)
26735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
26745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nss_task_runner_->PostTask(
26765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE, base::Bind(&Core::BufferRecvComplete, this,
26775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              scoped_refptr<IOBuffer>(read_buffer), result));
26785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
26795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
26805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
26825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result > 0) {
26845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char* buf;
26855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int nb = memio_GetReadParams(nss_bufs_, &buf);
26865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK_GE(nb, result);
26875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(buf, read_buffer->data(), result);
26885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (result == 0) {
26895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    transport_recv_eof_ = true;
26905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
26915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memio_PutReadResult(nss_bufs_, MapErrorToNSS(result));
26935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transport_recv_busy_ = false;
26945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OnRecvComplete(result);
26955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
26965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::PostOrRunCallback(
26985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const tracked_objects::Location& location,
26995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::Closure& task) {
27005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!OnNetworkTaskRunner()) {
27015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    network_task_runner_->PostTask(
27025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
27035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&Core::PostOrRunCallback, this, location, task));
27045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
27055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
27065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (detached_ || task.is_null())
27085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
27095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  task.Run();
27105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
27115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::AddCertProvidedEvent(int cert_count) {
27135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PostOrRunCallback(
27145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
27155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&AddLogEventWithCallback, weak_net_log_,
27165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 NetLog::TYPE_SSL_CLIENT_CERT_PROVIDED,
27175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 NetLog::IntegerCallback("cert_count", cert_count)));
27185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
27195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::SetChannelIDProvided() {
27215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PostOrRunCallback(
27225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE, base::Bind(&AddLogEvent, weak_net_log_,
27235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            NetLog::TYPE_SSL_CHANNEL_ID_PROVIDED));
27245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nss_handshake_state_.channel_id_sent = true;
27255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Update the network task runner's view of the handshake state now that
27265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // channel id has been sent.
27275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PostOrRunCallback(
27285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE, base::Bind(&Core::OnHandshakeStateUpdated, this,
27295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            nss_handshake_state_));
27305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
27315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SSLClientSocketNSS::SSLClientSocketNSS(
27335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::SequencedTaskRunner* nss_task_runner,
27343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_ptr<ClientSocketHandle> transport_socket,
27355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const HostPortPair& host_and_port,
27365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SSLConfig& ssl_config,
27375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SSLClientSocketContext& context)
27385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : nss_task_runner_(nss_task_runner),
27393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      transport_(transport_socket.Pass()),
27405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      host_and_port_(host_and_port),
27415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ssl_config_(ssl_config),
27425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cert_verifier_(context.cert_verifier),
2743a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      cert_transparency_verifier_(context.cert_transparency_verifier),
27445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      channel_id_service_(context.channel_id_service),
27455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ssl_session_cache_shard_(context.ssl_session_cache_shard),
27465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      completed_handshake_(false),
27475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next_handshake_state_(STATE_NONE),
27485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nss_fd_(NULL),
27493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      net_log_(transport_->socket()->NetLog()),
27505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      transport_security_state_(context.transport_security_state),
27515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      valid_thread_id_(base::kInvalidThreadId) {
27525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterFunction("");
27535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InitCore();
27545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LeaveFunction("");
27555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
27565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SSLClientSocketNSS::~SSLClientSocketNSS() {
27585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterFunction("");
27595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Disconnect();
27605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LeaveFunction("");
27615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
27625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
27645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocket::ClearSessionCache() {
27655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SSL_ClearSessionCache can't be called before NSS is initialized.  Don't
27665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // bother initializing NSS just to clear an empty SSL session cache.
27675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!NSS_IsInitialized())
27685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
27695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSL_ClearSessionCache();
27715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
27725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketNSS::GetSSLInfo(SSLInfo* ssl_info) {
27745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterFunction("");
27755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssl_info->Reset();
27765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (core_->state().server_cert_chain.empty() ||
27775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !core_->state().server_cert_chain[0]) {
27785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
27795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
27805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssl_info->cert_status = server_cert_verify_result_.cert_status;
27825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssl_info->cert = server_cert_verify_result_.verified_cert;
2783a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
2784a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  AddSCTInfoToSSLInfo(ssl_info);
2785a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
27865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssl_info->connection_status =
27875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      core_->state().ssl_connection_status;
27885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssl_info->public_key_hashes = server_cert_verify_result_.public_key_hashes;
27895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssl_info->is_issued_by_known_root =
27905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      server_cert_verify_result_.is_issued_by_known_root;
27915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssl_info->client_cert_sent =
2792868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      ssl_config_.send_client_cert && ssl_config_.client_cert.get();
27935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssl_info->channel_id_sent = WasChannelIDSent();
2794c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  ssl_info->pinning_failure_log = pinning_failure_log_;
27955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PRUint16 cipher_suite = SSLConnectionStatusToCipherSuite(
27975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      core_->state().ssl_connection_status);
27985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLCipherSuiteInfo cipher_info;
27995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECStatus ok = SSL_GetCipherSuiteInfo(cipher_suite,
28005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        &cipher_info, sizeof(cipher_info));
28015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ok == SECSuccess) {
28025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ssl_info->security_bits = cipher_info.effectiveKeyBits;
28035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
28045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ssl_info->security_bits = -1;
28055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(DFATAL) << "SSL_GetCipherSuiteInfo returned " << PR_GetError()
28065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                << " for cipherSuite " << cipher_suite;
28075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
28085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssl_info->handshake_type = core_->state().resumed_handshake ?
28105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SSLInfo::HANDSHAKE_RESUME : SSLInfo::HANDSHAKE_FULL;
28115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LeaveFunction("");
28135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
28145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
28155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
281603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)std::string SSLClientSocketNSS::GetSessionCacheKey() const {
281703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  NOTIMPLEMENTED();
281803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  return std::string();
281903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
282003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
28215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool SSLClientSocketNSS::InSessionCache() const {
28225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // For now, always return true so that SSLConnectJobs are never held back.
28235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return true;
28245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
28255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
28265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void SSLClientSocketNSS::SetHandshakeCompletionCallback(
28275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const base::Closure& callback) {
28285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  NOTIMPLEMENTED();
28295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
28305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
28315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::GetSSLCertRequestInfo(
28325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SSLCertRequestInfo* cert_request_info) {
28335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterFunction("");
28345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  cert_request_info->host_and_port = host_and_port_;
28352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  cert_request_info->cert_authorities = core_->state().cert_authorities;
28362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LeaveFunction("");
28375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
28385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::ExportKeyingMaterial(const base::StringPiece& label,
28405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             bool has_context,
28415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             const base::StringPiece& context,
28425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             unsigned char* out,
28435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             unsigned int outlen) {
28445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsConnected())
28455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_SOCKET_NOT_CONNECTED;
28465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SSL_ExportKeyingMaterial may block the current thread if |core_| is in
28485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the midst of a handshake.
28495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECStatus result = SSL_ExportKeyingMaterial(
28505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nss_fd_, label.data(), label.size(), has_context,
28515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reinterpret_cast<const unsigned char*>(context.data()),
28525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context.length(), out, outlen);
28535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != SECSuccess) {
28545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_ExportKeyingMaterial", "");
28555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return MapNSSError(PORT_GetError());
28565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
28575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
28585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
28595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::GetTLSUniqueChannelBinding(std::string* out) {
28615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsConnected())
28625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_SOCKET_NOT_CONNECTED;
28635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned char buf[64];
28645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int len;
28655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECStatus result = SSL_GetChannelBinding(nss_fd_,
28665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           SSL_CHANNEL_BINDING_TLS_UNIQUE,
28675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           buf, &len, arraysize(buf));
28685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != SECSuccess) {
28695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_GetChannelBinding", "");
28705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return MapNSSError(PORT_GetError());
28715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
28725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->assign(reinterpret_cast<char*>(buf), len);
28735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
28745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
28755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SSLClientSocket::NextProtoStatus
28775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)SSLClientSocketNSS::GetNextProto(std::string* proto) {
28785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *proto = core_->state().next_proto;
28795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return core_->state().next_proto_status;
28805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
28815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Connect(const CompletionCallback& callback) {
28835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterFunction("");
28845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(transport_.get());
28857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // It is an error to create an SSLClientSocket whose context has no
28867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // TransportSecurityState.
28877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DCHECK(transport_security_state_);
28885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(STATE_NONE, next_handshake_state_);
28895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(user_connect_callback_.is_null());
28905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!callback.is_null());
28915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnsureThreadIdAssigned();
28935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log_.BeginEvent(NetLog::TYPE_SSL_CONNECT);
28955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = Init();
28975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != OK) {
28985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
28995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
29005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
29015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = InitializeSSLOptions();
29035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != OK) {
29045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
29055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
29065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
29075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = InitializeSSLPeerName();
29095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != OK) {
29105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
29115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
29125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
29135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GotoState(STATE_HANDSHAKE);
29155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = DoHandshakeLoop(OK);
29175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv == ERR_IO_PENDING) {
29185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_connect_callback_ = callback;
29195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
29205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
29215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
29225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LeaveFunction("");
29245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv > OK ? OK : rv;
29255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
29265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Disconnect() {
29285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterFunction("");
29295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(CalledOnValidThread());
29315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Shut down anything that may call us back.
29335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_->Detach();
29345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  verifier_.reset();
29355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transport_->socket()->Disconnect();
29365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Reset object state.
29385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_connect_callback_.Reset();
29395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  server_cert_verify_result_.Reset();
29405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  completed_handshake_   = false;
29415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  start_cert_verification_time_ = base::TimeTicks();
29425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InitCore();
29435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LeaveFunction("");
29455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
29465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketNSS::IsConnected() const {
29485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterFunction("");
29492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool ret = completed_handshake_ &&
29502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             (core_->HasPendingAsyncOperation() ||
29512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              (core_->IsConnected() && core_->HasUnhandledReceivedData()) ||
29522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              transport_->socket()->IsConnected());
29535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LeaveFunction("");
29545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ret;
29555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
29565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketNSS::IsConnectedAndIdle() const {
29585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterFunction("");
29592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool ret = completed_handshake_ &&
29602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             !core_->HasPendingAsyncOperation() &&
29612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             !(core_->IsConnected() && core_->HasUnhandledReceivedData()) &&
29622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             transport_->socket()->IsConnectedAndIdle();
29635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LeaveFunction("");
29645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ret;
29655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
29665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::GetPeerAddress(IPEndPoint* address) const {
29685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return transport_->socket()->GetPeerAddress(address);
29695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
29705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::GetLocalAddress(IPEndPoint* address) const {
29725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return transport_->socket()->GetLocalAddress(address);
29735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
29745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const BoundNetLog& SSLClientSocketNSS::NetLog() const {
29765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return net_log_;
29775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
29785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::SetSubresourceSpeculation() {
29805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (transport_.get() && transport_->socket()) {
29815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    transport_->socket()->SetSubresourceSpeculation();
29825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
29835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
29845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
29855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
29865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::SetOmniboxSpeculation() {
29885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (transport_.get() && transport_->socket()) {
29895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    transport_->socket()->SetOmniboxSpeculation();
29905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
29915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
29925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
29935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
29945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketNSS::WasEverUsed() const {
2996effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK(core_.get());
2997effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
2998effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return core_->WasEverUsed();
29995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
30005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketNSS::UsingTCPFastOpen() const {
30025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (transport_.get() && transport_->socket()) {
30035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return transport_->socket()->UsingTCPFastOpen();
30045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
30055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
30065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
30075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
30085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Read(IOBuffer* buf, int buf_len,
30105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const CompletionCallback& callback) {
3011868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(core_.get());
30125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!callback.is_null());
30135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterFunction(buf_len);
30155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = core_->Read(buf, buf_len, callback);
30165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LeaveFunction(rv);
30175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
30195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
30205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Write(IOBuffer* buf, int buf_len,
30225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              const CompletionCallback& callback) {
3023868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(core_.get());
30245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!callback.is_null());
30255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterFunction(buf_len);
30275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = core_->Write(buf, buf_len, callback);
30285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LeaveFunction(rv);
30295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
30315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
30325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3033c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochint SSLClientSocketNSS::SetReceiveBufferSize(int32 size) {
30345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return transport_->socket()->SetReceiveBufferSize(size);
30355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
30365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3037c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochint SSLClientSocketNSS::SetSendBufferSize(int32 size) {
30385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return transport_->socket()->SetSendBufferSize(size);
30395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
30405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Init() {
30425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterFunction("");
30435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initialize the NSS SSL library in a threadsafe way.  This also
30445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // initializes the NSS base library.
30455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnsureNSSSSLInit();
30465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!NSS_IsInitialized())
30475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNEXPECTED;
30482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(USE_NSS) || defined(OS_IOS)
30495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ssl_config_.cert_io_enabled) {
30505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We must call EnsureNSSHttpIOInit() here, on the IO thread, to get the IO
30515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // loop by MessageLoopForIO::current().
30525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // X509Certificate::Verify() runs on a worker thread of CertVerifier.
30535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EnsureNSSHttpIOInit();
30545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
30555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
30565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LeaveFunction("");
30585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
30595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
30605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::InitCore() {
30627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  core_ = new Core(base::ThreadTaskRunnerHandle::Get().get(),
3063868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                   nss_task_runner_.get(),
3064868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                   transport_.get(),
3065868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                   host_and_port_,
3066868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                   ssl_config_,
3067868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                   &net_log_,
30685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                   channel_id_service_);
30695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
30705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::InitializeSSLOptions() {
30725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Transport connected, now hook it up to nss
30735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nss_fd_ = memio_CreateIOLayer(kRecvBufferSize, kSendBufferSize);
30745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (nss_fd_ == NULL) {
30755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_OUT_OF_MEMORY;  // TODO(port): map NSPR error code.
30765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
30775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Grab pointer to buffers
30795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memio_Private* nss_bufs = memio_GetSecret(nss_fd_);
30805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Create SSL state machine */
30825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Push SSL onto our fake I/O socket */
3083a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (SSL_ImportFD(GetNSSModelSocket(), nss_fd_) == NULL) {
30845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_ImportFD", "");
3085a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    PR_Close(nss_fd_);
3086a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    nss_fd_ = NULL;
30875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_OUT_OF_MEMORY;  // TODO(port): map NSPR/NSS error code.
30885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
30895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(port): set more ssl options!  Check errors!
30905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv;
30925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_OptionSet(nss_fd_, SSL_SECURITY, PR_TRUE);
30945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess) {
30955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_SECURITY");
30965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNEXPECTED;
30975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
30985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SSL2, PR_FALSE);
31005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess) {
31015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_SSL2");
31025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNEXPECTED;
31035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
31045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Don't do V2 compatible hellos because they don't support TLS extensions.
31065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_OptionSet(nss_fd_, SSL_V2_COMPATIBLE_HELLO, PR_FALSE);
31075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess) {
31085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_V2_COMPATIBLE_HELLO");
31095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNEXPECTED;
31105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
31115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLVersionRange version_range;
31135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  version_range.min = ssl_config_.version_min;
31145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  version_range.max = ssl_config_.version_max;
31155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_VersionRangeSet(nss_fd_, &version_range);
31165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess) {
31175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_VersionRangeSet", "");
31185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_NO_SSL_VERSIONS_ENABLED;
31195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
31205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3121a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (ssl_config_.version_fallback) {
3122a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_FALLBACK_SCSV, PR_TRUE);
3123a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (rv != SECSuccess) {
3124a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      LogFailedNSSFunction(
3125a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          net_log_, "SSL_OptionSet", "SSL_ENABLE_FALLBACK_SCSV");
3126a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
3127a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
3128a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
31295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::vector<uint16>::const_iterator it =
31305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           ssl_config_.disabled_cipher_suites.begin();
31315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != ssl_config_.disabled_cipher_suites.end(); ++it) {
31325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This will fail if the specified cipher is not implemented by NSS, but
31335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the failure is harmless.
31345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SSL_CipherPrefSet(nss_fd_, *it, PR_FALSE);
31355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
31365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Support RFC 5077
31385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SESSION_TICKETS, PR_TRUE);
31395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess) {
31405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(
31415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        net_log_, "SSL_OptionSet", "SSL_ENABLE_SESSION_TICKETS");
31425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
31435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_FALSE_START,
31454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                     ssl_config_.false_start_enabled);
31465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess)
31475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_FALSE_START");
31485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We allow servers to request renegotiation. Since we're a client,
31505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // prohibiting this is rather a waste of time. Only servers are in a
31515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // position to prevent renegotiation attacks.
31525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // http://extendedsubset.com/?p=8
31535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_RENEGOTIATION,
31555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     SSL_RENEGOTIATE_TRANSITIONAL);
31565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess) {
31575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(
31585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        net_log_, "SSL_OptionSet", "SSL_ENABLE_RENEGOTIATION");
31595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
31605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  rv = SSL_OptionSet(nss_fd_, SSL_CBC_RANDOM_IV, PR_TRUE);
31625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess)
31635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_CBC_RANDOM_IV");
31645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3165bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// Added in NSS 3.15
31665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SSL_ENABLE_OCSP_STAPLING
31675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Request OCSP stapling even on platforms that don't support it, in
31685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // order to extract Certificate Transparency information.
31695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_OCSP_STAPLING,
31705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     (IsOCSPStaplingSupported() ||
31715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      ssl_config_.signed_cert_timestamps_enabled));
31725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (rv != SECSuccess) {
31735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_OptionSet",
31745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                         "SSL_ENABLE_OCSP_STAPLING");
31755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
31765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
31775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3178a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SIGNED_CERT_TIMESTAMPS,
3179a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                     ssl_config_.signed_cert_timestamps_enabled);
3180a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (rv != SECSuccess) {
3181a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_OptionSet",
3182a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                         "SSL_ENABLE_SIGNED_CERT_TIMESTAMPS");
3183a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
3184a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
31855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_OptionSet(nss_fd_, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE);
31865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess) {
31875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_HANDSHAKE_AS_CLIENT");
31885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNEXPECTED;
31895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
31905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!core_->Init(nss_fd_, nss_bufs))
31925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNEXPECTED;
31935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Tell SSL the hostname we're trying to connect to.
31955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSL_SetURL(nss_fd_, host_and_port_.host().c_str());
31965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Tell SSL we're a client; needed if not letting NSPR do socket I/O
31985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSL_ResetHandshake(nss_fd_, PR_FALSE);
31995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
32015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
32025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::InitializeSSLPeerName() {
32045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Tell NSS who we're connected to
32055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPEndPoint peer_address;
32065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int err = transport_->socket()->GetPeerAddress(&peer_address);
32075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (err != OK)
32085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return err;
32095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SockaddrStorage storage;
32115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!peer_address.ToSockAddr(storage.addr, &storage.addr_len))
3212effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return ERR_ADDRESS_INVALID;
32135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PRNetAddr peername;
32155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&peername, 0, sizeof(peername));
32165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_LE(static_cast<size_t>(storage.addr_len), sizeof(peername));
32175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t len = std::min(static_cast<size_t>(storage.addr_len),
32185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        sizeof(peername));
32195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(&peername, storage.addr, len);
32205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Adjust the address family field for BSD, whose sockaddr
32225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // structure has a one-byte length and one-byte address family
32235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // field at the beginning.  PRNetAddr has a two-byte address
32245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // family field at the beginning.
32255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  peername.raw.family = storage.addr->sa_family;
32265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memio_SetPeerName(nss_fd_, &peername);
32285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set the peer ID for session reuse.  This is necessary when we create an
32305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SSL tunnel through a proxy -- GetPeerName returns the proxy's address
32315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // rather than the destination server's address in that case.
32325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string peer_id = host_and_port_.ToString();
32335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the ssl_session_cache_shard_ is non-empty, we append it to the peer id.
32345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This will cause session cache misses between sockets with different values
32355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // of ssl_session_cache_shard_ and this is used to partition the session cache
32365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // for incognito mode.
32375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ssl_session_cache_shard_.empty()) {
32385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    peer_id += "/" + ssl_session_cache_shard_;
32395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
32405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECStatus rv = SSL_SetSockPeerID(nss_fd_, const_cast<char*>(peer_id.c_str()));
32415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess)
32425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_SetSockPeerID", peer_id.c_str());
32435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
32455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
32465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::DoConnectCallback(int rv) {
32485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterFunction(rv);
32495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(ERR_IO_PENDING, rv);
32505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!user_connect_callback_.is_null());
32515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::ResetAndReturn(&user_connect_callback_).Run(rv > OK ? OK : rv);
32535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LeaveFunction("");
32545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
32555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::OnHandshakeIOComplete(int result) {
32575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterFunction(result);
32585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = DoHandshakeLoop(result);
32595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != ERR_IO_PENDING) {
32605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
32615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DoConnectCallback(rv);
32625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
32635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LeaveFunction("");
32645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
32655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::DoHandshakeLoop(int last_io_result) {
32675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterFunction(last_io_result);
32685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = last_io_result;
32695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
32705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Default to STATE_NONE for next state.
32715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // (This is a quirk carried over from the windows
32725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // implementation.  It makes reading the logs a bit harder.)
32735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // State handlers can and often do call GotoState just
32745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // to stay in the current state.
32755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    State state = next_handshake_state_;
32765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GotoState(STATE_NONE);
32775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (state) {
32785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_HANDSHAKE:
32795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoHandshake();
32805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
32815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_HANDSHAKE_COMPLETE:
32825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoHandshakeComplete(rv);
32835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
32845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_VERIFY_CERT:
32855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK(rv == OK);
32865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoVerifyCert(rv);
32875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
32885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_VERIFY_CERT_COMPLETE:
32895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoVerifyCertComplete(rv);
32905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
32915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_NONE:
32925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
32935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = ERR_UNEXPECTED;
32945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(DFATAL) << "unexpected state " << state;
32955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
32965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
32975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (rv != ERR_IO_PENDING && next_handshake_state_ != STATE_NONE);
32985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LeaveFunction("");
32995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
33005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
33015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::DoHandshake() {
33035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterFunction("");
33045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = core_->Connect(
33055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&SSLClientSocketNSS::OnHandshakeIOComplete,
33065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(this)));
33075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GotoState(STATE_HANDSHAKE_COMPLETE);
33085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LeaveFunction(rv);
33105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
33115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
33125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::DoHandshakeComplete(int result) {
33145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterFunction(result);
33155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == OK) {
33171675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch    if (ssl_config_.version_fallback &&
33181675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch        ssl_config_.version_max < ssl_config_.version_fallback_min) {
33191675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch      return ERR_SSL_FALLBACK_BEYOND_MINIMUM_VERSION;
33201675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch    }
33211675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch
33225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // SSL handshake is completed. Let's verify the certificate.
33232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GotoState(STATE_VERIFY_CERT);
33245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Done!
33255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
33265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set_channel_id_sent(core_->state().channel_id_sent);
3327a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  set_signed_cert_timestamps_received(
3328a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      !core_->state().sct_list_from_tls_extension.empty());
33295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  set_stapled_ocsp_response_received(
33305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      !core_->state().stapled_ocsp_response.empty());
33315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LeaveFunction(result);
33335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
33345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
33355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::DoVerifyCert(int result) {
33375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!core_->state().server_cert_chain.empty());
33385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(core_->state().server_cert_chain[0]);
33395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GotoState(STATE_VERIFY_CERT_COMPLETE);
33415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the certificate is expected to be bad we can use the expectation as
33435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the cert status.
33445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::StringPiece der_cert(
33455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reinterpret_cast<char*>(
33465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          core_->state().server_cert_chain[0]->derCert.data),
33475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      core_->state().server_cert_chain[0]->derCert.len);
33485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CertStatus cert_status;
33495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ssl_config_.IsAllowedBadCert(der_cert, &cert_status)) {
33505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(start_cert_verification_time_.is_null());
33515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "Received an expected bad cert with status: " << cert_status;
33525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_cert_verify_result_.Reset();
33535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_cert_verify_result_.cert_status = cert_status;
33545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_cert_verify_result_.verified_cert = core_->state().server_cert;
33555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
33565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
33575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We may have failed to create X509Certificate object if we are
33595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // running inside sandbox.
3360868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!core_->state().server_cert.get()) {
33615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_cert_verify_result_.Reset();
33625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_cert_verify_result_.cert_status = CERT_STATUS_INVALID;
33635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_CERT_INVALID;
33645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
33655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  start_cert_verification_time_ = base::TimeTicks::Now();
33675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int flags = 0;
33695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ssl_config_.rev_checking_enabled)
33705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    flags |= CertVerifier::VERIFY_REV_CHECKING_ENABLED;
33715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ssl_config_.verify_ev_cert)
33725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    flags |= CertVerifier::VERIFY_EV_CERT;
33735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ssl_config_.cert_io_enabled)
33745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    flags |= CertVerifier::VERIFY_CERT_IO_ENABLED;
3375558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  if (ssl_config_.rev_checking_required_local_anchors)
3376558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    flags |= CertVerifier::VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS;
33775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  verifier_.reset(new SingleRequestCertVerifier(cert_verifier_));
33785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return verifier_->Verify(
3379868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      core_->state().server_cert.get(),
3380868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      host_and_port_.host(),
3381868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      flags,
33827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      SSLConfigService::GetCRLSet().get(),
3383868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      &server_cert_verify_result_,
33845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&SSLClientSocketNSS::OnHandshakeIOComplete,
33855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(this)),
33865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_log_);
33875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
33885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Derived from AuthCertificateCallback() in
33905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// mozilla/source/security/manager/ssl/src/nsNSSCallbacks.cpp.
33915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::DoVerifyCertComplete(int result) {
33925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  verifier_.reset();
33935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!start_cert_verification_time_.is_null()) {
33955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::TimeDelta verify_time =
33965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::TimeTicks::Now() - start_cert_verification_time_;
33975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (result == OK)
33985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        UMA_HISTOGRAM_TIMES("Net.SSLCertVerificationTime", verify_time);
33995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
34005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        UMA_HISTOGRAM_TIMES("Net.SSLCertVerificationTimeError", verify_time);
34015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
34025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We used to remember the intermediate CA certs in the NSS database
34045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // persistently.  However, NSS opens a connection to the SQLite database
34055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // during NSS initialization and doesn't close the connection until NSS
34065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // shuts down.  If the file system where the database resides is gone,
34075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the database connection goes bad.  What's worse, the connection won't
34085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // recover when the file system comes back.  Until this NSS or SQLite bug
34095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is fixed, we need to  avoid using the NSS database for non-essential
34105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // purposes.  See https://bugzilla.mozilla.org/show_bug.cgi?id=508081 and
34115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // http://crbug.com/15630 for more info.
34125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(hclam): Skip logging if server cert was expected to be bad because
34145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |server_cert_verify_result_| doesn't contain all the information about
34155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the cert.
34165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == OK)
34175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogConnectionTypeMetrics();
34185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const CertStatus cert_status = server_cert_verify_result_.cert_status;
3420c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (transport_security_state_ &&
3421c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      (result == OK ||
3422c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       (IsCertificateError(result) && IsCertStatusMinorError(cert_status))) &&
34236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      !transport_security_state_->CheckPublicKeyPins(
34246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          host_and_port_.host(),
34256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          server_cert_verify_result_.is_issued_by_known_root,
34266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          server_cert_verify_result_.public_key_hashes,
34276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          &pinning_failure_log_)) {
34286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    result = ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN;
34295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
34305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3431a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (result == OK) {
3432a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // Only check Certificate Transparency if there were no other errors with
3433a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // the connection.
3434a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    VerifyCT();
34355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
34365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Only cache the session if the certificate verified successfully.
34375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    core_->CacheSessionIfNecessary();
3438a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
3439a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
3440a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  completed_handshake_ = true;
3441a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
34425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Exit DoHandshakeLoop and return the result to the caller to Connect.
34435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(STATE_NONE, next_handshake_state_);
34445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
34455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
34465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3447a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void SSLClientSocketNSS::VerifyCT() {
3448a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!cert_transparency_verifier_)
3449a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return;
3450a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
3451a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Note that this is a completely synchronous operation: The CT Log Verifier
3452a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // gets all the data it needs for SCT verification and does not do any
3453a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // external communication.
3454a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  int result = cert_transparency_verifier_->Verify(
34551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      server_cert_verify_result_.verified_cert.get(),
34565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      core_->state().stapled_ocsp_response,
3457a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      core_->state().sct_list_from_tls_extension,
3458a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      &ct_verify_result_,
3459a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      net_log_);
34605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // TODO(ekasper): wipe stapled_ocsp_response and sct_list_from_tls_extension
34615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // from the state after verification is complete, to conserve memory.
3462a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
3463a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  VLOG(1) << "CT Verification complete: result " << result
3464a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          << " Invalid scts: " << ct_verify_result_.invalid_scts.size()
3465a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          << " Verified scts: " << ct_verify_result_.verified_scts.size()
3466a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          << " scts from unknown logs: "
3467a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          << ct_verify_result_.unknown_logs_scts.size();
3468a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
3469a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
34705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::LogConnectionTypeMetrics() const {
34715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdateConnectionTypeHistograms(CONNECTION_SSL);
34725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ssl_version = SSLConnectionStatusToVersion(
34735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      core_->state().ssl_connection_status);
34745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (ssl_version) {
34755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_CONNECTION_VERSION_SSL2:
34765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UpdateConnectionTypeHistograms(CONNECTION_SSL_SSL2);
34775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
34785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_CONNECTION_VERSION_SSL3:
34795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UpdateConnectionTypeHistograms(CONNECTION_SSL_SSL3);
34805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
34815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_CONNECTION_VERSION_TLS1:
34825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UpdateConnectionTypeHistograms(CONNECTION_SSL_TLS1);
34835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
34845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_CONNECTION_VERSION_TLS1_1:
34855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UpdateConnectionTypeHistograms(CONNECTION_SSL_TLS1_1);
34865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
34875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_CONNECTION_VERSION_TLS1_2:
34885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UpdateConnectionTypeHistograms(CONNECTION_SSL_TLS1_2);
34895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
34905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
34915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
34925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::EnsureThreadIdAssigned() const {
34945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock auto_lock(lock_);
34955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (valid_thread_id_ != base::kInvalidThreadId)
34965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
34975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  valid_thread_id_ = base::PlatformThread::CurrentId();
34985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
34995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketNSS::CalledOnValidThread() const {
35015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnsureThreadIdAssigned();
35025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock auto_lock(lock_);
35035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return valid_thread_id_ == base::PlatformThread::CurrentId();
35045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
35055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3506a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void SSLClientSocketNSS::AddSCTInfoToSSLInfo(SSLInfo* ssl_info) const {
3507a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  for (ct::SCTList::const_iterator iter =
3508a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)       ct_verify_result_.verified_scts.begin();
3509a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)       iter != ct_verify_result_.verified_scts.end(); ++iter) {
3510a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ssl_info->signed_certificate_timestamps.push_back(
3511a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        SignedCertificateTimestampAndStatus(*iter, ct::SCT_STATUS_OK));
3512a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
3513a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  for (ct::SCTList::const_iterator iter =
3514a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)       ct_verify_result_.invalid_scts.begin();
3515a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)       iter != ct_verify_result_.invalid_scts.end(); ++iter) {
3516a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ssl_info->signed_certificate_timestamps.push_back(
3517a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        SignedCertificateTimestampAndStatus(*iter, ct::SCT_STATUS_INVALID));
3518a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
3519a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  for (ct::SCTList::const_iterator iter =
3520a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)       ct_verify_result_.unknown_logs_scts.begin();
3521a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)       iter != ct_verify_result_.unknown_logs_scts.end(); ++iter) {
3522a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ssl_info->signed_certificate_timestamps.push_back(
3523a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        SignedCertificateTimestampAndStatus(*iter,
3524a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                            ct::SCT_STATUS_LOG_UNKNOWN));
3525a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
3526a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
3527a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
3528a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)scoped_refptr<X509Certificate>
3529a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)SSLClientSocketNSS::GetUnverifiedServerCertificateChain() const {
3530a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return core_->state().server_cert.get();
3531a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
3532a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
35335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)ChannelIDService* SSLClientSocketNSS::GetChannelIDService() const {
35345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return channel_id_service_;
35355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
35365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
3538