| /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ |
| /* |
| * Copyright (c) 2013-2024 Regents of the University of California. |
| * |
| * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions). |
| * |
| * ndn-cxx library is free software: you can redistribute it and/or modify it under the |
| * terms of the GNU Lesser General Public License as published by the Free Software |
| * Foundation, either version 3 of the License, or (at your option) any later version. |
| * |
| * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY |
| * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A |
| * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. |
| * |
| * You should have received copies of the GNU General Public License and GNU Lesser |
| * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see |
| * <http://www.gnu.org/licenses/>. |
| * |
| * See AUTHORS.md for complete list of ndn-cxx authors and contributors. |
| */ |
| |
| #include "ndn-cxx/security/pib/impl/pib-memory.hpp" |
| #include "ndn-cxx/security/pib/impl/pib-sqlite3.hpp" |
| |
| #include "tests/boost-test.hpp" |
| #include "tests/unit/security/pib/pib-data-fixture.hpp" |
| |
| #include <filesystem> |
| |
| #include <boost/mp11/list.hpp> |
| |
| namespace ndn::tests { |
| |
| using namespace ndn::security::pib; |
| |
| BOOST_AUTO_TEST_SUITE(Security) |
| BOOST_AUTO_TEST_SUITE(TestPibImpl) |
| |
| class PibMemoryFixture : public PibDataFixture |
| { |
| public: |
| PibMemory pib; |
| }; |
| |
| class PibSqlite3Fixture : public PibDataFixture |
| { |
| public: |
| ~PibSqlite3Fixture() |
| { |
| std::filesystem::remove_all(m_path); |
| } |
| |
| private: |
| const std::filesystem::path m_path{std::filesystem::path(UNIT_TESTS_TMPDIR) / "TestPibImpl"}; |
| |
| public: |
| PibSqlite3 pib{m_path}; |
| }; |
| |
| using PibImpls = boost::mp11::mp_list<PibMemoryFixture, PibSqlite3Fixture>; |
| |
| BOOST_FIXTURE_TEST_CASE_TEMPLATE(TpmLocator, T, PibImpls, T) |
| { |
| // Basic getting and setting |
| BOOST_CHECK_EQUAL(this->pib.getTpmLocator(), ""); |
| this->pib.setTpmLocator("tpmLocator"); |
| BOOST_CHECK_EQUAL(this->pib.getTpmLocator(), "tpmLocator"); |
| |
| // Add cert, and do not change TPM locator |
| this->pib.addCertificate(this->id1Key1Cert1); |
| BOOST_CHECK(this->pib.hasIdentity(this->id1)); |
| BOOST_CHECK(this->pib.hasKey(this->id1Key1Name)); |
| BOOST_CHECK(this->pib.hasCertificate(this->id1Key1Cert1.getName())); |
| |
| // Set TPM locator to the same value, nothing should change |
| this->pib.setTpmLocator("tpmLocator"); |
| BOOST_CHECK(this->pib.hasIdentity(this->id1)); |
| BOOST_CHECK(this->pib.hasKey(this->id1Key1Name)); |
| BOOST_CHECK(this->pib.hasCertificate(this->id1Key1Cert1.getName())); |
| |
| // Change TPM locator (contents of PIB should not change) |
| this->pib.setTpmLocator("newTpmLocator"); |
| BOOST_CHECK(this->pib.hasIdentity(this->id1)); |
| BOOST_CHECK(this->pib.hasKey(this->id1Key1Name)); |
| BOOST_CHECK(this->pib.hasCertificate(this->id1Key1Cert1.getName())); |
| } |
| |
| BOOST_FIXTURE_TEST_CASE_TEMPLATE(IdentityManagement, T, PibImpls, T) |
| { |
| // no default setting, throw Error |
| BOOST_CHECK_THROW(this->pib.getDefaultIdentity(), Pib::Error); |
| |
| // check id1, which should not exist |
| BOOST_CHECK_EQUAL(this->pib.hasIdentity(this->id1), false); |
| |
| // add id1, should be default |
| this->pib.addIdentity(this->id1); |
| BOOST_CHECK_EQUAL(this->pib.hasIdentity(this->id1), true); |
| BOOST_CHECK_EQUAL(this->pib.getDefaultIdentity(), this->id1); |
| |
| // add id2, should not be default |
| this->pib.addIdentity(this->id2); |
| BOOST_CHECK_EQUAL(this->pib.hasIdentity(this->id2), true); |
| BOOST_CHECK_EQUAL(this->pib.getDefaultIdentity(), this->id1); |
| |
| // set id2 explicitly as default |
| this->pib.setDefaultIdentity(this->id2); |
| BOOST_CHECK_EQUAL(this->pib.getDefaultIdentity(), this->id2); |
| |
| // remove id2, should not have default identity |
| this->pib.removeIdentity(this->id2); |
| BOOST_CHECK_EQUAL(this->pib.hasIdentity(this->id2), false); |
| BOOST_CHECK_THROW(this->pib.getDefaultIdentity(), Pib::Error); |
| |
| // add id2 again, should be default |
| this->pib.addIdentity(this->id2); |
| BOOST_CHECK_EQUAL(this->pib.getDefaultIdentity(), this->id2); |
| |
| // try to set non-existing identity as a default |
| BOOST_CHECK_THROW(this->pib.setDefaultIdentity("/non-existing-identity"), Pib::Error); |
| |
| // get all identities, should contain id1 and id2 |
| std::set<Name> idNames = this->pib.getIdentities(); |
| BOOST_CHECK_EQUAL(idNames.size(), 2); |
| BOOST_CHECK_EQUAL(idNames.count(this->id1), 1); |
| BOOST_CHECK_EQUAL(idNames.count(this->id2), 1); |
| } |
| |
| BOOST_FIXTURE_TEST_CASE_TEMPLATE(ClearIdentities, T, PibImpls, T) |
| { |
| this->pib.setTpmLocator("tpmLocator"); |
| |
| // Add id, key, and cert |
| this->pib.addCertificate(this->id1Key1Cert1); |
| BOOST_CHECK(this->pib.hasIdentity(this->id1)); |
| BOOST_CHECK(this->pib.hasKey(this->id1Key1Name)); |
| BOOST_CHECK(this->pib.hasCertificate(this->id1Key1Cert1.getName())); |
| |
| // Clear identities |
| this->pib.clearIdentities(); |
| BOOST_CHECK_EQUAL(this->pib.getIdentities().size(), 0); |
| BOOST_CHECK_EQUAL(this->pib.getKeysOfIdentity(this->id1).size(), 0); |
| BOOST_CHECK_EQUAL(this->pib.getCertificatesOfKey(this->id1Key1Name).size(), 0); |
| BOOST_CHECK_EQUAL(this->pib.getTpmLocator(), "tpmLocator"); |
| } |
| |
| BOOST_FIXTURE_TEST_CASE_TEMPLATE(KeyManagement, T, PibImpls, T) |
| { |
| // no default setting, throw Error |
| BOOST_CHECK_THROW(this->pib.getDefaultKeyOfIdentity(this->id1), Pib::Error); |
| |
| // check id1Key1, should not exist, neither should id1. |
| BOOST_CHECK_EQUAL(this->pib.hasKey(this->id1Key1Name), false); |
| BOOST_CHECK_EQUAL(this->pib.hasIdentity(this->id1), false); |
| |
| // add id1Key1, should be default, id1 should be added implicitly |
| this->pib.addKey(this->id1, this->id1Key1Name, this->id1Key1); |
| BOOST_CHECK_EQUAL(this->pib.hasKey(this->id1Key1Name), true); |
| BOOST_CHECK_EQUAL(this->pib.hasIdentity(this->id1), true); |
| const Buffer& keyBits = this->pib.getKeyBits(this->id1Key1Name); |
| BOOST_TEST(keyBits == this->id1Key1, boost::test_tools::per_element()); |
| BOOST_CHECK_EQUAL(this->pib.getDefaultKeyOfIdentity(this->id1), this->id1Key1Name); |
| |
| // add id1Key2, should not be default |
| this->pib.addKey(this->id1, this->id1Key2Name, this->id1Key2); |
| BOOST_CHECK_EQUAL(this->pib.hasKey(this->id1Key2Name), true); |
| BOOST_CHECK_EQUAL(this->pib.getDefaultKeyOfIdentity(this->id1), this->id1Key1Name); |
| |
| // set id1Key2 explicitly as default |
| this->pib.setDefaultKeyOfIdentity(this->id1, this->id1Key2Name); |
| BOOST_CHECK_EQUAL(this->pib.getDefaultKeyOfIdentity(this->id1), this->id1Key2Name); |
| |
| // set a non-existing key as default, throw Error |
| BOOST_CHECK_THROW(this->pib.setDefaultKeyOfIdentity(this->id1, Name("/non-existing")), |
| Pib::Error); |
| |
| // remove id1Key2, should not have default key |
| this->pib.removeKey(this->id1Key2Name); |
| BOOST_CHECK_EQUAL(this->pib.hasKey(this->id1Key2Name), false); |
| BOOST_CHECK_THROW(this->pib.getKeyBits(this->id1Key2Name), Pib::Error); |
| BOOST_CHECK_THROW(this->pib.getDefaultKeyOfIdentity(this->id1), Pib::Error); |
| |
| // add id1Key2 back, should be default |
| this->pib.addKey(this->id1, this->id1Key2Name, this->id1Key2); |
| BOOST_CHECK_NO_THROW(this->pib.getKeyBits(this->id1Key2Name)); |
| BOOST_CHECK_EQUAL(this->pib.getDefaultKeyOfIdentity(this->id1), this->id1Key2Name); |
| |
| // get all the keys: id1Key1 and id1Key2 |
| std::set<Name> keyNames = this->pib.getKeysOfIdentity(this->id1); |
| BOOST_CHECK_EQUAL(keyNames.size(), 2); |
| BOOST_CHECK_EQUAL(keyNames.count(this->id1Key1Name), 1); |
| BOOST_CHECK_EQUAL(keyNames.count(this->id1Key2Name), 1); |
| |
| // remove id1, should remove all the keys |
| this->pib.removeIdentity(this->id1); |
| keyNames = this->pib.getKeysOfIdentity(this->id1); |
| BOOST_CHECK_EQUAL(keyNames.size(), 0); |
| } |
| |
| BOOST_FIXTURE_TEST_CASE_TEMPLATE(CertificateManagement, T, PibImpls, T) |
| { |
| // no default setting, throw Error |
| BOOST_CHECK_THROW(this->pib.getDefaultCertificateOfKey(this->id1Key1Name), Pib::Error); |
| |
| // check id1Key1Cert1, should not exist, neither should id1 and id1Key1 |
| BOOST_CHECK_EQUAL(this->pib.hasCertificate(this->id1Key1Cert1.getName()), false); |
| BOOST_CHECK_EQUAL(this->pib.hasIdentity(this->id1), false); |
| BOOST_CHECK_EQUAL(this->pib.hasKey(this->id1Key1Name), false); |
| |
| // add id1Key1Cert1, should be default, id1 and id1Key1 should be added implicitly |
| this->pib.addCertificate(this->id1Key1Cert1); |
| BOOST_CHECK_EQUAL(this->pib.hasCertificate(this->id1Key1Cert1.getName()), true); |
| BOOST_CHECK_EQUAL(this->pib.hasIdentity(this->id1), true); |
| BOOST_CHECK_EQUAL(this->pib.hasKey(this->id1Key1Name), true); |
| BOOST_CHECK_EQUAL(this->pib.getCertificate(this->id1Key1Cert1.getName()).wireEncode(), |
| this->id1Key1Cert1.wireEncode()); |
| BOOST_CHECK_EQUAL(this->pib.getDefaultCertificateOfKey(this->id1Key1Name), this->id1Key1Cert1); |
| |
| // add id1Key1Cert2, should not be default |
| this->pib.addCertificate(this->id1Key1Cert2); |
| BOOST_CHECK_EQUAL(this->pib.hasCertificate(this->id1Key1Cert2.getName()), true); |
| BOOST_CHECK_EQUAL(this->pib.getDefaultCertificateOfKey(this->id1Key1Name), this->id1Key1Cert1); |
| |
| // set id1Key1Cert2 explicitly as default |
| this->pib.setDefaultCertificateOfKey(this->id1Key1Name, this->id1Key1Cert2.getName()); |
| BOOST_CHECK_EQUAL(this->pib.getDefaultCertificateOfKey(this->id1Key1Name), this->id1Key1Cert2); |
| |
| // set a non-existing cert as default, throw Error |
| BOOST_CHECK_THROW(this->pib.setDefaultCertificateOfKey(this->id1Key1Name, Name("/non-existing")), |
| Pib::Error); |
| |
| // remove id1Key1Cert2, should not have default cert |
| this->pib.removeCertificate(this->id1Key1Cert2.getName()); |
| BOOST_CHECK_EQUAL(this->pib.hasCertificate(this->id1Key1Cert2.getName()), false); |
| BOOST_CHECK_THROW(this->pib.getCertificate(this->id1Key1Cert2.getName()), Pib::Error); |
| BOOST_CHECK_THROW(this->pib.getDefaultCertificateOfKey(this->id1Key1Name), Pib::Error); |
| |
| // add id1Key1Cert2, should be default |
| this->pib.addCertificate(this->id1Key1Cert2); |
| BOOST_CHECK_NO_THROW(this->pib.getCertificate(this->id1Key1Cert1.getName())); |
| BOOST_CHECK_EQUAL(this->pib.getDefaultCertificateOfKey(this->id1Key1Name), this->id1Key1Cert2); |
| |
| // get all certificates: id1Key1Cert1 and id1Key1Cert2 |
| std::set<Name> certNames = this->pib.getCertificatesOfKey(this->id1Key1Name); |
| BOOST_CHECK_EQUAL(certNames.size(), 2); |
| BOOST_CHECK_EQUAL(certNames.count(this->id1Key1Cert1.getName()), 1); |
| BOOST_CHECK_EQUAL(certNames.count(this->id1Key1Cert2.getName()), 1); |
| |
| // remove id1Key1, should remove all the certs |
| this->pib.removeKey(this->id1Key1Name); |
| certNames = this->pib.getCertificatesOfKey(this->id1Key1Name); |
| BOOST_CHECK_EQUAL(certNames.size(), 0); |
| } |
| |
| BOOST_FIXTURE_TEST_CASE_TEMPLATE(DefaultsManagement, T, PibImpls, T) |
| { |
| this->pib.addIdentity(this->id1); |
| BOOST_CHECK_EQUAL(this->pib.getDefaultIdentity(), this->id1); |
| |
| this->pib.addIdentity(this->id2); |
| BOOST_CHECK_EQUAL(this->pib.getDefaultIdentity(), this->id1); |
| |
| this->pib.removeIdentity(this->id1); |
| BOOST_CHECK_THROW(this->pib.getDefaultIdentity(), Pib::Error); |
| |
| this->pib.addKey(this->id2, this->id2Key1Name, this->id2Key1); |
| BOOST_CHECK_EQUAL(this->pib.getDefaultIdentity(), this->id2); |
| BOOST_CHECK_EQUAL(this->pib.getDefaultKeyOfIdentity(this->id2), this->id2Key1Name); |
| |
| this->pib.addKey(this->id2, this->id2Key2Name, this->id2Key2); |
| BOOST_CHECK_EQUAL(this->pib.getDefaultKeyOfIdentity(this->id2), this->id2Key1Name); |
| |
| this->pib.removeKey(this->id2Key1Name); |
| BOOST_CHECK_THROW(this->pib.getDefaultKeyOfIdentity(this->id2), Pib::Error); |
| |
| this->pib.addCertificate(this->id2Key2Cert1); |
| BOOST_CHECK_EQUAL(this->pib.getDefaultKeyOfIdentity(this->id2), this->id2Key2Name); |
| BOOST_CHECK_EQUAL(this->pib.getDefaultCertificateOfKey(this->id2Key2Name).getName(), |
| this->id2Key2Cert1.getName()); |
| |
| this->pib.addCertificate(this->id2Key2Cert2); |
| BOOST_CHECK_EQUAL(this->pib.getDefaultCertificateOfKey(this->id2Key2Name).getName(), |
| this->id2Key2Cert1.getName()); |
| |
| this->pib.removeCertificate(this->id2Key2Cert2.getName()); |
| BOOST_CHECK_EQUAL(this->pib.getDefaultCertificateOfKey(this->id2Key2Name).getName(), |
| this->id2Key2Cert1.getName()); |
| } |
| |
| BOOST_FIXTURE_TEST_CASE_TEMPLATE(Overwrite, T, PibImpls, T) |
| { |
| // check id1Key1, should not exist |
| this->pib.removeIdentity(this->id1); |
| BOOST_CHECK_EQUAL(this->pib.hasKey(this->id1Key1Name), false); |
| |
| // add id1Key1 |
| this->pib.addKey(this->id1, this->id1Key1Name, this->id1Key1); |
| BOOST_CHECK_EQUAL(this->pib.hasKey(this->id1Key1Name), true); |
| const Buffer& keyBits = this->pib.getKeyBits(this->id1Key1Name); |
| BOOST_CHECK(keyBits == this->id1Key1); |
| |
| // check overwrite, add a key with the same name. |
| this->pib.addKey(this->id1, this->id1Key1Name, this->id1Key2); |
| const Buffer& keyBits2 = this->pib.getKeyBits(this->id1Key1Name); |
| BOOST_CHECK(keyBits2 == this->id1Key2); |
| |
| // check id1Key1Cert1, should not exist |
| this->pib.removeIdentity(this->id1); |
| BOOST_CHECK_EQUAL(this->pib.hasCertificate(this->id1Key1Cert1.getName()), false); |
| |
| // add id1Key1Cert1 |
| this->pib.addKey(this->id1, this->id1Key1Name, this->id1Key1); |
| this->pib.addCertificate(this->id1Key1Cert1); |
| BOOST_CHECK_EQUAL(this->pib.hasCertificate(this->id1Key1Cert1.getName()), true); |
| |
| auto cert = this->pib.getCertificate(this->id1Key1Cert1.getName()); |
| BOOST_CHECK_EQUAL(cert.wireEncode(), this->id1Key1Cert1.wireEncode()); |
| |
| // Create a fake cert with the same name |
| auto cert2 = this->id1Key2Cert1; |
| cert2.setName(this->id1Key1Cert1.getName()); |
| BOOST_CHECK_EQUAL(cert2.getSignatureInfo(), this->id1Key2Cert1.getSignatureInfo()); |
| BOOST_CHECK_EQUAL(cert2.getSignatureValue(), this->id1Key2Cert1.getSignatureValue()); |
| this->pib.addCertificate(cert2); |
| |
| auto cert3 = this->pib.getCertificate(this->id1Key1Cert1.getName()); |
| BOOST_CHECK_EQUAL(cert3.wireEncode(), cert2.wireEncode()); |
| |
| // both key and certificate are overwritten |
| Buffer keyBits3 = this->pib.getKeyBits(this->id1Key1Name); |
| BOOST_CHECK(keyBits3 == this->id1Key2); |
| } |
| |
| BOOST_AUTO_TEST_SUITE_END() // TestPibImpl |
| BOOST_AUTO_TEST_SUITE_END() // Security |
| |
| } // namespace ndn::tests |