security: Introduce unsetKeyLocator method into SignatureInfo and Signature

Some specific signature types also provide an advisory (non-virtual)
override for unsetKeyLocator that disables reset and throws an
Exception.  As before, if an application really wants, it still can
unset the KeyLocator by setting a new SignatureInfo without the
KeyLocator.

Change-Id: Ibefd5f9ffbcb91f8a83e76db8704cba1b984f914
Refs: #1750
diff --git a/src/security/signature-sha256-with-ecdsa.cpp b/src/security/signature-sha256-with-ecdsa.cpp
index 1f67425..91b4a29 100644
--- a/src/security/signature-sha256-with-ecdsa.cpp
+++ b/src/security/signature-sha256-with-ecdsa.cpp
@@ -39,4 +39,10 @@
   }
 }
 
+void
+SignatureSha256WithEcdsa::unsetKeyLocator()
+{
+  throw Error("KeyLocator cannot be reset for SignatureSha256WithEcdsa");
+}
+
 } // namespace ndn
diff --git a/src/security/signature-sha256-with-ecdsa.hpp b/src/security/signature-sha256-with-ecdsa.hpp
index a20e6b0..4b0eb7f 100644
--- a/src/security/signature-sha256-with-ecdsa.hpp
+++ b/src/security/signature-sha256-with-ecdsa.hpp
@@ -48,6 +48,9 @@
   explicit
   SignatureSha256WithEcdsa(const Signature& signature);
 
+private:
+  void
+  unsetKeyLocator();
 };
 
 } // namespace ndn
diff --git a/src/security/signature-sha256-with-rsa.cpp b/src/security/signature-sha256-with-rsa.cpp
index bc4fe65..3c84b54 100644
--- a/src/security/signature-sha256-with-rsa.cpp
+++ b/src/security/signature-sha256-with-rsa.cpp
@@ -39,4 +39,10 @@
   }
 }
 
+void
+SignatureSha256WithRsa::unsetKeyLocator()
+{
+  throw Error("KeyLocator cannot be reset for SignatureSha256WithRsa");
+}
+
 } // namespace ndn
diff --git a/src/security/signature-sha256-with-rsa.hpp b/src/security/signature-sha256-with-rsa.hpp
index 94f9e30..937794b 100644
--- a/src/security/signature-sha256-with-rsa.hpp
+++ b/src/security/signature-sha256-with-rsa.hpp
@@ -47,6 +47,10 @@
 
   explicit
   SignatureSha256WithRsa(const Signature& signature);
+
+private:
+  void
+  unsetKeyLocator();
 };
 
 } // namespace ndn
diff --git a/src/signature-info.cpp b/src/signature-info.cpp
index 2543dd2..20e013f 100644
--- a/src/signature-info.cpp
+++ b/src/signature-info.cpp
@@ -63,6 +63,14 @@
   m_hasKeyLocator = true;
 }
 
+void
+SignatureInfo::unsetKeyLocator()
+{
+  m_wire.reset();
+  m_keyLocator = KeyLocator();
+  m_hasKeyLocator = false;
+}
+
 const KeyLocator&
 SignatureInfo::getKeyLocator() const
 {
diff --git a/src/signature-info.hpp b/src/signature-info.hpp
index c0a2d88..4ef60fc 100644
--- a/src/signature-info.hpp
+++ b/src/signature-info.hpp
@@ -78,6 +78,10 @@
   void
   setKeyLocator(const KeyLocator& keyLocator);
 
+  /// @brief Unset KeyLocator
+  void
+  unsetKeyLocator();
+
   /**
    * @brief Get KeyLocator
    *
diff --git a/src/signature.hpp b/src/signature.hpp
index 66a3f52..c2cb8c2 100644
--- a/src/signature.hpp
+++ b/src/signature.hpp
@@ -130,6 +130,18 @@
     m_info.setKeyLocator(keyLocator);
   }
 
+  /**
+   * @brief Unset KeyLocator
+   *
+   * Note that specific signature types may provide advisory (non-virtual) override
+   * to prevent unsetting KeyLocator if it is required by the specification.
+   */
+  void
+  unsetKeyLocator()
+  {
+    m_info.unsetKeyLocator();
+  }
+
 public: // EqualityComparable concept
   bool
   operator==(const Signature& other) const
diff --git a/tests/unit-tests/test-signature-info.cpp b/tests/unit-tests/test-signature-info.cpp
index 605b325..ad7d8f9 100644
--- a/tests/unit-tests/test-signature-info.cpp
+++ b/tests/unit-tests/test-signature-info.cpp
@@ -148,6 +148,10 @@
                                 sigInfoBlock.wire() + sigInfoBlock.size(),
                                 encoded.wire(),
                                 encoded.wire() + encoded.size());
+
+  info.unsetKeyLocator();
+  BOOST_CHECK_EQUAL(info.hasKeyLocator(), false);
+  BOOST_CHECK_THROW(info.getKeyLocator(), SignatureInfo::Error);
 }
 
 BOOST_AUTO_TEST_CASE(OtherTlvs)