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 |