security: add HMAC support in verification helpers
Add two more verifySignature() overloads with tpm and keyname as parameters
Change-Id: I53ef8f15c8764b17a26df3216c25f6b19f7c1719
diff --git a/ndn-cxx/security/verification-helpers.cpp b/ndn-cxx/security/verification-helpers.cpp
index 625537e..cbca64f 100644
--- a/ndn-cxx/security/verification-helpers.cpp
+++ b/ndn-cxx/security/verification-helpers.cpp
@@ -26,6 +26,8 @@
#include "ndn-cxx/encoding/buffer-stream.hpp"
#include "ndn-cxx/security/impl/openssl.hpp"
#include "ndn-cxx/security/pib/key.hpp"
+#include "ndn-cxx/security/tpm/key-handle.hpp"
+#include "ndn-cxx/security/tpm/tpm.hpp"
#include "ndn-cxx/security/transform/bool-sink.hpp"
#include "ndn-cxx/security/transform/buffer-source.hpp"
#include "ndn-cxx/security/transform/digest-filter.hpp"
@@ -37,6 +39,19 @@
namespace ndn {
namespace security {
+namespace {
+
+struct ParseResult
+{
+ bool isParsable = false;
+ const uint8_t* buf = nullptr;
+ size_t bufLen = 0;
+ const uint8_t* sig = nullptr;
+ size_t sigLen = 0;
+};
+
+} // namespace
+
bool
verifySignature(const uint8_t* blob, size_t blobLen, const uint8_t* sig, size_t sigLen,
const transform::PublicKey& key)
@@ -68,76 +83,62 @@
return verifySignature(data, dataLen, sig, sigLen, pKey);
}
-static std::tuple<bool, const uint8_t*, size_t, const uint8_t*, size_t>
+static ParseResult
parse(const Data& data)
{
try {
- return std::make_tuple(true,
- data.wireEncode().value(),
- data.wireEncode().value_size() - data.getSignature().getValue().size(),
- data.getSignature().getValue().value(),
- data.getSignature().getValue().value_size());
+ return {true,
+ data.wireEncode().value(),
+ data.wireEncode().value_size() - data.getSignature().getValue().size(),
+ data.getSignature().getValue().value(),
+ data.getSignature().getValue().value_size()};
}
catch (const tlv::Error&) {
- return std::make_tuple(false, nullptr, 0, nullptr, 0);
+ return ParseResult();
}
}
-static std::tuple<bool, const uint8_t*, size_t, const uint8_t*, size_t>
+static ParseResult
parse(const Interest& interest)
{
const Name& interestName = interest.getName();
if (interestName.size() < signed_interest::MIN_SIZE)
- return std::make_tuple(false, nullptr, 0, nullptr, 0);
+ return ParseResult();
try {
const Block& nameBlock = interestName.wireEncode();
-
- return std::make_tuple(true,
- nameBlock.value(), nameBlock.value_size() - interestName[signed_interest::POS_SIG_VALUE].size(),
- interestName[signed_interest::POS_SIG_VALUE].blockFromValue().value(),
- interestName[signed_interest::POS_SIG_VALUE].blockFromValue().value_size());
+ return {true,
+ nameBlock.value(),
+ nameBlock.value_size() - interestName[signed_interest::POS_SIG_VALUE].size(),
+ interestName[signed_interest::POS_SIG_VALUE].blockFromValue().value(),
+ interestName[signed_interest::POS_SIG_VALUE].blockFromValue().value_size()};
}
catch (const tlv::Error&) {
- return std::make_tuple(false, nullptr, 0, nullptr, 0);
+ return ParseResult();
}
}
static bool
-verifySignature(const std::tuple<bool, const uint8_t*, size_t, const uint8_t*, size_t>& params,
- const transform::PublicKey& key)
+verifySignature(ParseResult params, const transform::PublicKey& key)
{
- bool isParsable = false;
- const uint8_t* buf = nullptr;
- size_t bufLen = 0;
- const uint8_t* sig = nullptr;
- size_t sigLen = 0;
-
- std::tie(isParsable, buf, bufLen, sig, sigLen) = params;
-
- if (isParsable)
- return verifySignature(buf, bufLen, sig, sigLen, key);
- else
- return false;
+ return params.isParsable && verifySignature(params.buf, params.bufLen,
+ params.sig, params.sigLen, key);
}
static bool
-verifySignature(const std::tuple<bool, const uint8_t*, size_t, const uint8_t*, size_t>& params,
- const uint8_t* key, size_t keyLen)
+verifySignature(ParseResult params, const tpm::Tpm& tpm, const Name& keyName,
+ DigestAlgorithm digestAlgorithm)
{
- bool isParsable = false;
- const uint8_t* buf = nullptr;
- size_t bufLen = 0;
- const uint8_t* sig = nullptr;
- size_t sigLen = 0;
+ return params.isParsable && bool(tpm.verify(params.buf, params.bufLen,
+ params.sig, params.sigLen, keyName, digestAlgorithm));
+}
- std::tie(isParsable, buf, bufLen, sig, sigLen) = params;
-
- if (isParsable)
- return verifySignature(buf, bufLen, sig, sigLen, key, keyLen);
- else
- return false;
+static bool
+verifySignature(ParseResult params, const uint8_t* key, size_t keyLen)
+{
+ return params.isParsable && verifySignature(params.buf, params.bufLen,
+ params.sig, params.sigLen, key, keyLen);
}
bool
@@ -188,6 +189,20 @@
return verifySignature(parse(interest), cert.getContent().value(), cert.getContent().value_size());
}
+bool
+verifySignature(const Data& data, const tpm::Tpm& tpm,
+ const Name& keyName, DigestAlgorithm digestAlgorithm)
+{
+ return verifySignature(parse(data), tpm, keyName, digestAlgorithm);
+}
+
+bool
+verifySignature(const Interest& interest, const tpm::Tpm& tpm,
+ const Name& keyName, DigestAlgorithm digestAlgorithm)
+{
+ return verifySignature(parse(interest), tpm, keyName, digestAlgorithm);
+}
+
///////////////////////////////////////////////////////////////////////
bool
@@ -215,39 +230,17 @@
bool
verifyDigest(const Data& data, DigestAlgorithm algorithm)
{
- bool isParsable = false;
- const uint8_t* buf = nullptr;
- size_t bufLen = 0;
- const uint8_t* sig = nullptr;
- size_t sigLen = 0;
-
- std::tie(isParsable, buf, bufLen, sig, sigLen) = parse(data);
-
- if (isParsable) {
- return verifyDigest(buf, bufLen, sig, sigLen, algorithm);
- }
- else {
- return false;
- }
+ ParseResult parseResult = parse(data);
+ return parseResult.isParsable && verifyDigest(parseResult.buf, parseResult.bufLen,
+ parseResult.sig, parseResult.sigLen, algorithm);
}
bool
verifyDigest(const Interest& interest, DigestAlgorithm algorithm)
{
- bool isParsable = false;
- const uint8_t* buf = nullptr;
- size_t bufLen = 0;
- const uint8_t* sig = nullptr;
- size_t sigLen = 0;
-
- std::tie(isParsable, buf, bufLen, sig, sigLen) = parse(interest);
-
- if (isParsable) {
- return verifyDigest(buf, bufLen, sig, sigLen, algorithm);
- }
- else {
- return false;
- }
+ ParseResult parseResult = parse(interest);
+ return parseResult.isParsable && verifyDigest(parseResult.buf, parseResult.bufLen,
+ parseResult.sig, parseResult.sigLen, algorithm);
}
} // namespace security
diff --git a/ndn-cxx/security/verification-helpers.hpp b/ndn-cxx/security/verification-helpers.hpp
index c3c848a..3399821 100644
--- a/ndn-cxx/security/verification-helpers.hpp
+++ b/ndn-cxx/security/verification-helpers.hpp
@@ -22,6 +22,7 @@
#ifndef NDN_SECURITY_VERIFICATION_HELPERS_HPP
#define NDN_SECURITY_VERIFICATION_HELPERS_HPP
+#include "ndn-cxx/name.hpp"
#include "ndn-cxx/security/security-common.hpp"
namespace ndn {
@@ -35,6 +36,10 @@
class Key;
} // namespace pib
+namespace tpm {
+class Tpm;
+} // namespace tpm
+
namespace transform {
class PublicKey;
} // namespace transform
@@ -116,6 +121,22 @@
bool
verifySignature(const Interest& interest, const v2::Certificate& cert);
+/**
+ * @brief Verify @p data using @p tpm and @p keyName with the @p digestAlgorithm.
+ */
+bool
+verifySignature(const Data& data, const tpm::Tpm& tpm, const Name& keyName,
+ DigestAlgorithm digestAlgorithm);
+
+/**
+ * @brief Verify @p interest using @p tpm and @p keyName with the @p digestAlgorithm.
+ * @note This method verifies only signature of the signed interest.
+ * @sa docs/specs/signed-interest.rst
+ */
+bool
+verifySignature(const Interest& interest, const tpm::Tpm& tpm, const Name& keyName,
+ DigestAlgorithm digestAlgorithm);
+
//////////////////////////////////////////////////////////////////
/**
diff --git a/tests/unit/security/v2/key-chain.t.cpp b/tests/unit/security/v2/key-chain.t.cpp
index 17f8569..1d25e59 100644
--- a/tests/unit/security/v2/key-chain.t.cpp
+++ b/tests/unit/security/v2/key-chain.t.cpp
@@ -366,19 +366,8 @@
BOOST_CHECK_EQUAL(data.getSignature().getType(), tlv::SignatureHmacWithSha256);
BOOST_CHECK_EQUAL(interestSignature.getType(), tlv::SignatureHmacWithSha256);
- BOOST_CHECK(bool(tpm.verify(data.wireEncode().value(),
- data.wireEncode().value_size() - data.getSignature().getValue().size(),
- data.getSignature().getValue().value(),
- data.getSignature().getValue().value_size(),
- keyName, DigestAlgorithm::SHA256)));
-
- const Name& interestName = interest.getName();
- auto nameBlock = interestName.wireEncode();
- BOOST_CHECK(bool(tpm.verify(nameBlock.value(),
- nameBlock.value_size() - interestName[signed_interest::POS_SIG_VALUE].size(),
- interestName[signed_interest::POS_SIG_VALUE].blockFromValue().value(),
- interestName[signed_interest::POS_SIG_VALUE].blockFromValue().value_size(),
- keyName, DigestAlgorithm::SHA256)));
+ BOOST_CHECK(bool(verifySignature(data, tpm, keyName, DigestAlgorithm::SHA256)));
+ BOOST_CHECK(bool(verifySignature(interest, tpm, keyName, DigestAlgorithm::SHA256)));
}
else {
BOOST_CHECK_EQUAL(data.getSignature().getType(), tlv::SignatureSha256WithEcdsa);
diff --git a/tests/unit/security/verification-helpers.t.cpp b/tests/unit/security/verification-helpers.t.cpp
index 977ec30..c0c6b5a 100644
--- a/tests/unit/security/verification-helpers.t.cpp
+++ b/tests/unit/security/verification-helpers.t.cpp
@@ -469,6 +469,25 @@
// - pib::Key version is tested as part of v2/key-chain.t.cpp (Security/V2/TestKeyChain)
}
+BOOST_FIXTURE_TEST_CASE(VerifyHmac, IdentityManagementFixture)
+{
+ const Tpm& tpm = m_keyChain.getTpm();
+ Data data("/data");
+ Interest interest("/interest");
+ SigningInfo signingInfo;
+ signingInfo.setSigningHmacKey("QjM3NEEyNkE3MTQ5MDQzN0FBMDI0RTRGQURENUI0OTdGREZGMUE4RUE2RkYxMkY2"
+ "RkI2NUFGMjcyMEI1OUNDRg==");
+ signingInfo.setDigestAlgorithm(DigestAlgorithm::SHA256);
+
+ BOOST_CHECK(!verifySignature(data, tpm, signingInfo.getSignerName(), DigestAlgorithm::SHA256));
+ BOOST_CHECK(!verifySignature(interest, tpm, signingInfo.getSignerName(), DigestAlgorithm::SHA256));
+
+ m_keyChain.sign(data, signingInfo);
+ m_keyChain.sign(interest, signingInfo);
+ BOOST_CHECK(verifySignature(data, tpm, signingInfo.getSignerName(), DigestAlgorithm::SHA256));
+ BOOST_CHECK(verifySignature(interest, tpm, signingInfo.getSignerName(), DigestAlgorithm::SHA256));
+}
+
using DigestDatasets = boost::mpl::vector<Sha256Dataset>;
BOOST_AUTO_TEST_CASE_TEMPLATE(VerifyDigest, Dataset, DigestDatasets)