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