blob: 3fe58f303f0589ed11e44bc976fa15d05c850632 [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"
37
38namespace ndn {
39/**
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070040 * @brief Validator is one of the main classes of the security library.
Yingdi Yu6ac97982014-01-30 14:49:21 -080041 *
42 * The Validator class provides the interfaces for packet validation.
43 */
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -070044class Validator
45{
Yingdi Yu6ac97982014-01-30 14:49:21 -080046public:
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070047 class Error : public std::runtime_error
48 {
49 public:
50 explicit
51 Error(const std::string& what)
52 : std::runtime_error(what)
53 {
54 }
55 };
Yingdi Yu6ac97982014-01-30 14:49:21 -080056
Yingdi Yu4e9b0692014-11-04 16:13:56 -080057 /**
58 * @brief Validator constructor
59 *
60 * @param face Pointer to face through which validator may retrieve certificates.
61 * Passing a null pointer implies the validator is in offline mode.
62 *
63 * @note Make sure the lifetime of the passed Face is longer than validator.
64 */
65 explicit
66 Validator(Face* face = nullptr);
Yingdi Yu6ac97982014-01-30 14:49:21 -080067
Yingdi Yu4e9b0692014-11-04 16:13:56 -080068 /// @deprecated Use the constructor taking Face* as parameter.
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070069 explicit
Yingdi Yu96e64062014-04-15 19:57:33 -070070 Validator(Face& face);
Yingdi Yu6ac97982014-01-30 14:49:21 -080071
72 /**
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
183 Name signedName = interest.getName().getPrefix(-2);
184
185 return verifySignature(signedName.wireEncode().value(),
186 signedName.wireEncode().value_size(),
187 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,
219 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,
239 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 /**
283 * @brief trigger when interest for certificate times out.
284 *
285 * Validator can decide how to handle the timeout, either call onFailure, or retry.
286 *
287 * @param interest The interest that times out.
288 * @param nRemainingRetries The number of retries left.
289 * @param onFailure Failure callback when there is no more retries remaining.
290 * @param validationRequest The validationRequest containing the context of the interest.
291 */
292
293 virtual void
294 onTimeout(const Interest& interest,
295 int nRemainingRetries,
296 const OnFailure& onFailure,
297 const shared_ptr<ValidationRequest>& validationRequest);
298
299 /**
300 * @brief trigger after checkPolicy is done.
301 *
302 * Validator can decide how to handle the set of validation requests according to
303 * the trust model.
304 *
305 * @param nextSteps A set of validation request made by checkPolicy.
306 * @param onFailure Failure callback when errors happen in processing nextSteps.
307 */
308 virtual void
309 afterCheckPolicy(const std::vector<shared_ptr<ValidationRequest> >& nextSteps,
310 const OnFailure& onFailure);
311
Yingdi Yu6ac97982014-01-30 14:49:21 -0800312protected:
Yingdi Yu4e9b0692014-11-04 16:13:56 -0800313 Face* m_face;
Yingdi Yu6ac97982014-01-30 14:49:21 -0800314};
315
Yingdi Yufc40d872014-02-18 12:56:04 -0800316} // namespace ndn
Yingdi Yu6ac97982014-01-30 14:49:21 -0800317
Yingdi Yu4e9b0692014-11-04 16:13:56 -0800318#endif // NDN_SECURITY_VALIDATOR_HPP