blob: e6eec8d91be8a8c2534535833493c80818cd02fd [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"
29#include "public-key.hpp"
30#include "signature-sha256-with-rsa.hpp"
Yingdi Yuc8f883c2014-06-20 23:25:22 -070031#include "signature-sha256-with-ecdsa.hpp"
Yingdi Yubf6a2812014-06-17 15:32:11 -070032#include "digest-sha256.hpp"
Yingdi Yu6ac97982014-01-30 14:49:21 -080033#include "validation-request.hpp"
Joao Pereira0b3cac52015-07-02 14:49:49 -040034#include "identity-certificate.hpp"
Yingdi Yu6ac97982014-01-30 14:49:21 -080035
36namespace ndn {
Joao Pereira0b3cac52015-07-02 14:49:49 -040037
Yingdi Yu6ac97982014-01-30 14:49:21 -080038/**
Junxiao Shi198c3812016-08-12 19:24:18 +000039 * @brief provides the interfaces for packet validation.
Yingdi Yu6ac97982014-01-30 14:49:21 -080040 */
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -070041class Validator
42{
Yingdi Yu6ac97982014-01-30 14:49:21 -080043public:
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070044 class Error : public std::runtime_error
45 {
46 public:
47 explicit
48 Error(const std::string& what)
49 : std::runtime_error(what)
50 {
51 }
52 };
Yingdi Yu6ac97982014-01-30 14:49:21 -080053
Yingdi Yu4e9b0692014-11-04 16:13:56 -080054 /**
55 * @brief Validator constructor
56 *
57 * @param face Pointer to face through which validator may retrieve certificates.
58 * Passing a null pointer implies the validator is in offline mode.
59 *
60 * @note Make sure the lifetime of the passed Face is longer than validator.
61 */
62 explicit
63 Validator(Face* face = nullptr);
Yingdi Yu6ac97982014-01-30 14:49:21 -080064
Yingdi Yu4e9b0692014-11-04 16:13:56 -080065 /// @deprecated Use the constructor taking Face* as parameter.
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070066 explicit
Yingdi Yu96e64062014-04-15 19:57:33 -070067 Validator(Face& face);
Yingdi Yu6ac97982014-01-30 14:49:21 -080068
Davide Pesaventoc152e6f2016-08-14 02:54:48 +020069 virtual
70 ~Validator();
71
Yingdi Yu6ac97982014-01-30 14:49:21 -080072 /**
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070073 * @brief Validate Data and call either onValidated or onValidationFailed.
74 *
Yingdi Yu6ac97982014-01-30 14:49:21 -080075 * @param data The Data with the signature to check.
76 * @param onValidated If the Data is validated, this calls onValidated(data).
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070077 * @param onValidationFailed If validation fails, this calls onValidationFailed(data).
Yingdi Yu6ac97982014-01-30 14:49:21 -080078 */
79 void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070080 validate(const Data& data,
81 const OnDataValidated& onValidated,
82 const OnDataValidationFailed& onValidationFailed)
83 {
84 validate(data, onValidated, onValidationFailed, 0);
85 }
Yingdi Yu6ac97982014-01-30 14:49:21 -080086
87 /**
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070088 * @brief Validate Interest and call either onValidated or onValidationFailed.
89 *
Yingdi Yu6ac97982014-01-30 14:49:21 -080090 * @param interest The Interest with the signature to check.
91 * @param onValidated If the Interest is validated, this calls onValidated(interest).
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070092 * @param onValidationFailed If validation fails, this calls onValidationFailed(interest).
Yingdi Yu6ac97982014-01-30 14:49:21 -080093 */
94 void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070095 validate(const Interest& interest,
96 const OnInterestValidated& onValidated,
97 const OnInterestValidationFailed& onValidationFailed)
98 {
99 validate(interest, onValidated, onValidationFailed, 0);
100 }
Yingdi Yu6ac97982014-01-30 14:49:21 -0800101
102 /*****************************************
103 * verifySignature method set *
104 *****************************************/
105
106 /// @brief Verify the data using the publicKey.
107 static bool
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700108 verifySignature(const Data& data, const PublicKey& publicKey);
Yingdi Yu6ac97982014-01-30 14:49:21 -0800109
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700110 /**
111 * @brief Verify the signed Interest using the publicKey.
112 *
113 * (Note the signature covers the first n-2 name components).
114 */
Yingdi Yu6ac97982014-01-30 14:49:21 -0800115 static bool
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700116 verifySignature(const Interest& interest, const PublicKey& publicKey);
Yingdi Yu6ac97982014-01-30 14:49:21 -0800117
118 /// @brief Verify the blob using the publicKey against the signature.
119 static bool
Yingdi Yu4a557052014-07-09 16:40:37 -0700120 verifySignature(const Buffer& blob, const Signature& sig, const PublicKey& publicKey)
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700121 {
122 return verifySignature(blob.buf(), blob.size(), sig, publicKey);
123 }
Yingdi Yu6ac97982014-01-30 14:49:21 -0800124
125 /// @brief Verify the data using the publicKey against the SHA256-RSA signature.
126 static bool
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700127 verifySignature(const Data& data,
Yingdi Yu4a557052014-07-09 16:40:37 -0700128 const Signature& sig,
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700129 const PublicKey& publicKey)
130 {
131 return verifySignature(data.wireEncode().value(),
132 data.wireEncode().value_size() - data.getSignature().getValue().size(),
133 sig, publicKey);
134 }
135
136 /** @brief Verify the interest using the publicKey against the SHA256-RSA signature.
137 *
138 * (Note the signature covers the first n-2 name components).
139 */
140 static bool
141 verifySignature(const Interest& interest,
Yingdi Yu4a557052014-07-09 16:40:37 -0700142 const Signature& sig,
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700143 const PublicKey& publicKey)
144 {
145 if (interest.getName().size() < 2)
146 return false;
147
Yingdi Yu3cca4ab2014-04-11 12:46:53 -0700148 const Name& name = interest.getName();
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700149
Yingdi Yu3cca4ab2014-04-11 12:46:53 -0700150 return verifySignature(name.wireEncode().value(),
151 name.wireEncode().value_size() - name[-1].size(),
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700152 sig, publicKey);
153 }
Yingdi Yu6ac97982014-01-30 14:49:21 -0800154
155 /// @brief Verify the blob using the publicKey against the SHA256-RSA signature.
156 static bool
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700157 verifySignature(const uint8_t* buf,
158 const size_t size,
Yingdi Yu4a557052014-07-09 16:40:37 -0700159 const Signature& sig,
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700160 const PublicKey& publicKey);
Yingdi Yu6ac97982014-01-30 14:49:21 -0800161
Yingdi Yu21157162014-02-28 13:02:34 -0800162
163 /// @brief Verify the data against the SHA256 signature.
164 static bool
Yingdi Yubf6a2812014-06-17 15:32:11 -0700165 verifySignature(const Data& data, const DigestSha256& sig)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700166 {
167 return verifySignature(data.wireEncode().value(),
168 data.wireEncode().value_size() -
169 data.getSignature().getValue().size(),
170 sig);
171 }
172
173 /** @brief Verify the interest against the SHA256 signature.
174 *
175 * (Note the signature covers the first n-2 name components).
176 */
177 static bool
Yingdi Yubf6a2812014-06-17 15:32:11 -0700178 verifySignature(const Interest& interest, const DigestSha256& sig)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700179 {
180 if (interest.getName().size() < 2)
181 return false;
182
Yingdi Yu6ab67812014-11-27 15:00:34 -0800183 const Name& name = interest.getName();
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700184
Yingdi Yu6ab67812014-11-27 15:00:34 -0800185 return verifySignature(name.wireEncode().value(),
186 name.wireEncode().value_size() - name[-1].size(),
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700187 sig);
188 }
Yingdi Yu21157162014-02-28 13:02:34 -0800189
190 /// @brief Verify the blob against the SHA256 signature.
191 static bool
Yingdi Yubf6a2812014-06-17 15:32:11 -0700192 verifySignature(const Buffer& blob, const DigestSha256& sig)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700193 {
194 return verifySignature (blob.buf(), blob.size(), sig);
195 }
196
Yingdi Yu21157162014-02-28 13:02:34 -0800197 /// @brief Verify the blob against the SHA256 signature.
198 static bool
Yingdi Yubf6a2812014-06-17 15:32:11 -0700199 verifySignature(const uint8_t* buf, const size_t size, const DigestSha256& sig);
Yingdi Yu21157162014-02-28 13:02:34 -0800200
Yingdi Yu6ac97982014-01-30 14:49:21 -0800201protected:
202 /**
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700203 * @brief Check the Data against policy and return the next validation step if necessary.
Yingdi Yu6ac97982014-01-30 14:49:21 -0800204 *
205 * If there is no next validation step, that validation MUST have been done.
206 * i.e., either onValidated or onValidationFailed callback is invoked.
207 *
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700208 * @param data The Data to check.
209 * @param nSteps The number of validation steps that have been done.
210 * @param onValidated If the Data is validated, this calls onValidated(data)
211 * @param onValidationFailed If validation fails, this calls onValidationFailed(data)
212 * @param nextSteps On return, contains the next validation step
Yingdi Yu6ac97982014-01-30 14:49:21 -0800213 */
214 virtual void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700215 checkPolicy(const Data& data,
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700216 int nSteps,
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700217 const OnDataValidated& onValidated,
218 const OnDataValidationFailed& onValidationFailed,
Davide Pesaventoc152e6f2016-08-14 02:54:48 +0200219 std::vector<shared_ptr<ValidationRequest>>& nextSteps) = 0;
Yingdi Yu6ac97982014-01-30 14:49:21 -0800220
221 /**
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700222 * @brief Check the Interest against validation policy and return the next validation step
223 * if necessary.
Yingdi Yu6ac97982014-01-30 14:49:21 -0800224 *
225 * If there is no next validation step, that validation MUST have been done.
226 * i.e., either onValidated or onValidationFailed callback is invoked.
227 *
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700228 * @param interest The Interest to check.
229 * @param nSteps The number of validation steps that have been done.
230 * @param onValidated If the Interest is validated, this calls onValidated(data)
231 * @param onValidationFailed If validation fails, this calls onValidationFailed(data)
232 * @param nextSteps On return, contains the next validation step
Yingdi Yu6ac97982014-01-30 14:49:21 -0800233 */
234 virtual void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700235 checkPolicy(const Interest& interest,
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700236 int nSteps,
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700237 const OnInterestValidated& onValidated,
238 const OnInterestValidationFailed& onValidationFailed,
Davide Pesaventoc152e6f2016-08-14 02:54:48 +0200239 std::vector<shared_ptr<ValidationRequest>>& nextSteps) = 0;
Yingdi Yu6ac97982014-01-30 14:49:21 -0800240
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700241 typedef function<void(const std::string&)> OnFailure;
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700242
Yingdi Yu6ac97982014-01-30 14:49:21 -0800243 /// @brief Process the received certificate.
244 void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700245 onData(const Interest& interest,
246 const Data& data,
247 const shared_ptr<ValidationRequest>& nextStep);
248
Yingdi Yu6ac97982014-01-30 14:49:21 -0800249 void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700250 validate(const Data& data,
251 const OnDataValidated& onValidated,
252 const OnDataValidationFailed& onValidationFailed,
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700253 int nSteps);
Yingdi Yu6ac97982014-01-30 14:49:21 -0800254
255 void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700256 validate(const Interest& interest,
257 const OnInterestValidated& onValidated,
258 const OnInterestValidationFailed& onValidationFailed,
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700259 int nSteps);
Yingdi Yu6ac97982014-01-30 14:49:21 -0800260
Yingdi Yud9006e72014-06-23 19:10:44 -0700261 /// Hooks
262
263 /**
264 * @brief trigger before validating requested certificate.
265 *
266 * The Data:
267 * - matches the interest in the validation-request.
268 * - may be certificate or a data encapsulating certificate.
269 *
270 * This method returns a data (actually certificate) that is will be passed as Data into:
271 * Validator::validate(const Data& data,
272 * const OnDataValidated& onValidated,
273 * const OnDataValidationFailed& onValidationFailed,
274 * int nSteps);
275 */
276 virtual shared_ptr<const Data>
277 preCertificateValidation(const Data& data)
278 {
279 return data.shared_from_this();
280 }
281
282 /**
Teng Liange6f87512016-07-26 22:14:19 -0700283 * @brief trigger when interest retrieves a Nack.
284 *
285 * Validator can decide how to handle a Nack, either call onFailure, or retry.
286 *
287 * @param interest The interest that retrieves a Nack.
288 * @param nack The Nack that is retrieved.
289 * @param nRemainingRetries The number of retries left.
290 * @param onFailure Failure callback when there is no more retries remaining.
291 * @param validationRequest The validationRequest containing the context of the interest.
292 */
293 virtual void
294 onNack(const Interest& interest,
295 const lp::Nack& nack,
296 int nRemainingRetries,
297 const OnFailure& onFailure,
298 const shared_ptr<ValidationRequest>& validationRequest);
299
300 /**
Yingdi Yud9006e72014-06-23 19:10:44 -0700301 * @brief trigger when interest for certificate times out.
302 *
303 * Validator can decide how to handle the timeout, either call onFailure, or retry.
304 *
305 * @param interest The interest that times out.
306 * @param nRemainingRetries The number of retries left.
307 * @param onFailure Failure callback when there is no more retries remaining.
308 * @param validationRequest The validationRequest containing the context of the interest.
309 */
Yingdi Yud9006e72014-06-23 19:10:44 -0700310 virtual void
311 onTimeout(const Interest& interest,
312 int nRemainingRetries,
313 const OnFailure& onFailure,
314 const shared_ptr<ValidationRequest>& validationRequest);
315
316 /**
317 * @brief trigger after checkPolicy is done.
318 *
319 * Validator can decide how to handle the set of validation requests according to
320 * the trust model.
321 *
322 * @param nextSteps A set of validation request made by checkPolicy.
323 * @param onFailure Failure callback when errors happen in processing nextSteps.
324 */
325 virtual void
Davide Pesaventoc152e6f2016-08-14 02:54:48 +0200326 afterCheckPolicy(const std::vector<shared_ptr<ValidationRequest>>& nextSteps,
Yingdi Yud9006e72014-06-23 19:10:44 -0700327 const OnFailure& onFailure);
328
Yingdi Yu6ac97982014-01-30 14:49:21 -0800329protected:
Yingdi Yu4e9b0692014-11-04 16:13:56 -0800330 Face* m_face;
Yingdi Yu6ac97982014-01-30 14:49:21 -0800331};
332
Yingdi Yufc40d872014-02-18 12:56:04 -0800333} // namespace ndn
Yingdi Yu6ac97982014-01-30 14:49:21 -0800334
Yingdi Yu4e9b0692014-11-04 16:13:56 -0800335#endif // NDN_SECURITY_VALIDATOR_HPP