tests: rewrite and improve KeyChain signing test case
Added testing of:
* non-default identity
* non-default key
* different types of asymmetric keys
* SigningInfo(const std::string&) overload
Change-Id: Id16c77250cc25203f4fa49ecdbb9ee7ded218052
diff --git a/tests/unit/security/key-chain.t.cpp b/tests/unit/security/key-chain.t.cpp
index a9e1eaf..d3fb67e 100644
--- a/tests/unit/security/key-chain.t.cpp
+++ b/tests/unit/security/key-chain.t.cpp
@@ -27,6 +27,8 @@
#include "tests/key-chain-fixture.hpp"
#include "tests/unit/test-home-env-saver.hpp"
+#include <boost/mpl/vector.hpp>
+
namespace ndn {
namespace security {
inline namespace v2 {
@@ -136,7 +138,7 @@
const std::string PATH = "build/config-file-empty2-home/";
};
-BOOST_FIXTURE_TEST_CASE(ConstructorEmpty2Config, TestHomeAndPibFixture<PibPathConfigFileEmpty2Home>)
+BOOST_FIXTURE_TEST_CASE(ConstructorEmptyConfig2, TestHomeAndPibFixture<PibPathConfigFileEmpty2Home>)
{
createClientConf({"tpm=tpm-memory:"});
@@ -153,11 +155,10 @@
const std::string PATH = "build/config-file-malformed-home/";
};
-BOOST_FIXTURE_TEST_CASE(ConstructorMalConfig, TestHomeAndPibFixture<PibPathConfigFileMalformedHome>)
+BOOST_FIXTURE_TEST_CASE(ConstructorBadConfig, TestHomeAndPibFixture<PibPathConfigFileMalformedHome>)
{
createClientConf({"pib=lord", "tpm=ring"});
-
- BOOST_REQUIRE_THROW(KeyChain(), KeyChain::Error); // Wrong configuration. Error expected.
+ BOOST_CHECK_THROW(KeyChain(), KeyChain::Error); // Wrong configuration. Error expected.
}
struct PibPathConfigFileMalformed2Home
@@ -165,11 +166,10 @@
const std::string PATH = "build/config-file-malformed2-home/";
};
-BOOST_FIXTURE_TEST_CASE(ConstructorMal2Config, TestHomeAndPibFixture<PibPathConfigFileMalformed2Home>)
+BOOST_FIXTURE_TEST_CASE(ConstructorBadConfig2, TestHomeAndPibFixture<PibPathConfigFileMalformed2Home>)
{
createClientConf({"pib=pib-sqlite3:%PATH%", "tpm=just-wrong"});
-
- BOOST_REQUIRE_THROW(KeyChain(), KeyChain::Error); // Wrong configuration. Error expected.
+ BOOST_CHECK_THROW(KeyChain(), KeyChain::Error); // Wrong configuration. Error expected.
}
struct PibPathConfigFileNonCanonicalTpm
@@ -222,6 +222,13 @@
BOOST_CHECK_THROW(m_keyChain.sign(data, signingByIdentity(id)), KeyChain::InvalidSigningInfoError);
}
+BOOST_FIXTURE_TEST_CASE(SigningWithNonExistingIdentity, KeyChainFixture)
+{
+ Data data("/test/data");
+ BOOST_CHECK_THROW(m_keyChain.sign(data, signingByIdentity("/non-existing/identity")),
+ KeyChain::InvalidSigningInfoError);
+}
+
BOOST_FIXTURE_TEST_CASE(Management, KeyChainFixture)
{
Name identityName("/test/id");
@@ -315,172 +322,252 @@
m_keyChain.deleteIdentity(id);
// The identity instance should not be valid any more
BOOST_CHECK(!id);
- BOOST_REQUIRE_THROW(m_keyChain.getPib().getIdentity(identityName), Pib::Error);
+ BOOST_CHECK_THROW(m_keyChain.getPib().getIdentity(identityName), Pib::Error);
BOOST_CHECK(m_keyChain.getPib().getIdentities().find(identityName) == m_keyChain.getPib().getIdentities().end());
}
-BOOST_FIXTURE_TEST_CASE(GeneralSigningInterface, KeyChainFixture)
+struct DataPkt
{
- Identity id = m_keyChain.createIdentity("/id");
- Key key = id.getDefaultKey();
- Certificate cert = key.getDefaultCertificate();
+ Data packet{"/data"};
+ SignedInterestFormat sigFormat = SignedInterestFormat::V02; // irrelevant for Data
- Name hmacKeyName = m_keyChain.createHmacKey();
- const Tpm& tpm = m_keyChain.getTpm();
+ SignatureInfo
+ getSignatureInfo() const
+ {
+ return packet.getSignatureInfo();
+ }
+};
- std::vector<SigningInfo> signingInfos = {
- // New signed Interest format
- SigningInfo().setSignedInterestFormat(SignedInterestFormat::V03),
+struct InterestV02Pkt
+{
+ Interest packet = Interest{"/interest02"}.setCanBePrefix(false);
+ SignedInterestFormat sigFormat = SignedInterestFormat::V02;
- SigningInfo(SigningInfo::SIGNER_TYPE_ID, id.getName())
- .setSignedInterestFormat(SignedInterestFormat::V03),
- signingByIdentity(id.getName()).setSignedInterestFormat(SignedInterestFormat::V03),
+ SignatureInfo
+ getSignatureInfo() const
+ {
+ return SignatureInfo(packet.getName()[signed_interest::POS_SIG_INFO].blockFromValue());
+ }
+};
- SigningInfo(id).setSignedInterestFormat(SignedInterestFormat::V03),
- signingByIdentity(id).setSignedInterestFormat(SignedInterestFormat::V03),
+struct InterestV03Pkt
+{
+ Interest packet = Interest{"/interest03"}.setCanBePrefix(false);
+ SignedInterestFormat sigFormat = SignedInterestFormat::V03;
- SigningInfo(SigningInfo::SIGNER_TYPE_KEY, key.getName())
- .setSignedInterestFormat(SignedInterestFormat::V03),
- signingByKey(key.getName()).setSignedInterestFormat(SignedInterestFormat::V03),
+ SignatureInfo
+ getSignatureInfo() const
+ {
+ return packet.getSignatureInfo().value(); // use .value() for checked access
+ }
+};
- SigningInfo(key).setSignedInterestFormat(SignedInterestFormat::V03),
- signingByKey(key).setSignedInterestFormat(SignedInterestFormat::V03),
+template<typename KeyParams>
+struct DefaultIdentity
+{
+ Identity
+ operator()(KeyChain& keyChain) const
+ {
+ auto id = keyChain.createIdentity("/id", KeyParams());
+ BOOST_ASSERT(keyChain.getPib().getDefaultIdentity() == id);
+ return id;
+ }
+};
- SigningInfo(SigningInfo::SIGNER_TYPE_CERT, cert.getName())
- .setSignedInterestFormat(SignedInterestFormat::V03),
- signingByCertificate(cert.getName()).setSignedInterestFormat(SignedInterestFormat::V03),
- signingByCertificate(cert).setSignedInterestFormat(SignedInterestFormat::V03),
+template<typename KeyParams>
+struct NonDefaultIdentity
+{
+ Identity
+ operator()(KeyChain& keyChain) const
+ {
+ auto id = keyChain.createIdentity("/id");
+ auto id2 = keyChain.createIdentity("/id2", KeyParams());
+ BOOST_ASSERT(keyChain.getPib().getDefaultIdentity() == id);
+ return id2;
+ }
+};
- SigningInfo(SigningInfo::SIGNER_TYPE_HMAC, hmacKeyName)
- .setSignedInterestFormat(SignedInterestFormat::V03),
- SigningInfo("hmac-sha256:QjM3NEEyNkE3MTQ5MDQzN0FBMDI0RTRGQURENUI0OTdGREZGMUE4RUE2RkYxMkY2RkI2NUFGMjcyMEI1OUNDRg==")
- .setSignedInterestFormat(SignedInterestFormat::V03),
+template<typename KeyParams>
+struct DefaultKey
+{
+ Key
+ operator()(KeyChain&, const Identity& id) const
+ {
+ auto key = id.getDefaultKey();
+ BOOST_ASSERT(key.getKeyType() == KeyParams().getKeyType());
+ return key;
+ }
+};
- SigningInfo(SigningInfo::SIGNER_TYPE_SHA256)
- .setSignedInterestFormat(SignedInterestFormat::V03),
- signingWithSha256().setSignedInterestFormat(SignedInterestFormat::V03),
+template<typename KeyParams>
+struct NonDefaultKey
+{
+ Key
+ operator()(KeyChain& keyChain, const Identity& id) const
+ {
+ auto key2 = keyChain.createKey(id, KeyParams());
+ BOOST_ASSERT(id.getDefaultKey() != key2);
+ return key2;
+ }
+};
- // Deprecated signed Interest format
+template<typename PacketType,
+ template<typename> class IdentityMaker = DefaultIdentity,
+ template<typename> class KeyMaker = DefaultKey,
+ typename AsymmetricKeyParams = EcKeyParams,
+ uint32_t SignatureTypeTlvValue = tlv::SignatureSha256WithEcdsa>
+struct AsymmetricSigningBase : protected KeyChainFixture, protected PacketType
+{
+ const Identity id = IdentityMaker<AsymmetricKeyParams>()(m_keyChain);
+ const Key key = KeyMaker<AsymmetricKeyParams>()(m_keyChain, id);
+ const Certificate cert = key.getDefaultCertificate();
+
+ const uint32_t expectedSigType = SignatureTypeTlvValue;
+ const bool shouldHaveKeyLocator = true;
+ const optional<KeyLocator> expectedKeyLocator = cert.getName().getPrefix(-2);
+
+ bool
+ verify(const SigningInfo&) const
+ {
+ return verifySignature(this->packet, key);
+ }
+};
+
+template<typename PacketType,
+ typename AsymmetricKeyParams,
+ uint32_t SignatureTypeTlvValue>
+struct AsymmetricSigning : protected AsymmetricSigningBase<PacketType, DefaultIdentity, DefaultKey,
+ AsymmetricKeyParams, SignatureTypeTlvValue>
+{
+ const std::vector<SigningInfo> signingInfos = {
SigningInfo(),
+ SigningInfo(""),
- SigningInfo(SigningInfo::SIGNER_TYPE_ID, id.getName()),
- signingByIdentity(id.getName()),
+ SigningInfo(this->id),
+ SigningInfo(SigningInfo::SIGNER_TYPE_ID, this->id.getName()),
+ SigningInfo("id:" + this->id.getName().toUri()),
+ signingByIdentity(this->id),
+ signingByIdentity(this->id.getName()),
- SigningInfo(id),
- signingByIdentity(id),
+ SigningInfo(this->key),
+ SigningInfo(SigningInfo::SIGNER_TYPE_KEY, this->key.getName()),
+ SigningInfo("key:" + this->key.getName().toUri()),
+ signingByKey(this->key),
+ signingByKey(this->key.getName()),
- SigningInfo(SigningInfo::SIGNER_TYPE_KEY, key.getName()),
- signingByKey(key.getName()),
+ SigningInfo(SigningInfo::SIGNER_TYPE_CERT, this->cert.getName()),
+ SigningInfo("cert:" + this->cert.getName().toUri()),
+ signingByCertificate(this->cert),
+ signingByCertificate(this->cert.getName()),
+ };
+};
- SigningInfo(key),
- signingByKey(key),
+template<typename PacketType>
+using RsaSigning = AsymmetricSigning<PacketType, RsaKeyParams, tlv::SignatureSha256WithRsa>;
- SigningInfo(SigningInfo::SIGNER_TYPE_CERT, cert.getName()),
- signingByCertificate(cert.getName()),
- signingByCertificate(cert),
+template<typename PacketType>
+using EcdsaSigning = AsymmetricSigning<PacketType, EcKeyParams, tlv::SignatureSha256WithEcdsa>;
- SigningInfo(SigningInfo::SIGNER_TYPE_HMAC, hmacKeyName),
+template<typename PacketType>
+struct SigningWithNonDefaultIdentity : protected AsymmetricSigningBase<PacketType, NonDefaultIdentity>
+{
+ const std::vector<SigningInfo> signingInfos = {
+ signingByIdentity(this->id),
+ signingByIdentity(this->id.getName()),
+ signingByKey(this->key),
+ signingByCertificate(this->cert),
+ };
+};
+
+template<typename PacketType>
+struct SigningWithNonDefaultKey : protected AsymmetricSigningBase<PacketType, NonDefaultIdentity, NonDefaultKey>
+{
+ const std::vector<SigningInfo> signingInfos = {
+ signingByKey(this->key),
+ signingByKey(this->key.getName()),
+ signingByCertificate(this->cert),
+ };
+};
+
+template<typename PacketType,
+ DigestAlgorithm DigestAlgo = DigestAlgorithm::SHA256,
+ uint32_t SignatureTypeTlvValue = tlv::SignatureHmacWithSha256>
+struct HmacSigning : protected KeyChainFixture, protected PacketType
+{
+ const std::vector<SigningInfo> signingInfos = {
+ SigningInfo(SigningInfo::SIGNER_TYPE_HMAC, m_keyChain.createHmacKey()),
SigningInfo("hmac-sha256:QjM3NEEyNkE3MTQ5MDQzN0FBMDI0RTRGQURENUI0OTdGREZGMUE4RUE2RkYxMkY2RkI2NUFGMjcyMEI1OUNDRg=="),
+ };
+ const uint32_t expectedSigType = SignatureTypeTlvValue;
+ const bool shouldHaveKeyLocator = true;
+ const optional<KeyLocator> expectedKeyLocator = nullopt; // don't check KeyLocator value
+
+ bool
+ verify(const SigningInfo& si) const
+ {
+ return verifySignature(this->packet, m_keyChain.getTpm(), si.getSignerName(), DigestAlgo);
+ }
+};
+
+template<typename PacketType>
+struct Sha256Signing : protected KeyChainFixture, protected PacketType
+{
+ const std::vector<SigningInfo> signingInfos = {
SigningInfo(SigningInfo::SIGNER_TYPE_SHA256),
+ SigningInfo("id:" + SigningInfo::getDigestSha256Identity().toUri()),
signingWithSha256()
};
- for (const auto& signingInfo : signingInfos) {
- BOOST_TEST_MESSAGE("SigningInfo: " << signingInfo);
- Data data("/data");
- Interest interest("/interest");
- interest.setCanBePrefix(false);
+ const uint32_t expectedSigType = tlv::DigestSha256;
+ const bool shouldHaveKeyLocator = false;
+ const optional<KeyLocator> expectedKeyLocator = nullopt;
- m_keyChain.sign(data, signingInfo);
- m_keyChain.sign(interest, signingInfo);
+ bool
+ verify(const SigningInfo&) const
+ {
+ return verifyDigest(this->packet, DigestAlgorithm::SHA256);
+ }
+};
- if (signingInfo.getSignerType() == SigningInfo::SIGNER_TYPE_SHA256) {
- BOOST_CHECK_EQUAL(data.getSignatureType(), tlv::DigestSha256);
+using SigningTests = boost::mpl::vector<
+ RsaSigning<DataPkt>,
+ RsaSigning<InterestV02Pkt>,
+ RsaSigning<InterestV03Pkt>,
+ EcdsaSigning<DataPkt>,
+ EcdsaSigning<InterestV02Pkt>,
+ EcdsaSigning<InterestV03Pkt>,
+ HmacSigning<DataPkt>,
+ HmacSigning<InterestV02Pkt>,
+ HmacSigning<InterestV03Pkt>,
+ Sha256Signing<DataPkt>,
+ Sha256Signing<InterestV02Pkt>,
+ Sha256Signing<InterestV03Pkt>,
+ SigningWithNonDefaultIdentity<DataPkt>,
+ SigningWithNonDefaultKey<DataPkt>
+>;
- if (signingInfo.getSignedInterestFormat() == SignedInterestFormat::V03) {
- BOOST_REQUIRE(interest.getSignatureInfo() != nullopt);
- BOOST_CHECK_EQUAL(interest.getSignatureInfo()->getSignatureType(), tlv::DigestSha256);
+BOOST_FIXTURE_TEST_CASE_TEMPLATE(SigningInterface, T, SigningTests, T)
+{
+ BOOST_TEST_CONTEXT("Packet = " << this->packet.getName()) {
+ for (auto signingInfo : this->signingInfos) {
+ signingInfo.setSignedInterestFormat(this->sigFormat);
+
+ BOOST_TEST_CONTEXT("SigningInfo = " << signingInfo) {
+ this->m_keyChain.sign(this->packet, signingInfo);
+
+ auto sigInfo = this->getSignatureInfo();
+ BOOST_CHECK_EQUAL(sigInfo.getSignatureType(), this->expectedSigType);
+ BOOST_CHECK_EQUAL(sigInfo.hasKeyLocator(), this->shouldHaveKeyLocator);
+ if (this->expectedKeyLocator) {
+ BOOST_CHECK_EQUAL(sigInfo.getKeyLocator(), *this->expectedKeyLocator);
+ }
+ BOOST_CHECK(this->verify(signingInfo));
}
- else {
- SignatureInfo sigInfo(interest.getName()[signed_interest::POS_SIG_INFO].blockFromValue());
- BOOST_CHECK_EQUAL(sigInfo.getSignatureType(), tlv::DigestSha256);
- }
-
- BOOST_CHECK(verifyDigest(data, DigestAlgorithm::SHA256));
- BOOST_CHECK(verifyDigest(interest, DigestAlgorithm::SHA256));
- }
- else if (signingInfo.getSignerType() == SigningInfo::SIGNER_TYPE_HMAC) {
- Name keyName = signingInfo.getSignerName();
- BOOST_CHECK_EQUAL(data.getSignatureType(), tlv::SignatureHmacWithSha256);
-
- if (signingInfo.getSignedInterestFormat() == SignedInterestFormat::V03) {
- BOOST_REQUIRE(interest.getSignatureInfo() != nullopt);
- BOOST_CHECK_EQUAL(interest.getSignatureInfo()->getSignatureType(),
- tlv::SignatureHmacWithSha256);
- }
- else {
- SignatureInfo sigInfo(interest.getName()[signed_interest::POS_SIG_INFO].blockFromValue());
- BOOST_CHECK_EQUAL(sigInfo.getSignatureType(), tlv::SignatureHmacWithSha256);
- }
-
- BOOST_CHECK(verifySignature(data, tpm, keyName, DigestAlgorithm::SHA256));
- BOOST_CHECK(verifySignature(interest, tpm, keyName, DigestAlgorithm::SHA256));
- }
- else {
- BOOST_CHECK_EQUAL(data.getSignatureType(), tlv::SignatureSha256WithEcdsa);
-
- if (signingInfo.getSignedInterestFormat() == SignedInterestFormat::V03) {
- BOOST_REQUIRE(interest.getSignatureInfo() != nullopt);
- BOOST_CHECK_EQUAL(interest.getSignatureInfo()->getSignatureType(),
- tlv::SignatureSha256WithEcdsa);
- }
- else {
- SignatureInfo sigInfo(interest.getName()[signed_interest::POS_SIG_INFO].blockFromValue());
- BOOST_CHECK_EQUAL(sigInfo.getSignatureType(), tlv::SignatureSha256WithEcdsa);
- }
-
- BOOST_CHECK_EQUAL(data.getKeyLocator()->getName(), cert.getName().getPrefix(-2));
-
- if (signingInfo.getSignedInterestFormat() == SignedInterestFormat::V03) {
- BOOST_CHECK_EQUAL(interest.getSignatureInfo()->getKeyLocator().getName(),
- cert.getName().getPrefix(-2));
- }
- else {
- SignatureInfo sigInfo(interest.getName()[signed_interest::POS_SIG_INFO].blockFromValue());
- BOOST_CHECK_EQUAL(sigInfo.getKeyLocator().getName(), cert.getName().getPrefix(-2));
- }
-
- BOOST_CHECK(verifySignature(data, key));
- BOOST_CHECK(verifySignature(interest, key));
}
}
}
-BOOST_FIXTURE_TEST_CASE(PublicKeySigningDefaults, KeyChainFixture)
-{
- Data data("/test/data");
-
- // Identity will be created with generated key and self-signed cert with default parameters
- BOOST_CHECK_THROW(m_keyChain.sign(data, signingByIdentity("/non-existing/identity")), KeyChain::InvalidSigningInfoError);
-
- // Create identity with EC key and the corresponding self-signed certificate
- Identity id = m_keyChain.createIdentity("/ndn/test/ec", EcKeyParams());
- BOOST_CHECK_NO_THROW(m_keyChain.sign(data, signingByIdentity(id.getName())));
- BOOST_CHECK_EQUAL(data.getSignatureType(),
- KeyChain::getSignatureType(EcKeyParams().getKeyType(), DigestAlgorithm::SHA256));
- BOOST_REQUIRE(data.getKeyLocator().has_value());
- BOOST_CHECK(id.getName().isPrefixOf(data.getKeyLocator()->getName()));
-
- // Create identity with RSA key and the corresponding self-signed certificate
- id = m_keyChain.createIdentity("/ndn/test/rsa", RsaKeyParams());
- BOOST_CHECK_NO_THROW(m_keyChain.sign(data, signingByIdentity(id.getName())));
- BOOST_CHECK_EQUAL(data.getSignatureType(),
- KeyChain::getSignatureType(RsaKeyParams().getKeyType(), DigestAlgorithm::SHA256));
- BOOST_REQUIRE(data.getKeyLocator().has_value());
- BOOST_CHECK(id.getName().isPrefixOf(data.getKeyLocator()->getName()));
-}
-
BOOST_FIXTURE_TEST_CASE(ImportPrivateKey, KeyChainFixture)
{
Name keyName("/test/device2");