blob: bb401b97e7d9cea1168bdb2f90cabb4061962412 [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/**
Zhiyi Zhang48becde2017-01-05 16:41:38 -08003 * Copyright (c) 2013-2017 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.
Yingdi Yu6ac97982014-01-30 14:49:21 -080020 */
21
Yingdi Yufc40d872014-02-18 12:56:04 -080022#ifndef NDN_SECURITY_VALIDATOR_HPP
23#define NDN_SECURITY_VALIDATOR_HPP
Yingdi Yu6ac97982014-01-30 14:49:21 -080024
Yingdi Yu6ac97982014-01-30 14:49:21 -080025#include "../face.hpp"
Yingdi Yu6ac97982014-01-30 14:49:21 -080026#include "signature-sha256-with-rsa.hpp"
Yingdi Yuc8f883c2014-06-20 23:25:22 -070027#include "signature-sha256-with-ecdsa.hpp"
Yingdi Yubf6a2812014-06-17 15:32:11 -070028#include "digest-sha256.hpp"
Yingdi Yu6ac97982014-01-30 14:49:21 -080029#include "validation-request.hpp"
Alexander Afanasyev2fa59392016-07-29 17:24:23 -070030#include "v1/public-key.hpp"
31#include "v1/identity-certificate.hpp"
Yingdi Yu6ac97982014-01-30 14:49:21 -080032
33namespace ndn {
Alexander Afanasyev2fa59392016-07-29 17:24:23 -070034namespace security {
Joao Pereira0b3cac52015-07-02 14:49:49 -040035
Yingdi Yu6ac97982014-01-30 14:49:21 -080036/**
Junxiao Shi198c3812016-08-12 19:24:18 +000037 * @brief provides the interfaces for packet validation.
Yingdi Yu6ac97982014-01-30 14:49:21 -080038 */
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -070039class Validator
40{
Yingdi Yu6ac97982014-01-30 14:49:21 -080041public:
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070042 class Error : public std::runtime_error
43 {
44 public:
45 explicit
46 Error(const std::string& what)
47 : std::runtime_error(what)
48 {
49 }
50 };
Yingdi Yu6ac97982014-01-30 14:49:21 -080051
Yingdi Yu4e9b0692014-11-04 16:13:56 -080052 /**
53 * @brief Validator constructor
54 *
55 * @param face Pointer to face through which validator may retrieve certificates.
56 * Passing a null pointer implies the validator is in offline mode.
57 *
58 * @note Make sure the lifetime of the passed Face is longer than validator.
59 */
60 explicit
61 Validator(Face* face = nullptr);
Yingdi Yu6ac97982014-01-30 14:49:21 -080062
Yingdi Yu4e9b0692014-11-04 16:13:56 -080063 /// @deprecated Use the constructor taking Face* as parameter.
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070064 explicit
Yingdi Yu96e64062014-04-15 19:57:33 -070065 Validator(Face& face);
Yingdi Yu6ac97982014-01-30 14:49:21 -080066
Davide Pesaventoc152e6f2016-08-14 02:54:48 +020067 virtual
68 ~Validator();
69
Yingdi Yu6ac97982014-01-30 14:49:21 -080070 /**
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070071 * @brief Validate Data and call either onValidated or onValidationFailed.
72 *
Yingdi Yu6ac97982014-01-30 14:49:21 -080073 * @param data The Data with the signature to check.
74 * @param onValidated If the Data is validated, this calls onValidated(data).
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070075 * @param onValidationFailed If validation fails, this calls onValidationFailed(data).
Yingdi Yu6ac97982014-01-30 14:49:21 -080076 */
77 void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070078 validate(const Data& data,
79 const OnDataValidated& onValidated,
80 const OnDataValidationFailed& onValidationFailed)
81 {
82 validate(data, onValidated, onValidationFailed, 0);
83 }
Yingdi Yu6ac97982014-01-30 14:49:21 -080084
85 /**
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070086 * @brief Validate Interest and call either onValidated or onValidationFailed.
87 *
Yingdi Yu6ac97982014-01-30 14:49:21 -080088 * @param interest The Interest with the signature to check.
89 * @param onValidated If the Interest is validated, this calls onValidated(interest).
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070090 * @param onValidationFailed If validation fails, this calls onValidationFailed(interest).
Yingdi Yu6ac97982014-01-30 14:49:21 -080091 */
92 void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070093 validate(const Interest& interest,
94 const OnInterestValidated& onValidated,
95 const OnInterestValidationFailed& onValidationFailed)
96 {
97 validate(interest, onValidated, onValidationFailed, 0);
98 }
Yingdi Yu6ac97982014-01-30 14:49:21 -080099
Zhiyi Zhang48becde2017-01-05 16:41:38 -0800100 /**
101 * @brief Enable or disable the direct certificate fetch feature.
102 *
103 * When enabled, the validator will attempt to fetch the certificate that signs an Interest from
104 * the sender of that Interest, as identified by IncomingFaceId field, in addition to fetching
105 * from the infrastructure.
106 *
107 * Prior to enabling this feature, the application must enable NextHopFaceId privilege on the face
108 * used by this validator.
109 *
110 * @note Current implementation can only fetch the Interest signer certificate from the
111 * Interest sender; the issuer certificate of that certificate is only fetched from the
112 * infrastructure.
113 *
114 * @note Currently, this feature can only be used with ValidatorConfig.
115 *
116 * @param isEnabled Set true to enable the feature or false to disable.
117 */
118 void
119 setDirectCertFetchEnabled(bool isEnabled);
120
Yingdi Yu6ac97982014-01-30 14:49:21 -0800121 /*****************************************
122 * verifySignature method set *
123 *****************************************/
124
125 /// @brief Verify the data using the publicKey.
126 static bool
Alexander Afanasyev2fa59392016-07-29 17:24:23 -0700127 verifySignature(const Data& data, const v1::PublicKey& publicKey);
Yingdi Yu6ac97982014-01-30 14:49:21 -0800128
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700129 /**
130 * @brief Verify the signed Interest using the publicKey.
131 *
132 * (Note the signature covers the first n-2 name components).
133 */
Yingdi Yu6ac97982014-01-30 14:49:21 -0800134 static bool
Alexander Afanasyev2fa59392016-07-29 17:24:23 -0700135 verifySignature(const Interest& interest, const v1::PublicKey& publicKey);
Yingdi Yu6ac97982014-01-30 14:49:21 -0800136
137 /// @brief Verify the blob using the publicKey against the signature.
138 static bool
Alexander Afanasyev2fa59392016-07-29 17:24:23 -0700139 verifySignature(const Buffer& blob, const Signature& sig, const v1::PublicKey& publicKey)
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700140 {
141 return verifySignature(blob.buf(), blob.size(), sig, publicKey);
142 }
Yingdi Yu6ac97982014-01-30 14:49:21 -0800143
144 /// @brief Verify the data using the publicKey against the SHA256-RSA signature.
145 static bool
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700146 verifySignature(const Data& data,
Yingdi Yu4a557052014-07-09 16:40:37 -0700147 const Signature& sig,
Alexander Afanasyev2fa59392016-07-29 17:24:23 -0700148 const v1::PublicKey& publicKey)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700149 {
150 return verifySignature(data.wireEncode().value(),
151 data.wireEncode().value_size() - data.getSignature().getValue().size(),
152 sig, publicKey);
153 }
154
155 /** @brief Verify the interest using the publicKey against the SHA256-RSA signature.
156 *
157 * (Note the signature covers the first n-2 name components).
158 */
159 static bool
160 verifySignature(const Interest& interest,
Yingdi Yu4a557052014-07-09 16:40:37 -0700161 const Signature& sig,
Alexander Afanasyev2fa59392016-07-29 17:24:23 -0700162 const v1::PublicKey& publicKey)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700163 {
164 if (interest.getName().size() < 2)
165 return false;
166
Yingdi Yu3cca4ab2014-04-11 12:46:53 -0700167 const Name& name = interest.getName();
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700168
Yingdi Yu3cca4ab2014-04-11 12:46:53 -0700169 return verifySignature(name.wireEncode().value(),
170 name.wireEncode().value_size() - name[-1].size(),
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700171 sig, publicKey);
172 }
Yingdi Yu6ac97982014-01-30 14:49:21 -0800173
174 /// @brief Verify the blob using the publicKey against the SHA256-RSA signature.
175 static bool
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700176 verifySignature(const uint8_t* buf,
177 const size_t size,
Yingdi Yu4a557052014-07-09 16:40:37 -0700178 const Signature& sig,
Alexander Afanasyev2fa59392016-07-29 17:24:23 -0700179 const v1::PublicKey& publicKey);
Yingdi Yu6ac97982014-01-30 14:49:21 -0800180
Yingdi Yu21157162014-02-28 13:02:34 -0800181
182 /// @brief Verify the data against the SHA256 signature.
183 static bool
Yingdi Yubf6a2812014-06-17 15:32:11 -0700184 verifySignature(const Data& data, const DigestSha256& sig)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700185 {
186 return verifySignature(data.wireEncode().value(),
187 data.wireEncode().value_size() -
188 data.getSignature().getValue().size(),
189 sig);
190 }
191
192 /** @brief Verify the interest against the SHA256 signature.
193 *
194 * (Note the signature covers the first n-2 name components).
195 */
196 static bool
Yingdi Yubf6a2812014-06-17 15:32:11 -0700197 verifySignature(const Interest& interest, const DigestSha256& sig)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700198 {
199 if (interest.getName().size() < 2)
200 return false;
201
Yingdi Yu6ab67812014-11-27 15:00:34 -0800202 const Name& name = interest.getName();
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700203
Yingdi Yu6ab67812014-11-27 15:00:34 -0800204 return verifySignature(name.wireEncode().value(),
205 name.wireEncode().value_size() - name[-1].size(),
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700206 sig);
207 }
Yingdi Yu21157162014-02-28 13:02:34 -0800208
209 /// @brief Verify the blob against the SHA256 signature.
210 static bool
Yingdi Yubf6a2812014-06-17 15:32:11 -0700211 verifySignature(const Buffer& blob, const DigestSha256& sig)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700212 {
213 return verifySignature (blob.buf(), blob.size(), sig);
214 }
215
Yingdi Yu21157162014-02-28 13:02:34 -0800216 /// @brief Verify the blob against the SHA256 signature.
217 static bool
Yingdi Yubf6a2812014-06-17 15:32:11 -0700218 verifySignature(const uint8_t* buf, const size_t size, const DigestSha256& sig);
Yingdi Yu21157162014-02-28 13:02:34 -0800219
Yingdi Yu6ac97982014-01-30 14:49:21 -0800220protected:
221 /**
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700222 * @brief Check the Data against policy and return the next validation step if necessary.
Yingdi Yu6ac97982014-01-30 14:49:21 -0800223 *
224 * If there is no next validation step, that validation MUST have been done.
225 * i.e., either onValidated or onValidationFailed callback is invoked.
226 *
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700227 * @param data The Data to check.
228 * @param nSteps The number of validation steps that have been done.
229 * @param onValidated If the Data is validated, this calls onValidated(data)
230 * @param onValidationFailed If validation fails, this calls onValidationFailed(data)
231 * @param nextSteps On return, contains the next validation step
Yingdi Yu6ac97982014-01-30 14:49:21 -0800232 */
233 virtual void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700234 checkPolicy(const Data& data,
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700235 int nSteps,
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700236 const OnDataValidated& onValidated,
237 const OnDataValidationFailed& onValidationFailed,
Davide Pesaventoc152e6f2016-08-14 02:54:48 +0200238 std::vector<shared_ptr<ValidationRequest>>& nextSteps) = 0;
Yingdi Yu6ac97982014-01-30 14:49:21 -0800239
240 /**
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700241 * @brief Check the Interest against validation policy and return the next validation step
242 * if necessary.
Yingdi Yu6ac97982014-01-30 14:49:21 -0800243 *
244 * If there is no next validation step, that validation MUST have been done.
245 * i.e., either onValidated or onValidationFailed callback is invoked.
246 *
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700247 * @param interest The Interest to check.
248 * @param nSteps The number of validation steps that have been done.
249 * @param onValidated If the Interest is validated, this calls onValidated(data)
250 * @param onValidationFailed If validation fails, this calls onValidationFailed(data)
251 * @param nextSteps On return, contains the next validation step
Yingdi Yu6ac97982014-01-30 14:49:21 -0800252 */
253 virtual void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700254 checkPolicy(const Interest& interest,
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700255 int nSteps,
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700256 const OnInterestValidated& onValidated,
257 const OnInterestValidationFailed& onValidationFailed,
Davide Pesaventoc152e6f2016-08-14 02:54:48 +0200258 std::vector<shared_ptr<ValidationRequest>>& nextSteps) = 0;
Yingdi Yu6ac97982014-01-30 14:49:21 -0800259
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700260 typedef function<void(const std::string&)> OnFailure;
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700261
Yingdi Yu6ac97982014-01-30 14:49:21 -0800262 /// @brief Process the received certificate.
263 void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700264 onData(const Interest& interest,
265 const Data& data,
266 const shared_ptr<ValidationRequest>& nextStep);
267
Yingdi Yu6ac97982014-01-30 14:49:21 -0800268 void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700269 validate(const Data& data,
270 const OnDataValidated& onValidated,
271 const OnDataValidationFailed& onValidationFailed,
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700272 int nSteps);
Yingdi Yu6ac97982014-01-30 14:49:21 -0800273
274 void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700275 validate(const Interest& interest,
276 const OnInterestValidated& onValidated,
277 const OnInterestValidationFailed& onValidationFailed,
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700278 int nSteps);
Yingdi Yu6ac97982014-01-30 14:49:21 -0800279
Yingdi Yud9006e72014-06-23 19:10:44 -0700280 /// Hooks
281
282 /**
283 * @brief trigger before validating requested certificate.
284 *
285 * The Data:
286 * - matches the interest in the validation-request.
287 * - may be certificate or a data encapsulating certificate.
288 *
289 * This method returns a data (actually certificate) that is will be passed as Data into:
290 * Validator::validate(const Data& data,
291 * const OnDataValidated& onValidated,
292 * const OnDataValidationFailed& onValidationFailed,
293 * int nSteps);
294 */
295 virtual shared_ptr<const Data>
296 preCertificateValidation(const Data& data)
297 {
298 return data.shared_from_this();
299 }
300
301 /**
Teng Liange6f87512016-07-26 22:14:19 -0700302 * @brief trigger when interest retrieves a Nack.
303 *
304 * Validator can decide how to handle a Nack, either call onFailure, or retry.
305 *
306 * @param interest The interest that retrieves a Nack.
307 * @param nack The Nack that is retrieved.
308 * @param nRemainingRetries The number of retries left.
309 * @param onFailure Failure callback when there is no more retries remaining.
310 * @param validationRequest The validationRequest containing the context of the interest.
311 */
312 virtual void
313 onNack(const Interest& interest,
314 const lp::Nack& nack,
315 int nRemainingRetries,
316 const OnFailure& onFailure,
317 const shared_ptr<ValidationRequest>& validationRequest);
318
319 /**
Yingdi Yud9006e72014-06-23 19:10:44 -0700320 * @brief trigger when interest for certificate times out.
321 *
322 * Validator can decide how to handle the timeout, either call onFailure, or retry.
323 *
324 * @param interest The interest that times out.
325 * @param nRemainingRetries The number of retries left.
326 * @param onFailure Failure callback when there is no more retries remaining.
327 * @param validationRequest The validationRequest containing the context of the interest.
328 */
Yingdi Yud9006e72014-06-23 19:10:44 -0700329 virtual void
330 onTimeout(const Interest& interest,
331 int nRemainingRetries,
332 const OnFailure& onFailure,
333 const shared_ptr<ValidationRequest>& validationRequest);
334
335 /**
336 * @brief trigger after checkPolicy is done.
337 *
338 * Validator can decide how to handle the set of validation requests according to
339 * the trust model.
340 *
341 * @param nextSteps A set of validation request made by checkPolicy.
342 * @param onFailure Failure callback when errors happen in processing nextSteps.
343 */
344 virtual void
Davide Pesaventoc152e6f2016-08-14 02:54:48 +0200345 afterCheckPolicy(const std::vector<shared_ptr<ValidationRequest>>& nextSteps,
Yingdi Yud9006e72014-06-23 19:10:44 -0700346 const OnFailure& onFailure);
347
Yingdi Yu6ac97982014-01-30 14:49:21 -0800348protected:
Yingdi Yu4e9b0692014-11-04 16:13:56 -0800349 Face* m_face;
Zhiyi Zhang48becde2017-01-05 16:41:38 -0800350 bool m_wantDirectCertFetch;
Yingdi Yu6ac97982014-01-30 14:49:21 -0800351};
352
Alexander Afanasyev2fa59392016-07-29 17:24:23 -0700353} // namespace security
354
355using security::Validator;
356
Yingdi Yufc40d872014-02-18 12:56:04 -0800357} // namespace ndn
Yingdi Yu6ac97982014-01-30 14:49:21 -0800358
Yingdi Yu4e9b0692014-11-04 16:13:56 -0800359#endif // NDN_SECURITY_VALIDATOR_HPP