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