blob: d0faf22a07e6b071e6925e858dbc23583f46482e [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/**
Alexander Afanasyevc169a812014-05-20 20:37:29 -04003 * Copyright (c) 2013-2014 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
Alexander Afanasyeve2dcdfd2014-02-07 15:53:28 -080028#include "../common.hpp"
29
Yingdi Yu6ac97982014-01-30 14:49:21 -080030#include "../data.hpp"
31#include "../face.hpp"
32#include "public-key.hpp"
33#include "signature-sha256-with-rsa.hpp"
Yingdi Yuc8f883c2014-06-20 23:25:22 -070034#include "signature-sha256-with-ecdsa.hpp"
Yingdi Yubf6a2812014-06-17 15:32:11 -070035#include "digest-sha256.hpp"
Yingdi Yu6ac97982014-01-30 14:49:21 -080036#include "validation-request.hpp"
Joao Pereira0b3cac52015-07-02 14:49:49 -040037#include "identity-certificate.hpp"
Yingdi Yu6ac97982014-01-30 14:49:21 -080038
39namespace ndn {
Joao Pereira0b3cac52015-07-02 14:49:49 -040040
Yingdi Yu6ac97982014-01-30 14:49:21 -080041/**
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070042 * @brief Validator is one of the main classes of the security library.
Yingdi Yu6ac97982014-01-30 14:49:21 -080043 *
44 * The Validator class provides the interfaces for packet validation.
45 */
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -070046class Validator
47{
Yingdi Yu6ac97982014-01-30 14:49:21 -080048public:
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070049 class Error : public std::runtime_error
50 {
51 public:
52 explicit
53 Error(const std::string& what)
54 : std::runtime_error(what)
55 {
56 }
57 };
Yingdi Yu6ac97982014-01-30 14:49:21 -080058
Yingdi Yu4e9b0692014-11-04 16:13:56 -080059 /**
60 * @brief Validator constructor
61 *
62 * @param face Pointer to face through which validator may retrieve certificates.
63 * Passing a null pointer implies the validator is in offline mode.
64 *
65 * @note Make sure the lifetime of the passed Face is longer than validator.
66 */
67 explicit
68 Validator(Face* face = nullptr);
Yingdi Yu6ac97982014-01-30 14:49:21 -080069
Yingdi Yu4e9b0692014-11-04 16:13:56 -080070 /// @deprecated Use the constructor taking Face* as parameter.
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070071 explicit
Yingdi Yu96e64062014-04-15 19:57:33 -070072 Validator(Face& face);
Yingdi Yu6ac97982014-01-30 14:49:21 -080073
74 /**
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070075 * @brief Validate Data and call either onValidated or onValidationFailed.
76 *
Yingdi Yu6ac97982014-01-30 14:49:21 -080077 * @param data The Data with the signature to check.
78 * @param onValidated If the Data is validated, this calls onValidated(data).
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070079 * @param onValidationFailed If validation fails, this calls onValidationFailed(data).
Yingdi Yu6ac97982014-01-30 14:49:21 -080080 */
81 void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070082 validate(const Data& data,
83 const OnDataValidated& onValidated,
84 const OnDataValidationFailed& onValidationFailed)
85 {
86 validate(data, onValidated, onValidationFailed, 0);
87 }
Yingdi Yu6ac97982014-01-30 14:49:21 -080088
89 /**
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070090 * @brief Validate Interest and call either onValidated or onValidationFailed.
91 *
Yingdi Yu6ac97982014-01-30 14:49:21 -080092 * @param interest The Interest with the signature to check.
93 * @param onValidated If the Interest is validated, this calls onValidated(interest).
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070094 * @param onValidationFailed If validation fails, this calls onValidationFailed(interest).
Yingdi Yu6ac97982014-01-30 14:49:21 -080095 */
96 void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070097 validate(const Interest& interest,
98 const OnInterestValidated& onValidated,
99 const OnInterestValidationFailed& onValidationFailed)
100 {
101 validate(interest, onValidated, onValidationFailed, 0);
102 }
Yingdi Yu6ac97982014-01-30 14:49:21 -0800103
104 /*****************************************
105 * verifySignature method set *
106 *****************************************/
107
108 /// @brief Verify the data using the publicKey.
109 static bool
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700110 verifySignature(const Data& data, const PublicKey& publicKey);
Yingdi Yu6ac97982014-01-30 14:49:21 -0800111
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700112 /**
113 * @brief Verify the signed Interest using the publicKey.
114 *
115 * (Note the signature covers the first n-2 name components).
116 */
Yingdi Yu6ac97982014-01-30 14:49:21 -0800117 static bool
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700118 verifySignature(const Interest& interest, const PublicKey& publicKey);
Yingdi Yu6ac97982014-01-30 14:49:21 -0800119
120 /// @brief Verify the blob using the publicKey against the signature.
121 static bool
Yingdi Yu4a557052014-07-09 16:40:37 -0700122 verifySignature(const Buffer& blob, const Signature& sig, const PublicKey& publicKey)
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700123 {
124 return verifySignature(blob.buf(), blob.size(), sig, publicKey);
125 }
Yingdi Yu6ac97982014-01-30 14:49:21 -0800126
127 /// @brief Verify the data using the publicKey against the SHA256-RSA signature.
128 static bool
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700129 verifySignature(const Data& data,
Yingdi Yu4a557052014-07-09 16:40:37 -0700130 const Signature& sig,
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700131 const PublicKey& publicKey)
132 {
133 return verifySignature(data.wireEncode().value(),
134 data.wireEncode().value_size() - data.getSignature().getValue().size(),
135 sig, publicKey);
136 }
137
138 /** @brief Verify the interest using the publicKey against the SHA256-RSA signature.
139 *
140 * (Note the signature covers the first n-2 name components).
141 */
142 static bool
143 verifySignature(const Interest& interest,
Yingdi Yu4a557052014-07-09 16:40:37 -0700144 const Signature& sig,
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700145 const PublicKey& publicKey)
146 {
147 if (interest.getName().size() < 2)
148 return false;
149
Yingdi Yu3cca4ab2014-04-11 12:46:53 -0700150 const Name& name = interest.getName();
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700151
Yingdi Yu3cca4ab2014-04-11 12:46:53 -0700152 return verifySignature(name.wireEncode().value(),
153 name.wireEncode().value_size() - name[-1].size(),
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700154 sig, publicKey);
155 }
Yingdi Yu6ac97982014-01-30 14:49:21 -0800156
157 /// @brief Verify the blob using the publicKey against the SHA256-RSA signature.
158 static bool
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700159 verifySignature(const uint8_t* buf,
160 const size_t size,
Yingdi Yu4a557052014-07-09 16:40:37 -0700161 const Signature& sig,
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700162 const PublicKey& publicKey);
Yingdi Yu6ac97982014-01-30 14:49:21 -0800163
Yingdi Yu21157162014-02-28 13:02:34 -0800164
165 /// @brief Verify the data against the SHA256 signature.
166 static bool
Yingdi Yubf6a2812014-06-17 15:32:11 -0700167 verifySignature(const Data& data, const DigestSha256& sig)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700168 {
169 return verifySignature(data.wireEncode().value(),
170 data.wireEncode().value_size() -
171 data.getSignature().getValue().size(),
172 sig);
173 }
174
175 /** @brief Verify the interest against the SHA256 signature.
176 *
177 * (Note the signature covers the first n-2 name components).
178 */
179 static bool
Yingdi Yubf6a2812014-06-17 15:32:11 -0700180 verifySignature(const Interest& interest, const DigestSha256& sig)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700181 {
182 if (interest.getName().size() < 2)
183 return false;
184
Yingdi Yu6ab67812014-11-27 15:00:34 -0800185 const Name& name = interest.getName();
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700186
Yingdi Yu6ab67812014-11-27 15:00:34 -0800187 return verifySignature(name.wireEncode().value(),
188 name.wireEncode().value_size() - name[-1].size(),
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700189 sig);
190 }
Yingdi Yu21157162014-02-28 13:02:34 -0800191
192 /// @brief Verify the blob against the SHA256 signature.
193 static bool
Yingdi Yubf6a2812014-06-17 15:32:11 -0700194 verifySignature(const Buffer& blob, const DigestSha256& sig)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700195 {
196 return verifySignature (blob.buf(), blob.size(), sig);
197 }
198
Yingdi Yu21157162014-02-28 13:02:34 -0800199 /// @brief Verify the blob against the SHA256 signature.
200 static bool
Yingdi Yubf6a2812014-06-17 15:32:11 -0700201 verifySignature(const uint8_t* buf, const size_t size, const DigestSha256& sig);
Yingdi Yu21157162014-02-28 13:02:34 -0800202
Yingdi Yu6ac97982014-01-30 14:49:21 -0800203protected:
204 /**
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700205 * @brief Check the Data against policy and return the next validation step if necessary.
Yingdi Yu6ac97982014-01-30 14:49:21 -0800206 *
207 * If there is no next validation step, that validation MUST have been done.
208 * i.e., either onValidated or onValidationFailed callback is invoked.
209 *
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700210 * @param data The Data to check.
211 * @param nSteps The number of validation steps that have been done.
212 * @param onValidated If the Data is validated, this calls onValidated(data)
213 * @param onValidationFailed If validation fails, this calls onValidationFailed(data)
214 * @param nextSteps On return, contains the next validation step
Yingdi Yu6ac97982014-01-30 14:49:21 -0800215 */
216 virtual void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700217 checkPolicy(const Data& data,
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700218 int nSteps,
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700219 const OnDataValidated& onValidated,
220 const OnDataValidationFailed& onValidationFailed,
221 std::vector<shared_ptr<ValidationRequest> >& nextSteps) = 0;
Yingdi Yu6ac97982014-01-30 14:49:21 -0800222
223 /**
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700224 * @brief Check the Interest against validation policy and return the next validation step
225 * if necessary.
Yingdi Yu6ac97982014-01-30 14:49:21 -0800226 *
227 * If there is no next validation step, that validation MUST have been done.
228 * i.e., either onValidated or onValidationFailed callback is invoked.
229 *
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700230 * @param interest The Interest to check.
231 * @param nSteps The number of validation steps that have been done.
232 * @param onValidated If the Interest is validated, this calls onValidated(data)
233 * @param onValidationFailed If validation fails, this calls onValidationFailed(data)
234 * @param nextSteps On return, contains the next validation step
Yingdi Yu6ac97982014-01-30 14:49:21 -0800235 */
236 virtual void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700237 checkPolicy(const Interest& interest,
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700238 int nSteps,
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700239 const OnInterestValidated& onValidated,
240 const OnInterestValidationFailed& onValidationFailed,
241 std::vector<shared_ptr<ValidationRequest> >& nextSteps) = 0;
Yingdi Yu6ac97982014-01-30 14:49:21 -0800242
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700243 typedef function<void(const std::string&)> OnFailure;
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700244
Yingdi Yu6ac97982014-01-30 14:49:21 -0800245 /// @brief Process the received certificate.
246 void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700247 onData(const Interest& interest,
248 const Data& data,
249 const shared_ptr<ValidationRequest>& nextStep);
250
Yingdi Yu6ac97982014-01-30 14:49:21 -0800251 void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700252 validate(const Data& data,
253 const OnDataValidated& onValidated,
254 const OnDataValidationFailed& onValidationFailed,
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700255 int nSteps);
Yingdi Yu6ac97982014-01-30 14:49:21 -0800256
257 void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700258 validate(const Interest& interest,
259 const OnInterestValidated& onValidated,
260 const OnInterestValidationFailed& onValidationFailed,
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700261 int nSteps);
Yingdi Yu6ac97982014-01-30 14:49:21 -0800262
Yingdi Yud9006e72014-06-23 19:10:44 -0700263 /// Hooks
264
265 /**
266 * @brief trigger before validating requested certificate.
267 *
268 * The Data:
269 * - matches the interest in the validation-request.
270 * - may be certificate or a data encapsulating certificate.
271 *
272 * This method returns a data (actually certificate) that is will be passed as Data into:
273 * Validator::validate(const Data& data,
274 * const OnDataValidated& onValidated,
275 * const OnDataValidationFailed& onValidationFailed,
276 * int nSteps);
277 */
278 virtual shared_ptr<const Data>
279 preCertificateValidation(const Data& data)
280 {
281 return data.shared_from_this();
282 }
283
284 /**
285 * @brief trigger when interest for certificate times out.
286 *
287 * Validator can decide how to handle the timeout, either call onFailure, or retry.
288 *
289 * @param interest The interest that times out.
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
295 virtual void
296 onTimeout(const Interest& interest,
297 int nRemainingRetries,
298 const OnFailure& onFailure,
299 const shared_ptr<ValidationRequest>& validationRequest);
300
301 /**
302 * @brief trigger after checkPolicy is done.
303 *
304 * Validator can decide how to handle the set of validation requests according to
305 * the trust model.
306 *
307 * @param nextSteps A set of validation request made by checkPolicy.
308 * @param onFailure Failure callback when errors happen in processing nextSteps.
309 */
310 virtual void
311 afterCheckPolicy(const std::vector<shared_ptr<ValidationRequest> >& nextSteps,
312 const OnFailure& onFailure);
313
Yingdi Yu6ac97982014-01-30 14:49:21 -0800314protected:
Yingdi Yu4e9b0692014-11-04 16:13:56 -0800315 Face* m_face;
Yingdi Yu6ac97982014-01-30 14:49:21 -0800316};
317
Yingdi Yufc40d872014-02-18 12:56:04 -0800318} // namespace ndn
Yingdi Yu6ac97982014-01-30 14:49:21 -0800319
Yingdi Yu4e9b0692014-11-04 16:13:56 -0800320#endif // NDN_SECURITY_VALIDATOR_HPP