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)