blob: 13abf4b1d9bce208fbe486d7b2407a95000187a9 [file] [log] [blame]
Zhiyi Zhangf5246c42017-01-26 09:39:20 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Davide Pesavento914d05f2019-07-13 16:20:19 -04002/*
swa770de007bc2020-03-24 21:26:21 -07003 * Copyright (c) 2017-2020, Regents of the University of California.
Zhiyi Zhangf5246c42017-01-26 09:39:20 -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
Zhiyi Zhangf5246c42017-01-26 09:39:20 -080021#include "ca-module.hpp"
Zhiyi Zhangad6cf932017-10-26 16:19:15 -070022#include "database-fixture.hpp"
Zhiyi Zhangf5246c42017-01-26 09:39:20 -080023#include "client-module.hpp"
24#include "challenge-module.hpp"
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070025#include "challenge-module/challenge-pin.hpp"
26#include "challenge-module/challenge-email.hpp"
Davide Pesavento914d05f2019-07-13 16:20:19 -040027
Zhiyi Zhangf5246c42017-01-26 09:39:20 -080028#include <ndn-cxx/util/dummy-client-face.hpp>
29#include <ndn-cxx/security/signing-helpers.hpp>
30#include <ndn-cxx/security/transform/public-key.hpp>
31#include <ndn-cxx/security/verification-helpers.hpp>
32
33namespace ndn {
34namespace ndncert {
35namespace tests {
36
Zhiyi Zhangae123bf2017-04-14 12:24:53 -070037BOOST_FIXTURE_TEST_SUITE(TestCaModule, DatabaseFixture)
Zhiyi Zhangf5246c42017-01-26 09:39:20 -080038
39BOOST_AUTO_TEST_CASE(Initialization)
40{
Zhiyi Zhang42d992d2019-07-07 16:46:50 -070041 util::DummyClientFace face(io, {true, true});
42 CaModule ca(face, m_keyChain, "tests/unit-tests/ca.conf.test", "ca-storage-memory");
Suyong Won44d0cce2020-05-10 04:07:43 -070043 BOOST_CHECK_EQUAL(ca.getCaConf().m_caPrefix, "/ndn");
Zhiyi Zhangf5246c42017-01-26 09:39:20 -080044
45 auto identity = addIdentity(Name("/ndn/site2"));
46 auto key = identity.getDefaultKey();
47 auto cert = key.getDefaultCertificate();
48 ca.getCaStorage()->addCertificate("111", cert);
49 BOOST_CHECK_EQUAL(ca.getCaStorage()->getCertificate("111").getIdentity(), Name("/ndn/site2"));
50
51 advanceClocks(time::milliseconds(20), 60);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070052 BOOST_CHECK_EQUAL(ca.m_registeredPrefixHandles.size(), 2);
swa770cf1d8f72020-04-21 23:12:39 -070053 BOOST_CHECK_EQUAL(ca.m_interestFilterHandles.size(), 4); // onInfo, onProbe, onNew, onChallenge
Zhiyi Zhangf5246c42017-01-26 09:39:20 -080054}
55
56BOOST_AUTO_TEST_CASE(HandleProbe)
57{
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070058 auto identity = addIdentity(Name("/ndn"));
Zhiyi Zhangf5246c42017-01-26 09:39:20 -080059 auto key = identity.getDefaultKey();
60 auto cert = key.getDefaultCertificate();
61
Zhiyi Zhang42d992d2019-07-07 16:46:50 -070062 util::DummyClientFace face(io, {true, true});
63 CaModule ca(face, m_keyChain, "tests/unit-tests/ca.conf.test", "ca-storage-memory");
Suyong Won44d0cce2020-05-10 04:07:43 -070064 ca.setProbeHandler([&] (const Block& probeInfo) {
Yufeng Zhang424d0362019-06-12 16:48:27 -070065 return "example";
Zhiyi Zhangf5246c42017-01-26 09:39:20 -080066 });
Zhiyi Zhangf5246c42017-01-26 09:39:20 -080067 advanceClocks(time::milliseconds(20), 60);
68
swa770de007bc2020-03-24 21:26:21 -070069 Interest interest("/ndn/CA/PROBE");
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070070 interest.setCanBePrefix(false);
Suyong Won44d0cce2020-05-10 04:07:43 -070071
72 Block paramTLV = makeEmptyBlock(tlv::ApplicationParameters);
73 paramTLV.push_back(makeStringBlock(tlv_parameter_key, JSON_CLIENT_PROBE_INFO));
74 paramTLV.push_back(makeStringBlock(tlv_parameter_value, "zhiyi"));
75 paramTLV.encode();
76 interest.setApplicationParameters(paramTLV);
Zhiyi Zhangf5246c42017-01-26 09:39:20 -080077
78 int count = 0;
79 face.onSendData.connect([&] (const Data& response) {
80 count++;
81 BOOST_CHECK(security::verifySignature(response, cert));
Suyong Won44d0cce2020-05-10 04:07:43 -070082 Block contentBlock = response.getContent();
83 contentBlock.parse();
84 BOOST_CHECK_EQUAL(readString(contentBlock.get(tlv_ca_prefix)), "/ndn/example");
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070085 });
86 face.receive(interest);
87
88 advanceClocks(time::milliseconds(20), 60);
89 BOOST_CHECK_EQUAL(count, 1);
90}
91
swa77020643ac2020-03-26 02:24:45 -070092BOOST_AUTO_TEST_CASE(HandleInfo)
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070093{
94 auto identity = addIdentity(Name("/ndn"));
95 auto key = identity.getDefaultKey();
96 auto cert = key.getDefaultCertificate();
97
Zhiyi Zhang42d992d2019-07-07 16:46:50 -070098 util::DummyClientFace face(io, {true, true});
99 CaModule ca(face, m_keyChain, "tests/unit-tests/ca.conf.test", "ca-storage-memory");
Suyong Won44d0cce2020-05-10 04:07:43 -0700100 ca.setProbeHandler([&] (const Block& probeInfo) {
Yufeng Zhang424d0362019-06-12 16:48:27 -0700101 return "example";
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700102 });
103 advanceClocks(time::milliseconds(20), 60);
104
swa77020643ac2020-03-26 02:24:45 -0700105 Interest interest("/ndn/CA/INFO");
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700106 interest.setCanBePrefix(false);
107
108 int count = 0;
109 face.onSendData.connect([&] (const Data& response) {
110 count++;
111 BOOST_CHECK(security::verifySignature(response, cert));
112 auto contentJson = ClientModule::getJsonFromData(response);
113 auto caItem = ClientConfig::extractCaItem(contentJson);
Davide Pesavento914d05f2019-07-13 16:20:19 -0400114 BOOST_CHECK_EQUAL(caItem.m_caName, "/ndn");
Zhiyi Zhanga1fc6232019-06-13 14:56:59 -0700115 BOOST_CHECK_EQUAL(caItem.m_probe, "");
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700116 BOOST_CHECK_EQUAL(caItem.m_anchor.wireEncode(), cert.wireEncode());
117 BOOST_CHECK_EQUAL(caItem.m_caInfo, "ndn testbed ca");
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800118 });
119 face.receive(interest);
120
121 advanceClocks(time::milliseconds(20), 60);
122 BOOST_CHECK_EQUAL(count, 1);
123}
124
Zhiyi Zhanga63b7372017-05-17 14:14:34 -0700125BOOST_AUTO_TEST_CASE(HandleProbeUsingDefaultHandler)
126{
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700127 auto identity = addIdentity(Name("/ndn"));
Zhiyi Zhanga63b7372017-05-17 14:14:34 -0700128 auto key = identity.getDefaultKey();
129 auto cert = key.getDefaultCertificate();
130
Zhiyi Zhang42d992d2019-07-07 16:46:50 -0700131 util::DummyClientFace face(io, {true, true});
132 CaModule ca(face, m_keyChain, "tests/unit-tests/ca.conf.test", "ca-storage-memory");
Zhiyi Zhanga63b7372017-05-17 14:14:34 -0700133 advanceClocks(time::milliseconds(20), 60);
134
swa770de007bc2020-03-24 21:26:21 -0700135 Interest interest("/ndn/CA/PROBE");
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700136 interest.setCanBePrefix(false);
137 JsonSection paramJson;
138 paramJson.add(JSON_CLIENT_PROBE_INFO, "zhiyi");
139 interest.setApplicationParameters(ClientModule::paramFromJson(paramJson));
Zhiyi Zhanga63b7372017-05-17 14:14:34 -0700140
141 int count = 0;
142 face.onSendData.connect([&] (const Data& response) {
143 count++;
144 BOOST_CHECK(security::verifySignature(response, cert));
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700145 auto contentJson = ClientModule::getJsonFromData(response);
146 BOOST_CHECK(contentJson.get<std::string>(JSON_CA_NAME) != "");
Zhiyi Zhanga63b7372017-05-17 14:14:34 -0700147 });
148 face.receive(interest);
149
150 advanceClocks(time::milliseconds(20), 60);
151 BOOST_CHECK_EQUAL(count, 1);
152}
153
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800154BOOST_AUTO_TEST_CASE(HandleNew)
155{
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700156 auto identity = addIdentity(Name("/ndn"));
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800157 auto key = identity.getDefaultKey();
158 auto cert = key.getDefaultCertificate();
159
Zhiyi Zhang42d992d2019-07-07 16:46:50 -0700160 util::DummyClientFace face(io, {true, true});
161 CaModule ca(face, m_keyChain, "tests/unit-tests/ca.conf.test", "ca-storage-memory");
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800162 advanceClocks(time::milliseconds(20), 60);
163
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700164 ClientModule client(m_keyChain);
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800165 ClientCaItem item;
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700166 item.m_caName = Name("/ndn");
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800167 item.m_anchor = cert;
168 client.getClientConf().m_caItems.push_back(item);
Zhiyi Zhang5f749a22019-06-12 17:02:33 -0700169
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700170 auto interest = client.generateNewInterest(time::system_clock::now(),
Zhiyi Zhang5f749a22019-06-12 17:02:33 -0700171 time::system_clock::now() + time::days(10),
172 Name("/ndn/zhiyi"));
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +0800173
174 int count = 0;
175 face.onSendData.connect([&] (const Data& response) {
176 count++;
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700177 BOOST_CHECK(security::verifySignature(response, cert));
178 auto contentJson = ClientModule::getJsonFromData(response);
179 BOOST_CHECK(contentJson.get<std::string>(JSON_CA_ECDH) != "");
180 BOOST_CHECK(contentJson.get<std::string>(JSON_CA_SALT) != "");
Zhiyi Zhangff4bcb62019-09-08 12:57:42 -0700181 BOOST_CHECK(contentJson.get<std::string>(JSON_CA_REQUEST_ID) != "");
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700182 auto challengesJson = contentJson.get_child(JSON_CA_CHALLENGES);
183 BOOST_CHECK(challengesJson.size() != 0);
184
185 client.onNewResponse(response);
Zhiyi Zhang8da54d62019-11-21 00:03:05 -0800186 BOOST_CHECK_EQUAL_COLLECTIONS(client.m_aesKey, client.m_aesKey + sizeof(client.m_aesKey),
187 ca.m_aesKey, ca.m_aesKey + sizeof(ca.m_aesKey));
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +0800188 });
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700189 face.receive(*interest);
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +0800190
191 advanceClocks(time::milliseconds(20), 60);
192 BOOST_CHECK_EQUAL(count, 1);
193}
194
Zhiyi Zhang1a735bc2019-07-04 21:36:49 -0700195BOOST_AUTO_TEST_CASE(HandleNewWithInvalidValidityPeriod1)
196{
197 auto identity = addIdentity(Name("/ndn"));
198 auto key = identity.getDefaultKey();
199 auto cert = key.getDefaultCertificate();
200
201 util::DummyClientFace face(io, {true, true});
202 CaModule ca(face, m_keyChain, "tests/unit-tests/ca.conf.test");
203 advanceClocks(time::milliseconds(20), 60);
204
205 ClientModule client(m_keyChain);
206 ClientCaItem item;
207 item.m_caName = Name("/ndn");
208 item.m_anchor = cert;
209 client.getClientConf().m_caItems.push_back(item);
210 auto current_tp = time::system_clock::now();
211 auto interest1 = client.generateNewInterest(current_tp, current_tp - time::hours(1),
212 Name("/ndn/zhiyi"));
213 auto interest2 = client.generateNewInterest(current_tp, current_tp + time::days(361),
214 Name("/ndn/zhiyi"));
215 auto interest3 = client.generateNewInterest(current_tp - time::hours(1),
216 current_tp + time::hours(2),
217 Name("/ndn/zhiyi"));
218 face.onSendData.connect([&] (const Data& response) {
219 BOOST_CHECK(false);
220 });
221 face.receive(*interest1);
222 face.receive(*interest2);
223 face.receive(*interest3);
224
225 advanceClocks(time::milliseconds(20), 60);
226}
227
Zhiyi Zhang5f749a22019-06-12 17:02:33 -0700228BOOST_AUTO_TEST_CASE(HandleNewWithProbeToken)
229{
230 auto identity = addIdentity(Name("/ndn"));
231 auto key = identity.getDefaultKey();
232 auto cert = key.getDefaultCertificate();
233
Zhiyi Zhang42d992d2019-07-07 16:46:50 -0700234 util::DummyClientFace face(io, {true, true});
235 CaModule ca(face, m_keyChain, "tests/unit-tests/ca.conf.test", "ca-storage-memory");
Zhiyi Zhanga1fc6232019-06-13 14:56:59 -0700236 ca.m_config.m_probe = "email";
Zhiyi Zhang5f749a22019-06-12 17:02:33 -0700237 advanceClocks(time::milliseconds(20), 60);
238
239 ClientModule client(m_keyChain);
240 ClientCaItem item;
241 item.m_caName = Name("/ndn");
242 item.m_anchor = cert;
243 client.getClientConf().m_caItems.push_back(item);
244
swa770de007bc2020-03-24 21:26:21 -0700245 auto data = make_shared<Data>(Name("/ndn/CA/PROBE/123"));
Zhiyi Zhang5f749a22019-06-12 17:02:33 -0700246 m_keyChain.sign(*data, signingByIdentity(ca.m_config.m_caName));
247
248 auto interest = client.generateNewInterest(time::system_clock::now(),
249 time::system_clock::now() + time::days(10),
250 Name("/ndn/zhiyi"), data);
251
252 int count = 0;
253 face.onSendData.connect([&] (const Data& response) {
254 count++;
255 BOOST_CHECK(security::verifySignature(response, cert));
256 });
257 face.receive(*interest);
258
259 advanceClocks(time::milliseconds(20), 60);
260 BOOST_CHECK_EQUAL(count, 1);
261}
262
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700263BOOST_AUTO_TEST_CASE(HandleChallenge)
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +0800264{
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700265 auto identity = addIdentity(Name("/ndn"));
266 auto key = identity.getDefaultKey();
267 auto cert = key.getDefaultCertificate();
268
Zhiyi Zhang42d992d2019-07-07 16:46:50 -0700269 util::DummyClientFace face(io, {true, true});
270 CaModule ca(face, m_keyChain, "tests/unit-tests/ca.conf.test", "ca-storage-memory");
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +0800271 advanceClocks(time::milliseconds(20), 60);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700272
273 // generate NEW Interest
274 ClientModule client(m_keyChain);
275 ClientCaItem item;
276 item.m_caName = Name("/ndn");
277 item.m_anchor = cert;
278 client.getClientConf().m_caItems.push_back(item);
279 auto newInterest = client.generateNewInterest(time::system_clock::now(),
280 time::system_clock::now() + time::days(10), Name("/ndn/zhiyi"));
281
282 // generate CHALLENGE Interest
283 ChallengePin pinChallenge;
284 shared_ptr<Interest> challengeInterest = nullptr;
285 shared_ptr<Interest> challengeInterest2 = nullptr;
286 shared_ptr<Interest> challengeInterest3 = nullptr;
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +0800287
288 int count = 0;
289 face.onSendData.connect([&] (const Data& response) {
swa770de007bc2020-03-24 21:26:21 -0700290 if (Name("/ndn/CA/NEW").isPrefixOf(response.getName())) {
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700291 auto contentJson = ClientModule::getJsonFromData(response);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700292 client.onNewResponse(response);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700293 auto paramJson = pinChallenge.getRequirementForChallenge(client.m_status, client.m_challengeStatus);
Suyong Won44d0cce2020-05-10 04:07:43 -0700294 challengeInterest = client.generateChallengeInterest(pinChallenge.genChallengeRequestTLV(client.m_status,
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700295 client.m_challengeStatus,
296 paramJson));
297 }
swa770de007bc2020-03-24 21:26:21 -0700298 else if (Name("/ndn/CA/CHALLENGE").isPrefixOf(response.getName()) && count == 0) {
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +0800299 count++;
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700300 BOOST_CHECK(security::verifySignature(response, cert));
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +0800301
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700302 client.onChallengeResponse(response);
303 BOOST_CHECK_EQUAL(client.m_status, STATUS_CHALLENGE);
304 BOOST_CHECK_EQUAL(client.m_challengeStatus, ChallengePin::NEED_CODE);
Davide Pesavento914d05f2019-07-13 16:20:19 -0400305
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700306 auto paramJson = pinChallenge.getRequirementForChallenge(client.m_status, client.m_challengeStatus);
Suyong Won44d0cce2020-05-10 04:07:43 -0700307 challengeInterest2 = client.generateChallengeInterest(pinChallenge.genChallengeRequestTLV(client.m_status,
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700308 client.m_challengeStatus,
309 paramJson));
310 }
swa770de007bc2020-03-24 21:26:21 -0700311 else if (Name("/ndn/CA/CHALLENGE").isPrefixOf(response.getName()) && count == 1) {
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700312 count++;
313 BOOST_CHECK(security::verifySignature(response, cert));
314
315 client.onChallengeResponse(response);
316 BOOST_CHECK_EQUAL(client.m_status, STATUS_CHALLENGE);
317 BOOST_CHECK_EQUAL(client.m_challengeStatus, ChallengePin::WRONG_CODE);
Davide Pesavento914d05f2019-07-13 16:20:19 -0400318
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700319 auto paramJson = pinChallenge.getRequirementForChallenge(client.m_status, client.m_challengeStatus);
320 auto request = ca.getCertificateRequest(*challengeInterest2);
321 auto secret = request.m_challengeSecrets.get(ChallengePin::JSON_PIN_CODE, "");
Davide Pesavento914d05f2019-07-13 16:20:19 -0400322 for (auto& i : paramJson) {
323 if (i.first == ChallengePin::JSON_PIN_CODE)
324 i.second.put("", secret);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700325 }
Suyong Won44d0cce2020-05-10 04:07:43 -0700326 challengeInterest3 = client.generateChallengeInterest(pinChallenge.genChallengeRequestTLV(client.m_status,
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700327 client.m_challengeStatus,
328 paramJson));
329 }
swa770de007bc2020-03-24 21:26:21 -0700330 else if (Name("/ndn/CA/CHALLENGE").isPrefixOf(response.getName()) && count == 2) {
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700331 count++;
332 BOOST_CHECK(security::verifySignature(response, cert));
333
334 client.onChallengeResponse(response);
335 BOOST_CHECK_EQUAL(client.m_status, STATUS_SUCCESS);
336 BOOST_CHECK_EQUAL(client.m_challengeStatus, CHALLENGE_STATUS_SUCCESS);
337 }
Davide Pesavento914d05f2019-07-13 16:20:19 -0400338 });
339
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700340 face.receive(*newInterest);
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +0800341 advanceClocks(time::milliseconds(20), 60);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700342 face.receive(*challengeInterest);
343 advanceClocks(time::milliseconds(20), 60);
344 face.receive(*challengeInterest2);
345 advanceClocks(time::milliseconds(20), 60);
346 face.receive(*challengeInterest3);
347 advanceClocks(time::milliseconds(20), 60);
348 BOOST_CHECK_EQUAL(count, 3);
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +0800349}
350
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800351BOOST_AUTO_TEST_SUITE_END() // TestCaModule
352
353} // namespace tests
354} // namespace ndncert
355} // namespace ndn