blob: 2d2b6846fe02c4615d320c8fff33e43c460f1e58 [file] [log] [blame]
Yingdi Yu6ac97982014-01-30 14:49:21 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2/**
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07003 * Copyright (c) 2013-2014, Regents of the University of California.
4 * All rights reserved.
5 *
6 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
7 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
8 *
9 * This file licensed under New BSD License. See COPYING for detailed information about
10 * ndn-cxx library copyright, permissions, and redistribution restrictions.
11 *
12 * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
13 * @author Jeff Thompson <jefft0@remap.ucla.edu>
Yingdi Yu6ac97982014-01-30 14:49:21 -080014 */
15
Alexander Afanasyeve2dcdfd2014-02-07 15:53:28 -080016#include "common.hpp"
17
Yingdi Yu6ac97982014-01-30 14:49:21 -080018#include "validator.hpp"
Yingdi Yu21157162014-02-28 13:02:34 -080019#include "../util/crypto.hpp"
Yingdi Yu6ac97982014-01-30 14:49:21 -080020
Junxiao Shi482ccc52014-03-31 13:05:24 -070021#include "cryptopp.hpp"
Yingdi Yu21157162014-02-28 13:02:34 -080022
Yingdi Yu6ac97982014-01-30 14:49:21 -080023using namespace std;
24
Yingdi Yu6ac97982014-01-30 14:49:21 -080025namespace ndn {
26
Yingdi Yu96e64062014-04-15 19:57:33 -070027Validator::Validator()
28 : m_hasFace(false)
29 , m_face(*static_cast<Face*>(0))
30{
31}
Yingdi Yu6ac97982014-01-30 14:49:21 -080032
Yingdi Yu96e64062014-04-15 19:57:33 -070033Validator::Validator(Face& face)
34 : m_hasFace(true)
35 , m_face(face)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070036{
37}
Yingdi Yu6ac97982014-01-30 14:49:21 -080038
39void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070040Validator::validate(const Interest& interest,
41 const OnInterestValidated& onValidated,
42 const OnInterestValidationFailed& onValidationFailed,
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070043 int nSteps)
Yingdi Yu6ac97982014-01-30 14:49:21 -080044{
45 vector<shared_ptr<ValidationRequest> > nextSteps;
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070046 checkPolicy(interest, nSteps, onValidated, onValidationFailed, nextSteps);
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070047
Yingdi Yu6ac97982014-01-30 14:49:21 -080048 if (!nextSteps.empty())
49 {
Yingdi Yu96e64062014-04-15 19:57:33 -070050 if (!m_hasFace)
51 {
52 onValidationFailed(interest.shared_from_this(),
53 "Require more information to validate the interest!");
54 return;
55 }
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070056
Yingdi Yu6ac97982014-01-30 14:49:21 -080057 vector<shared_ptr<ValidationRequest> >::const_iterator it = nextSteps.begin();
Yingdi Yu40587c02014-02-21 16:40:48 -080058 OnFailure onFailure = bind(onValidationFailed, interest.shared_from_this(), _1);
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070059 for (; it != nextSteps.end(); it++)
Yingdi Yu96e64062014-04-15 19:57:33 -070060 m_face.expressInterest((*it)->m_interest,
61 bind(&Validator::onData, this, _1, _2, *it),
62 bind(&Validator::onTimeout,
63 this, _1, (*it)->m_nRetrials,
64 onFailure,
65 *it));
Yingdi Yu6ac97982014-01-30 14:49:21 -080066 }
67 else
68 {
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070069 // If there is no nextStep,
70 // that means InterestPolicy has already been able to verify the Interest.
71 // No more further processes.
Yingdi Yu6ac97982014-01-30 14:49:21 -080072 }
73}
74
75void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070076Validator::validate(const Data& data,
77 const OnDataValidated& onValidated,
78 const OnDataValidationFailed& onValidationFailed,
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070079 int nSteps)
Yingdi Yu6ac97982014-01-30 14:49:21 -080080{
81 vector<shared_ptr<ValidationRequest> > nextSteps;
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070082 checkPolicy(data, nSteps, onValidated, onValidationFailed, nextSteps);
Yingdi Yu6ac97982014-01-30 14:49:21 -080083
84 if (!nextSteps.empty())
85 {
Yingdi Yu96e64062014-04-15 19:57:33 -070086 if (!m_hasFace)
87 {
88 onValidationFailed(data.shared_from_this(),
89 "Require more information to validate the data!");
90 }
Yingdi Yu6ac97982014-01-30 14:49:21 -080091
92 vector<shared_ptr<ValidationRequest> >::const_iterator it = nextSteps.begin();
Yingdi Yu40587c02014-02-21 16:40:48 -080093 OnFailure onFailure = bind(onValidationFailed, data.shared_from_this(), _1);
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070094 for (; it != nextSteps.end(); it++)
Yingdi Yu96e64062014-04-15 19:57:33 -070095 m_face.expressInterest((*it)->m_interest,
96 bind(&Validator::onData, this, _1, _2, *it),
97 bind(&Validator::onTimeout,
98 this, _1, (*it)->m_nRetrials,
99 onFailure,
100 *it));
Yingdi Yu6ac97982014-01-30 14:49:21 -0800101 }
102 else
103 {
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700104 // If there is no nextStep,
105 // that means Data Policy has already been able to verify the Interest.
106 // No more further processes.
Yingdi Yu6ac97982014-01-30 14:49:21 -0800107 }
108}
109
110void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700111Validator::onData(const Interest& interest,
112 const Data& data,
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800113 const shared_ptr<ValidationRequest>& nextStep)
Yingdi Yu6ac97982014-01-30 14:49:21 -0800114{
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700115 validate(data, nextStep->m_onValidated, nextStep->m_onDataValidated, nextStep->m_nSteps);
Yingdi Yu6ac97982014-01-30 14:49:21 -0800116}
117
118void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700119Validator::onTimeout(const Interest& interest,
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700120 int nRetrials,
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700121 const OnFailure& onFailure,
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800122 const shared_ptr<ValidationRequest>& nextStep)
Yingdi Yu6ac97982014-01-30 14:49:21 -0800123{
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700124 if (nRetrials > 0)
125 // Issue the same expressInterest except decrement nRetrials.
Yingdi Yu96e64062014-04-15 19:57:33 -0700126 m_face.expressInterest(interest,
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700127 bind(&Validator::onData, this, _1, _2, nextStep),
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700128 bind(&Validator::onTimeout, this, _1,
129 nRetrials - 1, onFailure, nextStep));
Yingdi Yu6ac97982014-01-30 14:49:21 -0800130 else
Yingdi Yu40587c02014-02-21 16:40:48 -0800131 onFailure("Cannot fetch cert: " + interest.getName().toUri());
Yingdi Yu6ac97982014-01-30 14:49:21 -0800132}
133
134bool
135Validator::verifySignature(const Data& data, const PublicKey& key)
136{
Yingdi Yu40587c02014-02-21 16:40:48 -0800137 try
138 {
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700139 switch (data.getSignature().getType())
Yingdi Yu40587c02014-02-21 16:40:48 -0800140 {
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700141 case Signature::Sha256WithRsa:
142 {
143 SignatureSha256WithRsa sigSha256Rsa(data.getSignature());
144 return verifySignature(data, sigSha256Rsa, key);
145 }
146 default:
147 {
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700148 return false;
149 }
Yingdi Yu40587c02014-02-21 16:40:48 -0800150 }
Yingdi Yu6ac97982014-01-30 14:49:21 -0800151 }
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -0700152 catch (Signature::Error& e)
Yingdi Yu40587c02014-02-21 16:40:48 -0800153 {
Yingdi Yu40587c02014-02-21 16:40:48 -0800154 return false;
155 }
Yingdi Yu6ac97982014-01-30 14:49:21 -0800156 return false;
157}
158
159bool
Yingdi Yu21157162014-02-28 13:02:34 -0800160Validator::verifySignature(const Interest& interest, const PublicKey& key)
Yingdi Yu6ac97982014-01-30 14:49:21 -0800161{
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700162 const Name& interestName = interest.getName();
Yingdi Yu6ac97982014-01-30 14:49:21 -0800163
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700164 if (interestName.size() < 2)
Yingdi Yu6ac97982014-01-30 14:49:21 -0800165 return false;
166
Yingdi Yu40587c02014-02-21 16:40:48 -0800167 try
168 {
169 const Block& nameBlock = interestName.wireEncode();
Yingdi Yu6ac97982014-01-30 14:49:21 -0800170
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700171 Signature sig(interestName[-2].blockFromValue(),
Yingdi Yu40587c02014-02-21 16:40:48 -0800172 interestName[-1].blockFromValue());
Yingdi Yu6ac97982014-01-30 14:49:21 -0800173
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700174 switch (sig.getType())
Yingdi Yu40587c02014-02-21 16:40:48 -0800175 {
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700176 case Signature::Sha256WithRsa:
177 {
178 SignatureSha256WithRsa sigSha256Rsa(sig);
Yingdi Yu6ac97982014-01-30 14:49:21 -0800179
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700180 return verifySignature(nameBlock.value(),
181 nameBlock.value_size() - interestName[-1].size(),
182 sigSha256Rsa, key);
183 }
184 default:
185 {
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700186 return false;
187 }
Yingdi Yu40587c02014-02-21 16:40:48 -0800188 }
Yingdi Yu6ac97982014-01-30 14:49:21 -0800189 }
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -0700190 catch (Signature::Error& e)
Yingdi Yu40587c02014-02-21 16:40:48 -0800191 {
Yingdi Yu40587c02014-02-21 16:40:48 -0800192 return false;
193 }
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -0700194 catch (Block::Error& e)
Yingdi Yu40587c02014-02-21 16:40:48 -0800195 {
Yingdi Yu40587c02014-02-21 16:40:48 -0800196 return false;
197 }
Yingdi Yu6ac97982014-01-30 14:49:21 -0800198 return false;
199}
200
201bool
Yingdi Yu21157162014-02-28 13:02:34 -0800202Validator::verifySignature(const Buffer& data, const Signature& sig, const PublicKey& key)
Yingdi Yu6ac97982014-01-30 14:49:21 -0800203{
Yingdi Yu40587c02014-02-21 16:40:48 -0800204 try
205 {
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700206 switch (sig.getType())
Yingdi Yu40587c02014-02-21 16:40:48 -0800207 {
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700208 case Signature::Sha256WithRsa:
209 {
210 SignatureSha256WithRsa sigSha256Rsa(sig);
211 return verifySignature(data, sigSha256Rsa, key);
212 }
213 default:
214 {
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700215 return false;
216 }
Yingdi Yu40587c02014-02-21 16:40:48 -0800217 }
Yingdi Yu6ac97982014-01-30 14:49:21 -0800218 }
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -0700219 catch (Signature::Error& e)
Yingdi Yu40587c02014-02-21 16:40:48 -0800220 {
Yingdi Yu40587c02014-02-21 16:40:48 -0800221 return false;
222 }
Yingdi Yu6ac97982014-01-30 14:49:21 -0800223 return false;
224}
225
226bool
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700227Validator::verifySignature(const uint8_t* buf,
228 const size_t size,
229 const SignatureSha256WithRsa& sig,
230 const PublicKey& key)
Yingdi Yu6ac97982014-01-30 14:49:21 -0800231{
Yingdi Yu40587c02014-02-21 16:40:48 -0800232 try
233 {
234 using namespace CryptoPP;
Yingdi Yu6ac97982014-01-30 14:49:21 -0800235
Yingdi Yu40587c02014-02-21 16:40:48 -0800236 RSA::PublicKey publicKey;
237 ByteQueue queue;
Yingdi Yu6ac97982014-01-30 14:49:21 -0800238
Yingdi Yu40587c02014-02-21 16:40:48 -0800239 queue.Put(reinterpret_cast<const byte*>(key.get().buf()), key.get().size());
240 publicKey.Load(queue);
Yingdi Yu6ac97982014-01-30 14:49:21 -0800241
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700242 RSASS<PKCS1v15, SHA256>::Verifier verifier(publicKey);
243 return verifier.VerifyMessage(buf, size,
244 sig.getValue().value(),
245 sig.getValue().value_size());
Yingdi Yu40587c02014-02-21 16:40:48 -0800246 }
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -0700247 catch (CryptoPP::Exception& e)
Yingdi Yu40587c02014-02-21 16:40:48 -0800248 {
Yingdi Yu40587c02014-02-21 16:40:48 -0800249 return false;
250 }
Yingdi Yu6ac97982014-01-30 14:49:21 -0800251}
252
Yingdi Yu21157162014-02-28 13:02:34 -0800253bool
254Validator::verifySignature(const uint8_t* buf, const size_t size, const SignatureSha256& sig)
255{
256 try
257 {
258 ConstBufferPtr buffer = crypto::sha256(buf, size);
259 const Block& sigValue = sig.getValue();
260
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700261 if (static_cast<bool>(buffer) &&
262 buffer->size() == sigValue.value_size() &&
263 buffer->size() == crypto::SHA256_DIGEST_SIZE)
Yingdi Yu21157162014-02-28 13:02:34 -0800264 {
265
266 const uint8_t* p1 = buffer->buf();
267 const uint8_t* p2 = sigValue.value();
268
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700269 return 0 == memcmp(p1, p2, crypto::SHA256_DIGEST_SIZE);
Yingdi Yu21157162014-02-28 13:02:34 -0800270 }
271 else
272 return false;
273 }
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -0700274 catch (CryptoPP::Exception& e)
Yingdi Yu21157162014-02-28 13:02:34 -0800275 {
Yingdi Yu21157162014-02-28 13:02:34 -0800276 return false;
277 }
278}
279
Yingdi Yufc40d872014-02-18 12:56:04 -0800280} // namespace ndn