blob: 8d0e5ba08f297d984c4429c856551a70dcb6d1d8 [file] [log] [blame]
Alexander Afanasyev7e721412017-01-11 13:36:08 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2013-2017 Regents of the University of California.
4 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6 *
7 * 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.
20 */
21
22#ifndef NDN_SECURITY_V2_VALIDATION_STATE_HPP
23#define NDN_SECURITY_V2_VALIDATION_STATE_HPP
24
25#include "../../tag-host.hpp"
26#include "validation-callback.hpp"
27#include "certificate.hpp"
Alexander Afanasyev93338872017-01-30 22:37:00 -080028#include "../../util/signal.hpp"
Alexander Afanasyev7e721412017-01-11 13:36:08 -080029
Alexander Afanasyev7e721412017-01-11 13:36:08 -080030#include <list>
Junxiao Shi830ba972017-06-23 22:44:41 +000031#include <unordered_set>
32#include <boost/logic/tribool.hpp>
Alexander Afanasyev7e721412017-01-11 13:36:08 -080033
34namespace ndn {
35namespace security {
36namespace v2 {
37
38class Validator;
39
40/**
41 * @brief Validation state
42 *
43 * One instance of the validation state is kept for the validation of the whole certificate
44 * chain.
45 *
46 * The state collects the certificate chain that adheres to the selected validation policy to
47 * validate data or interest packets. Certificate, data, and interest packet signatures are
48 * verified only after the validator determines that the chain terminates with a trusted
49 * certificate (a trusted anchor or a previously validated certificate). This model allows
50 * filtering out invalid certificate chains without incurring (costly) cryptographic signature
51 * verification overhead and mitigates some forms of denial-of-service attacks.
52 *
53 * Validation policy and/or key fetcher may add custom information associated with the
54 * validation state using tags (@sa TagHost)
55 *
56 * @sa DataValidationState, InterestValidationState
57 */
58class ValidationState : public TagHost, noncopyable
59{
60public:
61 /**
62 * @brief Create validation state
63 */
64 ValidationState();
65
66 virtual
67 ~ValidationState();
68
Junxiao Shi830ba972017-06-23 22:44:41 +000069 boost::logic::tribool
70 getOutcome() const
71 {
72 return m_outcome;
73 }
74
Alexander Afanasyev7e721412017-01-11 13:36:08 -080075 /**
76 * @brief Call the failure callback
77 */
78 virtual void
79 fail(const ValidationError& error) = 0;
80
81 /**
82 * @return Depth of certificate chain
83 */
84 size_t
85 getDepth() const;
86
87 /**
88 * @brief Check if @p certName has been previously seen and record the supplied name
89 */
90 bool
91 hasSeenCertificateName(const Name& certName);
92
93 /**
94 * @brief Add @p cert to the top of the certificate chain
95 *
96 * If m_certificateChain is empty, @p cert should be the signer of the original
97 * packet. If m_certificateChain is not empty, @p cert should be the signer of
98 * m_certificateChain.front().
99 *
100 * @post m_certificateChain.front() == cert
101 * @note This function does not verify the signature bits.
102 */
103 void
104 addCertificate(const Certificate& cert);
105
106private: // Interface intended to be used only by Validator class
107 /**
108 * @brief Verify signature of the original packet
109 *
110 * @param trustCert The certificate that signs the original packet
111 */
112 virtual void
113 verifyOriginalPacket(const Certificate& trustedCert) = 0;
114
115 /**
116 * @brief Call success callback of the original packet without signature validation
117 */
118 virtual void
119 bypassValidation() = 0;
120
121 /**
122 * @brief Verify signatures of certificates in the certificate chain
123 *
124 * When certificate chain cannot be verified, this method will call this->fail() with
125 * INVALID_SIGNATURE error code and the appropriate diagnostic message.
126 *
127 * @retval nullptr Signatures of at least one certificate in the chain is invalid. All unverified
128 * certificates have been removed from m_certificateChain.
129 * @retval Certificate to validate original data packet, either m_certificateChain.back() or
130 * trustedCert if the certificate chain is empty.
131 *
132 * @post m_certificateChain includes a list of certificates successfully verified by
133 * @p trustedCert.
134 */
135 const Certificate*
136 verifyCertificateChain(const Certificate& trustedCert);
137
138protected:
Junxiao Shi830ba972017-06-23 22:44:41 +0000139 boost::logic::tribool m_outcome;
Alexander Afanasyev7e721412017-01-11 13:36:08 -0800140
141private:
142 std::unordered_set<Name> m_seenCertificateNames;
143
144 /**
145 * @brief the certificate chain
146 *
147 * Each certificate in the chain signs the next certificate. The last certificate signs the
148 * original packet.
149 */
150 std::list<v2::Certificate> m_certificateChain;
151
152 friend class Validator;
153};
154
155/**
156 * @brief Validation state for a data packet
157 */
158class DataValidationState final : public ValidationState
159{
160public:
161 /**
162 * @brief Create validation state for @p data
163 *
164 * The caller must ensure that state instance is valid until validation finishes (i.e., until
165 * after validateCertificateChain() and validateOriginalPacket() are called)
166 */
167 DataValidationState(const Data& data,
168 const DataValidationSuccessCallback& successCb,
169 const DataValidationFailureCallback& failureCb);
170
171 /**
172 * @brief Destructor
173 *
174 * If neither success callback nor failure callback was called, the destructor will call
175 * failure callback with IMPLEMENTATION_ERROR error code.
176 */
177 ~DataValidationState() final;
178
179 void
180 fail(const ValidationError& error) final;
181
182 /**
183 * @return Original data being validated
184 */
185 const Data&
186 getOriginalData() const;
187
188private:
189 void
190 verifyOriginalPacket(const Certificate& trustedCert) final;
191
192 void
193 bypassValidation() final;
194
195private:
196 Data m_data;
197 DataValidationSuccessCallback m_successCb;
198 DataValidationFailureCallback m_failureCb;
199};
200
201/**
202 * @brief Validation state for an interest packet
203 */
204class InterestValidationState final : public ValidationState
205{
206public:
207 /**
208 * @brief Create validation state for @p interest
209 *
210 * The caller must ensure that state instance is valid until validation finishes (i.e., until
211 * after validateCertificateChain() and validateOriginalPacket() are called)
212 */
213 InterestValidationState(const Interest& interest,
214 const InterestValidationSuccessCallback& successCb,
215 const InterestValidationFailureCallback& failureCb);
216
217 /**
218 * @brief Destructor
219 *
220 * If neither success callback nor failure callback was called, the destructor will call
221 * failure callback with IMPLEMENTATION_ERROR error code.
222 */
223 ~InterestValidationState() final;
224
225 void
226 fail(const ValidationError& error) final;
227
228 /**
229 * @return Original interest being validated
230 */
231 const Interest&
232 getOriginalInterest() const;
233
Alexander Afanasyev93338872017-01-30 22:37:00 -0800234public:
235 util::Signal<InterestValidationState, Interest> afterSuccess;
236
Alexander Afanasyev7e721412017-01-11 13:36:08 -0800237private:
238 void
239 verifyOriginalPacket(const Certificate& trustedCert) final;
240
241 void
242 bypassValidation() final;
243
244private:
245 Interest m_interest;
246 InterestValidationSuccessCallback m_successCb;
247 InterestValidationFailureCallback m_failureCb;
248};
249
250} // namespace v2
251} // namespace security
252} // namespace ndn
253
254#endif // NDN_SECURITY_V2_VALIDATION_STATE_HPP