blob: 9a3b4a34521668067ca281bf41a743b4596e29ea [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 Yu96e64062014-04-15 19:57:33 -070057 Validator();
Yingdi Yu6ac97982014-01-30 14:49:21 -080058
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070059 explicit
Yingdi Yu96e64062014-04-15 19:57:33 -070060 Validator(Face& face);
Yingdi Yu6ac97982014-01-30 14:49:21 -080061
62 /**
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070063 * @brief Validate Data and call either onValidated or onValidationFailed.
64 *
Yingdi Yu6ac97982014-01-30 14:49:21 -080065 * @param data The Data with the signature to check.
66 * @param onValidated If the Data is validated, this calls onValidated(data).
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070067 * @param onValidationFailed If validation fails, this calls onValidationFailed(data).
Yingdi Yu6ac97982014-01-30 14:49:21 -080068 */
69 void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070070 validate(const Data& data,
71 const OnDataValidated& onValidated,
72 const OnDataValidationFailed& onValidationFailed)
73 {
74 validate(data, onValidated, onValidationFailed, 0);
75 }
Yingdi Yu6ac97982014-01-30 14:49:21 -080076
77 /**
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070078 * @brief Validate Interest and call either onValidated or onValidationFailed.
79 *
Yingdi Yu6ac97982014-01-30 14:49:21 -080080 * @param interest The Interest with the signature to check.
81 * @param onValidated If the Interest is validated, this calls onValidated(interest).
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070082 * @param onValidationFailed If validation fails, this calls onValidationFailed(interest).
Yingdi Yu6ac97982014-01-30 14:49:21 -080083 */
84 void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070085 validate(const Interest& interest,
86 const OnInterestValidated& onValidated,
87 const OnInterestValidationFailed& onValidationFailed)
88 {
89 validate(interest, onValidated, onValidationFailed, 0);
90 }
Yingdi Yu6ac97982014-01-30 14:49:21 -080091
92 /*****************************************
93 * verifySignature method set *
94 *****************************************/
95
96 /// @brief Verify the data using the publicKey.
97 static bool
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070098 verifySignature(const Data& data, const PublicKey& publicKey);
Yingdi Yu6ac97982014-01-30 14:49:21 -080099
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700100 /**
101 * @brief Verify the signed Interest using the publicKey.
102 *
103 * (Note the signature covers the first n-2 name components).
104 */
Yingdi Yu6ac97982014-01-30 14:49:21 -0800105 static bool
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700106 verifySignature(const Interest& interest, const PublicKey& publicKey);
Yingdi Yu6ac97982014-01-30 14:49:21 -0800107
108 /// @brief Verify the blob using the publicKey against the signature.
109 static bool
Yingdi Yu4a557052014-07-09 16:40:37 -0700110 verifySignature(const Buffer& blob, const Signature& sig, const PublicKey& publicKey)
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700111 {
112 return verifySignature(blob.buf(), blob.size(), sig, publicKey);
113 }
Yingdi Yu6ac97982014-01-30 14:49:21 -0800114
115 /// @brief Verify the data using the publicKey against the SHA256-RSA signature.
116 static bool
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700117 verifySignature(const Data& data,
Yingdi Yu4a557052014-07-09 16:40:37 -0700118 const Signature& sig,
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700119 const PublicKey& publicKey)
120 {
121 return verifySignature(data.wireEncode().value(),
122 data.wireEncode().value_size() - data.getSignature().getValue().size(),
123 sig, publicKey);
124 }
125
126 /** @brief Verify the interest using the publicKey against the SHA256-RSA signature.
127 *
128 * (Note the signature covers the first n-2 name components).
129 */
130 static bool
131 verifySignature(const Interest& interest,
Yingdi Yu4a557052014-07-09 16:40:37 -0700132 const Signature& sig,
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700133 const PublicKey& publicKey)
134 {
135 if (interest.getName().size() < 2)
136 return false;
137
Yingdi Yu3cca4ab2014-04-11 12:46:53 -0700138 const Name& name = interest.getName();
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700139
Yingdi Yu3cca4ab2014-04-11 12:46:53 -0700140 return verifySignature(name.wireEncode().value(),
141 name.wireEncode().value_size() - name[-1].size(),
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700142 sig, publicKey);
143 }
Yingdi Yu6ac97982014-01-30 14:49:21 -0800144
145 /// @brief Verify the blob using the publicKey against the SHA256-RSA signature.
146 static bool
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700147 verifySignature(const uint8_t* buf,
148 const size_t size,
Yingdi Yu4a557052014-07-09 16:40:37 -0700149 const Signature& sig,
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700150 const PublicKey& publicKey);
Yingdi Yu6ac97982014-01-30 14:49:21 -0800151
Yingdi Yu21157162014-02-28 13:02:34 -0800152
153 /// @brief Verify the data against the SHA256 signature.
154 static bool
Yingdi Yubf6a2812014-06-17 15:32:11 -0700155 verifySignature(const Data& data, const DigestSha256& sig)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700156 {
157 return verifySignature(data.wireEncode().value(),
158 data.wireEncode().value_size() -
159 data.getSignature().getValue().size(),
160 sig);
161 }
162
163 /** @brief Verify the interest against the SHA256 signature.
164 *
165 * (Note the signature covers the first n-2 name components).
166 */
167 static bool
Yingdi Yubf6a2812014-06-17 15:32:11 -0700168 verifySignature(const Interest& interest, const DigestSha256& sig)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700169 {
170 if (interest.getName().size() < 2)
171 return false;
172
173 Name signedName = interest.getName().getPrefix(-2);
174
175 return verifySignature(signedName.wireEncode().value(),
176 signedName.wireEncode().value_size(),
177 sig);
178 }
Yingdi Yu21157162014-02-28 13:02:34 -0800179
180 /// @brief Verify the blob against the SHA256 signature.
181 static bool
Yingdi Yubf6a2812014-06-17 15:32:11 -0700182 verifySignature(const Buffer& blob, const DigestSha256& sig)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700183 {
184 return verifySignature (blob.buf(), blob.size(), sig);
185 }
186
Yingdi Yu21157162014-02-28 13:02:34 -0800187 /// @brief Verify the blob against the SHA256 signature.
188 static bool
Yingdi Yubf6a2812014-06-17 15:32:11 -0700189 verifySignature(const uint8_t* buf, const size_t size, const DigestSha256& sig);
Yingdi Yu21157162014-02-28 13:02:34 -0800190
Yingdi Yu6ac97982014-01-30 14:49:21 -0800191protected:
192 /**
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700193 * @brief Check the Data against policy and return the next validation step if necessary.
Yingdi Yu6ac97982014-01-30 14:49:21 -0800194 *
195 * If there is no next validation step, that validation MUST have been done.
196 * i.e., either onValidated or onValidationFailed callback is invoked.
197 *
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700198 * @param data The Data to check.
199 * @param nSteps The number of validation steps that have been done.
200 * @param onValidated If the Data is validated, this calls onValidated(data)
201 * @param onValidationFailed If validation fails, this calls onValidationFailed(data)
202 * @param nextSteps On return, contains the next validation step
Yingdi Yu6ac97982014-01-30 14:49:21 -0800203 */
204 virtual void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700205 checkPolicy(const Data& data,
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700206 int nSteps,
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700207 const OnDataValidated& onValidated,
208 const OnDataValidationFailed& onValidationFailed,
209 std::vector<shared_ptr<ValidationRequest> >& nextSteps) = 0;
Yingdi Yu6ac97982014-01-30 14:49:21 -0800210
211 /**
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700212 * @brief Check the Interest against validation policy and return the next validation step
213 * if necessary.
Yingdi Yu6ac97982014-01-30 14:49:21 -0800214 *
215 * If there is no next validation step, that validation MUST have been done.
216 * i.e., either onValidated or onValidationFailed callback is invoked.
217 *
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700218 * @param interest The Interest to check.
219 * @param nSteps The number of validation steps that have been done.
220 * @param onValidated If the Interest is validated, this calls onValidated(data)
221 * @param onValidationFailed If validation fails, this calls onValidationFailed(data)
222 * @param nextSteps On return, contains the next validation step
Yingdi Yu6ac97982014-01-30 14:49:21 -0800223 */
224 virtual void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700225 checkPolicy(const Interest& interest,
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700226 int nSteps,
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700227 const OnInterestValidated& onValidated,
228 const OnInterestValidationFailed& onValidationFailed,
229 std::vector<shared_ptr<ValidationRequest> >& nextSteps) = 0;
Yingdi Yu6ac97982014-01-30 14:49:21 -0800230
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700231 typedef function<void(const std::string&)> OnFailure;
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700232
Yingdi Yu6ac97982014-01-30 14:49:21 -0800233 /// @brief Process the received certificate.
234 void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700235 onData(const Interest& interest,
236 const Data& data,
237 const shared_ptr<ValidationRequest>& nextStep);
238
Yingdi Yu6ac97982014-01-30 14:49:21 -0800239 void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700240 validate(const Data& data,
241 const OnDataValidated& onValidated,
242 const OnDataValidationFailed& onValidationFailed,
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700243 int nSteps);
Yingdi Yu6ac97982014-01-30 14:49:21 -0800244
245 void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700246 validate(const Interest& interest,
247 const OnInterestValidated& onValidated,
248 const OnInterestValidationFailed& onValidationFailed,
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700249 int nSteps);
Yingdi Yu6ac97982014-01-30 14:49:21 -0800250
Yingdi Yud9006e72014-06-23 19:10:44 -0700251 /// Hooks
252
253 /**
254 * @brief trigger before validating requested certificate.
255 *
256 * The Data:
257 * - matches the interest in the validation-request.
258 * - may be certificate or a data encapsulating certificate.
259 *
260 * This method returns a data (actually certificate) that is will be passed as Data into:
261 * Validator::validate(const Data& data,
262 * const OnDataValidated& onValidated,
263 * const OnDataValidationFailed& onValidationFailed,
264 * int nSteps);
265 */
266 virtual shared_ptr<const Data>
267 preCertificateValidation(const Data& data)
268 {
269 return data.shared_from_this();
270 }
271
272 /**
273 * @brief trigger when interest for certificate times out.
274 *
275 * Validator can decide how to handle the timeout, either call onFailure, or retry.
276 *
277 * @param interest The interest that times out.
278 * @param nRemainingRetries The number of retries left.
279 * @param onFailure Failure callback when there is no more retries remaining.
280 * @param validationRequest The validationRequest containing the context of the interest.
281 */
282
283 virtual void
284 onTimeout(const Interest& interest,
285 int nRemainingRetries,
286 const OnFailure& onFailure,
287 const shared_ptr<ValidationRequest>& validationRequest);
288
289 /**
290 * @brief trigger after checkPolicy is done.
291 *
292 * Validator can decide how to handle the set of validation requests according to
293 * the trust model.
294 *
295 * @param nextSteps A set of validation request made by checkPolicy.
296 * @param onFailure Failure callback when errors happen in processing nextSteps.
297 */
298 virtual void
299 afterCheckPolicy(const std::vector<shared_ptr<ValidationRequest> >& nextSteps,
300 const OnFailure& onFailure);
301
Yingdi Yu6ac97982014-01-30 14:49:21 -0800302protected:
Yingdi Yu96e64062014-04-15 19:57:33 -0700303 bool m_hasFace;
304 Face& m_face;
Yingdi Yu6ac97982014-01-30 14:49:21 -0800305};
306
Yingdi Yufc40d872014-02-18 12:56:04 -0800307} // namespace ndn
Yingdi Yu6ac97982014-01-30 14:49:21 -0800308
Yingdi Yufc40d872014-02-18 12:56:04 -0800309#endif //NDN_SECURITY_VALIDATOR_HPP