diff options
author | mattm@chromium.org <mattm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-22 01:46:19 +0000 |
---|---|---|
committer | mattm@chromium.org <mattm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-22 01:46:19 +0000 |
commit | 4082fa2a9b307fc78675602bbcc0acade2029059 (patch) | |
tree | af99bc0b6de4414edea1b97af87316d203648095 | |
parent | 25142ecaf7ff6a2ade87625b34d715700cb7e68f (diff) | |
download | chromium_src-4082fa2a9b307fc78675602bbcc0acade2029059.zip chromium_src-4082fa2a9b307fc78675602bbcc0acade2029059.tar.gz chromium_src-4082fa2a9b307fc78675602bbcc0acade2029059.tar.bz2 |
Try#2: Handle Origin Bound Certificate expiration.
(Initialize test from raw time value to work around inability to parse dates past 2038 on 32-bit linux.)
BUG=107047
TEST=net_unittests, unit_tests
Review URL: http://codereview.chromium.org/9016002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@115463 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/net/sqlite_origin_bound_cert_store.cc | 72 | ||||
-rw-r--r-- | chrome/browser/net/sqlite_origin_bound_cert_store_unittest.cc | 223 | ||||
-rw-r--r-- | chrome/chrome_tests.gypi | 1 | ||||
-rw-r--r-- | net/base/default_origin_bound_cert_store.cc | 6 | ||||
-rw-r--r-- | net/base/default_origin_bound_cert_store.h | 2 | ||||
-rw-r--r-- | net/base/default_origin_bound_cert_store_unittest.cc | 91 | ||||
-rw-r--r-- | net/base/origin_bound_cert_service.cc | 45 | ||||
-rw-r--r-- | net/base/origin_bound_cert_service.h | 6 | ||||
-rw-r--r-- | net/base/origin_bound_cert_service_unittest.cc | 50 | ||||
-rw-r--r-- | net/base/origin_bound_cert_store.cc | 2 | ||||
-rw-r--r-- | net/base/origin_bound_cert_store.h | 14 | ||||
-rw-r--r-- | net/base/x509_certificate_nss.cc | 5 | ||||
-rw-r--r-- | net/base/x509_util.h | 6 | ||||
-rw-r--r-- | net/base/x509_util_nss.cc | 35 | ||||
-rw-r--r-- | net/base/x509_util_nss.h | 3 | ||||
-rw-r--r-- | net/base/x509_util_nss_unittest.cc | 22 | ||||
-rw-r--r-- | net/base/x509_util_openssl.cc | 6 | ||||
-rw-r--r-- | net/base/x509_util_openssl_unittest.cc | 11 |
18 files changed, 484 insertions, 116 deletions
diff --git a/chrome/browser/net/sqlite_origin_bound_cert_store.cc b/chrome/browser/net/sqlite_origin_bound_cert_store.cc index 2223394..039530b 100644 --- a/chrome/browser/net/sqlite_origin_bound_cert_store.cc +++ b/chrome/browser/net/sqlite_origin_bound_cert_store.cc @@ -18,6 +18,7 @@ #include "chrome/browser/diagnostics/sqlite_diagnostics.h" #include "content/public/browser/browser_thread.h" #include "net/base/ssl_client_cert_type.h" +#include "net/base/x509_certificate.h" #include "sql/meta_table.h" #include "sql/statement.h" #include "sql/transaction.h" @@ -117,7 +118,7 @@ class SQLiteOriginBoundCertStore::Backend }; // Version number of the database. -static const int kCurrentVersionNumber = 2; +static const int kCurrentVersionNumber = 3; static const int kCompatibleVersionNumber = 1; namespace { @@ -129,7 +130,8 @@ bool InitTable(sql::Connection* db) { "origin TEXT NOT NULL UNIQUE PRIMARY KEY," "private_key BLOB NOT NULL," "cert BLOB NOT NULL," - "cert_type INTEGER)")) + "cert_type INTEGER," + "expiration_time INTEGER)")) return false; } @@ -171,7 +173,8 @@ bool SQLiteOriginBoundCertStore::Backend::Load( // Slurp all the certs into the out-vector. sql::Statement smt(db_->GetUniqueStatement( - "SELECT origin, private_key, cert, cert_type FROM origin_bound_certs")); + "SELECT origin, private_key, cert, cert_type, expiration_time " + "FROM origin_bound_certs")); if (!smt) { NOTREACHED() << "select statement prep failed"; db_.reset(); @@ -186,6 +189,7 @@ bool SQLiteOriginBoundCertStore::Backend::Load( new net::DefaultOriginBoundCertStore::OriginBoundCert( smt.ColumnString(0), // origin static_cast<net::SSLClientCertType>(smt.ColumnInt(3)), + base::Time::FromInternalValue(smt.ColumnInt64(4)), private_key_from_db, cert_from_db)); certs->push_back(cert.release()); @@ -230,6 +234,63 @@ bool SQLiteOriginBoundCertStore::Backend::EnsureDatabaseVersion() { transaction.Commit(); } + if (cur_version == 2) { + sql::Transaction transaction(db_.get()); + if (!transaction.Begin()) + return false; + if (!db_->Execute("ALTER TABLE origin_bound_certs ADD COLUMN " + "expiration_time INTEGER")) { + LOG(WARNING) << "Unable to update origin bound cert database to " + << "version 3."; + return false; + } + + sql::Statement smt(db_->GetUniqueStatement( + "SELECT origin, cert FROM origin_bound_certs")); + if (!smt) { + LOG(WARNING) << "Unable to update origin bound cert database to " + << "version 3."; + return false; + } + sql::Statement update_expires_smt(db_->GetUniqueStatement( + "UPDATE origin_bound_certs SET expiration_time = ? WHERE origin = ?")); + if (!update_expires_smt) { + LOG(WARNING) << "Unable to update origin bound cert database to " + << "version 3."; + return false; + } + while (smt.Step()) { + std::string origin = smt.ColumnString(0); + std::string cert_from_db; + smt.ColumnBlobAsString(1, &cert_from_db); + // Parse the cert and extract the real value and then update the DB. + scoped_refptr<net::X509Certificate> cert( + net::X509Certificate::CreateFromBytes( + cert_from_db.data(), cert_from_db.size())); + if (cert) { + update_expires_smt.Reset(); + update_expires_smt.BindInt64(0, cert->valid_expiry().ToInternalValue()); + update_expires_smt.BindString(1, origin); + if (!update_expires_smt.Run()) { + LOG(WARNING) << "Unable to update origin bound cert database to " + << "version 3."; + return false; + } + } else { + // If there's a cert we can't parse, just leave it. It'll get replaced + // with a new one if we ever try to use it. + LOG(WARNING) << "Error parsing cert for database upgrade for origin " + << smt.ColumnString(0); + } + } + + ++cur_version; + meta_table_.SetVersionNumber(cur_version); + meta_table_.SetCompatibleVersionNumber( + std::min(cur_version, kCompatibleVersionNumber)); + transaction.Commit(); + } + // Put future migration cases here. // When the version is too old, we just try to continue anyway, there should @@ -298,8 +359,8 @@ void SQLiteOriginBoundCertStore::Backend::Commit() { return; sql::Statement add_smt(db_->GetCachedStatement(SQL_FROM_HERE, - "INSERT INTO origin_bound_certs (origin, private_key, cert, cert_type) " - "VALUES (?,?,?,?)")); + "INSERT INTO origin_bound_certs (origin, private_key, cert, cert_type, " + "expiration_time) VALUES (?,?,?,?,?)")); if (!add_smt) { NOTREACHED(); return; @@ -330,6 +391,7 @@ void SQLiteOriginBoundCertStore::Backend::Commit() { const std::string& cert = po->cert().cert(); add_smt.BindBlob(2, cert.data(), cert.size()); add_smt.BindInt(3, po->cert().type()); + add_smt.BindInt64(4, po->cert().expiration_time().ToInternalValue()); if (!add_smt.Run()) NOTREACHED() << "Could not add an origin bound cert to the DB."; break; diff --git a/chrome/browser/net/sqlite_origin_bound_cert_store_unittest.cc b/chrome/browser/net/sqlite_origin_bound_cert_store_unittest.cc index cc3130d..5ee226e 100644 --- a/chrome/browser/net/sqlite_origin_bound_cert_store_unittest.cc +++ b/chrome/browser/net/sqlite_origin_bound_cert_store_unittest.cc @@ -5,6 +5,7 @@ #include "base/bind.h" #include "base/file_util.h" #include "base/memory/ref_counted.h" +#include "base/memory/scoped_vector.h" #include "base/message_loop.h" #include "base/scoped_temp_dir.h" #include "base/stl_util.h" @@ -12,6 +13,7 @@ #include "chrome/browser/net/sqlite_origin_bound_cert_store.h" #include "chrome/common/chrome_constants.h" #include "content/test/test_browser_thread.h" +#include "net/base/cert_test_util.h" #include "sql/statement.h" #include "testing/gtest/include/gtest/gtest.h" @@ -24,19 +26,38 @@ class SQLiteOriginBoundCertStoreTest : public testing::Test { } protected: + static void ReadTestKeyAndCert(std::string* key, std::string* cert) { + FilePath key_path = net::GetTestCertsDirectory().AppendASCII( + "unittest.originbound.key.der"); + FilePath cert_path = net::GetTestCertsDirectory().AppendASCII( + "unittest.originbound.der"); + ASSERT_TRUE(file_util::ReadFileToString(key_path, key)); + ASSERT_TRUE(file_util::ReadFileToString(cert_path, cert)); + } + + static base::Time GetTestCertExpirationTime() { + // Cert expiration time from 'dumpasn1 unittest.originbound.der': + // GeneralizedTime 19/11/2111 02:23:45 GMT + // base::Time::FromUTCExploded can't generate values past 2038 on 32-bit + // linux, so we use the raw value here. + return base::Time::FromInternalValue(GG_INT64_C(16121816625000000)); + } + virtual void SetUp() { db_thread_.Start(); ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); store_ = new SQLiteOriginBoundCertStore( temp_dir_.path().Append(chrome::kOBCertFilename)); - std::vector<net::DefaultOriginBoundCertStore::OriginBoundCert*> certs; - ASSERT_TRUE(store_->Load(&certs)); + ScopedVector<net::DefaultOriginBoundCertStore::OriginBoundCert> certs; + ASSERT_TRUE(store_->Load(&certs.get())); ASSERT_EQ(0u, certs.size()); // Make sure the store gets written at least once. store_->AddOriginBoundCert( net::DefaultOriginBoundCertStore::OriginBoundCert( "https://encrypted.google.com:8443", - net::CLIENT_CERT_RSA_SIGN, "a", "b")); + net::CLIENT_CERT_RSA_SIGN, + base::Time(), + "a", "b")); } content::TestBrowserThread db_thread_; @@ -79,9 +100,12 @@ TEST_F(SQLiteOriginBoundCertStoreTest, RemoveOnDestruction) { TEST_F(SQLiteOriginBoundCertStoreTest, TestPersistence) { store_->AddOriginBoundCert( net::DefaultOriginBoundCertStore::OriginBoundCert( - "https://www.google.com/", net::CLIENT_CERT_ECDSA_SIGN, "c", "d")); + "https://www.google.com/", + net::CLIENT_CERT_ECDSA_SIGN, + base::Time(), + "c", "d")); - std::vector<net::DefaultOriginBoundCertStore::OriginBoundCert*> certs; + ScopedVector<net::DefaultOriginBoundCertStore::OriginBoundCert> certs; // Replace the store effectively destroying the current one and forcing it // to write it's data to disk. Then we can see if after loading it again it // is still there. @@ -95,7 +119,7 @@ TEST_F(SQLiteOriginBoundCertStoreTest, TestPersistence) { temp_dir_.path().Append(chrome::kOBCertFilename)); // Reload and test for persistence - ASSERT_TRUE(store_->Load(&certs)); + ASSERT_TRUE(store_->Load(&certs.get())); ASSERT_EQ(2U, certs.size()); net::DefaultOriginBoundCertStore::OriginBoundCert* ec_cert; net::DefaultOriginBoundCertStore::OriginBoundCert* rsa_cert; @@ -121,22 +145,25 @@ TEST_F(SQLiteOriginBoundCertStoreTest, TestPersistence) { store_ = NULL; // Make sure we wait until the destructor has run. ASSERT_TRUE(helper->Run()); - STLDeleteContainerPointers(certs.begin(), certs.end()); - certs.clear(); + certs.reset(); store_ = new SQLiteOriginBoundCertStore( temp_dir_.path().Append(chrome::kOBCertFilename)); // Reload and check if the cert has been removed. - ASSERT_TRUE(store_->Load(&certs)); + ASSERT_TRUE(store_->Load(&certs.get())); ASSERT_EQ(0U, certs.size()); } -TEST_F(SQLiteOriginBoundCertStoreTest, TestUpgrade) { +TEST_F(SQLiteOriginBoundCertStoreTest, TestUpgradeV1) { // Reset the store. We'll be using a different database for this test. store_ = NULL; FilePath v1_db_path(temp_dir_.path().AppendASCII("v1db")); + std::string key_data; + std::string cert_data; + ReadTestKeyAndCert(&key_data, &cert_data); + // Create a version 1 database. { sql::Connection db; @@ -148,49 +175,156 @@ TEST_F(SQLiteOriginBoundCertStoreTest, TestUpgrade) { "INSERT INTO \"meta\" VALUES('last_compatible_version','1');" "CREATE TABLE origin_bound_certs (" "origin TEXT NOT NULL UNIQUE PRIMARY KEY," - "private_key BLOB NOT NULL,cert BLOB NOT NULL);" - "INSERT INTO \"origin_bound_certs\" VALUES(" - "'https://google.com',X'AA',X'BB');" + "private_key BLOB NOT NULL,cert BLOB NOT NULL);")); + + sql::Statement add_smt(db.GetUniqueStatement( + "INSERT INTO origin_bound_certs (origin, private_key, cert) " + "VALUES (?,?,?)")); + add_smt.BindString(0, "https://www.google.com:443"); + add_smt.BindBlob(1, key_data.data(), key_data.size()); + add_smt.BindBlob(2, cert_data.data(), cert_data.size()); + ASSERT_TRUE(add_smt.Run()); + + ASSERT_TRUE(db.Execute( "INSERT INTO \"origin_bound_certs\" VALUES(" - "'https://foo.com',X'CC',X'DD');" + "'https://foo.com',X'AA',X'BB');" )); } - std::vector<net::DefaultOriginBoundCertStore::OriginBoundCert*> certs; - store_ = new SQLiteOriginBoundCertStore(v1_db_path); - - // Load the database and ensure the certs can be read and are marked as RSA. - ASSERT_TRUE(store_->Load(&certs)); - ASSERT_EQ(2U, certs.size()); - ASSERT_STREQ("https://google.com", certs[0]->origin().c_str()); - ASSERT_EQ(net::CLIENT_CERT_RSA_SIGN, certs[0]->type()); - ASSERT_STREQ("\xaa", certs[0]->private_key().c_str()); - ASSERT_STREQ("\xbb", certs[0]->cert().c_str()); - ASSERT_STREQ("https://foo.com", certs[1]->origin().c_str()); - ASSERT_EQ(net::CLIENT_CERT_RSA_SIGN, certs[1]->type()); - ASSERT_STREQ("\xcc", certs[1]->private_key().c_str()); - ASSERT_STREQ("\xdd", certs[1]->cert().c_str()); - - STLDeleteContainerPointers(certs.begin(), certs.end()); - certs.clear(); + // Load and test the DB contents twice. First time ensures that we can use + // the updated values immediately. Second time ensures that the updated + // values are stored and read correctly on next load. + for (int i = 0; i < 2; ++i) { + SCOPED_TRACE(i); + + ScopedVector<net::DefaultOriginBoundCertStore::OriginBoundCert> certs; + store_ = new SQLiteOriginBoundCertStore(v1_db_path); + + // Load the database and ensure the certs can be read and are marked as RSA. + ASSERT_TRUE(store_->Load(&certs.get())); + ASSERT_EQ(2U, certs.size()); + + ASSERT_STREQ("https://www.google.com:443", certs[0]->origin().c_str()); + ASSERT_EQ(net::CLIENT_CERT_RSA_SIGN, certs[0]->type()); + ASSERT_EQ(GetTestCertExpirationTime(), + certs[0]->expiration_time()); + ASSERT_EQ(key_data, certs[0]->private_key()); + ASSERT_EQ(cert_data, certs[0]->cert()); + + ASSERT_STREQ("https://foo.com", certs[1]->origin().c_str()); + ASSERT_EQ(net::CLIENT_CERT_RSA_SIGN, certs[1]->type()); + // Undecodable cert, expiration time will be uninitialized. + ASSERT_EQ(base::Time(), certs[1]->expiration_time()); + ASSERT_STREQ("\xaa", certs[1]->private_key().c_str()); + ASSERT_STREQ("\xbb", certs[1]->cert().c_str()); + + store_ = NULL; + // Make sure we wait until the destructor has run. + scoped_refptr<base::ThreadTestHelper> helper( + new base::ThreadTestHelper( + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB))); + ASSERT_TRUE(helper->Run()); + + // Verify the database version is updated. + { + sql::Connection db; + ASSERT_TRUE(db.Open(v1_db_path)); + sql::Statement smt(db.GetUniqueStatement( + "SELECT value FROM meta WHERE key = \"version\"")); + ASSERT_TRUE(smt); + ASSERT_TRUE(smt.Step()); + EXPECT_EQ(3, smt.ColumnInt(0)); + EXPECT_FALSE(smt.Step()); + } + } +} +TEST_F(SQLiteOriginBoundCertStoreTest, TestUpgradeV2) { + // Reset the store. We'll be using a different database for this test. store_ = NULL; - // Make sure we wait until the destructor has run. - scoped_refptr<base::ThreadTestHelper> helper( - new base::ThreadTestHelper( - BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB))); - ASSERT_TRUE(helper->Run()); - // Verify the database version is updated. + FilePath v2_db_path(temp_dir_.path().AppendASCII("v2db")); + + std::string key_data; + std::string cert_data; + ReadTestKeyAndCert(&key_data, &cert_data); + + // Create a version 2 database. { sql::Connection db; - ASSERT_TRUE(db.Open(v1_db_path)); - sql::Statement smt(db.GetUniqueStatement( - "SELECT value FROM meta WHERE key = \"version\"")); - ASSERT_TRUE(smt); - ASSERT_TRUE(smt.Step()); - EXPECT_EQ(2, smt.ColumnInt(0)); - EXPECT_FALSE(smt.Step()); + ASSERT_TRUE(db.Open(v2_db_path)); + ASSERT_TRUE(db.Execute( + "CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY," + "value LONGVARCHAR);" + "INSERT INTO \"meta\" VALUES('version','2');" + "INSERT INTO \"meta\" VALUES('last_compatible_version','1');" + "CREATE TABLE origin_bound_certs (" + "origin TEXT NOT NULL UNIQUE PRIMARY KEY," + "private_key BLOB NOT NULL," + "cert BLOB NOT NULL," + "cert_type INTEGER);" + )); + + sql::Statement add_smt(db.GetUniqueStatement( + "INSERT INTO origin_bound_certs (origin, private_key, cert, cert_type) " + "VALUES (?,?,?,?)")); + add_smt.BindString(0, "https://www.google.com:443"); + add_smt.BindBlob(1, key_data.data(), key_data.size()); + add_smt.BindBlob(2, cert_data.data(), cert_data.size()); + add_smt.BindInt64(3, 1); + ASSERT_TRUE(add_smt.Run()); + + ASSERT_TRUE(db.Execute( + "INSERT INTO \"origin_bound_certs\" VALUES(" + "'https://foo.com',X'AA',X'BB',64);" + )); + } + + // Load and test the DB contents twice. First time ensures that we can use + // the updated values immediately. Second time ensures that the updated + // values are saved and read correctly on next load. + for (int i = 0; i < 2; ++i) { + SCOPED_TRACE(i); + + ScopedVector<net::DefaultOriginBoundCertStore::OriginBoundCert> certs; + store_ = new SQLiteOriginBoundCertStore(v2_db_path); + + // Load the database and ensure the certs can be read and are marked as RSA. + ASSERT_TRUE(store_->Load(&certs.get())); + ASSERT_EQ(2U, certs.size()); + + ASSERT_STREQ("https://www.google.com:443", certs[0]->origin().c_str()); + ASSERT_EQ(net::CLIENT_CERT_RSA_SIGN, certs[0]->type()); + ASSERT_EQ(GetTestCertExpirationTime(), + certs[0]->expiration_time()); + ASSERT_EQ(key_data, certs[0]->private_key()); + ASSERT_EQ(cert_data, certs[0]->cert()); + + ASSERT_STREQ("https://foo.com", certs[1]->origin().c_str()); + ASSERT_EQ(net::CLIENT_CERT_ECDSA_SIGN, certs[1]->type()); + // Undecodable cert, expiration time will be uninitialized. + ASSERT_EQ(base::Time(), certs[1]->expiration_time()); + ASSERT_STREQ("\xaa", certs[1]->private_key().c_str()); + ASSERT_STREQ("\xbb", certs[1]->cert().c_str()); + + store_ = NULL; + // Make sure we wait until the destructor has run. + scoped_refptr<base::ThreadTestHelper> helper( + new base::ThreadTestHelper( + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB))); + ASSERT_TRUE(helper->Run()); + + // Verify the database version is updated. + { + sql::Connection db; + ASSERT_TRUE(db.Open(v2_db_path)); + sql::Statement smt(db.GetUniqueStatement( + "SELECT value FROM meta WHERE key = \"version\"")); + ASSERT_TRUE(smt); + ASSERT_TRUE(smt.Step()); + EXPECT_EQ(3, smt.ColumnInt(0)); + EXPECT_FALSE(smt.Step()); + } } } @@ -212,6 +346,7 @@ TEST_F(SQLiteOriginBoundCertStoreTest, TestFlush) { net::DefaultOriginBoundCertStore::OriginBoundCert( origin, net::CLIENT_CERT_RSA_SIGN, + base::Time(), private_key, cert)); } diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index 5483ea3..1e2ecf1 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -3944,7 +3944,6 @@ '../webkit/support/webkit_support.gyp:glue', ], 'sources': [ - 'browser/net/sqlite_origin_bound_cert_store_unittest.cc', 'browser/safe_browsing/filter_false_positive_perftest.cc', 'browser/visitedlink/visitedlink_perftest.cc', 'common/json_value_serializer_perftest.cc', diff --git a/net/base/default_origin_bound_cert_store.cc b/net/base/default_origin_bound_cert_store.cc index 8104658..3c311ca 100644 --- a/net/base/default_origin_bound_cert_store.cc +++ b/net/base/default_origin_bound_cert_store.cc @@ -30,6 +30,7 @@ void DefaultOriginBoundCertStore::FlushStore( bool DefaultOriginBoundCertStore::GetOriginBoundCert( const std::string& origin, SSLClientCertType* type, + base::Time* expiration_time, std::string* private_key_result, std::string* cert_result) { base::AutoLock autolock(lock_); @@ -42,6 +43,7 @@ bool DefaultOriginBoundCertStore::GetOriginBoundCert( OriginBoundCert* cert = it->second; *type = cert->type(); + *expiration_time = cert->expiration_time(); *private_key_result = cert->private_key(); *cert_result = cert->cert(); @@ -51,6 +53,7 @@ bool DefaultOriginBoundCertStore::GetOriginBoundCert( void DefaultOriginBoundCertStore::SetOriginBoundCert( const std::string& origin, SSLClientCertType type, + base::Time expiration_time, const std::string& private_key, const std::string& cert) { base::AutoLock autolock(lock_); @@ -58,7 +61,8 @@ void DefaultOriginBoundCertStore::SetOriginBoundCert( InternalDeleteOriginBoundCert(origin); InternalInsertOriginBoundCert( - origin, new OriginBoundCert(origin, type, private_key, cert)); + origin, + new OriginBoundCert(origin, type, expiration_time, private_key, cert)); } void DefaultOriginBoundCertStore::DeleteOriginBoundCert( diff --git a/net/base/default_origin_bound_cert_store.h b/net/base/default_origin_bound_cert_store.h index 8f9a3e3..1714248 100644 --- a/net/base/default_origin_bound_cert_store.h +++ b/net/base/default_origin_bound_cert_store.h @@ -57,11 +57,13 @@ class NET_EXPORT DefaultOriginBoundCertStore : public OriginBoundCertStore { virtual bool GetOriginBoundCert( const std::string& origin, SSLClientCertType* type, + base::Time* expiration_time, std::string* private_key_result, std::string* cert_result) OVERRIDE; virtual void SetOriginBoundCert( const std::string& origin, SSLClientCertType type, + base::Time expiration_time, const std::string& private_key, const std::string& cert) OVERRIDE; virtual void DeleteOriginBoundCert(const std::string& origin) OVERRIDE; diff --git a/net/base/default_origin_bound_cert_store_unittest.cc b/net/base/default_origin_bound_cert_store_unittest.cc index 6b888e0..a62191a 100644 --- a/net/base/default_origin_bound_cert_store_unittest.cc +++ b/net/base/default_origin_bound_cert_store_unittest.cc @@ -77,40 +77,59 @@ TEST(DefaultOriginBoundCertStoreTest, TestLoading) { persistent_store->AddOriginBoundCert( DefaultOriginBoundCertStore::OriginBoundCert( - "https://encrypted.google.com/", CLIENT_CERT_RSA_SIGN, "a", "b")); + "https://encrypted.google.com/", + CLIENT_CERT_RSA_SIGN, + base::Time(), + "a", "b")); persistent_store->AddOriginBoundCert( DefaultOriginBoundCertStore::OriginBoundCert( - "https://www.verisign.com/", CLIENT_CERT_ECDSA_SIGN, "c", "d")); + "https://www.verisign.com/", + CLIENT_CERT_ECDSA_SIGN, + base::Time(), + "c", "d")); // Make sure certs load properly. DefaultOriginBoundCertStore store(persistent_store.get()); EXPECT_EQ(2, store.GetCertCount()); store.SetOriginBoundCert( - "https://www.verisign.com/", CLIENT_CERT_RSA_SIGN, "e", "f"); + "https://www.verisign.com/", + CLIENT_CERT_RSA_SIGN, + base::Time(), + "e", "f"); EXPECT_EQ(2, store.GetCertCount()); store.SetOriginBoundCert( - "https://www.twitter.com/", CLIENT_CERT_RSA_SIGN, "g", "h"); + "https://www.twitter.com/", + CLIENT_CERT_RSA_SIGN, + base::Time(), + "g", "h"); EXPECT_EQ(3, store.GetCertCount()); } TEST(DefaultOriginBoundCertStoreTest, TestSettingAndGetting) { DefaultOriginBoundCertStore store(NULL); SSLClientCertType type; + base::Time expiration_time; std::string private_key, cert; EXPECT_EQ(0, store.GetCertCount()); EXPECT_FALSE(store.GetOriginBoundCert("https://www.verisign.com/", &type, + &expiration_time, &private_key, &cert)); EXPECT_TRUE(private_key.empty()); EXPECT_TRUE(cert.empty()); store.SetOriginBoundCert( - "https://www.verisign.com/", CLIENT_CERT_RSA_SIGN, "i", "j"); + "https://www.verisign.com/", + CLIENT_CERT_RSA_SIGN, + base::Time::FromInternalValue(123), + "i", "j"); EXPECT_TRUE(store.GetOriginBoundCert("https://www.verisign.com/", &type, + &expiration_time, &private_key, &cert)); EXPECT_EQ(CLIENT_CERT_RSA_SIGN, type); + EXPECT_EQ(123, expiration_time.ToInternalValue()); EXPECT_EQ("i", private_key); EXPECT_EQ("j", cert); } @@ -120,19 +139,28 @@ TEST(DefaultOriginBoundCertStoreTest, TestDuplicateCerts) { DefaultOriginBoundCertStore store(persistent_store.get()); SSLClientCertType type; + base::Time expiration_time; std::string private_key, cert; EXPECT_EQ(0, store.GetCertCount()); store.SetOriginBoundCert( - "https://www.verisign.com/", CLIENT_CERT_RSA_SIGN, "a", "b"); + "https://www.verisign.com/", + CLIENT_CERT_RSA_SIGN, + base::Time::FromInternalValue(123), + "a", "b"); store.SetOriginBoundCert( - "https://www.verisign.com/", CLIENT_CERT_ECDSA_SIGN, "c", "d"); + "https://www.verisign.com/", + CLIENT_CERT_ECDSA_SIGN, + base::Time::FromInternalValue(456), + "c", "d"); EXPECT_EQ(1, store.GetCertCount()); EXPECT_TRUE(store.GetOriginBoundCert("https://www.verisign.com/", &type, + &expiration_time, &private_key, &cert)); EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, type); + EXPECT_EQ(456, expiration_time.ToInternalValue()); EXPECT_EQ("c", private_key); EXPECT_EQ("d", cert); } @@ -143,11 +171,20 @@ TEST(DefaultOriginBoundCertStoreTest, TestDeleteAll) { EXPECT_EQ(0, store.GetCertCount()); store.SetOriginBoundCert( - "https://www.verisign.com/", CLIENT_CERT_RSA_SIGN, "a", "b"); + "https://www.verisign.com/", + CLIENT_CERT_RSA_SIGN, + base::Time(), + "a", "b"); store.SetOriginBoundCert( - "https://www.google.com/", CLIENT_CERT_RSA_SIGN, "c", "d"); + "https://www.google.com/", + CLIENT_CERT_RSA_SIGN, + base::Time(), + "c", "d"); store.SetOriginBoundCert( - "https://www.harvard.com/", CLIENT_CERT_RSA_SIGN, "e", "f"); + "https://www.harvard.com/", + CLIENT_CERT_RSA_SIGN, + base::Time(), + "e", "f"); EXPECT_EQ(3, store.GetCertCount()); store.DeleteAll(); @@ -159,28 +196,38 @@ TEST(DefaultOriginBoundCertStoreTest, TestDelete) { DefaultOriginBoundCertStore store(persistent_store.get()); SSLClientCertType type; + base::Time expiration_time; std::string private_key, cert; EXPECT_EQ(0, store.GetCertCount()); store.SetOriginBoundCert( - "https://www.verisign.com/", CLIENT_CERT_RSA_SIGN, "a", "b"); + "https://www.verisign.com/", + CLIENT_CERT_RSA_SIGN, + base::Time(), + "a", "b"); store.SetOriginBoundCert( - "https://www.google.com/", CLIENT_CERT_ECDSA_SIGN, "c", "d"); + "https://www.google.com/", + CLIENT_CERT_ECDSA_SIGN, + base::Time(), + "c", "d"); EXPECT_EQ(2, store.GetCertCount()); store.DeleteOriginBoundCert("https://www.verisign.com/"); EXPECT_EQ(1, store.GetCertCount()); EXPECT_FALSE(store.GetOriginBoundCert("https://www.verisign.com/", &type, + &expiration_time, &private_key, &cert)); EXPECT_TRUE(store.GetOriginBoundCert("https://www.google.com/", &type, + &expiration_time, &private_key, &cert)); store.DeleteOriginBoundCert("https://www.google.com/"); EXPECT_EQ(0, store.GetCertCount()); EXPECT_FALSE(store.GetOriginBoundCert("https://www.google.com/", &type, + &expiration_time, &private_key, &cert)); } @@ -191,13 +238,25 @@ TEST(DefaultOriginBoundCertStoreTest, TestGetAll) { EXPECT_EQ(0, store.GetCertCount()); store.SetOriginBoundCert( - "https://www.verisign.com/", CLIENT_CERT_RSA_SIGN, "a", "b"); + "https://www.verisign.com/", + CLIENT_CERT_RSA_SIGN, + base::Time(), + "a", "b"); store.SetOriginBoundCert( - "https://www.google.com/", CLIENT_CERT_ECDSA_SIGN, "c", "d"); + "https://www.google.com/", + CLIENT_CERT_ECDSA_SIGN, + base::Time(), + "c", "d"); store.SetOriginBoundCert( - "https://www.harvard.com/", CLIENT_CERT_RSA_SIGN, "e", "f"); + "https://www.harvard.com/", + CLIENT_CERT_RSA_SIGN, + base::Time(), + "e", "f"); store.SetOriginBoundCert( - "https://www.mit.com/", CLIENT_CERT_RSA_SIGN, "g", "h"); + "https://www.mit.com/", + CLIENT_CERT_RSA_SIGN, + base::Time(), + "g", "h"); EXPECT_EQ(4, store.GetCertCount()); std::vector<OriginBoundCertStore::OriginBoundCert> certs; diff --git a/net/base/origin_bound_cert_service.cc b/net/base/origin_bound_cert_service.cc index 762255f..246383e 100644 --- a/net/base/origin_bound_cert_service.cc +++ b/net/base/origin_bound_cert_service.cc @@ -134,6 +134,7 @@ class OriginBoundCertServiceWorker { error_ = OriginBoundCertService::GenerateCert(origin_, type_, serial_number_, + &expiration_time_, &private_key_, &cert_); #if defined(USE_NSS) @@ -159,8 +160,8 @@ class OriginBoundCertServiceWorker { // memory leaks or worse errors. base::AutoLock locked(lock_); if (!canceled_) { - origin_bound_cert_service_->HandleResult(origin_, error_, type_, - private_key_, cert_); + origin_bound_cert_service_->HandleResult( + origin_, error_, type_, expiration_time_, private_key_, cert_); } } delete this; @@ -208,6 +209,7 @@ class OriginBoundCertServiceWorker { bool canceled_; int error_; + base::Time expiration_time_; std::string private_key_; std::string cert_; @@ -322,20 +324,26 @@ int OriginBoundCertService::GetOriginBoundCert( requests_++; // Check if an origin bound cert of an acceptable type already exists for this - // origin. + // origin, and that it has not expired. + base::Time now = base::Time::Now(); + base::Time expiration_time; if (origin_bound_cert_store_->GetOriginBoundCert(origin, type, + &expiration_time, private_key, cert)) { - if (IsSupportedCertType(*type) && - std::find(requested_types.begin(), requested_types.end(), *type) != - requested_types.end()) { + if (expiration_time < now) { + DVLOG(1) << "Cert store had expired cert for " << origin; + } else if (!IsSupportedCertType(*type) || + std::find(requested_types.begin(), requested_types.end(), + *type) == requested_types.end()) { + DVLOG(1) << "Cert store had cert of wrong type " << *type << " for " + << origin; + } else { cert_store_hits_++; *out_req = NULL; return OK; } - DVLOG(1) << "Cert store had cert of wrong type " << *type << " for " - << origin; } // |origin_bound_cert_store_| has no cert for this origin. See if an @@ -363,8 +371,10 @@ int OriginBoundCertService::GetOriginBoundCert( inflight_joins_++; } else { // Need to make a new request. - OriginBoundCertServiceWorker* worker = - new OriginBoundCertServiceWorker(origin, preferred_type, this); + OriginBoundCertServiceWorker* worker = new OriginBoundCertServiceWorker( + origin, + preferred_type, + this); job = new OriginBoundCertServiceJob(worker, preferred_type); if (!worker->Start()) { delete job; @@ -388,8 +398,12 @@ int OriginBoundCertService::GetOriginBoundCert( int OriginBoundCertService::GenerateCert(const std::string& origin, SSLClientCertType type, uint32 serial_number, + base::Time* expiration_time, std::string* private_key, std::string* cert) { + base::Time now = base::Time::Now(); + base::Time not_valid_after = + now + base::TimeDelta::FromDays(kValidityPeriodInDays); std::string der_cert; std::vector<uint8> private_key_info; switch (type) { @@ -404,7 +418,8 @@ int OriginBoundCertService::GenerateCert(const std::string& origin, key.get(), origin, serial_number, - base::TimeDelta::FromDays(kValidityPeriodInDays), + now, + not_valid_after, &der_cert)) { DLOG(ERROR) << "Unable to create x509 cert for client"; return ERR_ORIGIN_BOUND_CERT_GENERATION_FAILED; @@ -426,7 +441,8 @@ int OriginBoundCertService::GenerateCert(const std::string& origin, key.get(), origin, serial_number, - base::TimeDelta::FromDays(kValidityPeriodInDays), + now, + not_valid_after, &der_cert)) { DLOG(ERROR) << "Unable to create x509 cert for client"; return ERR_ORIGIN_BOUND_CERT_GENERATION_FAILED; @@ -450,6 +466,7 @@ int OriginBoundCertService::GenerateCert(const std::string& origin, private_key->swap(key_out); cert->swap(der_cert); + *expiration_time = not_valid_after; return OK; } @@ -465,11 +482,13 @@ void OriginBoundCertService::CancelRequest(RequestHandle req) { void OriginBoundCertService::HandleResult(const std::string& origin, int error, SSLClientCertType type, + base::Time expiration_time, const std::string& private_key, const std::string& cert) { DCHECK(CalledOnValidThread()); - origin_bound_cert_store_->SetOriginBoundCert(origin, type, private_key, cert); + origin_bound_cert_store_->SetOriginBoundCert( + origin, type, expiration_time, private_key, cert); std::map<std::string, OriginBoundCertServiceJob*>::iterator j; j = inflight_.find(origin); diff --git a/net/base/origin_bound_cert_service.h b/net/base/origin_bound_cert_service.h index c3861e6..0f78260 100644 --- a/net/base/origin_bound_cert_service.h +++ b/net/base/origin_bound_cert_service.h @@ -12,6 +12,7 @@ #include "base/basictypes.h" #include "base/memory/scoped_ptr.h" +#include "base/time.h" #include "base/threading/non_thread_safe.h" #include "net/base/completion_callback.h" #include "net/base/net_export.h" @@ -86,7 +87,8 @@ class NET_EXPORT OriginBoundCertService friend class OriginBoundCertServiceWorker; // Calls HandleResult. // On success, |private_key| stores a DER-encoded PrivateKeyInfo - // struct, and |cert| stores a DER-encoded certificate. Returns + // struct, |cert| stores a DER-encoded certificate, and |expiration_time| + // stores the expiration time of the certificate. Returns // OK if successful and an error code otherwise. // |serial_number| is passed in because it is created with the function // base::RandInt, which opens the file /dev/urandom. /dev/urandom is opened @@ -94,12 +96,14 @@ class NET_EXPORT OriginBoundCertService static int GenerateCert(const std::string& origin, SSLClientCertType type, uint32 serial_number, + base::Time* expiration_time, std::string* private_key, std::string* cert); void HandleResult(const std::string& origin, int error, SSLClientCertType type, + base::Time expiration_time, const std::string& private_key, const std::string& cert); diff --git a/net/base/origin_bound_cert_service_unittest.cc b/net/base/origin_bound_cert_service_unittest.cc index 1adedfa..65f40a5 100644 --- a/net/base/origin_bound_cert_service_unittest.cc +++ b/net/base/origin_bound_cert_service_unittest.cc @@ -457,6 +457,56 @@ TEST(OriginBoundCertServiceTest, CancelRequest) { EXPECT_EQ(6, service->cert_count()); } +TEST(OriginBoundCertServiceTest, Expiration) { + OriginBoundCertStore* store = new DefaultOriginBoundCertStore(NULL); + store->SetOriginBoundCert("https://good", + CLIENT_CERT_RSA_SIGN, + base::Time::Now() + base::TimeDelta::FromDays(1), + "a", + "b"); + store->SetOriginBoundCert("https://expired", + CLIENT_CERT_RSA_SIGN, + base::Time::Now() - base::TimeDelta::FromDays(1), + "c", + "d"); + OriginBoundCertService service(store); + EXPECT_EQ(2, service.cert_count()); + + int error; + std::vector<uint8> types; + types.push_back(CLIENT_CERT_RSA_SIGN); + TestCompletionCallback callback; + OriginBoundCertService::RequestHandle request_handle; + + // Cert still valid - synchronous completion. + SSLClientCertType type1; + std::string private_key_info1, der_cert1; + error = service.GetOriginBoundCert( + "https://good", types, &type1, &private_key_info1, &der_cert1, + callback.callback(), &request_handle); + EXPECT_EQ(OK, error); + EXPECT_TRUE(request_handle == NULL); + EXPECT_EQ(2, service.cert_count()); + EXPECT_EQ(CLIENT_CERT_RSA_SIGN, type1); + EXPECT_STREQ("a", private_key_info1.c_str()); + EXPECT_STREQ("b", der_cert1.c_str()); + + // Cert expired - New cert will be generated, asynchronous completion. + SSLClientCertType type2; + std::string private_key_info2, der_cert2; + error = service.GetOriginBoundCert( + "https://expired", types, &type2, &private_key_info2, &der_cert2, + callback.callback(), &request_handle); + EXPECT_EQ(ERR_IO_PENDING, error); + EXPECT_TRUE(request_handle != NULL); + error = callback.WaitForResult(); + EXPECT_EQ(OK, error); + EXPECT_EQ(2, service.cert_count()); + EXPECT_EQ(CLIENT_CERT_RSA_SIGN, type2); + EXPECT_LT(1U, private_key_info2.size()); + EXPECT_LT(1U, der_cert2.size()); +} + #endif // !defined(USE_OPENSSL) } // namespace diff --git a/net/base/origin_bound_cert_store.cc b/net/base/origin_bound_cert_store.cc index fe2b45f..6a31a7e 100644 --- a/net/base/origin_bound_cert_store.cc +++ b/net/base/origin_bound_cert_store.cc @@ -13,10 +13,12 @@ OriginBoundCertStore::OriginBoundCert::OriginBoundCert() OriginBoundCertStore::OriginBoundCert::OriginBoundCert( const std::string& origin, SSLClientCertType type, + base::Time expiration_time, const std::string& private_key, const std::string& cert) : origin_(origin), type_(type), + expiration_time_(expiration_time), private_key_(private_key), cert_(cert) {} diff --git a/net/base/origin_bound_cert_store.h b/net/base/origin_bound_cert_store.h index 094839b..1eb8382 100644 --- a/net/base/origin_bound_cert_store.h +++ b/net/base/origin_bound_cert_store.h @@ -9,6 +9,7 @@ #include <string> #include <vector> +#include "base/time.h" #include "net/base/net_export.h" #include "net/base/ssl_client_cert_type.h" @@ -30,6 +31,7 @@ class NET_EXPORT OriginBoundCertStore { OriginBoundCert(); OriginBoundCert(const std::string& origin, SSLClientCertType type, + base::Time expiration_time, const std::string& private_key, const std::string& cert); ~OriginBoundCert(); @@ -38,6 +40,8 @@ class NET_EXPORT OriginBoundCertStore { const std::string& origin() const { return origin_; } // TLS ClientCertificateType. SSLClientCertType type() const { return type_; } + // The time after which this certificate is no longer valid. + base::Time expiration_time() const { return expiration_time_; } // The encoding of the private key depends on the type. // rsa_sign: DER-encoded PrivateKeyInfo struct. // ecdsa_sign: DER-encoded EncryptedPrivateKeyInfo struct. @@ -48,6 +52,7 @@ class NET_EXPORT OriginBoundCertStore { private: std::string origin_; SSLClientCertType type_; + base::Time expiration_time_; std::string private_key_; std::string cert_; }; @@ -57,12 +62,14 @@ class NET_EXPORT OriginBoundCertStore { // TODO(rkn): File I/O may be required, so this should have an asynchronous // interface. // Returns true on success. |private_key_result| stores a DER-encoded - // PrivateKeyInfo struct and |cert_result| stores a DER-encoded - // certificate. Returns false if no origin bound cert exists for the - // specified origin. + // PrivateKeyInfo struct, |cert_result| stores a DER-encoded certificate, + // |type| is the ClientCertificateType of the returned certificate, and + // |expiration_time| is the expiration time of the certificate. + // Returns false if no origin bound cert exists for the specified origin. virtual bool GetOriginBoundCert( const std::string& origin, SSLClientCertType* type, + base::Time* expiration_time, std::string* private_key_result, std::string* cert_result) = 0; @@ -70,6 +77,7 @@ class NET_EXPORT OriginBoundCertStore { virtual void SetOriginBoundCert( const std::string& origin, SSLClientCertType type, + base::Time expiration_time, const std::string& private_key, const std::string& cert) = 0; diff --git a/net/base/x509_certificate_nss.cc b/net/base/x509_certificate_nss.cc index 39f2a94..b4bf88d 100644 --- a/net/base/x509_certificate_nss.cc +++ b/net/base/x509_certificate_nss.cc @@ -778,11 +778,14 @@ X509Certificate* X509Certificate::CreateSelfSigned( base::TimeDelta valid_duration) { DCHECK(key); + base::Time not_valid_before = base::Time::Now(); + base::Time not_valid_after = not_valid_before + valid_duration; CERTCertificate* cert = x509_util::CreateSelfSignedCert(key->public_key(), key->key(), subject, serial_number, - valid_duration); + not_valid_before, + not_valid_after); if (!cert) return NULL; diff --git a/net/base/x509_util.h b/net/base/x509_util.h index 1d8c933..b35d274 100644 --- a/net/base/x509_util.h +++ b/net/base/x509_util.h @@ -30,12 +30,14 @@ namespace x509_util { bool NET_EXPORT_PRIVATE CreateOriginBoundCertRSA(crypto::RSAPrivateKey* key, const std::string& origin, uint32 serial_number, - base::TimeDelta valid_duration, + base::Time not_valid_before, + base::Time not_valid_after, std::string* der_cert); bool NET_EXPORT_PRIVATE CreateOriginBoundCertEC(crypto::ECPrivateKey* key, const std::string& origin, uint32 serial_number, - base::TimeDelta valid_duration, + base::Time not_valid_before, + base::Time not_valid_after, std::string* der_cert); } // namespace x509_util diff --git a/net/base/x509_util_nss.cc b/net/base/x509_util_nss.cc index 61126af..3f630e2 100644 --- a/net/base/x509_util_nss.cc +++ b/net/base/x509_util_nss.cc @@ -78,7 +78,8 @@ CERTCertificate* CreateCertificate( SECKEYPublicKey* public_key, const std::string& subject, uint32 serial_number, - base::TimeDelta valid_duration) { + base::Time not_valid_before, + base::Time not_valid_after) { // Create info about public key. CERTSubjectPublicKeyInfo* spki = SECKEY_CreateSubjectPublicKeyInfo(public_key); @@ -99,11 +100,9 @@ CERTCertificate* CreateCertificate( return NULL; } - PRTime now = PR_Now(); - PRTime not_after = now + valid_duration.InMicroseconds(); - - // Note that the time is now in micro-second unit. - CERTValidity* validity = CERT_CreateValidity(now, not_after); + CERTValidity* validity = CERT_CreateValidity( + crypto::BaseTimeToPRTime(not_valid_before), + crypto::BaseTimeToPRTime(not_valid_after)); CERTCertificate* cert = CERT_CreateCertificate(serial_number, subject_name, validity, cert_request); if (!cert) { @@ -176,13 +175,15 @@ bool CreateOriginBoundCertInternal( SECKEYPrivateKey* private_key, const std::string& origin, uint32 serial_number, - base::TimeDelta valid_duration, + base::Time not_valid_before, + base::Time not_valid_after, std::string* der_cert) { CERTCertificate* cert = CreateCertificate(public_key, "CN=anonymous.invalid", serial_number, - valid_duration); + not_valid_before, + not_valid_after); if (!cert) return false; @@ -254,11 +255,13 @@ CERTCertificate* CreateSelfSignedCert( SECKEYPrivateKey* private_key, const std::string& subject, uint32 serial_number, - base::TimeDelta valid_duration) { + base::Time not_valid_before, + base::Time not_valid_after) { CERTCertificate* cert = CreateCertificate(public_key, subject, serial_number, - valid_duration); + not_valid_before, + not_valid_after); if (!cert) return NULL; @@ -274,7 +277,8 @@ bool CreateOriginBoundCertRSA( crypto::RSAPrivateKey* key, const std::string& origin, uint32 serial_number, - base::TimeDelta valid_duration, + base::Time not_valid_before, + base::Time not_valid_after, std::string* der_cert) { DCHECK(key); @@ -329,7 +333,8 @@ bool CreateOriginBoundCertRSA( private_key, origin, serial_number, - valid_duration, + not_valid_before, + not_valid_after, der_cert); } @@ -337,14 +342,16 @@ bool CreateOriginBoundCertEC( crypto::ECPrivateKey* key, const std::string& origin, uint32 serial_number, - base::TimeDelta valid_duration, + base::Time not_valid_before, + base::Time not_valid_after, std::string* der_cert) { DCHECK(key); return CreateOriginBoundCertInternal(key->public_key(), key->key(), origin, serial_number, - valid_duration, + not_valid_before, + not_valid_after, der_cert); } diff --git a/net/base/x509_util_nss.h b/net/base/x509_util_nss.h index 82dd4f9..b5cc503 100644 --- a/net/base/x509_util_nss.h +++ b/net/base/x509_util_nss.h @@ -28,7 +28,8 @@ CERTCertificate* CreateSelfSignedCert( SECKEYPrivateKey* private_key, const std::string& subject, uint32 serial_number, - base::TimeDelta valid_duration); + base::Time not_valid_before, + base::Time not_valid_after); } // namespace x509_util diff --git a/net/base/x509_util_nss_unittest.cc b/net/base/x509_util_nss_unittest.cc index 7490874..1dc2cd2 100644 --- a/net/base/x509_util_nss_unittest.cc +++ b/net/base/x509_util_nss_unittest.cc @@ -145,14 +145,17 @@ void VerifyOriginBoundCert(const std::string& origin, TEST(X509UtilNSSTest, CreateOriginBoundCertRSA) { // Create a sample ASCII weborigin. std::string origin = "http://weborigin.com:443"; + base::Time now = base::Time::Now(); scoped_ptr<crypto::RSAPrivateKey> private_key( crypto::RSAPrivateKey::Create(1024)); std::string der_cert; - ASSERT_TRUE(x509_util::CreateOriginBoundCertRSA(private_key.get(), - origin, 1, - base::TimeDelta::FromDays(1), - &der_cert)); + ASSERT_TRUE(x509_util::CreateOriginBoundCertRSA( + private_key.get(), + origin, 1, + now, + now + base::TimeDelta::FromDays(1), + &der_cert)); VerifyOriginBoundCert(origin, der_cert); @@ -166,14 +169,17 @@ TEST(X509UtilNSSTest, CreateOriginBoundCertRSA) { TEST(X509UtilNSSTest, CreateOriginBoundCertEC) { // Create a sample ASCII weborigin. std::string origin = "http://weborigin.com:443"; + base::Time now = base::Time::Now(); scoped_ptr<crypto::ECPrivateKey> private_key( crypto::ECPrivateKey::Create()); std::string der_cert; - ASSERT_TRUE(x509_util::CreateOriginBoundCertEC(private_key.get(), - origin, 1, - base::TimeDelta::FromDays(1), - &der_cert)); + ASSERT_TRUE(x509_util::CreateOriginBoundCertEC( + private_key.get(), + origin, 1, + now, + now + base::TimeDelta::FromDays(1), + &der_cert)); VerifyOriginBoundCert(origin, der_cert); diff --git a/net/base/x509_util_openssl.cc b/net/base/x509_util_openssl.cc index e663b95..786dd86 100644 --- a/net/base/x509_util_openssl.cc +++ b/net/base/x509_util_openssl.cc @@ -19,7 +19,8 @@ bool CreateOriginBoundCertRSA( crypto::RSAPrivateKey* key, const std::string& origin, uint32 serial_number, - base::TimeDelta valid_duration, + base::Time not_valid_before, + base::Time not_valid_after, std::string* der_cert) { NOTIMPLEMENTED(); return false; @@ -29,7 +30,8 @@ bool CreateOriginBoundCertEC( crypto::ECPrivateKey* key, const std::string& origin, uint32 serial_number, - base::TimeDelta valid_duration, + base::Time not_valid_before, + base::Time not_valid_after, std::string* der_cert) { NOTIMPLEMENTED(); return false; diff --git a/net/base/x509_util_openssl_unittest.cc b/net/base/x509_util_openssl_unittest.cc index 23c33a3..5d96dfa 100644 --- a/net/base/x509_util_openssl_unittest.cc +++ b/net/base/x509_util_openssl_unittest.cc @@ -15,13 +15,16 @@ namespace net { // is present. TEST(X509UtilOpenSSLTest, CreateOriginBoundCertNotImplemented) { std::string origin = "http://weborigin.com:443"; + base::Time now = base::Time::Now(); scoped_ptr<crypto::RSAPrivateKey> private_key( crypto::RSAPrivateKey::Create(1024)); std::string der_cert; - EXPECT_FALSE(x509_util::CreateOriginBoundCertRSA(private_key.get(), - origin, 1, - base::TimeDelta::FromDays(1), - &der_cert)); + EXPECT_FALSE(x509_util::CreateOriginBoundCertRSA( + private_key.get(), + origin, 1, + now, + now + base::TimeDelta::FromDays(1), + &der_cert)); EXPECT_TRUE(der_cert.empty()); } |