ssl_client_socket_nss.cc revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
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"
96a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/cert/ct_verifier.h"
97a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/cert/ct_verify_result.h"
98f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "net/cert/scoped_nss_types.h"
99a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/cert/sct_status_flags.h"
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/single_request_cert_verifier.h"
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/x509_certificate_net_log_param.h"
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/x509_util.h"
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/http/transport_security_state.h"
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/ocsp/nss_ocsp.h"
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/client_socket_handle.h"
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/nss_ssl_util.h"
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/ssl_error_params.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)void DestroyCertificates(CERTCertificate** certs, size_t len) {
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < len; i++)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CERT_DestroyCertificate(certs[i]);
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper functions to make it possible to log events from within the
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SSLClientSocketNSS::Core.
280868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void AddLogEvent(const base::WeakPtr<BoundNetLog>& net_log,
281868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                 NetLog::EventType event_type) {
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!net_log)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log->AddEvent(event_type);
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper function to make it possible to log events from within the
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SSLClientSocketNSS::Core.
289868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void AddLogEventWithCallback(const base::WeakPtr<BoundNetLog>& net_log,
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             NetLog::EventType event_type,
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const NetLog::ParametersCallback& callback) {
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!net_log)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log->AddEvent(event_type, callback);
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper function to make it easier to call BoundNetLog::AddByteTransferEvent
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// from within the SSLClientSocketNSS::Core.
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// AddByteTransferEvent expects to receive a const char*, which within the
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Core is backed by an IOBuffer. If the "const char*" is bound via
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// base::Bind and posted to another thread, and the IOBuffer that backs that
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// pointer then goes out of scope on the origin thread, this would result in
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// an invalid read of a stale pointer.
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Instead, provide a signature that accepts an IOBuffer*, so that a reference
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to the owning IOBuffer can be bound to the Callback. This ensures that the
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// IOBuffer will stay alive long enough to cross threads if needed.
307868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void LogByteTransferEvent(
308868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const base::WeakPtr<BoundNetLog>& net_log, NetLog::EventType event_type,
309868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int len, IOBuffer* buffer) {
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!net_log)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log->AddByteTransferEvent(event_type, len, buffer->data());
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// PeerCertificateChain is a helper object which extracts the certificate
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// chain, as given by the server, from an NSS socket and performs the needed
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// resource management. The first element of the chain is the leaf certificate
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and the other elements are in the order given by the server.
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PeerCertificateChain {
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PeerCertificateChain() {}
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PeerCertificateChain(const PeerCertificateChain& other);
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~PeerCertificateChain();
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PeerCertificateChain& operator=(const PeerCertificateChain& other);
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Resets the current chain, freeing any resources, and updates the current
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // chain to be a copy of the chain stored in |nss_fd|.
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If |nss_fd| is NULL, then the current certificate chain will be freed.
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Reset(PRFileDesc* nss_fd);
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns the current certificate chain as a vector of DER-encoded
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // base::StringPieces. The returned vector remains valid until Reset is
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // called.
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<base::StringPiece> AsStringPieceVector() const;
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool empty() const { return certs_.empty(); }
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t size() const { return certs_.size(); }
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CERTCertificate* operator[](size_t index) const {
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_LT(index, certs_.size());
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return certs_[index];
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<CERTCertificate*> certs_;
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PeerCertificateChain::PeerCertificateChain(
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const PeerCertificateChain& other) {
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *this = other;
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PeerCertificateChain::~PeerCertificateChain() {
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Reset(NULL);
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PeerCertificateChain& PeerCertificateChain::operator=(
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const PeerCertificateChain& other) {
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (this == &other)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return *this;
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Reset(NULL);
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  certs_.reserve(other.certs_.size());
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < other.certs_.size(); ++i)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    certs_.push_back(CERT_DupCertificate(other.certs_[i]));
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return *this;
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PeerCertificateChain::Reset(PRFileDesc* nss_fd) {
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < certs_.size(); ++i)
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CERT_DestroyCertificate(certs_[i]);
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  certs_.clear();
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (nss_fd == NULL)
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  CERTCertList* list = SSL_PeerCertificateChain(nss_fd);
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The handshake on |nss_fd| may not have completed.
3804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (list == NULL)
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  for (CERTCertListNode* node = CERT_LIST_HEAD(list);
3844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)       !CERT_LIST_END(node, list); node = CERT_LIST_NEXT(node)) {
3854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    certs_.push_back(CERT_DupCertificate(node->cert));
3864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
3874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  CERT_DestroyCertList(list);
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::vector<base::StringPiece>
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PeerCertificateChain::AsStringPieceVector() const {
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<base::StringPiece> v(certs_.size());
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (unsigned i = 0; i < certs_.size(); i++) {
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v[i] = base::StringPiece(
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        reinterpret_cast<const char*>(certs_[i]->derCert.data),
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        certs_[i]->derCert.len);
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return v;
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// HandshakeState is a helper struct used to pass handshake state between
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the NSS task runner and the network task runner.
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// It contains members that may be read or written on the NSS task runner,
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// but which also need to be read from the network task runner. The NSS task
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// runner will notify the network task runner whenever this state changes, so
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that the network task runner can safely make a copy, which avoids the need
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// for locking.
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct HandshakeState {
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HandshakeState() { Reset(); }
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Reset() {
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_proto_status = SSLClientSocket::kNextProtoUnsupported;
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_proto.clear();
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_protos.clear();
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    channel_id_sent = false;
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_cert_chain.Reset(NULL);
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_cert = NULL;
420a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    sct_list_from_tls_extension.clear();
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    resumed_handshake = false;
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ssl_connection_status = 0;
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set to kNextProtoNegotiated if NPN was successfully negotiated, with the
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // negotiated protocol stored in |next_proto|.
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLClientSocket::NextProtoStatus next_proto_status;
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string next_proto;
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the server supports NPN, the protocols supported by the server.
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string server_protos;
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // True if a channel ID was sent.
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool channel_id_sent;
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // List of DER-encoded X.509 DistinguishedName of certificate authorities
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // allowed by the server.
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<std::string> cert_authorities;
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set when the handshake fully completes.
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The server certificate is first received from NSS as an NSS certificate
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // chain (|server_cert_chain|) and then converted into a platform-specific
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // X509Certificate object (|server_cert|). It's possible for some
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // certificates to be successfully parsed by NSS, and not by the platform
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // libraries (i.e.: when running within a sandbox, different parsing
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // algorithms, etc), so it's not safe to assume that |server_cert| will
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // always be non-NULL.
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PeerCertificateChain server_cert_chain;
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<X509Certificate> server_cert;
450a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // SignedCertificateTimestampList received via TLS extension (RFC 6962).
451a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  std::string sct_list_from_tls_extension;
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // True if the current handshake was the result of TLS session resumption.
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool resumed_handshake;
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The negotiated security parameters (TLS version, cipher, extensions) of
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the SSL connection.
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ssl_connection_status;
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Client-side error mapping functions.
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Map NSS error code to network error code.
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int MapNSSClientError(PRErrorCode err) {
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (err) {
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_ERROR_BAD_CERT_ALERT:
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_ERROR_UNSUPPORTED_CERT_ALERT:
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_ERROR_REVOKED_CERT_ALERT:
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_ERROR_EXPIRED_CERT_ALERT:
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_ERROR_CERTIFICATE_UNKNOWN_ALERT:
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_ERROR_UNKNOWN_CA_ALERT:
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_ERROR_ACCESS_DENIED_ALERT:
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ERR_BAD_SSL_CLIENT_AUTH_CERT;
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return MapNSSError(err);
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Map NSS error code from the first SSL handshake to network error code.
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int MapNSSClientHandshakeError(PRErrorCode err) {
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (err) {
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If the server closed on us, it is a protocol error.
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Some TLS-intolerant servers do this when we request TLS.
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PR_END_OF_FILE_ERROR:
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ERR_SSL_PROTOCOL_ERROR;
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return MapNSSClientError(err);
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SSLClientSocketNSS::Core provides a thread-safe, ref-counted core that is
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// able to marshal data between NSS functions and an underlying transport
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// socket.
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// All public functions are meant to be called from the network task runner,
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and any callbacks supplied will be invoked there as well, provided that
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Detach() has not been called yet.
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Threading within SSLClientSocketNSS and SSLClientSocketNSS::Core:
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Because NSS may block on either hardware or user input during operations
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// such as signing, creating certificates, or locating private keys, the Core
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// handles all of the interactions with the underlying NSS SSL socket, so
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that these blocking calls can be executed on a dedicated task runner.
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note that the network task runner and the NSS task runner may be executing
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// on the same thread. If that happens, then it's more performant to try to
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// complete as much work as possible synchronously, even if it might block,
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// rather than continually PostTask-ing to the same thread.
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Because NSS functions should only be called on the NSS task runner, while
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// I/O resources should only be accessed on the network task runner, most
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// public functions are implemented via three methods, each with different
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// task runner affinities.
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// In the single-threaded mode (where the network and NSS task runners run on
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the same thread), these are all attempted synchronously, while in the
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// multi-threaded mode, message passing is used.
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1) NSS Task Runner: Execute NSS function (DoPayloadRead, DoPayloadWrite,
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    DoHandshake)
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 2) NSS Task Runner: Prepare data to go from NSS to an IO function:
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    (BufferRecv, BufferSend)
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 3) Network Task Runner: Perform IO on that data (DoBufferRecv,
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    DoBufferSend, DoGetDomainBoundCert, OnGetDomainBoundCertComplete)
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 4) Both Task Runners: Callback for asynchronous completion or to marshal
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    data from the network task runner back to NSS (BufferRecvComplete,
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    BufferSendComplete, OnHandshakeIOComplete)
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Single-threaded example
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |--------------------------Network Task Runner--------------------------|
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  SSLClientSocketNSS              Core               (Transport Socket)
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//       Read()
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//         |-------------------------V
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                 Read()
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                   |
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                            DoPayloadRead()
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                   |
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                               BufferRecv()
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                   |
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                              DoBufferRecv()
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                   |-------------------------V
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                                           Read()
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                   V-------------------------|
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                          BufferRecvComplete()
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                   |
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                           PostOrRunCallback()
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//         V-------------------------|
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    (Read Callback)
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Multi-threaded example:
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |--------------------Network Task Runner-------------|--NSS Task Runner--|
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  SSLClientSocketNSS          Core            Socket         Core
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//       Read()
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//         |---------------------V
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                             Read()
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                               |-------------------------------V
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                                             Read()
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                                               |
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                                         DoPayloadRead()
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                                               |
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                                          BufferRecv
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                               V-------------------------------|
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                          DoBufferRecv
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                               |----------------V
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                              Read()
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                               V----------------|
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                        BufferRecvComplete()
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                               |-------------------------------V
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                                      BufferRecvComplete()
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                                               |
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                                       PostOrRunCallback()
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                               V-------------------------------|
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                        PostOrRunCallback()
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//         V---------------------|
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    (Read Callback)
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SSLClientSocketNSS::Core : public base::RefCountedThreadSafe<Core> {
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Creates a new Core.
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Any calls to NSS are executed on the |nss_task_runner|, while any calls
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // that need to operate on the underlying transport, net log, or server
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // bound certificate fetching will happen on the |network_task_runner|, so
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // that their lifetimes match that of the owning SSLClientSocketNSS.
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The caller retains ownership of |transport|, |net_log|, and
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |server_bound_cert_service|, and they will not be accessed once Detach()
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // has been called.
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Core(base::SequencedTaskRunner* network_task_runner,
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       base::SequencedTaskRunner* nss_task_runner,
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ClientSocketHandle* transport,
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       const HostPortPair& host_and_port,
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       const SSLConfig& ssl_config,
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       BoundNetLog* net_log,
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ServerBoundCertService* server_bound_cert_service);
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called on the network task runner.
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Transfers ownership of |socket|, an NSS SSL socket, and |buffers|, the
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // underlying memio implementation, to the Core. Returns true if the Core
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // was successfully registered with the socket.
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool Init(PRFileDesc* socket, memio_Private* buffers);
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called on the network task runner.
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Sets the predicted certificate chain that the peer will send, for use
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // with the TLS CachedInfo extension. If called, it must not be called
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // before Init() or after Connect().
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetPredictedCertificates(
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const std::vector<std::string>& predicted_certificates);
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called on the network task runner.
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Attempts to perform an SSL handshake. If the handshake cannot be
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // completed synchronously, returns ERR_IO_PENDING, invoking |callback| on
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the network task runner once the handshake has completed. Otherwise,
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // returns OK on success or a network error code on failure.
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int Connect(const CompletionCallback& callback);
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called on the network task runner.
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Signals that the resources owned by the network task runner are going
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // away. No further callbacks will be invoked on the network task runner.
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // May be called at any time.
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Detach();
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called on the network task runner.
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns the current state of the underlying SSL socket. May be called at
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // any time.
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HandshakeState& state() const { return network_handshake_state_; }
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called on the network task runner.
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read() and Write() mirror the net::Socket functions of the same name.
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If ERR_IO_PENDING is returned, |callback| will be invoked on the network
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // task runner at a later point, unless the caller calls Detach().
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int Read(IOBuffer* buf, int buf_len, const CompletionCallback& callback);
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int Write(IOBuffer* buf, int buf_len, const CompletionCallback& callback);
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Called on the network task runner.
6472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool IsConnected();
6482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool HasPendingAsyncOperation();
6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool HasUnhandledReceivedData();
6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class base::RefCountedThreadSafe<Core>;
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~Core();
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum State {
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    STATE_NONE,
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    STATE_HANDSHAKE,
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    STATE_GET_DOMAIN_BOUND_CERT_COMPLETE,
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool OnNSSTaskRunner() const;
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool OnNetworkTaskRunner() const;
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////////////////////////////////////////
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Methods that are ONLY called on the NSS task runner:
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////////////////////////////////////////
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called by NSS during full handshakes to allow the application to
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // verify the certificate. Instead of verifying the certificate in the midst
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // of the handshake, SECSuccess is always returned and the peer's certificate
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is verified afterwards.
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This behaviour is an artifact of the original SSLClientSocketWin
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // implementation, which could not verify the peer's certificate until after
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the handshake had completed, as well as bugs in NSS that prevent
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SSL_RestartHandshakeAfterCertReq from working.
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static SECStatus OwnAuthCertHandler(void* arg,
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      PRFileDesc* socket,
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      PRBool checksig,
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      PRBool is_server);
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Callbacks called by NSS when the peer requests client certificate
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // authentication.
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // See the documentation in third_party/nss/ssl/ssl.h for the meanings of
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the arguments.
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(NSS_PLATFORM_CLIENT_AUTH)
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // When NSS has been integrated with awareness of the underlying system
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // cryptographic libraries, this callback allows the caller to supply a
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // native platform certificate and key for use by NSS. At most, one of
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // either (result_certs, result_private_key) or (result_nss_certificate,
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // result_nss_private_key) should be set.
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |arg| contains a pointer to the current SSLClientSocketNSS::Core.
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static SECStatus PlatformClientAuthHandler(
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      void* arg,
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PRFileDesc* socket,
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CERTDistNames* ca_names,
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CERTCertList** result_certs,
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      void** result_private_key,
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CERTCertificate** result_nss_certificate,
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SECKEYPrivateKey** result_nss_private_key);
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static SECStatus ClientAuthHandler(void* arg,
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     PRFileDesc* socket,
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     CERTDistNames* ca_names,
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     CERTCertificate** result_certificate,
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     SECKEYPrivateKey** result_private_key);
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
708f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Called by NSS to determine if we can False Start.
709f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // |arg| contains a pointer to the current SSLClientSocketNSS::Core.
710f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  static SECStatus CanFalseStartCallback(PRFileDesc* socket,
711f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                         void* arg,
712f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                         PRBool* can_false_start);
713f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called by NSS once the handshake has completed.
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |arg| contains a pointer to the current SSLClientSocketNSS::Core.
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void HandshakeCallback(PRFileDesc* socket, void* arg);
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
718f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Called once the handshake has succeeded.
719f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  void HandshakeSucceeded();
720f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Handles an NSS error generated while handshaking or performing IO.
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns a network error code mapped from the original NSS error.
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int HandleNSSError(PRErrorCode error, bool handshake_error);
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int DoHandshakeLoop(int last_io_result);
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int DoReadLoop(int result);
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int DoWriteLoop(int result);
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int DoHandshake();
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int DoGetDBCertComplete(int result);
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int DoPayloadRead();
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int DoPayloadWrite();
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool DoTransportIO();
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int BufferRecv();
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int BufferSend();
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnRecvComplete(int result);
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnSendComplete(int result);
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DoConnectCallback(int result);
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DoReadCallback(int result);
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DoWriteCallback(int result);
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Client channel ID handler.
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static SECStatus ClientChannelIDHandler(
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      void* arg,
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PRFileDesc* socket,
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SECKEYPublicKey **out_public_key,
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SECKEYPrivateKey **out_private_key);
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ImportChannelIDKeys is a helper function for turning a DER-encoded cert and
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // key into a SECKEYPublicKey and SECKEYPrivateKey. Returns OK upon success
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and an error code otherwise.
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Requires |domain_bound_private_key_| and |domain_bound_cert_| to have been
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // set by a call to ServerBoundCertService->GetDomainBoundCert. The caller
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // takes ownership of the |*cert| and |*key|.
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ImportChannelIDKeys(SECKEYPublicKey** public_key, SECKEYPrivateKey** key);
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Updates the NSS and platform specific certificates.
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void UpdateServerCert();
763a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Update the nss_handshake_state_ with SignedCertificateTimestampLists
764a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // received in the handshake, via a TLS extension or (to be implemented)
765a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // OCSP stapling.
766a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  void UpdateSignedCertTimestamps();
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Updates the nss_handshake_state_ with the negotiated security parameters.
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void UpdateConnectionStatus();
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Record histograms for channel id support during full handshakes - resumed
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // handshakes are ignored.
7711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  void RecordChannelIDSupportOnNSSTaskRunner();
772eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // UpdateNextProto gets any application-layer protocol that may have been
773eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // negotiated by the TLS connection.
774eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  void UpdateNextProto();
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////////////////////////////////////////
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Methods that are ONLY called on the network task runner:
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////////////////////////////////////////
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int DoBufferRecv(IOBuffer* buffer, int len);
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int DoBufferSend(IOBuffer* buffer, int len);
781bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  int DoGetDomainBoundCert(const std::string& host);
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnGetDomainBoundCertComplete(int result);
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnHandshakeStateUpdated(const HandshakeState& state);
7852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void OnNSSBufferUpdated(int amount_in_read_buffer);
7862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void DidNSSRead(int result);
7872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void DidNSSWrite(int result);
788b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  void RecordChannelIDSupportOnNetworkTaskRunner(
789b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      bool negotiated_channel_id,
790b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      bool channel_id_enabled,
791b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      bool supports_ecc) const;
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////////////////////////////////////////
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Methods that are called on both the network task runner and the NSS
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // task runner.
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////////////////////////////////////////
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnHandshakeIOComplete(int result);
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void BufferRecvComplete(IOBuffer* buffer, int result);
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void BufferSendComplete(int result);
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // PostOrRunCallback is a helper function to ensure that |callback| is
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // invoked on the network task runner, but only if Detach() has not yet
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // been called.
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void PostOrRunCallback(const tracked_objects::Location& location,
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         const base::Closure& callback);
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Uses PostOrRunCallback and |weak_net_log_| to try and log a
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SSL_CLIENT_CERT_PROVIDED event, with the indicated count.
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AddCertProvidedEvent(int cert_count);
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Sets the handshake state |channel_id_sent| flag and logs the
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SSL_CHANNEL_ID_PROVIDED event.
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetChannelIDProvided();
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////////////////////////////////////////
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Members that are ONLY accessed on the network task runner:
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////////////////////////////////////////
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // True if the owning SSLClientSocketNSS has called Detach(). No further
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // callbacks will be invoked nor access to members owned by the network
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // task runner.
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool detached_;
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The underlying transport to use for network IO.
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClientSocketHandle* transport_;
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WeakPtrFactory<BoundNetLog> weak_net_log_factory_;
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The current handshake state. Mirrors |nss_handshake_state_|.
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HandshakeState network_handshake_state_;
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The service for retrieving Channel ID keys.  May be NULL.
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ServerBoundCertService* server_bound_cert_service_;
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ServerBoundCertService::RequestHandle domain_bound_cert_request_handle_;
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The information about NSS task runner.
8362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int unhandled_buffer_size_;
8372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool nss_waiting_read_;
8382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool nss_waiting_write_;
8392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool nss_is_closed_;
8402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////////////////////////////////////////
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Members that are ONLY accessed on the NSS task runner:
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////////////////////////////////////////
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HostPortPair host_and_port_;
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLConfig ssl_config_;
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NSS SSL socket.
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PRFileDesc* nss_fd_;
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Buffers for the network end of the SSL state machine
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memio_Private* nss_bufs_;
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Used by DoPayloadRead() when attempting to fill the caller's buffer with
8542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // as much data as possible, without blocking.
8552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If DoPayloadRead() encounters an error after having read some data, stores
8562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the results to return on the *next* call to DoPayloadRead(). A value of
8572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // kNoPendingReadResult indicates there is no pending result, otherwise 0
8582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // indicates EOF and < 0 indicates an error.
8592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int pending_read_result_;
8602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Contains the previously observed NSS error. Only valid when
8612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // pending_read_result_ != kNoPendingReadResult.
8622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PRErrorCode pending_read_nss_error_;
8632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The certificate chain, in DER form, that is expected to be received from
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the server.
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> predicted_certs_;
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  State next_handshake_state_;
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // True if channel ID extension was negotiated.
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool channel_id_xtn_negotiated_;
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // True if the handshake state machine was interrupted for channel ID.
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool channel_id_needed_;
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // True if the handshake state machine was interrupted for client auth.
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool client_auth_cert_needed_;
876f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // True if NSS has False Started.
877f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  bool false_started_;
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // True if NSS has called HandshakeCallback.
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool handshake_callback_called_;
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HandshakeState nss_handshake_state_;
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool transport_recv_busy_;
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool transport_recv_eof_;
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool transport_send_busy_;
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Used by Read function.
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<IOBuffer> user_read_buf_;
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int user_read_buf_len_;
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Used by Write function.
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<IOBuffer> user_write_buf_;
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int user_write_buf_len_;
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CompletionCallback user_connect_callback_;
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CompletionCallback user_read_callback_;
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CompletionCallback user_write_callback_;
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////////////////////////////////////////
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Members that are accessed on both the network task runner and the NSS
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // task runner.
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////////////////////////////////////////
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<base::SequencedTaskRunner> network_task_runner_;
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<base::SequencedTaskRunner> nss_task_runner_;
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Dereferenced only on the network task runner, but bound to tasks destined
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // for the network task runner from the NSS task runner.
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WeakPtr<BoundNetLog> weak_net_log_;
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Written on the network task runner by the |server_bound_cert_service_|,
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // prior to invoking OnHandshakeIOComplete.
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read on the NSS task runner when once OnHandshakeIOComplete is invoked
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // on the NSS task runner.
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string domain_bound_private_key_;
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string domain_bound_cert_;
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(Core);
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SSLClientSocketNSS::Core::Core(
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::SequencedTaskRunner* network_task_runner,
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::SequencedTaskRunner* nss_task_runner,
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ClientSocketHandle* transport,
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const HostPortPair& host_and_port,
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SSLConfig& ssl_config,
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BoundNetLog* net_log,
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ServerBoundCertService* server_bound_cert_service)
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : detached_(false),
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      transport_(transport),
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      weak_net_log_factory_(net_log),
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      server_bound_cert_service_(server_bound_cert_service),
9322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      unhandled_buffer_size_(0),
9332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      nss_waiting_read_(false),
9342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      nss_waiting_write_(false),
9352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      nss_is_closed_(false),
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      host_and_port_(host_and_port),
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ssl_config_(ssl_config),
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nss_fd_(NULL),
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nss_bufs_(NULL),
9402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      pending_read_result_(kNoPendingReadResult),
9412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      pending_read_nss_error_(0),
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next_handshake_state_(STATE_NONE),
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      channel_id_xtn_negotiated_(false),
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      channel_id_needed_(false),
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      client_auth_cert_needed_(false),
946f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      false_started_(false),
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      handshake_callback_called_(false),
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      transport_recv_busy_(false),
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      transport_recv_eof_(false),
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      transport_send_busy_(false),
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      user_read_buf_len_(0),
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      user_write_buf_len_(0),
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      network_task_runner_(network_task_runner),
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nss_task_runner_(nss_task_runner),
955bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      weak_net_log_(weak_net_log_factory_.GetWeakPtr()) {
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SSLClientSocketNSS::Core::~Core() {
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(wtc): Send SSL close_notify alert.
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (nss_fd_ != NULL) {
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PR_Close(nss_fd_);
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nss_fd_ = NULL;
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketNSS::Core::Init(PRFileDesc* socket,
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    memio_Private* buffers) {
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNetworkTaskRunner());
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!nss_fd_);
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!nss_bufs_);
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nss_fd_ = socket;
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nss_bufs_ = buffers;
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECStatus rv = SECSuccess;
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ssl_config_.next_protos.empty()) {
978eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    size_t wire_length = 0;
979eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    for (std::vector<std::string>::const_iterator
980eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch         i = ssl_config_.next_protos.begin();
981eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch         i != ssl_config_.next_protos.end(); ++i) {
982eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if (i->size() > 255) {
983eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        LOG(WARNING) << "Ignoring overlong NPN/ALPN protocol: " << *i;
984eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        continue;
985eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      }
986eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      wire_length += i->size();
987eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      wire_length++;
988eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
989eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_ptr<uint8[]> wire_protos(new uint8[wire_length]);
990eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    uint8* dst = wire_protos.get();
991eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    for (std::vector<std::string>::const_iterator
992eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch         i = ssl_config_.next_protos.begin();
993eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch         i != ssl_config_.next_protos.end(); i++) {
994eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if (i->size() > 255)
995eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        continue;
996eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      *dst++ = i->size();
997eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      memcpy(dst, i->data(), i->size());
998eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      dst += i->size();
999eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
1000eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    DCHECK_EQ(dst, wire_protos.get() + wire_length);
1001eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    rv = SSL_SetNextProtoNego(nss_fd_, wire_protos.get(), wire_length);
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv != SECSuccess)
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LogFailedNSSFunction(*weak_net_log_, "SSL_SetNextProtoCallback", "");
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_AuthCertificateHook(
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nss_fd_, SSLClientSocketNSS::Core::OwnAuthCertHandler, this);
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess) {
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(*weak_net_log_, "SSL_AuthCertificateHook", "");
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(NSS_PLATFORM_CLIENT_AUTH)
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_GetPlatformClientAuthDataHook(
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nss_fd_, SSLClientSocketNSS::Core::PlatformClientAuthHandler,
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this);
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_GetClientAuthDataHook(
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nss_fd_, SSLClientSocketNSS::Core::ClientAuthHandler, this);
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess) {
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(*weak_net_log_, "SSL_GetClientAuthDataHook", "");
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (IsChannelIDEnabled(ssl_config_, server_bound_cert_service_)) {
10271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    rv = SSL_SetClientChannelIDCallback(
10281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        nss_fd_, SSLClientSocketNSS::Core::ClientChannelIDHandler, this);
10291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (rv != SECSuccess) {
10301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      LogFailedNSSFunction(
10311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          *weak_net_log_, "SSL_SetClientChannelIDCallback", "");
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  rv = SSL_SetCanFalseStartCallback(
1036f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      nss_fd_, SSLClientSocketNSS::Core::CanFalseStartCallback, this);
1037f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (rv != SECSuccess) {
1038f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    LogFailedNSSFunction(*weak_net_log_, "SSL_SetCanFalseStartCallback", "");
1039f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return false;
1040f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
1041f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_HandshakeCallback(
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nss_fd_, SSLClientSocketNSS::Core::HandshakeCallback, this);
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess) {
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(*weak_net_log_, "SSL_HandshakeCallback", "");
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::SetPredictedCertificates(
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<std::string>& predicted_certs) {
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (predicted_certs.empty())
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!OnNSSTaskRunner()) {
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!detached_);
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nss_task_runner_->PostTask(
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&Core::SetPredictedCertificates, this, predicted_certs));
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(nss_fd_);
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  predicted_certs_ = predicted_certs;
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1069c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<CERTCertificate*[]> certs(
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new CERTCertificate*[predicted_certs.size()]);
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < predicted_certs.size(); i++) {
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECItem derCert;
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    derCert.data = const_cast<uint8*>(reinterpret_cast<const uint8*>(
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        predicted_certs[i].data()));
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    derCert.len = predicted_certs[i].size();
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    certs[i] = CERT_NewTempCertificate(
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CERT_GetDefaultCertDB(), &derCert, NULL /* no nickname given */,
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        PR_FALSE /* not permanent */, PR_TRUE /* copy DER data */);
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!certs[i]) {
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DestroyCertificates(&certs[0], i);
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECStatus rv;
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SSL_ENABLE_CACHED_INFO
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_SetPredictedPeerCertificates(nss_fd_, certs.get(),
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        predicted_certs.size());
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(SECSuccess, rv);
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SECFailure;  // Not implemented.
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DestroyCertificates(&certs[0], predicted_certs.size());
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess) {
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "SetPredictedCertificates failed: "
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << host_and_port_.ToString();
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Core::Connect(const CompletionCallback& callback) {
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!OnNSSTaskRunner()) {
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!detached_);
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool posted = nss_task_runner_->PostTask(
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(IgnoreResult(&Core::Connect), this, callback));
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return posted ? ERR_IO_PENDING : ERR_ABORTED;
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(STATE_NONE, next_handshake_state_);
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(user_read_callback_.is_null());
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(user_write_callback_.is_null());
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(user_connect_callback_.is_null());
1117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!user_read_buf_.get());
1118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!user_write_buf_.get());
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_handshake_state_ = STATE_HANDSHAKE;
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = DoHandshakeLoop(OK);
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv == ERR_IO_PENDING) {
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_connect_callback_ = callback;
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (rv > OK) {
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = OK;
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != ERR_IO_PENDING && !OnNetworkTaskRunner()) {
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PostOrRunCallback(FROM_HERE, base::Bind(callback, rv));
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_IO_PENDING;
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::Detach() {
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNetworkTaskRunner());
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  detached_ = true;
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transport_ = NULL;
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  weak_net_log_factory_.InvalidateWeakPtrs();
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  network_handshake_state_.Reset();
11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  domain_bound_cert_request_handle_.Cancel();
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Core::Read(IOBuffer* buf, int buf_len,
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   const CompletionCallback& callback) {
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!OnNSSTaskRunner()) {
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(OnNetworkTaskRunner());
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!detached_);
11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(transport_);
11532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(!nss_waiting_read_);
11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    nss_waiting_read_ = true;
11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool posted = nss_task_runner_->PostTask(
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(IgnoreResult(&Core::Read), this, make_scoped_refptr(buf),
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   buf_len, callback));
11602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!posted) {
11612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      nss_is_closed_ = true;
11622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      nss_waiting_read_ = false;
11632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return posted ? ERR_IO_PENDING : ERR_ABORTED;
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
1168f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(false_started_ || handshake_callback_called_);
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(STATE_NONE, next_handshake_state_);
11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(user_read_callback_.is_null());
11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(user_connect_callback_.is_null());
1172868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!user_read_buf_.get());
11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(nss_bufs_);
11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_read_buf_ = buf;
11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_read_buf_len_ = buf_len;
11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = DoReadLoop(OK);
11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv == ERR_IO_PENDING) {
11802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (OnNetworkTaskRunner())
11812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      nss_waiting_read_ = true;
11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_read_callback_ = callback;
11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_read_buf_ = NULL;
11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_read_buf_len_ = 0;
11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!OnNetworkTaskRunner()) {
11882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      PostOrRunCallback(FROM_HERE, base::Bind(&Core::DidNSSRead, this, rv));
11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PostOrRunCallback(FROM_HERE, base::Bind(callback, rv));
11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ERR_IO_PENDING;
11912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
11922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DCHECK(!nss_waiting_read_);
11932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (rv <= 0)
11942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        nss_is_closed_ = true;
11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Core::Write(IOBuffer* buf, int buf_len,
12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    const CompletionCallback& callback) {
12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!OnNSSTaskRunner()) {
12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(OnNetworkTaskRunner());
12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!detached_);
12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(transport_);
12072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(!nss_waiting_write_);
12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    nss_waiting_write_ = true;
12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool posted = nss_task_runner_->PostTask(
12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(IgnoreResult(&Core::Write), this, make_scoped_refptr(buf),
12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   buf_len, callback));
12142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!posted) {
12152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      nss_is_closed_ = true;
12162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      nss_waiting_write_ = false;
12172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
12182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return posted ? ERR_IO_PENDING : ERR_ABORTED;
12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
1222f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(false_started_ || handshake_callback_called_);
12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(STATE_NONE, next_handshake_state_);
12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(user_write_callback_.is_null());
12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(user_connect_callback_.is_null());
1226868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!user_write_buf_.get());
12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(nss_bufs_);
12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_write_buf_ = buf;
12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_write_buf_len_ = buf_len;
12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = DoWriteLoop(OK);
12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv == ERR_IO_PENDING) {
12342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (OnNetworkTaskRunner())
12352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      nss_waiting_write_ = true;
12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_write_callback_ = callback;
12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_write_buf_ = NULL;
12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_write_buf_len_ = 0;
12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!OnNetworkTaskRunner()) {
12422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      PostOrRunCallback(FROM_HERE, base::Bind(&Core::DidNSSWrite, this, rv));
12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PostOrRunCallback(FROM_HERE, base::Bind(callback, rv));
12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ERR_IO_PENDING;
12452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
12462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DCHECK(!nss_waiting_write_);
12472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (rv < 0)
12482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        nss_is_closed_ = true;
12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SSLClientSocketNSS::Core::IsConnected() {
12562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(OnNetworkTaskRunner());
12572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return !nss_is_closed_;
12582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
12592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SSLClientSocketNSS::Core::HasPendingAsyncOperation() {
12612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(OnNetworkTaskRunner());
12622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return nss_waiting_read_ || nss_waiting_write_;
12632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
12642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SSLClientSocketNSS::Core::HasUnhandledReceivedData() {
12662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(OnNetworkTaskRunner());
12672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return unhandled_buffer_size_ != 0;
12682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
12692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketNSS::Core::OnNSSTaskRunner() const {
12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return nss_task_runner_->RunsTasksOnCurrentThread();
12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketNSS::Core::OnNetworkTaskRunner() const {
12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return network_task_runner_->RunsTasksOnCurrentThread();
12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus SSLClientSocketNSS::Core::OwnAuthCertHandler(
12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* arg,
12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRFileDesc* socket,
12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRBool checksig,
12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRBool is_server) {
12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Core* core = reinterpret_cast<Core*>(arg);
1285f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (core->handshake_callback_called_) {
12868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // Disallow the server certificate to change in a renegotiation.
12878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    CERTCertificate* old_cert = core->nss_handshake_state_.server_cert_chain[0];
1288f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    ScopedCERTCertificate new_cert(SSL_PeerCertificate(socket));
12898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (new_cert->derCert.len != old_cert->derCert.len ||
12908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        memcmp(new_cert->derCert.data, old_cert->derCert.data,
12918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)               new_cert->derCert.len) != 0) {
12928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      // NSS doesn't have an error code that indicates the server certificate
12938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      // changed. Borrow SSL_ERROR_WRONG_CERTIFICATE (which NSS isn't using)
12948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      // for this purpose.
12958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      PORT_SetError(SSL_ERROR_WRONG_CERTIFICATE);
12968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      return SECFailure;
12978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Tell NSS to not verify the certificate.
13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SECSuccess;
13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(NSS_PLATFORM_CLIENT_AUTH)
13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus SSLClientSocketNSS::Core::PlatformClientAuthHandler(
13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* arg,
13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRFileDesc* socket,
13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CERTDistNames* ca_names,
13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CERTCertList** result_certs,
13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void** result_private_key,
13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CERTCertificate** result_nss_certificate,
13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECKEYPrivateKey** result_nss_private_key) {
13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Core* core = reinterpret_cast<Core*>(arg);
13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(core->OnNSSTaskRunner());
13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core->PostOrRunCallback(
13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&AddLogEvent, core->weak_net_log_,
13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 NetLog::TYPE_SSL_CLIENT_CERT_REQUESTED));
13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core->client_auth_cert_needed_ = !core->ssl_config_.send_client_cert;
13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (core->ssl_config_.send_client_cert) {
13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (core->ssl_config_.client_cert) {
13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PCCERT_CONTEXT cert_context =
13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          core->ssl_config_.client_cert->os_cert_handle();
13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HCRYPTPROV_OR_NCRYPT_KEY_HANDLE crypt_prov = 0;
13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DWORD key_spec = 0;
13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BOOL must_free = FALSE;
133290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      DWORD flags = 0;
133390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (base::win::GetVersion() >= base::win::VERSION_VISTA)
1334868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        flags |= CRYPT_ACQUIRE_PREFER_NCRYPT_KEY_FLAG;
133590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BOOL acquired_key = CryptAcquireCertificatePrivateKey(
133790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          cert_context, flags, NULL, &crypt_prov, &key_spec, &must_free);
13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (acquired_key) {
134090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        // Should never get a cached handle back - ownership must always be
134190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        // transferred.
134290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        CHECK_EQ(must_free, TRUE);
13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SECItem der_cert;
13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        der_cert.type = siDERCertBuffer;
13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        der_cert.data = cert_context->pbCertEncoded;
13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        der_cert.len  = cert_context->cbCertEncoded;
13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // TODO(rsleevi): Error checking for NSS allocation errors.
13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CERTCertDBHandle* db_handle = CERT_GetDefaultCertDB();
13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CERTCertificate* user_cert = CERT_NewTempCertificate(
13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            db_handle, &der_cert, NULL, PR_FALSE, PR_TRUE);
13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!user_cert) {
13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // Importing the certificate can fail for reasons including a serial
13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // number collision. See crbug.com/97355.
13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          core->AddCertProvidedEvent(0);
13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return SECFailure;
13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CERTCertList* cert_chain = CERT_NewCertList();
13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CERT_AddCertToListTail(cert_chain, user_cert);
13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Add the intermediates.
13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        X509Certificate::OSCertHandles intermediates =
13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            core->ssl_config_.client_cert->GetIntermediateCertificates();
13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (X509Certificate::OSCertHandles::const_iterator it =
13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            intermediates.begin(); it != intermediates.end(); ++it) {
13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          der_cert.data = (*it)->pbCertEncoded;
13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          der_cert.len = (*it)->cbCertEncoded;
13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          CERTCertificate* intermediate = CERT_NewTempCertificate(
13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              db_handle, &der_cert, NULL, PR_FALSE, PR_TRUE);
13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (!intermediate) {
13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            CERT_DestroyCertList(cert_chain);
13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            core->AddCertProvidedEvent(0);
13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return SECFailure;
13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          CERT_AddCertToListTail(cert_chain, intermediate);
13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        PCERT_KEY_CONTEXT key_context = reinterpret_cast<PCERT_KEY_CONTEXT>(
13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            PORT_ZAlloc(sizeof(CERT_KEY_CONTEXT)));
13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        key_context->cbSize = sizeof(*key_context);
138290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        // NSS will free this context when no longer in use.
13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        key_context->hCryptProv = crypt_prov;
13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        key_context->dwKeySpec = key_spec;
13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *result_private_key = key_context;
13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *result_certs = cert_chain;
13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int cert_count = 1 + intermediates.size();
13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        core->AddCertProvidedEvent(cert_count);
13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return SECSuccess;
13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(WARNING) << "Client cert found without private key";
13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Send no client certificate.
13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    core->AddCertProvidedEvent(0);
13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SECFailure;
13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  core->nss_handshake_state_.cert_authorities.clear();
14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<CERT_NAME_BLOB> issuer_list(ca_names->nnames);
14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < ca_names->nnames; ++i) {
14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    issuer_list[i].cbData = ca_names->names[i].len;
14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    issuer_list[i].pbData = ca_names->names[i].data;
14062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    core->nss_handshake_state_.cert_authorities.push_back(std::string(
14072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        reinterpret_cast<const char*>(ca_names->names[i].data),
14082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        static_cast<size_t>(ca_names->names[i].len)));
14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Update the network task runner's view of the handshake state now that
14122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // server certificate request has been recorded.
14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core->PostOrRunCallback(
14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE, base::Bind(&Core::OnHandshakeStateUpdated, core,
14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            core->nss_handshake_state_));
14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Tell NSS to suspend the client authentication.  We will then abort the
14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // handshake by returning ERR_SSL_CLIENT_AUTH_CERT_NEEDED.
14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SECWouldBlock;
14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_MACOSX)
14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (core->ssl_config_.send_client_cert) {
14227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (core->ssl_config_.client_cert.get()) {
14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OSStatus os_error = noErr;
14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SecIdentityRef identity = NULL;
14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SecKeyRef private_key = NULL;
1426c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      X509Certificate::OSCertHandles chain;
1427c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      {
1428c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        base::AutoLock lock(crypto::GetMacSecurityServicesLock());
1429c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        os_error = SecIdentityCreateWithCertificate(
1430c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            NULL, core->ssl_config_.client_cert->os_cert_handle(), &identity);
14315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1432c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (os_error == noErr) {
14335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        os_error = SecIdentityCopyPrivateKey(identity, &private_key);
1434c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        CFRelease(identity);
1435c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
14365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1437c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (os_error == noErr) {
14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // TODO(rsleevi): Error checking for NSS allocation errors.
14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *result_certs = CERT_NewCertList();
14405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *result_private_key = private_key;
14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1442c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        chain.push_back(core->ssl_config_.client_cert->os_cert_handle());
1443c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        const X509Certificate::OSCertHandles& intermediates =
1444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            core->ssl_config_.client_cert->GetIntermediateCertificates();
1445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (!intermediates.empty())
1446c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          chain.insert(chain.end(), intermediates.begin(), intermediates.end());
1447c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1448c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        for (size_t i = 0, chain_count = chain.size(); i < chain_count; ++i) {
14495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          CSSM_DATA cert_data;
1450c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          SecCertificateRef cert_ref = chain[i];
14515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          os_error = SecCertificateGetData(cert_ref, &cert_data);
14525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (os_error != noErr)
14535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
14545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          SECItem der_cert;
14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          der_cert.type = siDERCertBuffer;
14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          der_cert.data = cert_data.Data;
14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          der_cert.len = cert_data.Length;
14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          CERTCertificate* nss_cert = CERT_NewTempCertificate(
14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              CERT_GetDefaultCertDB(), &der_cert, NULL, PR_FALSE, PR_TRUE);
14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (!nss_cert) {
1462c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            // In the event of an NSS error, make up an OS error and reuse
1463c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            // the error handling below.
14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            os_error = errSecCreateChainFailed;
14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
14665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          CERT_AddCertToListTail(*result_certs, nss_cert);
14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
14695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1470c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (os_error == noErr) {
1472c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        core->AddCertProvidedEvent(chain.size());
14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return SECSuccess;
14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1475c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OSSTATUS_LOG(WARNING, os_error)
14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << "Client cert found, but could not be used";
14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (*result_certs) {
14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CERT_DestroyCertList(*result_certs);
14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *result_certs = NULL;
14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (*result_private_key)
14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *result_private_key = NULL;
14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (private_key)
14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CFRelease(private_key);
14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Send no client certificate.
14895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    core->AddCertProvidedEvent(0);
14905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SECFailure;
14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  core->nss_handshake_state_.cert_authorities.clear();
14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Retrieve the cert issuers accepted by the server.
14965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<CertPrincipal> valid_issuers;
14975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int n = ca_names->nnames;
14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < n; i++) {
14992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    core->nss_handshake_state_.cert_authorities.push_back(std::string(
15002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        reinterpret_cast<const char*>(ca_names->names[i].data),
15012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        static_cast<size_t>(ca_names->names[i].len)));
15025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Update the network task runner's view of the handshake state now that
15052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // server certificate request has been recorded.
15065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core->PostOrRunCallback(
15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE, base::Bind(&Core::OnHandshakeStateUpdated, core,
15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            core->nss_handshake_state_));
15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Tell NSS to suspend the client authentication.  We will then abort the
15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // handshake by returning ERR_SSL_CLIENT_AUTH_CERT_NEEDED.
15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SECWouldBlock;
15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SECFailure;
15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
15165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_IOS)
15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus SSLClientSocketNSS::Core::ClientAuthHandler(
15215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* arg,
15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRFileDesc* socket,
15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CERTDistNames* ca_names,
15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CERTCertificate** result_certificate,
15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECKEYPrivateKey** result_private_key) {
15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Core* core = reinterpret_cast<Core*>(arg);
15275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(core->OnNSSTaskRunner());
15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core->PostOrRunCallback(
15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
15315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&AddLogEvent, core->weak_net_log_,
15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 NetLog::TYPE_SSL_CLIENT_CERT_REQUESTED));
15335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(droger): Support client auth on iOS. See http://crbug.com/145954).
15355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG(WARNING) << "Client auth is not supported";
15365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Never send a certificate.
15385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core->AddCertProvidedEvent(0);
15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SECFailure;
15405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else  // NSS_PLATFORM_CLIENT_AUTH
15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Based on Mozilla's NSS_GetClientAuthData.
15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus SSLClientSocketNSS::Core::ClientAuthHandler(
15475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* arg,
15485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRFileDesc* socket,
15495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CERTDistNames* ca_names,
15505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CERTCertificate** result_certificate,
15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECKEYPrivateKey** result_private_key) {
15525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Core* core = reinterpret_cast<Core*>(arg);
15535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(core->OnNSSTaskRunner());
15545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core->PostOrRunCallback(
15565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
15575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&AddLogEvent, core->weak_net_log_,
15585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 NetLog::TYPE_SSL_CLIENT_CERT_REQUESTED));
15595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Regular client certificate requested.
15615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core->client_auth_cert_needed_ = !core->ssl_config_.send_client_cert;
15625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* wincx  = SSL_RevealPinArg(socket);
15635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (core->ssl_config_.send_client_cert) {
15652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Second pass: a client certificate should have been selected.
1566868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (core->ssl_config_.client_cert.get()) {
1567868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      CERTCertificate* cert =
1568868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          CERT_DupCertificate(core->ssl_config_.client_cert->os_cert_handle());
15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SECKEYPrivateKey* privkey = PK11_FindKeyByAnyCert(cert, wincx);
15705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (privkey) {
15715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // TODO(jsorianopastor): We should wait for server certificate
15725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // verification before sending our credentials.  See
15735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // http://crbug.com/13934.
15745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *result_certificate = cert;
15755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *result_private_key = privkey;
15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // A cert_count of -1 means the number of certificates is unknown.
15775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // NSS will construct the certificate chain.
15785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        core->AddCertProvidedEvent(-1);
15795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return SECSuccess;
15815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
15825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(WARNING) << "Client cert found without private key";
15835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
15845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Send no client certificate.
15855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    core->AddCertProvidedEvent(0);
15865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SECFailure;
15875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // First pass: client certificate is needed.
15902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  core->nss_handshake_state_.cert_authorities.clear();
15915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Retrieve the DER-encoded DistinguishedName of the cert issuers accepted by
15932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the server and save them in |cert_authorities|.
15942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int i = 0; i < ca_names->nnames; i++) {
15952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    core->nss_handshake_state_.cert_authorities.push_back(std::string(
15962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        reinterpret_cast<const char*>(ca_names->names[i].data),
15972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        static_cast<size_t>(ca_names->names[i].len)));
15985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Update the network task runner's view of the handshake state now that
16012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // server certificate request has been recorded.
16025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core->PostOrRunCallback(
16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE, base::Bind(&Core::OnHandshakeStateUpdated, core,
16045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            core->nss_handshake_state_));
16055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Tell NSS to suspend the client authentication.  We will then abort the
16075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // handshake by returning ERR_SSL_CLIENT_AUTH_CERT_NEEDED.
16085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SECWouldBlock;
16095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // NSS_PLATFORM_CLIENT_AUTH
16115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1613f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)SECStatus SSLClientSocketNSS::Core::CanFalseStartCallback(
1614f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    PRFileDesc* socket,
1615f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    void* arg,
1616f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    PRBool* can_false_start) {
1617f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // If the server doesn't support NPN or ALPN, then we don't do False
1618f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Start with it.
1619f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  PRBool negotiated_extension;
1620f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SECStatus rv = SSL_HandshakeNegotiatedExtension(socket,
1621f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                                  ssl_app_layer_protocol_xtn,
1622f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                                  &negotiated_extension);
1623f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (rv != SECSuccess || !negotiated_extension) {
1624f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    rv = SSL_HandshakeNegotiatedExtension(socket,
1625f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                          ssl_next_proto_nego_xtn,
1626f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                          &negotiated_extension);
1627f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
1628f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (rv != SECSuccess || !negotiated_extension) {
1629f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    *can_false_start = PR_FALSE;
1630f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return SECSuccess;
1631f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
1632f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1633f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return SSL_RecommendedCanFalseStart(socket, can_false_start);
1634f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
1635f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1636f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// static
16375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::HandshakeCallback(
16385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRFileDesc* socket,
16395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* arg) {
16405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Core* core = reinterpret_cast<Core*>(arg);
16415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(core->OnNSSTaskRunner());
16425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core->handshake_callback_called_ = true;
1644f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (core->false_started_) {
1645f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    core->false_started_ = false;
1646f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // If we False Started, DoHandshake already called HandshakeSucceeded.
1647f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
1648f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
1649f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  core->HandshakeSucceeded();
1650f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
16515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1652f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void SSLClientSocketNSS::Core::HandshakeSucceeded() {
1653f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(OnNSSTaskRunner());
16545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PRBool last_handshake_resumed;
1656f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SECStatus rv = SSL_HandshakeResumedSession(nss_fd_, &last_handshake_resumed);
16575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv == SECSuccess && last_handshake_resumed) {
1658f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    nss_handshake_state_.resumed_handshake = true;
16595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1660f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    nss_handshake_state_.resumed_handshake = false;
16615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1663f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  RecordChannelIDSupportOnNSSTaskRunner();
1664f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  UpdateServerCert();
1665a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  UpdateSignedCertTimestamps();
1666f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  UpdateConnectionStatus();
1667f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  UpdateNextProto();
16685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Update the network task runners view of the handshake state whenever
16705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a handshake has completed.
1671f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  PostOrRunCallback(
1672f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      FROM_HERE, base::Bind(&Core::OnHandshakeStateUpdated, this,
1673f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                            nss_handshake_state_));
16745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Core::HandleNSSError(PRErrorCode nss_error,
16775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             bool handshake_error) {
16785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
16795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int net_error = handshake_error ? MapNSSClientHandshakeError(nss_error) :
16815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    MapNSSClientError(nss_error);
16825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
16845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // On Windows, a handle to the HCRYPTPROV is cached in the X509Certificate
16855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // os_cert_handle() as an optimization. However, if the certificate
16865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // private key is stored on a smart card, and the smart card is removed,
16875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the cached HCRYPTPROV will not be able to obtain the HCRYPTKEY again,
16885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // preventing client certificate authentication. Because the
16895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // X509Certificate may outlive the individual SSLClientSocketNSS, due to
16905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // caching in X509Certificate, this failure ends up preventing client
16915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // certificate authentication with the same certificate for all future
16925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // attempts, even after the smart card has been re-inserted. By setting
16935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the CERT_KEY_PROV_HANDLE_PROP_ID to NULL, the cached HCRYPTPROV will
16945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // typically be freed. This allows a new HCRYPTPROV to be obtained from
16955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the certificate on the next attempt, which should succeed if the smart
16965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // card has been re-inserted, or will typically prompt the user to
16975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // re-insert the smart card if not.
16985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((net_error == ERR_SSL_CLIENT_AUTH_CERT_NO_PRIVATE_KEY ||
16995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       net_error == ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED) &&
17005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ssl_config_.send_client_cert && ssl_config_.client_cert) {
17015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CertSetCertificateContextProperty(
17025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ssl_config_.client_cert->os_cert_handle(),
17035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
17045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
17065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return net_error;
17085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Core::DoHandshakeLoop(int last_io_result) {
17115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
17125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = last_io_result;
17145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
17155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Default to STATE_NONE for next state.
17165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    State state = next_handshake_state_;
17175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GotoState(STATE_NONE);
17185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (state) {
17205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_HANDSHAKE:
17215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoHandshake();
17225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
17235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_GET_DOMAIN_BOUND_CERT_COMPLETE:
17245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoGetDBCertComplete(rv);
17255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
17265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_NONE:
17275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
17285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = ERR_UNEXPECTED;
17295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(DFATAL) << "unexpected state " << state;
17305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
17315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
17325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Do the actual network I/O
17345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool network_moved = DoTransportIO();
17355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (network_moved && next_handshake_state_ == STATE_HANDSHAKE) {
17365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // In general we exit the loop if rv is ERR_IO_PENDING.  In this
17375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // special case we keep looping even if rv is ERR_IO_PENDING because
17385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // the transport IO may allow DoHandshake to make progress.
17395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(rv == OK || rv == ERR_IO_PENDING);
17405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rv = OK;  // This causes us to stay in the loop.
17415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
17425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (rv != ERR_IO_PENDING && next_handshake_state_ != STATE_NONE);
17435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
17445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Core::DoReadLoop(int result) {
17475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
1748f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(false_started_ || handshake_callback_called_);
17495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(STATE_NONE, next_handshake_state_);
17505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result < 0)
17525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
17535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!nss_bufs_) {
17555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(DFATAL) << "!nss_bufs_";
17565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rv = ERR_UNEXPECTED;
17575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PostOrRunCallback(
17585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
17595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&AddLogEventWithCallback, weak_net_log_,
17605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   NetLog::TYPE_SSL_READ_ERROR,
17615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   CreateNetLogSSLErrorCallback(rv, 0)));
17625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
17635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool network_moved;
17665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv;
17675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
17685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = DoPayloadRead();
17695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    network_moved = DoTransportIO();
17705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (rv == ERR_IO_PENDING && network_moved);
17715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
17735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Core::DoWriteLoop(int result) {
17765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
1777f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(false_started_ || handshake_callback_called_);
17785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(STATE_NONE, next_handshake_state_);
17795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result < 0)
17815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
17825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!nss_bufs_) {
17845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(DFATAL) << "!nss_bufs_";
17855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rv = ERR_UNEXPECTED;
17865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PostOrRunCallback(
17875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
17885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&AddLogEventWithCallback, weak_net_log_,
17895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   NetLog::TYPE_SSL_READ_ERROR,
17905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   CreateNetLogSSLErrorCallback(rv, 0)));
17915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
17925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool network_moved;
17955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv;
17965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
17975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = DoPayloadWrite();
17985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    network_moved = DoTransportIO();
17995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (rv == ERR_IO_PENDING && network_moved);
18005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LeaveFunction(rv);
18025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
18035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
18045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Core::DoHandshake() {
18065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
18075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int net_error = net::OK;
18095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECStatus rv = SSL_ForceHandshake(nss_fd_);
18105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note: this function may be called multiple times during the handshake, so
18125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // even though channel id and client auth are separate else cases, they can
18135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // both be used during a single SSL handshake.
18145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (channel_id_needed_) {
18155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GotoState(STATE_GET_DOMAIN_BOUND_CERT_COMPLETE);
18165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_error = ERR_IO_PENDING;
18175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (client_auth_cert_needed_) {
18185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_error = ERR_SSL_CLIENT_AUTH_CERT_NEEDED;
18195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PostOrRunCallback(
18205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
18215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&AddLogEventWithCallback, weak_net_log_,
18225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   NetLog::TYPE_SSL_HANDSHAKE_ERROR,
18235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   CreateNetLogSSLErrorCallback(net_error, 0)));
18245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If the handshake already succeeded (because the server requests but
18265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // doesn't require a client cert), we need to invalidate the SSL session
18275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // so that we won't try to resume the non-client-authenticated session in
18285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the next handshake.  This will cause the server to ask for a client
18295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // cert again.
18305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv == SECSuccess && SSL_InvalidateSession(nss_fd_) != SECSuccess)
18315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(WARNING) << "Couldn't invalidate SSL session: " << PR_GetError();
18325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (rv == SECSuccess) {
18335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!handshake_callback_called_) {
1834f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      false_started_ = true;
1835f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      HandshakeSucceeded();
1836f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
1837f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1838f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // TODO(wtc): move this block of code to OwnAuthCertHandler.
18395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #if defined(SSL_ENABLE_OCSP_STAPLING)
1840f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // TODO(agl): figure out how to plumb an OCSP response into the Mac
1841f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // system library and update IsOCSPStaplingSupported for Mac.
1842f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (IsOCSPStaplingSupported()) {
1843f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      const SECItemArray* ocsp_responses =
1844f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          SSL_PeerStapledOCSPResponses(nss_fd_);
1845f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (ocsp_responses->len) {
18465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #if defined(OS_WIN)
1847f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        if (nss_handshake_state_.server_cert) {
1848f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          CRYPT_DATA_BLOB ocsp_response_blob;
1849f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          ocsp_response_blob.cbData = ocsp_responses->items[0].len;
1850f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          ocsp_response_blob.pbData = ocsp_responses->items[0].data;
1851f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          BOOL ok = CertSetCertificateContextProperty(
1852f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)              nss_handshake_state_.server_cert->os_cert_handle(),
1853f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)              CERT_OCSP_RESPONSE_PROP_ID,
1854f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)              CERT_SET_PROPERTY_IGNORE_PERSIST_ERROR_FLAG,
1855f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)              &ocsp_response_blob);
1856f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          if (!ok) {
1857f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            VLOG(1) << "Failed to set OCSP response property: "
1858f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                    << GetLastError();
18595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
1860f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        }
18615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #elif defined(USE_NSS)
1862f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        CacheOCSPResponseFromSideChannelFunction cache_ocsp_response =
1863f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            GetCacheOCSPResponseFromSideChannelFunction();
18645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1865f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        cache_ocsp_response(
1866f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            CERT_GetDefaultCertDB(),
1867f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            nss_handshake_state_.server_cert_chain[0], PR_Now(),
1868f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            &ocsp_responses->items[0], NULL);
18695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #endif
18705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
18715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1872f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  #endif
18735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Done!
18745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
18755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRErrorCode prerr = PR_GetError();
18765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_error = HandleNSSError(prerr, true);
18775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Some network devices that inspect application-layer packets seem to
18792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // inject TCP reset packets to break the connections when they see
18802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // TLS 1.1 in ClientHello or ServerHello. See http://crbug.com/130293.
18812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    //
18827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // Only allow ERR_CONNECTION_RESET to trigger a fallback from TLS 1.1 or
18837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // 1.2. We don't lose much in this fallback because the explicit IV for CBC
18847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // mode in TLS 1.1 is approximated by record splitting in TLS 1.0. The
18857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // fallback will be more painful for TLS 1.2 when we have GCM support.
18862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    //
18872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // ERR_CONNECTION_RESET is a common network error, so we don't want it
18882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // to trigger a version fallback in general, especially the TLS 1.0 ->
18892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // SSL 3.0 fallback, which would drop TLS extensions.
18902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (prerr == PR_CONNECT_RESET_ERROR &&
18917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        ssl_config_.version_max >= SSL_PROTOCOL_VERSION_TLS1_1) {
18922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      net_error = ERR_SSL_PROTOCOL_ERROR;
18932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
18942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If not done, stay in this state
18965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (net_error == ERR_IO_PENDING) {
18975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GotoState(STATE_HANDSHAKE);
18985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
18995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PostOrRunCallback(
19005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          FROM_HERE,
19015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Bind(&AddLogEventWithCallback, weak_net_log_,
19025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     NetLog::TYPE_SSL_HANDSHAKE_ERROR,
19035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     CreateNetLogSSLErrorCallback(net_error, prerr)));
19045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
19055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return net_error;
19085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Core::DoGetDBCertComplete(int result) {
19115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECStatus rv;
19125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PostOrRunCallback(
19135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
19145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&BoundNetLog::EndEventWithNetErrorCode, weak_net_log_,
19155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 NetLog::TYPE_SSL_GET_DOMAIN_BOUND_CERT, result));
19165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  channel_id_needed_ = false;
19185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != OK)
19205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
19215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECKEYPublicKey* public_key;
19235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECKEYPrivateKey* private_key;
19245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int error = ImportChannelIDKeys(&public_key, &private_key);
19255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (error != OK)
19265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return error;
19275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_RestartHandshakeAfterChannelIDReq(nss_fd_, public_key, private_key);
19295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess)
19305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return MapNSSError(PORT_GetError());
19315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetChannelIDProvided();
19335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GotoState(STATE_HANDSHAKE);
19345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
19355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Core::DoPayloadRead() {
19385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
1939868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(user_read_buf_.get());
19405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GT(user_read_buf_len_, 0);
19415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int rv;
19432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If a previous greedy read resulted in an error that was not consumed (eg:
19442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // due to the caller having read some data successfully), then return that
19452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // pending error now.
19462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (pending_read_result_ != kNoPendingReadResult) {
19472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    rv = pending_read_result_;
19482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PRErrorCode prerr = pending_read_nss_error_;
19492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    pending_read_result_ = kNoPendingReadResult;
19502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    pending_read_nss_error_ = 0;
19512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (rv == 0) {
19532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      PostOrRunCallback(
19542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          FROM_HERE,
19552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::Bind(&LogByteTransferEvent, weak_net_log_,
19562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     NetLog::TYPE_SSL_SOCKET_BYTES_RECEIVED, rv,
19572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     scoped_refptr<IOBuffer>(user_read_buf_)));
19582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
19592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      PostOrRunCallback(
19602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          FROM_HERE,
19612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::Bind(&AddLogEventWithCallback, weak_net_log_,
19622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     NetLog::TYPE_SSL_READ_ERROR,
19632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CreateNetLogSSLErrorCallback(rv, prerr)));
19642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
19655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
19665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Perform a greedy read, attempting to read as much as the caller has
19692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // requested. In the current NSS implementation, PR_Read will return
19702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // exactly one SSL application data record's worth of data per invocation.
19712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The record size is dictated by the server, and may be noticeably smaller
19722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // than the caller's buffer. This may be as little as a single byte, if the
19732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // server is performing 1/n-1 record splitting.
19742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
19752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // However, this greedy read may result in renegotiations/re-handshakes
19762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // happening or may lead to some data being read, followed by an EOF (such as
19772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // a TLS close-notify). If at least some data was read, then that result
19782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // should be deferred until the next call to DoPayloadRead(). Otherwise, if no
19792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // data was read, it's safe to return the error or EOF immediately.
19802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int total_bytes_read = 0;
19812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  do {
19822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    rv = PR_Read(nss_fd_, user_read_buf_->data() + total_bytes_read,
19832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 user_read_buf_len_ - total_bytes_read);
19842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (rv > 0)
19852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      total_bytes_read += rv;
19862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } while (total_bytes_read < user_read_buf_len_ && rv > 0);
19872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int amount_in_read_buffer = memio_GetReadableBufferSize(nss_bufs_);
19882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PostOrRunCallback(FROM_HERE, base::Bind(&Core::OnNSSBufferUpdated, this,
19892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                          amount_in_read_buffer));
19902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (total_bytes_read == user_read_buf_len_) {
19922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // The caller's entire request was satisfied without error. No further
19932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // processing needed.
19942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    rv = total_bytes_read;
19952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
19962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Otherwise, an error occurred (rv <= 0). The error needs to be handled
19972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // immediately, while the NSPR/NSS errors are still available in
19982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // thread-local storage. However, the handled/remapped error code should
19992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // only be returned if no application data was already read; if it was, the
20002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // error code should be deferred until the next call of DoPayloadRead.
20012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    //
20022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // If no data was read, |*next_result| will point to the return value of
20032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // this function. If at least some data was read, |*next_result| will point
20042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // to |pending_read_error_|, to be returned in a future call to
20052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // DoPayloadRead() (e.g.: after the current data is handled).
20062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int* next_result = &rv;
20072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (total_bytes_read > 0) {
20082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      pending_read_result_ = rv;
20092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      rv = total_bytes_read;
20102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      next_result = &pending_read_result_;
20112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
20122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
20132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (client_auth_cert_needed_) {
20142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *next_result = ERR_SSL_CLIENT_AUTH_CERT_NEEDED;
20152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      pending_read_nss_error_ = 0;
20162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else if (*next_result < 0) {
20172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // If *next_result == 0, then that indicates EOF, and no special error
20182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // handling is needed.
20192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      pending_read_nss_error_ = PR_GetError();
20202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *next_result = HandleNSSError(pending_read_nss_error_, false);
20212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (rv > 0 && *next_result == ERR_IO_PENDING) {
20222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // If at least some data was read from PR_Read(), do not treat
20232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // insufficient data as an error to return in the next call to
20242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // DoPayloadRead() - instead, let the call fall through to check
20252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // PR_Read() again. This is because DoTransportIO() may complete
20262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // in between the next call to DoPayloadRead(), and thus it is
20272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // important to check PR_Read() on subsequent invocations to see
20282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // if a complete record may now be read.
20292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        pending_read_nss_error_ = 0;
20302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        pending_read_result_ = kNoPendingReadResult;
20312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
20322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
20332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
20342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
20352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_NE(ERR_IO_PENDING, pending_read_result_);
20362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
20375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv >= 0) {
20385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PostOrRunCallback(
20395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
20405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&LogByteTransferEvent, weak_net_log_,
20415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   NetLog::TYPE_SSL_SOCKET_BYTES_RECEIVED, rv,
20425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   scoped_refptr<IOBuffer>(user_read_buf_)));
20432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else if (rv != ERR_IO_PENDING) {
20442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PostOrRunCallback(
20452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FROM_HERE,
20462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&AddLogEventWithCallback, weak_net_log_,
20472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   NetLog::TYPE_SSL_READ_ERROR,
20482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   CreateNetLogSSLErrorCallback(rv, pending_read_nss_error_)));
20492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    pending_read_nss_error_ = 0;
20505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
20515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
20525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
20535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Core::DoPayloadWrite() {
20555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
20565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2057868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(user_write_buf_.get());
20585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int old_amount_in_read_buffer = memio_GetReadableBufferSize(nss_bufs_);
20605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = PR_Write(nss_fd_, user_write_buf_->data(), user_write_buf_len_);
20612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int new_amount_in_read_buffer = memio_GetReadableBufferSize(nss_bufs_);
20622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // PR_Write could potentially consume the unhandled data in the memio read
20632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // buffer if a renegotiation is in progress. If the buffer is consumed,
20642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // notify the latest buffer size to NetworkRunner.
20652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (old_amount_in_read_buffer != new_amount_in_read_buffer) {
20662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PostOrRunCallback(
20672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FROM_HERE,
20682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&Core::OnNSSBufferUpdated, this, new_amount_in_read_buffer));
20692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
20705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv >= 0) {
20715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PostOrRunCallback(
20725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
20735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&LogByteTransferEvent, weak_net_log_,
20745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   NetLog::TYPE_SSL_SOCKET_BYTES_SENT, rv,
20755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   scoped_refptr<IOBuffer>(user_write_buf_)));
20765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
20775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
20785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PRErrorCode prerr = PR_GetError();
20795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (prerr == PR_WOULD_BLOCK_ERROR)
20805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_IO_PENDING;
20815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = HandleNSSError(prerr, false);
20835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PostOrRunCallback(
20845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
20855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&AddLogEventWithCallback, weak_net_log_,
20865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 NetLog::TYPE_SSL_WRITE_ERROR,
20875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 CreateNetLogSSLErrorCallback(rv, prerr)));
20885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
20895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
20905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Do as much network I/O as possible between the buffer and the
20925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// transport socket. Return true if some I/O performed, false
20935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// otherwise (error or ERR_IO_PENDING).
20945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketNSS::Core::DoTransportIO() {
20955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
20965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool network_moved = false;
20985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (nss_bufs_ != NULL) {
20995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rv;
21005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Read and write as much data as we can. The loop is neccessary
21015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // because Write() may return synchronously.
21025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    do {
21035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rv = BufferSend();
2104b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      if (rv != ERR_IO_PENDING && rv != 0)
21055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        network_moved = true;
21065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } while (rv > 0);
2107b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if (!transport_recv_eof_ && BufferRecv() != ERR_IO_PENDING)
21085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      network_moved = true;
21095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return network_moved;
21115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
21125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Core::BufferRecv() {
21145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
21155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (transport_recv_busy_)
21175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_IO_PENDING;
21185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If NSS is blocked on reading from |nss_bufs_|, because it is empty,
21202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // determine how much data NSS wants to read. If NSS was not blocked,
21212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // this will return 0.
21222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int requested = memio_GetReadRequest(nss_bufs_);
21232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (requested == 0) {
21242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // This is not a perfect match of error codes, as no operation is
21252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // actually pending. However, returning 0 would be interpreted as a
21262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // possible sign of EOF, which is also an inappropriate match.
21272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return ERR_IO_PENDING;
21282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
21292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
21305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* buf;
21315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nb = memio_GetReadParams(nss_bufs_, &buf);
21325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv;
21335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!nb) {
21345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // buffer too full to read into, so no I/O possible at moment
21355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = ERR_IO_PENDING;
21365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
21375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<IOBuffer> read_buffer(new IOBuffer(nb));
21385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (OnNetworkTaskRunner()) {
2139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      rv = DoBufferRecv(read_buffer.get(), nb);
21405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
21415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool posted = network_task_runner_->PostTask(
21425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          FROM_HERE,
21435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Bind(IgnoreResult(&Core::DoBufferRecv), this, read_buffer,
21445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     nb));
21455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rv = posted ? ERR_IO_PENDING : ERR_ABORTED;
21465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
21475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv == ERR_IO_PENDING) {
21495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      transport_recv_busy_ = true;
21505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
21515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (rv > 0) {
21525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        memcpy(buf, read_buffer->data(), rv);
21535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (rv == 0) {
21545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        transport_recv_eof_ = true;
21555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
21565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memio_PutReadResult(nss_bufs_, MapErrorToNSS(rv));
21575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
21585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
21605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
21615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2162b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// Return 0 if nss_bufs_ was empty,
21635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// > 0 for bytes transferred immediately,
21645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// < 0 for error (or the non-error ERR_IO_PENDING).
21655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Core::BufferSend() {
21665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
21675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (transport_send_busy_)
21695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_IO_PENDING;
21705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* buf1;
21725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* buf2;
21735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int len1, len2;
21745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memio_GetWriteParams(nss_bufs_, &buf1, &len1, &buf2, &len2);
21755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const unsigned int len = len1 + len2;
21765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = 0;
21785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (len) {
21795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<IOBuffer> send_buffer(new IOBuffer(len));
21805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(send_buffer->data(), buf1, len1);
21815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(send_buffer->data() + len1, buf2, len2);
21825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (OnNetworkTaskRunner()) {
2184868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      rv = DoBufferSend(send_buffer.get(), len);
21855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
21865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool posted = network_task_runner_->PostTask(
21875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          FROM_HERE,
21885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Bind(IgnoreResult(&Core::DoBufferSend), this, send_buffer,
21895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     len));
21905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rv = posted ? ERR_IO_PENDING : ERR_ABORTED;
21915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
21925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv == ERR_IO_PENDING) {
21945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      transport_send_busy_ = true;
21955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
21965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memio_PutWriteResult(nss_bufs_, MapErrorToNSS(rv));
21975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
21985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
22015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
22025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::OnRecvComplete(int result) {
22045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
22055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (next_handshake_state_ == STATE_HANDSHAKE) {
22075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnHandshakeIOComplete(result);
22085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
22095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Network layer received some data, check if client requested to read
22125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // decrypted data.
2213868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!user_read_buf_.get())
22145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
22155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = DoReadLoop(result);
22175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != ERR_IO_PENDING)
22185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DoReadCallback(rv);
22195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
22205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::OnSendComplete(int result) {
22225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
22235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (next_handshake_state_ == STATE_HANDSHAKE) {
22255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnHandshakeIOComplete(result);
22265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
22275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // OnSendComplete may need to call DoPayloadRead while the renegotiation
22305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // handshake is in progress.
22315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv_read = ERR_IO_PENDING;
22325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv_write = ERR_IO_PENDING;
22335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool network_moved;
22345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
2235868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (user_read_buf_.get())
2236a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      rv_read = DoPayloadRead();
2237868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (user_write_buf_.get())
2238a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      rv_write = DoPayloadWrite();
2239a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    network_moved = DoTransportIO();
2240868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } while (rv_read == ERR_IO_PENDING && rv_write == ERR_IO_PENDING &&
2241868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           (user_read_buf_.get() || user_write_buf_.get()) && network_moved);
22425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2243a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // If the parent SSLClientSocketNSS is deleted during the processing of the
2244a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Read callback and OnNSSTaskRunner() == OnNetworkTaskRunner(), then the Core
2245a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // will be detached (and possibly deleted). Guard against deletion by taking
2246a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // an extra reference, then check if the Core was detached before invoking the
2247a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // next callback.
2248a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  scoped_refptr<Core> guard(this);
2249868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (user_read_buf_.get() && rv_read != ERR_IO_PENDING)
2250a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    DoReadCallback(rv_read);
2251a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
2252a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (OnNetworkTaskRunner() && detached_)
2253a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return;
2254a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
2255868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (user_write_buf_.get() && rv_write != ERR_IO_PENDING)
2256a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    DoWriteCallback(rv_write);
22575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
22585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// As part of Connect(), the SSLClientSocketNSS object performs an SSL
22605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// handshake. This requires network IO, which in turn calls
22615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BufferRecvComplete() with a non-zero byte count. This byte count eventually
22625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// winds its way through the state machine and ends up being passed to the
22635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// callback. For Read() and Write(), that's what we want. But for Connect(),
22645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the caller expects OK (i.e. 0) for success.
22655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::DoConnectCallback(int rv) {
22665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
22675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(rv, ERR_IO_PENDING);
22685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!user_connect_callback_.is_null());
22695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Closure c = base::Bind(
22715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::ResetAndReturn(&user_connect_callback_),
22725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rv > OK ? OK : rv);
22735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PostOrRunCallback(FROM_HERE, c);
22745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
22755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::DoReadCallback(int rv) {
22775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
22785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(ERR_IO_PENDING, rv);
22795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!user_read_callback_.is_null());
22805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_read_buf_ = NULL;
22825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_read_buf_len_ = 0;
22832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int amount_in_read_buffer = memio_GetReadableBufferSize(nss_bufs_);
22842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This is used to curry the |amount_int_read_buffer| and |user_cb| back to
22852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the network task runner.
22862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PostOrRunCallback(
22872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE,
22882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&Core::OnNSSBufferUpdated, this, amount_in_read_buffer));
22892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PostOrRunCallback(
22902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE,
22912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&Core::DidNSSRead, this, rv));
22922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PostOrRunCallback(
22932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE,
22942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(base::ResetAndReturn(&user_read_callback_), rv));
22955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
22965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::DoWriteCallback(int rv) {
22985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
22995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(ERR_IO_PENDING, rv);
23005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!user_write_callback_.is_null());
23015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Since Run may result in Write being called, clear |user_write_callback_|
23035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // up front.
23045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_write_buf_ = NULL;
23055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_write_buf_len_ = 0;
23062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Update buffer status because DoWriteLoop called DoTransportIO which may
23072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // perform read operations.
23082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int amount_in_read_buffer = memio_GetReadableBufferSize(nss_bufs_);
23092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This is used to curry the |amount_int_read_buffer| and |user_cb| back to
23102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the network task runner.
23112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PostOrRunCallback(
23122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE,
23132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&Core::OnNSSBufferUpdated, this, amount_in_read_buffer));
23142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PostOrRunCallback(
23152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE,
23162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&Core::DidNSSWrite, this, rv));
23172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PostOrRunCallback(
23182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE,
23192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(base::ResetAndReturn(&user_write_callback_), rv));
23205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
23215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus SSLClientSocketNSS::Core::ClientChannelIDHandler(
23235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* arg,
23245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRFileDesc* socket,
23255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECKEYPublicKey **out_public_key,
23265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECKEYPrivateKey **out_private_key) {
23275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Core* core = reinterpret_cast<Core*>(arg);
23285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(core->OnNSSTaskRunner());
23295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core->PostOrRunCallback(
23315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
23325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&AddLogEvent, core->weak_net_log_,
23335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 NetLog::TYPE_SSL_CHANNEL_ID_REQUESTED));
23345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We have negotiated the TLS channel ID extension.
23365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core->channel_id_xtn_negotiated_ = true;
2337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string host = core->host_and_port_.host();
23385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int error = ERR_UNEXPECTED;
23395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (core->OnNetworkTaskRunner()) {
2340bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    error = core->DoGetDomainBoundCert(host);
23415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
23425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool posted = core->network_task_runner_->PostTask(
23435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
23445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(
23455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            IgnoreResult(&Core::DoGetDomainBoundCert),
2346bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch            core, host));
23475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error = posted ? ERR_IO_PENDING : ERR_ABORTED;
23485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
23495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (error == ERR_IO_PENDING) {
23515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Asynchronous case.
23525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    core->channel_id_needed_ = true;
23535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SECWouldBlock;
23545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
23555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core->PostOrRunCallback(
23575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
23585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&BoundNetLog::EndEventWithNetErrorCode, core->weak_net_log_,
23595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 NetLog::TYPE_SSL_GET_DOMAIN_BOUND_CERT, error));
23605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECStatus rv = SECSuccess;
23615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (error == OK) {
23625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Synchronous success.
23635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int result = core->ImportChannelIDKeys(out_public_key, out_private_key);
23645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (result == OK)
23655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      core->SetChannelIDProvided();
23665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
23675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rv = SECFailure;
23685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
23695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = SECFailure;
23705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
23715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
23735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
23745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Core::ImportChannelIDKeys(SECKEYPublicKey** public_key,
23765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  SECKEYPrivateKey** key) {
23775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set the certificate.
23785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECItem cert_item;
23795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cert_item.data = (unsigned char*) domain_bound_cert_.data();
23805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cert_item.len = domain_bound_cert_.size();
23815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedCERTCertificate cert(CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
23825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                     &cert_item,
23835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                     NULL,
23845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                     PR_FALSE,
23855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                     PR_TRUE));
23865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cert == NULL)
23875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return MapNSSError(PORT_GetError());
23885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2389f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  crypto::ScopedPK11Slot slot(PK11_GetInternalSlot());
23905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set the private key.
2391bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  if (!crypto::ECPrivateKey::ImportFromEncryptedPrivateKeyInfo(
2392f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          slot.get(),
23935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ServerBoundCertService::kEPKIPassword,
23945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          reinterpret_cast<const unsigned char*>(
23955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              domain_bound_private_key_.data()),
23965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          domain_bound_private_key_.size(),
23975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          &cert->subjectPublicKeyInfo,
23985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          false,
23995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          false,
24005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          key,
24015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          public_key)) {
2402bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    int error = MapNSSError(PORT_GetError());
2403bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return error;
24045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
24055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
24075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
24085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::UpdateServerCert() {
24105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nss_handshake_state_.server_cert_chain.Reset(nss_fd_);
24115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nss_handshake_state_.server_cert = X509Certificate::CreateFromDERCertChain(
24125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nss_handshake_state_.server_cert_chain.AsStringPieceVector());
2413868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (nss_handshake_state_.server_cert.get()) {
24145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Since this will be called asynchronously on another thread, it needs to
24155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // own a reference to the certificate.
24165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NetLog::ParametersCallback net_log_callback =
24175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&NetLogX509CertificateCallback,
24185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   nss_handshake_state_.server_cert);
24195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PostOrRunCallback(
24205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
24215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&AddLogEventWithCallback, weak_net_log_,
24225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   NetLog::TYPE_SSL_CERTIFICATES_RECEIVED,
24235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   net_log_callback));
24245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
24255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
24265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2427a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void SSLClientSocketNSS::Core::UpdateSignedCertTimestamps() {
2428a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  const SECItem* signed_cert_timestamps =
2429a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      SSL_PeerSignedCertTimestamps(nss_fd_);
2430a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
2431a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!signed_cert_timestamps || !signed_cert_timestamps->len)
2432a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return;
2433a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
2434a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  nss_handshake_state_.sct_list_from_tls_extension = std::string(
2435a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      reinterpret_cast<char*>(signed_cert_timestamps->data),
2436a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      signed_cert_timestamps->len);
2437a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
2438a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
24395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::UpdateConnectionStatus() {
24405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLChannelInfo channel_info;
24415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECStatus ok = SSL_GetChannelInfo(nss_fd_,
24425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    &channel_info, sizeof(channel_info));
24435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ok == SECSuccess &&
24445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      channel_info.length == sizeof(channel_info) &&
24455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      channel_info.cipherSuite) {
24465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nss_handshake_state_.ssl_connection_status |=
24475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (static_cast<int>(channel_info.cipherSuite) &
24485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         SSL_CONNECTION_CIPHERSUITE_MASK) <<
24495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SSL_CONNECTION_CIPHERSUITE_SHIFT;
24505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nss_handshake_state_.ssl_connection_status |=
24525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (static_cast<int>(channel_info.compressionMethod) &
24535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         SSL_CONNECTION_COMPRESSION_MASK) <<
24545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SSL_CONNECTION_COMPRESSION_SHIFT;
24555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2456bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    // NSS 3.14.x doesn't have a version macro for TLS 1.2 (because NSS didn't
2457bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    // support it yet), so use 0x0303 directly.
24585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int version = SSL_CONNECTION_VERSION_UNKNOWN;
24595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (channel_info.protocolVersion < SSL_LIBRARY_VERSION_3_0) {
24605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // All versions less than SSL_LIBRARY_VERSION_3_0 are treated as SSL
24615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // version 2.
24625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      version = SSL_CONNECTION_VERSION_SSL2;
24635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (channel_info.protocolVersion == SSL_LIBRARY_VERSION_3_0) {
24645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      version = SSL_CONNECTION_VERSION_SSL3;
24655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (channel_info.protocolVersion == SSL_LIBRARY_VERSION_3_1_TLS) {
24665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      version = SSL_CONNECTION_VERSION_TLS1;
2467bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    } else if (channel_info.protocolVersion == SSL_LIBRARY_VERSION_TLS_1_1) {
24685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      version = SSL_CONNECTION_VERSION_TLS1_1;
24695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (channel_info.protocolVersion == 0x0303) {
24705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      version = SSL_CONNECTION_VERSION_TLS1_2;
24715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
24725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nss_handshake_state_.ssl_connection_status |=
24735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (version & SSL_CONNECTION_VERSION_MASK) <<
24745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SSL_CONNECTION_VERSION_SHIFT;
24755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
24765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PRBool peer_supports_renego_ext;
24785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ok = SSL_HandshakeNegotiatedExtension(nss_fd_, ssl_renegotiation_info_xtn,
24795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        &peer_supports_renego_ext);
24805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ok == SECSuccess) {
24815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!peer_supports_renego_ext) {
24825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nss_handshake_state_.ssl_connection_status |=
24835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          SSL_CONNECTION_NO_RENEGOTIATION_EXTENSION;
24845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Log an informational message if the server does not support secure
24855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // renegotiation (RFC 5746).
24865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VLOG(1) << "The server " << host_and_port_.ToString()
24875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              << " does not support the TLS renegotiation_info extension.";
24885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
24895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UMA_HISTOGRAM_ENUMERATION("Net.RenegotiationExtensionSupported",
24905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              peer_supports_renego_ext, 2);
24912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
24922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // We would like to eliminate fallback to SSLv3 for non-buggy servers
24932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // because of security concerns. For example, Google offers forward
24942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // secrecy with ECDHE but that requires TLS 1.0. An attacker can block
24952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // TLSv1 connections and force us to downgrade to SSLv3 and remove forward
24962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // secrecy.
24972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    //
24982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Yngve from Opera has suggested using the renegotiation extension as an
24992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // indicator that SSLv3 fallback was mistaken:
25002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // tools.ietf.org/html/draft-pettersen-tls-version-rollback-removal-00 .
25012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    //
25022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // As a first step, measure how often clients perform version fallback
25032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // while the server advertises support secure renegotiation.
25042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (ssl_config_.version_fallback &&
25052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        channel_info.protocolVersion == SSL_LIBRARY_VERSION_3_0) {
25062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      UMA_HISTOGRAM_BOOLEAN("Net.SSLv3FallbackToRenegoPatchedServer",
25072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            peer_supports_renego_ext == PR_TRUE);
25082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
25095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
25105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ssl_config_.version_fallback) {
25125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nss_handshake_state_.ssl_connection_status |=
25135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SSL_CONNECTION_VERSION_FALLBACK;
25145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
25155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
25165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2517eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid SSLClientSocketNSS::Core::UpdateNextProto() {
2518eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  uint8 buf[256];
2519eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SSLNextProtoState state;
2520eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  unsigned buf_len;
2521eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2522eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SECStatus rv = SSL_GetNextProto(nss_fd_, &state, buf, &buf_len, sizeof(buf));
2523eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (rv != SECSuccess)
2524eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
2525eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2526eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  nss_handshake_state_.next_proto =
2527eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      std::string(reinterpret_cast<char*>(buf), buf_len);
2528eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  switch (state) {
2529eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case SSL_NEXT_PROTO_NEGOTIATED:
2530eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case SSL_NEXT_PROTO_SELECTED:
2531eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      nss_handshake_state_.next_proto_status = kNextProtoNegotiated;
2532eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
2533eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case SSL_NEXT_PROTO_NO_OVERLAP:
2534eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      nss_handshake_state_.next_proto_status = kNextProtoNoOverlap;
2535eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
2536eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case SSL_NEXT_PROTO_NO_SUPPORT:
2537eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      nss_handshake_state_.next_proto_status = kNextProtoUnsupported;
2538eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
2539eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    default:
2540eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      NOTREACHED();
2541eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
2542eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
2543eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
2544eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
25451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void SSLClientSocketNSS::Core::RecordChannelIDSupportOnNSSTaskRunner() {
2546b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  DCHECK(OnNSSTaskRunner());
25475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (nss_handshake_state_.resumed_handshake)
25485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
25495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2550b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // Copy the NSS task runner-only state to the network task runner and
2551b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // log histograms from there, since the histograms also need access to the
2552b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // network task runner state.
2553b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  PostOrRunCallback(
2554b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      FROM_HERE,
2555b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      base::Bind(&Core::RecordChannelIDSupportOnNetworkTaskRunner,
2556b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                 this,
2557b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                 channel_id_xtn_negotiated_,
2558b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                 ssl_config_.channel_id_enabled,
2559b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                 crypto::ECPrivateKey::IsSupported()));
2560b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
2561b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
2562b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void SSLClientSocketNSS::Core::RecordChannelIDSupportOnNetworkTaskRunner(
2563b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    bool negotiated_channel_id,
2564b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    bool channel_id_enabled,
2565b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    bool supports_ecc) const {
2566b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  DCHECK(OnNetworkTaskRunner());
2567b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
25681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  RecordChannelIDSupport(server_bound_cert_service_,
25691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                         negotiated_channel_id,
25701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                         channel_id_enabled,
25711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                         supports_ecc);
25725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
25735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Core::DoBufferRecv(IOBuffer* read_buffer, int len) {
25755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNetworkTaskRunner());
25765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GT(len, 0);
25775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (detached_)
25795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_ABORTED;
25805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = transport_->socket()->Read(
25825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      read_buffer, len,
25835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&Core::BufferRecvComplete, base::Unretained(this),
25845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 scoped_refptr<IOBuffer>(read_buffer)));
25855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!OnNSSTaskRunner() && rv != ERR_IO_PENDING) {
25875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nss_task_runner_->PostTask(
25885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE, base::Bind(&Core::BufferRecvComplete, this,
25895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              scoped_refptr<IOBuffer>(read_buffer), rv));
25905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
25915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
25925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
25945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
25955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Core::DoBufferSend(IOBuffer* send_buffer, int len) {
25975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNetworkTaskRunner());
25985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GT(len, 0);
25995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (detached_)
26015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_ABORTED;
26025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = transport_->socket()->Write(
26042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      send_buffer, len,
26052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&Core::BufferSendComplete,
26062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 base::Unretained(this)));
26075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!OnNSSTaskRunner() && rv != ERR_IO_PENDING) {
26095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nss_task_runner_->PostTask(
26105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
26115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&Core::BufferSendComplete, this, rv));
26125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
26135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
26145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
26165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
26175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2618bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochint SSLClientSocketNSS::Core::DoGetDomainBoundCert(const std::string& host) {
26195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNetworkTaskRunner());
26205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (detached_)
26225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_FAILED;
26235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  weak_net_log_->BeginEvent(NetLog::TYPE_SSL_GET_DOMAIN_BOUND_CERT);
26255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int rv = server_bound_cert_service_->GetOrCreateDomainBoundCert(
2627c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      host,
26285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &domain_bound_private_key_,
26295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &domain_bound_cert_,
26305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&Core::OnGetDomainBoundCertComplete, base::Unretained(this)),
26315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &domain_bound_cert_request_handle_);
26325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != ERR_IO_PENDING && !OnNSSTaskRunner()) {
26345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nss_task_runner_->PostTask(
26355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
26365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&Core::OnHandshakeIOComplete, this, rv));
26375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_IO_PENDING;
26385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
26395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
26415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
26425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::OnHandshakeStateUpdated(
26445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const HandshakeState& state) {
26452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(OnNetworkTaskRunner());
26465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  network_handshake_state_ = state;
26475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
26485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SSLClientSocketNSS::Core::OnNSSBufferUpdated(int amount_in_read_buffer) {
26502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(OnNetworkTaskRunner());
26512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  unhandled_buffer_size_ = amount_in_read_buffer;
26522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
26532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
26542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SSLClientSocketNSS::Core::DidNSSRead(int result) {
26552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(OnNetworkTaskRunner());
26562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(nss_waiting_read_);
26572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  nss_waiting_read_ = false;
26582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (result <= 0)
26592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    nss_is_closed_ = true;
26602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
26612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
26622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SSLClientSocketNSS::Core::DidNSSWrite(int result) {
26632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(OnNetworkTaskRunner());
26642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(nss_waiting_write_);
26652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  nss_waiting_write_ = false;
26662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (result < 0)
26672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    nss_is_closed_ = true;
26682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
26692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
26705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::BufferSendComplete(int result) {
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::BufferSendComplete, this, result));
26775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
26785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
26795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
26815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memio_PutWriteResult(nss_bufs_, MapErrorToNSS(result));
26835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transport_send_busy_ = false;
26845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OnSendComplete(result);
26855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
26865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::OnHandshakeIOComplete(int result) {
26885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!OnNSSTaskRunner()) {
26895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (detached_)
26905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
26915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nss_task_runner_->PostTask(
26935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE, base::Bind(&Core::OnHandshakeIOComplete, this, result));
26945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
26955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
26965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
26985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = DoHandshakeLoop(result);
27005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != ERR_IO_PENDING)
27015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DoConnectCallback(rv);
27025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
27035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::OnGetDomainBoundCertComplete(int result) {
27055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << __FUNCTION__ << " " << result;
27065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNetworkTaskRunner());
27075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OnHandshakeIOComplete(result);
27095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
27105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::BufferRecvComplete(
27125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IOBuffer* read_buffer,
27135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int result) {
27145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(read_buffer);
27155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!OnNSSTaskRunner()) {
27175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (detached_)
27185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
27195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nss_task_runner_->PostTask(
27215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE, base::Bind(&Core::BufferRecvComplete, this,
27225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              scoped_refptr<IOBuffer>(read_buffer), result));
27235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
27245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
27255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
27275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result > 0) {
27295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char* buf;
27305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int nb = memio_GetReadParams(nss_bufs_, &buf);
27315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK_GE(nb, result);
27325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(buf, read_buffer->data(), result);
27335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (result == 0) {
27345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    transport_recv_eof_ = true;
27355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
27365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memio_PutReadResult(nss_bufs_, MapErrorToNSS(result));
27385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transport_recv_busy_ = false;
27395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OnRecvComplete(result);
27405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
27415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::PostOrRunCallback(
27435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const tracked_objects::Location& location,
27445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::Closure& task) {
27455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!OnNetworkTaskRunner()) {
27465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    network_task_runner_->PostTask(
27475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
27485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&Core::PostOrRunCallback, this, location, task));
27495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
27505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
27515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (detached_ || task.is_null())
27535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
27545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  task.Run();
27555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
27565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::AddCertProvidedEvent(int cert_count) {
27585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PostOrRunCallback(
27595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
27605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&AddLogEventWithCallback, weak_net_log_,
27615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 NetLog::TYPE_SSL_CLIENT_CERT_PROVIDED,
27625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 NetLog::IntegerCallback("cert_count", cert_count)));
27635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
27645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::SetChannelIDProvided() {
27665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PostOrRunCallback(
27675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE, base::Bind(&AddLogEvent, weak_net_log_,
27685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            NetLog::TYPE_SSL_CHANNEL_ID_PROVIDED));
27695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nss_handshake_state_.channel_id_sent = true;
27705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Update the network task runner's view of the handshake state now that
27715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // channel id has been sent.
27725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PostOrRunCallback(
27735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE, base::Bind(&Core::OnHandshakeStateUpdated, this,
27745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            nss_handshake_state_));
27755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
27765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SSLClientSocketNSS::SSLClientSocketNSS(
27785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::SequencedTaskRunner* nss_task_runner,
27793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_ptr<ClientSocketHandle> transport_socket,
27805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const HostPortPair& host_and_port,
27815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SSLConfig& ssl_config,
27825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SSLClientSocketContext& context)
27835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : nss_task_runner_(nss_task_runner),
27843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      transport_(transport_socket.Pass()),
27855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      host_and_port_(host_and_port),
27865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ssl_config_(ssl_config),
27875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cert_verifier_(context.cert_verifier),
2788a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      cert_transparency_verifier_(context.cert_transparency_verifier),
27895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      server_bound_cert_service_(context.server_bound_cert_service),
27905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ssl_session_cache_shard_(context.ssl_session_cache_shard),
27915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      completed_handshake_(false),
27925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next_handshake_state_(STATE_NONE),
27935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nss_fd_(NULL),
27943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      net_log_(transport_->socket()->NetLog()),
27955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      transport_security_state_(context.transport_security_state),
27965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      valid_thread_id_(base::kInvalidThreadId) {
27975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterFunction("");
27985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InitCore();
27995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LeaveFunction("");
28005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
28015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SSLClientSocketNSS::~SSLClientSocketNSS() {
28035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterFunction("");
28045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Disconnect();
28055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LeaveFunction("");
28065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
28075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
28095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocket::ClearSessionCache() {
28105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SSL_ClearSessionCache can't be called before NSS is initialized.  Don't
28115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // bother initializing NSS just to clear an empty SSL session cache.
28125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!NSS_IsInitialized())
28135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
28145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSL_ClearSessionCache();
28165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
28175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketNSS::GetSSLInfo(SSLInfo* ssl_info) {
28195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterFunction("");
28205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssl_info->Reset();
28215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (core_->state().server_cert_chain.empty() ||
28225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !core_->state().server_cert_chain[0]) {
28235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
28245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
28255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssl_info->cert_status = server_cert_verify_result_.cert_status;
28275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssl_info->cert = server_cert_verify_result_.verified_cert;
2828a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
2829a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  AddSCTInfoToSSLInfo(ssl_info);
2830a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
28315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssl_info->connection_status =
28325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      core_->state().ssl_connection_status;
28335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssl_info->public_key_hashes = server_cert_verify_result_.public_key_hashes;
28345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (HashValueVector::const_iterator i = side_pinned_public_keys_.begin();
28355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != side_pinned_public_keys_.end(); ++i) {
28365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ssl_info->public_key_hashes.push_back(*i);
28375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
28385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssl_info->is_issued_by_known_root =
28395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      server_cert_verify_result_.is_issued_by_known_root;
28405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssl_info->client_cert_sent =
2841868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      ssl_config_.send_client_cert && ssl_config_.client_cert.get();
28425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssl_info->channel_id_sent = WasChannelIDSent();
28435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PRUint16 cipher_suite = SSLConnectionStatusToCipherSuite(
28455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      core_->state().ssl_connection_status);
28465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLCipherSuiteInfo cipher_info;
28475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECStatus ok = SSL_GetCipherSuiteInfo(cipher_suite,
28485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        &cipher_info, sizeof(cipher_info));
28495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ok == SECSuccess) {
28505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ssl_info->security_bits = cipher_info.effectiveKeyBits;
28515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
28525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ssl_info->security_bits = -1;
28535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(DFATAL) << "SSL_GetCipherSuiteInfo returned " << PR_GetError()
28545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                << " for cipherSuite " << cipher_suite;
28555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
28565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssl_info->handshake_type = core_->state().resumed_handshake ?
28585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SSLInfo::HANDSHAKE_RESUME : SSLInfo::HANDSHAKE_FULL;
28595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LeaveFunction("");
28615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
28625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
28635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::GetSSLCertRequestInfo(
28655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SSLCertRequestInfo* cert_request_info) {
28665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterFunction("");
28675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(rch): switch SSLCertRequestInfo.host_and_port to a HostPortPair
28685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cert_request_info->host_and_port = host_and_port_.ToString();
28692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  cert_request_info->cert_authorities = core_->state().cert_authorities;
28702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LeaveFunction("");
28715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
28725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::ExportKeyingMaterial(const base::StringPiece& label,
28745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             bool has_context,
28755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             const base::StringPiece& context,
28765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             unsigned char* out,
28775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             unsigned int outlen) {
28785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsConnected())
28795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_SOCKET_NOT_CONNECTED;
28805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SSL_ExportKeyingMaterial may block the current thread if |core_| is in
28825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the midst of a handshake.
28835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECStatus result = SSL_ExportKeyingMaterial(
28845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nss_fd_, label.data(), label.size(), has_context,
28855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reinterpret_cast<const unsigned char*>(context.data()),
28865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context.length(), out, outlen);
28875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != SECSuccess) {
28885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_ExportKeyingMaterial", "");
28895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return MapNSSError(PORT_GetError());
28905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
28915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
28925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
28935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::GetTLSUniqueChannelBinding(std::string* out) {
28955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsConnected())
28965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_SOCKET_NOT_CONNECTED;
28975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned char buf[64];
28985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int len;
28995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECStatus result = SSL_GetChannelBinding(nss_fd_,
29005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           SSL_CHANNEL_BINDING_TLS_UNIQUE,
29015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           buf, &len, arraysize(buf));
29025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != SECSuccess) {
29035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_GetChannelBinding", "");
29045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return MapNSSError(PORT_GetError());
29055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
29065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->assign(reinterpret_cast<char*>(buf), len);
29075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
29085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
29095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SSLClientSocket::NextProtoStatus
29115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SSLClientSocketNSS::GetNextProto(std::string* proto,
29125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 std::string* server_protos) {
29135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *proto = core_->state().next_proto;
29145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *server_protos = core_->state().server_protos;
29155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return core_->state().next_proto_status;
29165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
29175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Connect(const CompletionCallback& callback) {
29195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterFunction("");
29205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(transport_.get());
29217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // It is an error to create an SSLClientSocket whose context has no
29227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // TransportSecurityState.
29237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DCHECK(transport_security_state_);
29245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(STATE_NONE, next_handshake_state_);
29255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(user_connect_callback_.is_null());
29265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!callback.is_null());
29275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnsureThreadIdAssigned();
29295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log_.BeginEvent(NetLog::TYPE_SSL_CONNECT);
29315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = Init();
29335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != OK) {
29345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
29355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
29365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
29375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = InitializeSSLOptions();
29395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != OK) {
29405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
29415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
29425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
29435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = InitializeSSLPeerName();
29455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != OK) {
29465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
29475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
29485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
29495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GotoState(STATE_HANDSHAKE);
29515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = DoHandshakeLoop(OK);
29535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv == ERR_IO_PENDING) {
29545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_connect_callback_ = callback;
29555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
29565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
29575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
29585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LeaveFunction("");
29605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv > OK ? OK : rv;
29615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
29625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Disconnect() {
29645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterFunction("");
29655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(CalledOnValidThread());
29675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Shut down anything that may call us back.
29695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_->Detach();
29705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  verifier_.reset();
29715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transport_->socket()->Disconnect();
29725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Reset object state.
29745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_connect_callback_.Reset();
29755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  server_cert_verify_result_.Reset();
29765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  completed_handshake_   = false;
29775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  start_cert_verification_time_ = base::TimeTicks();
29785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InitCore();
29795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LeaveFunction("");
29815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
29825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketNSS::IsConnected() const {
29845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterFunction("");
29852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool ret = completed_handshake_ &&
29862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             (core_->HasPendingAsyncOperation() ||
29872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              (core_->IsConnected() && core_->HasUnhandledReceivedData()) ||
29882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              transport_->socket()->IsConnected());
29895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LeaveFunction("");
29905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ret;
29915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
29925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketNSS::IsConnectedAndIdle() const {
29945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterFunction("");
29952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool ret = completed_handshake_ &&
29962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             !core_->HasPendingAsyncOperation() &&
29972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             !(core_->IsConnected() && core_->HasUnhandledReceivedData()) &&
29982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             transport_->socket()->IsConnectedAndIdle();
29995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LeaveFunction("");
30005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ret;
30015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
30025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::GetPeerAddress(IPEndPoint* address) const {
30045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return transport_->socket()->GetPeerAddress(address);
30055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
30065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::GetLocalAddress(IPEndPoint* address) const {
30085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return transport_->socket()->GetLocalAddress(address);
30095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
30105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const BoundNetLog& SSLClientSocketNSS::NetLog() const {
30125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return net_log_;
30135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
30145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::SetSubresourceSpeculation() {
30165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (transport_.get() && transport_->socket()) {
30175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    transport_->socket()->SetSubresourceSpeculation();
30185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
30195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
30205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
30215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
30225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::SetOmniboxSpeculation() {
30245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (transport_.get() && transport_->socket()) {
30255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    transport_->socket()->SetOmniboxSpeculation();
30265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
30275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
30285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
30295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
30305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketNSS::WasEverUsed() const {
30325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (transport_.get() && transport_->socket()) {
30335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return transport_->socket()->WasEverUsed();
30345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
30355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
30365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
30375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
30385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketNSS::UsingTCPFastOpen() const {
30405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (transport_.get() && transport_->socket()) {
30415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return transport_->socket()->UsingTCPFastOpen();
30425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
30435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
30445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
30455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
30465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Read(IOBuffer* buf, int buf_len,
30485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const CompletionCallback& callback) {
3049868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(core_.get());
30505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!callback.is_null());
30515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterFunction(buf_len);
30535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = core_->Read(buf, buf_len, callback);
30545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LeaveFunction(rv);
30555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
30575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
30585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Write(IOBuffer* buf, int buf_len,
30605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              const CompletionCallback& callback) {
3061868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(core_.get());
30625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!callback.is_null());
30635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterFunction(buf_len);
30655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = core_->Write(buf, buf_len, callback);
30665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LeaveFunction(rv);
30675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
30695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
30705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketNSS::SetReceiveBufferSize(int32 size) {
30725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return transport_->socket()->SetReceiveBufferSize(size);
30735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
30745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketNSS::SetSendBufferSize(int32 size) {
30765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return transport_->socket()->SetSendBufferSize(size);
30775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
30785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Init() {
30805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterFunction("");
30815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initialize the NSS SSL library in a threadsafe way.  This also
30825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // initializes the NSS base library.
30835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnsureNSSSSLInit();
30845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!NSS_IsInitialized())
30855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNEXPECTED;
30862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(USE_NSS) || defined(OS_IOS)
30875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ssl_config_.cert_io_enabled) {
30885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We must call EnsureNSSHttpIOInit() here, on the IO thread, to get the IO
30895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // loop by MessageLoopForIO::current().
30905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // X509Certificate::Verify() runs on a worker thread of CertVerifier.
30915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EnsureNSSHttpIOInit();
30925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
30935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
30945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LeaveFunction("");
30965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
30975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
30985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::InitCore() {
31007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  core_ = new Core(base::ThreadTaskRunnerHandle::Get().get(),
3101868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                   nss_task_runner_.get(),
3102868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                   transport_.get(),
3103868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                   host_and_port_,
3104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                   ssl_config_,
3105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                   &net_log_,
31065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   server_bound_cert_service_);
31075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
31085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::InitializeSSLOptions() {
31105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Transport connected, now hook it up to nss
31115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nss_fd_ = memio_CreateIOLayer(kRecvBufferSize, kSendBufferSize);
31125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (nss_fd_ == NULL) {
31135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_OUT_OF_MEMORY;  // TODO(port): map NSPR error code.
31145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
31155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Grab pointer to buffers
31175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memio_Private* nss_bufs = memio_GetSecret(nss_fd_);
31185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Create SSL state machine */
31205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Push SSL onto our fake I/O socket */
3121a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (SSL_ImportFD(GetNSSModelSocket(), nss_fd_) == NULL) {
31225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_ImportFD", "");
3123a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    PR_Close(nss_fd_);
3124a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    nss_fd_ = NULL;
31255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_OUT_OF_MEMORY;  // TODO(port): map NSPR/NSS error code.
31265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
31275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(port): set more ssl options!  Check errors!
31285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv;
31305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_OptionSet(nss_fd_, SSL_SECURITY, PR_TRUE);
31325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess) {
31335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_SECURITY");
31345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNEXPECTED;
31355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
31365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SSL2, PR_FALSE);
31385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess) {
31395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_SSL2");
31405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNEXPECTED;
31415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
31425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Don't do V2 compatible hellos because they don't support TLS extensions.
31445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_OptionSet(nss_fd_, SSL_V2_COMPATIBLE_HELLO, PR_FALSE);
31455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess) {
31465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_V2_COMPATIBLE_HELLO");
31475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNEXPECTED;
31485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
31495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLVersionRange version_range;
31515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  version_range.min = ssl_config_.version_min;
31525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  version_range.max = ssl_config_.version_max;
31535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_VersionRangeSet(nss_fd_, &version_range);
31545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess) {
31555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_VersionRangeSet", "");
31565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_NO_SSL_VERSIONS_ENABLED;
31575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
31585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3159a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (ssl_config_.version_fallback) {
3160a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_FALLBACK_SCSV, PR_TRUE);
3161a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (rv != SECSuccess) {
3162a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      LogFailedNSSFunction(
3163a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          net_log_, "SSL_OptionSet", "SSL_ENABLE_FALLBACK_SCSV");
3164a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
3165a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
3166a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
31675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::vector<uint16>::const_iterator it =
31685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           ssl_config_.disabled_cipher_suites.begin();
31695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != ssl_config_.disabled_cipher_suites.end(); ++it) {
31705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This will fail if the specified cipher is not implemented by NSS, but
31715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the failure is harmless.
31725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SSL_CipherPrefSet(nss_fd_, *it, PR_FALSE);
31735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
31745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Support RFC 5077
31765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SESSION_TICKETS, PR_TRUE);
31775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess) {
31785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(
31795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        net_log_, "SSL_OptionSet", "SSL_ENABLE_SESSION_TICKETS");
31805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
31815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_FALSE_START,
31834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                     ssl_config_.false_start_enabled);
31845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess)
31855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_FALSE_START");
31865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We allow servers to request renegotiation. Since we're a client,
31885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // prohibiting this is rather a waste of time. Only servers are in a
31895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // position to prevent renegotiation attacks.
31905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // http://extendedsubset.com/?p=8
31915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_RENEGOTIATION,
31935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     SSL_RENEGOTIATE_TRANSITIONAL);
31945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess) {
31955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(
31965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        net_log_, "SSL_OptionSet", "SSL_ENABLE_RENEGOTIATION");
31975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
31985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  rv = SSL_OptionSet(nss_fd_, SSL_CBC_RANDOM_IV, PR_TRUE);
32005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess)
32015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_CBC_RANDOM_IV");
32025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3203bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// Added in NSS 3.15
32045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SSL_ENABLE_OCSP_STAPLING
32055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsOCSPStaplingSupported()) {
32065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_OCSP_STAPLING, PR_TRUE);
32075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv != SECSuccess) {
32085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LogFailedNSSFunction(net_log_, "SSL_OptionSet",
32095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           "SSL_ENABLE_OCSP_STAPLING");
32105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
32115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
32125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
32135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3214a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SIGNED_CERT_TIMESTAMPS,
3215a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                     ssl_config_.signed_cert_timestamps_enabled);
3216a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (rv != SECSuccess) {
3217a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_OptionSet",
3218a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                         "SSL_ENABLE_SIGNED_CERT_TIMESTAMPS");
3219a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
3220a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
3221bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// Chromium patch to libssl
32225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SSL_ENABLE_CACHED_INFO
32235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_CACHED_INFO,
32245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     ssl_config_.cached_info_enabled);
32255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess)
32265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_CACHED_INFO");
32275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
32285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_OptionSet(nss_fd_, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE);
32305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess) {
32315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_HANDSHAKE_AS_CLIENT");
32325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNEXPECTED;
32335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
32345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!core_->Init(nss_fd_, nss_bufs))
32365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNEXPECTED;
32375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Tell SSL the hostname we're trying to connect to.
32395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSL_SetURL(nss_fd_, host_and_port_.host().c_str());
32405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Tell SSL we're a client; needed if not letting NSPR do socket I/O
32425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSL_ResetHandshake(nss_fd_, PR_FALSE);
32435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
32455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
32465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::InitializeSSLPeerName() {
32485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Tell NSS who we're connected to
32495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPEndPoint peer_address;
32505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int err = transport_->socket()->GetPeerAddress(&peer_address);
32515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (err != OK)
32525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return err;
32535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SockaddrStorage storage;
32555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!peer_address.ToSockAddr(storage.addr, &storage.addr_len))
32565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNEXPECTED;
32575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PRNetAddr peername;
32595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&peername, 0, sizeof(peername));
32605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_LE(static_cast<size_t>(storage.addr_len), sizeof(peername));
32615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t len = std::min(static_cast<size_t>(storage.addr_len),
32625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        sizeof(peername));
32635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(&peername, storage.addr, len);
32645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Adjust the address family field for BSD, whose sockaddr
32665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // structure has a one-byte length and one-byte address family
32675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // field at the beginning.  PRNetAddr has a two-byte address
32685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // family field at the beginning.
32695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  peername.raw.family = storage.addr->sa_family;
32705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memio_SetPeerName(nss_fd_, &peername);
32725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set the peer ID for session reuse.  This is necessary when we create an
32745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SSL tunnel through a proxy -- GetPeerName returns the proxy's address
32755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // rather than the destination server's address in that case.
32765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string peer_id = host_and_port_.ToString();
32775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the ssl_session_cache_shard_ is non-empty, we append it to the peer id.
32785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This will cause session cache misses between sockets with different values
32795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // of ssl_session_cache_shard_ and this is used to partition the session cache
32805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // for incognito mode.
32815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ssl_session_cache_shard_.empty()) {
32825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    peer_id += "/" + ssl_session_cache_shard_;
32835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
32845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECStatus rv = SSL_SetSockPeerID(nss_fd_, const_cast<char*>(peer_id.c_str()));
32855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess)
32865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_SetSockPeerID", peer_id.c_str());
32875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
32895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
32905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::DoConnectCallback(int rv) {
32925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterFunction(rv);
32935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(ERR_IO_PENDING, rv);
32945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!user_connect_callback_.is_null());
32955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::ResetAndReturn(&user_connect_callback_).Run(rv > OK ? OK : rv);
32975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LeaveFunction("");
32985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
32995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::OnHandshakeIOComplete(int result) {
33015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterFunction(result);
33025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = DoHandshakeLoop(result);
33035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != ERR_IO_PENDING) {
33045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
33055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DoConnectCallback(rv);
33065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
33075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LeaveFunction("");
33085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
33095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::DoHandshakeLoop(int last_io_result) {
33115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterFunction(last_io_result);
33125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = last_io_result;
33135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
33145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Default to STATE_NONE for next state.
33155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // (This is a quirk carried over from the windows
33165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // implementation.  It makes reading the logs a bit harder.)
33175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // State handlers can and often do call GotoState just
33185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // to stay in the current state.
33195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    State state = next_handshake_state_;
33205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GotoState(STATE_NONE);
33215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (state) {
33225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_HANDSHAKE:
33235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoHandshake();
33245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
33255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_HANDSHAKE_COMPLETE:
33265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoHandshakeComplete(rv);
33275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
33285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_VERIFY_CERT:
33295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK(rv == OK);
33305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoVerifyCert(rv);
33315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
33325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_VERIFY_CERT_COMPLETE:
33335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoVerifyCertComplete(rv);
33345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
33355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_NONE:
33365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
33375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = ERR_UNEXPECTED;
33385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(DFATAL) << "unexpected state " << state;
33395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
33405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
33415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (rv != ERR_IO_PENDING && next_handshake_state_ != STATE_NONE);
33425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LeaveFunction("");
33435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
33445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
33455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::DoHandshake() {
33475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterFunction("");
33485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = core_->Connect(
33495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&SSLClientSocketNSS::OnHandshakeIOComplete,
33505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(this)));
33515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GotoState(STATE_HANDSHAKE_COMPLETE);
33525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LeaveFunction(rv);
33545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
33555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
33565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::DoHandshakeComplete(int result) {
33585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterFunction(result);
33595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == OK) {
33615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // SSL handshake is completed. Let's verify the certificate.
33622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GotoState(STATE_VERIFY_CERT);
33635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Done!
33645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
33655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set_channel_id_sent(core_->state().channel_id_sent);
3366a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  set_signed_cert_timestamps_received(
3367a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      !core_->state().sct_list_from_tls_extension.empty());
33685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LeaveFunction(result);
33705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
33715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
33725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::DoVerifyCert(int result) {
33745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!core_->state().server_cert_chain.empty());
33755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(core_->state().server_cert_chain[0]);
33765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GotoState(STATE_VERIFY_CERT_COMPLETE);
33785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the certificate is expected to be bad we can use the expectation as
33805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the cert status.
33815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::StringPiece der_cert(
33825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reinterpret_cast<char*>(
33835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          core_->state().server_cert_chain[0]->derCert.data),
33845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      core_->state().server_cert_chain[0]->derCert.len);
33855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CertStatus cert_status;
33865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ssl_config_.IsAllowedBadCert(der_cert, &cert_status)) {
33875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(start_cert_verification_time_.is_null());
33885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "Received an expected bad cert with status: " << cert_status;
33895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_cert_verify_result_.Reset();
33905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_cert_verify_result_.cert_status = cert_status;
33915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_cert_verify_result_.verified_cert = core_->state().server_cert;
33925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
33935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
33945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We may have failed to create X509Certificate object if we are
33965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // running inside sandbox.
3397868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!core_->state().server_cert.get()) {
33985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_cert_verify_result_.Reset();
33995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_cert_verify_result_.cert_status = CERT_STATUS_INVALID;
34005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_CERT_INVALID;
34015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
34025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  start_cert_verification_time_ = base::TimeTicks::Now();
34045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int flags = 0;
34065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ssl_config_.rev_checking_enabled)
34075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    flags |= CertVerifier::VERIFY_REV_CHECKING_ENABLED;
34085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ssl_config_.verify_ev_cert)
34095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    flags |= CertVerifier::VERIFY_EV_CERT;
34105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ssl_config_.cert_io_enabled)
34115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    flags |= CertVerifier::VERIFY_CERT_IO_ENABLED;
3412558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  if (ssl_config_.rev_checking_required_local_anchors)
3413558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    flags |= CertVerifier::VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS;
34145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  verifier_.reset(new SingleRequestCertVerifier(cert_verifier_));
34155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return verifier_->Verify(
3416868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      core_->state().server_cert.get(),
3417868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      host_and_port_.host(),
3418868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      flags,
34197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      SSLConfigService::GetCRLSet().get(),
3420868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      &server_cert_verify_result_,
34215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&SSLClientSocketNSS::OnHandshakeIOComplete,
34225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(this)),
34235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_log_);
34245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
34255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Derived from AuthCertificateCallback() in
34275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// mozilla/source/security/manager/ssl/src/nsNSSCallbacks.cpp.
34285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::DoVerifyCertComplete(int result) {
34295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  verifier_.reset();
34305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!start_cert_verification_time_.is_null()) {
34325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::TimeDelta verify_time =
34335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::TimeTicks::Now() - start_cert_verification_time_;
34345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (result == OK)
34355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        UMA_HISTOGRAM_TIMES("Net.SSLCertVerificationTime", verify_time);
34365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
34375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        UMA_HISTOGRAM_TIMES("Net.SSLCertVerificationTimeError", verify_time);
34385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
34395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We used to remember the intermediate CA certs in the NSS database
34415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // persistently.  However, NSS opens a connection to the SQLite database
34425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // during NSS initialization and doesn't close the connection until NSS
34435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // shuts down.  If the file system where the database resides is gone,
34445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the database connection goes bad.  What's worse, the connection won't
34455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // recover when the file system comes back.  Until this NSS or SQLite bug
34465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is fixed, we need to  avoid using the NSS database for non-essential
34475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // purposes.  See https://bugzilla.mozilla.org/show_bug.cgi?id=508081 and
34485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // http://crbug.com/15630 for more info.
34495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(hclam): Skip logging if server cert was expected to be bad because
34515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |server_cert_verify_result_| doesn't contain all the information about
34525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the cert.
34535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == OK)
34545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogConnectionTypeMetrics();
34555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OFFICIAL_BUILD) && !defined(OS_ANDROID) && !defined(OS_IOS)
34575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Take care of any mandates for public key pinning.
34585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
34595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Pinning is only enabled for official builds to make sure that others don't
34605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // end up with pins that cannot be easily updated.
34615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
3462c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // TODO(agl): We might have an issue here where a request for foo.example.com
34635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // merges into a SPDY connection to www.example.com, and gets a different
34645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // certificate.
34655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3466c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Perform pin validation if, and only if, all these conditions obtain:
3467c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  //
3468c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // * a TransportSecurityState object is available;
3469c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // * the server's certificate chain is valid (or suffers from only a minor
3470c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  //   error);
3471c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // * the server's certificate chain chains up to a known root (i.e. not a
3472c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  //   user-installed trust anchor); and
3473c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // * the build is recent (very old builds should fail open so that users
3474c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  //   have some chance to recover).
3475c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  //
34765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const CertStatus cert_status = server_cert_verify_result_.cert_status;
3477c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (transport_security_state_ &&
3478c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      (result == OK ||
3479c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       (IsCertificateError(result) && IsCertStatusMinorError(cert_status))) &&
34805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      server_cert_verify_result_.is_issued_by_known_root &&
3481c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      TransportSecurityState::IsBuildTimely()) {
34825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool sni_available =
34835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ssl_config_.version_max >= SSL_PROTOCOL_VERSION_TLS1 ||
34845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ssl_config_.version_fallback;
34855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& host = host_and_port_.host();
34865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TransportSecurityState::DomainState domain_state;
34885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (transport_security_state_->GetDomainState(host, sni_available,
34895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  &domain_state) &&
34902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        domain_state.HasPublicKeyPins()) {
34912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!domain_state.CheckPublicKeyPins(
3492c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)              server_cert_verify_result_.public_key_hashes)) {
3493c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        result = ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN;
3494c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        UMA_HISTOGRAM_BOOLEAN("Net.PublicKeyPinSuccess", false);
3495c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        TransportSecurityState::ReportUMAOnPinFailure(host);
34965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
34975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        UMA_HISTOGRAM_BOOLEAN("Net.PublicKeyPinSuccess", true);
34985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
34995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
35005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
35015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
35025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3503a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (result == OK) {
3504a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // Only check Certificate Transparency if there were no other errors with
3505a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // the connection.
3506a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    VerifyCT();
3507a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
3508a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
3509a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  completed_handshake_ = true;
3510a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
35115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Exit DoHandshakeLoop and return the result to the caller to Connect.
35125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(STATE_NONE, next_handshake_state_);
35135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
35145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
35155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3516a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void SSLClientSocketNSS::VerifyCT() {
3517a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!cert_transparency_verifier_)
3518a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return;
3519a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
3520a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Note that this is a completely synchronous operation: The CT Log Verifier
3521a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // gets all the data it needs for SCT verification and does not do any
3522a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // external communication.
3523a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  int result = cert_transparency_verifier_->Verify(
3524a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      server_cert_verify_result_.verified_cert,
3525a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      std::string(), // SCT list from OCSP response
3526a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      core_->state().sct_list_from_tls_extension,
3527a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      &ct_verify_result_,
3528a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      net_log_);
3529a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
3530a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  VLOG(1) << "CT Verification complete: result " << result
3531a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          << " Invalid scts: " << ct_verify_result_.invalid_scts.size()
3532a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          << " Verified scts: " << ct_verify_result_.verified_scts.size()
3533a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          << " scts from unknown logs: "
3534a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          << ct_verify_result_.unknown_logs_scts.size();
3535a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
3536a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
35375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::LogConnectionTypeMetrics() const {
35385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdateConnectionTypeHistograms(CONNECTION_SSL);
35395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ssl_version = SSLConnectionStatusToVersion(
35405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      core_->state().ssl_connection_status);
35415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (ssl_version) {
35425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_CONNECTION_VERSION_SSL2:
35435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UpdateConnectionTypeHistograms(CONNECTION_SSL_SSL2);
35445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
35455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_CONNECTION_VERSION_SSL3:
35465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UpdateConnectionTypeHistograms(CONNECTION_SSL_SSL3);
35475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
35485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_CONNECTION_VERSION_TLS1:
35495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UpdateConnectionTypeHistograms(CONNECTION_SSL_TLS1);
35505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
35515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_CONNECTION_VERSION_TLS1_1:
35525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UpdateConnectionTypeHistograms(CONNECTION_SSL_TLS1_1);
35535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
35545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_CONNECTION_VERSION_TLS1_2:
35555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UpdateConnectionTypeHistograms(CONNECTION_SSL_TLS1_2);
35565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
35575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
35585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
35595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::EnsureThreadIdAssigned() const {
35615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock auto_lock(lock_);
35625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (valid_thread_id_ != base::kInvalidThreadId)
35635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
35645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  valid_thread_id_ = base::PlatformThread::CurrentId();
35655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
35665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketNSS::CalledOnValidThread() const {
35685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnsureThreadIdAssigned();
35695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock auto_lock(lock_);
35705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return valid_thread_id_ == base::PlatformThread::CurrentId();
35715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
35725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3573a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void SSLClientSocketNSS::AddSCTInfoToSSLInfo(SSLInfo* ssl_info) const {
3574a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  for (ct::SCTList::const_iterator iter =
3575a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)       ct_verify_result_.verified_scts.begin();
3576a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)       iter != ct_verify_result_.verified_scts.end(); ++iter) {
3577a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ssl_info->signed_certificate_timestamps.push_back(
3578a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        SignedCertificateTimestampAndStatus(*iter, ct::SCT_STATUS_OK));
3579a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
3580a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  for (ct::SCTList::const_iterator iter =
3581a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)       ct_verify_result_.invalid_scts.begin();
3582a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)       iter != ct_verify_result_.invalid_scts.end(); ++iter) {
3583a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ssl_info->signed_certificate_timestamps.push_back(
3584a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        SignedCertificateTimestampAndStatus(*iter, ct::SCT_STATUS_INVALID));
3585a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
3586a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  for (ct::SCTList::const_iterator iter =
3587a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)       ct_verify_result_.unknown_logs_scts.begin();
3588a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)       iter != ct_verify_result_.unknown_logs_scts.end(); ++iter) {
3589a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ssl_info->signed_certificate_timestamps.push_back(
3590a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        SignedCertificateTimestampAndStatus(*iter,
3591a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                            ct::SCT_STATUS_LOG_UNKNOWN));
3592a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
3593a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
3594a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
35955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ServerBoundCertService* SSLClientSocketNSS::GetServerBoundCertService() const {
35965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return server_bound_cert_service_;
35975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
35985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
3600