NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.0: NDN, CCN, CCNx, content centric networks
API Documentation
validator.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
25 #include "common.hpp"
26 
27 #include "validator.hpp"
28 #include "../util/crypto.hpp"
29 
30 #include "cryptopp.hpp"
31 
32 namespace ndn {
33 
34 static OID SECP256R1("1.2.840.10045.3.1.7");
35 static OID SECP384R1("1.3.132.0.34");
36 
38  : m_face(face)
39 {
40 }
41 
43  : m_face(&face)
44 {
45 }
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  {
58  // If there is no nextStep,
59  // that means InterestPolicy has already been able to verify the Interest.
60  // No more further processes.
61  return;
62  }
63 
64  OnFailure onFailure = bind(onValidationFailed, interest.shared_from_this(), _1);
65  afterCheckPolicy(nextSteps, onFailure);
66 }
67 
68 void
70  const OnDataValidated& onValidated,
71  const OnDataValidationFailed& onValidationFailed,
72  int nSteps)
73 {
74  std::vector<shared_ptr<ValidationRequest> > nextSteps;
75  checkPolicy(data, nSteps, onValidated, onValidationFailed, nextSteps);
76 
77  if (nextSteps.empty())
78  {
79  // If there is no nextStep,
80  // that means Data Policy has already been able to verify the Interest.
81  // No more further processes.
82  return;
83  }
84 
85  OnFailure onFailure = bind(onValidationFailed, data.shared_from_this(), _1);
86  afterCheckPolicy(nextSteps, onFailure);
87 }
88 
89 void
90 Validator::onData(const Interest& interest,
91  const Data& data,
92  const shared_ptr<ValidationRequest>& nextStep)
93 {
94  shared_ptr<const Data> certificateData = preCertificateValidation(data);
95 
96  if (!static_cast<bool>(certificateData))
97  return nextStep->m_onDataValidationFailed(data.shared_from_this(),
98  "Cannot decode cert: " + data.getName().toUri());
99 
100  validate(*certificateData,
101  nextStep->m_onDataValidated, nextStep->m_onDataValidationFailed,
102  nextStep->m_nSteps);
103 }
104 
105 bool
106 Validator::verifySignature(const Data& data, const PublicKey& key)
107 {
108  if (!data.getSignature().hasKeyLocator())
109  return false;
110 
111  return verifySignature(data.wireEncode().value(),
112  data.wireEncode().value_size() -
113  data.getSignature().getValue().size(),
114  data.getSignature(), key);
115 }
116 
117 bool
118 Validator::verifySignature(const Interest& interest, const PublicKey& key)
119 {
120  const Name& interestName = interest.getName();
121 
122  if (interestName.size() < 2)
123  return false;
124 
125  try
126  {
127  const Block& nameBlock = interestName.wireEncode();
128 
129  Signature sig(interestName[-2].blockFromValue(),
130  interestName[-1].blockFromValue());
131 
132  if (!sig.hasKeyLocator())
133  return false;
134 
135  return verifySignature(nameBlock.value(),
136  nameBlock.value_size() - interestName[-1].size(),
137  sig, key);
138  }
139  catch (Block::Error& e)
140  {
141  return false;
142  }
143 }
144 
145 bool
146 Validator::verifySignature(const uint8_t* buf,
147  const size_t size,
148  const Signature& sig,
149  const PublicKey& key)
150 {
151  try
152  {
153  using namespace CryptoPP;
154 
155  switch (sig.getType())
156  {
158  {
159  if (key.getKeyType() != KEY_TYPE_RSA)
160  return false;
161 
162  RSA::PublicKey publicKey;
163  ByteQueue queue;
164 
165  queue.Put(reinterpret_cast<const byte*>(key.get().buf()), key.get().size());
166  publicKey.Load(queue);
167 
168  RSASS<PKCS1v15, SHA256>::Verifier verifier(publicKey);
169  return verifier.VerifyMessage(buf, size,
170  sig.getValue().value(), sig.getValue().value_size());
171  }
173  {
174  if (key.getKeyType() != KEY_TYPE_ECDSA)
175  return false;
176 
177  ECDSA<ECP, SHA256>::PublicKey publicKey;
178  ByteQueue queue;
179 
180  queue.Put(reinterpret_cast<const byte*>(key.get().buf()), key.get().size());
181  publicKey.Load(queue);
182 
183  ECDSA<ECP, SHA256>::Verifier verifier(publicKey);
184 
185  uint32_t length = 0;
186  StringSource src(key.get().buf(), key.get().size(), true);
187  BERSequenceDecoder subjectPublicKeyInfo(src);
188  {
189  BERSequenceDecoder algorithmInfo(subjectPublicKeyInfo);
190  {
191  OID algorithm;
192  algorithm.decode(algorithmInfo);
193 
194  OID curveId;
195  curveId.decode(algorithmInfo);
196 
197  if (curveId == SECP256R1)
198  length = 256;
199  else if (curveId == SECP384R1)
200  length = 384;
201  else
202  return false;
203  }
204  }
205 
206  switch (length)
207  {
208  case 256:
209  {
210  uint8_t buffer[64];
211  size_t usedSize = DSAConvertSignatureFormat(buffer, 64, DSA_P1363,
212  sig.getValue().value(),
213  sig.getValue().value_size(),
214  DSA_DER);
215  return verifier.VerifyMessage(buf, size, buffer, usedSize);
216  }
217  case 384:
218  {
219  uint8_t buffer[96];
220  size_t usedSize = DSAConvertSignatureFormat(buffer, 96, DSA_P1363,
221  sig.getValue().value(),
222  sig.getValue().value_size(),
223  DSA_DER);
224  return verifier.VerifyMessage(buf, size, buffer, usedSize);
225  }
226  default:
227  return false;
228  }
229  }
230  default:
231  // Unsupported sig type
232  return false;
233  }
234  }
235  catch (CryptoPP::Exception& e)
236  {
237  return false;
238  }
239 }
240 
241 bool
242 Validator::verifySignature(const uint8_t* buf, const size_t size, const DigestSha256& sig)
243 {
244  try
245  {
246  ConstBufferPtr buffer = crypto::sha256(buf, size);
247  const Block& sigValue = sig.getValue();
248 
249  if (static_cast<bool>(buffer) &&
250  buffer->size() == sigValue.value_size() &&
251  buffer->size() == crypto::SHA256_DIGEST_SIZE)
252  {
253 
254  const uint8_t* p1 = buffer->buf();
255  const uint8_t* p2 = sigValue.value();
256 
257  return 0 == memcmp(p1, p2, crypto::SHA256_DIGEST_SIZE);
258  }
259  else
260  return false;
261  }
262  catch (CryptoPP::Exception& e)
263  {
264  return false;
265  }
266 }
267 
268 void
270  int remainingRetries,
271  const OnFailure& onFailure,
272  const shared_ptr<ValidationRequest>& validationRequest)
273 {
274  if (remainingRetries > 0)
275  // Issue the same expressInterest except decrement nRetrials.
276  m_face->expressInterest(interest,
277  bind(&Validator::onData, this, _1, _2, validationRequest),
278  bind(&Validator::onTimeout, this, _1,
279  remainingRetries - 1, onFailure, validationRequest));
280  else
281  onFailure("Cannot fetch cert: " + interest.getName().toUri());
282 }
283 
284 
285 void
286 Validator::afterCheckPolicy(const std::vector<shared_ptr<ValidationRequest> >& nextSteps,
287  const OnFailure& onFailure)
288 {
289  if (m_face == nullptr)
290  {
291  onFailure("Require more information to validate the packet!");
292  return;
293  }
294 
295  for (std::vector<shared_ptr<ValidationRequest> >::const_iterator it = nextSteps.begin();
296  it != nextSteps.end(); it++)
297  {
298  m_face->expressInterest((*it)->m_interest,
299  bind(&Validator::onData, this, _1, _2, *it),
300  bind(&Validator::onTimeout,
301  this, _1, (*it)->m_nRetries,
302  onFailure,
303  *it));
304  }
305 }
306 
307 } // namespace ndn
const Name & getName() const
Definition: interest.hpp:216
Copyright (c) 2011-2015 Regents of the University of California.
static OID SECP256R1("1.2.840.10045.3.1.7")
Copyright (c) 2013-2014 Regents of the University of California.
Definition: oid.hpp:29
virtual void afterCheckPolicy(const std::vector< shared_ptr< ValidationRequest > > &nextSteps, const OnFailure &onFailure)
trigger after checkPolicy is done.
Definition: validator.cpp:286
void onData(const Interest &interest, const Data &data, const shared_ptr< ValidationRequest > &nextStep)
Process the received certificate.
Definition: validator.cpp:90
Validator(Face *face=nullptr)
Validator constructor.
Definition: validator.cpp:37
static const size_t SHA256_DIGEST_SIZE
number of octets in a SHA256 digest
Definition: crypto.hpp:43
Represent a SHA256 digest.
bool hasKeyLocator() const
Check if SignatureInfo block has a KeyLocator.
Definition: signature.hpp:123
size_t wireEncode(EncodingImpl< TAG > &encoder) const
Fast encoding or block size estimation.
Definition: name.cpp:69
Class representing a wire element of NDN-TLV packet format.
Definition: block.hpp:43
represents an Interest packet
Definition: interest.hpp:45
const Block & getValue() const
Get SignatureValue in the wire format.
Definition: signature.hpp:96
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:269
const Name & getName() const
Get name of the Data packet.
Definition: data.hpp:343
size_t size() const
Definition: block.cpp:504
uint32_t getType() const
Get signature type.
Definition: signature.hpp:114
std::string toUri() const
Encode this name as a URI.
Definition: name.cpp:183
void decode(CryptoPP::BufferedTransformation &in)
Definition: oid.cpp:147
size_t wireEncode(EncodingImpl< TAG > &encoder, bool wantUnsignedPortionOnly=false) const
Fast encoding or block size estimation.
Definition: data.cpp:52
function< void(const shared_ptr< const Data > &)> OnDataValidated
Callback to report a successful Data validation.
void validate(const Data &data, const OnDataValidated &onValidated, const OnDataValidationFailed &onValidationFailed)
Validate Data and call either onValidated or onValidationFailed.
Definition: validator.hpp:82
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.
uint8_t * buf()
Definition: buffer.hpp:87
function< void(const shared_ptr< const Data > &, const std::string &)> OnDataValidationFailed
Callback to report a failed Data validation.
Abstraction to communicate with local or remote NDN forwarder.
Definition: face.hpp:100
KeyType getKeyType() const
Definition: public-key.hpp:83
size_t size() const
Get the number of components.
Definition: name.hpp:408
Name abstraction to represent an absolute name.
Definition: name.hpp:46
const PendingInterestId * expressInterest(const Interest &interest, const OnData &onData, const OnTimeout &onTimeout=OnTimeout())
Express Interest.
Definition: face.cpp:63
size_t value_size() const
Definition: block.cpp:529
Definition: oid.hpp:35
const Signature & getSignature() const
Definition: data.hpp:373
function< void(const shared_ptr< const Interest > &, const std::string &)> OnInterestValidationFailed
Callback to report a failed Interest validation.
const Buffer & get() const
Definition: public-key.hpp:70
static bool verifySignature(const Data &data, const PublicKey &publicKey)
Verify the data using the publicKey.
Definition: validator.cpp:106
function< void(const std::string &)> OnFailure
Definition: validator.hpp:243
const uint8_t * value() const
Definition: block.cpp:520
shared_ptr< const Buffer > ConstBufferPtr
Definition: buffer.hpp:33
ConstBufferPtr sha256(const uint8_t *data, size_t dataLength)
Compute the sha-256 digest of data.
Definition: crypto.cpp:51
represents a Data packet
Definition: data.hpp:39
virtual shared_ptr< const Data > preCertificateValidation(const Data &data)
Hooks.
Definition: validator.hpp:279
function< void(const shared_ptr< const Interest > &)> OnInterestValidated
Callback to report a successful Interest validation.
static OID SECP384R1("1.3.132.0.34")
A Signature is storage for the signature-related information (info and value) in a Data packet...
Definition: signature.hpp:33