Skip to content
This repository has been archived by the owner on May 21, 2024. It is now read-only.

Commit

Permalink
Only re-import the client cert if the device ID is the same.
Browse files Browse the repository at this point in the history
Expand the test to check the negative case (with a different device ID)
as well.

Signed-off-by: Patrick Vacek <patrickvacek@gmail.com>
  • Loading branch information
pattivacek committed Aug 21, 2020
1 parent 880103d commit 4f7dec9
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 15 deletions.
44 changes: 41 additions & 3 deletions src/libaktualizr/storage/invstorage.cc
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,46 @@ void INvStorage::importUpdateSimple(const boost::filesystem::path& base_path, st
}
}

void INvStorage::importUpdateCertificate(const boost::filesystem::path& base_path,
const utils::BasedPath& imported_data_path) {
std::string prev_content;
std::string content;
bool update = false;
if (!loadTlsCert(&prev_content)) {
update = true;
} else if (!imported_data_path.empty()) {
content = Utils::readFile(imported_data_path.get(base_path).string());
if (Crypto::sha256digest(content) != Crypto::sha256digest(prev_content)) {
update = true;
}
}

if (update && !imported_data_path.empty()) {
boost::filesystem::path abs_path = imported_data_path.get(base_path);
if (!boost::filesystem::exists(abs_path)) {
LOG_ERROR << "Couldn't import client certificate: " << abs_path << " doesn't exist.";
return;
}
if (content.empty()) {
content = Utils::readFile(abs_path.string());
}

// Make sure the device ID of the new cert hasn't changed.
const std::string new_device_id = Crypto::extractSubjectCN(content);
std::string old_device_id;
if (!loadDeviceId(&old_device_id)) {
LOG_DEBUG << "Unable to load previous device ID.";
} else if (new_device_id != old_device_id) {
throw std::runtime_error(std::string("Certificate at ") + abs_path.string() + " has a device ID of " +
new_device_id + " but the device currently is identified as " + old_device_id +
". Changing device ID is not supported!");
}

storeTlsCert(content);
LOG_DEBUG << "Successfully imported client certificate from " << abs_path;
}
}

void INvStorage::importPrimaryKeys(const boost::filesystem::path& base_path, const utils::BasedPath& import_pubkey_path,
const utils::BasedPath& import_privkey_path) {
if (loadPrimaryKeys(nullptr, nullptr) || import_pubkey_path.empty() || import_privkey_path.empty()) {
Expand Down Expand Up @@ -91,13 +131,11 @@ void INvStorage::importInstalledVersions(const boost::filesystem::path& base_pat
void INvStorage::importData(const ImportConfig& import_config) {
importPrimaryKeys(import_config.base_path, import_config.uptane_public_key_path,
import_config.uptane_private_key_path);
importUpdateCertificate(import_config.base_path, import_config.tls_clientcert_path);
importUpdateSimple(import_config.base_path, &INvStorage::storeTlsCa, &INvStorage::loadTlsCa,
import_config.tls_cacert_path, "server CA certificate");
importUpdateSimple(import_config.base_path, &INvStorage::storeTlsCert, &INvStorage::loadTlsCert,
import_config.tls_clientcert_path, "client certificate");
importUpdateSimple(import_config.base_path, &INvStorage::storeTlsPkey, &INvStorage::loadTlsPkey,
import_config.tls_pkey_path, "client TLS key");

importInstalledVersions(import_config.base_path);
}

Expand Down
1 change: 1 addition & 0 deletions src/libaktualizr/storage/invstorage.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ class INvStorage {
const utils::BasedPath& imported_data_path, const std::string& data_name);
void importUpdateSimple(const boost::filesystem::path& base_path, store_data_t store_func, load_data_t load_func,
const utils::BasedPath& imported_data_path, const std::string& data_name);
void importUpdateCertificate(const boost::filesystem::path& base_path, const utils::BasedPath& imported_data_path);
void importPrimaryKeys(const boost::filesystem::path& base_path, const utils::BasedPath& import_pubkey_path,
const utils::BasedPath& import_privkey_path);

Expand Down
73 changes: 61 additions & 12 deletions src/libaktualizr/storage/storage_common_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,8 @@ TEST(StorageCommon, LoadStoreSecondaryInfo) {
}

/* Import keys and credentials from file into storage.
* Re-import updated credentials from file into storage. */
* Re-import updated credentials from file into storage.
* Reject new certificate with a different device ID. */
TEST(StorageImport, ImportData) {
TemporaryDirectory temp_dir;
std::unique_ptr<INvStorage> storage = Storage(temp_dir.Path());
Expand All @@ -540,30 +541,38 @@ TEST(StorageImport, ImportData) {
import_config.tls_clientcert_path = utils::BasedPath("cert");
import_config.tls_pkey_path = utils::BasedPath("pkey");

std::string tls_cert_in1;
std::string tls_pkey_in1;
const std::string device_id1 = "test_id1";
StructGuard<X509> certificate1 = Crypto::generateCert(1024, 365, "", "", "", device_id1, true);
Crypto::serializeCert(&tls_pkey_in1, &tls_cert_in1, certificate1.get());

Utils::writeFile(import_config.uptane_private_key_path.get(import_config.base_path).string(),
std::string("uptane_private_1"));
Utils::writeFile(import_config.uptane_public_key_path.get(import_config.base_path).string(),
std::string("uptane_public_1"));
Utils::writeFile(import_config.tls_cacert_path.get(import_config.base_path).string(), std::string("tls_cacert_1"));
Utils::writeFile(import_config.tls_clientcert_path.get(import_config.base_path).string(), std::string("tls_cert_1"));
Utils::writeFile(import_config.tls_pkey_path.get(import_config.base_path).string(), std::string("tls_pkey_1"));
Utils::writeFile(import_config.tls_clientcert_path.get(import_config.base_path).string(), tls_cert_in1);
Utils::writeFile(import_config.tls_pkey_path.get(import_config.base_path).string(), tls_pkey_in1);

// Initially the storage is empty
// Initially the storage is empty.
EXPECT_FALSE(storage->loadPrimaryPublic(nullptr));
EXPECT_FALSE(storage->loadPrimaryPrivate(nullptr));
EXPECT_FALSE(storage->loadTlsCa(nullptr));
EXPECT_FALSE(storage->loadTlsCert(nullptr));
EXPECT_FALSE(storage->loadTlsPkey(nullptr));

storage->importData(import_config);
// Set the device ID to simulate initialization with the given certificate.
storage->storeDeviceId(device_id1);

std::string primary_public;
std::string primary_private;
std::string tls_ca;
std::string tls_cert;
std::string tls_pkey;

// the data has been imported
// Verify that the data has been imported.
EXPECT_TRUE(storage->loadPrimaryPublic(&primary_public));
EXPECT_TRUE(storage->loadPrimaryPrivate(&primary_private));
EXPECT_TRUE(storage->loadTlsCa(&tls_ca));
Expand All @@ -573,16 +582,56 @@ TEST(StorageImport, ImportData) {
EXPECT_EQ(primary_private, "uptane_private_1");
EXPECT_EQ(primary_public, "uptane_public_1");
EXPECT_EQ(tls_ca, "tls_cacert_1");
EXPECT_EQ(tls_cert, "tls_cert_1");
EXPECT_EQ(tls_pkey, "tls_pkey_1");
EXPECT_EQ(tls_cert, tls_cert_in1);
EXPECT_EQ(tls_pkey, tls_pkey_in1);

// Create second TLS cert/key (with a different device ID) and other dummy
// files.
std::string tls_cert_in2;
std::string tls_pkey_in2;
const std::string device_id2 = "test_id2";
StructGuard<X509> certificate2 = Crypto::generateCert(1024, 365, "", "", "", device_id2, true);
Crypto::serializeCert(&tls_pkey_in2, &tls_cert_in2, certificate2.get());
EXPECT_NE(tls_cert_in1, tls_cert_in2);
EXPECT_NE(tls_pkey_in1, tls_pkey_in2);

Utils::writeFile(import_config.uptane_private_key_path.get(import_config.base_path).string(),
std::string("uptane_private_2"));
Utils::writeFile(import_config.uptane_public_key_path.get(import_config.base_path).string(),
std::string("uptane_public_2"));
Utils::writeFile(import_config.tls_cacert_path.get(import_config.base_path).string(), std::string("tls_cacert_2"));
Utils::writeFile(import_config.tls_clientcert_path.get(import_config.base_path).string(), std::string("tls_cert_2"));
Utils::writeFile(import_config.tls_pkey_path.get(import_config.base_path).string(), std::string("tls_pkey_2"));
Utils::writeFile(import_config.tls_clientcert_path.get(import_config.base_path).string(), tls_cert_in2);
Utils::writeFile(import_config.tls_pkey_path.get(import_config.base_path).string(), tls_pkey_in2);

// Attempt to re-import, but expect failure because the TLS cert's device ID
// changed.
EXPECT_THROW(storage->importData(import_config), std::runtime_error);

EXPECT_TRUE(storage->loadPrimaryPublic(&primary_public));
EXPECT_TRUE(storage->loadPrimaryPrivate(&primary_private));
EXPECT_TRUE(storage->loadTlsCa(&tls_ca));
EXPECT_TRUE(storage->loadTlsCert(&tls_cert));
EXPECT_TRUE(storage->loadTlsPkey(&tls_pkey));

// Nothing should be updated. Uptane keys cannot be updated, and the TLS
// credentials should have failed.
EXPECT_EQ(primary_private, "uptane_private_1");
EXPECT_EQ(primary_public, "uptane_public_1");
EXPECT_EQ(tls_ca, "tls_cacert_1");
EXPECT_EQ(tls_cert, tls_cert_in1);
EXPECT_EQ(tls_pkey, tls_pkey_in1);

// Create third TLS cert/key (with the same device ID as the first) and other
// dummy files.
std::string tls_cert_in3;
std::string tls_pkey_in3;
StructGuard<X509> certificate3 = Crypto::generateCert(1024, 365, "", "", "", device_id1, true);
Crypto::serializeCert(&tls_pkey_in3, &tls_cert_in3, certificate3.get());
EXPECT_NE(tls_cert_in1, tls_cert_in3);
EXPECT_NE(tls_pkey_in1, tls_pkey_in3);

Utils::writeFile(import_config.tls_clientcert_path.get(import_config.base_path).string(), tls_cert_in3);
Utils::writeFile(import_config.tls_pkey_path.get(import_config.base_path).string(), tls_pkey_in3);

storage->importData(import_config);

Expand All @@ -592,12 +641,12 @@ TEST(StorageImport, ImportData) {
EXPECT_TRUE(storage->loadTlsCert(&tls_cert));
EXPECT_TRUE(storage->loadTlsPkey(&tls_pkey));

// All TLS objects should be updated:
// All TLS objects should be updated.
EXPECT_EQ(primary_private, "uptane_private_1");
EXPECT_EQ(primary_public, "uptane_public_1");
EXPECT_EQ(tls_ca, "tls_cacert_2");
EXPECT_EQ(tls_cert, "tls_cert_2");
EXPECT_EQ(tls_pkey, "tls_pkey_2");
EXPECT_EQ(tls_cert, tls_cert_in3);
EXPECT_EQ(tls_pkey, tls_pkey_in3);
}

#ifndef __NO_MAIN__
Expand Down

0 comments on commit 4f7dec9

Please sign in to comment.