diff options
-rw-r--r-- | net/BUILD.gn | 3 | ||||
-rw-r--r-- | net/net.gyp | 1 | ||||
-rw-r--r-- | net/net.gypi | 3 | ||||
-rw-r--r-- | net/net_common.gypi | 2 | ||||
-rw-r--r-- | net/socket/ssl_client_socket_openssl_unittest.cc | 267 | ||||
-rw-r--r-- | net/socket/ssl_client_socket_unittest.cc | 119 | ||||
-rw-r--r-- | net/ssl/test_ssl_private_key.cc | 128 | ||||
-rw-r--r-- | net/ssl/test_ssl_private_key.h | 25 |
8 files changed, 278 insertions, 270 deletions
diff --git a/net/BUILD.gn b/net/BUILD.gn index 5653169..b8c44cb 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn @@ -225,6 +225,8 @@ if (!is_nacl) { "ssl/ssl_platform_key.h", "ssl/ssl_platform_key_task_runner.cc", "ssl/ssl_platform_key_task_runner.h", + "ssl/test_ssl_private_key.cc", + "ssl/test_ssl_private_key.h", "ssl/threaded_ssl_private_key.cc", "ssl/threaded_ssl_private_key.h", "ssl/token_binding_openssl.cc", @@ -1481,7 +1483,6 @@ test("net_unittests") { } else { sources -= [ "quic/test_tools/crypto_test_utils_openssl.cc", - "socket/ssl_client_socket_openssl_unittest.cc", "ssl/ssl_client_session_cache_openssl_unittest.cc", ] } diff --git a/net/net.gyp b/net/net.gyp index 16c2f7b..68a4cc0 100644 --- a/net/net.gyp +++ b/net/net.gyp @@ -255,7 +255,6 @@ }, { # else !use_openssl: remove the unneeded files and pull in NSS. 'sources!': [ 'quic/test_tools/crypto_test_utils_openssl.cc', - 'socket/ssl_client_socket_openssl_unittest.cc', 'ssl/ssl_client_session_cache_openssl_unittest.cc', ], }, diff --git a/net/net.gypi b/net/net.gypi index a6394f6..472941f 100644 --- a/net/net.gypi +++ b/net/net.gypi @@ -1183,6 +1183,8 @@ 'ssl/ssl_platform_key_task_runner.cc', 'ssl/ssl_platform_key_task_runner.h', 'ssl/ssl_platform_key_win.cc', + 'ssl/test_ssl_private_key.cc', + 'ssl/test_ssl_private_key.h', 'ssl/threaded_ssl_private_key.cc', 'ssl/threaded_ssl_private_key.h', 'ssl/token_binding.h', @@ -1689,7 +1691,6 @@ 'socket/socks5_client_socket_unittest.cc', 'socket/socks_client_socket_pool_unittest.cc', 'socket/socks_client_socket_unittest.cc', - 'socket/ssl_client_socket_openssl_unittest.cc', 'socket/ssl_client_socket_pool_unittest.cc', 'socket/ssl_client_socket_unittest.cc', 'socket/ssl_server_socket_unittest.cc', diff --git a/net/net_common.gypi b/net/net_common.gypi index 6d7f943..fe14edd 100644 --- a/net/net_common.gypi +++ b/net/net_common.gypi @@ -188,6 +188,8 @@ 'ssl/ssl_platform_key_nss.cc', 'ssl/ssl_platform_key_task_runner.cc', 'ssl/ssl_platform_key_task_runner.h', + 'ssl/test_ssl_private_key.cc', + 'ssl/test_ssl_private_key.h', 'ssl/threaded_ssl_private_key.cc', 'ssl/threaded_ssl_private_key.h', 'ssl/token_binding_openssl.cc', diff --git a/net/socket/ssl_client_socket_openssl_unittest.cc b/net/socket/ssl_client_socket_openssl_unittest.cc deleted file mode 100644 index a1ab91a..0000000 --- a/net/socket/ssl_client_socket_openssl_unittest.cc +++ /dev/null @@ -1,267 +0,0 @@ -// Copyright (c) 2012 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/socket/ssl_client_socket.h" - -#include <errno.h> -#include <openssl/bio.h> -#include <openssl/bn.h> -#include <openssl/evp.h> -#include <openssl/pem.h> -#include <openssl/rsa.h> -#include <string.h> -#include <utility> - -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/memory/ref_counted.h" -#include "base/values.h" -#include "crypto/openssl_util.h" -#include "crypto/scoped_openssl_types.h" -#include "net/base/address_list.h" -#include "net/base/io_buffer.h" -#include "net/base/net_errors.h" -#include "net/base/test_completion_callback.h" -#include "net/base/test_data_directory.h" -#include "net/cert/mock_cert_verifier.h" -#include "net/cert/test_root_certs.h" -#include "net/dns/host_resolver.h" -#include "net/http/transport_security_state.h" -#include "net/log/net_log.h" -#include "net/socket/client_socket_factory.h" -#include "net/socket/client_socket_handle.h" -#include "net/socket/socket_test_util.h" -#include "net/socket/tcp_client_socket.h" -#include "net/ssl/openssl_client_key_store.h" -#include "net/ssl/ssl_cert_request_info.h" -#include "net/ssl/ssl_config_service.h" -#include "net/ssl/ssl_platform_key.h" -#include "net/test/cert_test_util.h" -#include "net/test/spawned_test_server/spawned_test_server.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "testing/platform_test.h" - -namespace net { - -namespace { - -// These client auth tests are currently dependent on OpenSSL's struct X509. -#if defined(USE_OPENSSL_CERTS) - -// Loads a PEM-encoded private key file into a scoped EVP_PKEY object. -// |filepath| is the private key file path. -// |*pkey| is reset to the new EVP_PKEY on success, untouched otherwise. -// Returns true on success, false on failure. -bool LoadPrivateKeyOpenSSL( - const base::FilePath& filepath, - crypto::ScopedEVP_PKEY* pkey) { - std::string data; - if (!base::ReadFileToString(filepath, &data)) { - LOG(ERROR) << "Could not read private key file: " - << filepath.value() << ": " << strerror(errno); - return false; - } - crypto::ScopedBIO bio(BIO_new_mem_buf( - const_cast<char*>(reinterpret_cast<const char*>(data.data())), - static_cast<int>(data.size()))); - if (!bio.get()) { - LOG(ERROR) << "Could not allocate BIO for buffer?"; - return false; - } - EVP_PKEY* result = PEM_read_bio_PrivateKey(bio.get(), NULL, NULL, NULL); - if (result == NULL) { - LOG(ERROR) << "Could not decode private key file: " - << filepath.value(); - return false; - } - pkey->reset(result); - return true; -} - -class SSLClientSocketOpenSSLClientAuthTest : public PlatformTest { - public: - SSLClientSocketOpenSSLClientAuthTest() - : socket_factory_(ClientSocketFactory::GetDefaultFactory()), - cert_verifier_(new MockCertVerifier), - transport_security_state_(new TransportSecurityState) { - cert_verifier_->set_default_result(OK); - context_.cert_verifier = cert_verifier_.get(); - context_.transport_security_state = transport_security_state_.get(); - key_store_ = OpenSSLClientKeyStore::GetInstance(); - } - - ~SSLClientSocketOpenSSLClientAuthTest() override { key_store_->Flush(); } - - protected: - scoped_ptr<SSLClientSocket> CreateSSLClientSocket( - scoped_ptr<StreamSocket> transport_socket, - const HostPortPair& host_and_port, - const SSLConfig& ssl_config) { - scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle); - connection->SetSocket(std::move(transport_socket)); - return socket_factory_->CreateSSLClientSocket( - std::move(connection), host_and_port, ssl_config, context_); - } - - // Connect to a HTTPS test server. - bool ConnectToTestServer(SpawnedTestServer::SSLOptions& ssl_options) { - test_server_.reset(new SpawnedTestServer(SpawnedTestServer::TYPE_HTTPS, - ssl_options, - base::FilePath())); - if (!test_server_->Start()) { - LOG(ERROR) << "Could not start SpawnedTestServer"; - return false; - } - - if (!test_server_->GetAddressList(&addr_)) { - LOG(ERROR) << "Could not get SpawnedTestServer address list"; - return false; - } - - transport_.reset(new TCPClientSocket( - addr_, &log_, NetLog::Source())); - int rv = callback_.GetResult( - transport_->Connect(callback_.callback())); - if (rv != OK) { - LOG(ERROR) << "Could not connect to SpawnedTestServer"; - return false; - } - return true; - } - - // Record a certificate's private key to ensure it can be used - // by the OpenSSL-based SSLClientSocket implementation. - // |ssl_config| provides a client certificate. - // |private_key| must be an EVP_PKEY for the corresponding private key. - // Returns true on success, false on failure. - bool RecordPrivateKey(SSLConfig& ssl_config, - EVP_PKEY* private_key) { - return key_store_->RecordClientCertPrivateKey( - ssl_config.client_cert.get(), private_key); - } - - // Create an SSLClientSocket object and use it to connect to a test - // server, then wait for connection results. This must be called after - // a succesful ConnectToTestServer() call. - // |ssl_config| the SSL configuration to use. - // |result| will retrieve the ::Connect() result value. - // Returns true on succes, false otherwise. Success means that the socket - // could be created and its Connect() was called, not that the connection - // itself was a success. - bool CreateAndConnectSSLClientSocket(const SSLConfig& ssl_config, - int* result) { - sock_ = CreateSSLClientSocket(std::move(transport_), - test_server_->host_port_pair(), ssl_config); - - if (sock_->IsConnected()) { - LOG(ERROR) << "SSL Socket prematurely connected"; - return false; - } - - *result = callback_.GetResult(sock_->Connect(callback_.callback())); - return true; - } - - - // Check that the client certificate was sent. - // Returns true on success. - bool CheckSSLClientSocketSentCert() { - SSLInfo ssl_info; - sock_->GetSSLInfo(&ssl_info); - return ssl_info.client_cert_sent; - } - - ClientSocketFactory* socket_factory_; - scoped_ptr<MockCertVerifier> cert_verifier_; - scoped_ptr<TransportSecurityState> transport_security_state_; - SSLClientSocketContext context_; - OpenSSLClientKeyStore* key_store_; - scoped_ptr<SpawnedTestServer> test_server_; - AddressList addr_; - TestCompletionCallback callback_; - NetLog log_; - scoped_ptr<StreamSocket> transport_; - scoped_ptr<SSLClientSocket> sock_; -}; - -// Connect to a server requesting client authentication, do not send -// any client certificates. It should refuse the connection. -TEST_F(SSLClientSocketOpenSSLClientAuthTest, NoCert) { - SpawnedTestServer::SSLOptions ssl_options; - ssl_options.request_client_certificate = true; - - ASSERT_TRUE(ConnectToTestServer(ssl_options)); - - base::FilePath certs_dir = GetTestCertsDirectory(); - - int rv; - ASSERT_TRUE(CreateAndConnectSSLClientSocket(SSLConfig(), &rv)); - - EXPECT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv); - EXPECT_FALSE(sock_->IsConnected()); -} - -// Connect to a server requesting client authentication, and send it -// an empty certificate. It should refuse the connection. -TEST_F(SSLClientSocketOpenSSLClientAuthTest, SendEmptyCert) { - SpawnedTestServer::SSLOptions ssl_options; - ssl_options.request_client_certificate = true; - ssl_options.client_authorities.push_back( - GetTestClientCertsDirectory().AppendASCII("client_1_ca.pem")); - - ASSERT_TRUE(ConnectToTestServer(ssl_options)); - - base::FilePath certs_dir = GetTestCertsDirectory(); - SSLConfig ssl_config; - ssl_config.send_client_cert = true; - ssl_config.client_cert = NULL; - ssl_config.client_private_key = NULL; - - int rv; - ASSERT_TRUE(CreateAndConnectSSLClientSocket(ssl_config, &rv)); - - EXPECT_EQ(OK, rv); - EXPECT_TRUE(sock_->IsConnected()); -} - -// Connect to a server requesting client authentication. Send it a -// matching certificate. It should allow the connection. -TEST_F(SSLClientSocketOpenSSLClientAuthTest, SendGoodCert) { - SpawnedTestServer::SSLOptions ssl_options; - ssl_options.request_client_certificate = true; - ssl_options.client_authorities.push_back( - GetTestClientCertsDirectory().AppendASCII("client_1_ca.pem")); - - ASSERT_TRUE(ConnectToTestServer(ssl_options)); - - base::FilePath certs_dir = GetTestCertsDirectory(); - SSLConfig ssl_config; - ssl_config.send_client_cert = true; - ssl_config.client_cert = ImportCertFromFile(certs_dir, "client_1.pem"); - - // This is required to ensure that signing works with the client - // certificate's private key. - crypto::ScopedEVP_PKEY client_private_key; - ASSERT_TRUE(LoadPrivateKeyOpenSSL(certs_dir.AppendASCII("client_1.key"), - &client_private_key)); - EXPECT_TRUE(RecordPrivateKey(ssl_config, client_private_key.get())); - - ssl_config.client_private_key = - FetchClientCertPrivateKey(ssl_config.client_cert.get()); - - int rv; - ASSERT_TRUE(CreateAndConnectSSLClientSocket(ssl_config, &rv)); - - EXPECT_EQ(OK, rv); - EXPECT_TRUE(sock_->IsConnected()); - - EXPECT_TRUE(CheckSSLClientSocketSentCert()); - - sock_->Disconnect(); - EXPECT_FALSE(sock_->IsConnected()); -} -#endif // defined(USE_OPENSSL_CERTS) - -} // namespace -} // namespace net diff --git a/net/socket/ssl_client_socket_unittest.cc b/net/socket/ssl_client_socket_unittest.cc index 6a9d465..141f629 100644 --- a/net/socket/ssl_client_socket_unittest.cc +++ b/net/socket/ssl_client_socket_unittest.cc @@ -7,6 +7,7 @@ #include <utility> #include "base/callback_helpers.h" +#include "base/files/file_util.h" #include "base/location.h" #include "base/macros.h" #include "base/memory/ref_counted.h" @@ -49,6 +50,17 @@ #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" +#if defined(USE_OPENSSL) +#include <errno.h> +#include <openssl/bio.h> +#include <openssl/evp.h> +#include <openssl/pem.h> +#include <string.h> + +#include "crypto/scoped_openssl_types.h" +#include "net/ssl/test_ssl_private_key.h" +#endif + using testing::_; using testing::Return; using testing::Truly; @@ -3240,4 +3252,111 @@ TEST_F(SSLClientSocketTest, NPNServerDisabled) { sock_->GetNextProto(&proto)); } +// Client auth is not supported in NSS ports. +#if defined(USE_OPENSSL) + +namespace { + +// Loads a PEM-encoded private key file into a SSLPrivateKey object. +// |filepath| is the private key file path. +// Returns the new SSLPrivateKey. +scoped_refptr<SSLPrivateKey> LoadPrivateKeyOpenSSL( + const base::FilePath& filepath) { + std::string data; + if (!base::ReadFileToString(filepath, &data)) { + LOG(ERROR) << "Could not read private key file: " << filepath.value(); + return nullptr; + } + crypto::ScopedBIO bio(BIO_new_mem_buf(const_cast<char*>(data.data()), + static_cast<int>(data.size()))); + if (!bio) { + LOG(ERROR) << "Could not allocate BIO for buffer?"; + return nullptr; + } + crypto::ScopedEVP_PKEY result( + PEM_read_bio_PrivateKey(bio.get(), nullptr, nullptr, nullptr)); + if (!result) { + LOG(ERROR) << "Could not decode private key file: " << filepath.value(); + return nullptr; + } + return WrapOpenSSLPrivateKey(std::move(result)); +} + +} // namespace + +// Connect to a server requesting client authentication, do not send +// any client certificates. It should refuse the connection. +TEST_F(SSLClientSocketTest, NoCert) { + SpawnedTestServer::SSLOptions ssl_options; + ssl_options.request_client_certificate = true; + ASSERT_TRUE(StartTestServer(ssl_options)); + + int rv; + ASSERT_TRUE(CreateAndConnectSSLClientSocket(SSLConfig(), &rv)); + + EXPECT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv); + EXPECT_FALSE(sock_->IsConnected()); +} + +// Connect to a server requesting client authentication, and send it +// an empty certificate. +TEST_F(SSLClientSocketTest, SendEmptyCert) { + SpawnedTestServer::SSLOptions ssl_options; + ssl_options.request_client_certificate = true; + ssl_options.client_authorities.push_back( + GetTestClientCertsDirectory().AppendASCII("client_1_ca.pem")); + + ASSERT_TRUE(StartTestServer(ssl_options)); + + SSLConfig ssl_config; + ssl_config.send_client_cert = true; + ssl_config.client_cert = nullptr; + ssl_config.client_private_key = nullptr; + + int rv; + ASSERT_TRUE(CreateAndConnectSSLClientSocket(ssl_config, &rv)); + + EXPECT_EQ(OK, rv); + EXPECT_TRUE(sock_->IsConnected()); + + SSLInfo ssl_info; + ASSERT_TRUE(sock_->GetSSLInfo(&ssl_info)); + EXPECT_FALSE(ssl_info.client_cert_sent); +} + +// Connect to a server requesting client authentication. Send it a +// matching certificate. It should allow the connection. +TEST_F(SSLClientSocketTest, SendGoodCert) { + SpawnedTestServer::SSLOptions ssl_options; + ssl_options.request_client_certificate = true; + ssl_options.client_authorities.push_back( + GetTestClientCertsDirectory().AppendASCII("client_1_ca.pem")); + + ASSERT_TRUE(StartTestServer(ssl_options)); + + base::FilePath certs_dir = GetTestCertsDirectory(); + SSLConfig ssl_config; + ssl_config.send_client_cert = true; + ssl_config.client_cert = ImportCertFromFile(certs_dir, "client_1.pem"); + + // This is required to ensure that signing works with the client + // certificate's private key. + ssl_config.client_private_key = + LoadPrivateKeyOpenSSL(certs_dir.AppendASCII("client_1.key")); + + int rv; + ASSERT_TRUE(CreateAndConnectSSLClientSocket(ssl_config, &rv)); + + EXPECT_EQ(OK, rv); + EXPECT_TRUE(sock_->IsConnected()); + + SSLInfo ssl_info; + ASSERT_TRUE(sock_->GetSSLInfo(&ssl_info)); + EXPECT_TRUE(ssl_info.client_cert_sent); + + sock_->Disconnect(); + EXPECT_FALSE(sock_->IsConnected()); +} +#endif // defined(USE_OPENSSL) + } // namespace net diff --git a/net/ssl/test_ssl_private_key.cc b/net/ssl/test_ssl_private_key.cc new file mode 100644 index 0000000..99ed33b --- /dev/null +++ b/net/ssl/test_ssl_private_key.cc @@ -0,0 +1,128 @@ +// Copyright 2016 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/test_ssl_private_key.h" + +#include <openssl/digest.h> +#include <openssl/evp.h> +#include <utility> + +#include "base/logging.h" +#include "base/macros.h" +#include "crypto/scoped_openssl_types.h" +#include "net/base/net_errors.h" +#include "net/ssl/ssl_platform_key_task_runner.h" +#include "net/ssl/ssl_private_key.h" +#include "net/ssl/threaded_ssl_private_key.h" + +namespace net { + +namespace { + +class TestSSLPlatformKey : public ThreadedSSLPrivateKey::Delegate { + public: + TestSSLPlatformKey(crypto::ScopedEVP_PKEY key, SSLPrivateKey::Type type) + : key_(std::move(key)), type_(type) {} + + ~TestSSLPlatformKey() override {} + + SSLPrivateKey::Type GetType() override { return type_; } + + std::vector<SSLPrivateKey::Hash> GetDigestPreferences() override { + static const SSLPrivateKey::Hash kHashes[] = { + SSLPrivateKey::Hash::SHA512, SSLPrivateKey::Hash::SHA384, + SSLPrivateKey::Hash::SHA256, SSLPrivateKey::Hash::SHA1}; + return std::vector<SSLPrivateKey::Hash>(kHashes, + kHashes + arraysize(kHashes)); + } + + size_t GetMaxSignatureLengthInBytes() override { + return EVP_PKEY_size(key_.get()); + } + + Error SignDigest(SSLPrivateKey::Hash hash, + const base::StringPiece& input, + std::vector<uint8_t>* signature) override { + crypto::ScopedEVP_PKEY_CTX ctx = + crypto::ScopedEVP_PKEY_CTX(EVP_PKEY_CTX_new(key_.get(), NULL)); + if (!ctx) + return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; + if (!EVP_PKEY_sign_init(ctx.get())) + return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; + + if (type_ == SSLPrivateKey::Type::RSA) { + const EVP_MD* digest = nullptr; + switch (hash) { + case SSLPrivateKey::Hash::MD5_SHA1: + digest = EVP_md5_sha1(); + break; + case SSLPrivateKey::Hash::SHA1: + digest = EVP_sha1(); + break; + case SSLPrivateKey::Hash::SHA256: + digest = EVP_sha256(); + break; + case SSLPrivateKey::Hash::SHA384: + digest = EVP_sha384(); + break; + case SSLPrivateKey::Hash::SHA512: + digest = EVP_sha512(); + break; + default: + return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; + } + DCHECK(digest); + if (!EVP_PKEY_CTX_set_rsa_padding(ctx.get(), RSA_PKCS1_PADDING)) + return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; + if (!EVP_PKEY_CTX_set_signature_md(ctx.get(), digest)) + return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; + } + + const uint8_t* input_ptr = reinterpret_cast<const uint8_t*>(input.data()); + size_t input_len = input.size(); + size_t sig_len = 0; + if (!EVP_PKEY_sign(ctx.get(), NULL, &sig_len, input_ptr, input_len)) + return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; + signature->resize(sig_len); + if (!EVP_PKEY_sign(ctx.get(), signature->data(), &sig_len, input_ptr, + input_len)) { + return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; + } + + signature->resize(sig_len); + + return OK; + } + + private: + crypto::ScopedEVP_PKEY key_; + SSLPrivateKey::Type type_; + + DISALLOW_COPY_AND_ASSIGN(TestSSLPlatformKey); +}; + +} // namespace + +scoped_refptr<SSLPrivateKey> WrapOpenSSLPrivateKey(crypto::ScopedEVP_PKEY key) { + if (!key) + return nullptr; + + SSLPrivateKey::Type type; + switch (EVP_PKEY_id(key.get())) { + case EVP_PKEY_RSA: + type = SSLPrivateKey::Type::RSA; + break; + case EVP_PKEY_EC: + type = SSLPrivateKey::Type::ECDSA; + break; + default: + LOG(ERROR) << "Unknown key type: " << EVP_PKEY_id(key.get()); + return nullptr; + } + return make_scoped_refptr(new ThreadedSSLPrivateKey( + make_scoped_ptr(new TestSSLPlatformKey(std::move(key), type)), + GetSSLPlatformKeyTaskRunner())); +} + +} // namespace net diff --git a/net/ssl/test_ssl_private_key.h b/net/ssl/test_ssl_private_key.h new file mode 100644 index 0000000..f9ae906 --- /dev/null +++ b/net/ssl/test_ssl_private_key.h @@ -0,0 +1,25 @@ +// Copyright 2016 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_TEST_SSL_PLATFORM_KEY_H_ +#define NET_SSL_TEST_SSL_PLATFORM_KEY_H_ + +#include <openssl/evp.h> + +#include "base/memory/ref_counted.h" +#include "crypto/scoped_openssl_types.h" +#include "net/base/net_export.h" + +namespace net { + +class SSLPrivateKey; + +// Returns a new SSLPrivateKey which uses |key| for signing operations or +// nullptr on error. +NET_EXPORT scoped_refptr<SSLPrivateKey> WrapOpenSSLPrivateKey( + crypto::ScopedEVP_PKEY key); + +} // namespace net + +#endif // NET_SSL_TEST_SSL_PLATFORM_KEY_H_ |