Commit 1a32990c authored by Nick Harper's avatar Nick Harper Committed by Commit Bot

Don't use crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo in //net

This function was only used in the SQLite Channel ID store; a migration
away from it was added in April. This change removes the use of the
function which until now is only used for migrating old Channel ID db
formats to the new format. With this change, old databases won't be
upgradeable.

Bug: 618026
Change-Id: I245077dd1cb16cb5a53b174a15d7dbdf0e0e9942
Reviewed-on: https://chromium-review.googlesource.com/669866
Commit-Queue: Nick Harper <nharper@chromium.org>
Reviewed-by: default avatarDavid Benjamin <davidben@chromium.org>
Cr-Commit-Position: refs/heads/master@{#502966}
parent 6f91dde5
......@@ -321,92 +321,6 @@ bool SQLiteChannelIDStore::Backend::EnsureDatabaseVersion() {
}
}
// Migrate from previous versions to new version if possible
if (cur_version >= 2 && cur_version <= 4) {
sql::Statement statement(db_->GetUniqueStatement(
"SELECT origin, cert, private_key, cert_type FROM origin_bound_certs"));
sql::Statement insert_statement(db_->GetUniqueStatement(
"INSERT INTO channel_id (host, private_key, public_key, creation_time) "
"VALUES (?, ?, \"\", ?)"));
if (!statement.is_valid() || !insert_statement.is_valid()) {
LOG(WARNING) << "Unable to update server bound cert database to "
<< "version 6.";
return false;
}
while (statement.Step()) {
if (statement.ColumnInt64(3) != CLIENT_CERT_ECDSA_SIGN)
continue;
std::string origin = statement.ColumnString(0);
std::string cert_from_db;
statement.ColumnBlobAsString(1, &cert_from_db);
std::vector<uint8_t> encrypted_private_key, private_key;
statement.ColumnBlobAsVector(2, &encrypted_private_key);
std::unique_ptr<crypto::ECPrivateKey> key(
crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo(
encrypted_private_key, std::vector<uint8_t>()));
if (!key || !key->ExportPrivateKey(&private_key)) {
LOG(WARNING) << "Unable to parse encrypted private key when migrating "
"Channel ID database to version 6.";
continue;
}
// Parse the cert and extract the real value and then update the DB.
scoped_refptr<X509Certificate> cert(X509Certificate::CreateFromBytes(
cert_from_db.data(), static_cast<int>(cert_from_db.size())));
if (cert.get()) {
insert_statement.Reset(true);
insert_statement.BindString(0, origin);
insert_statement.BindBlob(1, private_key.data(),
static_cast<int>(private_key.size()));
insert_statement.BindInt64(2, cert->valid_start().ToInternalValue());
if (!insert_statement.Run()) {
LOG(WARNING) << "Unable to update channel id database to "
<< "version 6.";
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 "
<< statement.ColumnString(0);
}
}
} else if (cur_version == 5) {
sql::Statement select(
db_->GetUniqueStatement("SELECT host, private_key FROM channel_id"));
sql::Statement update(
db_->GetUniqueStatement("UPDATE channel_id SET private_key = ?, "
"public_key = \"\" WHERE host = ?"));
if (!select.is_valid() || !update.is_valid()) {
LOG(WARNING) << "Invalid SQL statements to update Channel ID database to "
"version 6.";
return false;
}
while (select.Step()) {
std::string host = select.ColumnString(0);
std::vector<uint8_t> encrypted_private_key, private_key;
select.ColumnBlobAsVector(1, &encrypted_private_key);
std::unique_ptr<crypto::ECPrivateKey> key(
crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo(
encrypted_private_key, std::vector<uint8_t>()));
if (!key || !key->ExportPrivateKey(&private_key)) {
LOG(WARNING) << "Unable to parse encrypted private key when migrating "
"Channel ID database to version 6.";
continue;
}
update.Reset(true);
update.BindBlob(0, private_key.data(),
static_cast<int>(private_key.size()));
update.BindString(1, host);
if (!update.Run()) {
LOG(WARNING) << "UPDATE statement failed when updating Channel ID "
"database to version 6.";
return false;
}
}
}
if (cur_version < kCurrentVersionNumber) {
if (cur_version <= 4) {
sql::Statement statement(
......@@ -416,6 +330,16 @@ bool SQLiteChannelIDStore::Backend::EnsureDatabaseVersion() {
return false;
}
}
if (cur_version < 6) {
// The old format had the private_key column in a format we no longer
// read. Just delete any entries in that format.
sql::Statement statement(
db_->GetUniqueStatement("DELETE FROM channel_id"));
if (!statement.Run()) {
LOG(WARNING) << "Error clearing channel_id table";
return false;
}
}
meta_table_.SetVersionNumber(kCurrentVersionNumber);
meta_table_.SetCompatibleVersionNumber(kCompatibleVersionNumber);
}
......
......@@ -12,6 +12,7 @@
#include "base/files/scoped_temp_dir.h"
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "crypto/ec_private_key.h"
#include "net/cert/asn1_util.h"
......@@ -50,23 +51,14 @@ class SQLiteChannelIDStoreTest : public testing::Test {
}
protected:
static void ReadTestKeyAndCert(std::string* key_data,
std::string* cert_data,
std::unique_ptr<crypto::ECPrivateKey>* key) {
static void ReadLegacyTestKeyAndCert(std::string* key_data,
std::string* cert_data) {
base::FilePath key_path =
GetTestCertsDirectory().AppendASCII("unittest.originbound.key.der");
base::FilePath cert_path =
GetTestCertsDirectory().AppendASCII("unittest.originbound.der");
ASSERT_TRUE(base::ReadFileToString(key_path, key_data));
ASSERT_TRUE(base::ReadFileToString(cert_path, cert_data));
std::vector<uint8_t> private_key(key_data->size());
memcpy(private_key.data(), key_data->data(), key_data->size());
base::StringPiece spki;
ASSERT_TRUE(asn1::ExtractSPKIFromDERCert(*cert_data, &spki));
std::vector<uint8_t> public_key(spki.size());
memcpy(public_key.data(), spki.data(), spki.size());
*key = crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo(private_key,
public_key);
}
static base::Time GetTestCertExpirationTime() {
......@@ -234,8 +226,7 @@ TEST_F(SQLiteChannelIDStoreTest, TestUpgradeV1) {
std::string key_data;
std::string cert_data;
std::unique_ptr<crypto::ECPrivateKey> key;
ASSERT_NO_FATAL_FAILURE(ReadTestKeyAndCert(&key_data, &cert_data, &key));
ASSERT_NO_FATAL_FAILURE(ReadLegacyTestKeyAndCert(&key_data, &cert_data));
// Create a version 1 database.
{
......@@ -263,9 +254,12 @@ TEST_F(SQLiteChannelIDStoreTest, TestUpgradeV1) {
"'foo.com',X'AA',X'BB');"));
}
// 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.
// Load and test the DB contents twice. The first time checks that the
// migration ran properly; the second time ensures that the DB is still
// readable post-migration.
//
// Since the V1 format is unsupported, the second load will be reading an
// empty database.
for (int i = 0; i < 2; ++i) {
SCOPED_TRACE(i);
......@@ -302,8 +296,7 @@ TEST_F(SQLiteChannelIDStoreTest, TestUpgradeV2) {
std::string key_data;
std::string cert_data;
std::unique_ptr<crypto::ECPrivateKey> key;
ASSERT_NO_FATAL_FAILURE(ReadTestKeyAndCert(&key_data, &cert_data, &key));
ASSERT_NO_FATAL_FAILURE(ReadLegacyTestKeyAndCert(&key_data, &cert_data));
// Create a version 2 database.
{
......@@ -335,9 +328,12 @@ TEST_F(SQLiteChannelIDStoreTest, TestUpgradeV2) {
"'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.
// Load and test the DB contents twice. The first time checks that the
// migration ran properly; the second time ensures that the DB is still
// readable post-migration.
//
// Since the V2 format is unsupported, the second load will be reading an
// empty database.
for (int i = 0; i < 2; ++i) {
SCOPED_TRACE(i);
......@@ -345,13 +341,10 @@ TEST_F(SQLiteChannelIDStoreTest, TestUpgradeV2) {
store_ = new SQLiteChannelIDStore(v2_db_path,
base::ThreadTaskRunnerHandle::Get());
// Load the database and ensure the certs can be read.
// Load the database. V2 cert keys are stored in a format that is
// unsupported, so they will be discarded.
Load(&channel_ids);
ASSERT_EQ(1U, channel_ids.size());
ASSERT_EQ("google.com", channel_ids[0]->server_identifier());
ASSERT_EQ(GetTestCertCreationTime(), channel_ids[0]->creation_time());
EXPECT_TRUE(KeysEqual(key.get(), channel_ids[0]->key()));
ASSERT_EQ(0U, channel_ids.size());
store_ = NULL;
// Make sure we wait until the destructor has run.
......@@ -378,8 +371,7 @@ TEST_F(SQLiteChannelIDStoreTest, TestUpgradeV3) {
std::string key_data;
std::string cert_data;
std::unique_ptr<crypto::ECPrivateKey> key;
ASSERT_NO_FATAL_FAILURE(ReadTestKeyAndCert(&key_data, &cert_data, &key));
ASSERT_NO_FATAL_FAILURE(ReadLegacyTestKeyAndCert(&key_data, &cert_data));
// Create a version 3 database.
{
......@@ -413,9 +405,12 @@ TEST_F(SQLiteChannelIDStoreTest, TestUpgradeV3) {
"'foo.com',X'AA',X'BB',64,2000);"));
}
// 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.
// Load and test the DB contents twice. The first time checks that the
// migration ran properly; the second time ensures that the DB is still
// readable post-migration.
//
// Since the V3 format is unsupported, the second load will be reading an
// empty database.
for (int i = 0; i < 2; ++i) {
SCOPED_TRACE(i);
......@@ -423,13 +418,10 @@ TEST_F(SQLiteChannelIDStoreTest, TestUpgradeV3) {
store_ = new SQLiteChannelIDStore(v3_db_path,
base::ThreadTaskRunnerHandle::Get());
// Load the database and ensure the certs can be read.
// Load the database. V3 cert keys are in a format that is no longer
// supported, so they are discarded.
Load(&channel_ids);
ASSERT_EQ(1U, channel_ids.size());
ASSERT_EQ("google.com", channel_ids[0]->server_identifier());
ASSERT_EQ(GetTestCertCreationTime(), channel_ids[0]->creation_time());
EXPECT_TRUE(KeysEqual(key.get(), channel_ids[0]->key()));
ASSERT_EQ(0U, channel_ids.size());
store_ = NULL;
// Make sure we wait until the destructor has run.
......@@ -456,8 +448,7 @@ TEST_F(SQLiteChannelIDStoreTest, TestUpgradeV4) {
std::string key_data;
std::string cert_data;
std::unique_ptr<crypto::ECPrivateKey> key;
ASSERT_NO_FATAL_FAILURE(ReadTestKeyAndCert(&key_data, &cert_data, &key));
ASSERT_NO_FATAL_FAILURE(ReadLegacyTestKeyAndCert(&key_data, &cert_data));
// Create a version 4 database.
{
......@@ -507,9 +498,12 @@ TEST_F(SQLiteChannelIDStoreTest, TestUpgradeV4) {
"'bar.com',X'AA',X'BB',64,2000,3000);"));
}
// 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.
// Load and test the DB contents twice. The first time checks that the
// migration ran properly; the second time ensures that the DB is still
// readable post-migration.
//
// Since the V4 format is unsupported, the second load will be reading an
// empty database.
for (int i = 0; i < 2; ++i) {
SCOPED_TRACE(i);
......@@ -517,13 +511,10 @@ TEST_F(SQLiteChannelIDStoreTest, TestUpgradeV4) {
store_ = new SQLiteChannelIDStore(v4_db_path,
base::ThreadTaskRunnerHandle::Get());
// Load the database and ensure the certs can be read.
// Load the database. V4 cert keys are in a format that is no longer
// supported, so they are discarded.
Load(&channel_ids);
ASSERT_EQ(1U, channel_ids.size());
ASSERT_EQ("google.com", channel_ids[0]->server_identifier());
ASSERT_EQ(GetTestCertCreationTime(), channel_ids[0]->creation_time());
EXPECT_TRUE(KeysEqual(key.get(), channel_ids[0]->key()));
ASSERT_EQ(0U, channel_ids.size());
store_ = NULL;
// Make sure we wait until the destructor has run.
......@@ -550,8 +541,7 @@ TEST_F(SQLiteChannelIDStoreTest, TestUpgradeV5) {
std::string key_data;
std::string cert_data;
std::unique_ptr<crypto::ECPrivateKey> key;
ASSERT_NO_FATAL_FAILURE(ReadTestKeyAndCert(&key_data, &cert_data, &key));
ASSERT_NO_FATAL_FAILURE(ReadLegacyTestKeyAndCert(&key_data, &cert_data));
// Create a version 5 database.
{
......@@ -583,9 +573,12 @@ TEST_F(SQLiteChannelIDStoreTest, TestUpgradeV5) {
"'bar.com',X'AA',X'BB',3000);"));
}
// 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.
// Load and test the DB contents twice. The first time checks that the
// migration ran properly; the second time ensures that the DB is still
// readable post-migration.
//
// Since the V5 format is unsupported, the second load will be reading an
// empty database.
for (int i = 0; i < 2; ++i) {
SCOPED_TRACE(i);
......@@ -593,13 +586,10 @@ TEST_F(SQLiteChannelIDStoreTest, TestUpgradeV5) {
store_ = new SQLiteChannelIDStore(v5_db_path,
base::ThreadTaskRunnerHandle::Get());
// Load the database and ensure the certs can be read.
// Load the database. V5 private keys are in a format that is no longer
// supported, so the keys get deleted in the migration.
Load(&channel_ids);
ASSERT_EQ(1U, channel_ids.size());
ASSERT_EQ("google.com", channel_ids[0]->server_identifier());
ASSERT_EQ(GetTestCertCreationTime(), channel_ids[0]->creation_time());
EXPECT_TRUE(KeysEqual(key.get(), channel_ids[0]->key()));
ASSERT_EQ(0U, channel_ids.size());
store_ = NULL;
// Make sure we wait until the destructor has run.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment