blob: bb401b97e7d9cea1168bdb2f90cabb4061962412 [file] [log] [blame]
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2013-2017 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
* ndn-cxx library is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received copies of the GNU General Public License and GNU Lesser
* General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
* <http://www.gnu.org/licenses/>.
*
* See AUTHORS.md for complete list of ndn-cxx authors and contributors.
*/
#ifndef NDN_SECURITY_VALIDATOR_HPP
#define NDN_SECURITY_VALIDATOR_HPP
#include "../face.hpp"
#include "signature-sha256-with-rsa.hpp"
#include "signature-sha256-with-ecdsa.hpp"
#include "digest-sha256.hpp"
#include "validation-request.hpp"
#include "v1/public-key.hpp"
#include "v1/identity-certificate.hpp"
namespace ndn {
namespace security {
/**
* @brief provides the interfaces for packet validation.
*/
class Validator
{
public:
class Error : public std::runtime_error
{
public:
explicit
Error(const std::string& what)
: std::runtime_error(what)
{
}
};
/**
* @brief Validator constructor
*
* @param face Pointer to face through which validator may retrieve certificates.
* Passing a null pointer implies the validator is in offline mode.
*
* @note Make sure the lifetime of the passed Face is longer than validator.
*/
explicit
Validator(Face* face = nullptr);
/// @deprecated Use the constructor taking Face* as parameter.
explicit
Validator(Face& face);
virtual
~Validator();
/**
* @brief Validate Data and call either onValidated or onValidationFailed.
*
* @param data The Data with the signature to check.
* @param onValidated If the Data is validated, this calls onValidated(data).
* @param onValidationFailed If validation fails, this calls onValidationFailed(data).
*/
void
validate(const Data& data,
const OnDataValidated& onValidated,
const OnDataValidationFailed& onValidationFailed)
{
validate(data, onValidated, onValidationFailed, 0);
}
/**
* @brief Validate Interest and call either onValidated or onValidationFailed.
*
* @param interest The Interest with the signature to check.
* @param onValidated If the Interest is validated, this calls onValidated(interest).
* @param onValidationFailed If validation fails, this calls onValidationFailed(interest).
*/
void
validate(const Interest& interest,
const OnInterestValidated& onValidated,
const OnInterestValidationFailed& onValidationFailed)
{
validate(interest, onValidated, onValidationFailed, 0);
}
/**
* @brief Enable or disable the direct certificate fetch feature.
*
* When enabled, the validator will attempt to fetch the certificate that signs an Interest from
* the sender of that Interest, as identified by IncomingFaceId field, in addition to fetching
* from the infrastructure.
*
* Prior to enabling this feature, the application must enable NextHopFaceId privilege on the face
* used by this validator.
*
* @note Current implementation can only fetch the Interest signer certificate from the
* Interest sender; the issuer certificate of that certificate is only fetched from the
* infrastructure.
*
* @note Currently, this feature can only be used with ValidatorConfig.
*
* @param isEnabled Set true to enable the feature or false to disable.
*/
void
setDirectCertFetchEnabled(bool isEnabled);
/*****************************************
* verifySignature method set *
*****************************************/
/// @brief Verify the data using the publicKey.
static bool
verifySignature(const Data& data, const v1::PublicKey& publicKey);
/**
* @brief Verify the signed Interest using the publicKey.
*
* (Note the signature covers the first n-2 name components).
*/
static bool
verifySignature(const Interest& interest, const v1::PublicKey& publicKey);
/// @brief Verify the blob using the publicKey against the signature.
static bool
verifySignature(const Buffer& blob, const Signature& sig, const v1::PublicKey& publicKey)
{
return verifySignature(blob.buf(), blob.size(), sig, publicKey);
}
/// @brief Verify the data using the publicKey against the SHA256-RSA signature.
static bool
verifySignature(const Data& data,
const Signature& sig,
const v1::PublicKey& publicKey)
{
return verifySignature(data.wireEncode().value(),
data.wireEncode().value_size() - data.getSignature().getValue().size(),
sig, publicKey);
}
/** @brief Verify the interest using the publicKey against the SHA256-RSA signature.
*
* (Note the signature covers the first n-2 name components).
*/
static bool
verifySignature(const Interest& interest,
const Signature& sig,
const v1::PublicKey& publicKey)
{
if (interest.getName().size() < 2)
return false;
const Name& name = interest.getName();
return verifySignature(name.wireEncode().value(),
name.wireEncode().value_size() - name[-1].size(),
sig, publicKey);
}
/// @brief Verify the blob using the publicKey against the SHA256-RSA signature.
static bool
verifySignature(const uint8_t* buf,
const size_t size,
const Signature& sig,
const v1::PublicKey& publicKey);
/// @brief Verify the data against the SHA256 signature.
static bool
verifySignature(const Data& data, const DigestSha256& sig)
{
return verifySignature(data.wireEncode().value(),
data.wireEncode().value_size() -
data.getSignature().getValue().size(),
sig);
}
/** @brief Verify the interest against the SHA256 signature.
*
* (Note the signature covers the first n-2 name components).
*/
static bool
verifySignature(const Interest& interest, const DigestSha256& sig)
{
if (interest.getName().size() < 2)
return false;
const Name& name = interest.getName();
return verifySignature(name.wireEncode().value(),
name.wireEncode().value_size() - name[-1].size(),
sig);
}
/// @brief Verify the blob against the SHA256 signature.
static bool
verifySignature(const Buffer& blob, const DigestSha256& sig)
{
return verifySignature (blob.buf(), blob.size(), sig);
}
/// @brief Verify the blob against the SHA256 signature.
static bool
verifySignature(const uint8_t* buf, const size_t size, const DigestSha256& sig);
protected:
/**
* @brief Check the Data against policy and return the next validation step if necessary.
*
* If there is no next validation step, that validation MUST have been done.
* i.e., either onValidated or onValidationFailed callback is invoked.
*
* @param data The Data to check.
* @param nSteps The number of validation steps that have been done.
* @param onValidated If the Data is validated, this calls onValidated(data)
* @param onValidationFailed If validation fails, this calls onValidationFailed(data)
* @param nextSteps On return, contains the next validation step
*/
virtual void
checkPolicy(const Data& data,
int nSteps,
const OnDataValidated& onValidated,
const OnDataValidationFailed& onValidationFailed,
std::vector<shared_ptr<ValidationRequest>>& nextSteps) = 0;
/**
* @brief Check the Interest against validation policy and return the next validation step
* if necessary.
*
* If there is no next validation step, that validation MUST have been done.
* i.e., either onValidated or onValidationFailed callback is invoked.
*
* @param interest The Interest to check.
* @param nSteps The number of validation steps that have been done.
* @param onValidated If the Interest is validated, this calls onValidated(data)
* @param onValidationFailed If validation fails, this calls onValidationFailed(data)
* @param nextSteps On return, contains the next validation step
*/
virtual void
checkPolicy(const Interest& interest,
int nSteps,
const OnInterestValidated& onValidated,
const OnInterestValidationFailed& onValidationFailed,
std::vector<shared_ptr<ValidationRequest>>& nextSteps) = 0;
typedef function<void(const std::string&)> OnFailure;
/// @brief Process the received certificate.
void
onData(const Interest& interest,
const Data& data,
const shared_ptr<ValidationRequest>& nextStep);
void
validate(const Data& data,
const OnDataValidated& onValidated,
const OnDataValidationFailed& onValidationFailed,
int nSteps);
void
validate(const Interest& interest,
const OnInterestValidated& onValidated,
const OnInterestValidationFailed& onValidationFailed,
int nSteps);
/// Hooks
/**
* @brief trigger before validating requested certificate.
*
* The Data:
* - matches the interest in the validation-request.
* - may be certificate or a data encapsulating certificate.
*
* This method returns a data (actually certificate) that is will be passed as Data into:
* Validator::validate(const Data& data,
* const OnDataValidated& onValidated,
* const OnDataValidationFailed& onValidationFailed,
* int nSteps);
*/
virtual shared_ptr<const Data>
preCertificateValidation(const Data& data)
{
return data.shared_from_this();
}
/**
* @brief trigger when interest retrieves a Nack.
*
* Validator can decide how to handle a Nack, either call onFailure, or retry.
*
* @param interest The interest that retrieves a Nack.
* @param nack The Nack that is retrieved.
* @param nRemainingRetries The number of retries left.
* @param onFailure Failure callback when there is no more retries remaining.
* @param validationRequest The validationRequest containing the context of the interest.
*/
virtual void
onNack(const Interest& interest,
const lp::Nack& nack,
int nRemainingRetries,
const OnFailure& onFailure,
const shared_ptr<ValidationRequest>& validationRequest);
/**
* @brief trigger when interest for certificate times out.
*
* Validator can decide how to handle the timeout, either call onFailure, or retry.
*
* @param interest The interest that times out.
* @param nRemainingRetries The number of retries left.
* @param onFailure Failure callback when there is no more retries remaining.
* @param validationRequest The validationRequest containing the context of the interest.
*/
virtual void
onTimeout(const Interest& interest,
int nRemainingRetries,
const OnFailure& onFailure,
const shared_ptr<ValidationRequest>& validationRequest);
/**
* @brief trigger after checkPolicy is done.
*
* Validator can decide how to handle the set of validation requests according to
* the trust model.
*
* @param nextSteps A set of validation request made by checkPolicy.
* @param onFailure Failure callback when errors happen in processing nextSteps.
*/
virtual void
afterCheckPolicy(const std::vector<shared_ptr<ValidationRequest>>& nextSteps,
const OnFailure& onFailure);
protected:
Face* m_face;
bool m_wantDirectCertFetch;
};
} // namespace security
using security::Validator;
} // namespace ndn
#endif // NDN_SECURITY_VALIDATOR_HPP