diff options
-rw-r--r-- | DEPS | 2 | ||||
-rw-r--r-- | chrome/browser/io_thread.cc | 32 | ||||
-rw-r--r-- | net/BUILD.gn | 2 | ||||
-rw-r--r-- | net/net.gypi | 2 | ||||
-rw-r--r-- | net/net_common.gypi | 2 | ||||
-rw-r--r-- | net/socket/ssl_client_socket.cc | 8 | ||||
-rw-r--r-- | net/socket/ssl_client_socket.h | 18 | ||||
-rw-r--r-- | net/socket/ssl_client_socket_openssl.cc | 43 | ||||
-rw-r--r-- | net/socket/ssl_client_socket_openssl.h | 17 | ||||
-rw-r--r-- | net/ssl/ssl_key_logger.cc | 68 | ||||
-rw-r--r-- | net/ssl/ssl_key_logger.h | 50 | ||||
-rw-r--r-- | third_party/boringssl/boringssl.gypi | 1 |
12 files changed, 209 insertions, 36 deletions
@@ -67,7 +67,7 @@ vars = { # Three lines of non-changing comments so that # the commit queue can handle CLs rolling BoringSSL # and whatever else without interference from each other. - 'boringssl_revision': '3ac32b1eda0da7a99d9c2b6c605fe50af80ccd90', + 'boringssl_revision': 'fde89b43c347155798dee8b1210c2c5faabe25f8', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling nss # and whatever else without interference from each other. diff --git a/chrome/browser/io_thread.cc b/chrome/browser/io_thread.cc index 485999c..37b1c40 100644 --- a/chrome/browser/io_thread.cc +++ b/chrome/browser/io_thread.cc @@ -13,6 +13,7 @@ #include "base/compiler_specific.h" #include "base/debug/leak_tracker.h" #include "base/environment.h" +#include "base/files/file_path.h" #include "base/logging.h" #include "base/metrics/field_trial.h" #include "base/prefs/pref_registry_simple.h" @@ -23,6 +24,7 @@ #include "base/strings/string_piece.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" +#include "base/strings/utf_string_conversions.h" #include "base/threading/sequenced_worker_pool.h" #include "base/threading/thread.h" #include "base/threading/worker_pool.h" @@ -174,20 +176,24 @@ void ObserveKeychainEvents() { // Gets file path into ssl_keylog_file from command line argument or // environment variable. Command line argument has priority when // both specified. -std::string GetSSLKeyLogFile(const base::CommandLine& command_line) { +base::FilePath GetSSLKeyLogFile(const base::CommandLine& command_line) { if (command_line.HasSwitch(switches::kSSLKeyLogFile)) { - std::string file = - command_line.GetSwitchValueASCII(switches::kSSLKeyLogFile); - if (!file.empty()) { - return file; - } - + base::FilePath path = + command_line.GetSwitchValuePath(switches::kSSLKeyLogFile); + if (!path.empty()) + return path; LOG(WARNING) << "ssl-key-log-file argument missing"; } + scoped_ptr<base::Environment> env(base::Environment::Create()); - std::string file; - env->GetVar("SSLKEYLOGFILE", &file); - return file; + std::string path_str; + env->GetVar("SSLKEYLOGFILE", &path_str); +#if defined(OS_WIN) + // base::Environment returns environment variables in UTF-8 on Windows. + return base::FilePath(base::UTF8ToUTF16(path_str)); +#else + return base::FilePath(path_str); +#endif } // Used for the "system" URLRequestContext. @@ -587,9 +593,11 @@ void IOThread::Init() { *base::CommandLine::ForCurrentProcess(); // Export ssl keys if log file specified. - std::string ssl_keylog_file = GetSSLKeyLogFile(command_line); + base::FilePath ssl_keylog_file = GetSSLKeyLogFile(command_line); if (!ssl_keylog_file.empty()) { - net::SSLClientSocket::SetSSLKeyLogFile(ssl_keylog_file); + net::SSLClientSocket::SetSSLKeyLogFile( + ssl_keylog_file, + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)); } DCHECK(!globals_); diff --git a/net/BUILD.gn b/net/BUILD.gn index 3f743ca..74d0c67 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn @@ -208,6 +208,8 @@ if (!is_nacl) { "ssl/openssl_ssl_util.h", "ssl/ssl_client_session_cache_openssl.cc", "ssl/ssl_client_session_cache_openssl.h", + "ssl/ssl_key_logger.cc", + "ssl/ssl_key_logger.h", "ssl/ssl_platform_key.h", "ssl/ssl_platform_key_task_runner.cc", "ssl/ssl_platform_key_task_runner.h", diff --git a/net/net.gypi b/net/net.gypi index 58261b7..bfab4cb 100644 --- a/net/net.gypi +++ b/net/net.gypi @@ -1148,6 +1148,8 @@ 'ssl/client_cert_store_win.h', 'ssl/ssl_config_service_defaults.cc', 'ssl/ssl_config_service_defaults.h', + 'ssl/ssl_key_logger.cc', + 'ssl/ssl_key_logger.h', 'ssl/ssl_platform_key.h', 'ssl/ssl_platform_key_task_runner.cc', 'ssl/ssl_platform_key_task_runner.h', diff --git a/net/net_common.gypi b/net/net_common.gypi index 9489d0a..d373325 100644 --- a/net/net_common.gypi +++ b/net/net_common.gypi @@ -163,6 +163,8 @@ 'ssl/openssl_ssl_util.h', 'ssl/ssl_client_session_cache_openssl.cc', 'ssl/ssl_client_session_cache_openssl.h', + 'ssl/ssl_key_logger.cc', + 'ssl/ssl_key_logger.h', 'ssl/ssl_platform_key.h', 'ssl/ssl_platform_key_nss.cc', 'ssl/ssl_platform_key_task_runner.cc', diff --git a/net/socket/ssl_client_socket.cc b/net/socket/ssl_client_socket.cc index 68d44f8..ccd1f86 100644 --- a/net/socket/ssl_client_socket.cc +++ b/net/socket/ssl_client_socket.cc @@ -83,9 +83,11 @@ const char* SSLClientSocket::NextProtoStatusToString( } // static -void SSLClientSocket::SetSSLKeyLogFile(const std::string& ssl_keylog_file) { -#if defined(USE_OPENSSL) - SSLClientSocketOpenSSL::SetSSLKeyLogFile(ssl_keylog_file); +void SSLClientSocket::SetSSLKeyLogFile( + const base::FilePath& path, + const scoped_refptr<base::SequencedTaskRunner>& task_runner) { +#if defined(USE_OPENSSL) && !defined(OS_NACL) + SSLClientSocketOpenSSL::SetSSLKeyLogFile(path, task_runner); #else NOTIMPLEMENTED(); #endif diff --git a/net/socket/ssl_client_socket.h b/net/socket/ssl_client_socket.h index ad458b2..c8bfa8e 100644 --- a/net/socket/ssl_client_socket.h +++ b/net/socket/ssl_client_socket.h @@ -15,6 +15,11 @@ #include "net/socket/stream_socket.h" #include "net/ssl/ssl_failure_state.h" +namespace base { +class FilePath; +class SequencedTaskRunner; +} + namespace net { class CertPolicyEnforcer; @@ -114,9 +119,16 @@ class NET_EXPORT SSLClientSocket : public SSLSocket { static const char* NextProtoStatusToString(const NextProtoStatus status); - // Export SSL key material to be logged to the specified file if platform - // uses OpenSSL. Must be called before SSLClientSockets are created. - static void SetSSLKeyLogFile(const std::string& ssl_keylog_file); + // Log SSL key material to |path| on |task_runner|. Must be called before any + // SSLClientSockets are created. + // + // TODO(davidben): Switch this to a parameter on the SSLClientSocketContext + // once https://crbug.com/458365 is resolved. This will require splitting + // SSLKeyLogger into an interface, built with OS_NACL and a non-NaCl + // SSLKeyLoggerImpl. + static void SetSSLKeyLogFile( + const base::FilePath& path, + const scoped_refptr<base::SequencedTaskRunner>& task_runner); // Returns true if |error| is OK or |load_flags| ignores certificate errors // and |error| is a certificate error. diff --git a/net/socket/ssl_client_socket_openssl.cc b/net/socket/ssl_client_socket_openssl.cc index 34c8601..090f2bd 100644 --- a/net/socket/ssl_client_socket_openssl.cc +++ b/net/socket/ssl_client_socket_openssl.cc @@ -51,6 +51,10 @@ #include "base/win/windows_version.h" #endif +#if !defined(OS_NACL) +#include "net/ssl/ssl_key_logger.h" +#endif + #if defined(USE_NSS_CERTS) || defined(OS_IOS) #include "net/cert_net/nss_ocsp.h" #endif @@ -146,11 +150,6 @@ ScopedX509Stack OSCertHandlesToOpenSSL( return stack.Pass(); } -int LogErrorCallback(const char* str, size_t len, void* context) { - LOG(ERROR) << base::StringPiece(str, len); - return 1; -} - bool EVP_MDToPrivateKeyHash(const EVP_MD* md, SSLPrivateKey::Hash* hash) { switch (EVP_MD_type(md)) { case NID_md5_sha1: @@ -206,6 +205,16 @@ class SSLClientSocketOpenSSL::SSLContext { return SSL_set_ex_data(ssl, ssl_socket_data_index_, socket) != 0; } +#if !defined(OS_NACL) + void SetSSLKeyLogFile( + const base::FilePath& path, + const scoped_refptr<base::SequencedTaskRunner>& task_runner) { + DCHECK(!ssl_key_logger_); + ssl_key_logger_.reset(new SSLKeyLogger(path, task_runner)); + SSL_CTX_set_keylog_callback(ssl_ctx_.get(), KeyLogCallback); + } +#endif + static const SSL_PRIVATE_KEY_METHOD kPrivateKeyMethod; private: @@ -335,12 +344,22 @@ class SSLClientSocketOpenSSL::SSLContext { return socket->PrivateKeySignCompleteCallback(out, out_len, max_out); } +#if !defined(OS_NACL) + static void KeyLogCallback(const SSL* ssl, const char* line) { + GetInstance()->ssl_key_logger_->WriteLine(line); + } +#endif + // This is the index used with SSL_get_ex_data to retrieve the owner // SSLClientSocketOpenSSL object from an SSL instance. int ssl_socket_data_index_; ScopedSSL_CTX ssl_ctx_; +#if !defined(OS_NACL) + scoped_ptr<SSLKeyLogger> ssl_key_logger_; +#endif + // TODO(davidben): Use a separate cache per URLRequestContext. // https://crbug.com/458365 // @@ -489,17 +508,13 @@ SSLClientSocketOpenSSL::~SSLClientSocketOpenSSL() { Disconnect(); } +#if !defined(OS_NACL) void SSLClientSocketOpenSSL::SetSSLKeyLogFile( - const std::string& ssl_keylog_file) { - crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); - BIO* bio = BIO_new_file(ssl_keylog_file.c_str(), "a"); - if (!bio) { - LOG(ERROR) << "Failed to open " << ssl_keylog_file; - ERR_print_errors_cb(&LogErrorCallback, NULL); - } else { - SSL_CTX_set_keylog_bio(SSLContext::GetInstance()->ssl_ctx(), bio); - } + const base::FilePath& ssl_keylog_file, + const scoped_refptr<base::SequencedTaskRunner>& task_runner) { + SSLContext::GetInstance()->SetSSLKeyLogFile(ssl_keylog_file, task_runner); } +#endif void SSLClientSocketOpenSSL::GetSSLCertRequestInfo( SSLCertRequestInfo* cert_request_info) { diff --git a/net/socket/ssl_client_socket_openssl.h b/net/socket/ssl_client_socket_openssl.h index a5d545b..c200c31 100644 --- a/net/socket/ssl_client_socket_openssl.h +++ b/net/socket/ssl_client_socket_openssl.h @@ -12,9 +12,10 @@ #include <string> #include <vector> -#include "base/compiler_specific.h" +#include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" +#include "build/build_config.h" #include "net/base/completion_callback.h" #include "net/base/io_buffer.h" #include "net/cert/cert_verifier.h" @@ -28,6 +29,11 @@ #include "net/ssl/ssl_config_service.h" #include "net/ssl/ssl_failure_state.h" +namespace base { +class FilePath; +class SequencedTaskRunner; +} + namespace net { class CertVerifier; @@ -53,8 +59,13 @@ class SSLClientSocketOpenSSL : public SSLClientSocket { return ssl_session_cache_shard_; } - // Export ssl key log files if env variable is not set. - static void SetSSLKeyLogFile(const std::string& ssl_keylog_file); +#if !defined(OS_NACL) + // Log SSL key material to |path| on |task_runner|. Must be called before any + // SSLClientSockets are created. + static void SetSSLKeyLogFile( + const base::FilePath& path, + const scoped_refptr<base::SequencedTaskRunner>& task_runner); +#endif // SSLClientSocket implementation. void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override; diff --git a/net/ssl/ssl_key_logger.cc b/net/ssl/ssl_key_logger.cc new file mode 100644 index 0000000..6e4c2d4 --- /dev/null +++ b/net/ssl/ssl_key_logger.cc @@ -0,0 +1,68 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/ssl/ssl_key_logger.h" + +#include <stdio.h> + +#include "base/bind.h" +#include "base/files/file_util.h" +#include "base/files/scoped_file.h" +#include "base/location.h" +#include "base/logging.h" +#include "base/sequence_checker.h" +#include "base/sequenced_task_runner.h" + +namespace net { + +// An object which lives on the background SequencedTaskRunner and performs the +// blocking file operations. +class SSLKeyLogger::Core { + public: + Core() { sequence_checker_.DetachFromSequence(); } + ~Core() { DCHECK(sequence_checker_.CalledOnValidSequencedThread()); } + + void OpenFile(const base::FilePath& path) { + DCHECK(sequence_checker_.CalledOnValidSequencedThread()); + DCHECK(!file_); + file_.reset(base::OpenFile(path, "a")); + if (!file_) + LOG(WARNING) << "Could not open " << path.value(); + } + + void WriteLine(const std::string& line) { + DCHECK(sequence_checker_.CalledOnValidSequencedThread()); + if (!file_) + return; + fprintf(file_.get(), "%s\n", line.c_str()); + fflush(file_.get()); + } + + private: + base::ScopedFILE file_; + base::SequenceChecker sequence_checker_; + + DISALLOW_COPY_AND_ASSIGN(Core); +}; + +SSLKeyLogger::SSLKeyLogger( + const base::FilePath& path, + const scoped_refptr<base::SequencedTaskRunner>& task_runner) + : task_runner_(task_runner), core_(new Core) { + task_runner_->PostTask( + FROM_HERE, + base::Bind(&Core::OpenFile, base::Unretained(core_.get()), path)); +} + +SSLKeyLogger::~SSLKeyLogger() { + task_runner_->DeleteSoon(FROM_HERE, core_.release()); +} + +void SSLKeyLogger::WriteLine(const std::string& line) { + task_runner_->PostTask( + FROM_HERE, + base::Bind(&Core::WriteLine, base::Unretained(core_.get()), line)); +} + +} // namespace net diff --git a/net/ssl/ssl_key_logger.h b/net/ssl/ssl_key_logger.h new file mode 100644 index 0000000..dcaf6c6 --- /dev/null +++ b/net/ssl/ssl_key_logger.h @@ -0,0 +1,50 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_SSL_SSL_KEY_LOGGER_H_ +#define NET_SSL_SSL_KEY_LOGGER_H_ + +#include <string> + +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" + +namespace base { +class FilePath; +class SequencedTaskRunner; +} + +namespace net { + +// SSLKeyLogger logs SSL key material for debugging purposes. This should only +// be used when requested by the user, typically via the SSLKEYLOGFILE +// environment variable. See also +// https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format. +class SSLKeyLogger { + public: + // Creates a new SSLKeyLogger which writes to |path|, scheduling write + // operations on |task_runner|. + SSLKeyLogger(const base::FilePath& path, + const scoped_refptr<base::SequencedTaskRunner>& task_runner); + ~SSLKeyLogger(); + + // Writes |line| followed by a newline. This may be called by multiple threads + // simultaneously. If two calls race, the order of the lines is undefined, but + // each line will be written atomically. + void WriteLine(const std::string& line); + + private: + class Core; + + scoped_refptr<base::SequencedTaskRunner> task_runner_; + // Destroyed on |task_runner_|. + scoped_ptr<Core> core_; + + DISALLOW_COPY_AND_ASSIGN(SSLKeyLogger); +}; + +} // namespace net + +#endif // NET_SSL_SSL_KEY_LOGGER_H_ diff --git a/third_party/boringssl/boringssl.gypi b/third_party/boringssl/boringssl.gypi index c3ffa5b..096c903 100644 --- a/third_party/boringssl/boringssl.gypi +++ b/third_party/boringssl/boringssl.gypi @@ -324,6 +324,7 @@ 'linux-arm/crypto/sha/sha512-armv4.S', 'src/crypto/chacha/chacha_vec_arm.S', 'src/crypto/cpu-arm-asm.S', + 'src/crypto/curve25519/asm/x25519-arm.S', 'src/crypto/poly1305/poly1305_arm_asm.S', ], 'boringssl_linux_x86_sources': [ |