blob: c031083a3908316e5faffbda102be18ed2fc9204 [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/*
Davide Pesavento76304d82023-08-10 23:38:06 -04003 * Copyright (c) 2017-2023, 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
Davide Pesavento0d1d11c2022-04-11 22:11:34 -040030namespace ndncert::requester {
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -070031
Davide Pesavento0dc02012021-11-23 22:55:03 -050032class Request : boost::noncopyable
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -070033{
34public:
tylerliudf6e5cc2020-10-05 18:52:13 -070035 /**
Zhiyi Zhang6d9eda62020-10-16 17:37:02 -070036 * @brief Generates a CA profile discovery Interest following RDR protocol.
37 *
38 * @param caName The name prefix of the CA.
Zhiyi Zhangfbcab842020-10-07 15:17:13 -070039 * @return A shared pointer to an Interest ready to be sent.
tylerliudf6e5cc2020-10-05 18:52:13 -070040 */
Davide Pesavento0dc02012021-11-23 22:55:03 -050041 static std::shared_ptr<Interest>
Zhiyi Zhangfbcab842020-10-07 15:17:13 -070042 genCaProfileDiscoveryInterest(const Name& caName);
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -070043
44 /**
Zhiyi Zhang6d9eda62020-10-16 17:37:02 -070045 * @brief Generates a CA profile fetching Interest following RDR protocol.
46 *
47 * @param reply The Data packet replied from discovery Interest.
Zhiyi Zhangfbcab842020-10-07 15:17:13 -070048 * @return A shared pointer to an Interest ready to be sent.
49 */
Davide Pesavento0dc02012021-11-23 22:55:03 -050050 static std::shared_ptr<Interest>
Zhiyi Zhangfbcab842020-10-07 15:17:13 -070051 genCaProfileInterestFromDiscoveryResponse(const Data& reply);
52
53 /**
Zhiyi Zhang6d9eda62020-10-16 17:37:02 -070054 * @brief Decodes the CA profile from the replied CA profile Data packet.
55 *
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -070056 * Will first verify the signature of the packet using the key provided inside the profile.
Zhiyi Zhanga16b7582020-10-29 18:59:46 -070057 * The application should be cautious whether to add CaProfile into the ProfileStorage.
Zhiyi Zhang6d9eda62020-10-16 17:37:02 -070058 *
59 * @param reply The Data packet replied from CA profile fetching Interest.
tylerliudf6e5cc2020-10-05 18:52:13 -070060 * @return the CaProfile if decoding is successful
61 * @throw std::runtime_error if the decoding fails or receiving an error packet.
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -070062 */
Davide Pesavento0d1d11c2022-04-11 22:11:34 -040063 static std::optional<CaProfile>
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -070064 onCaProfileResponse(const Data& reply);
65
Zhiyi Zhangfbcab842020-10-07 15:17:13 -070066 /**
Zhiyi Zhang6d9eda62020-10-16 17:37:02 -070067 * @brief Decodes the CA profile from the replied CA profile Data packet after the redirection.
68 *
Zhiyi Zhangfbcab842020-10-07 15:17:13 -070069 * Will first verify the signature of the packet using the key provided inside the profile and
70 * verify the certificate's digest matches the one obtained from the original CA.
Zhiyi Zhanga16b7582020-10-29 18:59:46 -070071 * The application should be cautious whether to add CaProfile into the ProfileStorage.
Zhiyi Zhang6d9eda62020-10-16 17:37:02 -070072 *
73 * @param reply The Data packet replied from CA profile fetching Interest.
74 * @param caCertFullName The full name obtained from original CA's probe response.
Zhiyi Zhangfbcab842020-10-07 15:17:13 -070075 * @return the CaProfile if decoding is successful
76 * @throw std::runtime_error if the decoding fails or receiving an error packet.
77 */
Davide Pesavento0d1d11c2022-04-11 22:11:34 -040078 static std::optional<CaProfile>
Zhiyi Zhang837406d2020-10-05 22:01:31 -070079 onCaProfileResponseAfterRedirection(const Data& reply, const Name& caCertFullName);
80
tylerliudf6e5cc2020-10-05 18:52:13 -070081 /**
Zhiyi Zhang6d9eda62020-10-16 17:37:02 -070082 * @brief Generates a PROBE interest to the CA (for suggested name assignments).
83 *
84 * @param ca The CA that interest is send to
85 * @param probeInfo The requester information to carry to the CA
tylerliudf6e5cc2020-10-05 18:52:13 -070086 * @return A shared pointer of to the encoded interest, ready to be sent.
87 */
Davide Pesavento0dc02012021-11-23 22:55:03 -050088 static std::shared_ptr<Interest>
tylerliu40226332020-11-11 15:37:16 -080089 genProbeInterest(const CaProfile& ca, std::multimap<std::string, std::string>&& probeInfo);
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -070090
tylerliudf6e5cc2020-10-05 18:52:13 -070091 /**
Zhiyi Zhang6d9eda62020-10-16 17:37:02 -070092 * @brief Decodes the replied data for PROBE process from the CA.
93 *
tylerliudf6e5cc2020-10-05 18:52:13 -070094 * Will first verify the signature of the packet using the key provided inside the profile.
Zhiyi Zhang6d9eda62020-10-16 17:37:02 -070095 *
96 * @param reply The replied data packet
97 * @param ca the profile of the CA that replies the packet
98 * @param identityNames The vector to load the decoded identity names from the data.
99 * @param otherCas The vector to load the decoded redirection CA prefixes from the data.
tylerliudf6e5cc2020-10-05 18:52:13 -0700100 * @throw std::runtime_error if the decoding fails or receiving an error packet.
101 */
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700102 static void
103 onProbeResponse(const Data& reply, const CaProfile& ca,
tylerliub47dad72020-10-08 21:36:55 -0700104 std::vector<std::pair<Name, int>>& identityNames, std::vector<Name>& otherCas);
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700105
tylerliu4140fe82021-01-27 15:45:44 -0800106 explicit
Davide Pesavento0dc02012021-11-23 22:55:03 -0500107 Request(ndn::KeyChain& keyChain, const CaProfile& profile, RequestType requestType);
tylerliu4140fe82021-01-27 15:45:44 -0800108
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700109 // NEW/REVOKE/RENEW related helpers
tylerliudf6e5cc2020-10-05 18:52:13 -0700110 /**
Zhiyi Zhang6d9eda62020-10-16 17:37:02 -0700111 * @brief Generates a NEW interest to the CA.
112 *
113 * @param state The current requester state for this request. Will be modified in the function.
Tianyuan Yuca23bb02022-03-09 14:09:14 -0800114 * @param keyName The key name to be requested.
Zhiyi Zhang6d9eda62020-10-16 17:37:02 -0700115 * @param notBefore The expected notBefore field for the certificate (starting time)
116 * @param notAfter The expected notAfter field for the certificate (expiration time)
tylerliudf6e5cc2020-10-05 18:52:13 -0700117 * @return The shared pointer to the encoded interest.
118 */
Davide Pesavento0dc02012021-11-23 22:55:03 -0500119 std::shared_ptr<Interest>
Tianyuan Yuca23bb02022-03-09 14:09:14 -0800120 genNewInterest(const Name& keyName,
Davide Pesavento76304d82023-08-10 23:38:06 -0400121 const time::system_clock::time_point& notBefore,
122 const time::system_clock::time_point& notAfter);
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700123
tylerliudf6e5cc2020-10-05 18:52:13 -0700124 /**
Zhiyi Zhang6d9eda62020-10-16 17:37:02 -0700125 * @brief Generates a REVOKE interest to the CA.
126 *
Zhiyi Zhang6d9eda62020-10-16 17:37:02 -0700127 * @param certificate The certificate to the revoked.
tylerliudf6e5cc2020-10-05 18:52:13 -0700128 * @return The shared pointer to the encoded interest.
129 */
Davide Pesavento0dc02012021-11-23 22:55:03 -0500130 std::shared_ptr<Interest>
131 genRevokeInterest(const Certificate& certificate);
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700132
tylerliudf6e5cc2020-10-05 18:52:13 -0700133 /**
Zhiyi Zhang6d9eda62020-10-16 17:37:02 -0700134 * @brief Decodes the replied data of NEW, RENEW, or REVOKE interest from the CA.
135 *
Zhiyi Zhang6d9eda62020-10-16 17:37:02 -0700136 * @param reply The replied data from the network
tylerliudf6e5cc2020-10-05 18:52:13 -0700137 * @return the list of challenge accepted by the CA, for CHALLENGE step.
138 * @throw std::runtime_error if the decoding fails or receiving an error packet.
139 */
tylerliu4140fe82021-01-27 15:45:44 -0800140 std::list<std::string>
141 onNewRenewRevokeResponse(const Data& reply);
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700142
143 // CHALLENGE helpers
tylerliudf6e5cc2020-10-05 18:52:13 -0700144 /**
Zhiyi Zhang6d9eda62020-10-16 17:37:02 -0700145 * @brief Generates the required parameter for the selected challenge for the request
146 *
Davide Pesavento76304d82023-08-10 23:38:06 -0400147 * @param challengeSelected The selected challenge for the request.
148 * Can use state.m_challengeType to continue.
tylerliudf6e5cc2020-10-05 18:52:13 -0700149 * @return The requirement list for the current stage of the challenge, in name, prompt mapping.
Zhiyi Zhangc5d93a92020-10-14 17:07:35 -0700150 * @throw std::runtime_error if the challenge is not supported.
tylerliudf6e5cc2020-10-05 18:52:13 -0700151 */
tylerliu4140fe82021-01-27 15:45:44 -0800152 std::multimap<std::string, std::string>
153 selectOrContinueChallenge(const std::string& challengeSelected);
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700154
tylerliudf6e5cc2020-10-05 18:52:13 -0700155 /**
Zhiyi Zhang6d9eda62020-10-16 17:37:02 -0700156 * @brief Generates the CHALLENGE interest for the request.
157 *
Davide Pesavento76304d82023-08-10 23:38:06 -0400158 * @param parameters The requirement list, in name, value mapping.
tylerliudf6e5cc2020-10-05 18:52:13 -0700159 * @return The shared pointer to the encoded interest
Zhiyi Zhangc5d93a92020-10-14 17:07:35 -0700160 * @throw std::runtime_error if the challenge is not selected or is not supported.
tylerliudf6e5cc2020-10-05 18:52:13 -0700161 */
Davide Pesavento0dc02012021-11-23 22:55:03 -0500162 std::shared_ptr<Interest>
tylerliu4140fe82021-01-27 15:45:44 -0800163 genChallengeInterest(std::multimap<std::string, std::string>&& parameters);
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700164
tylerliudf6e5cc2020-10-05 18:52:13 -0700165 /**
Zhiyi Zhang6d9eda62020-10-16 17:37:02 -0700166 * @brief Decodes the responded data from the CHALLENGE interest.
167 *
Davide Pesavento76304d82023-08-10 23:38:06 -0400168 * @param reply The response data.
tylerliudf6e5cc2020-10-05 18:52:13 -0700169 * @throw std::runtime_error if the decoding fails or receiving an error packet.
170 */
tylerliu4140fe82021-01-27 15:45:44 -0800171 void
172 onChallengeResponse(const Data& reply);
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700173
tylerliudf6e5cc2020-10-05 18:52:13 -0700174 /**
Zhiyi Zhang6d9eda62020-10-16 17:37:02 -0700175 * @brief Generate the interest to fetch the issued certificate
176 *
tylerliudf6e5cc2020-10-05 18:52:13 -0700177 * @return The shared pointer to the encoded interest
178 */
Davide Pesavento0dc02012021-11-23 22:55:03 -0500179 std::shared_ptr<Interest>
tylerliu4140fe82021-01-27 15:45:44 -0800180 genCertFetchInterest() const;
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700181
tylerliudf6e5cc2020-10-05 18:52:13 -0700182 /**
Zhiyi Zhang6d9eda62020-10-16 17:37:02 -0700183 * @brief Decoded and installs the response certificate from the certificate fetch.
184 *
Davide Pesavento76304d82023-08-10 23:38:06 -0400185 * @param reply The data replied from the certificate fetch interest.
tylerliudf6e5cc2020-10-05 18:52:13 -0700186 * @return The shared pointer to the certificate being fetched.
187 */
Davide Pesavento0dc02012021-11-23 22:55:03 -0500188 static std::shared_ptr<Certificate>
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700189 onCertFetchResponse(const Data& reply);
190
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700191private:
192 static void
193 processIfError(const Data& data);
tylerliu4140fe82021-01-27 15:45:44 -0800194
195public:
196 /**
197 * @brief The CA profile for this request.
198 */
Zhiyi Zhang6499edd2021-02-17 22:37:21 -0800199 CaProfile m_caProfile;
tylerliu4140fe82021-01-27 15:45:44 -0800200 /**
201 * @brief The type of request. Either NEW, RENEW, or REVOKE.
202 */
Zhiyi Zhang6499edd2021-02-17 22:37:21 -0800203 RequestType m_type;
tylerliu4140fe82021-01-27 15:45:44 -0800204 /**
205 * @brief The identity name for the requesting certificate.
206 */
Zhiyi Zhang6499edd2021-02-17 22:37:21 -0800207 Name m_identityName;
tylerliu4140fe82021-01-27 15:45:44 -0800208 /**
209 * @brief The CA-generated request ID for the request.
210 */
Zhiyi Zhang6499edd2021-02-17 22:37:21 -0800211 RequestId m_requestId;
tylerliu4140fe82021-01-27 15:45:44 -0800212 /**
213 * @brief The current status of the request.
214 */
Zhiyi Zhang6499edd2021-02-17 22:37:21 -0800215 Status m_status = Status::BEFORE_CHALLENGE;
tylerliu4140fe82021-01-27 15:45:44 -0800216 /**
217 * @brief The type of challenge chosen.
218 */
Zhiyi Zhang6499edd2021-02-17 22:37:21 -0800219 std::string m_challengeType;
tylerliu4140fe82021-01-27 15:45:44 -0800220 /**
221 * @brief The status of the current challenge.
222 */
Zhiyi Zhang6499edd2021-02-17 22:37:21 -0800223 std::string m_challengeStatus;
tylerliu4140fe82021-01-27 15:45:44 -0800224 /**
225 * @brief The remaining number of tries left for the challenge
226 */
Zhiyi Zhang6499edd2021-02-17 22:37:21 -0800227 int m_remainingTries = 0;
tylerliu4140fe82021-01-27 15:45:44 -0800228 /**
229 * @brief The time this challenge will remain fresh
230 */
Davide Pesavento76304d82023-08-10 23:38:06 -0400231 time::system_clock::time_point m_freshBefore;
tylerliu4140fe82021-01-27 15:45:44 -0800232 /**
233 * @brief the name of the certificate being issued.
234 */
Zhiyi Zhang6499edd2021-02-17 22:37:21 -0800235 Name m_issuedCertName;
tylerliu4140fe82021-01-27 15:45:44 -0800236 /**
Tianyuan Yu60775552022-03-07 17:10:10 -0800237 * @brief The optional forwarding hint.
238 */
239 Name m_forwardingHint;
240 /**
tylerliu4140fe82021-01-27 15:45:44 -0800241 * @brief ecdh state.
242 */
Zhiyi Zhang6499edd2021-02-17 22:37:21 -0800243 ECDHState m_ecdh;
tylerliu4140fe82021-01-27 15:45:44 -0800244 /**
245 * @brief AES key derived from the ecdh shared secret.
246 */
Zhiyi Zhang6499edd2021-02-17 22:37:21 -0800247 std::array<uint8_t, 16> m_aesKey = {};
tylerliu4140fe82021-01-27 15:45:44 -0800248 /**
249 * @brief The last Initialization Vector used by the AES encryption.
250 */
Zhiyi Zhang6499edd2021-02-17 22:37:21 -0800251 std::vector<uint8_t> m_encryptionIv;
tylerliu4140fe82021-01-27 15:45:44 -0800252 /**
253 * @brief The last Initialization Vector used by the other side's AES encryption.
254 */
Zhiyi Zhang6499edd2021-02-17 22:37:21 -0800255 std::vector<uint8_t> m_decryptionIv;
tylerliu4140fe82021-01-27 15:45:44 -0800256 /**
257 * @brief Store Nonce for signature
258 */
Zhiyi Zhang6499edd2021-02-17 22:37:21 -0800259 std::array<uint8_t, 16> m_nonce = {};
Zhiyi Zhang3f1c7cf2021-02-17 14:08:14 -0800260
tylerliu4140fe82021-01-27 15:45:44 -0800261private:
262 /**
263 * @brief The local keychain to generate and install identities, keys and certificates
264 */
Davide Pesavento0dc02012021-11-23 22:55:03 -0500265 ndn::KeyChain& m_keyChain;
tylerliu4140fe82021-01-27 15:45:44 -0800266 /**
tylerliu4140fe82021-01-27 15:45:44 -0800267 * @brief The keypair for the request.
268 */
Davide Pesavento0dc02012021-11-23 22:55:03 -0500269 ndn::security::Key m_keyPair;
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700270};
271
Davide Pesavento0d1d11c2022-04-11 22:11:34 -0400272} // namespace ndncert::requester
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700273
tylerliu4140fe82021-01-27 15:45:44 -0800274#endif // NDNCERT_REQUESTER_REQUEST_HPP