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;
+}
+
+}