security: use high-level EVP routines in HmacFilter

Change-Id: I58aabf111193d3b554c8777b4ec41e3f761be263
diff --git a/src/security/transform/hmac-filter.cpp b/src/security/transform/hmac-filter.cpp
index 07a1796..81f7a27 100644
--- a/src/security/transform/hmac-filter.cpp
+++ b/src/security/transform/hmac-filter.cpp
@@ -22,6 +22,8 @@
 #include "hmac-filter.hpp"
 #include "../detail/openssl-helper.hpp"
 
+#include <boost/lexical_cast.hpp>
+
 namespace ndn {
 namespace security {
 namespace transform {
@@ -29,43 +31,29 @@
 class HmacFilter::Impl
 {
 public:
+  Impl() noexcept
+    : key(nullptr)
+  {
 #if OPENSSL_VERSION_NUMBER < 0x1010000fL
-  Impl()
-  {
-    HMAC_CTX_init(&m_context);
-  }
-
-  ~Impl()
-  {
-    HMAC_CTX_cleanup(&m_context);
-  }
-
-  operator HMAC_CTX*()
-  {
-    return &m_context;
-  }
-
-private:
-  HMAC_CTX m_context;
+    ctx = EVP_MD_CTX_create();
 #else
-  Impl()
-    : m_context(HMAC_CTX_new())
-  {
+    ctx = EVP_MD_CTX_new();
+#endif
   }
 
   ~Impl()
   {
-    HMAC_CTX_free(m_context);
+#if OPENSSL_VERSION_NUMBER < 0x1010000fL
+    EVP_MD_CTX_destroy(ctx);
+#else
+    EVP_MD_CTX_free(ctx);
+#endif
+    EVP_PKEY_free(key);
   }
 
-  operator HMAC_CTX*()
-  {
-    return m_context;
-  }
-
-private:
-  HMAC_CTX* m_context;
-#endif // OPENSSL_VERSION_NUMBER < 0x1010000fL
+public:
+  EVP_MD_CTX* ctx;
+  EVP_PKEY* key;
 };
 
 
@@ -75,12 +63,18 @@
   BOOST_ASSERT(key != nullptr);
   BOOST_ASSERT(keyLen > 0);
 
-  const EVP_MD* algorithm = detail::digestAlgorithmToEvpMd(algo);
-  if (algorithm == nullptr)
-    BOOST_THROW_EXCEPTION(Error(getIndex(), "Unsupported digest algorithm"));
+  const EVP_MD* md = detail::digestAlgorithmToEvpMd(algo);
+  if (md == nullptr)
+    BOOST_THROW_EXCEPTION(Error(getIndex(), "Unsupported digest algorithm " +
+                                boost::lexical_cast<std::string>(algo)));
 
-  if (HMAC_Init_ex(*m_impl, key, keyLen, algorithm, nullptr) == 0)
-    BOOST_THROW_EXCEPTION(Error(getIndex(), "Cannot initialize HMAC"));
+  m_impl->key = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, nullptr, key, static_cast<int>(keyLen));
+  if (m_impl->key == nullptr)
+    BOOST_THROW_EXCEPTION(Error(getIndex(), "Failed to create HMAC key"));
+
+  if (EVP_DigestSignInit(m_impl->ctx, nullptr, md, nullptr, m_impl->key) != 1)
+    BOOST_THROW_EXCEPTION(Error(getIndex(), "Failed to initialize HMAC context with " +
+                                boost::lexical_cast<std::string>(algo) + " digest"));
 }
 
 HmacFilter::~HmacFilter() = default;
@@ -88,8 +82,8 @@
 size_t
 HmacFilter::convert(const uint8_t* buf, size_t size)
 {
-  if (HMAC_Update(*m_impl, buf, size) == 0)
-    BOOST_THROW_EXCEPTION(Error(getIndex(), "Failed to update HMAC"));
+  if (EVP_DigestSignUpdate(m_impl->ctx, buf, size) != 1)
+    BOOST_THROW_EXCEPTION(Error(getIndex(), "Failed to accept more input"));
 
   return size;
 }
@@ -98,12 +92,12 @@
 HmacFilter::finalize()
 {
   auto buffer = make_unique<OBuffer>(EVP_MAX_MD_SIZE);
-  unsigned int mdLen = 0;
+  size_t hmacLen = 0;
 
-  if (HMAC_Final(*m_impl, buffer->data(), &mdLen) == 0)
+  if (EVP_DigestSignFinal(m_impl->ctx, buffer->data(), &hmacLen) != 1)
     BOOST_THROW_EXCEPTION(Error(getIndex(), "Failed to finalize HMAC"));
 
-  buffer->erase(buffer->begin() + mdLen, buffer->end());
+  buffer->erase(buffer->begin() + hmacLen, buffer->end());
   setOutputBuffer(std::move(buffer));
 
   flushAllOutput();
diff --git a/src/security/transform/hmac-filter.hpp b/src/security/transform/hmac-filter.hpp
index d0770b3..92c1905 100644
--- a/src/security/transform/hmac-filter.hpp
+++ b/src/security/transform/hmac-filter.hpp
@@ -36,7 +36,7 @@
 {
 public:
   /**
-   * @brief Create a HMAC module to generate HMAC using algorithm @p algo and @p key
+   * @brief Create a module to generate HMAC using digest algorithm @p algo and key @p key
    * @pre @p key must not be nullptr, and @p size must be a positive integer.
    */
   HmacFilter(DigestAlgorithm algo, const uint8_t* key, size_t keyLen);
@@ -45,7 +45,7 @@
 
 private:
   /**
-   * @brief write data @p buf into HMAC signer
+   * @brief Write data @p buf into HMAC signer
    *
    * @return The number of bytes that are actually accepted
    */