ssl_client_socket_nss.cc revision effb81e5f8246d0db0270817048dc992db66e9fb
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file includes code SSLClientSocketNSS::DoVerifyCertComplete() derived
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// from AuthCertificateCallback() in
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// mozilla/security/manager/ssl/src/nsNSSCallbacks.cpp.
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* ***** BEGIN LICENSE BLOCK *****
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Version: MPL 1.1/GPL 2.0/LGPL 2.1
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The contents of this file are subject to the Mozilla Public License Version
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1.1 (the "License"); you may not use this file except in compliance with
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the License. You may obtain a copy of the License at
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * http://www.mozilla.org/MPL/
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Software distributed under the License is distributed on an "AS IS" basis,
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * for the specific language governing rights and limitations under the
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * License.
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The Original Code is the Netscape security libraries.
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The Initial Developer of the Original Code is
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Netscape Communications Corporation.
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Portions created by the Initial Developer are Copyright (C) 2000
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the Initial Developer. All Rights Reserved.
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Contributor(s):
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *   Ian McGreer <mcgreer@netscape.com>
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *   Javier Delgadillo <javi@netscape.com>
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *   Kai Engert <kengert@redhat.com>
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Alternatively, the contents of this file may be used under the terms of
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * either the GNU General Public License Version 2 or later (the "GPL"), or
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * in which case the provisions of the GPL or the LGPL are applicable instead
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * of those above. If you wish to allow use of your version of this file only
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * under the terms of either the GPL or the LGPL, and not to allow others to
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * use your version of this file under the terms of the MPL, indicate your
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * decision by deleting the provisions above and replace them with the notice
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * and other provisions required by the GPL or the LGPL. If you do not delete
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the provisions above, a recipient may use your version of this file under
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the terms of any one of the MPL, the GPL or the LGPL.
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ***** END LICENSE BLOCK ***** */
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/ssl_client_socket_nss.h"
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <certdb.h>
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <hasht.h>
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <keyhi.h>
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <nspr.h>
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <nss.h>
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <ocsp.h>
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <pk11pub.h>
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <secerr.h>
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sechash.h>
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <ssl.h>
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sslerr.h>
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sslproto.h>
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <limits>
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map>
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h"
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback_helpers.h"
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/singleton.h"
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h"
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/single_thread_task_runner.h"
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
765e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
775e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h"
785e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/stringprintf.h"
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/thread_task_runner_handle.h"
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread_restrictions.h"
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/ec_private_key.h"
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/nss_util.h"
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/nss_util_internal.h"
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/rsa_private_key.h"
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/scoped_nss_types.h"
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/address_list.h"
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/connection_type_histograms.h"
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/dns_util.h"
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/io_buffer.h"
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h"
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_log.h"
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/asn1_util.h"
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/cert_status_flags.h"
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/cert_verifier.h"
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/cert/ct_objects_extractor.h"
97a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/cert/ct_verifier.h"
98a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/cert/ct_verify_result.h"
99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "net/cert/scoped_nss_types.h"
100a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/cert/sct_status_flags.h"
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/single_request_cert_verifier.h"
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/x509_certificate_net_log_param.h"
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/x509_util.h"
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/http/transport_security_state.h"
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/ocsp/nss_ocsp.h"
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/client_socket_handle.h"
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/nss_ssl_util.h"
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/ssl_error_params.h"
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/ssl/ssl_cert_request_info.h"
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/ssl/ssl_connection_status_flags.h"
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/ssl/ssl_info.h"
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h>
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <wincrypt.h>
11690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
11790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/win/windows_version.h"
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_MACOSX)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <Security/SecBase.h>
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <Security/SecCertificate.h>
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <Security/SecIdentity.h>
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/mac/mac_logging.h"
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/synchronization/lock.h"
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "crypto/mac_security_services_lock.h"
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(USE_NSS)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <dlfcn.h>
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace net {
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// State machines are easier to debug if you log state transitions.
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Enable these if you want to see what's going on.
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if 1
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define EnterFunction(x)
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define LeaveFunction(x)
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define GotoState(s) next_handshake_state_ = s
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define EnterFunction(x)\
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VLOG(1) << (void *)this << " " << __FUNCTION__ << " enter " << x\
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            << "; next_handshake_state " << next_handshake_state_
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define LeaveFunction(x)\
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VLOG(1) << (void *)this << " " << __FUNCTION__ << " leave " << x\
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            << "; next_handshake_state " << next_handshake_state_
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define GotoState(s)\
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    do {\
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      VLOG(1) << (void *)this << " " << __FUNCTION__ << " jump to state " << s;\
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      next_handshake_state_ = s;\
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } while (0)
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SSL plaintext fragments are shorter than 16KB. Although the record layer
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// overhead is allowed to be 2K + 5 bytes, in practice the overhead is much
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// smaller than 1KB. So a 17KB buffer should be large enough to hold an
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// entire SSL record.
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kRecvBufferSize = 17 * 1024;
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kSendBufferSize = 17 * 1024;
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Used by SSLClientSocketNSS::Core to indicate there is no read result
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// obtained by a previous operation waiting to be returned to the caller.
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This constant can be any non-negative/non-zero value (eg: it does not
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// overlap with any value of the net::Error range, including net::OK).
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kNoPendingReadResult = 1;
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CERT_OCSP_RESPONSE_PROP_ID is only implemented on Vista+, but it can be
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// set on Windows XP without error. There is some overhead from the server
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// sending the OCSP response if it supports the extension, for the subset of
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// XP clients who will request it but be unable to use it, but this is an
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// acceptable trade-off for simplicity of implementation.
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool IsOCSPStaplingSupported() {
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(USE_NSS)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef SECStatus
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)(*CacheOCSPResponseFromSideChannelFunction)(
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CERTCertDBHandle *handle, CERTCertificate *cert, PRTime time,
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECItem *encodedResponse, void *pwArg);
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// On Linux, we dynamically link against the system version of libnss3.so. In
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// order to continue working on systems without up-to-date versions of NSS we
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// lookup CERT_CacheOCSPResponseFromSideChannel with dlsym.
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// RuntimeLibNSSFunctionPointers is a singleton which caches the results of any
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// runtime symbol resolution that we need.
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class RuntimeLibNSSFunctionPointers {
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CacheOCSPResponseFromSideChannelFunction
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetCacheOCSPResponseFromSideChannelFunction() {
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return cache_ocsp_response_from_side_channel_;
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static RuntimeLibNSSFunctionPointers* GetInstance() {
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return Singleton<RuntimeLibNSSFunctionPointers>::get();
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend struct DefaultSingletonTraits<RuntimeLibNSSFunctionPointers>;
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RuntimeLibNSSFunctionPointers() {
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cache_ocsp_response_from_side_channel_ =
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (CacheOCSPResponseFromSideChannelFunction)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dlsym(RTLD_DEFAULT, "CERT_CacheOCSPResponseFromSideChannel");
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CacheOCSPResponseFromSideChannelFunction
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cache_ocsp_response_from_side_channel_;
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)CacheOCSPResponseFromSideChannelFunction
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GetCacheOCSPResponseFromSideChannelFunction() {
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return RuntimeLibNSSFunctionPointers::GetInstance()
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ->GetCacheOCSPResponseFromSideChannelFunction();
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool IsOCSPStaplingSupported() {
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetCacheOCSPResponseFromSideChannelFunction() != NULL;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(agl): Figure out if we can plumb the OCSP response into Mac's system
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// certificate validation functions.
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool IsOCSPStaplingSupported() {
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This callback is intended to be used with CertFindChainInStore. In addition
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to filtering by extended/enhanced key usage, we do not show expired
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// certificates and require digital signature usage in the key usage
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// extension.
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This matches our behavior on Mac OS X and that of NSS. It also matches the
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// default behavior of IE8. See http://support.microsoft.com/kb/890326 and
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (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
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BOOL WINAPI ClientCertFindCallback(PCCERT_CONTEXT cert_context,
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   void* find_arg) {
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "Calling ClientCertFindCallback from _nss";
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify the certificate's KU is good.
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BYTE key_usage;
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (CertGetIntendedKeyUsage(X509_ASN_ENCODING, cert_context->pCertInfo,
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              &key_usage, 1)) {
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!(key_usage & CERT_DIGITAL_SIGNATURE_KEY_USAGE))
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return FALSE;
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DWORD err = GetLastError();
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If |err| is non-zero, it's an actual error. Otherwise the extension
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // just isn't present, and we treat it as if everything was allowed.
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (err) {
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DLOG(ERROR) << "CertGetIntendedKeyUsage failed: " << err;
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return FALSE;
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify the current time is within the certificate's validity period.
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (CertVerifyTimeValidity(NULL, cert_context->pCertInfo) != 0)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return FALSE;
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify private key metadata is associated with this certificate.
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD size = 0;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!CertGetCertificateContextProperty(
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          cert_context, CERT_KEY_PROV_INFO_PROP_ID, NULL, &size)) {
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return FALSE;
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TRUE;
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper functions to make it possible to log events from within the
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SSLClientSocketNSS::Core.
276868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void AddLogEvent(const base::WeakPtr<BoundNetLog>& net_log,
277868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                 NetLog::EventType event_type) {
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!net_log)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log->AddEvent(event_type);
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper function to make it possible to log events from within the
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SSLClientSocketNSS::Core.
285868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void AddLogEventWithCallback(const base::WeakPtr<BoundNetLog>& net_log,
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             NetLog::EventType event_type,
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const NetLog::ParametersCallback& callback) {
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!net_log)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log->AddEvent(event_type, callback);
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper function to make it easier to call BoundNetLog::AddByteTransferEvent
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// from within the SSLClientSocketNSS::Core.
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// AddByteTransferEvent expects to receive a const char*, which within the
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Core is backed by an IOBuffer. If the "const char*" is bound via
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// base::Bind and posted to another thread, and the IOBuffer that backs that
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// pointer then goes out of scope on the origin thread, this would result in
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// an invalid read of a stale pointer.
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Instead, provide a signature that accepts an IOBuffer*, so that a reference
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to the owning IOBuffer can be bound to the Callback. This ensures that the
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// IOBuffer will stay alive long enough to cross threads if needed.
303868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void LogByteTransferEvent(
304868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const base::WeakPtr<BoundNetLog>& net_log, NetLog::EventType event_type,
305868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int len, IOBuffer* buffer) {
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!net_log)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log->AddByteTransferEvent(event_type, len, buffer->data());
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// PeerCertificateChain is a helper object which extracts the certificate
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// chain, as given by the server, from an NSS socket and performs the needed
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// resource management. The first element of the chain is the leaf certificate
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and the other elements are in the order given by the server.
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PeerCertificateChain {
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PeerCertificateChain() {}
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PeerCertificateChain(const PeerCertificateChain& other);
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~PeerCertificateChain();
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PeerCertificateChain& operator=(const PeerCertificateChain& other);
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Resets the current chain, freeing any resources, and updates the current
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // chain to be a copy of the chain stored in |nss_fd|.
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If |nss_fd| is NULL, then the current certificate chain will be freed.
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Reset(PRFileDesc* nss_fd);
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns the current certificate chain as a vector of DER-encoded
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // base::StringPieces. The returned vector remains valid until Reset is
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // called.
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<base::StringPiece> AsStringPieceVector() const;
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool empty() const { return certs_.empty(); }
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CERTCertificate* operator[](size_t index) const {
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_LT(index, certs_.size());
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return certs_[index];
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<CERTCertificate*> certs_;
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PeerCertificateChain::PeerCertificateChain(
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const PeerCertificateChain& other) {
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *this = other;
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PeerCertificateChain::~PeerCertificateChain() {
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Reset(NULL);
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PeerCertificateChain& PeerCertificateChain::operator=(
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const PeerCertificateChain& other) {
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (this == &other)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return *this;
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Reset(NULL);
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  certs_.reserve(other.certs_.size());
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < other.certs_.size(); ++i)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    certs_.push_back(CERT_DupCertificate(other.certs_[i]));
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return *this;
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PeerCertificateChain::Reset(PRFileDesc* nss_fd) {
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < certs_.size(); ++i)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CERT_DestroyCertificate(certs_[i]);
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  certs_.clear();
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (nss_fd == NULL)
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  CERTCertList* list = SSL_PeerCertificateChain(nss_fd);
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The handshake on |nss_fd| may not have completed.
3754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (list == NULL)
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  for (CERTCertListNode* node = CERT_LIST_HEAD(list);
3794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)       !CERT_LIST_END(node, list); node = CERT_LIST_NEXT(node)) {
3804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    certs_.push_back(CERT_DupCertificate(node->cert));
3814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
3824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  CERT_DestroyCertList(list);
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::vector<base::StringPiece>
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PeerCertificateChain::AsStringPieceVector() const {
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<base::StringPiece> v(certs_.size());
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (unsigned i = 0; i < certs_.size(); i++) {
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v[i] = base::StringPiece(
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        reinterpret_cast<const char*>(certs_[i]->derCert.data),
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        certs_[i]->derCert.len);
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return v;
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// HandshakeState is a helper struct used to pass handshake state between
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the NSS task runner and the network task runner.
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// It contains members that may be read or written on the NSS task runner,
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// but which also need to be read from the network task runner. The NSS task
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// runner will notify the network task runner whenever this state changes, so
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that the network task runner can safely make a copy, which avoids the need
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// for locking.
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct HandshakeState {
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HandshakeState() { Reset(); }
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Reset() {
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_proto_status = SSLClientSocket::kNextProtoUnsupported;
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_proto.clear();
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_protos.clear();
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    channel_id_sent = false;
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_cert_chain.Reset(NULL);
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_cert = NULL;
415a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    sct_list_from_tls_extension.clear();
4165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    stapled_ocsp_response.clear();
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    resumed_handshake = false;
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ssl_connection_status = 0;
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set to kNextProtoNegotiated if NPN was successfully negotiated, with the
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // negotiated protocol stored in |next_proto|.
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLClientSocket::NextProtoStatus next_proto_status;
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string next_proto;
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the server supports NPN, the protocols supported by the server.
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string server_protos;
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // True if a channel ID was sent.
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool channel_id_sent;
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // List of DER-encoded X.509 DistinguishedName of certificate authorities
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // allowed by the server.
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<std::string> cert_authorities;
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set when the handshake fully completes.
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The server certificate is first received from NSS as an NSS certificate
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // chain (|server_cert_chain|) and then converted into a platform-specific
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // X509Certificate object (|server_cert|). It's possible for some
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // certificates to be successfully parsed by NSS, and not by the platform
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // libraries (i.e.: when running within a sandbox, different parsing
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // algorithms, etc), so it's not safe to assume that |server_cert| will
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // always be non-NULL.
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PeerCertificateChain server_cert_chain;
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<X509Certificate> server_cert;
446a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // SignedCertificateTimestampList received via TLS extension (RFC 6962).
447a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  std::string sct_list_from_tls_extension;
4485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Stapled OCSP response received.
4495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string stapled_ocsp_response;
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // True if the current handshake was the result of TLS session resumption.
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool resumed_handshake;
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The negotiated security parameters (TLS version, cipher, extensions) of
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the SSL connection.
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ssl_connection_status;
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Client-side error mapping functions.
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Map NSS error code to network error code.
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int MapNSSClientError(PRErrorCode err) {
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (err) {
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_ERROR_BAD_CERT_ALERT:
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_ERROR_UNSUPPORTED_CERT_ALERT:
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_ERROR_REVOKED_CERT_ALERT:
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_ERROR_EXPIRED_CERT_ALERT:
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_ERROR_CERTIFICATE_UNKNOWN_ALERT:
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_ERROR_UNKNOWN_CA_ALERT:
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_ERROR_ACCESS_DENIED_ALERT:
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ERR_BAD_SSL_CLIENT_AUTH_CERT;
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return MapNSSError(err);
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Map NSS error code from the first SSL handshake to network error code.
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int MapNSSClientHandshakeError(PRErrorCode err) {
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (err) {
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If the server closed on us, it is a protocol error.
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Some TLS-intolerant servers do this when we request TLS.
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PR_END_OF_FILE_ERROR:
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ERR_SSL_PROTOCOL_ERROR;
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return MapNSSClientError(err);
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SSLClientSocketNSS::Core provides a thread-safe, ref-counted core that is
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// able to marshal data between NSS functions and an underlying transport
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// socket.
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// All public functions are meant to be called from the network task runner,
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and any callbacks supplied will be invoked there as well, provided that
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Detach() has not been called yet.
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Threading within SSLClientSocketNSS and SSLClientSocketNSS::Core:
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Because NSS may block on either hardware or user input during operations
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// such as signing, creating certificates, or locating private keys, the Core
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// handles all of the interactions with the underlying NSS SSL socket, so
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that these blocking calls can be executed on a dedicated task runner.
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note that the network task runner and the NSS task runner may be executing
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// on the same thread. If that happens, then it's more performant to try to
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// complete as much work as possible synchronously, even if it might block,
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// rather than continually PostTask-ing to the same thread.
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Because NSS functions should only be called on the NSS task runner, while
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// I/O resources should only be accessed on the network task runner, most
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// public functions are implemented via three methods, each with different
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// task runner affinities.
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// In the single-threaded mode (where the network and NSS task runners run on
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the same thread), these are all attempted synchronously, while in the
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// multi-threaded mode, message passing is used.
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1) NSS Task Runner: Execute NSS function (DoPayloadRead, DoPayloadWrite,
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    DoHandshake)
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 2) NSS Task Runner: Prepare data to go from NSS to an IO function:
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    (BufferRecv, BufferSend)
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 3) Network Task Runner: Perform IO on that data (DoBufferRecv,
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    DoBufferSend, DoGetDomainBoundCert, OnGetDomainBoundCertComplete)
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 4) Both Task Runners: Callback for asynchronous completion or to marshal
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    data from the network task runner back to NSS (BufferRecvComplete,
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    BufferSendComplete, OnHandshakeIOComplete)
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Single-threaded example
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |--------------------------Network Task Runner--------------------------|
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  SSLClientSocketNSS              Core               (Transport Socket)
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//       Read()
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//         |-------------------------V
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                 Read()
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                   |
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                            DoPayloadRead()
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                   |
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                               BufferRecv()
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                   |
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                              DoBufferRecv()
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                   |-------------------------V
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                                           Read()
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                   V-------------------------|
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                          BufferRecvComplete()
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                   |
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                           PostOrRunCallback()
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//         V-------------------------|
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    (Read Callback)
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Multi-threaded example:
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |--------------------Network Task Runner-------------|--NSS Task Runner--|
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  SSLClientSocketNSS          Core            Socket         Core
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//       Read()
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//         |---------------------V
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                             Read()
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                               |-------------------------------V
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                                             Read()
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                                               |
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                                         DoPayloadRead()
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                                               |
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                                          BufferRecv
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                               V-------------------------------|
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                          DoBufferRecv
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                               |----------------V
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                              Read()
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                               V----------------|
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                        BufferRecvComplete()
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                               |-------------------------------V
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                                      BufferRecvComplete()
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                                               |
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                                       PostOrRunCallback()
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                               V-------------------------------|
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                        PostOrRunCallback()
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//         V---------------------|
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    (Read Callback)
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SSLClientSocketNSS::Core : public base::RefCountedThreadSafe<Core> {
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Creates a new Core.
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Any calls to NSS are executed on the |nss_task_runner|, while any calls
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // that need to operate on the underlying transport, net log, or server
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // bound certificate fetching will happen on the |network_task_runner|, so
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // that their lifetimes match that of the owning SSLClientSocketNSS.
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The caller retains ownership of |transport|, |net_log|, and
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |server_bound_cert_service|, and they will not be accessed once Detach()
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // has been called.
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Core(base::SequencedTaskRunner* network_task_runner,
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       base::SequencedTaskRunner* nss_task_runner,
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ClientSocketHandle* transport,
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       const HostPortPair& host_and_port,
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       const SSLConfig& ssl_config,
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       BoundNetLog* net_log,
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ServerBoundCertService* server_bound_cert_service);
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called on the network task runner.
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Transfers ownership of |socket|, an NSS SSL socket, and |buffers|, the
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // underlying memio implementation, to the Core. Returns true if the Core
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // was successfully registered with the socket.
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool Init(PRFileDesc* socket, memio_Private* buffers);
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called on the network task runner.
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Attempts to perform an SSL handshake. If the handshake cannot be
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // completed synchronously, returns ERR_IO_PENDING, invoking |callback| on
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the network task runner once the handshake has completed. Otherwise,
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // returns OK on success or a network error code on failure.
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int Connect(const CompletionCallback& callback);
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called on the network task runner.
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Signals that the resources owned by the network task runner are going
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // away. No further callbacks will be invoked on the network task runner.
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // May be called at any time.
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Detach();
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called on the network task runner.
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns the current state of the underlying SSL socket. May be called at
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // any time.
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HandshakeState& state() const { return network_handshake_state_; }
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called on the network task runner.
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read() and Write() mirror the net::Socket functions of the same name.
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If ERR_IO_PENDING is returned, |callback| will be invoked on the network
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // task runner at a later point, unless the caller calls Detach().
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int Read(IOBuffer* buf, int buf_len, const CompletionCallback& callback);
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int Write(IOBuffer* buf, int buf_len, const CompletionCallback& callback);
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Called on the network task runner.
638effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  bool IsConnected() const;
639effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  bool HasPendingAsyncOperation() const;
640effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  bool HasUnhandledReceivedData() const;
641effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  bool WasEverUsed() const;
6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Called on the network task runner.
6445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Causes the associated SSL/TLS session ID to be added to NSS's session
6455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // cache, but only if the connection has not been False Started.
6465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  //
6475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // This should only be called after the server's certificate has been
6485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // verified, and may not be called within an NSS callback.
6495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void CacheSessionIfNecessary();
6505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (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();
7635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Update the nss_handshake_state_ with the SignedCertificateTimestampList
7645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // received in the handshake via a TLS extension.
765a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  void UpdateSignedCertTimestamps();
7665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Update the OCSP response cache with the stapled response received in the
7675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // handshake, and update nss_handshake_state_ with
7685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // the SignedCertificateTimestampList received in the stapled OCSP response.
7695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void UpdateStapledOCSPResponse();
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Updates the nss_handshake_state_ with the negotiated security parameters.
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void UpdateConnectionStatus();
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Record histograms for channel id support during full handshakes - resumed
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // handshakes are ignored.
7741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  void RecordChannelIDSupportOnNSSTaskRunner();
775eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // UpdateNextProto gets any application-layer protocol that may have been
776eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // negotiated by the TLS connection.
777eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  void UpdateNextProto();
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////////////////////////////////////////
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Methods that are ONLY called on the network task runner:
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////////////////////////////////////////
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int DoBufferRecv(IOBuffer* buffer, int len);
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int DoBufferSend(IOBuffer* buffer, int len);
784bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  int DoGetDomainBoundCert(const std::string& host);
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnGetDomainBoundCertComplete(int result);
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnHandshakeStateUpdated(const HandshakeState& state);
7882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void OnNSSBufferUpdated(int amount_in_read_buffer);
7892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void DidNSSRead(int result);
7902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void DidNSSWrite(int result);
791b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  void RecordChannelIDSupportOnNetworkTaskRunner(
792b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      bool negotiated_channel_id,
793b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      bool channel_id_enabled,
794b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      bool supports_ecc) const;
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////////////////////////////////////////
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Methods that are called on both the network task runner and the NSS
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // task runner.
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////////////////////////////////////////
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnHandshakeIOComplete(int result);
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void BufferRecvComplete(IOBuffer* buffer, int result);
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void BufferSendComplete(int result);
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // PostOrRunCallback is a helper function to ensure that |callback| is
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // invoked on the network task runner, but only if Detach() has not yet
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // been called.
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void PostOrRunCallback(const tracked_objects::Location& location,
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         const base::Closure& callback);
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Uses PostOrRunCallback and |weak_net_log_| to try and log a
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SSL_CLIENT_CERT_PROVIDED event, with the indicated count.
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AddCertProvidedEvent(int cert_count);
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Sets the handshake state |channel_id_sent| flag and logs the
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SSL_CHANNEL_ID_PROVIDED event.
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetChannelIDProvided();
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////////////////////////////////////////
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Members that are ONLY accessed on the network task runner:
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////////////////////////////////////////
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // True if the owning SSLClientSocketNSS has called Detach(). No further
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // callbacks will be invoked nor access to members owned by the network
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // task runner.
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool detached_;
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The underlying transport to use for network IO.
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClientSocketHandle* transport_;
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WeakPtrFactory<BoundNetLog> weak_net_log_factory_;
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The current handshake state. Mirrors |nss_handshake_state_|.
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HandshakeState network_handshake_state_;
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The service for retrieving Channel ID keys.  May be NULL.
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ServerBoundCertService* server_bound_cert_service_;
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ServerBoundCertService::RequestHandle domain_bound_cert_request_handle_;
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The information about NSS task runner.
8392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int unhandled_buffer_size_;
8402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool nss_waiting_read_;
8412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool nss_waiting_write_;
8422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool nss_is_closed_;
8432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
844effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Set when Read() or Write() successfully reads or writes data to or from the
845effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // network.
846effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  bool was_ever_used_;
847effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////////////////////////////////////////
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Members that are ONLY accessed on the NSS task runner:
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////////////////////////////////////////
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HostPortPair host_and_port_;
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLConfig ssl_config_;
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NSS SSL socket.
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PRFileDesc* nss_fd_;
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Buffers for the network end of the SSL state machine
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memio_Private* nss_bufs_;
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Used by DoPayloadRead() when attempting to fill the caller's buffer with
8612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // as much data as possible, without blocking.
8622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If DoPayloadRead() encounters an error after having read some data, stores
8632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the results to return on the *next* call to DoPayloadRead(). A value of
8642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // kNoPendingReadResult indicates there is no pending result, otherwise 0
8652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // indicates EOF and < 0 indicates an error.
8662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int pending_read_result_;
8672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Contains the previously observed NSS error. Only valid when
8682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // pending_read_result_ != kNoPendingReadResult.
8692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PRErrorCode pending_read_nss_error_;
8702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The certificate chain, in DER form, that is expected to be received from
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the server.
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> predicted_certs_;
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  State next_handshake_state_;
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // True if channel ID extension was negotiated.
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool channel_id_xtn_negotiated_;
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // True if the handshake state machine was interrupted for channel ID.
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool channel_id_needed_;
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // True if the handshake state machine was interrupted for client auth.
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool client_auth_cert_needed_;
883f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // True if NSS has False Started.
884f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  bool false_started_;
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // True if NSS has called HandshakeCallback.
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool handshake_callback_called_;
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HandshakeState nss_handshake_state_;
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool transport_recv_busy_;
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool transport_recv_eof_;
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool transport_send_busy_;
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Used by Read function.
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<IOBuffer> user_read_buf_;
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int user_read_buf_len_;
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Used by Write function.
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<IOBuffer> user_write_buf_;
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int user_write_buf_len_;
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CompletionCallback user_connect_callback_;
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CompletionCallback user_read_callback_;
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CompletionCallback user_write_callback_;
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////////////////////////////////////////
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Members that are accessed on both the network task runner and the NSS
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // task runner.
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////////////////////////////////////////
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<base::SequencedTaskRunner> network_task_runner_;
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<base::SequencedTaskRunner> nss_task_runner_;
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Dereferenced only on the network task runner, but bound to tasks destined
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // for the network task runner from the NSS task runner.
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WeakPtr<BoundNetLog> weak_net_log_;
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Written on the network task runner by the |server_bound_cert_service_|,
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // prior to invoking OnHandshakeIOComplete.
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read on the NSS task runner when once OnHandshakeIOComplete is invoked
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // on the NSS task runner.
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string domain_bound_private_key_;
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string domain_bound_cert_;
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(Core);
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SSLClientSocketNSS::Core::Core(
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::SequencedTaskRunner* network_task_runner,
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::SequencedTaskRunner* nss_task_runner,
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ClientSocketHandle* transport,
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const HostPortPair& host_and_port,
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SSLConfig& ssl_config,
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BoundNetLog* net_log,
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ServerBoundCertService* server_bound_cert_service)
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : detached_(false),
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      transport_(transport),
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      weak_net_log_factory_(net_log),
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      server_bound_cert_service_(server_bound_cert_service),
9392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      unhandled_buffer_size_(0),
9402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      nss_waiting_read_(false),
9412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      nss_waiting_write_(false),
9422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      nss_is_closed_(false),
943effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      was_ever_used_(false),
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      host_and_port_(host_and_port),
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ssl_config_(ssl_config),
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nss_fd_(NULL),
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nss_bufs_(NULL),
9482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      pending_read_result_(kNoPendingReadResult),
9492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      pending_read_nss_error_(0),
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next_handshake_state_(STATE_NONE),
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      channel_id_xtn_negotiated_(false),
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      channel_id_needed_(false),
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      client_auth_cert_needed_(false),
954f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      false_started_(false),
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      handshake_callback_called_(false),
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      transport_recv_busy_(false),
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      transport_recv_eof_(false),
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      transport_send_busy_(false),
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      user_read_buf_len_(0),
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      user_write_buf_len_(0),
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      network_task_runner_(network_task_runner),
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nss_task_runner_(nss_task_runner),
963bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      weak_net_log_(weak_net_log_factory_.GetWeakPtr()) {
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SSLClientSocketNSS::Core::~Core() {
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(wtc): Send SSL close_notify alert.
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (nss_fd_ != NULL) {
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PR_Close(nss_fd_);
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nss_fd_ = NULL;
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketNSS::Core::Init(PRFileDesc* socket,
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    memio_Private* buffers) {
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNetworkTaskRunner());
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!nss_fd_);
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!nss_bufs_);
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nss_fd_ = socket;
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nss_bufs_ = buffers;
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECStatus rv = SECSuccess;
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ssl_config_.next_protos.empty()) {
986eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    size_t wire_length = 0;
987eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    for (std::vector<std::string>::const_iterator
988eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch         i = ssl_config_.next_protos.begin();
989eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch         i != ssl_config_.next_protos.end(); ++i) {
990eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if (i->size() > 255) {
991eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        LOG(WARNING) << "Ignoring overlong NPN/ALPN protocol: " << *i;
992eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        continue;
993eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      }
994eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      wire_length += i->size();
995eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      wire_length++;
996eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
997eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_ptr<uint8[]> wire_protos(new uint8[wire_length]);
998eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    uint8* dst = wire_protos.get();
999eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    for (std::vector<std::string>::const_iterator
1000eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch         i = ssl_config_.next_protos.begin();
1001eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch         i != ssl_config_.next_protos.end(); i++) {
1002eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if (i->size() > 255)
1003eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        continue;
1004eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      *dst++ = i->size();
1005eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      memcpy(dst, i->data(), i->size());
1006eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      dst += i->size();
1007eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
1008eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    DCHECK_EQ(dst, wire_protos.get() + wire_length);
1009eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    rv = SSL_SetNextProtoNego(nss_fd_, wire_protos.get(), wire_length);
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv != SECSuccess)
10115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      LogFailedNSSFunction(*weak_net_log_, "SSL_SetNextProtoNego", "");
10125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_ALPN, PR_TRUE);
10135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (rv != SECSuccess)
10145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      LogFailedNSSFunction(*weak_net_log_, "SSL_OptionSet", "SSL_ENABLE_ALPN");
10155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_NPN, PR_TRUE);
10165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (rv != SECSuccess)
10175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      LogFailedNSSFunction(*weak_net_log_, "SSL_OptionSet", "SSL_ENABLE_NPN");
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_AuthCertificateHook(
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nss_fd_, SSLClientSocketNSS::Core::OwnAuthCertHandler, this);
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess) {
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(*weak_net_log_, "SSL_AuthCertificateHook", "");
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(NSS_PLATFORM_CLIENT_AUTH)
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_GetPlatformClientAuthDataHook(
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nss_fd_, SSLClientSocketNSS::Core::PlatformClientAuthHandler,
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this);
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_GetClientAuthDataHook(
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nss_fd_, SSLClientSocketNSS::Core::ClientAuthHandler, this);
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess) {
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(*weak_net_log_, "SSL_GetClientAuthDataHook", "");
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (IsChannelIDEnabled(ssl_config_, server_bound_cert_service_)) {
10411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    rv = SSL_SetClientChannelIDCallback(
10421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        nss_fd_, SSLClientSocketNSS::Core::ClientChannelIDHandler, this);
10431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (rv != SECSuccess) {
10441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      LogFailedNSSFunction(
10451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          *weak_net_log_, "SSL_SetClientChannelIDCallback", "");
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1049f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  rv = SSL_SetCanFalseStartCallback(
1050f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      nss_fd_, SSLClientSocketNSS::Core::CanFalseStartCallback, this);
1051f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (rv != SECSuccess) {
1052f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    LogFailedNSSFunction(*weak_net_log_, "SSL_SetCanFalseStartCallback", "");
1053f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return false;
1054f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
1055f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_HandshakeCallback(
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nss_fd_, SSLClientSocketNSS::Core::HandshakeCallback, this);
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess) {
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(*weak_net_log_, "SSL_HandshakeCallback", "");
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Core::Connect(const CompletionCallback& callback) {
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!OnNSSTaskRunner()) {
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!detached_);
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool posted = nss_task_runner_->PostTask(
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(IgnoreResult(&Core::Connect), this, callback));
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return posted ? ERR_IO_PENDING : ERR_ABORTED;
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(STATE_NONE, next_handshake_state_);
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(user_read_callback_.is_null());
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(user_write_callback_.is_null());
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(user_connect_callback_.is_null());
1080868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!user_read_buf_.get());
1081868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!user_write_buf_.get());
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_handshake_state_ = STATE_HANDSHAKE;
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = DoHandshakeLoop(OK);
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv == ERR_IO_PENDING) {
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_connect_callback_ = callback;
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (rv > OK) {
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = OK;
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != ERR_IO_PENDING && !OnNetworkTaskRunner()) {
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PostOrRunCallback(FROM_HERE, base::Bind(callback, rv));
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_IO_PENDING;
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::Detach() {
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNetworkTaskRunner());
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  detached_ = true;
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transport_ = NULL;
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  weak_net_log_factory_.InvalidateWeakPtrs();
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  network_handshake_state_.Reset();
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  domain_bound_cert_request_handle_.Cancel();
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Core::Read(IOBuffer* buf, int buf_len,
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   const CompletionCallback& callback) {
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!OnNSSTaskRunner()) {
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(OnNetworkTaskRunner());
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!detached_);
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(transport_);
11162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(!nss_waiting_read_);
11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    nss_waiting_read_ = true;
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool posted = nss_task_runner_->PostTask(
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(IgnoreResult(&Core::Read), this, make_scoped_refptr(buf),
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   buf_len, callback));
11232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!posted) {
11242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      nss_is_closed_ = true;
11252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      nss_waiting_read_ = false;
11262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return posted ? ERR_IO_PENDING : ERR_ABORTED;
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
1131f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(false_started_ || handshake_callback_called_);
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(STATE_NONE, next_handshake_state_);
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(user_read_callback_.is_null());
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(user_connect_callback_.is_null());
1135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!user_read_buf_.get());
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(nss_bufs_);
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_read_buf_ = buf;
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_read_buf_len_ = buf_len;
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = DoReadLoop(OK);
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv == ERR_IO_PENDING) {
11432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (OnNetworkTaskRunner())
11442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      nss_waiting_read_ = true;
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_read_callback_ = callback;
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_read_buf_ = NULL;
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_read_buf_len_ = 0;
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!OnNetworkTaskRunner()) {
11512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      PostOrRunCallback(FROM_HERE, base::Bind(&Core::DidNSSRead, this, rv));
11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PostOrRunCallback(FROM_HERE, base::Bind(callback, rv));
11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ERR_IO_PENDING;
11542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
11552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DCHECK(!nss_waiting_read_);
1156effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      if (rv <= 0) {
11572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        nss_is_closed_ = true;
1158effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      } else {
1159effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        was_ever_used_ = true;
1160effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      }
11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Core::Write(IOBuffer* buf, int buf_len,
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    const CompletionCallback& callback) {
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!OnNSSTaskRunner()) {
11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(OnNetworkTaskRunner());
11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!detached_);
11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(transport_);
11732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(!nss_waiting_write_);
11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    nss_waiting_write_ = true;
11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool posted = nss_task_runner_->PostTask(
11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(IgnoreResult(&Core::Write), this, make_scoped_refptr(buf),
11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   buf_len, callback));
11802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!posted) {
11812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      nss_is_closed_ = true;
11822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      nss_waiting_write_ = false;
11832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
11842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return posted ? ERR_IO_PENDING : ERR_ABORTED;
11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
1188f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(false_started_ || handshake_callback_called_);
11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(STATE_NONE, next_handshake_state_);
11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(user_write_callback_.is_null());
11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(user_connect_callback_.is_null());
1192868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!user_write_buf_.get());
11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(nss_bufs_);
11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_write_buf_ = buf;
11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_write_buf_len_ = buf_len;
11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = DoWriteLoop(OK);
11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv == ERR_IO_PENDING) {
12002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (OnNetworkTaskRunner())
12012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      nss_waiting_write_ = true;
12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_write_callback_ = callback;
12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_write_buf_ = NULL;
12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_write_buf_len_ = 0;
12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!OnNetworkTaskRunner()) {
12082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      PostOrRunCallback(FROM_HERE, base::Bind(&Core::DidNSSWrite, this, rv));
12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PostOrRunCallback(FROM_HERE, base::Bind(callback, rv));
12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ERR_IO_PENDING;
12112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
12122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DCHECK(!nss_waiting_write_);
1213effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      if (rv < 0) {
12142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        nss_is_closed_ = true;
1215effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      } else if (rv > 0) {
1216effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        was_ever_used_ = true;
1217effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      }
12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1224effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochbool SSLClientSocketNSS::Core::IsConnected() const {
12252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(OnNetworkTaskRunner());
12262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return !nss_is_closed_;
12272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
12282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1229effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochbool SSLClientSocketNSS::Core::HasPendingAsyncOperation() const {
12302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(OnNetworkTaskRunner());
12312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return nss_waiting_read_ || nss_waiting_write_;
12322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
12332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1234effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochbool SSLClientSocketNSS::Core::HasUnhandledReceivedData() const {
12352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(OnNetworkTaskRunner());
12362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return unhandled_buffer_size_ != 0;
12372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
12382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1239effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochbool SSLClientSocketNSS::Core::WasEverUsed() const {
1240effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK(OnNetworkTaskRunner());
1241effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return was_ever_used_;
1242effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
1243effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
12445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SSLClientSocketNSS::Core::CacheSessionIfNecessary() {
12455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // TODO(rsleevi): This should occur on the NSS task runner, due to the use of
12465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // nss_fd_. However, it happens on the network task runner in order to match
12475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // the buggy behavior of ExportKeyingMaterial.
12485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  //
12495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Once http://crbug.com/330360 is fixed, this should be moved to an
12505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // implementation that exclusively does this work on the NSS TaskRunner. This
12515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // is "safe" because it is only called during the certificate verification
12525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // state machine of the main socket, which is safe because no underlying
12535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // transport IO will be occuring in that state, and NSS will not be blocking
12545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // on any PKCS#11 related locks that might block the Network TaskRunner.
12555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(OnNetworkTaskRunner());
12565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
12575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Only cache the session if the connection was not False Started, because
12585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // sessions should only be cached *after* the peer's Finished message is
12595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // processed.
12605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // In the case of False Start, the session will be cached once the
12615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // HandshakeCallback is called, which signals the receipt and processing of
12625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // the Finished message, and which will happen during a call to
12635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // PR_Read/PR_Write.
12645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!false_started_)
12655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    SSL_CacheSession(nss_fd_);
12665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
12675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketNSS::Core::OnNSSTaskRunner() const {
12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return nss_task_runner_->RunsTasksOnCurrentThread();
12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketNSS::Core::OnNetworkTaskRunner() const {
12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return network_task_runner_->RunsTasksOnCurrentThread();
12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus SSLClientSocketNSS::Core::OwnAuthCertHandler(
12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* arg,
12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRFileDesc* socket,
12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRBool checksig,
12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRBool is_server) {
12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Core* core = reinterpret_cast<Core*>(arg);
1283f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (core->handshake_callback_called_) {
12848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // Disallow the server certificate to change in a renegotiation.
12858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    CERTCertificate* old_cert = core->nss_handshake_state_.server_cert_chain[0];
1286f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    ScopedCERTCertificate new_cert(SSL_PeerCertificate(socket));
12878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (new_cert->derCert.len != old_cert->derCert.len ||
12888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        memcmp(new_cert->derCert.data, old_cert->derCert.data,
12898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)               new_cert->derCert.len) != 0) {
12908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      // NSS doesn't have an error code that indicates the server certificate
12918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      // changed. Borrow SSL_ERROR_WRONG_CERTIFICATE (which NSS isn't using)
12928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      // for this purpose.
12938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      PORT_SetError(SSL_ERROR_WRONG_CERTIFICATE);
12948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      return SECFailure;
12958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Tell NSS to not verify the certificate.
12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SECSuccess;
13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(NSS_PLATFORM_CLIENT_AUTH)
13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus SSLClientSocketNSS::Core::PlatformClientAuthHandler(
13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* arg,
13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRFileDesc* socket,
13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CERTDistNames* ca_names,
13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CERTCertList** result_certs,
13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void** result_private_key,
13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CERTCertificate** result_nss_certificate,
13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECKEYPrivateKey** result_nss_private_key) {
13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Core* core = reinterpret_cast<Core*>(arg);
13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(core->OnNSSTaskRunner());
13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core->PostOrRunCallback(
13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&AddLogEvent, core->weak_net_log_,
13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 NetLog::TYPE_SSL_CLIENT_CERT_REQUESTED));
13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core->client_auth_cert_needed_ = !core->ssl_config_.send_client_cert;
13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (core->ssl_config_.send_client_cert) {
13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (core->ssl_config_.client_cert) {
13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PCCERT_CONTEXT cert_context =
13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          core->ssl_config_.client_cert->os_cert_handle();
13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HCRYPTPROV_OR_NCRYPT_KEY_HANDLE crypt_prov = 0;
13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DWORD key_spec = 0;
13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BOOL must_free = FALSE;
133090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      DWORD flags = 0;
133190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (base::win::GetVersion() >= base::win::VERSION_VISTA)
1332868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        flags |= CRYPT_ACQUIRE_PREFER_NCRYPT_KEY_FLAG;
133390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BOOL acquired_key = CryptAcquireCertificatePrivateKey(
133590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          cert_context, flags, NULL, &crypt_prov, &key_spec, &must_free);
13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (acquired_key) {
133890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        // Should never get a cached handle back - ownership must always be
133990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        // transferred.
134090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        CHECK_EQ(must_free, TRUE);
13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SECItem der_cert;
13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        der_cert.type = siDERCertBuffer;
13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        der_cert.data = cert_context->pbCertEncoded;
13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        der_cert.len  = cert_context->cbCertEncoded;
13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // TODO(rsleevi): Error checking for NSS allocation errors.
13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CERTCertDBHandle* db_handle = CERT_GetDefaultCertDB();
13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CERTCertificate* user_cert = CERT_NewTempCertificate(
13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            db_handle, &der_cert, NULL, PR_FALSE, PR_TRUE);
13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!user_cert) {
13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // Importing the certificate can fail for reasons including a serial
13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // number collision. See crbug.com/97355.
13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          core->AddCertProvidedEvent(0);
13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return SECFailure;
13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CERTCertList* cert_chain = CERT_NewCertList();
13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CERT_AddCertToListTail(cert_chain, user_cert);
13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Add the intermediates.
13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        X509Certificate::OSCertHandles intermediates =
13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            core->ssl_config_.client_cert->GetIntermediateCertificates();
13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (X509Certificate::OSCertHandles::const_iterator it =
13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            intermediates.begin(); it != intermediates.end(); ++it) {
13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          der_cert.data = (*it)->pbCertEncoded;
13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          der_cert.len = (*it)->cbCertEncoded;
13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          CERTCertificate* intermediate = CERT_NewTempCertificate(
13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              db_handle, &der_cert, NULL, PR_FALSE, PR_TRUE);
13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (!intermediate) {
13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            CERT_DestroyCertList(cert_chain);
13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            core->AddCertProvidedEvent(0);
13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return SECFailure;
13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          CERT_AddCertToListTail(cert_chain, intermediate);
13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        PCERT_KEY_CONTEXT key_context = reinterpret_cast<PCERT_KEY_CONTEXT>(
13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            PORT_ZAlloc(sizeof(CERT_KEY_CONTEXT)));
13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        key_context->cbSize = sizeof(*key_context);
138090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        // NSS will free this context when no longer in use.
13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        key_context->hCryptProv = crypt_prov;
13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        key_context->dwKeySpec = key_spec;
13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *result_private_key = key_context;
13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *result_certs = cert_chain;
13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int cert_count = 1 + intermediates.size();
13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        core->AddCertProvidedEvent(cert_count);
13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return SECSuccess;
13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(WARNING) << "Client cert found without private key";
13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Send no client certificate.
13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    core->AddCertProvidedEvent(0);
13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SECFailure;
13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  core->nss_handshake_state_.cert_authorities.clear();
13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<CERT_NAME_BLOB> issuer_list(ca_names->nnames);
14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < ca_names->nnames; ++i) {
14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    issuer_list[i].cbData = ca_names->names[i].len;
14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    issuer_list[i].pbData = ca_names->names[i].data;
14042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    core->nss_handshake_state_.cert_authorities.push_back(std::string(
14052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        reinterpret_cast<const char*>(ca_names->names[i].data),
14062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        static_cast<size_t>(ca_names->names[i].len)));
14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Update the network task runner's view of the handshake state now that
14102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // server certificate request has been recorded.
14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core->PostOrRunCallback(
14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE, base::Bind(&Core::OnHandshakeStateUpdated, core,
14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            core->nss_handshake_state_));
14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Tell NSS to suspend the client authentication.  We will then abort the
14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // handshake by returning ERR_SSL_CLIENT_AUTH_CERT_NEEDED.
14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SECWouldBlock;
14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_MACOSX)
14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (core->ssl_config_.send_client_cert) {
14207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (core->ssl_config_.client_cert.get()) {
14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OSStatus os_error = noErr;
14225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SecIdentityRef identity = NULL;
14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SecKeyRef private_key = NULL;
1424c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      X509Certificate::OSCertHandles chain;
1425c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      {
1426c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        base::AutoLock lock(crypto::GetMacSecurityServicesLock());
1427c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        os_error = SecIdentityCreateWithCertificate(
1428c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            NULL, core->ssl_config_.client_cert->os_cert_handle(), &identity);
14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1430c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (os_error == noErr) {
14315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        os_error = SecIdentityCopyPrivateKey(identity, &private_key);
1432c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        CFRelease(identity);
1433c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
14345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (os_error == noErr) {
14365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // TODO(rsleevi): Error checking for NSS allocation errors.
14375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *result_certs = CERT_NewCertList();
14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *result_private_key = private_key;
14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1440c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        chain.push_back(core->ssl_config_.client_cert->os_cert_handle());
1441c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        const X509Certificate::OSCertHandles& intermediates =
1442c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            core->ssl_config_.client_cert->GetIntermediateCertificates();
1443c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (!intermediates.empty())
1444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          chain.insert(chain.end(), intermediates.begin(), intermediates.end());
1445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1446c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        for (size_t i = 0, chain_count = chain.size(); i < chain_count; ++i) {
14475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          CSSM_DATA cert_data;
1448c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          SecCertificateRef cert_ref = chain[i];
14495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          os_error = SecCertificateGetData(cert_ref, &cert_data);
14505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (os_error != noErr)
14515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
14525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          SECItem der_cert;
14545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          der_cert.type = siDERCertBuffer;
14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          der_cert.data = cert_data.Data;
14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          der_cert.len = cert_data.Length;
14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          CERTCertificate* nss_cert = CERT_NewTempCertificate(
14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              CERT_GetDefaultCertDB(), &der_cert, NULL, PR_FALSE, PR_TRUE);
14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (!nss_cert) {
1460c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            // In the event of an NSS error, make up an OS error and reuse
1461c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            // the error handling below.
14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            os_error = errSecCreateChainFailed;
14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          CERT_AddCertToListTail(*result_certs, nss_cert);
14665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1468c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
14695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (os_error == noErr) {
1470c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        core->AddCertProvidedEvent(chain.size());
14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return SECSuccess;
14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1473c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OSSTATUS_LOG(WARNING, os_error)
14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << "Client cert found, but could not be used";
14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (*result_certs) {
14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CERT_DestroyCertList(*result_certs);
14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *result_certs = NULL;
14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (*result_private_key)
14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *result_private_key = NULL;
14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (private_key)
14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CFRelease(private_key);
14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Send no client certificate.
14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    core->AddCertProvidedEvent(0);
14885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SECFailure;
14895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  core->nss_handshake_state_.cert_authorities.clear();
14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Retrieve the cert issuers accepted by the server.
14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<CertPrincipal> valid_issuers;
14955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int n = ca_names->nnames;
14965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < n; i++) {
14972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    core->nss_handshake_state_.cert_authorities.push_back(std::string(
14982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        reinterpret_cast<const char*>(ca_names->names[i].data),
14992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        static_cast<size_t>(ca_names->names[i].len)));
15005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Update the network task runner's view of the handshake state now that
15032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // server certificate request has been recorded.
15045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core->PostOrRunCallback(
15055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE, base::Bind(&Core::OnHandshakeStateUpdated, core,
15065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            core->nss_handshake_state_));
15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Tell NSS to suspend the client authentication.  We will then abort the
15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // handshake by returning ERR_SSL_CLIENT_AUTH_CERT_NEEDED.
15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SECWouldBlock;
15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SECFailure;
15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_IOS)
15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus SSLClientSocketNSS::Core::ClientAuthHandler(
15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* arg,
15205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRFileDesc* socket,
15215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CERTDistNames* ca_names,
15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CERTCertificate** result_certificate,
15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECKEYPrivateKey** result_private_key) {
15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Core* core = reinterpret_cast<Core*>(arg);
15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(core->OnNSSTaskRunner());
15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core->PostOrRunCallback(
15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
15295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&AddLogEvent, core->weak_net_log_,
15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 NetLog::TYPE_SSL_CLIENT_CERT_REQUESTED));
15315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(droger): Support client auth on iOS. See http://crbug.com/145954).
15335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG(WARNING) << "Client auth is not supported";
15345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Never send a certificate.
15365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core->AddCertProvidedEvent(0);
15375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SECFailure;
15385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else  // NSS_PLATFORM_CLIENT_AUTH
15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Based on Mozilla's NSS_GetClientAuthData.
15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus SSLClientSocketNSS::Core::ClientAuthHandler(
15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* arg,
15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRFileDesc* socket,
15475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CERTDistNames* ca_names,
15485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CERTCertificate** result_certificate,
15495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECKEYPrivateKey** result_private_key) {
15505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Core* core = reinterpret_cast<Core*>(arg);
15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(core->OnNSSTaskRunner());
15525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core->PostOrRunCallback(
15545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
15555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&AddLogEvent, core->weak_net_log_,
15565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 NetLog::TYPE_SSL_CLIENT_CERT_REQUESTED));
15575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Regular client certificate requested.
15595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core->client_auth_cert_needed_ = !core->ssl_config_.send_client_cert;
15605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* wincx  = SSL_RevealPinArg(socket);
15615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (core->ssl_config_.send_client_cert) {
15632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Second pass: a client certificate should have been selected.
1564868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (core->ssl_config_.client_cert.get()) {
1565868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      CERTCertificate* cert =
1566868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          CERT_DupCertificate(core->ssl_config_.client_cert->os_cert_handle());
15675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SECKEYPrivateKey* privkey = PK11_FindKeyByAnyCert(cert, wincx);
15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (privkey) {
15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // TODO(jsorianopastor): We should wait for server certificate
15705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // verification before sending our credentials.  See
15715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // http://crbug.com/13934.
15725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *result_certificate = cert;
15735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *result_private_key = privkey;
15745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // A cert_count of -1 means the number of certificates is unknown.
15755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // NSS will construct the certificate chain.
15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        core->AddCertProvidedEvent(-1);
15775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return SECSuccess;
15795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
15805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(WARNING) << "Client cert found without private key";
15815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
15825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Send no client certificate.
15835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    core->AddCertProvidedEvent(0);
15845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SECFailure;
15855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // First pass: client certificate is needed.
15882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  core->nss_handshake_state_.cert_authorities.clear();
15895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Retrieve the DER-encoded DistinguishedName of the cert issuers accepted by
15912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the server and save them in |cert_authorities|.
15922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int i = 0; i < ca_names->nnames; i++) {
15932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    core->nss_handshake_state_.cert_authorities.push_back(std::string(
15942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        reinterpret_cast<const char*>(ca_names->names[i].data),
15952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        static_cast<size_t>(ca_names->names[i].len)));
15965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Update the network task runner's view of the handshake state now that
15992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // server certificate request has been recorded.
16005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core->PostOrRunCallback(
16015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE, base::Bind(&Core::OnHandshakeStateUpdated, core,
16025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            core->nss_handshake_state_));
16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Tell NSS to suspend the client authentication.  We will then abort the
16055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // handshake by returning ERR_SSL_CLIENT_AUTH_CERT_NEEDED.
16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SECWouldBlock;
16075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // NSS_PLATFORM_CLIENT_AUTH
16095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1611f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)SECStatus SSLClientSocketNSS::Core::CanFalseStartCallback(
1612f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    PRFileDesc* socket,
1613f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    void* arg,
1614f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    PRBool* can_false_start) {
1615f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // If the server doesn't support NPN or ALPN, then we don't do False
1616f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Start with it.
1617f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  PRBool negotiated_extension;
1618f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SECStatus rv = SSL_HandshakeNegotiatedExtension(socket,
1619f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                                  ssl_app_layer_protocol_xtn,
1620f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                                  &negotiated_extension);
1621f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (rv != SECSuccess || !negotiated_extension) {
1622f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    rv = SSL_HandshakeNegotiatedExtension(socket,
1623f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                          ssl_next_proto_nego_xtn,
1624f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                          &negotiated_extension);
1625f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
1626f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (rv != SECSuccess || !negotiated_extension) {
1627f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    *can_false_start = PR_FALSE;
1628f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return SECSuccess;
1629f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
1630f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1631f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return SSL_RecommendedCanFalseStart(socket, can_false_start);
1632f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
1633f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1634f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// static
16355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::HandshakeCallback(
16365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRFileDesc* socket,
16375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* arg) {
16385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Core* core = reinterpret_cast<Core*>(arg);
16395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(core->OnNSSTaskRunner());
16405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core->handshake_callback_called_ = true;
1642f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (core->false_started_) {
1643f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    core->false_started_ = false;
16445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // If the connection was False Started, then at the time of this callback,
16455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // the peer's certificate will have been verified or the caller will have
16465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // accepted the error.
16475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // This is guaranteed when using False Start because this callback will
16485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // not be invoked until processing the peer's Finished message, which
16495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // will only happen in a PR_Read/PR_Write call, which can only happen
16505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // after the peer's certificate is verified.
16515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    SSL_CacheSessionUnlocked(socket);
16525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
16535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Additionally, when False Starting, DoHandshake() will have already
16545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // called HandshakeSucceeded(), so return now.
1655f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
1656f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
1657f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  core->HandshakeSucceeded();
1658f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
16595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1660f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void SSLClientSocketNSS::Core::HandshakeSucceeded() {
1661f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(OnNSSTaskRunner());
16625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PRBool last_handshake_resumed;
1664f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SECStatus rv = SSL_HandshakeResumedSession(nss_fd_, &last_handshake_resumed);
16655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv == SECSuccess && last_handshake_resumed) {
1666f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    nss_handshake_state_.resumed_handshake = true;
16675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1668f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    nss_handshake_state_.resumed_handshake = false;
16695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1671f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  RecordChannelIDSupportOnNSSTaskRunner();
1672f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  UpdateServerCert();
1673a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  UpdateSignedCertTimestamps();
16745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  UpdateStapledOCSPResponse();
1675f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  UpdateConnectionStatus();
1676f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  UpdateNextProto();
16775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Update the network task runners view of the handshake state whenever
16795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a handshake has completed.
1680f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  PostOrRunCallback(
1681f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      FROM_HERE, base::Bind(&Core::OnHandshakeStateUpdated, this,
1682f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                            nss_handshake_state_));
16835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Core::HandleNSSError(PRErrorCode nss_error,
16865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             bool handshake_error) {
16875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
16885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int net_error = handshake_error ? MapNSSClientHandshakeError(nss_error) :
16905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    MapNSSClientError(nss_error);
16915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
16935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // On Windows, a handle to the HCRYPTPROV is cached in the X509Certificate
16945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // os_cert_handle() as an optimization. However, if the certificate
16955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // private key is stored on a smart card, and the smart card is removed,
16965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the cached HCRYPTPROV will not be able to obtain the HCRYPTKEY again,
16975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // preventing client certificate authentication. Because the
16985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // X509Certificate may outlive the individual SSLClientSocketNSS, due to
16995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // caching in X509Certificate, this failure ends up preventing client
17005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // certificate authentication with the same certificate for all future
17015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // attempts, even after the smart card has been re-inserted. By setting
17025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the CERT_KEY_PROV_HANDLE_PROP_ID to NULL, the cached HCRYPTPROV will
17035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // typically be freed. This allows a new HCRYPTPROV to be obtained from
17045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the certificate on the next attempt, which should succeed if the smart
17055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // card has been re-inserted, or will typically prompt the user to
17065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // re-insert the smart card if not.
17075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((net_error == ERR_SSL_CLIENT_AUTH_CERT_NO_PRIVATE_KEY ||
17085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       net_error == ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED) &&
17095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ssl_config_.send_client_cert && ssl_config_.client_cert) {
17105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CertSetCertificateContextProperty(
17115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ssl_config_.client_cert->os_cert_handle(),
17125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
17135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
17155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return net_error;
17175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Core::DoHandshakeLoop(int last_io_result) {
17205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
17215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = last_io_result;
17235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
17245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Default to STATE_NONE for next state.
17255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    State state = next_handshake_state_;
17265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GotoState(STATE_NONE);
17275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (state) {
17295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_HANDSHAKE:
17305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoHandshake();
17315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
17325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_GET_DOMAIN_BOUND_CERT_COMPLETE:
17335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoGetDBCertComplete(rv);
17345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
17355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_NONE:
17365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
17375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = ERR_UNEXPECTED;
17385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(DFATAL) << "unexpected state " << state;
17395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
17405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
17415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Do the actual network I/O
17435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool network_moved = DoTransportIO();
17445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (network_moved && next_handshake_state_ == STATE_HANDSHAKE) {
17455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // In general we exit the loop if rv is ERR_IO_PENDING.  In this
17465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // special case we keep looping even if rv is ERR_IO_PENDING because
17475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // the transport IO may allow DoHandshake to make progress.
17485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(rv == OK || rv == ERR_IO_PENDING);
17495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rv = OK;  // This causes us to stay in the loop.
17505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
17515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (rv != ERR_IO_PENDING && next_handshake_state_ != STATE_NONE);
17525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
17535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Core::DoReadLoop(int result) {
17565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
1757f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(false_started_ || handshake_callback_called_);
17585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(STATE_NONE, next_handshake_state_);
17595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result < 0)
17615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
17625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!nss_bufs_) {
17645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(DFATAL) << "!nss_bufs_";
17655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rv = ERR_UNEXPECTED;
17665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PostOrRunCallback(
17675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
17685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&AddLogEventWithCallback, weak_net_log_,
17695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   NetLog::TYPE_SSL_READ_ERROR,
17705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   CreateNetLogSSLErrorCallback(rv, 0)));
17715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
17725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool network_moved;
17755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv;
17765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
17775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = DoPayloadRead();
17785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    network_moved = DoTransportIO();
17795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (rv == ERR_IO_PENDING && network_moved);
17805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
17825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Core::DoWriteLoop(int result) {
17855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
1786f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(false_started_ || handshake_callback_called_);
17875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(STATE_NONE, next_handshake_state_);
17885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result < 0)
17905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
17915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!nss_bufs_) {
17935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(DFATAL) << "!nss_bufs_";
17945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rv = ERR_UNEXPECTED;
17955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PostOrRunCallback(
17965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
17975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&AddLogEventWithCallback, weak_net_log_,
17985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   NetLog::TYPE_SSL_READ_ERROR,
17995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   CreateNetLogSSLErrorCallback(rv, 0)));
18005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
18015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool network_moved;
18045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv;
18055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
18065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = DoPayloadWrite();
18075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    network_moved = DoTransportIO();
18085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (rv == ERR_IO_PENDING && network_moved);
18095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LeaveFunction(rv);
18115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
18125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
18135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Core::DoHandshake() {
18155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
18165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int net_error = net::OK;
18185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECStatus rv = SSL_ForceHandshake(nss_fd_);
18195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note: this function may be called multiple times during the handshake, so
18215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // even though channel id and client auth are separate else cases, they can
18225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // both be used during a single SSL handshake.
18235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (channel_id_needed_) {
18245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GotoState(STATE_GET_DOMAIN_BOUND_CERT_COMPLETE);
18255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_error = ERR_IO_PENDING;
18265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (client_auth_cert_needed_) {
18275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_error = ERR_SSL_CLIENT_AUTH_CERT_NEEDED;
18285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PostOrRunCallback(
18295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
18305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&AddLogEventWithCallback, weak_net_log_,
18315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   NetLog::TYPE_SSL_HANDSHAKE_ERROR,
18325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   CreateNetLogSSLErrorCallback(net_error, 0)));
18335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If the handshake already succeeded (because the server requests but
18355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // doesn't require a client cert), we need to invalidate the SSL session
18365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // so that we won't try to resume the non-client-authenticated session in
18375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the next handshake.  This will cause the server to ask for a client
18385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // cert again.
18395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv == SECSuccess && SSL_InvalidateSession(nss_fd_) != SECSuccess)
18405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(WARNING) << "Couldn't invalidate SSL session: " << PR_GetError();
18415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (rv == SECSuccess) {
18425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!handshake_callback_called_) {
1843f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      false_started_ = true;
1844f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      HandshakeSucceeded();
1845f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
18465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
18475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRErrorCode prerr = PR_GetError();
18485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_error = HandleNSSError(prerr, true);
18495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Some network devices that inspect application-layer packets seem to
18512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // inject TCP reset packets to break the connections when they see
18522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // TLS 1.1 in ClientHello or ServerHello. See http://crbug.com/130293.
18532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    //
18547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // Only allow ERR_CONNECTION_RESET to trigger a fallback from TLS 1.1 or
18557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // 1.2. We don't lose much in this fallback because the explicit IV for CBC
18567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // mode in TLS 1.1 is approximated by record splitting in TLS 1.0. The
18577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // fallback will be more painful for TLS 1.2 when we have GCM support.
18582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    //
18592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // ERR_CONNECTION_RESET is a common network error, so we don't want it
18602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // to trigger a version fallback in general, especially the TLS 1.0 ->
18612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // SSL 3.0 fallback, which would drop TLS extensions.
18622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (prerr == PR_CONNECT_RESET_ERROR &&
18637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        ssl_config_.version_max >= SSL_PROTOCOL_VERSION_TLS1_1) {
18642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      net_error = ERR_SSL_PROTOCOL_ERROR;
18652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
18662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If not done, stay in this state
18685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (net_error == ERR_IO_PENDING) {
18695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GotoState(STATE_HANDSHAKE);
18705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
18715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PostOrRunCallback(
18725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          FROM_HERE,
18735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Bind(&AddLogEventWithCallback, weak_net_log_,
18745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     NetLog::TYPE_SSL_HANDSHAKE_ERROR,
18755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     CreateNetLogSSLErrorCallback(net_error, prerr)));
18765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
18775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return net_error;
18805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
18815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Core::DoGetDBCertComplete(int result) {
18835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECStatus rv;
18845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PostOrRunCallback(
18855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
18865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&BoundNetLog::EndEventWithNetErrorCode, weak_net_log_,
18875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 NetLog::TYPE_SSL_GET_DOMAIN_BOUND_CERT, result));
18885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  channel_id_needed_ = false;
18905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != OK)
18925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
18935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECKEYPublicKey* public_key;
18955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECKEYPrivateKey* private_key;
18965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int error = ImportChannelIDKeys(&public_key, &private_key);
18975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (error != OK)
18985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return error;
18995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_RestartHandshakeAfterChannelIDReq(nss_fd_, public_key, private_key);
19015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess)
19025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return MapNSSError(PORT_GetError());
19035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetChannelIDProvided();
19055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GotoState(STATE_HANDSHAKE);
19065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
19075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Core::DoPayloadRead() {
19105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
1911868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(user_read_buf_.get());
19125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GT(user_read_buf_len_, 0);
19135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int rv;
19152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If a previous greedy read resulted in an error that was not consumed (eg:
19162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // due to the caller having read some data successfully), then return that
19172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // pending error now.
19182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (pending_read_result_ != kNoPendingReadResult) {
19192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    rv = pending_read_result_;
19202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PRErrorCode prerr = pending_read_nss_error_;
19212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    pending_read_result_ = kNoPendingReadResult;
19222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    pending_read_nss_error_ = 0;
19232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (rv == 0) {
19252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      PostOrRunCallback(
19262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          FROM_HERE,
19272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::Bind(&LogByteTransferEvent, weak_net_log_,
19282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     NetLog::TYPE_SSL_SOCKET_BYTES_RECEIVED, rv,
19292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     scoped_refptr<IOBuffer>(user_read_buf_)));
19302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
19312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      PostOrRunCallback(
19322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          FROM_HERE,
19332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::Bind(&AddLogEventWithCallback, weak_net_log_,
19342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     NetLog::TYPE_SSL_READ_ERROR,
19352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CreateNetLogSSLErrorCallback(rv, prerr)));
19362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
19375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
19385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Perform a greedy read, attempting to read as much as the caller has
19412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // requested. In the current NSS implementation, PR_Read will return
19422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // exactly one SSL application data record's worth of data per invocation.
19432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The record size is dictated by the server, and may be noticeably smaller
19442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // than the caller's buffer. This may be as little as a single byte, if the
19452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // server is performing 1/n-1 record splitting.
19462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
19472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // However, this greedy read may result in renegotiations/re-handshakes
19482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // happening or may lead to some data being read, followed by an EOF (such as
19492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // a TLS close-notify). If at least some data was read, then that result
19502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // should be deferred until the next call to DoPayloadRead(). Otherwise, if no
19512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // data was read, it's safe to return the error or EOF immediately.
19522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int total_bytes_read = 0;
19532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  do {
19542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    rv = PR_Read(nss_fd_, user_read_buf_->data() + total_bytes_read,
19552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 user_read_buf_len_ - total_bytes_read);
19562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (rv > 0)
19572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      total_bytes_read += rv;
19582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } while (total_bytes_read < user_read_buf_len_ && rv > 0);
19592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int amount_in_read_buffer = memio_GetReadableBufferSize(nss_bufs_);
19602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PostOrRunCallback(FROM_HERE, base::Bind(&Core::OnNSSBufferUpdated, this,
19612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                          amount_in_read_buffer));
19622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (total_bytes_read == user_read_buf_len_) {
19642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // The caller's entire request was satisfied without error. No further
19652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // processing needed.
19662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    rv = total_bytes_read;
19672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
19682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Otherwise, an error occurred (rv <= 0). The error needs to be handled
19692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // immediately, while the NSPR/NSS errors are still available in
19702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // thread-local storage. However, the handled/remapped error code should
19712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // only be returned if no application data was already read; if it was, the
19722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // error code should be deferred until the next call of DoPayloadRead.
19732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    //
19742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // If no data was read, |*next_result| will point to the return value of
19752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // this function. If at least some data was read, |*next_result| will point
19762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // to |pending_read_error_|, to be returned in a future call to
19772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // DoPayloadRead() (e.g.: after the current data is handled).
19782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int* next_result = &rv;
19792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (total_bytes_read > 0) {
19802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      pending_read_result_ = rv;
19812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      rv = total_bytes_read;
19822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      next_result = &pending_read_result_;
19832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
19842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (client_auth_cert_needed_) {
19862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *next_result = ERR_SSL_CLIENT_AUTH_CERT_NEEDED;
19872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      pending_read_nss_error_ = 0;
19882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else if (*next_result < 0) {
19892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // If *next_result == 0, then that indicates EOF, and no special error
19902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // handling is needed.
19912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      pending_read_nss_error_ = PR_GetError();
19922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *next_result = HandleNSSError(pending_read_nss_error_, false);
19932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (rv > 0 && *next_result == ERR_IO_PENDING) {
19942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // If at least some data was read from PR_Read(), do not treat
19952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // insufficient data as an error to return in the next call to
19962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // DoPayloadRead() - instead, let the call fall through to check
19972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // PR_Read() again. This is because DoTransportIO() may complete
19982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // in between the next call to DoPayloadRead(), and thus it is
19992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // important to check PR_Read() on subsequent invocations to see
20002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // if a complete record may now be read.
20012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        pending_read_nss_error_ = 0;
20022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        pending_read_result_ = kNoPendingReadResult;
20032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
20042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
20052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
20062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
20072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_NE(ERR_IO_PENDING, pending_read_result_);
20082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
20095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv >= 0) {
20105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PostOrRunCallback(
20115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
20125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&LogByteTransferEvent, weak_net_log_,
20135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   NetLog::TYPE_SSL_SOCKET_BYTES_RECEIVED, rv,
20145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   scoped_refptr<IOBuffer>(user_read_buf_)));
20152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else if (rv != ERR_IO_PENDING) {
20162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PostOrRunCallback(
20172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FROM_HERE,
20182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&AddLogEventWithCallback, weak_net_log_,
20192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   NetLog::TYPE_SSL_READ_ERROR,
20202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   CreateNetLogSSLErrorCallback(rv, pending_read_nss_error_)));
20212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    pending_read_nss_error_ = 0;
20225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
20235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
20245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
20255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Core::DoPayloadWrite() {
20275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
20285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2029868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(user_write_buf_.get());
20305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int old_amount_in_read_buffer = memio_GetReadableBufferSize(nss_bufs_);
20325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = PR_Write(nss_fd_, user_write_buf_->data(), user_write_buf_len_);
20332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int new_amount_in_read_buffer = memio_GetReadableBufferSize(nss_bufs_);
20342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // PR_Write could potentially consume the unhandled data in the memio read
20352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // buffer if a renegotiation is in progress. If the buffer is consumed,
20362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // notify the latest buffer size to NetworkRunner.
20372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (old_amount_in_read_buffer != new_amount_in_read_buffer) {
20382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PostOrRunCallback(
20392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FROM_HERE,
20402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&Core::OnNSSBufferUpdated, this, new_amount_in_read_buffer));
20412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
20425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv >= 0) {
20435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PostOrRunCallback(
20445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
20455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&LogByteTransferEvent, weak_net_log_,
20465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   NetLog::TYPE_SSL_SOCKET_BYTES_SENT, rv,
20475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   scoped_refptr<IOBuffer>(user_write_buf_)));
20485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
20495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
20505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PRErrorCode prerr = PR_GetError();
20515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (prerr == PR_WOULD_BLOCK_ERROR)
20525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_IO_PENDING;
20535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = HandleNSSError(prerr, false);
20555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PostOrRunCallback(
20565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
20575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&AddLogEventWithCallback, weak_net_log_,
20585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 NetLog::TYPE_SSL_WRITE_ERROR,
20595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 CreateNetLogSSLErrorCallback(rv, prerr)));
20605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
20615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
20625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Do as much network I/O as possible between the buffer and the
20645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// transport socket. Return true if some I/O performed, false
20655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// otherwise (error or ERR_IO_PENDING).
20665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketNSS::Core::DoTransportIO() {
20675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
20685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool network_moved = false;
20705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (nss_bufs_ != NULL) {
20715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rv;
20725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Read and write as much data as we can. The loop is neccessary
20735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // because Write() may return synchronously.
20745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    do {
20755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rv = BufferSend();
2076b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      if (rv != ERR_IO_PENDING && rv != 0)
20775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        network_moved = true;
20785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } while (rv > 0);
2079b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if (!transport_recv_eof_ && BufferRecv() != ERR_IO_PENDING)
20805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      network_moved = true;
20815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
20825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return network_moved;
20835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
20845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Core::BufferRecv() {
20865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
20875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (transport_recv_busy_)
20895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_IO_PENDING;
20905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If NSS is blocked on reading from |nss_bufs_|, because it is empty,
20922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // determine how much data NSS wants to read. If NSS was not blocked,
20932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // this will return 0.
20942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int requested = memio_GetReadRequest(nss_bufs_);
20952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (requested == 0) {
20962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // This is not a perfect match of error codes, as no operation is
20972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // actually pending. However, returning 0 would be interpreted as a
20982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // possible sign of EOF, which is also an inappropriate match.
20992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return ERR_IO_PENDING;
21002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
21012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
21025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* buf;
21035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nb = memio_GetReadParams(nss_bufs_, &buf);
21045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv;
21055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!nb) {
21065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // buffer too full to read into, so no I/O possible at moment
21075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = ERR_IO_PENDING;
21085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
21095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<IOBuffer> read_buffer(new IOBuffer(nb));
21105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (OnNetworkTaskRunner()) {
2111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      rv = DoBufferRecv(read_buffer.get(), nb);
21125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
21135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool posted = network_task_runner_->PostTask(
21145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          FROM_HERE,
21155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Bind(IgnoreResult(&Core::DoBufferRecv), this, read_buffer,
21165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     nb));
21175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rv = posted ? ERR_IO_PENDING : ERR_ABORTED;
21185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
21195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv == ERR_IO_PENDING) {
21215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      transport_recv_busy_ = true;
21225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
21235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (rv > 0) {
21245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        memcpy(buf, read_buffer->data(), rv);
21255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (rv == 0) {
21265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        transport_recv_eof_ = true;
21275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
21285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memio_PutReadResult(nss_bufs_, MapErrorToNSS(rv));
21295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
21305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
21325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
21335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2134b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// Return 0 if nss_bufs_ was empty,
21355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// > 0 for bytes transferred immediately,
21365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// < 0 for error (or the non-error ERR_IO_PENDING).
21375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Core::BufferSend() {
21385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
21395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (transport_send_busy_)
21415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_IO_PENDING;
21425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* buf1;
21445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* buf2;
21455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int len1, len2;
21465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memio_GetWriteParams(nss_bufs_, &buf1, &len1, &buf2, &len2);
21475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const unsigned int len = len1 + len2;
21485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = 0;
21505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (len) {
21515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<IOBuffer> send_buffer(new IOBuffer(len));
21525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(send_buffer->data(), buf1, len1);
21535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(send_buffer->data() + len1, buf2, len2);
21545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (OnNetworkTaskRunner()) {
2156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      rv = DoBufferSend(send_buffer.get(), len);
21575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
21585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool posted = network_task_runner_->PostTask(
21595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          FROM_HERE,
21605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Bind(IgnoreResult(&Core::DoBufferSend), this, send_buffer,
21615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     len));
21625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rv = posted ? ERR_IO_PENDING : ERR_ABORTED;
21635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
21645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv == ERR_IO_PENDING) {
21665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      transport_send_busy_ = true;
21675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
21685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memio_PutWriteResult(nss_bufs_, MapErrorToNSS(rv));
21695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
21705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
21735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
21745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::OnRecvComplete(int result) {
21765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
21775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (next_handshake_state_ == STATE_HANDSHAKE) {
21795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnHandshakeIOComplete(result);
21805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
21815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Network layer received some data, check if client requested to read
21845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // decrypted data.
2185868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!user_read_buf_.get())
21865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
21875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = DoReadLoop(result);
21895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != ERR_IO_PENDING)
21905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DoReadCallback(rv);
21915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
21925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::OnSendComplete(int result) {
21945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
21955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (next_handshake_state_ == STATE_HANDSHAKE) {
21975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnHandshakeIOComplete(result);
21985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
21995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // OnSendComplete may need to call DoPayloadRead while the renegotiation
22025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // handshake is in progress.
22035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv_read = ERR_IO_PENDING;
22045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv_write = ERR_IO_PENDING;
22055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool network_moved;
22065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
2207868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (user_read_buf_.get())
2208a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      rv_read = DoPayloadRead();
2209868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (user_write_buf_.get())
2210a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      rv_write = DoPayloadWrite();
2211a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    network_moved = DoTransportIO();
2212868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } while (rv_read == ERR_IO_PENDING && rv_write == ERR_IO_PENDING &&
2213868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           (user_read_buf_.get() || user_write_buf_.get()) && network_moved);
22145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2215a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // If the parent SSLClientSocketNSS is deleted during the processing of the
2216a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Read callback and OnNSSTaskRunner() == OnNetworkTaskRunner(), then the Core
2217a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // will be detached (and possibly deleted). Guard against deletion by taking
2218a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // an extra reference, then check if the Core was detached before invoking the
2219a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // next callback.
2220a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  scoped_refptr<Core> guard(this);
2221868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (user_read_buf_.get() && rv_read != ERR_IO_PENDING)
2222a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    DoReadCallback(rv_read);
2223a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
2224a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (OnNetworkTaskRunner() && detached_)
2225a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return;
2226a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
2227868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (user_write_buf_.get() && rv_write != ERR_IO_PENDING)
2228a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    DoWriteCallback(rv_write);
22295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
22305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// As part of Connect(), the SSLClientSocketNSS object performs an SSL
22325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// handshake. This requires network IO, which in turn calls
22335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BufferRecvComplete() with a non-zero byte count. This byte count eventually
22345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// winds its way through the state machine and ends up being passed to the
22355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// callback. For Read() and Write(), that's what we want. But for Connect(),
22365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the caller expects OK (i.e. 0) for success.
22375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::DoConnectCallback(int rv) {
22385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
22395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(rv, ERR_IO_PENDING);
22405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!user_connect_callback_.is_null());
22415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Closure c = base::Bind(
22435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::ResetAndReturn(&user_connect_callback_),
22445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rv > OK ? OK : rv);
22455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PostOrRunCallback(FROM_HERE, c);
22465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
22475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::DoReadCallback(int rv) {
22495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
22505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(ERR_IO_PENDING, rv);
22515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!user_read_callback_.is_null());
22525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_read_buf_ = NULL;
22545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_read_buf_len_ = 0;
22552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int amount_in_read_buffer = memio_GetReadableBufferSize(nss_bufs_);
22562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This is used to curry the |amount_int_read_buffer| and |user_cb| back to
22572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the network task runner.
22582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PostOrRunCallback(
22592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE,
22602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&Core::OnNSSBufferUpdated, this, amount_in_read_buffer));
22612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PostOrRunCallback(
22622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE,
22632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&Core::DidNSSRead, this, rv));
22642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PostOrRunCallback(
22652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE,
22662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(base::ResetAndReturn(&user_read_callback_), rv));
22675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
22685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::DoWriteCallback(int rv) {
22705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
22715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(ERR_IO_PENDING, rv);
22725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!user_write_callback_.is_null());
22735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Since Run may result in Write being called, clear |user_write_callback_|
22755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // up front.
22765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_write_buf_ = NULL;
22775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_write_buf_len_ = 0;
22782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Update buffer status because DoWriteLoop called DoTransportIO which may
22792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // perform read operations.
22802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int amount_in_read_buffer = memio_GetReadableBufferSize(nss_bufs_);
22812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This is used to curry the |amount_int_read_buffer| and |user_cb| back to
22822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the network task runner.
22832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PostOrRunCallback(
22842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE,
22852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&Core::OnNSSBufferUpdated, this, amount_in_read_buffer));
22862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PostOrRunCallback(
22872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE,
22882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&Core::DidNSSWrite, this, rv));
22892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PostOrRunCallback(
22902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE,
22912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(base::ResetAndReturn(&user_write_callback_), rv));
22925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
22935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus SSLClientSocketNSS::Core::ClientChannelIDHandler(
22955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* arg,
22965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRFileDesc* socket,
22975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECKEYPublicKey **out_public_key,
22985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECKEYPrivateKey **out_private_key) {
22995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Core* core = reinterpret_cast<Core*>(arg);
23005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(core->OnNSSTaskRunner());
23015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core->PostOrRunCallback(
23035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
23045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&AddLogEvent, core->weak_net_log_,
23055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 NetLog::TYPE_SSL_CHANNEL_ID_REQUESTED));
23065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We have negotiated the TLS channel ID extension.
23085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core->channel_id_xtn_negotiated_ = true;
2309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string host = core->host_and_port_.host();
23105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int error = ERR_UNEXPECTED;
23115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (core->OnNetworkTaskRunner()) {
2312bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    error = core->DoGetDomainBoundCert(host);
23135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
23145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool posted = core->network_task_runner_->PostTask(
23155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
23165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(
23175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            IgnoreResult(&Core::DoGetDomainBoundCert),
2318bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch            core, host));
23195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error = posted ? ERR_IO_PENDING : ERR_ABORTED;
23205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
23215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (error == ERR_IO_PENDING) {
23235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Asynchronous case.
23245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    core->channel_id_needed_ = true;
23255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SECWouldBlock;
23265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
23275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core->PostOrRunCallback(
23295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
23305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&BoundNetLog::EndEventWithNetErrorCode, core->weak_net_log_,
23315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 NetLog::TYPE_SSL_GET_DOMAIN_BOUND_CERT, error));
23325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECStatus rv = SECSuccess;
23335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (error == OK) {
23345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Synchronous success.
23355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int result = core->ImportChannelIDKeys(out_public_key, out_private_key);
23365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (result == OK)
23375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      core->SetChannelIDProvided();
23385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
23395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rv = SECFailure;
23405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
23415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = SECFailure;
23425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
23435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
23455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
23465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Core::ImportChannelIDKeys(SECKEYPublicKey** public_key,
23485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  SECKEYPrivateKey** key) {
23495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set the certificate.
23505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECItem cert_item;
23515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cert_item.data = (unsigned char*) domain_bound_cert_.data();
23525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cert_item.len = domain_bound_cert_.size();
23535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedCERTCertificate cert(CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
23545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                     &cert_item,
23555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                     NULL,
23565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                     PR_FALSE,
23575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                     PR_TRUE));
23585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cert == NULL)
23595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return MapNSSError(PORT_GetError());
23605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2361f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  crypto::ScopedPK11Slot slot(PK11_GetInternalSlot());
23625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set the private key.
2363bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  if (!crypto::ECPrivateKey::ImportFromEncryptedPrivateKeyInfo(
2364f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          slot.get(),
23655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ServerBoundCertService::kEPKIPassword,
23665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          reinterpret_cast<const unsigned char*>(
23675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              domain_bound_private_key_.data()),
23685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          domain_bound_private_key_.size(),
23695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          &cert->subjectPublicKeyInfo,
23705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          false,
23715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          false,
23725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          key,
23735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          public_key)) {
2374bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    int error = MapNSSError(PORT_GetError());
2375bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return error;
23765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
23775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
23795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
23805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::UpdateServerCert() {
23825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nss_handshake_state_.server_cert_chain.Reset(nss_fd_);
23835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nss_handshake_state_.server_cert = X509Certificate::CreateFromDERCertChain(
23845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nss_handshake_state_.server_cert_chain.AsStringPieceVector());
2385868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (nss_handshake_state_.server_cert.get()) {
23865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Since this will be called asynchronously on another thread, it needs to
23875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // own a reference to the certificate.
23885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NetLog::ParametersCallback net_log_callback =
23895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&NetLogX509CertificateCallback,
23905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   nss_handshake_state_.server_cert);
23915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PostOrRunCallback(
23925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
23935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&AddLogEventWithCallback, weak_net_log_,
23945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   NetLog::TYPE_SSL_CERTIFICATES_RECEIVED,
23955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   net_log_callback));
23965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
23975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
23985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2399a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void SSLClientSocketNSS::Core::UpdateSignedCertTimestamps() {
2400a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  const SECItem* signed_cert_timestamps =
2401a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      SSL_PeerSignedCertTimestamps(nss_fd_);
2402a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
2403a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!signed_cert_timestamps || !signed_cert_timestamps->len)
2404a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return;
2405a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
2406a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  nss_handshake_state_.sct_list_from_tls_extension = std::string(
2407a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      reinterpret_cast<char*>(signed_cert_timestamps->data),
2408a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      signed_cert_timestamps->len);
2409a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
2410a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
24115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SSLClientSocketNSS::Core::UpdateStapledOCSPResponse() {
2412a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  PRBool ocsp_requested = PR_FALSE;
2413a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  SSL_OptionGet(nss_fd_, SSL_ENABLE_OCSP_STAPLING, &ocsp_requested);
24145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const SECItemArray* ocsp_responses =
24155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      SSL_PeerStapledOCSPResponses(nss_fd_);
2416a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bool ocsp_responses_present = ocsp_responses && ocsp_responses->len;
2417a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (ocsp_requested)
2418a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    UMA_HISTOGRAM_BOOLEAN("Net.OCSPResponseStapled", ocsp_responses_present);
2419a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!ocsp_responses_present)
24205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
24215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
24225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  nss_handshake_state_.stapled_ocsp_response = std::string(
24235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      reinterpret_cast<char*>(ocsp_responses->items[0].data),
24245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ocsp_responses->items[0].len);
24255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
24265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // TODO(agl): figure out how to plumb an OCSP response into the Mac
24275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // system library and update IsOCSPStaplingSupported for Mac.
24285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (IsOCSPStaplingSupported()) {
24295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  #if defined(OS_WIN)
24305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (nss_handshake_state_.server_cert) {
24315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      CRYPT_DATA_BLOB ocsp_response_blob;
24325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ocsp_response_blob.cbData = ocsp_responses->items[0].len;
24335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ocsp_response_blob.pbData = ocsp_responses->items[0].data;
24345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      BOOL ok = CertSetCertificateContextProperty(
24355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          nss_handshake_state_.server_cert->os_cert_handle(),
24365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          CERT_OCSP_RESPONSE_PROP_ID,
24375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          CERT_SET_PROPERTY_IGNORE_PERSIST_ERROR_FLAG,
24385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          &ocsp_response_blob);
24395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (!ok) {
24405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        VLOG(1) << "Failed to set OCSP response property: "
24415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                << GetLastError();
24425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
24435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
24445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  #elif defined(USE_NSS)
24455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CacheOCSPResponseFromSideChannelFunction cache_ocsp_response =
24465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        GetCacheOCSPResponseFromSideChannelFunction();
24475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
24485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    cache_ocsp_response(
24495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        CERT_GetDefaultCertDB(),
24505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        nss_handshake_state_.server_cert_chain[0], PR_Now(),
24515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        &ocsp_responses->items[0], NULL);
24525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  #endif
24535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }  // IsOCSPStaplingSupported()
24545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
24555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
24565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::UpdateConnectionStatus() {
24575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLChannelInfo channel_info;
24585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECStatus ok = SSL_GetChannelInfo(nss_fd_,
24595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    &channel_info, sizeof(channel_info));
24605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ok == SECSuccess &&
24615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      channel_info.length == sizeof(channel_info) &&
24625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      channel_info.cipherSuite) {
24635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nss_handshake_state_.ssl_connection_status |=
24645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (static_cast<int>(channel_info.cipherSuite) &
24655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         SSL_CONNECTION_CIPHERSUITE_MASK) <<
24665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SSL_CONNECTION_CIPHERSUITE_SHIFT;
24675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nss_handshake_state_.ssl_connection_status |=
24695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (static_cast<int>(channel_info.compressionMethod) &
24705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         SSL_CONNECTION_COMPRESSION_MASK) <<
24715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SSL_CONNECTION_COMPRESSION_SHIFT;
24725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2473bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    // NSS 3.14.x doesn't have a version macro for TLS 1.2 (because NSS didn't
2474bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    // support it yet), so use 0x0303 directly.
24755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int version = SSL_CONNECTION_VERSION_UNKNOWN;
24765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (channel_info.protocolVersion < SSL_LIBRARY_VERSION_3_0) {
24775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // All versions less than SSL_LIBRARY_VERSION_3_0 are treated as SSL
24785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // version 2.
24795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      version = SSL_CONNECTION_VERSION_SSL2;
24805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (channel_info.protocolVersion == SSL_LIBRARY_VERSION_3_0) {
24815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      version = SSL_CONNECTION_VERSION_SSL3;
24825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (channel_info.protocolVersion == SSL_LIBRARY_VERSION_3_1_TLS) {
24835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      version = SSL_CONNECTION_VERSION_TLS1;
2484bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    } else if (channel_info.protocolVersion == SSL_LIBRARY_VERSION_TLS_1_1) {
24855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      version = SSL_CONNECTION_VERSION_TLS1_1;
24865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (channel_info.protocolVersion == 0x0303) {
24875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      version = SSL_CONNECTION_VERSION_TLS1_2;
24885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
24895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nss_handshake_state_.ssl_connection_status |=
24905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (version & SSL_CONNECTION_VERSION_MASK) <<
24915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SSL_CONNECTION_VERSION_SHIFT;
24925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
24935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PRBool peer_supports_renego_ext;
24955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ok = SSL_HandshakeNegotiatedExtension(nss_fd_, ssl_renegotiation_info_xtn,
24965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        &peer_supports_renego_ext);
24975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ok == SECSuccess) {
24985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!peer_supports_renego_ext) {
24995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nss_handshake_state_.ssl_connection_status |=
25005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          SSL_CONNECTION_NO_RENEGOTIATION_EXTENSION;
25015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Log an informational message if the server does not support secure
25025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // renegotiation (RFC 5746).
25035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VLOG(1) << "The server " << host_and_port_.ToString()
25045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              << " does not support the TLS renegotiation_info extension.";
25055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
25065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UMA_HISTOGRAM_ENUMERATION("Net.RenegotiationExtensionSupported",
25075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              peer_supports_renego_ext, 2);
25082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
25092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // We would like to eliminate fallback to SSLv3 for non-buggy servers
25102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // because of security concerns. For example, Google offers forward
25112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // secrecy with ECDHE but that requires TLS 1.0. An attacker can block
25122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // TLSv1 connections and force us to downgrade to SSLv3 and remove forward
25132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // secrecy.
25142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    //
25152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Yngve from Opera has suggested using the renegotiation extension as an
25162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // indicator that SSLv3 fallback was mistaken:
25172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // tools.ietf.org/html/draft-pettersen-tls-version-rollback-removal-00 .
25182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    //
25192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // As a first step, measure how often clients perform version fallback
25202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // while the server advertises support secure renegotiation.
25212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (ssl_config_.version_fallback &&
25222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        channel_info.protocolVersion == SSL_LIBRARY_VERSION_3_0) {
25232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      UMA_HISTOGRAM_BOOLEAN("Net.SSLv3FallbackToRenegoPatchedServer",
25242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            peer_supports_renego_ext == PR_TRUE);
25252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
25265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
25275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ssl_config_.version_fallback) {
25295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nss_handshake_state_.ssl_connection_status |=
25305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SSL_CONNECTION_VERSION_FALLBACK;
25315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
25325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
25335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2534eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid SSLClientSocketNSS::Core::UpdateNextProto() {
2535eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  uint8 buf[256];
2536eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SSLNextProtoState state;
2537eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  unsigned buf_len;
2538eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2539eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SECStatus rv = SSL_GetNextProto(nss_fd_, &state, buf, &buf_len, sizeof(buf));
2540eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (rv != SECSuccess)
2541eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
2542eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2543eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  nss_handshake_state_.next_proto =
2544eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      std::string(reinterpret_cast<char*>(buf), buf_len);
2545eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  switch (state) {
2546eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case SSL_NEXT_PROTO_NEGOTIATED:
2547eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case SSL_NEXT_PROTO_SELECTED:
2548eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      nss_handshake_state_.next_proto_status = kNextProtoNegotiated;
2549eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
2550eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case SSL_NEXT_PROTO_NO_OVERLAP:
2551eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      nss_handshake_state_.next_proto_status = kNextProtoNoOverlap;
2552eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
2553eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case SSL_NEXT_PROTO_NO_SUPPORT:
2554eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      nss_handshake_state_.next_proto_status = kNextProtoUnsupported;
2555eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
2556eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    default:
2557eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      NOTREACHED();
2558eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
2559eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
2560eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
2561eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
25621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void SSLClientSocketNSS::Core::RecordChannelIDSupportOnNSSTaskRunner() {
2563b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  DCHECK(OnNSSTaskRunner());
25645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (nss_handshake_state_.resumed_handshake)
25655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
25665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2567b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // Copy the NSS task runner-only state to the network task runner and
2568b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // log histograms from there, since the histograms also need access to the
2569b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // network task runner state.
2570b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  PostOrRunCallback(
2571b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      FROM_HERE,
2572b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      base::Bind(&Core::RecordChannelIDSupportOnNetworkTaskRunner,
2573b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                 this,
2574b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                 channel_id_xtn_negotiated_,
2575b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                 ssl_config_.channel_id_enabled,
2576b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                 crypto::ECPrivateKey::IsSupported()));
2577b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
2578b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
2579b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void SSLClientSocketNSS::Core::RecordChannelIDSupportOnNetworkTaskRunner(
2580b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    bool negotiated_channel_id,
2581b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    bool channel_id_enabled,
2582b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    bool supports_ecc) const {
2583b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  DCHECK(OnNetworkTaskRunner());
2584b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
25851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  RecordChannelIDSupport(server_bound_cert_service_,
25861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                         negotiated_channel_id,
25871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                         channel_id_enabled,
25881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                         supports_ecc);
25895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
25905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Core::DoBufferRecv(IOBuffer* read_buffer, int len) {
25925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNetworkTaskRunner());
25935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GT(len, 0);
25945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (detached_)
25965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_ABORTED;
25975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = transport_->socket()->Read(
25995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      read_buffer, len,
26005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&Core::BufferRecvComplete, base::Unretained(this),
26015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 scoped_refptr<IOBuffer>(read_buffer)));
26025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!OnNSSTaskRunner() && rv != ERR_IO_PENDING) {
26045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nss_task_runner_->PostTask(
26055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE, base::Bind(&Core::BufferRecvComplete, this,
26065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              scoped_refptr<IOBuffer>(read_buffer), rv));
26075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
26085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
26095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
26115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
26125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Core::DoBufferSend(IOBuffer* send_buffer, int len) {
26145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNetworkTaskRunner());
26155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GT(len, 0);
26165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (detached_)
26185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_ABORTED;
26195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = transport_->socket()->Write(
26212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      send_buffer, len,
26222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&Core::BufferSendComplete,
26232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 base::Unretained(this)));
26245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!OnNSSTaskRunner() && rv != ERR_IO_PENDING) {
26265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nss_task_runner_->PostTask(
26275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
26285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&Core::BufferSendComplete, this, rv));
26295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
26305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
26315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
26335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
26345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochint SSLClientSocketNSS::Core::DoGetDomainBoundCert(const std::string& host) {
26365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNetworkTaskRunner());
26375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (detached_)
26395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_FAILED;
26405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  weak_net_log_->BeginEvent(NetLog::TYPE_SSL_GET_DOMAIN_BOUND_CERT);
26425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int rv = server_bound_cert_service_->GetOrCreateDomainBoundCert(
2644c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      host,
26455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &domain_bound_private_key_,
26465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &domain_bound_cert_,
26475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&Core::OnGetDomainBoundCertComplete, base::Unretained(this)),
26485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &domain_bound_cert_request_handle_);
26495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != ERR_IO_PENDING && !OnNSSTaskRunner()) {
26515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nss_task_runner_->PostTask(
26525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
26535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&Core::OnHandshakeIOComplete, this, rv));
26545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_IO_PENDING;
26555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
26565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
26585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
26595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::OnHandshakeStateUpdated(
26615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const HandshakeState& state) {
26622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(OnNetworkTaskRunner());
26635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  network_handshake_state_ = state;
26645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
26655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SSLClientSocketNSS::Core::OnNSSBufferUpdated(int amount_in_read_buffer) {
26672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(OnNetworkTaskRunner());
26682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  unhandled_buffer_size_ = amount_in_read_buffer;
26692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
26702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
26712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SSLClientSocketNSS::Core::DidNSSRead(int result) {
26722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(OnNetworkTaskRunner());
26732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(nss_waiting_read_);
26742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  nss_waiting_read_ = false;
2675effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (result <= 0) {
26762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    nss_is_closed_ = true;
2677effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  } else {
2678effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    was_ever_used_ = true;
2679effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
26802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
26812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
26822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SSLClientSocketNSS::Core::DidNSSWrite(int result) {
26832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(OnNetworkTaskRunner());
26842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(nss_waiting_write_);
26852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  nss_waiting_write_ = false;
2686effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (result < 0) {
26872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    nss_is_closed_ = true;
2688effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  } else if (result > 0) {
2689effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    was_ever_used_ = true;
2690effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
26912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
26922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
26935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::BufferSendComplete(int result) {
26945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!OnNSSTaskRunner()) {
26955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (detached_)
26965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
26975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nss_task_runner_->PostTask(
26995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE, base::Bind(&Core::BufferSendComplete, this, result));
27005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
27015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
27025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
27045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memio_PutWriteResult(nss_bufs_, MapErrorToNSS(result));
27065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transport_send_busy_ = false;
27075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OnSendComplete(result);
27085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
27095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::OnHandshakeIOComplete(int result) {
27115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!OnNSSTaskRunner()) {
27125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (detached_)
27135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
27145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nss_task_runner_->PostTask(
27165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE, base::Bind(&Core::OnHandshakeIOComplete, this, result));
27175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
27185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
27195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
27215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = DoHandshakeLoop(result);
27235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != ERR_IO_PENDING)
27245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DoConnectCallback(rv);
27255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
27265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::OnGetDomainBoundCertComplete(int result) {
27285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << __FUNCTION__ << " " << result;
27295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNetworkTaskRunner());
27305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OnHandshakeIOComplete(result);
27325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
27335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::BufferRecvComplete(
27355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IOBuffer* read_buffer,
27365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int result) {
27375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(read_buffer);
27385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!OnNSSTaskRunner()) {
27405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (detached_)
27415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
27425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nss_task_runner_->PostTask(
27445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE, base::Bind(&Core::BufferRecvComplete, this,
27455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              scoped_refptr<IOBuffer>(read_buffer), result));
27465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
27475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
27485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(OnNSSTaskRunner());
27505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result > 0) {
27525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char* buf;
27535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int nb = memio_GetReadParams(nss_bufs_, &buf);
27545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK_GE(nb, result);
27555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(buf, read_buffer->data(), result);
27565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (result == 0) {
27575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    transport_recv_eof_ = true;
27585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
27595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memio_PutReadResult(nss_bufs_, MapErrorToNSS(result));
27615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transport_recv_busy_ = false;
27625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OnRecvComplete(result);
27635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
27645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::PostOrRunCallback(
27665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const tracked_objects::Location& location,
27675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::Closure& task) {
27685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!OnNetworkTaskRunner()) {
27695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    network_task_runner_->PostTask(
27705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
27715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&Core::PostOrRunCallback, this, location, task));
27725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
27735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
27745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (detached_ || task.is_null())
27765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
27775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  task.Run();
27785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
27795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::AddCertProvidedEvent(int cert_count) {
27815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PostOrRunCallback(
27825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
27835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&AddLogEventWithCallback, weak_net_log_,
27845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 NetLog::TYPE_SSL_CLIENT_CERT_PROVIDED,
27855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 NetLog::IntegerCallback("cert_count", cert_count)));
27865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
27875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Core::SetChannelIDProvided() {
27895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PostOrRunCallback(
27905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE, base::Bind(&AddLogEvent, weak_net_log_,
27915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            NetLog::TYPE_SSL_CHANNEL_ID_PROVIDED));
27925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nss_handshake_state_.channel_id_sent = true;
27935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Update the network task runner's view of the handshake state now that
27945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // channel id has been sent.
27955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PostOrRunCallback(
27965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE, base::Bind(&Core::OnHandshakeStateUpdated, this,
27975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            nss_handshake_state_));
27985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
27995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SSLClientSocketNSS::SSLClientSocketNSS(
28015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::SequencedTaskRunner* nss_task_runner,
28023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_ptr<ClientSocketHandle> transport_socket,
28035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const HostPortPair& host_and_port,
28045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SSLConfig& ssl_config,
28055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SSLClientSocketContext& context)
28065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : nss_task_runner_(nss_task_runner),
28073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      transport_(transport_socket.Pass()),
28085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      host_and_port_(host_and_port),
28095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ssl_config_(ssl_config),
28105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cert_verifier_(context.cert_verifier),
2811a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      cert_transparency_verifier_(context.cert_transparency_verifier),
28125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      server_bound_cert_service_(context.server_bound_cert_service),
28135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ssl_session_cache_shard_(context.ssl_session_cache_shard),
28145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      completed_handshake_(false),
28155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next_handshake_state_(STATE_NONE),
28165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nss_fd_(NULL),
28173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      net_log_(transport_->socket()->NetLog()),
28185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      transport_security_state_(context.transport_security_state),
28195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      valid_thread_id_(base::kInvalidThreadId) {
28205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterFunction("");
28215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InitCore();
28225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LeaveFunction("");
28235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
28245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SSLClientSocketNSS::~SSLClientSocketNSS() {
28265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterFunction("");
28275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Disconnect();
28285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LeaveFunction("");
28295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
28305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
28325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocket::ClearSessionCache() {
28335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SSL_ClearSessionCache can't be called before NSS is initialized.  Don't
28345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // bother initializing NSS just to clear an empty SSL session cache.
28355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!NSS_IsInitialized())
28365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
28375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSL_ClearSessionCache();
28395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
28405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketNSS::GetSSLInfo(SSLInfo* ssl_info) {
28425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterFunction("");
28435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssl_info->Reset();
28445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (core_->state().server_cert_chain.empty() ||
28455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !core_->state().server_cert_chain[0]) {
28465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
28475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
28485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssl_info->cert_status = server_cert_verify_result_.cert_status;
28505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssl_info->cert = server_cert_verify_result_.verified_cert;
2851a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
2852a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  AddSCTInfoToSSLInfo(ssl_info);
2853a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
28545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssl_info->connection_status =
28555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      core_->state().ssl_connection_status;
28565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssl_info->public_key_hashes = server_cert_verify_result_.public_key_hashes;
28575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssl_info->is_issued_by_known_root =
28585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      server_cert_verify_result_.is_issued_by_known_root;
28595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssl_info->client_cert_sent =
2860868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      ssl_config_.send_client_cert && ssl_config_.client_cert.get();
28615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssl_info->channel_id_sent = WasChannelIDSent();
28625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PRUint16 cipher_suite = SSLConnectionStatusToCipherSuite(
28645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      core_->state().ssl_connection_status);
28655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLCipherSuiteInfo cipher_info;
28665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECStatus ok = SSL_GetCipherSuiteInfo(cipher_suite,
28675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        &cipher_info, sizeof(cipher_info));
28685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ok == SECSuccess) {
28695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ssl_info->security_bits = cipher_info.effectiveKeyBits;
28705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
28715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ssl_info->security_bits = -1;
28725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(DFATAL) << "SSL_GetCipherSuiteInfo returned " << PR_GetError()
28735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                << " for cipherSuite " << cipher_suite;
28745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
28755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssl_info->handshake_type = core_->state().resumed_handshake ?
28775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SSLInfo::HANDSHAKE_RESUME : SSLInfo::HANDSHAKE_FULL;
28785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LeaveFunction("");
28805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
28815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
28825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::GetSSLCertRequestInfo(
28845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SSLCertRequestInfo* cert_request_info) {
28855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterFunction("");
28865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  cert_request_info->host_and_port = host_and_port_;
28872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  cert_request_info->cert_authorities = core_->state().cert_authorities;
28882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LeaveFunction("");
28895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
28905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::ExportKeyingMaterial(const base::StringPiece& label,
28925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             bool has_context,
28935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             const base::StringPiece& context,
28945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             unsigned char* out,
28955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             unsigned int outlen) {
28965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsConnected())
28975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_SOCKET_NOT_CONNECTED;
28985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SSL_ExportKeyingMaterial may block the current thread if |core_| is in
29005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the midst of a handshake.
29015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECStatus result = SSL_ExportKeyingMaterial(
29025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nss_fd_, label.data(), label.size(), has_context,
29035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reinterpret_cast<const unsigned char*>(context.data()),
29045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context.length(), out, outlen);
29055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != SECSuccess) {
29065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_ExportKeyingMaterial", "");
29075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return MapNSSError(PORT_GetError());
29085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
29095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
29105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
29115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::GetTLSUniqueChannelBinding(std::string* out) {
29135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsConnected())
29145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_SOCKET_NOT_CONNECTED;
29155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned char buf[64];
29165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int len;
29175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECStatus result = SSL_GetChannelBinding(nss_fd_,
29185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           SSL_CHANNEL_BINDING_TLS_UNIQUE,
29195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           buf, &len, arraysize(buf));
29205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != SECSuccess) {
29215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_GetChannelBinding", "");
29225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return MapNSSError(PORT_GetError());
29235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
29245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->assign(reinterpret_cast<char*>(buf), len);
29255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
29265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
29275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SSLClientSocket::NextProtoStatus
29295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SSLClientSocketNSS::GetNextProto(std::string* proto,
29305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 std::string* server_protos) {
29315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *proto = core_->state().next_proto;
29325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *server_protos = core_->state().server_protos;
29335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return core_->state().next_proto_status;
29345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
29355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Connect(const CompletionCallback& callback) {
29375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterFunction("");
29385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(transport_.get());
29397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // It is an error to create an SSLClientSocket whose context has no
29407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // TransportSecurityState.
29417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DCHECK(transport_security_state_);
29425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(STATE_NONE, next_handshake_state_);
29435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(user_connect_callback_.is_null());
29445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!callback.is_null());
29455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnsureThreadIdAssigned();
29475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log_.BeginEvent(NetLog::TYPE_SSL_CONNECT);
29495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = Init();
29515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != OK) {
29525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
29535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
29545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
29555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = InitializeSSLOptions();
29575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != OK) {
29585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
29595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
29605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
29615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = InitializeSSLPeerName();
29635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != OK) {
29645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
29655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
29665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
29675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GotoState(STATE_HANDSHAKE);
29695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = DoHandshakeLoop(OK);
29715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv == ERR_IO_PENDING) {
29725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_connect_callback_ = callback;
29735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
29745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
29755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
29765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LeaveFunction("");
29785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv > OK ? OK : rv;
29795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
29805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::Disconnect() {
29825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterFunction("");
29835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(CalledOnValidThread());
29855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Shut down anything that may call us back.
29875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_->Detach();
29885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  verifier_.reset();
29895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transport_->socket()->Disconnect();
29905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Reset object state.
29925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_connect_callback_.Reset();
29935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  server_cert_verify_result_.Reset();
29945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  completed_handshake_   = false;
29955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  start_cert_verification_time_ = base::TimeTicks();
29965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InitCore();
29975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LeaveFunction("");
29995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
30005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketNSS::IsConnected() const {
30025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterFunction("");
30032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool ret = completed_handshake_ &&
30042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             (core_->HasPendingAsyncOperation() ||
30052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              (core_->IsConnected() && core_->HasUnhandledReceivedData()) ||
30062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              transport_->socket()->IsConnected());
30075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LeaveFunction("");
30085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ret;
30095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
30105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketNSS::IsConnectedAndIdle() const {
30125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterFunction("");
30132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool ret = completed_handshake_ &&
30142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             !core_->HasPendingAsyncOperation() &&
30152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             !(core_->IsConnected() && core_->HasUnhandledReceivedData()) &&
30162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             transport_->socket()->IsConnectedAndIdle();
30175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LeaveFunction("");
30185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ret;
30195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
30205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::GetPeerAddress(IPEndPoint* address) const {
30225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return transport_->socket()->GetPeerAddress(address);
30235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
30245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::GetLocalAddress(IPEndPoint* address) const {
30265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return transport_->socket()->GetLocalAddress(address);
30275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
30285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const BoundNetLog& SSLClientSocketNSS::NetLog() const {
30305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return net_log_;
30315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
30325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::SetSubresourceSpeculation() {
30345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (transport_.get() && transport_->socket()) {
30355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    transport_->socket()->SetSubresourceSpeculation();
30365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
30375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
30385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
30395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
30405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::SetOmniboxSpeculation() {
30425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (transport_.get() && transport_->socket()) {
30435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    transport_->socket()->SetOmniboxSpeculation();
30445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
30455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
30465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
30475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
30485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketNSS::WasEverUsed() const {
3050effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK(core_.get());
3051effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
3052effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return core_->WasEverUsed();
30535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
30545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketNSS::UsingTCPFastOpen() const {
30565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (transport_.get() && transport_->socket()) {
30575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return transport_->socket()->UsingTCPFastOpen();
30585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
30595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
30605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
30615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
30625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Read(IOBuffer* buf, int buf_len,
30645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const CompletionCallback& callback) {
3065868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(core_.get());
30665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!callback.is_null());
30675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterFunction(buf_len);
30695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = core_->Read(buf, buf_len, callback);
30705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LeaveFunction(rv);
30715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
30735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
30745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Write(IOBuffer* buf, int buf_len,
30765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              const CompletionCallback& callback) {
3077868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(core_.get());
30785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!callback.is_null());
30795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterFunction(buf_len);
30815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = core_->Write(buf, buf_len, callback);
30825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LeaveFunction(rv);
30835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
30855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
30865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketNSS::SetReceiveBufferSize(int32 size) {
30885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return transport_->socket()->SetReceiveBufferSize(size);
30895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
30905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketNSS::SetSendBufferSize(int32 size) {
30925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return transport_->socket()->SetSendBufferSize(size);
30935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
30945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::Init() {
30965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterFunction("");
30975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initialize the NSS SSL library in a threadsafe way.  This also
30985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // initializes the NSS base library.
30995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnsureNSSSSLInit();
31005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!NSS_IsInitialized())
31015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNEXPECTED;
31022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(USE_NSS) || defined(OS_IOS)
31035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ssl_config_.cert_io_enabled) {
31045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We must call EnsureNSSHttpIOInit() here, on the IO thread, to get the IO
31055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // loop by MessageLoopForIO::current().
31065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // X509Certificate::Verify() runs on a worker thread of CertVerifier.
31075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EnsureNSSHttpIOInit();
31085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
31095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
31105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LeaveFunction("");
31125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
31135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
31145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::InitCore() {
31167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  core_ = new Core(base::ThreadTaskRunnerHandle::Get().get(),
3117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                   nss_task_runner_.get(),
3118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                   transport_.get(),
3119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                   host_and_port_,
3120868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                   ssl_config_,
3121868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                   &net_log_,
31225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   server_bound_cert_service_);
31235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
31245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::InitializeSSLOptions() {
31265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Transport connected, now hook it up to nss
31275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nss_fd_ = memio_CreateIOLayer(kRecvBufferSize, kSendBufferSize);
31285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (nss_fd_ == NULL) {
31295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_OUT_OF_MEMORY;  // TODO(port): map NSPR error code.
31305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
31315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Grab pointer to buffers
31335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memio_Private* nss_bufs = memio_GetSecret(nss_fd_);
31345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Create SSL state machine */
31365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Push SSL onto our fake I/O socket */
3137a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (SSL_ImportFD(GetNSSModelSocket(), nss_fd_) == NULL) {
31385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_ImportFD", "");
3139a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    PR_Close(nss_fd_);
3140a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    nss_fd_ = NULL;
31415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_OUT_OF_MEMORY;  // TODO(port): map NSPR/NSS error code.
31425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
31435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(port): set more ssl options!  Check errors!
31445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv;
31465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_OptionSet(nss_fd_, SSL_SECURITY, PR_TRUE);
31485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess) {
31495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_SECURITY");
31505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNEXPECTED;
31515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
31525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SSL2, PR_FALSE);
31545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess) {
31555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_SSL2");
31565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNEXPECTED;
31575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
31585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Don't do V2 compatible hellos because they don't support TLS extensions.
31605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_OptionSet(nss_fd_, SSL_V2_COMPATIBLE_HELLO, PR_FALSE);
31615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess) {
31625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_V2_COMPATIBLE_HELLO");
31635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNEXPECTED;
31645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
31655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLVersionRange version_range;
31675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  version_range.min = ssl_config_.version_min;
31685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  version_range.max = ssl_config_.version_max;
31695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_VersionRangeSet(nss_fd_, &version_range);
31705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess) {
31715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_VersionRangeSet", "");
31725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_NO_SSL_VERSIONS_ENABLED;
31735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
31745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3175a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (ssl_config_.version_fallback) {
3176a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_FALLBACK_SCSV, PR_TRUE);
3177a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (rv != SECSuccess) {
3178a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      LogFailedNSSFunction(
3179a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          net_log_, "SSL_OptionSet", "SSL_ENABLE_FALLBACK_SCSV");
3180a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
3181a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
3182a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
31835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::vector<uint16>::const_iterator it =
31845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           ssl_config_.disabled_cipher_suites.begin();
31855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != ssl_config_.disabled_cipher_suites.end(); ++it) {
31865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This will fail if the specified cipher is not implemented by NSS, but
31875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the failure is harmless.
31885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SSL_CipherPrefSet(nss_fd_, *it, PR_FALSE);
31895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
31905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Support RFC 5077
31925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SESSION_TICKETS, PR_TRUE);
31935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess) {
31945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(
31955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        net_log_, "SSL_OptionSet", "SSL_ENABLE_SESSION_TICKETS");
31965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
31975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_FALSE_START,
31994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                     ssl_config_.false_start_enabled);
32005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess)
32015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_FALSE_START");
32025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We allow servers to request renegotiation. Since we're a client,
32045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // prohibiting this is rather a waste of time. Only servers are in a
32055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // position to prevent renegotiation attacks.
32065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // http://extendedsubset.com/?p=8
32075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_RENEGOTIATION,
32095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     SSL_RENEGOTIATE_TRANSITIONAL);
32105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess) {
32115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(
32125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        net_log_, "SSL_OptionSet", "SSL_ENABLE_RENEGOTIATION");
32135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
32145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  rv = SSL_OptionSet(nss_fd_, SSL_CBC_RANDOM_IV, PR_TRUE);
32165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess)
32175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_CBC_RANDOM_IV");
32185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3219bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// Added in NSS 3.15
32205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SSL_ENABLE_OCSP_STAPLING
32215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Request OCSP stapling even on platforms that don't support it, in
32225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // order to extract Certificate Transparency information.
32235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_OCSP_STAPLING,
32245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     (IsOCSPStaplingSupported() ||
32255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      ssl_config_.signed_cert_timestamps_enabled));
32265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (rv != SECSuccess) {
32275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_OptionSet",
32285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                         "SSL_ENABLE_OCSP_STAPLING");
32295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
32305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
32315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3232a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SIGNED_CERT_TIMESTAMPS,
3233a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                     ssl_config_.signed_cert_timestamps_enabled);
3234a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (rv != SECSuccess) {
3235a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_OptionSet",
3236a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                         "SSL_ENABLE_SIGNED_CERT_TIMESTAMPS");
3237a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
3238a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
32395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_OptionSet(nss_fd_, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE);
32405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess) {
32415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_HANDSHAKE_AS_CLIENT");
32425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNEXPECTED;
32435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
32445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!core_->Init(nss_fd_, nss_bufs))
32465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNEXPECTED;
32475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Tell SSL the hostname we're trying to connect to.
32495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSL_SetURL(nss_fd_, host_and_port_.host().c_str());
32505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Tell SSL we're a client; needed if not letting NSPR do socket I/O
32525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSL_ResetHandshake(nss_fd_, PR_FALSE);
32535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
32555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
32565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::InitializeSSLPeerName() {
32585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Tell NSS who we're connected to
32595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPEndPoint peer_address;
32605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int err = transport_->socket()->GetPeerAddress(&peer_address);
32615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (err != OK)
32625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return err;
32635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SockaddrStorage storage;
32655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!peer_address.ToSockAddr(storage.addr, &storage.addr_len))
3266effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return ERR_ADDRESS_INVALID;
32675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PRNetAddr peername;
32695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&peername, 0, sizeof(peername));
32705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_LE(static_cast<size_t>(storage.addr_len), sizeof(peername));
32715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t len = std::min(static_cast<size_t>(storage.addr_len),
32725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        sizeof(peername));
32735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(&peername, storage.addr, len);
32745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Adjust the address family field for BSD, whose sockaddr
32765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // structure has a one-byte length and one-byte address family
32775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // field at the beginning.  PRNetAddr has a two-byte address
32785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // family field at the beginning.
32795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  peername.raw.family = storage.addr->sa_family;
32805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memio_SetPeerName(nss_fd_, &peername);
32825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set the peer ID for session reuse.  This is necessary when we create an
32845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SSL tunnel through a proxy -- GetPeerName returns the proxy's address
32855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // rather than the destination server's address in that case.
32865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string peer_id = host_and_port_.ToString();
32875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the ssl_session_cache_shard_ is non-empty, we append it to the peer id.
32885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This will cause session cache misses between sockets with different values
32895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // of ssl_session_cache_shard_ and this is used to partition the session cache
32905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // for incognito mode.
32915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ssl_session_cache_shard_.empty()) {
32925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    peer_id += "/" + ssl_session_cache_shard_;
32935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
32945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECStatus rv = SSL_SetSockPeerID(nss_fd_, const_cast<char*>(peer_id.c_str()));
32955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess)
32965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_SetSockPeerID", peer_id.c_str());
32975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
32995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
33005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::DoConnectCallback(int rv) {
33025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterFunction(rv);
33035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(ERR_IO_PENDING, rv);
33045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!user_connect_callback_.is_null());
33055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::ResetAndReturn(&user_connect_callback_).Run(rv > OK ? OK : rv);
33075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LeaveFunction("");
33085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
33095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::OnHandshakeIOComplete(int result) {
33115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterFunction(result);
33125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = DoHandshakeLoop(result);
33135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != ERR_IO_PENDING) {
33145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
33155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DoConnectCallback(rv);
33165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
33175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LeaveFunction("");
33185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
33195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::DoHandshakeLoop(int last_io_result) {
33215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterFunction(last_io_result);
33225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = last_io_result;
33235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
33245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Default to STATE_NONE for next state.
33255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // (This is a quirk carried over from the windows
33265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // implementation.  It makes reading the logs a bit harder.)
33275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // State handlers can and often do call GotoState just
33285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // to stay in the current state.
33295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    State state = next_handshake_state_;
33305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GotoState(STATE_NONE);
33315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (state) {
33325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_HANDSHAKE:
33335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoHandshake();
33345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
33355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_HANDSHAKE_COMPLETE:
33365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoHandshakeComplete(rv);
33375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
33385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_VERIFY_CERT:
33395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK(rv == OK);
33405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoVerifyCert(rv);
33415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
33425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_VERIFY_CERT_COMPLETE:
33435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoVerifyCertComplete(rv);
33445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
33455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_NONE:
33465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
33475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = ERR_UNEXPECTED;
33485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(DFATAL) << "unexpected state " << state;
33495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
33505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
33515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (rv != ERR_IO_PENDING && next_handshake_state_ != STATE_NONE);
33525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LeaveFunction("");
33535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
33545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
33555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::DoHandshake() {
33575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterFunction("");
33585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = core_->Connect(
33595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&SSLClientSocketNSS::OnHandshakeIOComplete,
33605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(this)));
33615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GotoState(STATE_HANDSHAKE_COMPLETE);
33625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LeaveFunction(rv);
33645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
33655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
33665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::DoHandshakeComplete(int result) {
33685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterFunction(result);
33695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == OK) {
33715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // SSL handshake is completed. Let's verify the certificate.
33722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GotoState(STATE_VERIFY_CERT);
33735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Done!
33745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
33755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set_channel_id_sent(core_->state().channel_id_sent);
3376a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  set_signed_cert_timestamps_received(
3377a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      !core_->state().sct_list_from_tls_extension.empty());
33785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  set_stapled_ocsp_response_received(
33795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      !core_->state().stapled_ocsp_response.empty());
33805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LeaveFunction(result);
33825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
33835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
33845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::DoVerifyCert(int result) {
33865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!core_->state().server_cert_chain.empty());
33875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(core_->state().server_cert_chain[0]);
33885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GotoState(STATE_VERIFY_CERT_COMPLETE);
33905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the certificate is expected to be bad we can use the expectation as
33925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the cert status.
33935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::StringPiece der_cert(
33945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reinterpret_cast<char*>(
33955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          core_->state().server_cert_chain[0]->derCert.data),
33965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      core_->state().server_cert_chain[0]->derCert.len);
33975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CertStatus cert_status;
33985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ssl_config_.IsAllowedBadCert(der_cert, &cert_status)) {
33995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(start_cert_verification_time_.is_null());
34005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "Received an expected bad cert with status: " << cert_status;
34015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_cert_verify_result_.Reset();
34025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_cert_verify_result_.cert_status = cert_status;
34035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_cert_verify_result_.verified_cert = core_->state().server_cert;
34045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
34055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
34065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We may have failed to create X509Certificate object if we are
34085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // running inside sandbox.
3409868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!core_->state().server_cert.get()) {
34105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_cert_verify_result_.Reset();
34115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_cert_verify_result_.cert_status = CERT_STATUS_INVALID;
34125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_CERT_INVALID;
34135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
34145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  start_cert_verification_time_ = base::TimeTicks::Now();
34165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int flags = 0;
34185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ssl_config_.rev_checking_enabled)
34195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    flags |= CertVerifier::VERIFY_REV_CHECKING_ENABLED;
34205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ssl_config_.verify_ev_cert)
34215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    flags |= CertVerifier::VERIFY_EV_CERT;
34225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ssl_config_.cert_io_enabled)
34235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    flags |= CertVerifier::VERIFY_CERT_IO_ENABLED;
3424558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  if (ssl_config_.rev_checking_required_local_anchors)
3425558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    flags |= CertVerifier::VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS;
34265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  verifier_.reset(new SingleRequestCertVerifier(cert_verifier_));
34275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return verifier_->Verify(
3428868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      core_->state().server_cert.get(),
3429868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      host_and_port_.host(),
3430868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      flags,
34317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      SSLConfigService::GetCRLSet().get(),
3432868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      &server_cert_verify_result_,
34335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&SSLClientSocketNSS::OnHandshakeIOComplete,
34345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(this)),
34355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_log_);
34365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
34375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Derived from AuthCertificateCallback() in
34395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// mozilla/source/security/manager/ssl/src/nsNSSCallbacks.cpp.
34405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketNSS::DoVerifyCertComplete(int result) {
34415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  verifier_.reset();
34425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!start_cert_verification_time_.is_null()) {
34445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::TimeDelta verify_time =
34455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::TimeTicks::Now() - start_cert_verification_time_;
34465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (result == OK)
34475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        UMA_HISTOGRAM_TIMES("Net.SSLCertVerificationTime", verify_time);
34485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
34495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        UMA_HISTOGRAM_TIMES("Net.SSLCertVerificationTimeError", verify_time);
34505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
34515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We used to remember the intermediate CA certs in the NSS database
34535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // persistently.  However, NSS opens a connection to the SQLite database
34545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // during NSS initialization and doesn't close the connection until NSS
34555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // shuts down.  If the file system where the database resides is gone,
34565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the database connection goes bad.  What's worse, the connection won't
34575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // recover when the file system comes back.  Until this NSS or SQLite bug
34585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is fixed, we need to  avoid using the NSS database for non-essential
34595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // purposes.  See https://bugzilla.mozilla.org/show_bug.cgi?id=508081 and
34605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // http://crbug.com/15630 for more info.
34615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(hclam): Skip logging if server cert was expected to be bad because
34635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |server_cert_verify_result_| doesn't contain all the information about
34645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the cert.
34655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == OK)
34665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogConnectionTypeMetrics();
34675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OFFICIAL_BUILD) && !defined(OS_ANDROID) && !defined(OS_IOS)
34695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Take care of any mandates for public key pinning.
34705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
34715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Pinning is only enabled for official builds to make sure that others don't
34725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // end up with pins that cannot be easily updated.
34735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
3474c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // TODO(agl): We might have an issue here where a request for foo.example.com
34755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // merges into a SPDY connection to www.example.com, and gets a different
34765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // certificate.
34775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3478c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Perform pin validation if, and only if, all these conditions obtain:
3479c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  //
3480c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // * a TransportSecurityState object is available;
3481c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // * the server's certificate chain is valid (or suffers from only a minor
3482c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  //   error);
3483c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // * the server's certificate chain chains up to a known root (i.e. not a
3484c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  //   user-installed trust anchor); and
3485c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // * the build is recent (very old builds should fail open so that users
3486c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  //   have some chance to recover).
3487c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  //
34885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const CertStatus cert_status = server_cert_verify_result_.cert_status;
3489c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (transport_security_state_ &&
3490c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      (result == OK ||
3491c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       (IsCertificateError(result) && IsCertStatusMinorError(cert_status))) &&
34925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      server_cert_verify_result_.is_issued_by_known_root &&
3493c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      TransportSecurityState::IsBuildTimely()) {
34945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool sni_available =
34955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ssl_config_.version_max >= SSL_PROTOCOL_VERSION_TLS1 ||
34965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ssl_config_.version_fallback;
34975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& host = host_and_port_.host();
34985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TransportSecurityState::DomainState domain_state;
35005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (transport_security_state_->GetDomainState(host, sni_available,
35015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  &domain_state) &&
35022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        domain_state.HasPublicKeyPins()) {
35032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!domain_state.CheckPublicKeyPins(
3504c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)              server_cert_verify_result_.public_key_hashes)) {
3505c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        result = ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN;
3506c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        UMA_HISTOGRAM_BOOLEAN("Net.PublicKeyPinSuccess", false);
3507c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        TransportSecurityState::ReportUMAOnPinFailure(host);
35085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
35095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        UMA_HISTOGRAM_BOOLEAN("Net.PublicKeyPinSuccess", true);
35105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
35115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
35125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
35135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
35145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3515a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (result == OK) {
3516a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // Only check Certificate Transparency if there were no other errors with
3517a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // the connection.
3518a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    VerifyCT();
35195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
35205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Only cache the session if the certificate verified successfully.
35215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    core_->CacheSessionIfNecessary();
3522a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
3523a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
3524a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  completed_handshake_ = true;
3525a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
35265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Exit DoHandshakeLoop and return the result to the caller to Connect.
35275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(STATE_NONE, next_handshake_state_);
35285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
35295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
35305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3531a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void SSLClientSocketNSS::VerifyCT() {
3532a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!cert_transparency_verifier_)
3533a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return;
3534a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
3535a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Note that this is a completely synchronous operation: The CT Log Verifier
3536a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // gets all the data it needs for SCT verification and does not do any
3537a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // external communication.
3538a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  int result = cert_transparency_verifier_->Verify(
3539a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      server_cert_verify_result_.verified_cert,
35405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      core_->state().stapled_ocsp_response,
3541a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      core_->state().sct_list_from_tls_extension,
3542a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      &ct_verify_result_,
3543a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      net_log_);
35445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // TODO(ekasper): wipe stapled_ocsp_response and sct_list_from_tls_extension
35455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // from the state after verification is complete, to conserve memory.
3546a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
3547a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  VLOG(1) << "CT Verification complete: result " << result
3548a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          << " Invalid scts: " << ct_verify_result_.invalid_scts.size()
3549a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          << " Verified scts: " << ct_verify_result_.verified_scts.size()
3550a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          << " scts from unknown logs: "
3551a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          << ct_verify_result_.unknown_logs_scts.size();
3552a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
3553a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
35545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::LogConnectionTypeMetrics() const {
35555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdateConnectionTypeHistograms(CONNECTION_SSL);
35565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ssl_version = SSLConnectionStatusToVersion(
35575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      core_->state().ssl_connection_status);
35585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (ssl_version) {
35595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_CONNECTION_VERSION_SSL2:
35605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UpdateConnectionTypeHistograms(CONNECTION_SSL_SSL2);
35615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
35625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_CONNECTION_VERSION_SSL3:
35635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UpdateConnectionTypeHistograms(CONNECTION_SSL_SSL3);
35645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
35655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_CONNECTION_VERSION_TLS1:
35665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UpdateConnectionTypeHistograms(CONNECTION_SSL_TLS1);
35675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
35685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_CONNECTION_VERSION_TLS1_1:
35695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UpdateConnectionTypeHistograms(CONNECTION_SSL_TLS1_1);
35705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
35715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_CONNECTION_VERSION_TLS1_2:
35725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UpdateConnectionTypeHistograms(CONNECTION_SSL_TLS1_2);
35735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
35745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
35755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
35765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketNSS::EnsureThreadIdAssigned() const {
35785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock auto_lock(lock_);
35795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (valid_thread_id_ != base::kInvalidThreadId)
35805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
35815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  valid_thread_id_ = base::PlatformThread::CurrentId();
35825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
35835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketNSS::CalledOnValidThread() const {
35855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnsureThreadIdAssigned();
35865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock auto_lock(lock_);
35875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return valid_thread_id_ == base::PlatformThread::CurrentId();
35885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
35895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3590a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void SSLClientSocketNSS::AddSCTInfoToSSLInfo(SSLInfo* ssl_info) const {
3591a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  for (ct::SCTList::const_iterator iter =
3592a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)       ct_verify_result_.verified_scts.begin();
3593a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)       iter != ct_verify_result_.verified_scts.end(); ++iter) {
3594a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ssl_info->signed_certificate_timestamps.push_back(
3595a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        SignedCertificateTimestampAndStatus(*iter, ct::SCT_STATUS_OK));
3596a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
3597a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  for (ct::SCTList::const_iterator iter =
3598a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)       ct_verify_result_.invalid_scts.begin();
3599a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)       iter != ct_verify_result_.invalid_scts.end(); ++iter) {
3600a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ssl_info->signed_certificate_timestamps.push_back(
3601a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        SignedCertificateTimestampAndStatus(*iter, ct::SCT_STATUS_INVALID));
3602a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
3603a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  for (ct::SCTList::const_iterator iter =
3604a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)       ct_verify_result_.unknown_logs_scts.begin();
3605a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)       iter != ct_verify_result_.unknown_logs_scts.end(); ++iter) {
3606a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ssl_info->signed_certificate_timestamps.push_back(
3607a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        SignedCertificateTimestampAndStatus(*iter,
3608a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                            ct::SCT_STATUS_LOG_UNKNOWN));
3609a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
3610a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
3611a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
3612a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)scoped_refptr<X509Certificate>
3613a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)SSLClientSocketNSS::GetUnverifiedServerCertificateChain() const {
3614a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return core_->state().server_cert.get();
3615a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
3616a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
36175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ServerBoundCertService* SSLClientSocketNSS::GetServerBoundCertService() const {
36185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return server_bound_cert_service_;
36195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
36205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
3622