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