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