Home | History | Annotate | Download | only in ssl
      1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "net/ssl/openssl_client_key_store.h"
      6 
      7 #include "base/memory/ref_counted.h"
      8 #include "net/base/test_data_directory.h"
      9 #include "net/test/cert_test_util.h"
     10 #include "testing/gtest/include/gtest/gtest.h"
     11 
     12 namespace net {
     13 
     14 namespace {
     15 
     16 typedef OpenSSLClientKeyStore::ScopedEVP_PKEY ScopedEVP_PKEY;
     17 
     18 // Return the internal reference count of a given EVP_PKEY.
     19 int EVP_PKEY_get_refcount(EVP_PKEY* pkey) {
     20   return pkey->references;
     21 }
     22 
     23 // A common test class to ensure that the store is flushed after
     24 // each test.
     25 class OpenSSLClientKeyStoreTest : public ::testing::Test {
     26  public:
     27   OpenSSLClientKeyStoreTest()
     28     : store_(OpenSSLClientKeyStore::GetInstance()) {
     29   }
     30 
     31   virtual ~OpenSSLClientKeyStoreTest() {
     32     if (store_)
     33       store_->Flush();
     34   }
     35 
     36  protected:
     37   OpenSSLClientKeyStore* store_;
     38 };
     39 
     40 // Check that GetInstance() returns non-null
     41 TEST_F(OpenSSLClientKeyStoreTest, GetInstance) {
     42   ASSERT_TRUE(store_);
     43 }
     44 
     45 // Check that Flush() works correctly.
     46 TEST_F(OpenSSLClientKeyStoreTest, Flush) {
     47   ASSERT_TRUE(store_);
     48 
     49   scoped_refptr<X509Certificate> cert_1(
     50       ImportCertFromFile(GetTestCertsDirectory(), "client_1.pem"));
     51   ASSERT_TRUE(cert_1.get());
     52 
     53   ScopedEVP_PKEY priv_key(EVP_PKEY_new());
     54   ASSERT_TRUE(priv_key.get());
     55 
     56   ASSERT_TRUE(store_->RecordClientCertPrivateKey(cert_1.get(),
     57                                                  priv_key.get()));
     58 
     59   store_->Flush();
     60 
     61   // Retrieve the private key. This should fail because the store
     62   // was flushed.
     63   ScopedEVP_PKEY pkey;
     64   ASSERT_FALSE(store_->FetchClientCertPrivateKey(cert_1.get(), &pkey));
     65   ASSERT_FALSE(pkey.get());
     66 }
     67 
     68 // Check that trying to retrieve the private key of an unknown certificate
     69 // simply fails by returning null.
     70 TEST_F(OpenSSLClientKeyStoreTest, FetchEmptyPrivateKey) {
     71   ASSERT_TRUE(store_);
     72 
     73   scoped_refptr<X509Certificate> cert_1(
     74       ImportCertFromFile(GetTestCertsDirectory(), "client_1.pem"));
     75   ASSERT_TRUE(cert_1.get());
     76 
     77   // Retrieve the private key now. This should fail because it was
     78   // never recorded in the store.
     79   ScopedEVP_PKEY pkey;
     80   ASSERT_FALSE(store_->FetchClientCertPrivateKey(cert_1.get(), &pkey));
     81   ASSERT_FALSE(pkey.get());
     82 }
     83 
     84 // Check that any private key recorded through RecordClientCertPrivateKey
     85 // can be retrieved with FetchClientCertPrivateKey.
     86 TEST_F(OpenSSLClientKeyStoreTest, RecordAndFetchPrivateKey) {
     87   ASSERT_TRUE(store_);
     88 
     89   // Any certificate / key pair will do, the store is not supposed to
     90   // check that the private and certificate public keys match. This is
     91   // by design since the private EVP_PKEY could be a wrapper around a
     92   // JNI reference, with no way to access the real private key bits.
     93   scoped_refptr<X509Certificate> cert_1(
     94       ImportCertFromFile(GetTestCertsDirectory(), "client_1.pem"));
     95   ASSERT_TRUE(cert_1.get());
     96 
     97   ScopedEVP_PKEY priv_key(EVP_PKEY_new());
     98   ASSERT_TRUE(priv_key.get());
     99   ASSERT_EQ(1, EVP_PKEY_get_refcount(priv_key.get()));
    100 
    101   // Add the key a first time, this should increment its reference count.
    102   ASSERT_TRUE(store_->RecordClientCertPrivateKey(cert_1.get(),
    103                                                  priv_key.get()));
    104   ASSERT_EQ(2, EVP_PKEY_get_refcount(priv_key.get()));
    105 
    106   // Two successive calls with the same certificate / private key shall
    107   // also succeed, but the key's reference count should not be incremented.
    108   ASSERT_TRUE(store_->RecordClientCertPrivateKey(cert_1.get(),
    109                                                  priv_key.get()));
    110   ASSERT_EQ(2, EVP_PKEY_get_refcount(priv_key.get()));
    111 
    112   // Retrieve the private key. This should increment the private key's
    113   // reference count.
    114   ScopedEVP_PKEY pkey2;
    115   ASSERT_TRUE(store_->FetchClientCertPrivateKey(cert_1.get(), &pkey2));
    116   ASSERT_EQ(pkey2.get(), priv_key.get());
    117   ASSERT_EQ(3, EVP_PKEY_get_refcount(priv_key.get()));
    118 
    119   // Flush the store explicitely, this should decrement the private
    120   // key's reference count.
    121   store_->Flush();
    122   ASSERT_EQ(2, EVP_PKEY_get_refcount(priv_key.get()));
    123 }
    124 
    125 // Same test, but with two certificates / private keys.
    126 TEST_F(OpenSSLClientKeyStoreTest, RecordAndFetchTwoPrivateKeys) {
    127   scoped_refptr<X509Certificate> cert_1(
    128       ImportCertFromFile(GetTestCertsDirectory(), "client_1.pem"));
    129   ASSERT_TRUE(cert_1.get());
    130 
    131   scoped_refptr<X509Certificate> cert_2(
    132       ImportCertFromFile(GetTestCertsDirectory(), "client_2.pem"));
    133   ASSERT_TRUE(cert_2.get());
    134 
    135   ScopedEVP_PKEY priv_key1(EVP_PKEY_new());
    136   ASSERT_TRUE(priv_key1.get());
    137   ASSERT_EQ(1, EVP_PKEY_get_refcount(priv_key1.get()));
    138 
    139   ScopedEVP_PKEY priv_key2(EVP_PKEY_new());
    140   ASSERT_TRUE(priv_key2.get());
    141   ASSERT_EQ(1, EVP_PKEY_get_refcount(priv_key2.get()));
    142 
    143   ASSERT_NE(priv_key1.get(), priv_key2.get());
    144 
    145   // Add the key a first time, this shall succeed, and increment the
    146   // reference count.
    147   EXPECT_TRUE(store_->RecordClientCertPrivateKey(cert_1.get(),
    148                                                  priv_key1.get()));
    149   EXPECT_TRUE(store_->RecordClientCertPrivateKey(cert_2.get(),
    150                                                  priv_key2.get()));
    151   EXPECT_EQ(2, EVP_PKEY_get_refcount(priv_key1.get()));
    152   EXPECT_EQ(2, EVP_PKEY_get_refcount(priv_key2.get()));
    153 
    154   // Retrieve the private key now. This shall succeed and increment
    155   // the private key's reference count.
    156   ScopedEVP_PKEY fetch_key1;
    157   ASSERT_TRUE(store_->FetchClientCertPrivateKey(cert_1.get(),
    158                                                 &fetch_key1));
    159   ScopedEVP_PKEY fetch_key2;
    160   ASSERT_TRUE(store_->FetchClientCertPrivateKey(cert_2.get(),
    161                                                 &fetch_key2));
    162   EXPECT_TRUE(fetch_key1.get());
    163   EXPECT_TRUE(fetch_key2.get());
    164 
    165   EXPECT_EQ(fetch_key1.get(), priv_key1.get());
    166   EXPECT_EQ(fetch_key2.get(), priv_key2.get());
    167 
    168   EXPECT_EQ(3, EVP_PKEY_get_refcount(priv_key1.get()));
    169   EXPECT_EQ(3, EVP_PKEY_get_refcount(priv_key2.get()));
    170 }
    171 
    172 }  // namespace
    173 }  // namespace net
    174