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