blob: d22d55bf737883c21dc85b64d896cc6441f46bb5 [file] [log] [blame]
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2013, Regents of the University of California
* Yingdi Yu
*
* BSD license, See the LICENSE file for more information
*
* Author: Yingdi Yu <yingdi@cs.ucla.edu>
*/
#include "validator-invitation.h"
#include "logging.h"
using namespace std;
using namespace ndn;
INIT_LOGGER("ValidatorInvitation");
namespace chronos{
const shared_ptr<CertificateCache> ValidatorInvitation::DefaultCertificateCache = shared_ptr<CertificateCache>();
ValidatorInvitation::ValidatorInvitation(shared_ptr<Face> face,
const string& chatroomName,
const Name& signingIdentity,
shared_ptr<CertificateCache> certificateCache,
int stepLimit)
: Validator(face)
, m_stepLimit(stepLimit)
, m_certificateCache(certificateCache)
, m_chatroomName(chatroomName)
, m_signingIdentity(signingIdentity)
{
m_invitationRule = make_shared<SecRuleRelative>("^<ndn><broadcast><chronos><invitation>([^<chatroom>]*)<chatroom>",
"^([^<KEY>]*)<KEY>(<>*)[<dsk-.*><ksk-.*>]<ID-CERT>$",
"==", "\\1", "\\1\\2", true);
m_dskRule = make_shared<SecRuleRelative>("^([^<KEY>]*)<KEY><dsk-.*><ID-CERT><>$",
"^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>$",
"==", "\\1", "\\1\\2", true);
}
void
ValidatorInvitation::checkPolicy (const shared_ptr<const Data>& data,
int stepCount,
const OnDataValidated& onValidated,
const OnDataValidationFailed& onValidationFailed,
vector<shared_ptr<ValidationRequest> >& nextSteps)
{
if(m_stepLimit == stepCount)
{
_LOG_DEBUG("reach the maximum steps of verification");
onValidationFailed(data);
return;
}
try{
SignatureSha256WithRsa sig(data->getSignature());
const Name & keyLocatorName = sig.getKeyLocator().getName();
const uint8_t* buf = data->wireEncode().wire();
const size_t size = data->wireEncode().size();
if(m_invitationRule->satisfy(data->getName(), keyLocatorName))
processSignature(buf, size,
sig, keyLocatorName,
bind(onValidated, data),
bind(onValidationFailed, data),
stepCount,
nextSteps);
if(m_dskRule->satisfy(data->getName(), keyLocatorName))
processFinalSignature(buf, size,
sig, keyLocatorName,
bind(onValidated, data),
bind(onValidationFailed, data));
}catch(...){
onValidationFailed(data);
return;
}
}
void
ValidatorInvitation::checkPolicy (const shared_ptr<const Interest>& interest,
int stepCount,
const OnInterestValidated& onValidated,
const OnInterestValidationFailed& onValidationFailed,
vector<shared_ptr<ValidationRequest> >& nextSteps)
{
try{
Name interestName = interest->getName();
Block signatureBlock = interestName.get(-1).blockFromValue();
Block signatureInfo = interestName.get(-2).blockFromValue();
Signature signature(signatureInfo, signatureBlock);
SignatureSha256WithRsa sig(signature);
const Name & keyLocatorName = sig.getKeyLocator().getName();
Name signedName = interestName.getPrefix(-1);
Buffer signedBlob = Buffer(signedName.wireEncode().value(), signedName.wireEncode().value_size());
processSignature(signedBlob.buf(), signedBlob.size(),
sig, keyLocatorName,
bind(onValidated, interest),
bind(onValidationFailed, interest),
stepCount,
nextSteps);
}catch(...){
onValidationFailed(interest);
return;
}
}
void
ValidatorInvitation::processSignature (const uint8_t* buf,
const size_t size,
const SignatureSha256WithRsa& signature,
const Name& keyLocatorName,
const OnValidated& onValidated,
const OnValidationFailed& onValidationFailed,
int stepCount,
vector<shared_ptr<ValidationRequest> >& nextSteps)
{
try{
Name keyName = IdentityCertificate::certificateNameToPublicKeyName(keyLocatorName);
if(m_trustAnchors.find(keyName) != m_trustAnchors.end())
{
if(Validator::verifySignature(buf, size, signature, m_trustAnchors[keyName]))
onValidated();
else
onValidationFailed();
return;
}
if(static_cast<bool>(m_certificateCache))
{
shared_ptr<const IdentityCertificate> trustedCert = m_certificateCache->getCertificate(keyLocatorName);
if(static_cast<bool>(trustedCert)){
if(Validator::verifySignature(buf, size, signature, trustedCert->getPublicKeyInfo()))
onValidated();
else
onValidationFailed();
return;
}
}
OnDataValidated onKeyLocatorValidated =
bind(&ValidatorInvitation::onDskKeyLocatorValidated,
this, _1, buf, size, signature, onValidated, onValidationFailed);
OnDataValidationFailed onKeyLocatorValidationFailed =
bind(&ValidatorInvitation::onDskKeyLocatorValidationFailed,
this, _1, onValidationFailed);
Interest interest(keyLocatorName);
interest.setMustBeFresh(true);
shared_ptr<ValidationRequest> nextStep = make_shared<ValidationRequest>
(interest, onKeyLocatorValidated, onKeyLocatorValidationFailed, 0, stepCount + 1);
nextSteps.push_back(nextStep);
return;
}catch(...){
onValidationFailed();
return;
}
}
void
ValidatorInvitation::processFinalSignature (const uint8_t* buf,
const size_t size,
const SignatureSha256WithRsa& signature,
const Name& keyLocatorName,
const OnValidated& onValidated,
const OnValidationFailed& onValidationFailed)
{
try{
Name keyName = IdentityCertificate::certificateNameToPublicKeyName(keyLocatorName);
if(m_trustAnchors.end() != m_trustAnchors.find(keyName) && Validator::verifySignature(buf, size, signature, m_trustAnchors[keyName]))
onValidated();
else
onValidationFailed();
return;
}catch(...){
onValidationFailed();
return;
}
}
void
ValidatorInvitation::onDskKeyLocatorValidated(const shared_ptr<const Data>& certData,
const uint8_t* buf,
const size_t size,
const SignatureSha256WithRsa& signature,
const OnValidated& onValidated,
const OnValidationFailed& onValidationFailed)
{
shared_ptr<IdentityCertificate> certificate = make_shared<IdentityCertificate>(*certData);
if(!certificate->isTooLate() && !certificate->isTooEarly())
{
Name certName = certificate->getName().getPrefix(-1);
m_dskCertificates[certName] = certificate;
if(Validator::verifySignature(buf, size, signature, certificate->getPublicKeyInfo()))
{
onValidated();
return;
}
}
onValidationFailed();
return;
}
void
ValidatorInvitation::onDskKeyLocatorValidationFailed(const shared_ptr<const Data>& certData,
const OnValidationFailed& onValidationFailed)
{ onValidationFailed(); }
}//chronos