security: Split KeyChain into signing (KeyChain) and verification (Verifier) interfaces

This split removes the need for IdentityManager.

Also in this commit: Make verifySignature methods a set of static methods of Verifier.

Change-Id: Iea1c4353857a21417b2dcd1f91ba7013995d1459
diff --git a/src/security/verifier.cpp b/src/security/verifier.cpp
new file mode 100644
index 0000000..67a1f33
--- /dev/null
+++ b/src/security/verifier.cpp
@@ -0,0 +1,139 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/**
+ * Copyright (C) 2013 Regents of the University of California.
+ * @author: Yingdi Yu <yingdi@cs.ucla.edu>
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * See COPYING for copyright and distribution information.
+ */
+
+#if __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wreorder"
+#pragma clang diagnostic ignored "-Wtautological-compare"
+#pragma clang diagnostic ignored "-Wunused-variable"
+#pragma clang diagnostic ignored "-Wunused-function"
+#elif __GNUC__
+#pragma GCC diagnostic ignored "-Wreorder"
+#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-function"
+#endif
+
+#include <ndn-cpp/security/verifier.hpp>
+
+#include <ndn-cpp/security/policy/policy-manager.hpp>
+
+#include <cryptopp/rsa.h>
+
+#include "../util/logging.hpp"
+
+using namespace std;
+using namespace ndn::func_lib;
+#if NDN_CPP_HAVE_CXX11
+// In the std library, the placeholders are in a different namespace than boost.
+using namespace ndn::func_lib::placeholders;
+#endif
+
+INIT_LOGGER("ndn.Verifier");
+
+namespace ndn {
+const ptr_lib::shared_ptr<PolicyManager>     Verifier::DefaultPolicyManager     = ptr_lib::shared_ptr<PolicyManager>();
+
+Verifier::Verifier(const ptr_lib::shared_ptr<PolicyManager>     &policyManager     /* = DefaultPolicyManager */)                   
+  : policyManager_(policyManager)
+{
+  if (policyManager_ == DefaultPolicyManager)
+    {
+      // #ifdef USE_SIMPLE_POLICY_MANAGER
+      //   Ptr<SimplePolicyManager> policyManager = Ptr<SimplePolicyManager>(new SimplePolicyManager());
+      //   Ptr<IdentityPolicyRule> rule1 = Ptr<IdentityPolicyRule>(new IdentityPolicyRule("^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>",
+      //                                                                                  "^([^<KEY>]*)<KEY><dsk-.*><ID-CERT>",
+      //                                                                                  ">", "\\1\\2", "\\1", true));
+      //   Ptr<IdentityPolicyRule> rule2 = Ptr<IdentityPolicyRule>(new IdentityPolicyRule("^([^<KEY>]*)<KEY><dsk-.*><ID-CERT>",
+      //                                                                                  "^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>",
+      //                                                                                  "==", "\\1", "\\1\\2", true));
+      //   Ptr<IdentityPolicyRule> rule3 = Ptr<IdentityPolicyRule>(new IdentityPolicyRule("^(<>*)$", 
+      //                                                                                  "^([^<KEY>]*)<KEY><dsk-.*><ID-CERT>", 
+      //                                                                                  ">", "\\1", "\\1", true));
+      //   policyManager->addVerificationPolicyRule(rule1);
+      //   policyManager->addVerificationPolicyRule(rule2);
+      //   policyManager->addVerificationPolicyRule(rule3);
+    
+      //   policyManager->addSigningPolicyRule(rule3);
+
+      //   m_policyManager = policyManager;
+      //
+      // #else
+      //   policyManager_ = new NoVerifyPolicyManager();
+      // #endif
+    }  
+}
+
+void
+Verifier::verifyData
+  (const ptr_lib::shared_ptr<Data>& data, const OnVerified& onVerified, const OnVerifyFailed& onVerifyFailed, int stepCount)
+{
+  if (policies().requireVerify(*data)) {
+    ptr_lib::shared_ptr<ValidationRequest> nextStep = policyManager_->checkVerificationPolicy
+      (data, stepCount, onVerified, onVerifyFailed);
+    if (static_cast<bool>(nextStep))
+      {
+        if (!face_)
+          throw Error("Face should be set prior to verifyData method to call");
+        
+        face_->expressInterest
+          (*nextStep->interest_, 
+           bind(&Verifier::onCertificateData, this, _1, _2, nextStep), 
+           bind(&Verifier::onCertificateInterestTimeout, this, _1, nextStep->retry_, onVerifyFailed, data, nextStep));
+      }
+  }
+  else if (policies().skipVerifyAndTrust(*data))
+    onVerified(data);
+  else
+    onVerifyFailed(data);
+}
+
+void
+Verifier::onCertificateData(const ptr_lib::shared_ptr<const Interest> &interest, const ptr_lib::shared_ptr<Data> &data, ptr_lib::shared_ptr<ValidationRequest> nextStep)
+{
+  // Try to verify the certificate (data) according to the parameters in nextStep.
+  verifyData(data, nextStep->onVerified_, nextStep->onVerifyFailed_, nextStep->stepCount_);
+}
+
+void
+Verifier::onCertificateInterestTimeout
+  (const ptr_lib::shared_ptr<const Interest> &interest, int retry, const OnVerifyFailed& onVerifyFailed, const ptr_lib::shared_ptr<Data> &data, 
+   ptr_lib::shared_ptr<ValidationRequest> nextStep)
+{
+  if (retry > 0)
+    // Issue the same expressInterest as in verifyData except decrement retry.
+    face_->expressInterest
+      (*interest, 
+       bind(&Verifier::onCertificateData, this, _1, _2, nextStep), 
+       bind(&Verifier::onCertificateInterestTimeout, this, _1, retry - 1, onVerifyFailed, data, nextStep));
+  else
+    onVerifyFailed(data);
+}
+
+bool
+Verifier::verifySignature(const Data& data, const SignatureSha256WithRsa& sig, const PublicKey& key)
+{
+  using namespace CryptoPP;
+
+  bool result = false;
+  
+  RSA::PublicKey publicKey;
+  ByteQueue queue;
+
+  queue.Put(reinterpret_cast<const byte*>(key.get().buf()), key.get().size());
+  publicKey.Load(queue);
+
+  RSASS<PKCS1v15, SHA256>::Verifier verifier (publicKey);
+  result = verifier.VerifyMessage(data.wireEncode().value(), data.wireEncode().value_size() - data.getSignature().getValue().size(),
+				  sig.getValue().value(), sig.getValue().value_size());
+
+  _LOG_DEBUG("Signature verified? " << data.getName().toUri() << " " << boolalpha << result);
+  
+  return result;
+}
+
+}