blob: edc036597658cff6b28d9bf193acba6ca0fa6e0b [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/**
Teng Liange6f87512016-07-26 22:14:19 -07003 * Copyright (c) 2013-2016 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
Yingdi Yufc40d872014-02-18 12:56:04 -080025#ifndef NDN_SECURITY_VALIDATOR_HPP
26#define NDN_SECURITY_VALIDATOR_HPP
Yingdi Yu6ac97982014-01-30 14:49:21 -080027
Yingdi Yu6ac97982014-01-30 14:49:21 -080028#include "../face.hpp"
Yingdi Yu6ac97982014-01-30 14:49:21 -080029#include "signature-sha256-with-rsa.hpp"
Yingdi Yuc8f883c2014-06-20 23:25:22 -070030#include "signature-sha256-with-ecdsa.hpp"
Yingdi Yubf6a2812014-06-17 15:32:11 -070031#include "digest-sha256.hpp"
Yingdi Yu6ac97982014-01-30 14:49:21 -080032#include "validation-request.hpp"
Alexander Afanasyev2fa59392016-07-29 17:24:23 -070033#include "v1/public-key.hpp"
34#include "v1/identity-certificate.hpp"
Yingdi Yu6ac97982014-01-30 14:49:21 -080035
36namespace ndn {
Alexander Afanasyev2fa59392016-07-29 17:24:23 -070037namespace security {
Joao Pereira0b3cac52015-07-02 14:49:49 -040038
Yingdi Yu6ac97982014-01-30 14:49:21 -080039/**
Junxiao Shi198c3812016-08-12 19:24:18 +000040 * @brief provides the interfaces for packet validation.
Yingdi Yu6ac97982014-01-30 14:49:21 -080041 */
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -070042class Validator
43{
Yingdi Yu6ac97982014-01-30 14:49:21 -080044public:
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070045 class Error : public std::runtime_error
46 {
47 public:
48 explicit
49 Error(const std::string& what)
50 : std::runtime_error(what)
51 {
52 }
53 };
Yingdi Yu6ac97982014-01-30 14:49:21 -080054
Yingdi Yu4e9b0692014-11-04 16:13:56 -080055 /**
56 * @brief Validator constructor
57 *
58 * @param face Pointer to face through which validator may retrieve certificates.
59 * Passing a null pointer implies the validator is in offline mode.
60 *
61 * @note Make sure the lifetime of the passed Face is longer than validator.
62 */
63 explicit
64 Validator(Face* face = nullptr);
Yingdi Yu6ac97982014-01-30 14:49:21 -080065
Yingdi Yu4e9b0692014-11-04 16:13:56 -080066 /// @deprecated Use the constructor taking Face* as parameter.
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070067 explicit
Yingdi Yu96e64062014-04-15 19:57:33 -070068 Validator(Face& face);
Yingdi Yu6ac97982014-01-30 14:49:21 -080069
Davide Pesaventoc152e6f2016-08-14 02:54:48 +020070 virtual
71 ~Validator();
72
Yingdi Yu6ac97982014-01-30 14:49:21 -080073 /**
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070074 * @brief Validate Data and call either onValidated or onValidationFailed.
75 *
Yingdi Yu6ac97982014-01-30 14:49:21 -080076 * @param data The Data with the signature to check.
77 * @param onValidated If the Data is validated, this calls onValidated(data).
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070078 * @param onValidationFailed If validation fails, this calls onValidationFailed(data).
Yingdi Yu6ac97982014-01-30 14:49:21 -080079 */
80 void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070081 validate(const Data& data,
82 const OnDataValidated& onValidated,
83 const OnDataValidationFailed& onValidationFailed)
84 {
85 validate(data, onValidated, onValidationFailed, 0);
86 }
Yingdi Yu6ac97982014-01-30 14:49:21 -080087
88 /**
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070089 * @brief Validate Interest and call either onValidated or onValidationFailed.
90 *
Yingdi Yu6ac97982014-01-30 14:49:21 -080091 * @param interest The Interest with the signature to check.
92 * @param onValidated If the Interest is validated, this calls onValidated(interest).
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070093 * @param onValidationFailed If validation fails, this calls onValidationFailed(interest).
Yingdi Yu6ac97982014-01-30 14:49:21 -080094 */
95 void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070096 validate(const Interest& interest,
97 const OnInterestValidated& onValidated,
98 const OnInterestValidationFailed& onValidationFailed)
99 {
100 validate(interest, onValidated, onValidationFailed, 0);
101 }
Yingdi Yu6ac97982014-01-30 14:49:21 -0800102
103 /*****************************************
104 * verifySignature method set *
105 *****************************************/
106
107 /// @brief Verify the data using the publicKey.
108 static bool
Alexander Afanasyev2fa59392016-07-29 17:24:23 -0700109 verifySignature(const Data& data, const v1::PublicKey& publicKey);
Yingdi Yu6ac97982014-01-30 14:49:21 -0800110
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700111 /**
112 * @brief Verify the signed Interest using the publicKey.
113 *
114 * (Note the signature covers the first n-2 name components).
115 */
Yingdi Yu6ac97982014-01-30 14:49:21 -0800116 static bool
Alexander Afanasyev2fa59392016-07-29 17:24:23 -0700117 verifySignature(const Interest& interest, const v1::PublicKey& publicKey);
Yingdi Yu6ac97982014-01-30 14:49:21 -0800118
119 /// @brief Verify the blob using the publicKey against the signature.
120 static bool
Alexander Afanasyev2fa59392016-07-29 17:24:23 -0700121 verifySignature(const Buffer& blob, const Signature& sig, const v1::PublicKey& publicKey)
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700122 {
123 return verifySignature(blob.buf(), blob.size(), sig, publicKey);
124 }
Yingdi Yu6ac97982014-01-30 14:49:21 -0800125
126 /// @brief Verify the data using the publicKey against the SHA256-RSA signature.
127 static bool
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700128 verifySignature(const Data& data,
Yingdi Yu4a557052014-07-09 16:40:37 -0700129 const Signature& sig,
Alexander Afanasyev2fa59392016-07-29 17:24:23 -0700130 const v1::PublicKey& publicKey)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700131 {
132 return verifySignature(data.wireEncode().value(),
133 data.wireEncode().value_size() - data.getSignature().getValue().size(),
134 sig, publicKey);
135 }
136
137 /** @brief Verify the interest using the publicKey against the SHA256-RSA signature.
138 *
139 * (Note the signature covers the first n-2 name components).
140 */
141 static bool
142 verifySignature(const Interest& interest,
Yingdi Yu4a557052014-07-09 16:40:37 -0700143 const Signature& sig,
Alexander Afanasyev2fa59392016-07-29 17:24:23 -0700144 const v1::PublicKey& publicKey)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700145 {
146 if (interest.getName().size() < 2)
147 return false;
148
Yingdi Yu3cca4ab2014-04-11 12:46:53 -0700149 const Name& name = interest.getName();
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700150
Yingdi Yu3cca4ab2014-04-11 12:46:53 -0700151 return verifySignature(name.wireEncode().value(),
152 name.wireEncode().value_size() - name[-1].size(),
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700153 sig, publicKey);
154 }
Yingdi Yu6ac97982014-01-30 14:49:21 -0800155
156 /// @brief Verify the blob using the publicKey against the SHA256-RSA signature.
157 static bool
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700158 verifySignature(const uint8_t* buf,
159 const size_t size,
Yingdi Yu4a557052014-07-09 16:40:37 -0700160 const Signature& sig,
Alexander Afanasyev2fa59392016-07-29 17:24:23 -0700161 const v1::PublicKey& publicKey);
Yingdi Yu6ac97982014-01-30 14:49:21 -0800162
Yingdi Yu21157162014-02-28 13:02:34 -0800163
164 /// @brief Verify the data against the SHA256 signature.
165 static bool
Yingdi Yubf6a2812014-06-17 15:32:11 -0700166 verifySignature(const Data& data, const DigestSha256& sig)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700167 {
168 return verifySignature(data.wireEncode().value(),
169 data.wireEncode().value_size() -
170 data.getSignature().getValue().size(),
171 sig);
172 }
173
174 /** @brief Verify the interest against the SHA256 signature.
175 *
176 * (Note the signature covers the first n-2 name components).
177 */
178 static bool
Yingdi Yubf6a2812014-06-17 15:32:11 -0700179 verifySignature(const Interest& interest, const DigestSha256& sig)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700180 {
181 if (interest.getName().size() < 2)
182 return false;
183
Yingdi Yu6ab67812014-11-27 15:00:34 -0800184 const Name& name = interest.getName();
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700185
Yingdi Yu6ab67812014-11-27 15:00:34 -0800186 return verifySignature(name.wireEncode().value(),
187 name.wireEncode().value_size() - name[-1].size(),
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700188 sig);
189 }
Yingdi Yu21157162014-02-28 13:02:34 -0800190
191 /// @brief Verify the blob against the SHA256 signature.
192 static bool
Yingdi Yubf6a2812014-06-17 15:32:11 -0700193 verifySignature(const Buffer& blob, const DigestSha256& sig)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700194 {
195 return verifySignature (blob.buf(), blob.size(), sig);
196 }
197
Yingdi Yu21157162014-02-28 13:02:34 -0800198 /// @brief Verify the blob against the SHA256 signature.
199 static bool
Yingdi Yubf6a2812014-06-17 15:32:11 -0700200 verifySignature(const uint8_t* buf, const size_t size, const DigestSha256& sig);
Yingdi Yu21157162014-02-28 13:02:34 -0800201
Yingdi Yu6ac97982014-01-30 14:49:21 -0800202protected:
203 /**
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700204 * @brief Check the Data against policy and return the next validation step if necessary.
Yingdi Yu6ac97982014-01-30 14:49:21 -0800205 *
206 * If there is no next validation step, that validation MUST have been done.
207 * i.e., either onValidated or onValidationFailed callback is invoked.
208 *
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700209 * @param data The Data to check.
210 * @param nSteps The number of validation steps that have been done.
211 * @param onValidated If the Data is validated, this calls onValidated(data)
212 * @param onValidationFailed If validation fails, this calls onValidationFailed(data)
213 * @param nextSteps On return, contains the next validation step
Yingdi Yu6ac97982014-01-30 14:49:21 -0800214 */
215 virtual void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700216 checkPolicy(const Data& data,
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700217 int nSteps,
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700218 const OnDataValidated& onValidated,
219 const OnDataValidationFailed& onValidationFailed,
Davide Pesaventoc152e6f2016-08-14 02:54:48 +0200220 std::vector<shared_ptr<ValidationRequest>>& nextSteps) = 0;
Yingdi Yu6ac97982014-01-30 14:49:21 -0800221
222 /**
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700223 * @brief Check the Interest against validation policy and return the next validation step
224 * if necessary.
Yingdi Yu6ac97982014-01-30 14:49:21 -0800225 *
226 * If there is no next validation step, that validation MUST have been done.
227 * i.e., either onValidated or onValidationFailed callback is invoked.
228 *
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700229 * @param interest The Interest to check.
230 * @param nSteps The number of validation steps that have been done.
231 * @param onValidated If the Interest is validated, this calls onValidated(data)
232 * @param onValidationFailed If validation fails, this calls onValidationFailed(data)
233 * @param nextSteps On return, contains the next validation step
Yingdi Yu6ac97982014-01-30 14:49:21 -0800234 */
235 virtual void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700236 checkPolicy(const Interest& interest,
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700237 int nSteps,
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700238 const OnInterestValidated& onValidated,
239 const OnInterestValidationFailed& onValidationFailed,
Davide Pesaventoc152e6f2016-08-14 02:54:48 +0200240 std::vector<shared_ptr<ValidationRequest>>& nextSteps) = 0;
Yingdi Yu6ac97982014-01-30 14:49:21 -0800241
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700242 typedef function<void(const std::string&)> OnFailure;
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700243
Yingdi Yu6ac97982014-01-30 14:49:21 -0800244 /// @brief Process the received certificate.
245 void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700246 onData(const Interest& interest,
247 const Data& data,
248 const shared_ptr<ValidationRequest>& nextStep);
249
Yingdi Yu6ac97982014-01-30 14:49:21 -0800250 void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700251 validate(const Data& data,
252 const OnDataValidated& onValidated,
253 const OnDataValidationFailed& onValidationFailed,
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700254 int nSteps);
Yingdi Yu6ac97982014-01-30 14:49:21 -0800255
256 void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700257 validate(const Interest& interest,
258 const OnInterestValidated& onValidated,
259 const OnInterestValidationFailed& onValidationFailed,
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700260 int nSteps);
Yingdi Yu6ac97982014-01-30 14:49:21 -0800261
Yingdi Yud9006e72014-06-23 19:10:44 -0700262 /// Hooks
263
264 /**
265 * @brief trigger before validating requested certificate.
266 *
267 * The Data:
268 * - matches the interest in the validation-request.
269 * - may be certificate or a data encapsulating certificate.
270 *
271 * This method returns a data (actually certificate) that is will be passed as Data into:
272 * Validator::validate(const Data& data,
273 * const OnDataValidated& onValidated,
274 * const OnDataValidationFailed& onValidationFailed,
275 * int nSteps);
276 */
277 virtual shared_ptr<const Data>
278 preCertificateValidation(const Data& data)
279 {
280 return data.shared_from_this();
281 }
282
283 /**
Teng Liange6f87512016-07-26 22:14:19 -0700284 * @brief trigger when interest retrieves a Nack.
285 *
286 * Validator can decide how to handle a Nack, either call onFailure, or retry.
287 *
288 * @param interest The interest that retrieves a Nack.
289 * @param nack The Nack that is retrieved.
290 * @param nRemainingRetries The number of retries left.
291 * @param onFailure Failure callback when there is no more retries remaining.
292 * @param validationRequest The validationRequest containing the context of the interest.
293 */
294 virtual void
295 onNack(const Interest& interest,
296 const lp::Nack& nack,
297 int nRemainingRetries,
298 const OnFailure& onFailure,
299 const shared_ptr<ValidationRequest>& validationRequest);
300
301 /**
Yingdi Yud9006e72014-06-23 19:10:44 -0700302 * @brief trigger when interest for certificate times out.
303 *
304 * Validator can decide how to handle the timeout, either call onFailure, or retry.
305 *
306 * @param interest The interest that times out.
307 * @param nRemainingRetries The number of retries left.
308 * @param onFailure Failure callback when there is no more retries remaining.
309 * @param validationRequest The validationRequest containing the context of the interest.
310 */
Yingdi Yud9006e72014-06-23 19:10:44 -0700311 virtual void
312 onTimeout(const Interest& interest,
313 int nRemainingRetries,
314 const OnFailure& onFailure,
315 const shared_ptr<ValidationRequest>& validationRequest);
316
317 /**
318 * @brief trigger after checkPolicy is done.
319 *
320 * Validator can decide how to handle the set of validation requests according to
321 * the trust model.
322 *
323 * @param nextSteps A set of validation request made by checkPolicy.
324 * @param onFailure Failure callback when errors happen in processing nextSteps.
325 */
326 virtual void
Davide Pesaventoc152e6f2016-08-14 02:54:48 +0200327 afterCheckPolicy(const std::vector<shared_ptr<ValidationRequest>>& nextSteps,
Yingdi Yud9006e72014-06-23 19:10:44 -0700328 const OnFailure& onFailure);
329
Yingdi Yu6ac97982014-01-30 14:49:21 -0800330protected:
Yingdi Yu4e9b0692014-11-04 16:13:56 -0800331 Face* m_face;
Yingdi Yu6ac97982014-01-30 14:49:21 -0800332};
333
Alexander Afanasyev2fa59392016-07-29 17:24:23 -0700334} // namespace security
335
336using security::Validator;
337
Yingdi Yufc40d872014-02-18 12:56:04 -0800338} // namespace ndn
Yingdi Yu6ac97982014-01-30 14:49:21 -0800339
Yingdi Yu4e9b0692014-11-04 16:13:56 -0800340#endif // NDN_SECURITY_VALIDATOR_HPP