security: fix extraction of signed portion during Data signature verification

refs #4583

Change-Id: Ia0fc93a6e2408bb5f0de16fd76fcb6d9f06a0398
diff --git a/ndn-cxx/data.cpp b/ndn-cxx/data.cpp
index 8106fd3..f5eb8b9 100644
--- a/ndn-cxx/data.cpp
+++ b/ndn-cxx/data.cpp
@@ -326,6 +326,19 @@
   return *this;
 }
 
+InputBuffers
+Data::extractSignedRanges() const
+{
+  InputBuffers bufs;
+  bufs.reserve(1); // One range containing data value up to, but not including, SignatureValue
+
+  wireEncode();
+  auto lastSignedIt = std::prev(m_wire.find(tlv::SignatureValue));
+  bufs.emplace_back(m_wire.value(),
+                    std::distance(m_wire.value_begin(), lastSignedIt->end()));
+  return bufs;
+}
+
 Data&
 Data::setContentType(uint32_t type)
 {
diff --git a/ndn-cxx/data.hpp b/ndn-cxx/data.hpp
index ac25c07..838df88 100644
--- a/ndn-cxx/data.hpp
+++ b/ndn-cxx/data.hpp
@@ -26,6 +26,7 @@
 #include "ndn-cxx/encoding/block.hpp"
 #include "ndn-cxx/meta-info.hpp"
 #include "ndn-cxx/name.hpp"
+#include "ndn-cxx/security/security-common.hpp"
 #include "ndn-cxx/signature-info.hpp"
 
 namespace ndn {
@@ -264,6 +265,13 @@
   Data&
   setSignatureValue(ConstBufferPtr value);
 
+  /** @brief Extract ranges of Data covered by the signature
+   *  @throw Error Data cannot be encoded or is missing ranges necessary for signing
+   *  @warning The returned pointers will be invalidated if wireDecode() or wireEncode() are called.
+   */
+  InputBuffers
+  extractSignedRanges() const;
+
 public: // MetaInfo fields
   uint32_t
   getContentType() const
diff --git a/ndn-cxx/security/verification-helpers.cpp b/ndn-cxx/security/verification-helpers.cpp
index d21fb2a..17df3f9 100644
--- a/ndn-cxx/security/verification-helpers.cpp
+++ b/ndn-cxx/security/verification-helpers.cpp
@@ -110,8 +110,7 @@
 parse(const Data& data)
 {
   try {
-    const Block& wire = data.wireEncode();
-    return ParseResult({{wire.value(), wire.value_size() - data.getSignatureValue().size()}},
+    return ParseResult(data.extractSignedRanges(),
                        data.getSignatureValue().value(),
                        data.getSignatureValue().value_size());
   }