blob: 62f660d936c754554484f750cdbb025cf0f994da [file] [log] [blame]
/* -*- 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 "security/verifier.hpp"
#include "security/sec-policy.hpp"
#include <cryptopp/rsa.h>
#include "../util/logging.hpp"
using namespace std;
#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<SecPolicy> Verifier::DefaultPolicy = ptr_lib::shared_ptr<SecPolicy>();
Verifier::Verifier(const ptr_lib::shared_ptr<SecPolicy> &policy /* = DefaultPolicy */)
: m_policy(policy)
{
if (m_policy == DefaultPolicy)
{
// #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
// policy_ = new NoVerifyPolicyManager();
// #endif
}
}
void
Verifier::verify(const ptr_lib::shared_ptr<const Interest> &interest,
const OnVerified &onVerified,
const OnVerifyFailed &onVerifyFailed,
int stepCount)
{
//It does not make sense to verify Interest without specified policy, verification must fail!
if(!static_cast<bool>(m_policy))
onVerifyFailed();
else
{
//check verification policy
ptr_lib::shared_ptr<ValidationRequest> nextStep = m_policy->checkVerificationPolicy(interest, stepCount, onVerified, onVerifyFailed);
if (static_cast<bool>(nextStep))
{
if(!m_face)
throw Error("Face should be set prior to verify method to call");
m_face->expressInterest
(*nextStep->m_interest,
func_lib::bind(&Verifier::onCertificateData, this, _1, _2, nextStep),
func_lib::bind(&Verifier::onCertificateInterestTimeout, this, _1, nextStep->m_retry, onVerifyFailed, nextStep));
}
else
{
//If there is no nextStep, that means InterestPolicy has already been able to verify the Interest.
//No more further processes.
}
}
}
void
Verifier::verify(const ptr_lib::shared_ptr<const Data> &data,
const OnVerified &onVerified,
const OnVerifyFailed &onVerifyFailed,
int stepCount)
{
//It does not make sense to verify Interest without specified policy, verification must fail!
if(!static_cast<bool>(m_policy))
onVerifyFailed();
else
{
//check verification policy
ptr_lib::shared_ptr<ValidationRequest> nextStep = m_policy->checkVerificationPolicy(data, stepCount, onVerified, onVerifyFailed);
if (static_cast<bool>(nextStep))
{
if(!m_face)
throw Error("Face should be set prior to verify method to call");
m_face->expressInterest
(*nextStep->m_interest,
func_lib::bind(&Verifier::onCertificateData, this, _1, _2, nextStep),
func_lib::bind(&Verifier::onCertificateInterestTimeout, this, _1, nextStep->m_retry, onVerifyFailed, nextStep));
}
else
{
//If there is no nextStep, that means InterestPolicy has already been able to verify the Interest.
//No more further processes.
}
}
}
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.
verify(data,
func_lib::bind(nextStep->m_onVerified, data),
func_lib::bind(nextStep->m_onVerifyFailed, data),
nextStep->m_stepCount);
}
void
Verifier::onCertificateInterestTimeout
(const ptr_lib::shared_ptr<const Interest> &interest, int retry, const OnVerifyFailed& onVerifyFailed, ptr_lib::shared_ptr<ValidationRequest> nextStep)
{
if (retry > 0)
// Issue the same expressInterest as in verifyData except decrement retry.
m_face->expressInterest
(*interest,
func_lib::bind(&Verifier::onCertificateData, this, _1, _2, nextStep),
func_lib::bind(&Verifier::onCertificateInterestTimeout, this, _1, retry - 1, onVerifyFailed, nextStep));
else
onVerifyFailed();
}
bool
Verifier::verifySignature(const Data& 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
Verifier::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
Verifier::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
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;
}
bool
Verifier::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
Verifier::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;
}
}