blob: 8e3bd174ced0e5ea027a7bb5d9e98aa90edda503 [file] [log] [blame]
Zhiyi Zhang23564c82017-03-01 10:22:22 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -07003 * Copyright (c) 2017-2020, Regents of the University of California.
Zhiyi Zhang23564c82017-03-01 10:22:22 -08004 *
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
21#include "client-module.hpp"
22#include "logging.hpp"
Zhiyi Zhanga9bda732017-05-20 22:58:55 -070023#include "challenge-module.hpp"
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070024#include "crypto-support/enc-tlv.hpp"
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +080025#include <ndn-cxx/util/io.hpp>
Zhiyi Zhang23564c82017-03-01 10:22:22 -080026#include <ndn-cxx/security/signing-helpers.hpp>
27#include <ndn-cxx/security/verification-helpers.hpp>
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070028#include <ndn-cxx/util/random.hpp>
29#include <ndn-cxx/security/transform/base64-encode.hpp>
30#include <ndn-cxx/security/transform/buffer-source.hpp>
31#include <ndn-cxx/security/transform/stream-sink.hpp>
Zhiyi Zhang23564c82017-03-01 10:22:22 -080032
33namespace ndn {
34namespace ndncert {
35
36_LOG_INIT(ndncert.client);
37
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070038ClientModule::ClientModule(security::v2::KeyChain& keyChain)
39 : m_keyChain(keyChain)
Zhiyi Zhang23564c82017-03-01 10:22:22 -080040{
41}
42
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -070043ClientModule::~ClientModule()
44{
45 endSession();
46}
Davide Pesavento08994782018-01-22 12:13:41 -050047
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070048shared_ptr<Interest>
swa77020643ac2020-03-26 02:24:45 -070049ClientModule::generateInfoInterest(const Name& caName)
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +080050{
51 Name interestName = caName;
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070052 if (readString(caName.at(-1)) != "CA")
53 interestName.append("CA");
swa77020643ac2020-03-26 02:24:45 -070054 interestName.append("INFO");
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070055 auto interest = make_shared<Interest>(interestName);
56 interest->setMustBeFresh(true);
57 interest->setCanBePrefix(false);
58 return interest;
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +080059}
60
Zhiyi Zhangcaab5462019-10-18 13:41:02 -070061bool
62ClientModule::verifyProbeInfoResponse(const Data& reply)
63{
64 // parse the ca item
65 auto contentJson = getJsonFromData(reply);
66 auto caItem = ClientConfig::extractCaItem(contentJson);
67
68 // verify the probe Data's sig
69 if (!security::verifySignature(reply, caItem.m_anchor)) {
70 _LOG_ERROR("Cannot verify data signature from " << m_ca.m_caName.toUri());
71 return false;
72 }
73 return true;
74}
75
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +080076void
Zhiyi Zhangcaab5462019-10-18 13:41:02 -070077ClientModule::addCaFromProbeInfoResponse(const Data& reply)
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +080078{
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070079 // parse the ca item
80 auto contentJson = getJsonFromData(reply);
81 auto caItem = ClientConfig::extractCaItem(contentJson);
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +080082
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070083 // update the local config
84 bool findItem = false;
85 for (auto& item : m_config.m_caItems) {
86 if (item.m_caName == caItem.m_caName) {
87 findItem = true;
88 item = caItem;
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +080089 }
90 }
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070091 if (!findItem) {
92 m_config.m_caItems.push_back(caItem);
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +080093 }
Zhiyi Zhang23564c82017-03-01 10:22:22 -080094}
95
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070096shared_ptr<Interest>
97ClientModule::generateProbeInterest(const ClientCaItem& ca, const std::string& probeInfo)
Zhiyi Zhang23564c82017-03-01 10:22:22 -080098{
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070099 Name interestName = ca.m_caName;
swa770de007bc2020-03-24 21:26:21 -0700100 interestName.append("CA").append("PROBE");
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700101 auto interest = make_shared<Interest>(interestName);
102 interest->setMustBeFresh(true);
103 interest->setCanBePrefix(false);
Yufeng Zhang424d0362019-06-12 16:48:27 -0700104 auto paramJson = genProbeRequestJson(ca, probeInfo);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700105 interest->setApplicationParameters(paramFromJson(paramJson));
106
107 // update local state
108 m_ca = ca;
109 return interest;
110}
111
112void
113ClientModule::onProbeResponse(const Data& reply)
114{
115 if (!security::verifySignature(reply, m_ca.m_anchor)) {
116 _LOG_ERROR("Cannot verify data signature from " << m_ca.m_caName.toUri());
117 return;
118 }
119 auto contentJson = getJsonFromData(reply);
120
121 // read the available name and put it into the state
Zhiyi Zhang8da54d62019-11-21 00:03:05 -0800122 auto nameUri = contentJson.get(JSON_CA_NAME, "");
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700123 if (nameUri != "") {
124 m_identityName = Name(nameUri);
125 }
Zhiyi Zhang781a5602019-06-26 19:05:04 -0700126 else {
127 NDN_LOG_TRACE("The JSON_CA_NAME is empty.");
128 }
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700129}
130
131shared_ptr<Interest>
132ClientModule::generateNewInterest(const time::system_clock::TimePoint& notBefore,
133 const time::system_clock::TimePoint& notAfter,
Zhiyi Zhang5f749a22019-06-12 17:02:33 -0700134 const Name& identityName, const shared_ptr<Data>& probeToken)
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700135{
136 // Name requestedName = identityName;
137 if (!identityName.empty()) { // if identityName is not empty, find the corresponding CA
138 bool findCa = false;
139 for (const auto& caItem : m_config.m_caItems) {
140 if (caItem.m_caName.isPrefixOf(identityName)) {
141 m_ca = caItem;
142 findCa = true;
143 }
144 }
145 if (!findCa) { // if cannot find, cannot proceed
146 return nullptr;
147 }
148 m_identityName = identityName;
149 }
150 else { // if identityName is empty, check m_identityName or generate a random name
151 if (!m_identityName.empty()) {
152 // do nothing
153 }
154 else {
Zhiyi Zhang781a5602019-06-26 19:05:04 -0700155 NDN_LOG_TRACE("Randomly create a new name because m_identityName is empty and the param is empty.");
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700156 auto id = std::to_string(random::generateSecureWord64());
157 m_identityName = m_ca.m_caName;
158 m_identityName.append(id);
159 }
160 }
161
162 // generate a newly key pair or use an existing key
Zhiyi Zhang10130782018-02-01 18:28:49 -0800163 const auto& pib = m_keyChain.getPib();
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -0700164 security::pib::Identity identity;
Zhiyi Zhang10130782018-02-01 18:28:49 -0800165 try {
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -0700166 identity = pib.getIdentity(m_identityName);
Zhiyi Zhang10130782018-02-01 18:28:49 -0800167 }
168 catch (const security::Pib::Error& e) {
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -0700169 identity = m_keyChain.createIdentity(m_identityName);
170 m_isNewlyCreatedIdentity = true;
171 m_isNewlyCreatedKey = true;
172 }
173 try {
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700174 m_key = identity.getDefaultKey();
Zhiyi Zhang10130782018-02-01 18:28:49 -0800175 }
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -0700176 catch (const security::Pib::Error& e) {
177 m_key = m_keyChain.createKey(identity);
178 m_isNewlyCreatedKey = true;
179 }
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800180
181 // generate certificate request
182 security::v2::Certificate certRequest;
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700183 certRequest.setName(Name(m_key.getName()).append("cert-request").appendVersion());
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800184 certRequest.setContentType(tlv::ContentType_Key);
185 certRequest.setFreshnessPeriod(time::hours(24));
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700186 certRequest.setContent(m_key.getPublicKey().data(), m_key.getPublicKey().size());
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800187 SignatureInfo signatureInfo;
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700188 signatureInfo.setValidityPeriod(security::ValidityPeriod(notBefore, notAfter));
189 m_keyChain.sign(certRequest, signingByKey(m_key.getName()).setSignatureInfo(signatureInfo));
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800190
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700191 // generate Interest packet
192 Name interestName = m_ca.m_caName;
swa770de007bc2020-03-24 21:26:21 -0700193 interestName.append("CA").append("NEW");
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700194 auto interest = make_shared<Interest>(interestName);
195 interest->setMustBeFresh(true);
196 interest->setCanBePrefix(false);
Zhiyi Zhang5f749a22019-06-12 17:02:33 -0700197 interest->setApplicationParameters(paramFromJson(genNewRequestJson(m_ecdh.getBase64PubKey(), certRequest, probeToken)));
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800198
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700199 // sign the Interest packet
200 m_keyChain.sign(*interest, signingByKey(m_key.getName()));
201 return interest;
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800202}
203
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700204std::list<std::string>
205ClientModule::onNewResponse(const Data& reply)
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800206{
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700207 if (!security::verifySignature(reply, m_ca.m_anchor)) {
208 _LOG_ERROR("Cannot verify data signature from " << m_ca.m_caName.toUri());
209 return std::list<std::string>();
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800210 }
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700211 auto contentJson = getJsonFromData(reply);
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800212
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700213 // ECDH
Zhiyi Zhang8da54d62019-11-21 00:03:05 -0800214 const auto& peerKeyBase64Str = contentJson.get(JSON_CA_ECDH, "");
215 const auto& saltStr = contentJson.get(JSON_CA_SALT, "");
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700216 uint64_t saltInt = std::stoull(saltStr);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700217 m_ecdh.deriveSecret(peerKeyBase64Str);
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800218
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700219 // HKDF
Zhiyi Zhang36706832019-07-04 21:33:03 -0700220 hkdf(m_ecdh.context->sharedSecret, m_ecdh.context->sharedSecretLen,
221 (uint8_t*)&saltInt, sizeof(saltInt), m_aesKey, sizeof(m_aesKey));
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800222
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700223 // update state
Zhiyi Zhang8da54d62019-11-21 00:03:05 -0800224 m_status = contentJson.get(JSON_CA_STATUS, 0);
225 m_requestId = contentJson.get(JSON_CA_REQUEST_ID, "");
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700226
227 auto challengesJson = contentJson.get_child(JSON_CA_CHALLENGES);
228 m_challengeList.clear();
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800229 for (const auto& challengeJson : challengesJson) {
Zhiyi Zhang8da54d62019-11-21 00:03:05 -0800230 m_challengeList.push_back(challengeJson.second.get(JSON_CA_CHALLENGE_ID, ""));
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800231 }
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700232 return m_challengeList;
233}
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800234
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700235shared_ptr<Interest>
236ClientModule::generateChallengeInterest(const JsonSection& paramJson)
237{
Zhiyi Zhang8da54d62019-11-21 00:03:05 -0800238 m_challengeType = paramJson.get(JSON_CLIENT_SELECTED_CHALLENGE, "");
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800239
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700240 Name interestName = m_ca.m_caName;
swa770de007bc2020-03-24 21:26:21 -0700241 interestName.append("CA").append("CHALLENGE").append(m_requestId);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700242 auto interest = make_shared<Interest>(interestName);
243 interest->setMustBeFresh(true);
244 interest->setCanBePrefix(false);
245
246 // encrypt the Interest parameters
247 std::stringstream ss;
248 boost::property_tree::write_json(ss, paramJson);
249 auto payload = ss.str();
Zhiyi Zhang36706832019-07-04 21:33:03 -0700250 auto paramBlock = genEncBlock(tlv::ApplicationParameters, m_aesKey, sizeof(m_aesKey),
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700251 (const uint8_t*)payload.c_str(), payload.size());
252 interest->setApplicationParameters(paramBlock);
253
254 m_keyChain.sign(*interest, signingByKey(m_key.getName()));
255 return interest;
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800256}
257
258void
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700259ClientModule::onChallengeResponse(const Data& reply)
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800260{
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700261 if (!security::verifySignature(reply, m_ca.m_anchor)) {
262 _LOG_ERROR("Cannot verify data signature from " << m_ca.m_caName.toUri());
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800263 return;
264 }
Zhiyi Zhang36706832019-07-04 21:33:03 -0700265 auto result = parseEncBlock(m_aesKey, sizeof(m_aesKey), reply.getContent());
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700266 std::string payload((const char*)result.data(), result.size());
267 std::istringstream ss(payload);
268 JsonSection contentJson;
269 boost::property_tree::json_parser::read_json(ss, contentJson);
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800270
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700271 // update state
Zhiyi Zhang8da54d62019-11-21 00:03:05 -0800272 m_status = contentJson.get(JSON_CA_STATUS, 0);
273 m_challengeStatus = contentJson.get(JSON_CHALLENGE_STATUS, "");
274 m_remainingTries = contentJson.get(JSON_CHALLENGE_REMAINING_TRIES, 0);
275 m_freshBefore = time::system_clock::now() + time::seconds(contentJson.get(JSON_CHALLENGE_REMAINING_TIME, 0));
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700276}
Zhiyi Zhange30eb352017-04-13 15:26:14 -0700277
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700278shared_ptr<Interest>
279ClientModule::generateDownloadInterest()
280{
281 Name interestName = m_ca.m_caName;
swa770de007bc2020-03-24 21:26:21 -0700282 interestName.append("CA").append("DOWNLOAD").append(m_requestId);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700283 auto interest = make_shared<Interest>(interestName);
284 interest->setMustBeFresh(true);
285 interest->setCanBePrefix(false);
286 return interest;
287}
Zhiyi Zhange30eb352017-04-13 15:26:14 -0700288
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700289shared_ptr<Interest>
290ClientModule::generateCertFetchInterest()
291{
292 Name interestName = m_identityName;
293 interestName.append("KEY").append(m_certId);
294 auto interest = make_shared<Interest>(interestName);
295 interest->setMustBeFresh(true);
296 interest->setCanBePrefix(false);
297 return interest;
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800298}
299
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -0700300shared_ptr<security::v2::Certificate>
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700301ClientModule::onDownloadResponse(const Data& reply)
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800302{
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800303 try {
304 security::v2::Certificate cert(reply.getContent().blockFromValue());
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700305 m_keyChain.addCertificate(m_key, cert);
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800306 _LOG_TRACE("Got DOWNLOAD response and installed the cert " << cert.getName());
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -0700307 m_isCertInstalled = true;
308 return make_shared<security::v2::Certificate>(cert);
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800309 }
310 catch (const std::exception& e) {
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700311 _LOG_ERROR("Cannot add replied certificate into the keychain " << e.what());
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -0700312 return nullptr;
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800313 }
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800314}
315
316void
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700317ClientModule::onCertFetchResponse(const Data& reply)
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800318{
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700319 onDownloadResponse(reply);
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800320}
321
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -0700322void
323ClientModule::endSession()
324{
325 if (getApplicationStatus() == STATUS_SUCCESS || getApplicationStatus() == STATUS_ENDED) {
326 return;
327 }
328 if (m_isNewlyCreatedIdentity) {
329 // put the identity into the if scope is because it may cause an error
330 // outside since when endSession is called, identity may not have been created yet.
331 auto identity = m_keyChain.getPib().getIdentity(m_identityName);
332 m_keyChain.deleteIdentity(identity);
333 }
334 else if (m_isNewlyCreatedKey) {
335 auto identity = m_keyChain.getPib().getIdentity(m_identityName);
336 m_keyChain.deleteKey(identity, m_key);
337 }
338 m_status = STATUS_ENDED;
339}
340
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800341JsonSection
342ClientModule::getJsonFromData(const Data& data)
343{
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700344 std::istringstream ss(encoding::readString(data.getContent()));
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800345 JsonSection json;
346 boost::property_tree::json_parser::read_json(ss, json);
347 return json;
348}
349
Zhiyi Zhang547c8512019-06-18 23:46:14 -0700350std::vector<std::string>
351ClientModule::parseProbeComponents(const std::string& probe)
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700352{
Zhiyi Zhang547c8512019-06-18 23:46:14 -0700353 std::vector<std::string> components;
Yufeng Zhang424d0362019-06-12 16:48:27 -0700354 std::string delimiter = ":";
355 size_t last = 0;
356 size_t next = 0;
Zhiyi Zhang547c8512019-06-18 23:46:14 -0700357 while ((next = probe.find(delimiter, last)) != std::string::npos) {
358 components.push_back(probe.substr(last, next - last));
359 last = next + 1;
360 }
361 components.push_back(probe.substr(last));
362 return components;
363}
Yufeng Zhang424d0362019-06-12 16:48:27 -0700364
swa77020643ac2020-03-26 02:24:45 -0700365JsonSection
Zhiyi Zhang547c8512019-06-18 23:46:14 -0700366ClientModule::genProbeRequestJson(const ClientCaItem& ca, const std::string& probeInfo)
367{
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700368 JsonSection root;
Zhiyi Zhang547c8512019-06-18 23:46:14 -0700369 std::vector<std::string> fields = parseProbeComponents(ca.m_probe);
370 std::vector<std::string> arguments = parseProbeComponents(probeInfo);;
Yufeng Zhang424d0362019-06-12 16:48:27 -0700371
372 if (arguments.size() != fields.size()) {
373 BOOST_THROW_EXCEPTION(Error("Error in genProbeRequestJson: argument list does not match field list in the config file."));
374 }
Yufeng Zhang424d0362019-06-12 16:48:27 -0700375 for (size_t i = 0; i < fields.size(); ++i) {
376 root.put(fields.at(i), arguments.at(i));
377 }
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700378 return root;
379}
380
swa77020643ac2020-03-26 02:24:45 -0700381JsonSection
Zhiyi Zhang5f749a22019-06-12 17:02:33 -0700382ClientModule::genNewRequestJson(const std::string& ecdhPub, const security::v2::Certificate& certRequest,
383 const shared_ptr<Data>& probeToken)
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700384{
385 JsonSection root;
386 std::stringstream ss;
387 try {
388 security::transform::bufferSource(certRequest.wireEncode().wire(), certRequest.wireEncode().size())
Zhiyi Zhang8da54d62019-11-21 00:03:05 -0800389 >> security::transform::base64Encode(false)
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700390 >> security::transform::streamSink(ss);
391 }
392 catch (const security::transform::Error& e) {
393 _LOG_ERROR("Cannot convert self-signed cert into BASE64 string " << e.what());
394 return root;
395 }
396 root.put(JSON_CLIENT_ECDH, ecdhPub);
397 root.put(JSON_CLIENT_CERT_REQ, ss.str());
Zhiyi Zhang5f749a22019-06-12 17:02:33 -0700398 if (probeToken != nullptr) {
399 // clear the stringstream
400 ss.str("");
401 ss.clear();
402 // transform the probe data into a base64 string
403 try {
404 security::transform::bufferSource(probeToken->wireEncode().wire(), probeToken->wireEncode().size())
Zhiyi Zhang8da54d62019-11-21 00:03:05 -0800405 >> security::transform::base64Encode(false)
Zhiyi Zhang5f749a22019-06-12 17:02:33 -0700406 >> security::transform::streamSink(ss);
407 }
408 catch (const security::transform::Error& e) {
409 _LOG_ERROR("Cannot convert self-signed cert into BASE64 string " << e.what());
410 return root;
411 }
412 // add the token into the JSON
413 root.put("probe-token", ss.str());
414 }
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700415 return root;
416}
417
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800418Block
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700419ClientModule::paramFromJson(const JsonSection& json)
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800420{
421 std::stringstream ss;
422 boost::property_tree::write_json(ss, json);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700423 return makeStringBlock(ndn::tlv::ApplicationParameters, ss.str());
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800424}
425
426} // namespace ndncert
427} // namespace ndn