blob: 1b9d92af5824ac77a742167a4fcccebd7f578c96 [file] [log] [blame]
Alexander Afanasyevc169a812014-05-20 20:37:29 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Yingdi Yu6ac97982014-01-30 14:49:21 -08002/**
Alexander Afanasyevc169a812014-05-20 20:37:29 -04003 * Copyright (c) 2013-2014 Regents of the University of California.
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07006 *
Alexander Afanasyevc169a812014-05-20 20:37:29 -04007 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -070020 *
21 * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
22 * @author Jeff Thompson <jefft0@remap.ucla.edu>
Yingdi Yu6ac97982014-01-30 14:49:21 -080023 */
24
Alexander Afanasyeve2dcdfd2014-02-07 15:53:28 -080025#include "common.hpp"
26
Yingdi Yu6ac97982014-01-30 14:49:21 -080027#include "validator.hpp"
Yingdi Yu21157162014-02-28 13:02:34 -080028#include "../util/crypto.hpp"
Yingdi Yu6ac97982014-01-30 14:49:21 -080029
Junxiao Shi482ccc52014-03-31 13:05:24 -070030#include "cryptopp.hpp"
Yingdi Yu21157162014-02-28 13:02:34 -080031
Yingdi Yu6ac97982014-01-30 14:49:21 -080032namespace ndn {
33
Yingdi Yuc8f883c2014-06-20 23:25:22 -070034static OID SECP256R1("1.2.840.10045.3.1.7");
35static OID SECP384R1("1.3.132.0.34");
36
Yingdi Yu96e64062014-04-15 19:57:33 -070037Validator::Validator()
38 : m_hasFace(false)
39 , m_face(*static_cast<Face*>(0))
40{
41}
Yingdi Yu6ac97982014-01-30 14:49:21 -080042
Yingdi Yu96e64062014-04-15 19:57:33 -070043Validator::Validator(Face& face)
44 : m_hasFace(true)
45 , m_face(face)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070046{
47}
Yingdi Yu6ac97982014-01-30 14:49:21 -080048
49void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070050Validator::validate(const Interest& interest,
51 const OnInterestValidated& onValidated,
52 const OnInterestValidationFailed& onValidationFailed,
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070053 int nSteps)
Yingdi Yu6ac97982014-01-30 14:49:21 -080054{
Yingdi Yuc8f883c2014-06-20 23:25:22 -070055 std::vector<shared_ptr<ValidationRequest> > nextSteps;
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070056 checkPolicy(interest, nSteps, onValidated, onValidationFailed, nextSteps);
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070057
Yingdi Yud9006e72014-06-23 19:10:44 -070058 if (nextSteps.empty())
Yingdi Yu6ac97982014-01-30 14:49:21 -080059 {
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070060 // If there is no nextStep,
61 // that means InterestPolicy has already been able to verify the Interest.
62 // No more further processes.
Yingdi Yud9006e72014-06-23 19:10:44 -070063 return;
Yingdi Yu6ac97982014-01-30 14:49:21 -080064 }
Yingdi Yud9006e72014-06-23 19:10:44 -070065
66 if (!m_hasFace)
67 {
68 onValidationFailed(interest.shared_from_this(),
69 "Require more information to validate the interest!");
70 return;
71 }
72
73 OnFailure onFailure = bind(onValidationFailed, interest.shared_from_this(), _1);
74 afterCheckPolicy(nextSteps, onFailure);
Yingdi Yu6ac97982014-01-30 14:49:21 -080075}
76
77void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070078Validator::validate(const Data& data,
79 const OnDataValidated& onValidated,
80 const OnDataValidationFailed& onValidationFailed,
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070081 int nSteps)
Yingdi Yu6ac97982014-01-30 14:49:21 -080082{
Yingdi Yuc8f883c2014-06-20 23:25:22 -070083 std::vector<shared_ptr<ValidationRequest> > nextSteps;
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070084 checkPolicy(data, nSteps, onValidated, onValidationFailed, nextSteps);
Yingdi Yu6ac97982014-01-30 14:49:21 -080085
Yingdi Yud9006e72014-06-23 19:10:44 -070086 if (nextSteps.empty())
Yingdi Yu6ac97982014-01-30 14:49:21 -080087 {
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070088 // If there is no nextStep,
89 // that means Data Policy has already been able to verify the Interest.
90 // No more further processes.
Yingdi Yud9006e72014-06-23 19:10:44 -070091 return;
Yingdi Yu6ac97982014-01-30 14:49:21 -080092 }
Yingdi Yud9006e72014-06-23 19:10:44 -070093
94 if (!m_hasFace)
95 {
96 onValidationFailed(data.shared_from_this(),
97 "Require more information to validate the data!");
98 return;
99 }
100
101 OnFailure onFailure = bind(onValidationFailed, data.shared_from_this(), _1);
102 afterCheckPolicy(nextSteps, onFailure);
Yingdi Yu6ac97982014-01-30 14:49:21 -0800103}
104
105void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700106Validator::onData(const Interest& interest,
107 const Data& data,
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800108 const shared_ptr<ValidationRequest>& nextStep)
Yingdi Yu6ac97982014-01-30 14:49:21 -0800109{
Yingdi Yud9006e72014-06-23 19:10:44 -0700110 shared_ptr<const Data> certificateData = preCertificateValidation(data);
Yingdi Yu6ac97982014-01-30 14:49:21 -0800111
Yingdi Yud9006e72014-06-23 19:10:44 -0700112 if (!static_cast<bool>(certificateData))
113 return nextStep->m_onDataValidationFailed(data.shared_from_this(),
114 "Cannot decode cert: " + data.getName().toUri());
115
116 validate(*certificateData,
117 nextStep->m_onDataValidated, nextStep->m_onDataValidationFailed,
118 nextStep->m_nSteps);
Yingdi Yu6ac97982014-01-30 14:49:21 -0800119}
120
121bool
122Validator::verifySignature(const Data& data, const PublicKey& key)
123{
Yingdi Yu40587c02014-02-21 16:40:48 -0800124 try
125 {
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700126 switch (data.getSignature().getType())
Yingdi Yu40587c02014-02-21 16:40:48 -0800127 {
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700128 case Tlv::SignatureSha256WithRsa:
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700129 {
130 SignatureSha256WithRsa sigSha256Rsa(data.getSignature());
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700131 return verifySignature(data.wireEncode().value(),
132 data.wireEncode().value_size() -
133 data.getSignature().getValue().size(),
134 sigSha256Rsa, key);
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700135 }
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700136 case Tlv::SignatureSha256WithEcdsa:
137 {
138 SignatureSha256WithEcdsa sigSha256Ecdsa(data.getSignature());
139 return verifySignature(data.wireEncode().value(),
140 data.wireEncode().value_size() -
141 data.getSignature().getValue().size(),
142 sigSha256Ecdsa, key);
143 }
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700144 default:
145 {
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700146 // Unsupported sig type
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700147 return false;
148 }
Yingdi Yu40587c02014-02-21 16:40:48 -0800149 }
Yingdi Yu6ac97982014-01-30 14:49:21 -0800150 }
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -0700151 catch (Signature::Error& e)
Yingdi Yu40587c02014-02-21 16:40:48 -0800152 {
Yingdi Yu40587c02014-02-21 16:40:48 -0800153 return false;
154 }
Yingdi Yu6ac97982014-01-30 14:49:21 -0800155 return false;
156}
157
158bool
Yingdi Yu21157162014-02-28 13:02:34 -0800159Validator::verifySignature(const Interest& interest, const PublicKey& key)
Yingdi Yu6ac97982014-01-30 14:49:21 -0800160{
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700161 const Name& interestName = interest.getName();
Yingdi Yu6ac97982014-01-30 14:49:21 -0800162
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700163 if (interestName.size() < 2)
Yingdi Yu6ac97982014-01-30 14:49:21 -0800164 return false;
165
Yingdi Yu40587c02014-02-21 16:40:48 -0800166 try
167 {
168 const Block& nameBlock = interestName.wireEncode();
Yingdi Yu6ac97982014-01-30 14:49:21 -0800169
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700170 Signature sig(interestName[-2].blockFromValue(),
Yingdi Yu40587c02014-02-21 16:40:48 -0800171 interestName[-1].blockFromValue());
Yingdi Yu6ac97982014-01-30 14:49:21 -0800172
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700173 switch (sig.getType())
Yingdi Yu40587c02014-02-21 16:40:48 -0800174 {
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700175 case Tlv::SignatureSha256WithRsa:
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700176 {
177 SignatureSha256WithRsa sigSha256Rsa(sig);
Yingdi Yu6ac97982014-01-30 14:49:21 -0800178
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700179 return verifySignature(nameBlock.value(),
180 nameBlock.value_size() - interestName[-1].size(),
181 sigSha256Rsa, key);
182 }
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700183 case Tlv::SignatureSha256WithEcdsa:
184 {
185 SignatureSha256WithEcdsa sigSha256Ecdsa(sig);
186
187 return verifySignature(nameBlock.value(),
188 nameBlock.value_size() - interestName[-1].size(),
189 sigSha256Ecdsa, key);
190 }
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700191 default:
192 {
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700193 // Unsupported sig type
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700194 return false;
195 }
Yingdi Yu40587c02014-02-21 16:40:48 -0800196 }
Yingdi Yu6ac97982014-01-30 14:49:21 -0800197 }
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -0700198 catch (Signature::Error& e)
Yingdi Yu40587c02014-02-21 16:40:48 -0800199 {
Yingdi Yu40587c02014-02-21 16:40:48 -0800200 return false;
201 }
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -0700202 catch (Block::Error& e)
Yingdi Yu40587c02014-02-21 16:40:48 -0800203 {
Yingdi Yu40587c02014-02-21 16:40:48 -0800204 return false;
205 }
Yingdi Yu6ac97982014-01-30 14:49:21 -0800206 return false;
207}
208
209bool
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700210Validator::verifySignature(const uint8_t* buf,
211 const size_t size,
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700212 const SignatureWithPublicKey& sig,
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700213 const PublicKey& key)
Yingdi Yu6ac97982014-01-30 14:49:21 -0800214{
Yingdi Yu40587c02014-02-21 16:40:48 -0800215 try
216 {
217 using namespace CryptoPP;
Yingdi Yu6ac97982014-01-30 14:49:21 -0800218
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700219 switch (sig.getType())
220 {
221 case Tlv::SignatureSha256WithRsa:
222 {
223 if (key.getKeyType() != KEY_TYPE_RSA)
224 return false;
Yingdi Yu6ac97982014-01-30 14:49:21 -0800225
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700226 RSA::PublicKey publicKey;
227 ByteQueue queue;
Yingdi Yu6ac97982014-01-30 14:49:21 -0800228
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700229 queue.Put(reinterpret_cast<const byte*>(key.get().buf()), key.get().size());
230 publicKey.Load(queue);
231
232 RSASS<PKCS1v15, SHA256>::Verifier verifier(publicKey);
233 return verifier.VerifyMessage(buf, size,
234 sig.getValue().value(), sig.getValue().value_size());
235 }
236 case Tlv::SignatureSha256WithEcdsa:
237 {
238 if (key.getKeyType() != KEY_TYPE_ECDSA)
239 return false;
240
241 ECDSA<ECP, SHA256>::PublicKey publicKey;
242 ByteQueue queue;
243
244 queue.Put(reinterpret_cast<const byte*>(key.get().buf()), key.get().size());
245 publicKey.Load(queue);
246
247 ECDSA<ECP, SHA256>::Verifier verifier(publicKey);
248
249 uint32_t length = 0;
250 StringSource src(key.get().buf(), key.get().size(), true);
251 BERSequenceDecoder subjectPublicKeyInfo(src);
252 {
253 BERSequenceDecoder algorithmInfo(subjectPublicKeyInfo);
254 {
255 OID algorithm;
256 algorithm.decode(algorithmInfo);
257
258 OID curveId;
259 curveId.decode(algorithmInfo);
260
261 if (curveId == SECP256R1)
262 length = 256;
263 else if (curveId == SECP384R1)
264 length = 384;
265 else
266 return false;
267 }
268 }
269
270 switch (length)
271 {
272 case 256:
273 {
274 uint8_t buffer[64];
275 size_t usedSize = DSAConvertSignatureFormat(buffer, 64, DSA_P1363,
276 sig.getValue().value(),
277 sig.getValue().value_size(),
278 DSA_DER);
279 return verifier.VerifyMessage(buf, size, buffer, usedSize);
280 }
281 case 384:
282 {
283 uint8_t buffer[96];
284 size_t usedSize = DSAConvertSignatureFormat(buffer, 96, DSA_P1363,
285 sig.getValue().value(),
286 sig.getValue().value_size(),
287 DSA_DER);
288 return verifier.VerifyMessage(buf, size, buffer, usedSize);
289 }
290 default:
291 return false;
292 }
293 }
294 default:
295 // Unsupported sig type
296 return false;
297 }
Yingdi Yu40587c02014-02-21 16:40:48 -0800298 }
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -0700299 catch (CryptoPP::Exception& e)
Yingdi Yu40587c02014-02-21 16:40:48 -0800300 {
Yingdi Yu40587c02014-02-21 16:40:48 -0800301 return false;
302 }
Yingdi Yu6ac97982014-01-30 14:49:21 -0800303}
304
Yingdi Yu21157162014-02-28 13:02:34 -0800305bool
Yingdi Yubf6a2812014-06-17 15:32:11 -0700306Validator::verifySignature(const uint8_t* buf, const size_t size, const DigestSha256& sig)
Yingdi Yu21157162014-02-28 13:02:34 -0800307{
308 try
309 {
310 ConstBufferPtr buffer = crypto::sha256(buf, size);
311 const Block& sigValue = sig.getValue();
312
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700313 if (static_cast<bool>(buffer) &&
314 buffer->size() == sigValue.value_size() &&
315 buffer->size() == crypto::SHA256_DIGEST_SIZE)
Yingdi Yu21157162014-02-28 13:02:34 -0800316 {
317
318 const uint8_t* p1 = buffer->buf();
319 const uint8_t* p2 = sigValue.value();
320
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700321 return 0 == memcmp(p1, p2, crypto::SHA256_DIGEST_SIZE);
Yingdi Yu21157162014-02-28 13:02:34 -0800322 }
323 else
324 return false;
325 }
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -0700326 catch (CryptoPP::Exception& e)
Yingdi Yu21157162014-02-28 13:02:34 -0800327 {
Yingdi Yu21157162014-02-28 13:02:34 -0800328 return false;
329 }
330}
331
Yingdi Yud9006e72014-06-23 19:10:44 -0700332void
333Validator::onTimeout(const Interest& interest,
334 int remainingRetries,
335 const OnFailure& onFailure,
336 const shared_ptr<ValidationRequest>& validationRequest)
337{
338 if (remainingRetries > 0)
339 // Issue the same expressInterest except decrement nRetrials.
340 m_face.expressInterest(interest,
341 bind(&Validator::onData, this, _1, _2, validationRequest),
342 bind(&Validator::onTimeout, this, _1,
343 remainingRetries - 1, onFailure, validationRequest));
344 else
345 onFailure("Cannot fetch cert: " + interest.getName().toUri());
346}
347
348
349void
350Validator::afterCheckPolicy(const std::vector<shared_ptr<ValidationRequest> >& nextSteps,
351 const OnFailure& onFailure)
352{
353 for (std::vector<shared_ptr<ValidationRequest> >::const_iterator it = nextSteps.begin();
354 it != nextSteps.end(); it++)
355 {
356 m_face.expressInterest((*it)->m_interest,
357 bind(&Validator::onData, this, _1, _2, *it),
358 bind(&Validator::onTimeout,
359 this, _1, (*it)->m_nRetries,
360 onFailure,
361 *it));
362 }
363}
364
Yingdi Yufc40d872014-02-18 12:56:04 -0800365} // namespace ndn