| Index: net/ssl/openssl_client_key_store_unittest.cc
|
| diff --git a/net/ssl/openssl_client_key_store_unittest.cc b/net/ssl/openssl_client_key_store_unittest.cc
|
| index 2ab344955684fa6c1dbb39e2a9f2f2c34844d281..835fce3de188b55c1323fb755ea9705923cb8e41 100644
|
| --- a/net/ssl/openssl_client_key_store_unittest.cc
|
| +++ b/net/ssl/openssl_client_key_store_unittest.cc
|
| @@ -4,8 +4,10 @@
|
|
|
| #include "net/ssl/openssl_client_key_store.h"
|
|
|
| +#include "base/logging.h"
|
| #include "base/memory/ref_counted.h"
|
| #include "crypto/scoped_openssl_types.h"
|
| +#include "net/ssl/ssl_private_key.h"
|
| #include "net/test/cert_test_util.h"
|
| #include "net/test/test_data_directory.h"
|
| #include "testing/gtest/include/gtest/gtest.h"
|
| @@ -14,11 +16,6 @@ namespace net {
|
|
|
| namespace {
|
|
|
| -// Return the internal reference count of a given EVP_PKEY.
|
| -int EVP_PKEY_get_refcount(EVP_PKEY* pkey) {
|
| - return pkey->references;
|
| -}
|
| -
|
| // A common test class to ensure that the store is flushed after
|
| // each test.
|
| class OpenSSLClientKeyStoreTest : public ::testing::Test {
|
| @@ -36,6 +33,42 @@ class OpenSSLClientKeyStoreTest : public ::testing::Test {
|
| OpenSSLClientKeyStore* store_;
|
| };
|
|
|
| +class MockSSLPrivateKey : public SSLPrivateKey {
|
| + public:
|
| + MockSSLPrivateKey() : on_destroyed_(nullptr) {}
|
| +
|
| + void set_on_destroyed(bool* on_destroyed) { on_destroyed_ = on_destroyed; }
|
| +
|
| + Type GetType() override {
|
| + NOTREACHED();
|
| + return Type::RSA;
|
| + }
|
| +
|
| + std::vector<Hash> GetDigestPreferences() override {
|
| + NOTREACHED();
|
| + return {};
|
| + }
|
| +
|
| + size_t GetMaxSignatureLengthInBytes() override {
|
| + NOTREACHED();
|
| + return 0;
|
| + }
|
| +
|
| + void SignDigest(Hash hash,
|
| + const base::StringPiece& input,
|
| + const SignCallback& callback) override {
|
| + NOTREACHED();
|
| + }
|
| +
|
| + private:
|
| + ~MockSSLPrivateKey() override {
|
| + if (on_destroyed_)
|
| + *on_destroyed_ = true;
|
| + }
|
| +
|
| + bool* on_destroyed_;
|
| +};
|
| +
|
| // Check that GetInstance() returns non-null
|
| TEST_F(OpenSSLClientKeyStoreTest, GetInstance) {
|
| ASSERT_TRUE(store_);
|
| @@ -47,20 +80,16 @@ TEST_F(OpenSSLClientKeyStoreTest, Flush) {
|
|
|
| scoped_refptr<X509Certificate> cert_1(
|
| ImportCertFromFile(GetTestCertsDirectory(), "client_1.pem"));
|
| - ASSERT_TRUE(cert_1.get());
|
| -
|
| - crypto::ScopedEVP_PKEY priv_key(EVP_PKEY_new());
|
| - ASSERT_TRUE(priv_key.get());
|
| + ASSERT_TRUE(cert_1);
|
|
|
| - ASSERT_TRUE(store_->RecordClientCertPrivateKey(cert_1.get(),
|
| - priv_key.get()));
|
| + EXPECT_TRUE(store_->RecordClientCertPrivateKey(
|
| + cert_1.get(), make_scoped_refptr(new MockSSLPrivateKey)));
|
|
|
| store_->Flush();
|
|
|
| // Retrieve the private key. This should fail because the store
|
| // was flushed.
|
| - crypto::ScopedEVP_PKEY pkey = store_->FetchClientCertPrivateKey(cert_1.get());
|
| - ASSERT_FALSE(pkey.get());
|
| + EXPECT_FALSE(store_->FetchClientCertPrivateKey(cert_1.get()));
|
| }
|
|
|
| // Check that trying to retrieve the private key of an unknown certificate
|
| @@ -70,12 +99,11 @@ TEST_F(OpenSSLClientKeyStoreTest, FetchEmptyPrivateKey) {
|
|
|
| scoped_refptr<X509Certificate> cert_1(
|
| ImportCertFromFile(GetTestCertsDirectory(), "client_1.pem"));
|
| - ASSERT_TRUE(cert_1.get());
|
| + ASSERT_TRUE(cert_1);
|
|
|
| // Retrieve the private key now. This should fail because it was
|
| // never recorded in the store.
|
| - crypto::ScopedEVP_PKEY pkey = store_->FetchClientCertPrivateKey(cert_1.get());
|
| - ASSERT_FALSE(pkey.get());
|
| + EXPECT_FALSE(store_->FetchClientCertPrivateKey(cert_1.get()));
|
| }
|
|
|
| // Check that any private key recorded through RecordClientCertPrivateKey
|
| @@ -89,80 +117,55 @@ TEST_F(OpenSSLClientKeyStoreTest, RecordAndFetchPrivateKey) {
|
| // JNI reference, with no way to access the real private key bits.
|
| scoped_refptr<X509Certificate> cert_1(
|
| ImportCertFromFile(GetTestCertsDirectory(), "client_1.pem"));
|
| - ASSERT_TRUE(cert_1.get());
|
| -
|
| - crypto::ScopedEVP_PKEY priv_key(EVP_PKEY_new());
|
| - ASSERT_TRUE(priv_key.get());
|
| - ASSERT_EQ(1, EVP_PKEY_get_refcount(priv_key.get()));
|
| -
|
| - // Add the key a first time, this should increment its reference count.
|
| - ASSERT_TRUE(store_->RecordClientCertPrivateKey(cert_1.get(),
|
| - priv_key.get()));
|
| - ASSERT_EQ(2, EVP_PKEY_get_refcount(priv_key.get()));
|
| -
|
| - // Two successive calls with the same certificate / private key shall
|
| - // also succeed, but the key's reference count should not be incremented.
|
| - ASSERT_TRUE(store_->RecordClientCertPrivateKey(cert_1.get(),
|
| - priv_key.get()));
|
| - ASSERT_EQ(2, EVP_PKEY_get_refcount(priv_key.get()));
|
| -
|
| - // Retrieve the private key. This should increment the private key's
|
| - // reference count.
|
| - crypto::ScopedEVP_PKEY pkey2 =
|
| + ASSERT_TRUE(cert_1);
|
| +
|
| + bool on_destroyed = false;
|
| + scoped_refptr<MockSSLPrivateKey> priv_key(new MockSSLPrivateKey);
|
| + priv_key->set_on_destroyed(&on_destroyed);
|
| +
|
| + // Add a key twice.
|
| + EXPECT_TRUE(store_->RecordClientCertPrivateKey(cert_1.get(), priv_key));
|
| + EXPECT_TRUE(store_->RecordClientCertPrivateKey(cert_1.get(), priv_key));
|
| +
|
| + // Retrieve the private key.
|
| + scoped_refptr<SSLPrivateKey> pkey2 =
|
| store_->FetchClientCertPrivateKey(cert_1.get());
|
| - ASSERT_EQ(pkey2.get(), priv_key.get());
|
| - ASSERT_EQ(3, EVP_PKEY_get_refcount(priv_key.get()));
|
| + EXPECT_EQ(pkey2.get(), priv_key.get());
|
|
|
| - // Flush the store explicitely, this should decrement the private
|
| - // key's reference count.
|
| + // Flush the key store and release all references. At this point, the private
|
| + // key should be cleanly destroyed.
|
| store_->Flush();
|
| - ASSERT_EQ(2, EVP_PKEY_get_refcount(priv_key.get()));
|
| + priv_key = nullptr;
|
| + pkey2 = nullptr;
|
| + EXPECT_TRUE(on_destroyed);
|
| }
|
|
|
| // Same test, but with two certificates / private keys.
|
| TEST_F(OpenSSLClientKeyStoreTest, RecordAndFetchTwoPrivateKeys) {
|
| scoped_refptr<X509Certificate> cert_1(
|
| ImportCertFromFile(GetTestCertsDirectory(), "client_1.pem"));
|
| - ASSERT_TRUE(cert_1.get());
|
| + ASSERT_TRUE(cert_1);
|
|
|
| scoped_refptr<X509Certificate> cert_2(
|
| ImportCertFromFile(GetTestCertsDirectory(), "client_2.pem"));
|
| - ASSERT_TRUE(cert_2.get());
|
| -
|
| - crypto::ScopedEVP_PKEY priv_key1(EVP_PKEY_new());
|
| - ASSERT_TRUE(priv_key1.get());
|
| - ASSERT_EQ(1, EVP_PKEY_get_refcount(priv_key1.get()));
|
| -
|
| - crypto::ScopedEVP_PKEY priv_key2(EVP_PKEY_new());
|
| - ASSERT_TRUE(priv_key2.get());
|
| - ASSERT_EQ(1, EVP_PKEY_get_refcount(priv_key2.get()));
|
| -
|
| - ASSERT_NE(priv_key1.get(), priv_key2.get());
|
| -
|
| - // Add the key a first time, this shall succeed, and increment the
|
| - // reference count.
|
| - EXPECT_TRUE(store_->RecordClientCertPrivateKey(cert_1.get(),
|
| - priv_key1.get()));
|
| - EXPECT_TRUE(store_->RecordClientCertPrivateKey(cert_2.get(),
|
| - priv_key2.get()));
|
| - EXPECT_EQ(2, EVP_PKEY_get_refcount(priv_key1.get()));
|
| - EXPECT_EQ(2, EVP_PKEY_get_refcount(priv_key2.get()));
|
| -
|
| - // Retrieve the private key now. This shall succeed and increment
|
| - // the private key's reference count.
|
| - crypto::ScopedEVP_PKEY fetch_key1 =
|
| + ASSERT_TRUE(cert_2);
|
| +
|
| + scoped_refptr<SSLPrivateKey> priv_key1(new MockSSLPrivateKey);
|
| + scoped_refptr<SSLPrivateKey> priv_key2(new MockSSLPrivateKey);
|
| +
|
| + EXPECT_TRUE(store_->RecordClientCertPrivateKey(cert_1.get(), priv_key1));
|
| + EXPECT_TRUE(store_->RecordClientCertPrivateKey(cert_2.get(), priv_key2));
|
| +
|
| + scoped_refptr<SSLPrivateKey> fetch_key1 =
|
| store_->FetchClientCertPrivateKey(cert_1.get());
|
| - crypto::ScopedEVP_PKEY fetch_key2 =
|
| + scoped_refptr<SSLPrivateKey> fetch_key2 =
|
| store_->FetchClientCertPrivateKey(cert_2.get());
|
|
|
| - EXPECT_TRUE(fetch_key1.get());
|
| - EXPECT_TRUE(fetch_key2.get());
|
| + EXPECT_TRUE(fetch_key1);
|
| + EXPECT_TRUE(fetch_key2);
|
|
|
| EXPECT_EQ(fetch_key1.get(), priv_key1.get());
|
| EXPECT_EQ(fetch_key2.get(), priv_key2.get());
|
| -
|
| - EXPECT_EQ(3, EVP_PKEY_get_refcount(priv_key1.get()));
|
| - EXPECT_EQ(3, EVP_PKEY_get_refcount(priv_key2.get()));
|
| }
|
|
|
| } // namespace
|
|
|