security: rename NO_SIGNATURE error code to MALFORMED_SIGNATURE

And move the documentation for all validation error codes to doxygen

Change-Id: Ibf4b507e3a544f2978192fbfad20cd7dc486818f
diff --git a/docs/index.rst b/docs/index.rst
index 5d7364c..b1f9012 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -51,7 +51,6 @@
 
    + :doc:`specs/certificate`
    + :doc:`specs/safe-bag`
-   + :doc:`specs/validation-error-code`
    + :doc:`specs/signed-interest`
 
 - :doc:`manpages`
diff --git a/docs/specs.rst b/docs/specs.rst
index 2d4a5ab..e5b1eff 100644
--- a/docs/specs.rst
+++ b/docs/specs.rst
@@ -6,5 +6,4 @@
 
    specs/certificate
    specs/safe-bag
-   specs/validation-error-code
    specs/signed-interest
diff --git a/docs/specs/validation-error-code.rst b/docs/specs/validation-error-code.rst
deleted file mode 100644
index dc2c18c..0000000
--- a/docs/specs/validation-error-code.rst
+++ /dev/null
@@ -1,33 +0,0 @@
-Validation Error Code
-=====================
-
-The following table defines a list of known codes and their description, which can be returned from the :ndn-cxx:`Validator` interface.
-Other error codes can be returned by validator implementations outside ndn-cxx codebase.
-
-+------------+--------------------------+-----------------------------------------------------+
-| Error code | Short ID                 | Description                                         |
-+============+==========================+=====================================================+
-| 0          | NO_ERROR                 | No error                                            |
-+------------+--------------------------+-----------------------------------------------------+
-| 1          | INVALID_SIGNATURE        | Invalid signature                                   |
-+------------+--------------------------+-----------------------------------------------------+
-| 2          | NO_SIGNATURE             | Missing signature                                   |
-+------------+--------------------------+-----------------------------------------------------+
-| 3          | CANNOT_RETRIEVE_CERT     | Cannot retrieve certificate                         |
-+------------+--------------------------+-----------------------------------------------------+
-| 4          | EXPIRED_CERT             | Certificate expired                                 |
-+------------+--------------------------+-----------------------------------------------------+
-| 5          | LOOP_DETECTED            | Loop detected in certification chain                |
-+------------+--------------------------+-----------------------------------------------------+
-| 6          | MALFORMED_CERT           | Malformed certificate                               |
-+------------+--------------------------+-----------------------------------------------------+
-| 7          | EXCEEDED_DEPTH_LIMIT     | Exceeded validation depth limit                     |
-+------------+--------------------------+-----------------------------------------------------+
-| 8          | INVALID_KEY_LOCATOR      | Key locator violates validation policy              |
-+------------+--------------------------+-----------------------------------------------------+
-| ..         | ...                      | ...                                                 |
-+------------+--------------------------+-----------------------------------------------------+
-| 255        | IMPLEMENTATION_ERROR     | Internal implementation error                       |
-+------------+--------------------------+-----------------------------------------------------+
-
-Specialized validator implementations can use error codes >= 256 to indicate a specialized error.
diff --git a/ndn-cxx/security/validation-error.cpp b/ndn-cxx/security/validation-error.cpp
index b32ce5a..7ab3abe 100644
--- a/ndn-cxx/security/validation-error.cpp
+++ b/ndn-cxx/security/validation-error.cpp
@@ -32,9 +32,9 @@
     case ValidationError::NO_ERROR:
       return os << "No error";
     case ValidationError::INVALID_SIGNATURE:
-      return os << "Invalid signature";
-    case ValidationError::NO_SIGNATURE:
-      return os << "Missing signature";
+      return os << "Signature verification failed";
+    case ValidationError::MALFORMED_SIGNATURE:
+      return os << "Missing or malformed signature";
     case ValidationError::CANNOT_RETRIEVE_CERT:
       return os << "Cannot retrieve certificate";
     case ValidationError::EXPIRED_CERT:
@@ -46,9 +46,9 @@
     case ValidationError::EXCEEDED_DEPTH_LIMIT:
       return os << "Exceeded validation depth limit";
     case ValidationError::INVALID_KEY_LOCATOR:
-      return os << "Key locator violates validation policy";
+      return os << "Invalid key locator";
     case ValidationError::POLICY_ERROR:
-      return os << "Validation policy error";
+      return os << "Policy violation";
     case ValidationError::IMPLEMENTATION_ERROR:
       return os << "Internal error";
     case ValidationError::USER_MIN:
@@ -58,14 +58,14 @@
     return os << "Custom error code " << to_underlying(code);
   }
   else {
-    return os << "Unrecognized error code " << to_underlying(code);
+    return os << "Unknown error code " << to_underlying(code);
   }
 }
 
 void
 ValidationError::print(std::ostream& os) const
 {
-  os << static_cast<ValidationError::Code>(m_code);
+  os << m_code;
   if (!m_info.empty()) {
     os << " (" << m_info << ")";
   }
diff --git a/ndn-cxx/security/validation-error.hpp b/ndn-cxx/security/validation-error.hpp
index bc68b4e..07a1aaa 100644
--- a/ndn-cxx/security/validation-error.hpp
+++ b/ndn-cxx/security/validation-error.hpp
@@ -35,34 +35,49 @@
 {
 public:
   /**
-   * @brief Known validation error codes
-   * @sa <a href="../specs/validation-error-code.html">Validation Error Codes</a>
+   * @brief Known error codes that can be returned by the Validator interface.
+   *
+   * Additional error codes can be defined by validation policies implemented outside ndn-cxx.
    */
   enum Code : uint32_t {
+    /// No error
     NO_ERROR             = 0,
+    /// Signature verification failed
     INVALID_SIGNATURE    = 1,
-    NO_SIGNATURE         = 2,
+    /// The signature (e.g., SignatureInfo element) is missing or malformed
+    MALFORMED_SIGNATURE  = 2,
+    /// The certificate cannot be retrieved
     CANNOT_RETRIEVE_CERT = 3,
+    /// The certificate expired or is not yet valid
     EXPIRED_CERT         = 4,
+    /// Loop detected in the certification chain
     LOOP_DETECTED        = 5,
+    /// The certificate is malformed
     MALFORMED_CERT       = 6,
+    /// Exceeded validation depth limit
     EXCEEDED_DEPTH_LIMIT = 7,
+    /// The KeyLocator element is missing or has an invalid format
     INVALID_KEY_LOCATOR  = 8,
+    /// The packet violates the validation rules enforced by the policy
     POLICY_ERROR         = 9,
+    /// Internal implementation error
     IMPLEMENTATION_ERROR = 255,
-    USER_MIN             = 256, // custom error codes should use >=256
+    /// Third-party validator implementations can use error codes greater than or equal
+    /// to this value to indicate a custom or specialized error condition
+    USER_MIN             = 256,
   };
 
   /**
-   * @brief Validation error, implicitly convertible from an error code and info string
+   * @brief ValidationError is implicitly constructible from an integer error code and
+   *        an optional info string.
    */
   ValidationError(uint32_t code, const std::string& info = "")
-    : m_code(code)
+    : m_code(static_cast<Code>(code))
     , m_info(info)
   {
   }
 
-  uint32_t
+  Code
   getCode() const
   {
     return m_code;
@@ -87,7 +102,7 @@
   }
 
 private:
-  uint32_t m_code;
+  Code m_code;
   std::string m_info;
 };
 
diff --git a/ndn-cxx/security/validation-policy.cpp b/ndn-cxx/security/validation-policy.cpp
index 5dc199b..97a839b 100644
--- a/ndn-cxx/security/validation-policy.cpp
+++ b/ndn-cxx/security/validation-policy.cpp
@@ -95,7 +95,8 @@
   // Try the old Signed Interest format from Packet Specification v0.2
   const Name& name = interest.getName();
   if (name.size() < signed_interest::MIN_SIZE) {
-    state.fail({ValidationError::NO_SIGNATURE, "Interest name too short `" + name.toUri() + "`"});
+    state.fail({ValidationError::MALFORMED_SIGNATURE,
+                "Interest name too short `" + name.toUri() + "`"});
     return {};
   }
 
@@ -103,7 +104,7 @@
     return SignatureInfo(name[signed_interest::POS_SIG_INFO].blockFromValue());
   }
   catch (const tlv::Error& e) {
-    state.fail({ValidationError::NO_SIGNATURE,
+    state.fail({ValidationError::MALFORMED_SIGNATURE,
                 "Malformed SignatureInfo in `" + name.toUri() + "`: " + e.what()});
     return {};
   }
diff --git a/ndn-cxx/security/validation-policy.hpp b/ndn-cxx/security/validation-policy.hpp
index 31ef78e..f49670a 100644
--- a/ndn-cxx/security/validation-policy.hpp
+++ b/ndn-cxx/security/validation-policy.hpp
@@ -154,7 +154,7 @@
  * SignedInterestFormatTag inside @p state, must have an InterestSignatureInfo element.
  * Legacy signed Interests must contain a (%Data)%SignatureInfo name component.
  * In both cases, if any TLV parsing errors are encountered, ValidationState::fail()
- * is invoked on @p state with a ValidationError::NO_SIGNATURE error code.
+ * is invoked on @p state with a ValidationError::MALFORMED_SIGNATURE error code.
  *
  * @pre @p state must contain a SignedInterestFormatTag to indicate whether the %Interest is
  *      signed according to Packet Specification v0.3+ or a previous specification.
diff --git a/ndn-cxx/security/validator.cpp b/ndn-cxx/security/validator.cpp
index 984508b..99d1a6f 100644
--- a/ndn-cxx/security/validator.cpp
+++ b/ndn-cxx/security/validator.cpp
@@ -71,7 +71,7 @@
     state->setTag(make_shared<SignedInterestFormatTag>(fmt));
   }
   catch (const tlv::Error& e) {
-    return state->fail({ValidationError::NO_SIGNATURE, "Malformed InterestSignatureInfo in `" +
+    return state->fail({ValidationError::MALFORMED_SIGNATURE, "Malformed InterestSignatureInfo in `" +
                         interest.getName().toUri() + "`: " + e.what()});
   }
 
diff --git a/tests/unit/security/validation-error.t.cpp b/tests/unit/security/validation-error.t.cpp
index 6c1b5f7..c4a1a08 100644
--- a/tests/unit/security/validation-error.t.cpp
+++ b/tests/unit/security/validation-error.t.cpp
@@ -22,6 +22,7 @@
 #include "ndn-cxx/security/validation-error.hpp"
 
 #include "tests/boost-test.hpp"
+
 #include <boost/lexical_cast.hpp>
 
 namespace ndn {
@@ -37,17 +38,22 @@
   ValidationError e1{ValidationError::INVALID_SIGNATURE};
   BOOST_CHECK_EQUAL(e1.getCode(), 1);
   BOOST_CHECK_EQUAL(e1.getInfo(), "");
-  BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(e1), "Invalid signature");
+  BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(e1), "Signature verification failed");
 
-  ValidationError e2{ValidationError::NO_SIGNATURE, "message"};
+  ValidationError e2{ValidationError::MALFORMED_SIGNATURE, "message"};
   BOOST_CHECK_EQUAL(e2.getCode(), 2);
   BOOST_CHECK_EQUAL(e2.getInfo(), "message");
-  BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(e2), "Missing signature (message)");
+  BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(e2), "Missing or malformed signature (message)");
 
   ValidationError e3{65535, "other message"};
   BOOST_CHECK_EQUAL(e3.getCode(), 65535);
   BOOST_CHECK_EQUAL(e3.getInfo(), "other message");
   BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(e3), "Custom error code 65535 (other message)");
+
+  ValidationError e4{200};
+  BOOST_CHECK_EQUAL(e4.getCode(), 200);
+  BOOST_CHECK_EQUAL(e4.getInfo(), "");
+  BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(e4), "Unknown error code 200");
 }
 
 BOOST_AUTO_TEST_SUITE_END() // TestValidationError
diff --git a/tests/unit/security/validation-policy-command-interest.t.cpp b/tests/unit/security/validation-policy-command-interest.t.cpp
index d6fd74f..604c60d 100644
--- a/tests/unit/security/validation-policy-command-interest.t.cpp
+++ b/tests/unit/security/validation-policy-command-interest.t.cpp
@@ -165,7 +165,7 @@
   auto i1 = Interest("/short");
   BOOST_TEST_REQUIRE(i1.getName().size() < signed_interest::MIN_SIZE);
   VALIDATE_FAILURE(i1, "Should fail (not signed / name too short)");
-  BOOST_TEST(lastError.getCode() == ValidationError::NO_SIGNATURE);
+  BOOST_TEST(lastError.getCode() == ValidationError::MALFORMED_SIGNATURE);
 }
 
 BOOST_AUTO_TEST_CASE(BadSigInfo)
@@ -174,7 +174,7 @@
   setNameComponent(i1, command_interest::POS_SIG_INFO, "not-SignatureInfo");
   BOOST_TEST_REQUIRE(i1.getName().size() >= command_interest::MIN_SIZE);
   VALIDATE_FAILURE(i1, "Should fail (signature info is missing)");
-  BOOST_TEST(lastError.getCode() == ValidationError::NO_SIGNATURE);
+  BOOST_TEST(lastError.getCode() == ValidationError::MALFORMED_SIGNATURE);
 }
 
 BOOST_AUTO_TEST_CASE(BadTimestampV02)
diff --git a/tests/unit/security/validation-policy-simple-hierarchy.t.cpp b/tests/unit/security/validation-policy-simple-hierarchy.t.cpp
index 38ab30c..788a7c9 100644
--- a/tests/unit/security/validation-policy-simple-hierarchy.t.cpp
+++ b/tests/unit/security/validation-policy-simple-hierarchy.t.cpp
@@ -43,7 +43,7 @@
 
   auto packet = Packet::makePacket(name);
   VALIDATE_FAILURE(packet, "Unsigned");
-  BOOST_TEST((lastError.getCode() == ValidationError::NO_SIGNATURE ||        // Interest
+  BOOST_TEST((lastError.getCode() == ValidationError::MALFORMED_SIGNATURE || // Interest
               lastError.getCode() == ValidationError::INVALID_KEY_LOCATOR)); // Data
 
   packet = Packet::makePacket(name);
diff --git a/tests/unit/security/validator.t.cpp b/tests/unit/security/validator.t.cpp
index 842f2f5..d1b746b 100644
--- a/tests/unit/security/validator.t.cpp
+++ b/tests/unit/security/validator.t.cpp
@@ -64,7 +64,7 @@
   BOOST_REQUIRE_NO_THROW(interest.getSignatureValue());
 
   VALIDATE_FAILURE(interest, "InterestSignatureInfo decoding should fail");
-  BOOST_TEST(lastError.getCode() == ValidationError::NO_SIGNATURE);
+  BOOST_TEST(lastError.getCode() == ValidationError::MALFORMED_SIGNATURE);
   BOOST_TEST(face.sentInterests.size() == 0);
 }
 
@@ -259,7 +259,7 @@
   Data data("/Security/ValidatorFixture/Sub1/Sub2/Data");
 
   VALIDATE_FAILURE(interest, "Unsigned");
-  BOOST_TEST(lastError.getCode() == ValidationError::NO_SIGNATURE);
+  BOOST_TEST(lastError.getCode() == ValidationError::MALFORMED_SIGNATURE);
   VALIDATE_SUCCESS(data, "Policy bypasses validation for all data");
   BOOST_TEST(face.sentInterests.size() == 0);
   face.sentInterests.clear();