validator.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
22 #include "validator.hpp"
23 #include "../util/crypto.hpp"
24 #include "../lp/tags.hpp"
25 
26 #include "v1/cryptopp.hpp"
27 
28 namespace ndn {
29 namespace security {
30 
31 static Oid SECP256R1("1.2.840.10045.3.1.7");
32 static Oid SECP384R1("1.3.132.0.34");
33 
35  : m_face(face)
36  , m_wantDirectCertFetch(false)
37 {
38 }
39 
41  : Validator(&face)
42 {
43 }
44 
45 Validator::~Validator() = default;
46 
47 void
48 Validator::validate(const Interest& interest,
49  const OnInterestValidated& onValidated,
50  const OnInterestValidationFailed& onValidationFailed,
51  int nSteps)
52 {
53  std::vector<shared_ptr<ValidationRequest> > nextSteps;
54  checkPolicy(interest, nSteps, onValidated, onValidationFailed, nextSteps);
55 
56  if (nextSteps.empty()) {
57  // If there is no nextStep,
58  // that means InterestPolicy has already been able to verify the Interest.
59  // No more further processes.
60  return;
61  }
62 
63  OnFailure onFailure = bind(onValidationFailed, interest.shared_from_this(), _1);
64  afterCheckPolicy(nextSteps, onFailure);
65 }
66 
67 void
69  const OnDataValidated& onValidated,
70  const OnDataValidationFailed& onValidationFailed,
71  int nSteps)
72 {
73  std::vector<shared_ptr<ValidationRequest> > nextSteps;
74  checkPolicy(data, nSteps, onValidated, onValidationFailed, nextSteps);
75 
76  if (nextSteps.empty()) {
77  // If there is no nextStep,
78  // that means Data Policy has already been able to verify the Interest.
79  // No more further processes.
80  return;
81  }
82 
83  OnFailure onFailure = bind(onValidationFailed, data.shared_from_this(), _1);
84  afterCheckPolicy(nextSteps, onFailure);
85 }
86 
87 void
88 Validator::onData(const Interest& interest,
89  const Data& data,
90  const shared_ptr<ValidationRequest>& nextStep)
91 {
92  shared_ptr<const Data> certificateData = preCertificateValidation(data);
93 
94  if (!static_cast<bool>(certificateData))
95  return nextStep->m_onDataValidationFailed(data.shared_from_this(),
96  "Cannot decode cert: " + data.getName().toUri());
97 
98  validate(*certificateData,
99  nextStep->m_onDataValidated, nextStep->m_onDataValidationFailed,
100  nextStep->m_nSteps);
101 }
102 
103 bool
105 {
106  if (!data.getSignature().hasKeyLocator())
107  return false;
108 
109  return verifySignature(data.wireEncode().value(),
110  data.wireEncode().value_size() -
111  data.getSignature().getValue().size(),
112  data.getSignature(), key);
113 }
114 
115 bool
117 {
118  const Name& name = interest.getName();
119 
120  if (name.size() < signed_interest::MIN_SIZE)
121  return false;
122 
123  Signature sig;
124  try {
125  sig.setInfo(name[signed_interest::POS_SIG_INFO].blockFromValue());
126  sig.setValue(name[signed_interest::POS_SIG_VALUE].blockFromValue());
127  }
128  catch (const tlv::Error&) {
129  return false;
130  }
131 
132  if (!sig.hasKeyLocator())
133  return false;
134 
135  const Block& nameWire = name.wireEncode();
136  return verifySignature(nameWire.value(),
137  nameWire.value_size() - name[signed_interest::POS_SIG_VALUE].size(),
138  sig, key);
139 }
140 
141 bool
142 Validator::verifySignature(const uint8_t* buf,
143  const size_t size,
144  const Signature& sig,
145  const v1::PublicKey& key)
146 {
147  try {
148  using namespace CryptoPP;
149 
150  switch (sig.getType()) {
152  if (key.getKeyType() != KeyType::RSA)
153  return false;
154 
155  RSA::PublicKey publicKey;
156  ByteQueue queue;
157 
158  queue.Put(reinterpret_cast<const byte*>(key.get().buf()), key.get().size());
159  publicKey.Load(queue);
160 
161  RSASS<PKCS1v15, SHA256>::Verifier verifier(publicKey);
162  return verifier.VerifyMessage(buf, size,
163  sig.getValue().value(), sig.getValue().value_size());
164  }
165 
167  if (key.getKeyType() != KeyType::EC)
168  return false;
169 
170  ECDSA<ECP, SHA256>::PublicKey publicKey;
171  ByteQueue queue;
172 
173  queue.Put(reinterpret_cast<const byte*>(key.get().buf()), key.get().size());
174  publicKey.Load(queue);
175 
176  ECDSA<ECP, SHA256>::Verifier verifier(publicKey);
177 
178  uint32_t length = 0;
179  StringSource src(key.get().buf(), key.get().size(), true);
180  BERSequenceDecoder subjectPublicKeyInfo(src);
181  {
182  BERSequenceDecoder algorithmInfo(subjectPublicKeyInfo);
183  {
184  Oid algorithm;
185  algorithm.decode(algorithmInfo);
186 
187  Oid curveId;
188  curveId.decode(algorithmInfo);
189 
190  if (curveId == SECP256R1)
191  length = 256;
192  else if (curveId == SECP384R1)
193  length = 384;
194  else
195  return false;
196  }
197  }
198 
199  switch (length) {
200  case 256: {
201  uint8_t buffer[64];
202  size_t usedSize = DSAConvertSignatureFormat(buffer, sizeof(buffer), DSA_P1363,
203  sig.getValue().value(),
204  sig.getValue().value_size(),
205  DSA_DER);
206  return verifier.VerifyMessage(buf, size, buffer, usedSize);
207  }
208 
209  case 384: {
210  uint8_t buffer[96];
211  size_t usedSize = DSAConvertSignatureFormat(buffer, sizeof(buffer), DSA_P1363,
212  sig.getValue().value(),
213  sig.getValue().value_size(),
214  DSA_DER);
215  return verifier.VerifyMessage(buf, size, buffer, usedSize);
216  }
217 
218  default:
219  return false;
220  }
221  }
222 
223  default:
224  // Unsupported sig type
225  return false;
226  }
227  }
228  catch (const CryptoPP::Exception& e) {
229  return false;
230  }
231 }
232 
233 bool
234 Validator::verifySignature(const uint8_t* buf, const size_t size, const DigestSha256& sig)
235 {
236  try {
237  ConstBufferPtr buffer = crypto::computeSha256Digest(buf, size);
238  const Block& sigValue = sig.getValue();
239 
240  if (buffer != nullptr &&
241  buffer->size() == sigValue.value_size() &&
242  buffer->size() == crypto::SHA256_DIGEST_SIZE) {
243  const uint8_t* p1 = buffer->buf();
244  const uint8_t* p2 = sigValue.value();
245 
246  return 0 == memcmp(p1, p2, crypto::SHA256_DIGEST_SIZE);
247  }
248  else
249  return false;
250  }
251  catch (const CryptoPP::Exception& e) {
252  return false;
253  }
254 }
255 
256 void
257 Validator::onNack(const Interest& interest,
258  const lp::Nack& nack,
259  int remainingRetries,
260  const OnFailure& onFailure,
261  const shared_ptr<ValidationRequest>& validationRequest)
262 {
263  if (remainingRetries > 0) {
264  Interest newInterest = Interest(interest);
265  newInterest.refreshNonce();
266 
267  //Express the same interest with different nonce and decremented remainingRetries.
268  m_face->expressInterest(newInterest,
269  bind(&Validator::onData, this, _1, _2, validationRequest),
270  bind(&Validator::onNack, this, _1, _2,
271  remainingRetries - 1, onFailure, validationRequest),
272  bind(&Validator::onTimeout, this, _1,
273  remainingRetries - 1, onFailure, validationRequest));
274  }
275  else {
276  onFailure("Cannot fetch cert: " + interest.getName().toUri());
277  }
278 }
279 
280 void
282  int remainingRetries,
283  const OnFailure& onFailure,
284  const shared_ptr<ValidationRequest>& validationRequest)
285 {
286  if (remainingRetries > 0) {
287  Interest newInterest = Interest(interest);
288  newInterest.refreshNonce();
289 
290  // Express the same interest with different nonce and decremented remainingRetries.
291  m_face->expressInterest(newInterest,
292  bind(&Validator::onData, this, _1, _2, validationRequest),
293  bind(&Validator::onNack, this, _1, _2,
294  remainingRetries - 1, onFailure, validationRequest),
295  bind(&Validator::onTimeout, this, _1,
296  remainingRetries - 1, onFailure, validationRequest));
297  }
298  else {
299  onFailure("Cannot fetch cert: " + interest.getName().toUri());
300  }
301 }
302 
303 void
304 Validator::afterCheckPolicy(const std::vector<shared_ptr<ValidationRequest>>& nextSteps,
305  const OnFailure& onFailure)
306 {
307  if (m_face == nullptr) {
308  onFailure("Require more information to validate the packet!");
309  return;
310  }
311 
312  for (shared_ptr<ValidationRequest> step : nextSteps) {
313  if (m_wantDirectCertFetch && step->m_requesterFaceId != 0) {
314  Interest directFetchInterest(step->m_interest);
315  directFetchInterest.refreshNonce();
316  directFetchInterest.setTag(make_shared<lp::NextHopFaceIdTag>(step->m_requesterFaceId));
317  m_face->expressInterest(directFetchInterest, nullptr, nullptr, nullptr);
318  }
319  m_face->expressInterest(step->m_interest,
320  bind(&Validator::onData, this, _1, _2, step),
321  bind(&Validator::onNack, this, _1, _2,
322  step->m_nRetries, onFailure, step),
323  bind(&Validator::onTimeout,
324  this, _1, step->m_nRetries,
325  onFailure,
326  step));
327  }
328 }
329 
330 void
332 {
333  m_wantDirectCertFetch = isEnabled;
334 }
335 
336 } // namespace security
337 } // namespace ndn
void decode(CryptoPP::BufferedTransformation &in)
Definition: oid.cpp:135
function< void(const shared_ptr< const Interest > &, const std::string &)> OnInterestValidationFailed
Callback to report a failed Interest validation.
void validate(const Data &data, const OnDataValidated &onValidated, const OnDataValidationFailed &onValidationFailed)
Validate Data and call either onValidated or onValidationFailed.
Definition: validator.hpp:78
const Name & getName() const
Definition: interest.hpp:226
Copyright (c) 2013-2016 Regents of the University of California.
Definition: common.hpp:74
const Buffer & get() const
Copyright (c) 2013-2016 Regents of the University of California.
Definition: oid.hpp:29
virtual shared_ptr< const Data > preCertificateValidation(const Data &data)
Hooks.
Definition: validator.hpp:296
virtual void checkPolicy(const Data &data, int nSteps, const OnDataValidated &onValidated, const OnDataValidationFailed &onValidationFailed, std::vector< shared_ptr< ValidationRequest >> &nextSteps)=0
Check the Data against policy and return the next validation step if necessary.
void refreshNonce()
Refresh nonce.
Definition: interest.cpp:91
static const size_t SHA256_DIGEST_SIZE
number of octets in a SHA256 digest
Definition: crypto.hpp:32
Represent a SHA256 digest.
void setInfo(const Block &info)
Set SignatureInfo from a block.
Definition: signature.cpp:44
bool hasKeyLocator() const
Check if SignatureInfo block has a KeyLocator.
Definition: signature.hpp:132
virtual void afterCheckPolicy(const std::vector< shared_ptr< ValidationRequest >> &nextSteps, const OnFailure &onFailure)
trigger after checkPolicy is done.
Definition: validator.cpp:304
const size_t MIN_SIZE
minimal number of components for Signed Interest
size_t wireEncode(EncodingImpl< TAG > &encoder) const
Fast encoding or block size estimation.
Definition: name.cpp:122
Class representing a wire element of NDN-TLV packet format.
Definition: block.hpp:43
represents an Interest packet
Definition: interest.hpp:42
const Block & getValue() const
Get SignatureValue in the wire format.
Definition: signature.hpp:105
function< void(const shared_ptr< const Data > &, const std::string &)> OnDataValidationFailed
Callback to report a failed Data validation.
void setTag(shared_ptr< T > tag) const
set a tag item
Definition: tag-host.hpp:80
function< void(const shared_ptr< const Data > &)> OnDataValidated
Callback to report a successful Data validation.
represents a Network Nack
Definition: nack.hpp:40
const Name & getName() const
Get name of the Data packet.
Definition: data.hpp:318
function< void(const shared_ptr< const Interest > &)> OnInterestValidated
Callback to report a successful Interest validation.
size_t size() const
Definition: block.cpp:504
uint32_t getType() const
Get signature type.
Definition: signature.hpp:123
std::string toUri() const
Encode this name as a URI.
Definition: name.cpp:171
size_t wireEncode(EncodingImpl< TAG > &encoder, bool wantUnsignedPortionOnly=false) const
Fast encoding or block size estimation.
Definition: data.cpp:52
Validator(Face *face=nullptr)
Validator constructor.
Definition: validator.cpp:34
uint8_t * buf()
Definition: buffer.hpp:87
void setValue(const Block &value)
Get SignatureValue from a block.
Definition: signature.cpp:50
provides the interfaces for packet validation.
Definition: validator.hpp:39
Provide a communication channel with local or remote NDN forwarder.
Definition: face.hpp:121
size_t size() const
Get the number of components.
Definition: name.hpp:400
Definition: oid.hpp:35
Name abstraction to represent an absolute name.
Definition: name.hpp:46
size_t value_size() const
Definition: block.cpp:529
const ssize_t POS_SIG_VALUE
function< void(const std::string &)> OnFailure
Definition: validator.hpp:260
void onData(const Interest &interest, const Data &data, const shared_ptr< ValidationRequest > &nextStep)
Process the received certificate.
Definition: validator.cpp:88
const Signature & getSignature() const
Definition: data.hpp:348
static Oid SECP384R1("1.3.132.0.34")
const ssize_t POS_SIG_INFO
ConstBufferPtr computeSha256Digest(const uint8_t *data, size_t dataLength)
Compute the sha-256 digest of data.
Definition: crypto.cpp:31
const uint8_t * value() const
Definition: block.cpp:520
const PendingInterestId * expressInterest(const Interest &interest, const DataCallback &afterSatisfied, const NackCallback &afterNacked, const TimeoutCallback &afterTimeout)
Express Interest.
Definition: face.cpp:166
virtual void onNack(const Interest &interest, const lp::Nack &nack, int nRemainingRetries, const OnFailure &onFailure, const shared_ptr< ValidationRequest > &validationRequest)
trigger when interest retrieves a Nack.
Definition: validator.cpp:257
static bool verifySignature(const Data &data, const v1::PublicKey &publicKey)
Verify the data using the publicKey.
Definition: validator.cpp:104
void setDirectCertFetchEnabled(bool isEnabled)
Enable or disable the direct certificate fetch feature.
Definition: validator.cpp:331
shared_ptr< const Buffer > ConstBufferPtr
Definition: buffer.hpp:33
represents a Data packet
Definition: data.hpp:37
represents an error in TLV encoding or decoding
A Signature is storage for the signature-related information (info and value) in a Data packet...
Definition: signature.hpp:33
static Oid SECP256R1("1.2.840.10045.3.1.7")
virtual void onTimeout(const Interest &interest, int nRemainingRetries, const OnFailure &onFailure, const shared_ptr< ValidationRequest > &validationRequest)
trigger when interest for certificate times out.
Definition: validator.cpp:281