blob: acd06cc644586fd9155ee5acff8788d54d44fd98 [file] [log] [blame]
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Davide Pesavento0dc02012021-11-23 22:55:03 -05002/*
3 * Copyright (c) 2017-2021, Regents of the University of California.
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -07004 *
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
tylerliu4140fe82021-01-27 15:45:44 -080021#ifndef NDNCERT_REQUESTER_REQUEST_HPP
22#define NDNCERT_REQUESTER_REQUEST_HPP
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -070023
tylerliu4140fe82021-01-27 15:45:44 -080024#include "detail/ca-request-state.hpp"
25#include "detail/crypto-helpers.hpp"
26#include "detail/profile-storage.hpp"
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -070027
Davide Pesavento0dc02012021-11-23 22:55:03 -050028#include <ndn-cxx/security/key-chain.hpp>
29
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -070030namespace ndncert {
Zhiyi Zhang3002e6b2020-10-29 18:54:07 -070031namespace requester {
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -070032
Davide Pesavento0dc02012021-11-23 22:55:03 -050033class Request : boost::noncopyable
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -070034{
35public:
tylerliudf6e5cc2020-10-05 18:52:13 -070036 /**
Zhiyi Zhang6d9eda62020-10-16 17:37:02 -070037 * @brief Generates a CA profile discovery Interest following RDR protocol.
38 *
39 * @param caName The name prefix of the CA.
Zhiyi Zhangfbcab842020-10-07 15:17:13 -070040 * @return A shared pointer to an Interest ready to be sent.
tylerliudf6e5cc2020-10-05 18:52:13 -070041 */
Davide Pesavento0dc02012021-11-23 22:55:03 -050042 static std::shared_ptr<Interest>
Zhiyi Zhangfbcab842020-10-07 15:17:13 -070043 genCaProfileDiscoveryInterest(const Name& caName);
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -070044
45 /**
Zhiyi Zhang6d9eda62020-10-16 17:37:02 -070046 * @brief Generates a CA profile fetching Interest following RDR protocol.
47 *
48 * @param reply The Data packet replied from discovery Interest.
Zhiyi Zhangfbcab842020-10-07 15:17:13 -070049 * @return A shared pointer to an Interest ready to be sent.
50 */
Davide Pesavento0dc02012021-11-23 22:55:03 -050051 static std::shared_ptr<Interest>
Zhiyi Zhangfbcab842020-10-07 15:17:13 -070052 genCaProfileInterestFromDiscoveryResponse(const Data& reply);
53
54 /**
Zhiyi Zhang6d9eda62020-10-16 17:37:02 -070055 * @brief Decodes the CA profile from the replied CA profile Data packet.
56 *
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -070057 * Will first verify the signature of the packet using the key provided inside the profile.
Zhiyi Zhanga16b7582020-10-29 18:59:46 -070058 * The application should be cautious whether to add CaProfile into the ProfileStorage.
Zhiyi Zhang6d9eda62020-10-16 17:37:02 -070059 *
60 * @param reply The Data packet replied from CA profile fetching Interest.
tylerliudf6e5cc2020-10-05 18:52:13 -070061 * @return the CaProfile if decoding is successful
62 * @throw std::runtime_error if the decoding fails or receiving an error packet.
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -070063 */
Zhiyi Zhang997669a2020-10-28 21:15:40 -070064 static optional<CaProfile>
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -070065 onCaProfileResponse(const Data& reply);
66
Zhiyi Zhangfbcab842020-10-07 15:17:13 -070067 /**
Zhiyi Zhang6d9eda62020-10-16 17:37:02 -070068 * @brief Decodes the CA profile from the replied CA profile Data packet after the redirection.
69 *
Zhiyi Zhangfbcab842020-10-07 15:17:13 -070070 * Will first verify the signature of the packet using the key provided inside the profile and
71 * verify the certificate's digest matches the one obtained from the original CA.
Zhiyi Zhanga16b7582020-10-29 18:59:46 -070072 * The application should be cautious whether to add CaProfile into the ProfileStorage.
Zhiyi Zhang6d9eda62020-10-16 17:37:02 -070073 *
74 * @param reply The Data packet replied from CA profile fetching Interest.
75 * @param caCertFullName The full name obtained from original CA's probe response.
Zhiyi Zhangfbcab842020-10-07 15:17:13 -070076 * @return the CaProfile if decoding is successful
77 * @throw std::runtime_error if the decoding fails or receiving an error packet.
78 */
Zhiyi Zhang997669a2020-10-28 21:15:40 -070079 static optional<CaProfile>
Zhiyi Zhang837406d2020-10-05 22:01:31 -070080 onCaProfileResponseAfterRedirection(const Data& reply, const Name& caCertFullName);
81
tylerliudf6e5cc2020-10-05 18:52:13 -070082 /**
Zhiyi Zhang6d9eda62020-10-16 17:37:02 -070083 * @brief Generates a PROBE interest to the CA (for suggested name assignments).
84 *
85 * @param ca The CA that interest is send to
86 * @param probeInfo The requester information to carry to the CA
tylerliudf6e5cc2020-10-05 18:52:13 -070087 * @return A shared pointer of to the encoded interest, ready to be sent.
88 */
Davide Pesavento0dc02012021-11-23 22:55:03 -050089 static std::shared_ptr<Interest>
tylerliu40226332020-11-11 15:37:16 -080090 genProbeInterest(const CaProfile& ca, std::multimap<std::string, std::string>&& probeInfo);
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -070091
tylerliudf6e5cc2020-10-05 18:52:13 -070092 /**
Zhiyi Zhang6d9eda62020-10-16 17:37:02 -070093 * @brief Decodes the replied data for PROBE process from the CA.
94 *
tylerliudf6e5cc2020-10-05 18:52:13 -070095 * Will first verify the signature of the packet using the key provided inside the profile.
Zhiyi Zhang6d9eda62020-10-16 17:37:02 -070096 *
97 * @param reply The replied data packet
98 * @param ca the profile of the CA that replies the packet
99 * @param identityNames The vector to load the decoded identity names from the data.
100 * @param otherCas The vector to load the decoded redirection CA prefixes from the data.
tylerliudf6e5cc2020-10-05 18:52:13 -0700101 * @throw std::runtime_error if the decoding fails or receiving an error packet.
102 */
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700103 static void
104 onProbeResponse(const Data& reply, const CaProfile& ca,
tylerliub47dad72020-10-08 21:36:55 -0700105 std::vector<std::pair<Name, int>>& identityNames, std::vector<Name>& otherCas);
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700106
tylerliu4140fe82021-01-27 15:45:44 -0800107 explicit
Davide Pesavento0dc02012021-11-23 22:55:03 -0500108 Request(ndn::KeyChain& keyChain, const CaProfile& profile, RequestType requestType);
tylerliu4140fe82021-01-27 15:45:44 -0800109
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700110 // NEW/REVOKE/RENEW related helpers
tylerliudf6e5cc2020-10-05 18:52:13 -0700111 /**
Zhiyi Zhang6d9eda62020-10-16 17:37:02 -0700112 * @brief Generates a NEW interest to the CA.
113 *
114 * @param state The current requester state for this request. Will be modified in the function.
tylerliu4140fe82021-01-27 15:45:44 -0800115 * @param newIdentityName The identity name to be requested.
Zhiyi Zhang6d9eda62020-10-16 17:37:02 -0700116 * @param notBefore The expected notBefore field for the certificate (starting time)
117 * @param notAfter The expected notAfter field for the certificate (expiration time)
tylerliudf6e5cc2020-10-05 18:52:13 -0700118 * @return The shared pointer to the encoded interest.
119 */
Davide Pesavento0dc02012021-11-23 22:55:03 -0500120 std::shared_ptr<Interest>
tylerliu4140fe82021-01-27 15:45:44 -0800121 genNewInterest(const Name& newIdentityName,
Zhiyi Zhangc5d93a92020-10-14 17:07:35 -0700122 const time::system_clock::TimePoint& notBefore,
123 const time::system_clock::TimePoint& notAfter);
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700124
tylerliudf6e5cc2020-10-05 18:52:13 -0700125 /**
Zhiyi Zhang6d9eda62020-10-16 17:37:02 -0700126 * @brief Generates a REVOKE interest to the CA.
127 *
128 * @param state The current requester state for this request. Will be modified in the function.
129 * @param certificate The certificate to the revoked.
tylerliudf6e5cc2020-10-05 18:52:13 -0700130 * @return The shared pointer to the encoded interest.
131 */
Davide Pesavento0dc02012021-11-23 22:55:03 -0500132 std::shared_ptr<Interest>
133 genRevokeInterest(const Certificate& certificate);
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700134
tylerliudf6e5cc2020-10-05 18:52:13 -0700135 /**
Zhiyi Zhang6d9eda62020-10-16 17:37:02 -0700136 * @brief Decodes the replied data of NEW, RENEW, or REVOKE interest from the CA.
137 *
138 * @param state The current requester state for the request. Will be updated in the function.
139 * @param reply The replied data from the network
tylerliudf6e5cc2020-10-05 18:52:13 -0700140 * @return the list of challenge accepted by the CA, for CHALLENGE step.
141 * @throw std::runtime_error if the decoding fails or receiving an error packet.
142 */
tylerliu4140fe82021-01-27 15:45:44 -0800143 std::list<std::string>
144 onNewRenewRevokeResponse(const Data& reply);
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700145
146 // CHALLENGE helpers
tylerliudf6e5cc2020-10-05 18:52:13 -0700147 /**
Zhiyi Zhang6d9eda62020-10-16 17:37:02 -0700148 * @brief Generates the required parameter for the selected challenge for the request
149 *
150 * @param state, The requester state of the request.Will be updated in the function.
151 * @param challengeSelected, The selected challenge for the request.
tylerliudf6e5cc2020-10-05 18:52:13 -0700152 * Can use state.m_challengeType to continue.
153 * @return The requirement list for the current stage of the challenge, in name, prompt mapping.
Zhiyi Zhangc5d93a92020-10-14 17:07:35 -0700154 * @throw std::runtime_error if the challenge is not supported.
tylerliudf6e5cc2020-10-05 18:52:13 -0700155 */
tylerliu4140fe82021-01-27 15:45:44 -0800156 std::multimap<std::string, std::string>
157 selectOrContinueChallenge(const std::string& challengeSelected);
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700158
tylerliudf6e5cc2020-10-05 18:52:13 -0700159 /**
Zhiyi Zhang6d9eda62020-10-16 17:37:02 -0700160 * @brief Generates the CHALLENGE interest for the request.
161 *
162 * @param state, The requester state of the request.
163 * @param parameters, The requirement list, in name, value mapping.
tylerliudf6e5cc2020-10-05 18:52:13 -0700164 * @return The shared pointer to the encoded interest
Zhiyi Zhangc5d93a92020-10-14 17:07:35 -0700165 * @throw std::runtime_error if the challenge is not selected or is not supported.
tylerliudf6e5cc2020-10-05 18:52:13 -0700166 */
Davide Pesavento0dc02012021-11-23 22:55:03 -0500167 std::shared_ptr<Interest>
tylerliu4140fe82021-01-27 15:45:44 -0800168 genChallengeInterest(std::multimap<std::string, std::string>&& parameters);
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700169
tylerliudf6e5cc2020-10-05 18:52:13 -0700170 /**
Zhiyi Zhang6d9eda62020-10-16 17:37:02 -0700171 * @brief Decodes the responded data from the CHALLENGE interest.
172 *
173 * @param state, the corresponding requester state of the request. Will be modified.
174 * @param reply, the response data.
tylerliudf6e5cc2020-10-05 18:52:13 -0700175 * @throw std::runtime_error if the decoding fails or receiving an error packet.
176 */
tylerliu4140fe82021-01-27 15:45:44 -0800177 void
178 onChallengeResponse(const Data& reply);
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700179
tylerliudf6e5cc2020-10-05 18:52:13 -0700180 /**
Zhiyi Zhang6d9eda62020-10-16 17:37:02 -0700181 * @brief Generate the interest to fetch the issued certificate
182 *
183 * @param state, the state of the request.
tylerliudf6e5cc2020-10-05 18:52:13 -0700184 * @return The shared pointer to the encoded interest
185 */
Davide Pesavento0dc02012021-11-23 22:55:03 -0500186 std::shared_ptr<Interest>
tylerliu4140fe82021-01-27 15:45:44 -0800187 genCertFetchInterest() const;
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700188
tylerliudf6e5cc2020-10-05 18:52:13 -0700189 /**
Zhiyi Zhang6d9eda62020-10-16 17:37:02 -0700190 * @brief Decoded and installs the response certificate from the certificate fetch.
191 *
192 * @param reply, the data replied from the certificate fetch interest.
tylerliudf6e5cc2020-10-05 18:52:13 -0700193 * @return The shared pointer to the certificate being fetched.
194 */
Davide Pesavento0dc02012021-11-23 22:55:03 -0500195 static std::shared_ptr<Certificate>
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700196 onCertFetchResponse(const Data& reply);
197
tylerliudf6e5cc2020-10-05 18:52:13 -0700198 /**
Zhiyi Zhang6d9eda62020-10-16 17:37:02 -0700199 * @brief End the current request session and performs cleanup if necessary.
200 *
201 * @param state, the requester state for the request.
tylerliudf6e5cc2020-10-05 18:52:13 -0700202 */
tylerliu4140fe82021-01-27 15:45:44 -0800203 void
204 endSession();
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700205
206private:
207 static void
208 processIfError(const Data& data);
tylerliu4140fe82021-01-27 15:45:44 -0800209
210public:
211 /**
212 * @brief The CA profile for this request.
213 */
Zhiyi Zhang6499edd2021-02-17 22:37:21 -0800214 CaProfile m_caProfile;
tylerliu4140fe82021-01-27 15:45:44 -0800215 /**
216 * @brief The type of request. Either NEW, RENEW, or REVOKE.
217 */
Zhiyi Zhang6499edd2021-02-17 22:37:21 -0800218 RequestType m_type;
tylerliu4140fe82021-01-27 15:45:44 -0800219 /**
220 * @brief The identity name for the requesting certificate.
221 */
Zhiyi Zhang6499edd2021-02-17 22:37:21 -0800222 Name m_identityName;
tylerliu4140fe82021-01-27 15:45:44 -0800223 /**
224 * @brief The CA-generated request ID for the request.
225 */
Zhiyi Zhang6499edd2021-02-17 22:37:21 -0800226 RequestId m_requestId;
tylerliu4140fe82021-01-27 15:45:44 -0800227 /**
228 * @brief The current status of the request.
229 */
Zhiyi Zhang6499edd2021-02-17 22:37:21 -0800230 Status m_status = Status::BEFORE_CHALLENGE;
tylerliu4140fe82021-01-27 15:45:44 -0800231 /**
232 * @brief The type of challenge chosen.
233 */
Zhiyi Zhang6499edd2021-02-17 22:37:21 -0800234 std::string m_challengeType;
tylerliu4140fe82021-01-27 15:45:44 -0800235 /**
236 * @brief The status of the current challenge.
237 */
Zhiyi Zhang6499edd2021-02-17 22:37:21 -0800238 std::string m_challengeStatus;
tylerliu4140fe82021-01-27 15:45:44 -0800239 /**
240 * @brief The remaining number of tries left for the challenge
241 */
Zhiyi Zhang6499edd2021-02-17 22:37:21 -0800242 int m_remainingTries = 0;
tylerliu4140fe82021-01-27 15:45:44 -0800243 /**
244 * @brief The time this challenge will remain fresh
245 */
Zhiyi Zhang6499edd2021-02-17 22:37:21 -0800246 time::system_clock::TimePoint m_freshBefore;
tylerliu4140fe82021-01-27 15:45:44 -0800247 /**
248 * @brief the name of the certificate being issued.
249 */
Zhiyi Zhang6499edd2021-02-17 22:37:21 -0800250 Name m_issuedCertName;
tylerliu4140fe82021-01-27 15:45:44 -0800251 /**
252 * @brief ecdh state.
253 */
Zhiyi Zhang6499edd2021-02-17 22:37:21 -0800254 ECDHState m_ecdh;
tylerliu4140fe82021-01-27 15:45:44 -0800255 /**
256 * @brief AES key derived from the ecdh shared secret.
257 */
Zhiyi Zhang6499edd2021-02-17 22:37:21 -0800258 std::array<uint8_t, 16> m_aesKey = {};
tylerliu4140fe82021-01-27 15:45:44 -0800259 /**
260 * @brief The last Initialization Vector used by the AES encryption.
261 */
Zhiyi Zhang6499edd2021-02-17 22:37:21 -0800262 std::vector<uint8_t> m_encryptionIv;
tylerliu4140fe82021-01-27 15:45:44 -0800263 /**
264 * @brief The last Initialization Vector used by the other side's AES encryption.
265 */
Zhiyi Zhang6499edd2021-02-17 22:37:21 -0800266 std::vector<uint8_t> m_decryptionIv;
tylerliu4140fe82021-01-27 15:45:44 -0800267 /**
268 * @brief Store Nonce for signature
269 */
Zhiyi Zhang6499edd2021-02-17 22:37:21 -0800270 std::array<uint8_t, 16> m_nonce = {};
Zhiyi Zhang3f1c7cf2021-02-17 14:08:14 -0800271
tylerliu4140fe82021-01-27 15:45:44 -0800272private:
273 /**
274 * @brief The local keychain to generate and install identities, keys and certificates
275 */
Davide Pesavento0dc02012021-11-23 22:55:03 -0500276 ndn::KeyChain& m_keyChain;
tylerliu4140fe82021-01-27 15:45:44 -0800277 /**
278 * @brief State about how identity/key is generated.
279 */
280 bool m_isNewlyCreatedIdentity = false;
281 bool m_isNewlyCreatedKey = false;
282 /**
283 * @brief The keypair for the request.
284 */
Davide Pesavento0dc02012021-11-23 22:55:03 -0500285 ndn::security::Key m_keyPair;
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700286};
287
Zhiyi Zhang3002e6b2020-10-29 18:54:07 -0700288} // namespace requester
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700289} // namespace ndncert
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700290
tylerliu4140fe82021-01-27 15:45:44 -0800291#endif // NDNCERT_REQUESTER_REQUEST_HPP