security: use high-level EVP routines in DigestFilter
Change-Id: Iac47c1024a9fcbd96e988a110aadb52d59178d3d
diff --git a/src/security/transform/digest-filter.cpp b/src/security/transform/digest-filter.cpp
index c984b8c..eca72b2 100644
--- a/src/security/transform/digest-filter.cpp
+++ b/src/security/transform/digest-filter.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2013-2016 Regents of the University of California.
+/*
+ * Copyright (c) 2013-2017 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -20,7 +20,6 @@
*/
#include "digest-filter.hpp"
-#include "../../encoding/buffer.hpp"
#include "../detail/openssl-helper.hpp"
#include <boost/lexical_cast.hpp>
@@ -30,69 +29,65 @@
namespace transform {
/**
- * @brief The implementation class which contains the internal state of
- * the digest calculator which includes openssl specific structures.
+ * Implementation class that contains the internal state of the
+ * digest calculator, including openssl-specific structures.
*/
class DigestFilter::Impl
{
public:
- Impl()
- : m_md(BIO_new(BIO_f_md()))
- , m_sink(BIO_new(BIO_s_null()))
+ Impl() noexcept
{
- BIO_push(m_md, m_sink);
+#if OPENSSL_VERSION_NUMBER < 0x1010000fL
+ ctx = EVP_MD_CTX_create();
+#else
+ ctx = EVP_MD_CTX_new();
+#endif
}
~Impl()
{
- BIO_free_all(m_md);
+#if OPENSSL_VERSION_NUMBER < 0x1010000fL
+ EVP_MD_CTX_destroy(ctx);
+#else
+ EVP_MD_CTX_free(ctx);
+#endif
}
public:
- BIO* m_md;
- BIO* m_sink;
+ EVP_MD_CTX* ctx;
};
+
DigestFilter::DigestFilter(DigestAlgorithm algo)
- : m_impl(new Impl)
+ : m_impl(make_unique<Impl>())
{
const EVP_MD* md = detail::toDigestEvpMd(algo);
- if (md == nullptr) {
+ if (md == nullptr)
BOOST_THROW_EXCEPTION(Error(getIndex(), "Unsupported digest algorithm " +
boost::lexical_cast<std::string>(algo)));
- }
- if (!BIO_set_md(m_impl->m_md, md)) {
- BOOST_THROW_EXCEPTION(Error(getIndex(), "Cannot set digest"+
+ if (EVP_DigestInit_ex(m_impl->ctx, md, nullptr) == 0)
+ BOOST_THROW_EXCEPTION(Error(getIndex(), "Cannot initialize digest " +
boost::lexical_cast<std::string>(algo)));
- }
}
size_t
DigestFilter::convert(const uint8_t* buf, size_t size)
{
- int wLen = BIO_write(m_impl->m_md, buf, size);
+ if (EVP_DigestUpdate(m_impl->ctx, buf, size) == 0)
+ BOOST_THROW_EXCEPTION(Error(getIndex(), "Failed to accept more input"));
- if (wLen <= 0) { // fail to write data
- if (!BIO_should_retry(m_impl->m_md)) {
- // we haven't written everything but some error happens, and we cannot retry
- BOOST_THROW_EXCEPTION(Error(getIndex(), "Failed to accept more input"));
- }
- return 0;
- }
- else { // update number of bytes written
- return wLen;
- }
+ return size;
}
void
DigestFilter::finalize()
{
auto buffer = make_unique<OBuffer>(EVP_MAX_MD_SIZE);
+ unsigned int mdLen = 0;
- int mdLen = BIO_gets(m_impl->m_md, reinterpret_cast<char*>(&(*buffer)[0]), EVP_MAX_MD_SIZE);
- if (mdLen <= 0)
- BOOST_THROW_EXCEPTION(Error(getIndex(), "Failed to compute digest"));
+ if (EVP_DigestFinal_ex(m_impl->ctx, buffer->data(), &mdLen) == 0)
+ BOOST_THROW_EXCEPTION(Error(getIndex(), "Failed to finalize digest"));
buffer->erase(buffer->begin() + mdLen, buffer->end());
setOutputBuffer(std::move(buffer));