blob: 1b64d4bd8eb858c0e1e7b42aa8d67c79dc708f22 [file] [log] [blame]
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2017-2020, Regents of the University of California.
4 *
5 * This file is part of ndncert, a certificate management system based on NDN.
6 *
7 * ndncert is free software: you can redistribute it and/or modify it under the terms
8 * of the GNU General Public License as published by the Free Software Foundation, either
9 * version 3 of the License, or (at your option) any later version.
10 *
11 * ndncert 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 General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License along with
16 * ndncert, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * See AUTHORS.md for complete list of ndncert authors and contributors.
19 */
20
tylerliu8704d032020-06-23 10:18:15 -070021#ifndef NDNCERT_REQUESTER_HPP
22#define NDNCERT_REQUESTER_HPP
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -070023
24#include "configuration.hpp"
tylerliu8704d032020-06-23 10:18:15 -070025#include "ca-state.hpp"
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -070026#include "crypto-support/crypto-helper.hpp"
27
28namespace ndn {
29namespace ndncert {
30
31// TODO
32// For each RequesterState, create a validator instance and initialize it with CA's cert
33// The validator instance should be in CaProfile
34
35struct RequesterState {
36 explicit
tylerliua7bea662020-10-08 18:51:02 -070037 RequesterState(security::KeyChain& keyChain, const CaProfile& caItem, RequestType requestType);
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -070038
tylerliudf6e5cc2020-10-05 18:52:13 -070039 /**
40 * The CA profile for this request.
41 */
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -070042 CaProfile m_caItem;
tylerliudf6e5cc2020-10-05 18:52:13 -070043 /**
44 * The local keychain to generate and install identities, keys and certificates
45 */
tylerliua7bea662020-10-08 18:51:02 -070046 security::KeyChain& m_keyChain;
tylerliudf6e5cc2020-10-05 18:52:13 -070047 /**
48 * The type of request. Either NEW, RENEW, or REVOKE.
49 */
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -070050 RequestType m_type;
51
tylerliudf6e5cc2020-10-05 18:52:13 -070052 /**
53 * The identity name for the requesting certificate.
54 */
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -070055 Name m_identityName;
tylerliudf6e5cc2020-10-05 18:52:13 -070056 /**
57 * The keypair for the request.
58 */
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -070059 security::Key m_keyPair;
tylerliudf6e5cc2020-10-05 18:52:13 -070060 /**
61 * The CA-generated request ID for the request.
62 */
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -070063 std::string m_requestId;
tylerliudf6e5cc2020-10-05 18:52:13 -070064 /**
65 * The current status of the request.
66 */
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -070067 Status m_status = Status::NOT_STARTED;
tylerliudf6e5cc2020-10-05 18:52:13 -070068
69 /**
70 * The type of challenge chosen.
71 */
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -070072 std::string m_challengeType;
tylerliudf6e5cc2020-10-05 18:52:13 -070073 /**
74 * The status of the current challenge.
75 */
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -070076 std::string m_challengeStatus;
tylerliudf6e5cc2020-10-05 18:52:13 -070077 /**
78 * The remaining number of tries left for the challenge
79 */
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -070080 int m_remainingTries = 0;
tylerliudf6e5cc2020-10-05 18:52:13 -070081 /**
82 * The time this challenge will remain fresh
83 */
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -070084 time::system_clock::TimePoint m_freshBefore;
tylerliudf6e5cc2020-10-05 18:52:13 -070085 /**
86 * the name of the certificate being issued.
87 */
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -070088 Name m_issuedCertName;
89
90 ECDHState m_ecdh;
91 uint8_t m_aesKey[16] = {0};
92
93 bool m_isCertInstalled = false;
94 bool m_isNewlyCreatedIdentity = false;
95 bool m_isNewlyCreatedKey = false;
96};
97
98class Requester : noncopyable
99{
100public:
tylerliudf6e5cc2020-10-05 18:52:13 -0700101 /**
Zhiyi Zhangfbcab842020-10-07 15:17:13 -0700102 * Generates a CA profile discovery Interest following RDR protocol.
103 * @param caName, the name prefix of the CA.
104 * @return A shared pointer to an Interest ready to be sent.
tylerliudf6e5cc2020-10-05 18:52:13 -0700105 */
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700106 static shared_ptr<Interest>
Zhiyi Zhangfbcab842020-10-07 15:17:13 -0700107 genCaProfileDiscoveryInterest(const Name& caName);
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700108
109 /**
Zhiyi Zhangfbcab842020-10-07 15:17:13 -0700110 * Generates a CA profile fetching Interest following RDR protocol.
111 * @param reply, the Data packet replied from discovery Interest.
112 * @return A shared pointer to an Interest ready to be sent.
113 */
114 static shared_ptr<Interest>
115 genCaProfileInterestFromDiscoveryResponse(const Data& reply);
116
117 /**
118 * Decodes the CA profile from the replied CA profile Data packet.
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700119 * Will first verify the signature of the packet using the key provided inside the profile.
120 * The application should be cautious whether to add CaProfile into the RequesterCaCache.
Zhiyi Zhangfbcab842020-10-07 15:17:13 -0700121 * @param reply, the Data packet replied from CA profile fetching Interest.
tylerliudf6e5cc2020-10-05 18:52:13 -0700122 * @return the CaProfile if decoding is successful
123 * @throw std::runtime_error if the decoding fails or receiving an error packet.
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700124 */
125 static boost::optional<CaProfile>
126 onCaProfileResponse(const Data& reply);
127
Zhiyi Zhangfbcab842020-10-07 15:17:13 -0700128 /**
129 * Decodes the CA profile from the replied CA profile Data packet after the redirection.
130 * Will first verify the signature of the packet using the key provided inside the profile and
131 * verify the certificate's digest matches the one obtained from the original CA.
132 * The application should be cautious whether to add CaProfile into the RequesterCaCache.
133 * @param reply, the Data packet replied from CA profile fetching Interest.
134 * @param caCertFullName, the full name obtained from original CA's probe response.
135 * @return the CaProfile if decoding is successful
136 * @throw std::runtime_error if the decoding fails or receiving an error packet.
137 */
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700138 static boost::optional<CaProfile>
139 onCaProfileResponseAfterRedirection(const Data& reply, const Name& caCertFullName);
140
tylerliudf6e5cc2020-10-05 18:52:13 -0700141 /**
142 * Generates a PROBE interest to the CA (for suggested name assignments).
Zhiyi Zhangfbcab842020-10-07 15:17:13 -0700143 * @param ca, the CA that interest is send to
144 * @param probeInfo, the requester information to carry to the CA
tylerliudf6e5cc2020-10-05 18:52:13 -0700145 * @return A shared pointer of to the encoded interest, ready to be sent.
146 */
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700147 static shared_ptr<Interest>
148 genProbeInterest(const CaProfile& ca, std::vector<std::tuple<std::string, std::string>>&& probeInfo);
149
tylerliudf6e5cc2020-10-05 18:52:13 -0700150 /**
151 * Decodes the replied data for PROBE process from the CA.
152 * Will first verify the signature of the packet using the key provided inside the profile.
Zhiyi Zhangfbcab842020-10-07 15:17:13 -0700153 * @param reply, The replied data packet
154 * @param ca, the profile of the CA that replies the packet
155 * @param identityNames, The vector to load the decoded identity names from the data.
156 * @param otherCas, The vector to load the decoded redirection CA prefixes from the data.
tylerliudf6e5cc2020-10-05 18:52:13 -0700157 * @throw std::runtime_error if the decoding fails or receiving an error packet.
158 */
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700159 static void
160 onProbeResponse(const Data& reply, const CaProfile& ca,
161 std::vector<Name>& identityNames, std::vector<Name>& otherCas);
162
163 // NEW/REVOKE/RENEW related helpers
tylerliudf6e5cc2020-10-05 18:52:13 -0700164 /**
165 * Generates a NEW interest to the CA.
Zhiyi Zhangfbcab842020-10-07 15:17:13 -0700166 * @param state, The current requester state for this request. Will be modified in the function.
167 * @param identityName, The identity name to be requested.
168 * @param notBefore, The expected notBefore field for the certificate (starting time)
169 * @param notAfter, The expected notAfter field for the certificate (expiration time)
tylerliudf6e5cc2020-10-05 18:52:13 -0700170 * @return The shared pointer to the encoded interest.
171 */
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700172 static shared_ptr<Interest>
173 genNewInterest(RequesterState& state, const Name& identityName,
174 const time::system_clock::TimePoint& notBefore,
175 const time::system_clock::TimePoint& notAfter);
176
tylerliudf6e5cc2020-10-05 18:52:13 -0700177 /**
178 * Generates a REVOKE interest to the CA.
Zhiyi Zhangfbcab842020-10-07 15:17:13 -0700179 * @param state, The current requester state for this request. Will be modified in the function.
180 * @param certificate, the certificate to the revoked.
tylerliudf6e5cc2020-10-05 18:52:13 -0700181 * @return The shared pointer to the encoded interest.
182 */
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700183 static shared_ptr<Interest>
tylerliua7bea662020-10-08 18:51:02 -0700184 genRevokeInterest(RequesterState& state, const security::Certificate& certificate);
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700185
tylerliudf6e5cc2020-10-05 18:52:13 -0700186 /**
187 * Decodes the replied data of NEW, RENEW, or REVOKE interest from the CA.
Zhiyi Zhangfbcab842020-10-07 15:17:13 -0700188 * @param state, the current requester state for the request. Will be updated in the function.
189 * @param reply, the replied data from the network
tylerliudf6e5cc2020-10-05 18:52:13 -0700190 * @return the list of challenge accepted by the CA, for CHALLENGE step.
191 * @throw std::runtime_error if the decoding fails or receiving an error packet.
192 */
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700193 static std::list<std::string>
194 onNewRenewRevokeResponse(RequesterState& state, const Data& reply);
195
196 // CHALLENGE helpers
tylerliudf6e5cc2020-10-05 18:52:13 -0700197 /**
198 * Generates the required parameter for the selected challenge for the request
Zhiyi Zhangfbcab842020-10-07 15:17:13 -0700199 * @param state, The requester state of the request.Will be updated in the function.
200 * @param challengeSelected, The selected challenge for the request.
tylerliudf6e5cc2020-10-05 18:52:13 -0700201 * Can use state.m_challengeType to continue.
202 * @return The requirement list for the current stage of the challenge, in name, prompt mapping.
203 */
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700204 static std::vector<std::tuple<std::string, std::string>>
205 selectOrContinueChallenge(RequesterState& state, const std::string& challengeSelected);
206
tylerliudf6e5cc2020-10-05 18:52:13 -0700207 /**
208 * Generates the CHALLENGE interest for the request.
Zhiyi Zhangfbcab842020-10-07 15:17:13 -0700209 * @param state, The requester state of the request.
210 * @param parameters, The requirement list, in name, value mapping.
tylerliudf6e5cc2020-10-05 18:52:13 -0700211 * @return The shared pointer to the encoded interest
212 */
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700213 static shared_ptr<Interest>
214 genChallengeInterest(const RequesterState& state,
215 std::vector<std::tuple<std::string, std::string>>&& parameters);
216
tylerliudf6e5cc2020-10-05 18:52:13 -0700217 /**
Zhiyi Zhangfbcab842020-10-07 15:17:13 -0700218 * Decodes the responded data from the CHALLENGE interest.
219 * @param state, the corresponding requester state of the request. Will be modified.
220 * @param reply, the response data.
tylerliudf6e5cc2020-10-05 18:52:13 -0700221 * @throw std::runtime_error if the decoding fails or receiving an error packet.
222 */
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700223 static void
224 onChallengeResponse(RequesterState& state, const Data& reply);
225
tylerliudf6e5cc2020-10-05 18:52:13 -0700226 /**
227 * Generate the interest to fetch the issued certificate
Zhiyi Zhangfbcab842020-10-07 15:17:13 -0700228 * @param state, the state of the request.
tylerliudf6e5cc2020-10-05 18:52:13 -0700229 * @return The shared pointer to the encoded interest
230 */
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700231 static shared_ptr<Interest>
232 genCertFetchInterest(const RequesterState& state);
233
tylerliudf6e5cc2020-10-05 18:52:13 -0700234 /**
235 * Decoded and installs the response certificate from the certificate fetch.
Zhiyi Zhangfbcab842020-10-07 15:17:13 -0700236 * @param reply, the data replied from the certificate fetch interest.
tylerliudf6e5cc2020-10-05 18:52:13 -0700237 * @return The shared pointer to the certificate being fetched.
238 */
tylerliua7bea662020-10-08 18:51:02 -0700239 static shared_ptr<security::Certificate>
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700240 onCertFetchResponse(const Data& reply);
241
tylerliudf6e5cc2020-10-05 18:52:13 -0700242 /**
243 * End the current request session and performs cleanup if necessary.
Zhiyi Zhangfbcab842020-10-07 15:17:13 -0700244 * @param state, the requester state for the request.
tylerliudf6e5cc2020-10-05 18:52:13 -0700245 */
tylerliufeabfdc2020-10-03 15:09:58 -0700246 static void
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700247 endSession(RequesterState& state);
248
249private:
250 static void
251 processIfError(const Data& data);
252};
253
254} // namespace ndncert
255} // namespace ndn
256
tylerliu8704d032020-06-23 10:18:15 -0700257#endif // NDNCERT_REQUESTER_HPP