blob: 1f06c83b5d52a96e47feb9d8e3af9faa6daccdff [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
69 /**
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070070 * @brief Validate Data and call either onValidated or onValidationFailed.
71 *
Yingdi Yu6ac97982014-01-30 14:49:21 -080072 * @param data The Data with the signature to check.
73 * @param onValidated If the Data is validated, this calls onValidated(data).
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070074 * @param onValidationFailed If validation fails, this calls onValidationFailed(data).
Yingdi Yu6ac97982014-01-30 14:49:21 -080075 */
76 void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070077 validate(const Data& data,
78 const OnDataValidated& onValidated,
79 const OnDataValidationFailed& onValidationFailed)
80 {
81 validate(data, onValidated, onValidationFailed, 0);
82 }
Yingdi Yu6ac97982014-01-30 14:49:21 -080083
84 /**
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070085 * @brief Validate Interest and call either onValidated or onValidationFailed.
86 *
Yingdi Yu6ac97982014-01-30 14:49:21 -080087 * @param interest The Interest with the signature to check.
88 * @param onValidated If the Interest is validated, this calls onValidated(interest).
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070089 * @param onValidationFailed If validation fails, this calls onValidationFailed(interest).
Yingdi Yu6ac97982014-01-30 14:49:21 -080090 */
91 void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070092 validate(const Interest& interest,
93 const OnInterestValidated& onValidated,
94 const OnInterestValidationFailed& onValidationFailed)
95 {
96 validate(interest, onValidated, onValidationFailed, 0);
97 }
Yingdi Yu6ac97982014-01-30 14:49:21 -080098
99 /*****************************************
100 * verifySignature method set *
101 *****************************************/
102
103 /// @brief Verify the data using the publicKey.
104 static bool
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700105 verifySignature(const Data& data, const PublicKey& publicKey);
Yingdi Yu6ac97982014-01-30 14:49:21 -0800106
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700107 /**
108 * @brief Verify the signed Interest using the publicKey.
109 *
110 * (Note the signature covers the first n-2 name components).
111 */
Yingdi Yu6ac97982014-01-30 14:49:21 -0800112 static bool
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700113 verifySignature(const Interest& interest, const PublicKey& publicKey);
Yingdi Yu6ac97982014-01-30 14:49:21 -0800114
115 /// @brief Verify the blob using the publicKey against the signature.
116 static bool
Yingdi Yu4a557052014-07-09 16:40:37 -0700117 verifySignature(const Buffer& blob, const Signature& sig, const PublicKey& publicKey)
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700118 {
119 return verifySignature(blob.buf(), blob.size(), sig, publicKey);
120 }
Yingdi Yu6ac97982014-01-30 14:49:21 -0800121
122 /// @brief Verify the data using the publicKey against the SHA256-RSA signature.
123 static bool
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700124 verifySignature(const Data& data,
Yingdi Yu4a557052014-07-09 16:40:37 -0700125 const Signature& sig,
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700126 const PublicKey& publicKey)
127 {
128 return verifySignature(data.wireEncode().value(),
129 data.wireEncode().value_size() - data.getSignature().getValue().size(),
130 sig, publicKey);
131 }
132
133 /** @brief Verify the interest using the publicKey against the SHA256-RSA signature.
134 *
135 * (Note the signature covers the first n-2 name components).
136 */
137 static bool
138 verifySignature(const Interest& interest,
Yingdi Yu4a557052014-07-09 16:40:37 -0700139 const Signature& sig,
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700140 const PublicKey& publicKey)
141 {
142 if (interest.getName().size() < 2)
143 return false;
144
Yingdi Yu3cca4ab2014-04-11 12:46:53 -0700145 const Name& name = interest.getName();
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700146
Yingdi Yu3cca4ab2014-04-11 12:46:53 -0700147 return verifySignature(name.wireEncode().value(),
148 name.wireEncode().value_size() - name[-1].size(),
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700149 sig, publicKey);
150 }
Yingdi Yu6ac97982014-01-30 14:49:21 -0800151
152 /// @brief Verify the blob using the publicKey against the SHA256-RSA signature.
153 static bool
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700154 verifySignature(const uint8_t* buf,
155 const size_t size,
Yingdi Yu4a557052014-07-09 16:40:37 -0700156 const Signature& sig,
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700157 const PublicKey& publicKey);
Yingdi Yu6ac97982014-01-30 14:49:21 -0800158
Yingdi Yu21157162014-02-28 13:02:34 -0800159
160 /// @brief Verify the data against the SHA256 signature.
161 static bool
Yingdi Yubf6a2812014-06-17 15:32:11 -0700162 verifySignature(const Data& data, const DigestSha256& sig)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700163 {
164 return verifySignature(data.wireEncode().value(),
165 data.wireEncode().value_size() -
166 data.getSignature().getValue().size(),
167 sig);
168 }
169
170 /** @brief Verify the interest against the SHA256 signature.
171 *
172 * (Note the signature covers the first n-2 name components).
173 */
174 static bool
Yingdi Yubf6a2812014-06-17 15:32:11 -0700175 verifySignature(const Interest& interest, const DigestSha256& sig)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700176 {
177 if (interest.getName().size() < 2)
178 return false;
179
Yingdi Yu6ab67812014-11-27 15:00:34 -0800180 const Name& name = interest.getName();
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700181
Yingdi Yu6ab67812014-11-27 15:00:34 -0800182 return verifySignature(name.wireEncode().value(),
183 name.wireEncode().value_size() - name[-1].size(),
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700184 sig);
185 }
Yingdi Yu21157162014-02-28 13:02:34 -0800186
187 /// @brief Verify the blob against the SHA256 signature.
188 static bool
Yingdi Yubf6a2812014-06-17 15:32:11 -0700189 verifySignature(const Buffer& blob, const DigestSha256& sig)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700190 {
191 return verifySignature (blob.buf(), blob.size(), sig);
192 }
193
Yingdi Yu21157162014-02-28 13:02:34 -0800194 /// @brief Verify the blob against the SHA256 signature.
195 static bool
Yingdi Yubf6a2812014-06-17 15:32:11 -0700196 verifySignature(const uint8_t* buf, const size_t size, const DigestSha256& sig);
Yingdi Yu21157162014-02-28 13:02:34 -0800197
Yingdi Yu6ac97982014-01-30 14:49:21 -0800198protected:
199 /**
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700200 * @brief Check the Data against policy and return the next validation step if necessary.
Yingdi Yu6ac97982014-01-30 14:49:21 -0800201 *
202 * If there is no next validation step, that validation MUST have been done.
203 * i.e., either onValidated or onValidationFailed callback is invoked.
204 *
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700205 * @param data The Data to check.
206 * @param nSteps The number of validation steps that have been done.
207 * @param onValidated If the Data is validated, this calls onValidated(data)
208 * @param onValidationFailed If validation fails, this calls onValidationFailed(data)
209 * @param nextSteps On return, contains the next validation step
Yingdi Yu6ac97982014-01-30 14:49:21 -0800210 */
211 virtual void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700212 checkPolicy(const Data& data,
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700213 int nSteps,
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700214 const OnDataValidated& onValidated,
215 const OnDataValidationFailed& onValidationFailed,
216 std::vector<shared_ptr<ValidationRequest> >& nextSteps) = 0;
Yingdi Yu6ac97982014-01-30 14:49:21 -0800217
218 /**
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700219 * @brief Check the Interest against validation policy and return the next validation step
220 * if necessary.
Yingdi Yu6ac97982014-01-30 14:49:21 -0800221 *
222 * If there is no next validation step, that validation MUST have been done.
223 * i.e., either onValidated or onValidationFailed callback is invoked.
224 *
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700225 * @param interest The Interest to check.
226 * @param nSteps The number of validation steps that have been done.
227 * @param onValidated If the Interest is validated, this calls onValidated(data)
228 * @param onValidationFailed If validation fails, this calls onValidationFailed(data)
229 * @param nextSteps On return, contains the next validation step
Yingdi Yu6ac97982014-01-30 14:49:21 -0800230 */
231 virtual void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700232 checkPolicy(const Interest& interest,
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700233 int nSteps,
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700234 const OnInterestValidated& onValidated,
235 const OnInterestValidationFailed& onValidationFailed,
236 std::vector<shared_ptr<ValidationRequest> >& nextSteps) = 0;
Yingdi Yu6ac97982014-01-30 14:49:21 -0800237
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700238 typedef function<void(const std::string&)> OnFailure;
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700239
Yingdi Yu6ac97982014-01-30 14:49:21 -0800240 /// @brief Process the received certificate.
241 void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700242 onData(const Interest& interest,
243 const Data& data,
244 const shared_ptr<ValidationRequest>& nextStep);
245
Yingdi Yu6ac97982014-01-30 14:49:21 -0800246 void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700247 validate(const Data& data,
248 const OnDataValidated& onValidated,
249 const OnDataValidationFailed& onValidationFailed,
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700250 int nSteps);
Yingdi Yu6ac97982014-01-30 14:49:21 -0800251
252 void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700253 validate(const Interest& interest,
254 const OnInterestValidated& onValidated,
255 const OnInterestValidationFailed& onValidationFailed,
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700256 int nSteps);
Yingdi Yu6ac97982014-01-30 14:49:21 -0800257
Yingdi Yud9006e72014-06-23 19:10:44 -0700258 /// Hooks
259
260 /**
261 * @brief trigger before validating requested certificate.
262 *
263 * The Data:
264 * - matches the interest in the validation-request.
265 * - may be certificate or a data encapsulating certificate.
266 *
267 * This method returns a data (actually certificate) that is will be passed as Data into:
268 * Validator::validate(const Data& data,
269 * const OnDataValidated& onValidated,
270 * const OnDataValidationFailed& onValidationFailed,
271 * int nSteps);
272 */
273 virtual shared_ptr<const Data>
274 preCertificateValidation(const Data& data)
275 {
276 return data.shared_from_this();
277 }
278
279 /**
Teng Liange6f87512016-07-26 22:14:19 -0700280 * @brief trigger when interest retrieves a Nack.
281 *
282 * Validator can decide how to handle a Nack, either call onFailure, or retry.
283 *
284 * @param interest The interest that retrieves a Nack.
285 * @param nack The Nack that is retrieved.
286 * @param nRemainingRetries The number of retries left.
287 * @param onFailure Failure callback when there is no more retries remaining.
288 * @param validationRequest The validationRequest containing the context of the interest.
289 */
290 virtual void
291 onNack(const Interest& interest,
292 const lp::Nack& nack,
293 int nRemainingRetries,
294 const OnFailure& onFailure,
295 const shared_ptr<ValidationRequest>& validationRequest);
296
297 /**
Yingdi Yud9006e72014-06-23 19:10:44 -0700298 * @brief trigger when interest for certificate times out.
299 *
300 * Validator can decide how to handle the timeout, either call onFailure, or retry.
301 *
302 * @param interest The interest that times out.
303 * @param nRemainingRetries The number of retries left.
304 * @param onFailure Failure callback when there is no more retries remaining.
305 * @param validationRequest The validationRequest containing the context of the interest.
306 */
Yingdi Yud9006e72014-06-23 19:10:44 -0700307 virtual void
308 onTimeout(const Interest& interest,
309 int nRemainingRetries,
310 const OnFailure& onFailure,
311 const shared_ptr<ValidationRequest>& validationRequest);
312
313 /**
314 * @brief trigger after checkPolicy is done.
315 *
316 * Validator can decide how to handle the set of validation requests according to
317 * the trust model.
318 *
319 * @param nextSteps A set of validation request made by checkPolicy.
320 * @param onFailure Failure callback when errors happen in processing nextSteps.
321 */
322 virtual void
323 afterCheckPolicy(const std::vector<shared_ptr<ValidationRequest> >& nextSteps,
324 const OnFailure& onFailure);
325
Yingdi Yu6ac97982014-01-30 14:49:21 -0800326protected:
Yingdi Yu4e9b0692014-11-04 16:13:56 -0800327 Face* m_face;
Yingdi Yu6ac97982014-01-30 14:49:21 -0800328};
329
Yingdi Yufc40d872014-02-18 12:56:04 -0800330} // namespace ndn
Yingdi Yu6ac97982014-01-30 14:49:21 -0800331
Yingdi Yu4e9b0692014-11-04 16:13:56 -0800332#endif // NDN_SECURITY_VALIDATOR_HPP