security: introduce KeyChain::makeCertificate
KeyChain::makeCertificate() captures a common routine of creating and
signing a certificate. Having it in the library allows deduplicating
similar code elsewhere.
Also add "find by certificate name" tests for CertificateCache and
TrustAnchorContainer.
refs #5112
Change-Id: I954587e1c03d6b372e3b4f04e702339d1ff1533e
diff --git a/tests/unit/security/key-chain.t.cpp b/tests/unit/security/key-chain.t.cpp
index 94e75a0..b7aef11 100644
--- a/tests/unit/security/key-chain.t.cpp
+++ b/tests/unit/security/key-chain.t.cpp
@@ -26,6 +26,7 @@
#include "tests/boost-test.hpp"
#include "tests/key-chain-fixture.hpp"
+#include "tests/unit/clock-fixture.hpp"
#include "tests/unit/test-home-env-saver.hpp"
#include <boost/mpl/vector.hpp>
@@ -573,6 +574,146 @@
}
}
+class MakeCertificateFixture : public ClockFixture
+{
+public:
+ MakeCertificateFixture()
+ : requesterKeyChain("pib-memory:", "tpm-memory:")
+ , signerKeyChain("pib-memory:", "tpm-memory:")
+ {
+ m_systemClock->setNow(time::fromIsoString("20091117T203458,651387237").time_since_epoch());
+
+ requester = requesterKeyChain.createIdentity("/requester").getDefaultKey();
+ Name signerIdentityName("/signer");
+ signerKey = signerKeyChain.createIdentity(signerIdentityName).getDefaultKey();
+ signerParams = signingByIdentity(signerIdentityName);
+ }
+
+ void
+ checkKeyLocatorName(const Certificate& cert, optional<Name> klName = nullopt) const
+ {
+ auto kl = cert.getKeyLocator();
+ if (!kl.has_value()) {
+ BOOST_ERROR("KeyLocator is missing");
+ return;
+ }
+ BOOST_CHECK_EQUAL(kl->getName(),
+ klName.value_or(signerKey.getDefaultCertificate().getName()));
+ }
+
+ void
+ checkCertFromDefaults(const Certificate& cert) const
+ {
+ BOOST_CHECK(Certificate::isValidName(cert.getName()));
+ BOOST_CHECK_EQUAL(cert.getKeyName(), requester.getName());
+ BOOST_CHECK_EQUAL(cert.getName()[-2], name::Component("NA"));
+ BOOST_CHECK(cert.getName()[-1].isVersion());
+
+ BOOST_CHECK_EQUAL(cert.getContentType(), tlv::ContentType_Key);
+ BOOST_CHECK_EQUAL(cert.getFreshnessPeriod(), 1_h);
+
+ BOOST_TEST(cert.getContent().value_bytes() == requester.getPublicKey(),
+ boost::test_tools::per_element());
+
+ checkKeyLocatorName(cert);
+
+ BOOST_CHECK(cert.isValid());
+ auto vp = cert.getValidityPeriod().getPeriod();
+ BOOST_CHECK_EQUAL(vp.first, time::fromIsoString("20091117T203458"));
+ BOOST_CHECK_EQUAL(vp.second, time::fromIsoString("20101117T203458"));
+
+ auto adBlock = cert.getSignatureInfo().getCustomTlv(tlv::AdditionalDescription);
+ BOOST_CHECK(!adBlock.has_value());
+ }
+
+public:
+ KeyChain requesterKeyChain;
+ pib::Key requester;
+
+ KeyChain signerKeyChain;
+ pib::Key signerKey;
+ Name signerCertificateName;
+ SigningInfo signerParams;
+};
+
+BOOST_FIXTURE_TEST_SUITE(MakeCertificate, MakeCertificateFixture)
+
+BOOST_AUTO_TEST_CASE(DefaultsFromKey)
+{
+ auto cert = signerKeyChain.makeCertificate(requester, signerParams);
+ checkCertFromDefaults(cert);
+}
+
+BOOST_AUTO_TEST_CASE(DefaultsFromCert)
+{
+ auto cert = signerKeyChain.makeCertificate(requester.getDefaultCertificate(), signerParams);
+ checkCertFromDefaults(cert);
+}
+
+BOOST_AUTO_TEST_CASE(Options)
+{
+ MakeCertificateOptions opts;
+ opts.issuerId = name::Component::fromEscapedString("ISSUER");
+ opts.version = 41218268;
+ opts.freshnessPeriod = 321_s;
+ opts.validity.emplace(time::fromIsoString("20060702T150405"),
+ time::fromIsoString("20160702T150405"));
+
+ SignatureInfo sigInfo;
+ sigInfo.setKeyLocator(signerKey.getName());
+ sigInfo.setValidityPeriod(ValidityPeriod(time::fromIsoString("20060102T150405"),
+ time::fromIsoString("20160102T150405")));
+ sigInfo.addCustomTlv(Block(0xF0));
+ signerParams.setSignatureInfo(sigInfo);
+
+ auto cert = signerKeyChain.makeCertificate(requester, signerParams, opts);
+
+ BOOST_CHECK_EQUAL(cert.getName(),
+ Name(requester.getName()).append(PartialName("ISSUER/v=41218268")));
+ BOOST_CHECK_EQUAL(cert.getFreshnessPeriod(), 321_s);
+ checkKeyLocatorName(cert, signerKey.getName());
+
+ auto vp = cert.getValidityPeriod().getPeriod();
+ BOOST_CHECK_EQUAL(vp.first, time::fromIsoString("20060702T150405"));
+ BOOST_CHECK_EQUAL(vp.second, time::fromIsoString("20160702T150405"));
+
+ BOOST_CHECK(cert.getSignatureInfo().getCustomTlv(0xF0).has_value());
+}
+
+BOOST_AUTO_TEST_CASE(ErrSigner)
+{
+ signerParams = signingByIdentity("/nonexistent");
+ BOOST_CHECK_THROW(signerKeyChain.makeCertificate(requester, signerParams), KeyChain::Error);
+}
+
+BOOST_AUTO_TEST_CASE(ErrZeroFreshness)
+{
+ MakeCertificateOptions opts;
+ opts.freshnessPeriod = 0_ms;
+ BOOST_CHECK_THROW(signerKeyChain.makeCertificate(requester, signerParams, opts),
+ std::invalid_argument);
+}
+
+BOOST_AUTO_TEST_CASE(ErrNegativeFreshness)
+{
+ MakeCertificateOptions opts;
+ opts.freshnessPeriod = -1_ms;
+ BOOST_CHECK_THROW(signerKeyChain.makeCertificate(requester, signerParams, opts),
+ std::invalid_argument);
+}
+
+BOOST_AUTO_TEST_CASE(ErrContent)
+{
+ Certificate request(requester.getDefaultCertificate());
+ const auto& oldContent = request.getContent();
+ std::vector<uint8_t> content(oldContent.value_begin(), oldContent.value_end());
+ content[0] ^= 0x80;
+ request.setContent(content);
+ BOOST_CHECK_THROW(signerKeyChain.makeCertificate(request, signerParams), std::invalid_argument);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // MakeCertificate
+
BOOST_FIXTURE_TEST_CASE(ImportPrivateKey, KeyChainFixture)
{
const Name keyName("/test/device2");