security: Merging SecPolicy into Validator (previously Verifier)

Change-Id: I469fc8f823406cb217bf85248d38d241c32f31f0
diff --git a/src/security/validator.cpp b/src/security/validator.cpp
new file mode 100644
index 0000000..9440d84
--- /dev/null
+++ b/src/security/validator.cpp
@@ -0,0 +1,272 @@
+/* -*- 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 "validator.hpp"
+#include "../util/logging.hpp"
+
+#include <cryptopp/rsa.h>
+
+using namespace std;
+
+INIT_LOGGER("ndn::Validator");
+
+namespace ndn {
+
+const shared_ptr<Face> Validator::DefaultFace = shared_ptr<Face>();
+
+Validator::Validator(shared_ptr<Face> face /* = DefaultFace */)                   
+  : m_face(face)
+{}
+
+void
+Validator::validate(const shared_ptr<const Interest> &interest, 
+                    const OnInterestValidated &onValidated, 
+                    const OnInterestValidationFailed &onValidationFailed,
+                    int stepCount)
+{
+  vector<shared_ptr<ValidationRequest> > nextSteps;
+  checkPolicy(interest, stepCount, onValidated, onValidationFailed, nextSteps);
+  
+  if (!nextSteps.empty())
+    {
+      if(!static_cast<bool>(m_face))
+        throw Error("Face should be set prior to verify method to call");
+      
+      vector<shared_ptr<ValidationRequest> >::const_iterator it = nextSteps.begin();
+      OnFailure onFailure = bind(onValidationFailed, interest);
+      for(; it != nextSteps.end(); it++)
+        m_face->expressInterest((*it)->m_interest,
+                                bind(&Validator::onData, this, _1, _2, *it), 
+                                bind(&Validator::onTimeout, 
+                                     this, _1, (*it)->m_retry, 
+                                     onFailure, 
+                                     *it));
+    }
+  else
+    {
+      //If there is no nextStep, that means InterestPolicy has already been able to verify the Interest.
+      //No more further processes.
+    }
+}
+
+void
+Validator::validate(const shared_ptr<const Data> &data, 
+                    const OnDataValidated &onValidated, 
+                    const OnDataValidationFailed &onValidationFailed,
+                    int stepCount)
+{
+  vector<shared_ptr<ValidationRequest> > nextSteps;
+  checkPolicy(data, stepCount, onValidated, onValidationFailed, nextSteps);
+
+  if (!nextSteps.empty())
+    {
+      if(!static_cast<bool>(m_face))
+        throw Error("Face should be set prior to verify method to call");
+
+      vector<shared_ptr<ValidationRequest> >::const_iterator it = nextSteps.begin();
+      OnFailure onFailure = bind(onValidationFailed, data);
+      for(; it != nextSteps.end(); it++)
+        m_face->expressInterest((*it)->m_interest,
+                                bind(&Validator::onData, this, _1, _2, *it), 
+                                bind(&Validator::onTimeout, 
+                                     this, _1, (*it)->m_retry, 
+                                     onFailure,
+                                     *it));
+    }
+  else
+    {
+      //If there is no nextStep, that means InterestPolicy has already been able to verify the Interest.
+      //No more further processes.
+    }
+}
+
+void
+Validator::onData(const shared_ptr<const Interest> &interest, 
+                  const shared_ptr<const Data> &data, 
+                  shared_ptr<ValidationRequest> nextStep)
+{
+  validate(data, nextStep->m_onValidated, nextStep->m_onDataValidated, nextStep->m_stepCount);
+}
+
+void
+Validator::onTimeout(const shared_ptr<const Interest> &interest, 
+                     int retry, 
+                     const OnFailure &onFailure, 
+                     shared_ptr<ValidationRequest> nextStep)
+{
+  if (retry > 0)
+    // Issue the same expressInterest except decrement retry.
+    m_face->expressInterest(*interest, 
+                            bind(&Validator::onData, this, _1, _2, nextStep), 
+                            bind(&Validator::onTimeout, this, _1, retry - 1, onFailure, nextStep));
+  else
+    onFailure();
+}
+
+bool
+Validator::verifySignature(const Data& data, const PublicKey& key)
+{
+  try{
+    switch(data.getSignature().getType()){
+    case Signature::Sha256WithRsa:
+      {
+        SignatureSha256WithRsa sigSha256Rsa(data.getSignature());
+        return verifySignature(data, sigSha256Rsa, key);
+      }
+    default:
+      {
+        _LOG_DEBUG("verifySignature: Unknown signature type: " << sig.getType());
+        return false;
+      }
+    }
+  }catch(Signature::Error &e){
+    _LOG_DEBUG("verifySignature: " << e.what());
+    return false;
+  }
+  return false;
+}
+
+bool
+Validator::verifySignature(const Interest &interest, const PublicKey &key)
+{
+  const Name &interestName = interest.getName();
+
+  if(interestName.size() < 3)
+    return false;
+
+  try{
+    const Block &nameBlock = interestName.wireEncode();
+
+    if(nameBlock.getAll().size() != interestName.size()) //HACK!! we should change it when Name::Component is changed to derive from Block.
+      const_cast<Block&>(nameBlock).parse();
+
+    Signature sig((++nameBlock.getAll().rbegin())->blockFromValue(), 
+                  (nameBlock.getAll().rbegin())->blockFromValue());
+
+    switch(sig.getType()){
+    case Signature::Sha256WithRsa:
+      {
+        SignatureSha256WithRsa sigSha256Rsa(sig);
+
+        return verifySignature(nameBlock.value(), 
+                               nameBlock.value_size() - (nameBlock.getAll().rbegin())->size(), 
+                               sigSha256Rsa, key);
+      }
+    default:
+      {
+        _LOG_DEBUG("verifySignature: Unknown signature type: " << sig.getType());
+        return false;
+      }
+    }
+  }catch(Signature::Error &e){
+    _LOG_DEBUG("verifySignature: " << e.what());
+    return false;
+  }catch(Block::Error &e){
+    _LOG_DEBUG("verifySignature: " << e.what());
+    return false;
+  }
+  return false;
+}
+
+bool
+Validator::verifySignature(const Buffer &data, const Signature &sig, const PublicKey &key)
+{
+  try{
+    switch(sig.getType()){
+    case Signature::Sha256WithRsa:
+      {
+        SignatureSha256WithRsa sigSha256Rsa(sig);
+        return verifySignature(data, sigSha256Rsa, key);
+      }
+    default:
+      {
+        _LOG_DEBUG("verifySignature: Unknown signature type: " << sig.getType());
+        return false;
+      }
+    }
+  }catch(Signature::Error &e){
+    _LOG_DEBUG("verifySignature: " << e.what());
+    return false;
+  }
+  return false;
+}
+
+bool
+Validator::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;
+}
+
+bool
+Validator::verifySignature(const Buffer& 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.buf(), data.size(),
+				  sig.getValue().value(), sig.getValue().value_size());
+  
+  return result;
+}
+
+bool
+Validator::verifySignature(const uint8_t* buf, const size_t size, 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(buf, size, sig.getValue().value(), sig.getValue().value_size());
+  
+  return result;
+}
+
+}