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