security: cleanup validation error reporting

Change-Id: I313bedb336ecfb4180ba0f31ad77666544ba1c10
diff --git a/.jenkins.d/00-deps.sh b/.jenkins.d/00-deps.sh
index 54476fe..12b5de3 100755
--- a/.jenkins.d/00-deps.sh
+++ b/.jenkins.d/00-deps.sh
@@ -8,7 +8,7 @@
 case $JOB_NAME in
     *code-coverage)
         APT_PKGS+=(lcov python3-pip)
-        PIP_PKGS+=('gcovr~=5.1')
+        PIP_PKGS+=('gcovr~=5.2')
         ;;
     *Docs)
         APT_PKGS+=(doxygen graphviz python3-pip)
diff --git a/docs/INSTALL.rst b/docs/INSTALL.rst
index 45652ab..f9492db 100644
--- a/docs/INSTALL.rst
+++ b/docs/INSTALL.rst
@@ -42,7 +42,7 @@
 To build ndn-cxx from source, one must first install a C++ compiler and all necessary
 development tools and libraries:
 
-- On **Ubuntu**
+- On **Debian** and **Ubuntu**
 
     In a terminal, enter::
 
@@ -98,7 +98,7 @@
 
       export PATH="${HOME}/.local/bin${PATH:+:}${PATH}"
 
-- On **Ubuntu**:
+- On **Debian** and **Ubuntu**:
 
   .. code-block:: sh
 
diff --git a/ndn-cxx/mgmt/nfd/controller.cpp b/ndn-cxx/mgmt/nfd/controller.cpp
index dbc0014..8d8f248 100644
--- a/ndn-cxx/mgmt/nfd/controller.cpp
+++ b/ndn-cxx/mgmt/nfd/controller.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2021 Regents of the University of California.
+ * Copyright (c) 2013-2022 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -66,9 +66,10 @@
     [=] (const Interest&, const Data& data) {
       processCommandResponse(data, command, onSuccess, onFailure);
     },
-    [=] (const Interest&, const lp::Nack&) {
+    [=] (const Interest&, const lp::Nack& nack) {
       if (onFailure)
-        onFailure(ControlResponse(Controller::ERROR_NACK, "network Nack received"));
+        onFailure(ControlResponse(Controller::ERROR_NACK,
+                                  "received Nack: " + boost::lexical_cast<std::string>(nack.getReason())));
     },
     [=] (const Interest&) {
       if (onFailure)
@@ -159,8 +160,8 @@
   }
 
   auto it = m_fetchers.insert(fetcher).first;
-  fetcher->onComplete.connect([this, it] (ConstBufferPtr) { m_fetchers.erase(it); });
-  fetcher->onError.connect([this, it] (uint32_t, const std::string&) { m_fetchers.erase(it); });
+  fetcher->onComplete.connect([this, it] (auto&&...) { m_fetchers.erase(it); });
+  fetcher->onError.connect([this, it] (auto&&...) { m_fetchers.erase(it); });
 }
 
 void
diff --git a/ndn-cxx/security/certificate-fetcher-direct-fetch.cpp b/ndn-cxx/security/certificate-fetcher-direct-fetch.cpp
index abfc636..06c6a57 100644
--- a/ndn-cxx/security/certificate-fetcher-direct-fetch.cpp
+++ b/ndn-cxx/security/certificate-fetcher-direct-fetch.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2020 Regents of the University of California.
+ * Copyright (c) 2013-2022 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -46,8 +46,8 @@
                                        const shared_ptr<ValidationState>& state,
                                        const ValidationContinuation& continueValidation)
 {
-  auto interestState = dynamic_pointer_cast<InterestValidationState>(state);
   uint64_t incomingFaceId = 0;
+  auto interestState = dynamic_pointer_cast<InterestValidationState>(state);
   if (interestState != nullptr) {
     auto incomingFaceIdTag = interestState->getOriginalInterest().getTag<lp::IncomingFaceIdTag>();
     if (incomingFaceIdTag != nullptr) {
@@ -61,6 +61,7 @@
       incomingFaceId = incomingFaceIdTag->get();
     }
   }
+
   if (incomingFaceId != 0) {
     Interest directInterest(keyRequest->interest);
     directInterest.refreshNonce();
@@ -89,8 +90,7 @@
     CertificateFetcherFromNetwork::doFetch(keyRequest, state, continueValidation);
   }
   else if (incomingFaceId == 0) {
-    state->fail({ValidationError::Code::CANNOT_RETRIEVE_CERT,
-          "Cannot direct fetch certificate as IncomingFaceId tag is not set"});
+    state->fail({ValidationError::CANNOT_RETRIEVE_CERT, "IncomingFaceId not set"});
   }
 }
 
diff --git a/ndn-cxx/security/certificate-fetcher-from-network.cpp b/ndn-cxx/security/certificate-fetcher-from-network.cpp
index a117ee4..65c70c9 100644
--- a/ndn-cxx/security/certificate-fetcher-from-network.cpp
+++ b/ndn-cxx/security/certificate-fetcher-from-network.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2020 Regents of the University of California.
+ * Copyright (c) 2013-2022 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -71,8 +71,7 @@
     cert = Certificate(data);
   }
   catch (const tlv::Error& e) {
-    return state->fail({ValidationError::Code::MALFORMED_CERT, "Fetched a malformed certificate "
-                        "`" + data.getName().toUri() + "` (" + e.what() + ")"});
+    return state->fail({ValidationError::MALFORMED_CERT, "`" + data.getName().toUri() + "`: " + e.what()});
   }
   continueValidation(cert, state);
 }
@@ -83,7 +82,7 @@
                                             const shared_ptr<ValidationState>& state,
                                             const ValidationContinuation& continueValidation)
 {
-  NDN_LOG_DEBUG_DEPTH("NACK (" << nack.getReason() <<  ") while fetching certificate "
+  NDN_LOG_DEBUG_DEPTH("Nack (" << nack.getReason() << ") while fetching certificate "
                       << certRequest->interest.getName());
 
   --certRequest->nRetriesLeft;
@@ -93,8 +92,8 @@
     certRequest->waitAfterNack *= 2;
   }
   else {
-    state->fail({ValidationError::Code::CANNOT_RETRIEVE_CERT, "Cannot fetch certificate after all "
-                 "retries `" + certRequest->interest.getName().toUri() + "`"});
+    state->fail({ValidationError::CANNOT_RETRIEVE_CERT, "Nack after exhausting all retries for "
+                 "`" + certRequest->interest.getName().toUri() + "`"});
   }
 }
 
@@ -103,16 +102,15 @@
                                                const shared_ptr<ValidationState>& state,
                                                const ValidationContinuation& continueValidation)
 {
-  NDN_LOG_DEBUG_DEPTH("Timeout while fetching certificate " << certRequest->interest.getName()
-                      << ", retrying");
+  NDN_LOG_DEBUG_DEPTH("Timeout while fetching certificate " << certRequest->interest.getName());
 
   --certRequest->nRetriesLeft;
   if (certRequest->nRetriesLeft >= 0) {
     fetch(certRequest, state, continueValidation);
   }
   else {
-    state->fail({ValidationError::Code::CANNOT_RETRIEVE_CERT, "Cannot fetch certificate after all "
-                 "retries `" + certRequest->interest.getName().toUri() + "`"});
+    state->fail({ValidationError::CANNOT_RETRIEVE_CERT, "Timeout after exhausting all retries for "
+                 "`" + certRequest->interest.getName().toUri() + "`"});
   }
 }
 
diff --git a/ndn-cxx/security/certificate-fetcher-offline.cpp b/ndn-cxx/security/certificate-fetcher-offline.cpp
index ea19a73..a613a9e 100644
--- a/ndn-cxx/security/certificate-fetcher-offline.cpp
+++ b/ndn-cxx/security/certificate-fetcher-offline.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2020 Regents of the University of California.
+ * Copyright (c) 2013-2022 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -32,8 +32,8 @@
                                    const shared_ptr<ValidationState>& state,
                                    const ValidationContinuation&)
 {
-  state->fail({ValidationError::Code::CANNOT_RETRIEVE_CERT,
-               "Cannot fetch certificate " + certRequest->interest.getName().toUri() + " in offline mode"});
+  state->fail({ValidationError::CANNOT_RETRIEVE_CERT,
+               "Cannot fetch `" + certRequest->interest.getName().toUri() + "` in offline mode"});
 }
 
 } // inline namespace v2
diff --git a/ndn-cxx/security/validation-callback.hpp b/ndn-cxx/security/validation-callback.hpp
index 23018eb..8e00c33 100644
--- a/ndn-cxx/security/validation-callback.hpp
+++ b/ndn-cxx/security/validation-callback.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2021 Regents of the University of California.
+ * Copyright (c) 2013-2022 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -24,7 +24,6 @@
 
 #include "ndn-cxx/data.hpp"
 #include "ndn-cxx/interest.hpp"
-#include "ndn-cxx/security/security-common.hpp"
 #include "ndn-cxx/security/validation-error.hpp"
 
 namespace ndn {
@@ -34,22 +33,22 @@
 /**
  * @brief Callback to report a successful Data validation.
  */
-typedef function<void(const Data& data)> DataValidationSuccessCallback;
+using DataValidationSuccessCallback = std::function<void(const Data&)>;
 
 /**
  * @brief Callback to report a failed Data validation.
  */
-typedef function<void(const Data& data, const ValidationError& error)> DataValidationFailureCallback;
+using DataValidationFailureCallback = std::function<void(const Data&, const ValidationError&)>;
 
 /**
  * @brief Callback to report a successful Interest validation.
  */
-typedef function<void(const Interest& interest)> InterestValidationSuccessCallback;
+using InterestValidationSuccessCallback = std::function<void(const Interest&)>;
 
 /**
  * @brief Callback to report a failed Interest validation.
  */
-typedef function<void(const Interest& interest, const ValidationError& error)> InterestValidationFailureCallback;
+using InterestValidationFailureCallback = std::function<void(const Interest&, const ValidationError&)>;
 
 } // inline namespace v2
 } // namespace security
diff --git a/ndn-cxx/security/validation-error.cpp b/ndn-cxx/security/validation-error.cpp
index 102cb30..b32ce5a 100644
--- a/ndn-cxx/security/validation-error.cpp
+++ b/ndn-cxx/security/validation-error.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2020 Regents of the University of California.
+ * Copyright (c) 2013-2022 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -21,8 +21,6 @@
 
 #include "ndn-cxx/security/validation-error.hpp"
 
-#include <ostream>
-
 namespace ndn {
 namespace security {
 inline namespace v2 {
@@ -31,29 +29,29 @@
 operator<<(std::ostream& os, ValidationError::Code code)
 {
   switch (code) {
-    case ValidationError::Code::NO_ERROR:
+    case ValidationError::NO_ERROR:
       return os << "No error";
-    case ValidationError::Code::INVALID_SIGNATURE:
+    case ValidationError::INVALID_SIGNATURE:
       return os << "Invalid signature";
-    case ValidationError::Code::NO_SIGNATURE:
+    case ValidationError::NO_SIGNATURE:
       return os << "Missing signature";
-    case ValidationError::Code::CANNOT_RETRIEVE_CERT:
+    case ValidationError::CANNOT_RETRIEVE_CERT:
       return os << "Cannot retrieve certificate";
-    case ValidationError::Code::EXPIRED_CERT:
-      return os << "Certificate expired";
-    case ValidationError::Code::LOOP_DETECTED:
+    case ValidationError::EXPIRED_CERT:
+      return os << "Certificate expired or not yet valid";
+    case ValidationError::LOOP_DETECTED:
       return os << "Loop detected in certification chain";
-    case ValidationError::Code::MALFORMED_CERT:
+    case ValidationError::MALFORMED_CERT:
       return os << "Malformed certificate";
-    case ValidationError::Code::EXCEEDED_DEPTH_LIMIT:
+    case ValidationError::EXCEEDED_DEPTH_LIMIT:
       return os << "Exceeded validation depth limit";
-    case ValidationError::Code::INVALID_KEY_LOCATOR:
+    case ValidationError::INVALID_KEY_LOCATOR:
       return os << "Key locator violates validation policy";
-    case ValidationError::Code::POLICY_ERROR:
+    case ValidationError::POLICY_ERROR:
       return os << "Validation policy error";
-    case ValidationError::Code::IMPLEMENTATION_ERROR:
-      return os << "Internal implementation error";
-    case ValidationError::Code::USER_MIN:
+    case ValidationError::IMPLEMENTATION_ERROR:
+      return os << "Internal error";
+    case ValidationError::USER_MIN:
       break;
   }
   if (code >= ValidationError::Code::USER_MIN) {
@@ -64,14 +62,13 @@
   }
 }
 
-std::ostream&
-operator<<(std::ostream& os, const ValidationError& error)
+void
+ValidationError::print(std::ostream& os) const
 {
-  os << static_cast<ValidationError::Code>(error.getCode());
-  if (!error.getInfo().empty()) {
-    os << " (" << error.getInfo() << ")";
+  os << static_cast<ValidationError::Code>(m_code);
+  if (!m_info.empty()) {
+    os << " (" << m_info << ")";
   }
-  return os;
 }
 
 } // inline namespace v2
diff --git a/ndn-cxx/security/validation-error.hpp b/ndn-cxx/security/validation-error.hpp
index 5c0c3ae..bc68b4e 100644
--- a/ndn-cxx/security/validation-error.hpp
+++ b/ndn-cxx/security/validation-error.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2021 Regents of the University of California.
+ * Copyright (c) 2013-2022 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -50,12 +50,11 @@
     INVALID_KEY_LOCATOR  = 8,
     POLICY_ERROR         = 9,
     IMPLEMENTATION_ERROR = 255,
-    USER_MIN             = 256 // custom error codes should use >=256
+    USER_MIN             = 256, // custom error codes should use >=256
   };
 
-public:
   /**
-   * @brief Validation error, implicitly convertible from an error code and info
+   * @brief Validation error, implicitly convertible from an error code and info string
    */
   ValidationError(uint32_t code, const std::string& info = "")
     : m_code(code)
@@ -76,6 +75,18 @@
   }
 
 private:
+  void
+  print(std::ostream& os) const;
+
+  // hidden friend non-member operator, must be defined inline
+  friend std::ostream&
+  operator<<(std::ostream& os, const ValidationError& err)
+  {
+    err.print(os);
+    return os;
+  }
+
+private:
   uint32_t m_code;
   std::string m_info;
 };
@@ -83,9 +94,6 @@
 std::ostream&
 operator<<(std::ostream& os, ValidationError::Code code);
 
-std::ostream&
-operator<<(std::ostream& os, const ValidationError& error);
-
 } // inline namespace v2
 } // namespace security
 } // namespace ndn
diff --git a/ndn-cxx/security/validation-policy-command-interest.cpp b/ndn-cxx/security/validation-policy-command-interest.cpp
index 8da3d68..3ee2cb8 100644
--- a/ndn-cxx/security/validation-policy-command-interest.cpp
+++ b/ndn-cxx/security/validation-policy-command-interest.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2020 Regents of the University of California.
+ * Copyright (c) 2013-2022 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -93,7 +93,7 @@
     // TODO: Refactor to support other/combinations of the restrictions based on Nonce, Time, and/or SeqNum
     if (!optionalTimestamp) {
       state->fail({ValidationError::POLICY_ERROR, "Signed Interest `" +
-                   interest.getName().toUri() + "` doesn't include required SignatureTime element"});
+                   interest.getName().toUri() + "` does not include required SignatureTime element"});
       return std::make_tuple(false, Name(), time::system_clock::TimePoint{});
     }
     timestamp = *optionalTimestamp;
@@ -106,10 +106,10 @@
       return std::make_tuple(false, Name(), time::system_clock::TimePoint{});
     }
 
-    const name::Component& timestampComp = name.at(command_interest::POS_TIMESTAMP);
+    const auto& timestampComp = name.at(command_interest::POS_TIMESTAMP);
     if (!timestampComp.isNumber()) {
       state->fail({ValidationError::POLICY_ERROR, "Command interest `" +
-                   interest.getName().toUri() + "` doesn't include timestamp component"});
+                   interest.getName().toUri() + "` does not include timestamp component"});
       return std::make_tuple(false, Name(), time::system_clock::TimePoint{});
     }
     timestamp = time::fromUnixTimestamp(time::milliseconds(timestampComp.toNumber()));
diff --git a/ndn-cxx/security/validation-policy-config.cpp b/ndn-cxx/security/validation-policy-config.cpp
index 4cf0f44..18ed830 100644
--- a/ndn-cxx/security/validation-policy-config.cpp
+++ b/ndn-cxx/security/validation-policy-config.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2021 Regents of the University of California.
+ * Copyright (c) 2013-2022 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -294,11 +294,10 @@
 
         SignatureInfo si;
         try {
-          si.wireDecode(interest.getName().at(signed_interest::POS_SIG_INFO).blockFromValue());
+          si.wireDecode(interest.getName()[signed_interest::POS_SIG_INFO].blockFromValue());
         }
         catch (const tlv::Error& e) {
-          state->fail({ValidationError::Code::INVALID_KEY_LOCATOR,
-                       "Invalid signed Interest: " + std::string(e.what())});
+          state->fail({ValidationError::INVALID_KEY_LOCATOR, "Invalid signed Interest: "s + e.what()});
           return;
         }
 
diff --git a/ndn-cxx/security/validation-policy-simple-hierarchy.cpp b/ndn-cxx/security/validation-policy-simple-hierarchy.cpp
index 95b24f9..40f554f 100644
--- a/ndn-cxx/security/validation-policy-simple-hierarchy.cpp
+++ b/ndn-cxx/security/validation-policy-simple-hierarchy.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2020 Regents of the University of California.
+ * Copyright (c) 2013-2022 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -41,12 +41,12 @@
     }
   }
   catch (const KeyLocator::Error& e) {
-    state->fail({ValidationError::Code::INVALID_KEY_LOCATOR, e.what()});
+    state->fail({ValidationError::INVALID_KEY_LOCATOR, e.what()});
     return;
   }
 
-  state->fail({ValidationError::Code::INVALID_KEY_LOCATOR, "Data signing policy violation for " +
-        data.getName().toUri() + " by " + klName.toUri()});
+  state->fail({ValidationError::INVALID_KEY_LOCATOR, "Data signing policy violation for " +
+               data.getName().toUri() + " by " + klName.toUri()});
 }
 
 void
@@ -65,12 +65,12 @@
     }
   }
   catch (const KeyLocator::Error& e) {
-    state->fail({ValidationError::Code::INVALID_KEY_LOCATOR, e.what()});
+    state->fail({ValidationError::INVALID_KEY_LOCATOR, e.what()});
     return;
   }
 
-  state->fail({ValidationError::Code::INVALID_KEY_LOCATOR, "Interest signing policy violation for " +
-        interest.getName().toUri() + " by " + klName.toUri()});
+  state->fail({ValidationError::INVALID_KEY_LOCATOR, "Interest signing policy violation for " +
+               interest.getName().toUri() + " by " + klName.toUri()});
 }
 
 } // inline namespace v2
diff --git a/ndn-cxx/security/validation-policy.cpp b/ndn-cxx/security/validation-policy.cpp
index 969d403..8b8fabc 100644
--- a/ndn-cxx/security/validation-policy.cpp
+++ b/ndn-cxx/security/validation-policy.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2020 Regents of the University of California.
+ * Copyright (c) 2013-2022 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -68,14 +68,14 @@
   }
 
   if (!si.hasKeyLocator()) {
-    state.fail({ValidationError::Code::INVALID_KEY_LOCATOR, "KeyLocator is missing"});
-    return Name();
+    state.fail({ValidationError::INVALID_KEY_LOCATOR, "KeyLocator is missing"});
+    return {};
   }
 
   const KeyLocator& kl = si.getKeyLocator();
   if (kl.getType() != tlv::Name) {
-    state.fail({ValidationError::Code::INVALID_KEY_LOCATOR, "KeyLocator type is not Name"});
-    return Name();
+    state.fail({ValidationError::INVALID_KEY_LOCATOR, "KeyLocator type is not Name"});
+    return {};
   }
 
   return kl.getName();
@@ -102,17 +102,16 @@
   const Name& name = interest.getName();
   if (name.size() < signed_interest::MIN_SIZE) {
     state.fail({ValidationError::INVALID_KEY_LOCATOR, "Invalid signed Interest: name too short"});
-    return Name();
+    return {};
   }
 
   SignatureInfo si;
   try {
-    si.wireDecode(name.at(signed_interest::POS_SIG_INFO).blockFromValue());
+    si.wireDecode(name[signed_interest::POS_SIG_INFO].blockFromValue());
   }
   catch (const tlv::Error& e) {
-    state.fail({ValidationError::Code::INVALID_KEY_LOCATOR,
-                "Invalid signed Interest: " + std::string(e.what())});
-    return Name();
+    state.fail({ValidationError::INVALID_KEY_LOCATOR, "Invalid signed Interest: "s + e.what()});
+    return {};
   }
 
   return getKeyLocatorName(si, state);
diff --git a/ndn-cxx/security/validation-state.cpp b/ndn-cxx/security/validation-state.cpp
index 4bb1ab9..b926fd7 100644
--- a/ndn-cxx/security/validation-state.cpp
+++ b/ndn-cxx/security/validation-state.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2021 Regents of the University of California.
+ * Copyright (c) 2013-2022 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -33,23 +33,12 @@
 #define NDN_LOG_DEBUG_DEPTH(x) NDN_LOG_DEBUG(std::string(this->getDepth() + 1, '>') << " " << x)
 #define NDN_LOG_TRACE_DEPTH(x) NDN_LOG_TRACE(std::string(this->getDepth() + 1, '>') << " " << x)
 
-ValidationState::ValidationState()
-  : m_outcome(boost::logic::indeterminate)
-{
-}
-
 ValidationState::~ValidationState()
 {
   NDN_LOG_TRACE(__func__);
   BOOST_ASSERT(!boost::logic::indeterminate(m_outcome));
 }
 
-size_t
-ValidationState::getDepth() const
-{
-  return m_certificateChain.size();
-}
-
 bool
 ValidationState::hasSeenCertificateName(const Name& certName)
 {
@@ -70,7 +59,7 @@
     const auto& certToValidate = *it;
 
     if (!verifySignature(certToValidate, *validatedCert)) {
-      this->fail({ValidationError::Code::INVALID_SIGNATURE, "Invalid signature of certificate `" +
+      this->fail({ValidationError::INVALID_SIGNATURE, "Invalid signature of certificate `" +
                   certToValidate.getName().toUri() + "`"});
       m_certificateChain.erase(it, m_certificateChain.end());
       return nullptr;
@@ -99,7 +88,7 @@
 DataValidationState::~DataValidationState()
 {
   if (boost::logic::indeterminate(m_outcome)) {
-    this->fail({ValidationError::Code::IMPLEMENTATION_ERROR,
+    this->fail({ValidationError::IMPLEMENTATION_ERROR,
                 "Validator/policy did not invoke success or failure callback"});
   }
 }
@@ -114,7 +103,7 @@
     m_outcome = true;
   }
   else {
-    this->fail({ValidationError::Code::INVALID_SIGNATURE, "Invalid signature of data `" +
+    this->fail({ValidationError::INVALID_SIGNATURE, "Invalid signature of data `" +
                 m_data.getName().toUri() + "`"});
   }
 }
@@ -137,12 +126,6 @@
   m_outcome = false;
 }
 
-const Data&
-DataValidationState::getOriginalData() const
-{
-  return m_data;
-}
-
 /////// InterestValidationState
 
 InterestValidationState::InterestValidationState(const Interest& interest,
@@ -159,7 +142,7 @@
 InterestValidationState::~InterestValidationState()
 {
   if (boost::logic::indeterminate(m_outcome)) {
-    this->fail({ValidationError::Code::IMPLEMENTATION_ERROR,
+    this->fail({ValidationError::IMPLEMENTATION_ERROR,
                 "Validator/policy did not invoke success or failure callback"});
   }
 }
@@ -174,7 +157,7 @@
     m_outcome = true;
   }
   else {
-    this->fail({ValidationError::Code::INVALID_SIGNATURE, "Invalid signature of interest `" +
+    this->fail({ValidationError::INVALID_SIGNATURE, "Invalid signature of interest `" +
                 m_interest.getName().toUri() + "`"});
   }
 }
@@ -197,12 +180,6 @@
   m_outcome = false;
 }
 
-const Interest&
-InterestValidationState::getOriginalInterest() const
-{
-  return m_interest;
-}
-
 } // inline namespace v2
 } // namespace security
 } // namespace ndn
diff --git a/ndn-cxx/security/validation-state.hpp b/ndn-cxx/security/validation-state.hpp
index 83d7f94..aed0264 100644
--- a/ndn-cxx/security/validation-state.hpp
+++ b/ndn-cxx/security/validation-state.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2021 Regents of the University of California.
+ * Copyright (c) 2013-2022 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -59,16 +59,11 @@
 class ValidationState : public TagHost, noncopyable
 {
 public:
-  /**
-   * @brief Create validation state
-   */
-  ValidationState();
-
   virtual
   ~ValidationState();
 
   boost::logic::tribool
-  getOutcome() const
+  getOutcome() const noexcept
   {
     return m_outcome;
   }
@@ -83,7 +78,10 @@
    * @return Depth of certificate chain
    */
   size_t
-  getDepth() const;
+  getDepth() const noexcept
+  {
+    return m_certificateChain.size();
+  }
 
   /**
    * @brief Check if @p certName has been previously seen and record the supplied name
@@ -139,7 +137,7 @@
   verifyCertificateChain(const Certificate& trustedCert);
 
 protected:
-  boost::logic::tribool m_outcome;
+  boost::logic::tribool m_outcome{boost::logic::indeterminate};
 
 private:
   std::unordered_set<Name> m_seenCertificateNames;
@@ -186,7 +184,10 @@
    * @return Original data being validated
    */
   const Data&
-  getOriginalData() const;
+  getOriginalData() const
+  {
+    return m_data;
+  }
 
 private:
   void
@@ -232,7 +233,10 @@
    * @return Original interest being validated
    */
   const Interest&
-  getOriginalInterest() const;
+  getOriginalInterest() const
+  {
+    return m_interest;
+  }
 
 public:
   util::Signal<InterestValidationState, Interest> afterSuccess;
diff --git a/ndn-cxx/security/validator.cpp b/ndn-cxx/security/validator.cpp
index 2a86be4..ba00728 100644
--- a/ndn-cxx/security/validator.cpp
+++ b/ndn-cxx/security/validator.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2021 Regents of the University of California.
+ * Copyright (c) 2013-2022 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -20,11 +20,10 @@
  */
 
 #include "ndn-cxx/security/validator.hpp"
-
-#include "ndn-cxx/face.hpp"
-#include "ndn-cxx/security/transform/public-key.hpp"
 #include "ndn-cxx/util/logger.hpp"
 
+#include <boost/lexical_cast.hpp>
+
 namespace ndn {
 namespace security {
 inline namespace v2 {
@@ -37,7 +36,6 @@
 Validator::Validator(unique_ptr<ValidationPolicy> policy, unique_ptr<CertificateFetcher> certFetcher)
   : m_policy(std::move(policy))
   , m_certFetcher(std::move(certFetcher))
-  , m_maxDepth(25)
 {
   BOOST_ASSERT(m_policy != nullptr);
   BOOST_ASSERT(m_certFetcher != nullptr);
@@ -45,31 +43,7 @@
   m_certFetcher->setCertificateStorage(*this);
 }
 
-Validator::~Validator() = default;
-
-ValidationPolicy&
-Validator::getPolicy()
-{
-  return *m_policy;
-}
-
-CertificateFetcher&
-Validator::getFetcher()
-{
-  return *m_certFetcher;
-}
-
-void
-Validator::setMaxDepth(size_t depth)
-{
-  m_maxDepth = depth;
-}
-
-size_t
-Validator::getMaxDepth() const
-{
-  return m_maxDepth;
-}
+Validator::~Validator() noexcept = default;
 
 void
 Validator::validate(const Data& data,
@@ -77,10 +51,11 @@
                     const DataValidationFailureCallback& failureCb)
 {
   auto state = make_shared<DataValidationState>(data, successCb, failureCb);
+
   NDN_LOG_DEBUG_DEPTH("Start validating data " << data.getName());
 
   m_policy->checkPolicy(data, state,
-      [this] (const shared_ptr<CertificateRequest>& certRequest, const shared_ptr<ValidationState>& state) {
+    [this] (const shared_ptr<CertificateRequest>& certRequest, const shared_ptr<ValidationState>& state) {
       if (certRequest == nullptr) {
         state->bypassValidation();
       }
@@ -97,14 +72,13 @@
                     const InterestValidationFailureCallback& failureCb)
 {
   auto state = make_shared<InterestValidationState>(interest, successCb, failureCb);
-
   auto fmt = interest.getSignatureInfo() ? SignedInterestFormat::V03 : SignedInterestFormat::V02;
   state->setTag(make_shared<SignedInterestFormatTag>(fmt));
 
   NDN_LOG_DEBUG_DEPTH("Start validating interest (" << fmt << ") " << interest.getName());
 
   m_policy->checkPolicy(interest, state,
-      [this] (const shared_ptr<CertificateRequest>& certRequest, const shared_ptr<ValidationState>& state) {
+    [this] (const shared_ptr<CertificateRequest>& certRequest, const shared_ptr<ValidationState>& state) {
       if (certRequest == nullptr) {
         state->bypassValidation();
       }
@@ -121,12 +95,12 @@
   NDN_LOG_DEBUG_DEPTH("Start validating certificate " << cert.getName());
 
   if (!cert.isValid()) {
-    return state->fail({ValidationError::Code::EXPIRED_CERT, "Retrieved certificate is not yet valid or expired "
-          "`" + cert.getName().toUri() + "`"});
+    return state->fail({ValidationError::EXPIRED_CERT, "`" + cert.getName().toUri() + "` is valid "
+                        "between " + boost::lexical_cast<std::string>(cert.getValidityPeriod())});
   }
 
   m_policy->checkPolicy(cert, state,
-      [this, cert] (const shared_ptr<CertificateRequest>& certRequest, const shared_ptr<ValidationState>& state) {
+    [this, cert] (const shared_ptr<CertificateRequest>& certRequest, const shared_ptr<ValidationState>& state) {
       if (certRequest == nullptr) {
         state->fail({ValidationError::POLICY_ERROR, "Validation policy is not allowed to designate `" +
                      cert.getName().toUri() + "` as a trust anchor"});
@@ -143,10 +117,8 @@
 Validator::requestCertificate(const shared_ptr<CertificateRequest>& certRequest,
                               const shared_ptr<ValidationState>& state)
 {
-  // TODO configurable check for the maximum number of steps
   if (state->getDepth() >= m_maxDepth) {
-    state->fail({ValidationError::Code::EXCEEDED_DEPTH_LIMIT,
-                 "Exceeded validation depth limit (" + to_string(m_maxDepth) + ")"});
+    state->fail({ValidationError::EXCEEDED_DEPTH_LIMIT, to_string(m_maxDepth)});
     return;
   }
 
@@ -156,8 +128,7 @@
   }
 
   if (state->hasSeenCertificateName(certRequest->interest.getName())) {
-    state->fail({ValidationError::Code::LOOP_DETECTED,
-                 "Validation loop detected for certificate `" + certRequest->interest.getName().toUri() + "`"});
+    state->fail({ValidationError::LOOP_DETECTED, "`" + certRequest->interest.getName().toUri() + "`"});
     return;
   }
 
@@ -179,9 +150,9 @@
     return;
   }
 
-  m_certFetcher->fetch(certRequest, state, [this] (const Certificate& cert, const shared_ptr<ValidationState>& state) {
-      validate(cert, state);
-    });
+  m_certFetcher->fetch(certRequest, state, [this] (auto&&... args) {
+    validate(std::forward<decltype(args)>(args)...);
+  });
 }
 
 ////////////////////////////////////////////////////////////////////////
diff --git a/ndn-cxx/security/validator.hpp b/ndn-cxx/security/validator.hpp
index 46712c7..1e453ec 100644
--- a/ndn-cxx/security/validator.hpp
+++ b/ndn-cxx/security/validator.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2021 Regents of the University of California.
+ * Copyright (c) 2013-2022 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -64,30 +64,42 @@
   /**
    * @brief Validator constructor.
    *
-   * @param policy      Validation policy to be associated with the validator
+   * @param policy      Validation policy to be associated with the validator.
    * @param certFetcher Certificate fetcher implementation.
    */
   Validator(unique_ptr<ValidationPolicy> policy, unique_ptr<CertificateFetcher> certFetcher);
 
-  ~Validator();
+  ~Validator() noexcept;
 
   ValidationPolicy&
-  getPolicy();
+  getPolicy() const noexcept
+  {
+    return *m_policy;
+  }
 
   CertificateFetcher&
-  getFetcher();
+  getFetcher() const noexcept
+  {
+    return *m_certFetcher;
+  }
 
   /**
-   * @brief Set the maximum depth of the certificate chain
-   */
-  void
-  setMaxDepth(size_t depth);
-
-  /**
-   * @return The maximum depth of the certificate chain
+   * @brief Return the maximum depth of the certificate chain.
    */
   size_t
-  getMaxDepth() const;
+  getMaxDepth() const noexcept
+  {
+    return m_maxDepth;
+  }
+
+  /**
+   * @brief Set the maximum depth of the certificate chain.
+   */
+  void
+  setMaxDepth(size_t depth) noexcept
+  {
+    m_maxDepth = depth;
+  }
 
   /**
    * @brief Asynchronously validate @p data
@@ -179,7 +191,7 @@
 private:
   unique_ptr<ValidationPolicy> m_policy;
   unique_ptr<CertificateFetcher> m_certFetcher;
-  size_t m_maxDepth;
+  size_t m_maxDepth{25};
 };
 
 } // inline namespace v2
diff --git a/tests/unit/security/certificate-fetcher-direct-fetch.t.cpp b/tests/unit/security/certificate-fetcher-direct-fetch.t.cpp
index bc134a1..183a947 100644
--- a/tests/unit/security/certificate-fetcher-direct-fetch.t.cpp
+++ b/tests/unit/security/certificate-fetcher-direct-fetch.t.cpp
@@ -216,7 +216,7 @@
 
   VALIDATE_FAILURE(this->data, "Should fail, as no interests are expected");
   BOOST_CHECK_EQUAL(this->face.sentInterests.size(), 0);
-  BOOST_CHECK(this->lastError.getCode() != ValidationError::Code::IMPLEMENTATION_ERROR);
+  BOOST_CHECK_NE(this->lastError.getCode(), ValidationError::IMPLEMENTATION_ERROR);
 }
 
 BOOST_FIXTURE_TEST_CASE(ValidateSuccessInterest, CertificateFetcherDirectFetchFixture<Cert>)
diff --git a/tests/unit/security/validation-error.t.cpp b/tests/unit/security/validation-error.t.cpp
index 6ecb94f..6c1b5f7 100644
--- a/tests/unit/security/validation-error.t.cpp
+++ b/tests/unit/security/validation-error.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2020 Regents of the University of California.
+ * Copyright (c) 2013-2022 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -34,12 +34,12 @@
 
 BOOST_AUTO_TEST_CASE(Basic)
 {
-  ValidationError e1{ValidationError::Code::INVALID_SIGNATURE};
+  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");
 
-  ValidationError e2{ValidationError::Code::NO_SIGNATURE, "message"};
+  ValidationError e2{ValidationError::NO_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)");
diff --git a/tests/unit/security/validator-fixture.hpp b/tests/unit/security/validator-fixture.hpp
index 25cbe93..b225c53 100644
--- a/tests/unit/security/validator-fixture.hpp
+++ b/tests/unit/security/validator-fixture.hpp
@@ -68,7 +68,7 @@
   util::DummyClientFace face{m_io, {true, true}};
   std::function<void(const Interest&)> processInterest;
   CertificateCache cache{100_days};
-  ValidationError lastError{ValidationError::Code::NO_ERROR};
+  ValidationError lastError{ValidationError::NO_ERROR};
 
 private:
   const static time::milliseconds s_mockPeriod;