blob: 4374a86ef0e0685fd38eb200658f51a765489b50 [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 Zhangdbd9d432020-10-07 15:56:27 -070022#include "identity-challenge/challenge-module.hpp"
23#include "identity-challenge/challenge-email.hpp"
24#include "identity-challenge/challenge-pin.hpp"
Suyong Won7968f7a2020-05-12 01:01:25 -070025#include "protocol-detail/info.hpp"
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -070026#include "requester.hpp"
Zhiyi Zhang5d80e1e2020-09-25 11:34:54 -070027#include "test-common.hpp"
Zhiyi Zhangf5246c42017-01-26 09:39:20 -080028
29namespace ndn {
30namespace ndncert {
31namespace tests {
32
Zhiyi Zhangae123bf2017-04-14 12:24:53 -070033BOOST_FIXTURE_TEST_SUITE(TestCaModule, DatabaseFixture)
Zhiyi Zhangf5246c42017-01-26 09:39:20 -080034
35BOOST_AUTO_TEST_CASE(Initialization)
36{
Zhiyi Zhang22998612020-09-25 14:43:23 -070037 util::DummyClientFace face(io, m_keyChain, {true, true});
Zhiyi Zhang9829da92020-09-30 16:19:34 -070038 CaModule ca(face, m_keyChain, "tests/unit-tests/config-files/config-ca-1", "ca-storage-memory");
39 BOOST_CHECK_EQUAL(ca.getCaConf().m_caItem.m_caPrefix, "/ndn");
Zhiyi Zhangf5246c42017-01-26 09:39:20 -080040
Zhiyi Zhangf5246c42017-01-26 09:39:20 -080041 advanceClocks(time::milliseconds(20), 60);
Zhiyi Zhangfbcab842020-10-07 15:17:13 -070042 BOOST_CHECK_EQUAL(ca.m_registeredPrefixHandles.size(), 1); // removed local discovery registration
43 BOOST_CHECK_EQUAL(ca.m_interestFilterHandles.size(), 4); // onProbe, onNew, onChallenge, onRevoke
Zhiyi Zhangf5246c42017-01-26 09:39:20 -080044}
45
Zhiyi Zhangfbcab842020-10-07 15:17:13 -070046BOOST_AUTO_TEST_CASE(HandleProfileFetching)
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070047{
48 auto identity = addIdentity(Name("/ndn"));
49 auto key = identity.getDefaultKey();
50 auto cert = key.getDefaultCertificate();
51
Zhiyi Zhang22998612020-09-25 14:43:23 -070052 util::DummyClientFace face(io, m_keyChain, {true, true});
Zhiyi Zhang9829da92020-09-30 16:19:34 -070053 CaModule ca(face, m_keyChain, "tests/unit-tests/config-files/config-ca-1", "ca-storage-memory");
Zhiyi Zhangf61404d2020-10-07 15:41:07 -070054 auto metaData = ca.generateCaProfileMetaData();
55 auto profileData = ca.generateCaProfileData();
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070056 advanceClocks(time::milliseconds(20), 60);
57
Zhiyi Zhangfbcab842020-10-07 15:17:13 -070058 Interest interest = MetadataObject::makeDiscoveryInterest(Name("/ndn/CA/INFO"));
59 shared_ptr<Interest> infoInterest = nullptr;
60
61 face.setInterestFilter(InterestFilter("/ndn/CA/INFO"),
62 [&](const auto&, const Interest& interest) {
63 if (interest.matchesData(*metaData)) {
64 face.put(*metaData);
65 }
66 else {
67 BOOST_CHECK(interest.matchesData(*profileData));
68 face.put(*profileData);
69 }
70 }, nullptr, nullptr);
71 advanceClocks(time::milliseconds(20), 60);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070072
73 int count = 0;
Zhiyi Zhangfc1678a2020-05-12 16:52:14 -070074 face.onSendData.connect([&](const Data& response) {
Zhiyi Zhangfbcab842020-10-07 15:17:13 -070075 if (count == 0) {
76 count++;
77 auto block = response.getContent();
78 block.parse();
79 Interest interest(Name(block.get(tlv::Name)));
80 interest.setCanBePrefix(true);
81 infoInterest = make_shared<Interest>(interest);
82 }
83 else {
84 count++;
85 BOOST_CHECK(security::verifySignature(response, cert));
86 auto contentBlock = response.getContent();
87 contentBlock.parse();
88 auto caItem = INFO::decodeDataContent(contentBlock);
89 BOOST_CHECK_EQUAL(caItem.m_caPrefix, "/ndn");
90 BOOST_CHECK_EQUAL(caItem.m_probeParameterKeys.size(), 1);
91 BOOST_CHECK_EQUAL(caItem.m_probeParameterKeys.front(), "full name");
92 BOOST_CHECK_EQUAL(caItem.m_cert->wireEncode(), cert.wireEncode());
93 BOOST_CHECK_EQUAL(caItem.m_caInfo, "ndn testbed ca");
94 }
Zhiyi Zhangfc1678a2020-05-12 16:52:14 -070095 });
Zhiyi Zhangf5246c42017-01-26 09:39:20 -080096 face.receive(interest);
Zhiyi Zhangf5246c42017-01-26 09:39:20 -080097 advanceClocks(time::milliseconds(20), 60);
Zhiyi Zhangfbcab842020-10-07 15:17:13 -070098 face.receive(*infoInterest);
99 advanceClocks(time::milliseconds(20), 60);
100 BOOST_CHECK_EQUAL(count, 2);
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800101}
102
Zhiyi Zhang6f395812020-09-29 14:42:03 -0700103BOOST_AUTO_TEST_CASE(HandleProbe)
104{
105 auto identity = addIdentity(Name("/ndn"));
106 auto key = identity.getDefaultKey();
107 auto cert = key.getDefaultCertificate();
108
109 util::DummyClientFace face(io, m_keyChain, {true, true});
Zhiyi Zhang9829da92020-09-30 16:19:34 -0700110 CaModule ca(face, m_keyChain, "tests/unit-tests/config-files/config-ca-1", "ca-storage-memory");
tylerliu8fc08072020-10-06 15:37:40 -0700111 ca.setNameAssignmentFunction([&](const std::vector<std::tuple<std::string, std::string>>) -> std::vector<PartialName> {
112 std::vector<PartialName> result;
113 result.push_back(Name("/example"));
Zhiyi Zhang6f395812020-09-29 14:42:03 -0700114 return result;
115 });
116 advanceClocks(time::milliseconds(20), 60);
117
118 Interest interest("/ndn/CA/PROBE");
119 interest.setCanBePrefix(false);
120
121 Block paramTLV = makeEmptyBlock(tlv::ApplicationParameters);
122 paramTLV.push_back(makeStringBlock(tlv_parameter_key, "name"));
123 paramTLV.push_back(makeStringBlock(tlv_parameter_value, "zhiyi"));
124 paramTLV.encode();
125
126 interest.setApplicationParameters(paramTLV);
127
128 int count = 0;
129 face.onSendData.connect([&](const Data& response) {
130 count++;
131 BOOST_CHECK(security::verifySignature(response, cert));
132 Block contentBlock = response.getContent();
133 contentBlock.parse();
134 Block probeResponse = contentBlock.get(tlv_probe_response);
135 probeResponse.parse();
136 Name caName;
137 caName.wireDecode(probeResponse.get(tlv::Name));
Zhiyi Zhang8683ec92020-10-07 18:18:35 -0700138 BOOST_CHECK_EQUAL(caName.size(), 2);
Zhiyi Zhang6f395812020-09-29 14:42:03 -0700139 });
140 face.receive(interest);
141
142 advanceClocks(time::milliseconds(20), 60);
143 BOOST_CHECK_EQUAL(count, 1);
144}
145
Zhiyi Zhanga63b7372017-05-17 14:14:34 -0700146BOOST_AUTO_TEST_CASE(HandleProbeUsingDefaultHandler)
147{
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700148 auto identity = addIdentity(Name("/ndn"));
Zhiyi Zhanga63b7372017-05-17 14:14:34 -0700149 auto key = identity.getDefaultKey();
150 auto cert = key.getDefaultCertificate();
151
Zhiyi Zhang22998612020-09-25 14:43:23 -0700152 util::DummyClientFace face(io, m_keyChain, {true, true});
Zhiyi Zhang9829da92020-09-30 16:19:34 -0700153 CaModule ca(face, m_keyChain, "tests/unit-tests/config-files/config-ca-1", "ca-storage-memory");
Zhiyi Zhanga63b7372017-05-17 14:14:34 -0700154 advanceClocks(time::milliseconds(20), 60);
155
swa770de007bc2020-03-24 21:26:21 -0700156 Interest interest("/ndn/CA/PROBE");
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700157 interest.setCanBePrefix(false);
Suyong Won7968f7a2020-05-12 01:01:25 -0700158
159 Block paramTLV = makeEmptyBlock(tlv::ApplicationParameters);
Zhiyi Zhang6f395812020-09-29 14:42:03 -0700160 paramTLV.push_back(makeStringBlock(tlv_parameter_key, "name"));
Suyong Won7968f7a2020-05-12 01:01:25 -0700161 paramTLV.push_back(makeStringBlock(tlv_parameter_value, "zhiyi"));
162 paramTLV.encode();
163
164 interest.setApplicationParameters(paramTLV);
Zhiyi Zhanga63b7372017-05-17 14:14:34 -0700165
166 int count = 0;
Zhiyi Zhangfc1678a2020-05-12 16:52:14 -0700167 face.onSendData.connect([&](const Data& response) {
168 count++;
169 BOOST_CHECK(security::verifySignature(response, cert));
170 auto contentBlock = response.getContent();
171 contentBlock.parse();
172 auto probeResponseBlock = contentBlock.get(tlv_probe_response);
173 probeResponseBlock.parse();
174 Name caPrefix;
175 caPrefix.wireDecode(probeResponseBlock.get(tlv::Name));
176 BOOST_CHECK(caPrefix != "");
177 });
Zhiyi Zhanga63b7372017-05-17 14:14:34 -0700178 face.receive(interest);
179
180 advanceClocks(time::milliseconds(20), 60);
181 BOOST_CHECK_EQUAL(count, 1);
182}
183
Suyong Wone2afeb52020-10-04 03:05:39 +0900184BOOST_AUTO_TEST_CASE(HandleProbeRedirection)
185{
186 auto identity = addIdentity(Name("/ndn"));
187 auto key = identity.getDefaultKey();
188 auto cert = key.getDefaultCertificate();
189
190 util::DummyClientFace face(io, m_keyChain, {true, true});
191 CaModule ca(face, m_keyChain, "tests/unit-tests/config-files/config-ca-5", "ca-storage-memory");
tylerliu8fc08072020-10-06 15:37:40 -0700192 ca.setNameAssignmentFunction([&](const std::vector<std::tuple<std::string, std::string>>) -> std::vector<PartialName> {
193 std::vector<PartialName> result;
194 result.push_back(Name("/example"));
Suyong Wone2afeb52020-10-04 03:05:39 +0900195 return result;
196 });
197 advanceClocks(time::milliseconds(20), 60);
198
199 Interest interest("/ndn/CA/PROBE");
200 interest.setCanBePrefix(false);
201
202 Block paramTLV = makeEmptyBlock(tlv::ApplicationParameters);
203 paramTLV.push_back(makeStringBlock(tlv_parameter_key, "name"));
204 paramTLV.push_back(makeStringBlock(tlv_parameter_value, "zhiyi"));
205 paramTLV.encode();
206
207 interest.setApplicationParameters(paramTLV);
208
209 int count = 0;
210 face.onSendData.connect([&](const Data& response) {
211 count++;
212 BOOST_CHECK(security::verifySignature(response, cert));
213 Block contentBlock = response.getContent();
214 contentBlock.parse();
215
216 // Test CA sent redirections
Zhiyi Zhang34a8d432020-10-03 22:14:25 -0700217 std::vector<Name> redirectionItems;
218 for (auto item : contentBlock.elements()) {
219 if (item.type() == tlv_probe_redirect) {
220 redirectionItems.push_back(Name(item.blockFromValue()));
221 }
Suyong Wone2afeb52020-10-04 03:05:39 +0900222 }
Zhiyi Zhang34a8d432020-10-03 22:14:25 -0700223 BOOST_CHECK_EQUAL(redirectionItems.size(), 2);
224 BOOST_CHECK_EQUAL(security::v2::extractIdentityFromCertName(redirectionItems[0].getPrefix(-1)), "/ndn/site1");
225 BOOST_CHECK_EQUAL(security::v2::extractIdentityFromCertName(redirectionItems[1].getPrefix(-1)), "/ndn/site1");
Suyong Wone2afeb52020-10-04 03:05:39 +0900226 });
227 face.receive(interest);
228 advanceClocks(time::milliseconds(20), 60);
229 BOOST_CHECK_EQUAL(count, 1);
230}
231
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800232BOOST_AUTO_TEST_CASE(HandleNew)
233{
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700234 auto identity = addIdentity(Name("/ndn"));
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800235 auto key = identity.getDefaultKey();
236 auto cert = key.getDefaultCertificate();
237
Zhiyi Zhang22998612020-09-25 14:43:23 -0700238 util::DummyClientFace face(io, m_keyChain, {true, true});
Zhiyi Zhang9829da92020-09-30 16:19:34 -0700239 CaModule ca(face, m_keyChain, "tests/unit-tests/config-files/config-ca-1", "ca-storage-memory");
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800240 advanceClocks(time::milliseconds(20), 60);
241
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700242 CaProfile item;
Suyong Won256c9062020-05-11 02:45:56 -0700243 item.m_caPrefix = Name("/ndn");
Zhiyi Zhang9829da92020-09-30 16:19:34 -0700244 item.m_cert = std::make_shared<security::v2::Certificate>(cert);
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700245 RequesterState state(m_keyChain, item, RequestType::NEW);
246 auto interest = Requester::genNewInterest(state, Name("/ndn/zhiyi"),
247 time::system_clock::now(),
248 time::system_clock::now() + time::days(1));
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +0800249
250 int count = 0;
Zhiyi Zhangfc1678a2020-05-12 16:52:14 -0700251 face.onSendData.connect([&](const Data& response) {
252 count++;
253 BOOST_CHECK(security::verifySignature(response, cert));
254 auto contentBlock = response.getContent();
255 contentBlock.parse();
Suyong Won7968f7a2020-05-12 01:01:25 -0700256
Zhiyi Zhangfc1678a2020-05-12 16:52:14 -0700257 BOOST_CHECK(readString(contentBlock.get(tlv_ecdh_pub)) != "");
258 BOOST_CHECK(readString(contentBlock.get(tlv_salt)) != "");
259 BOOST_CHECK(readString(contentBlock.get(tlv_request_id)) != "");
Suyong Won7968f7a2020-05-12 01:01:25 -0700260
Zhiyi Zhangfc1678a2020-05-12 16:52:14 -0700261 auto challengeBlockCount = 0;
262 for (auto const& element : contentBlock.elements()) {
263 if (element.type() == tlv_challenge) {
264 challengeBlockCount++;
Suyong Won7968f7a2020-05-12 01:01:25 -0700265 }
Zhiyi Zhangfc1678a2020-05-12 16:52:14 -0700266 }
Suyong Won7968f7a2020-05-12 01:01:25 -0700267
Zhiyi Zhangfc1678a2020-05-12 16:52:14 -0700268 BOOST_CHECK(challengeBlockCount != 0);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700269
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700270 auto challengeList = Requester::onNewRenewRevokeResponse(state, response);
tylerliu8e170d62020-09-30 01:31:53 -0700271 auto ca_encryption_key = ca.getCaStorage()->getRequest(readString(contentBlock.get(tlv_request_id))).m_encryptionKey;
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700272 BOOST_CHECK_EQUAL_COLLECTIONS(state.m_aesKey, state.m_aesKey + sizeof(state.m_aesKey),
tylerliu8e170d62020-09-30 01:31:53 -0700273 ca_encryption_key.value(), ca_encryption_key.value() + ca_encryption_key.value_size());
Zhiyi Zhangfc1678a2020-05-12 16:52:14 -0700274 });
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700275 face.receive(*interest);
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +0800276
277 advanceClocks(time::milliseconds(20), 60);
278 BOOST_CHECK_EQUAL(count, 1);
279}
280
Zhiyi Zhang1a735bc2019-07-04 21:36:49 -0700281BOOST_AUTO_TEST_CASE(HandleNewWithInvalidValidityPeriod1)
282{
283 auto identity = addIdentity(Name("/ndn"));
284 auto key = identity.getDefaultKey();
285 auto cert = key.getDefaultCertificate();
286
Zhiyi Zhang22998612020-09-25 14:43:23 -0700287 util::DummyClientFace face(io, m_keyChain, {true, true});
Zhiyi Zhang9829da92020-09-30 16:19:34 -0700288 CaModule ca(face, m_keyChain, "tests/unit-tests/config-files/config-ca-1");
Zhiyi Zhang1a735bc2019-07-04 21:36:49 -0700289 advanceClocks(time::milliseconds(20), 60);
290
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700291 CaProfile item;
Suyong Won256c9062020-05-11 02:45:56 -0700292 item.m_caPrefix = Name("/ndn");
Zhiyi Zhang9829da92020-09-30 16:19:34 -0700293 item.m_cert = std::make_shared<security::v2::Certificate>(cert);
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700294 RequesterState state(m_keyChain, item, RequestType::NEW);
Zhiyi Zhang1a735bc2019-07-04 21:36:49 -0700295 auto current_tp = time::system_clock::now();
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700296 auto interest1 = Requester::genNewInterest(state, Name("/ndn/zhiyi"), current_tp, current_tp - time::hours(1));
297 auto interest2 = Requester::genNewInterest(state, Name("/ndn/zhiyi"), current_tp, current_tp + time::days(361));
298 auto interest3 = Requester::genNewInterest(state, Name("/ndn/zhiyi"), current_tp - time::hours(1), current_tp + time::hours(2));
Zhiyi Zhangfc1678a2020-05-12 16:52:14 -0700299 face.onSendData.connect([&](const Data& response) {
Zhiyi Zhang01e91a32020-09-29 12:10:00 -0700300 auto contentTlv = response.getContent();
301 contentTlv.parse();
302 auto errorCode = static_cast<ErrorCode>(readNonNegativeInteger(contentTlv.get(tlv_error_code)));
303 BOOST_CHECK(errorCode != ErrorCode::NO_ERROR);
Zhiyi Zhangfc1678a2020-05-12 16:52:14 -0700304 });
Zhiyi Zhang1a735bc2019-07-04 21:36:49 -0700305 face.receive(*interest1);
306 face.receive(*interest2);
307 face.receive(*interest3);
308
309 advanceClocks(time::milliseconds(20), 60);
310}
311
tylerliu0b6d0db2020-09-28 17:52:02 -0700312BOOST_AUTO_TEST_CASE(HandleNewWithLongSuffix)
313{
314 auto identity = addIdentity(Name("/ndn"));
315 auto key = identity.getDefaultKey();
316 auto cert = key.getDefaultCertificate();
317
Zhiyi Zhang01e91a32020-09-29 12:10:00 -0700318 util::DummyClientFace face(io, m_keyChain, {true, true});
Zhiyi Zhang9829da92020-09-30 16:19:34 -0700319 CaModule ca(face, m_keyChain, "tests/unit-tests/config-files/config-ca-1", "ca-storage-memory");
tylerliu0b6d0db2020-09-28 17:52:02 -0700320 advanceClocks(time::milliseconds(20), 60);
321
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700322 CaProfile item;
tylerliu0b6d0db2020-09-28 17:52:02 -0700323 item.m_caPrefix = Name("/ndn");
Zhiyi Zhang9829da92020-09-30 16:19:34 -0700324 item.m_cert = std::make_shared<security::v2::Certificate>(cert);
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700325 RequesterState state(m_keyChain, item, RequestType::NEW);
tylerliu0b6d0db2020-09-28 17:52:02 -0700326
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700327 auto interest1 = Requester::genNewInterest(state, Name("/ndn/a"), time::system_clock::now(),
328 time::system_clock::now() + time::days(1));
329 auto interest2 = Requester::genNewInterest(state, Name("/ndn/a/b"), time::system_clock::now(),
330 time::system_clock::now() + time::days(1));
331 auto interest3 = Requester::genNewInterest(state, Name("/ndn/a/b/c/d"), time::system_clock::now(),
332 time::system_clock::now() + time::days(1));
tylerliu0b6d0db2020-09-28 17:52:02 -0700333
tylerliu0b6d0db2020-09-28 17:52:02 -0700334 face.onSendData.connect([&](const Data& response) {
Zhiyi Zhang01e91a32020-09-29 12:10:00 -0700335 auto contentTlv = response.getContent();
336 contentTlv.parse();
337 if (interest3->getName().isPrefixOf(response.getName())) {
338 auto errorCode = static_cast<ErrorCode>(readNonNegativeInteger(contentTlv.get(tlv_error_code)));
339 BOOST_CHECK(errorCode != ErrorCode::NO_ERROR);
340 }
341 else {
342 // should successfully get responses
343 BOOST_CHECK_EXCEPTION(readNonNegativeInteger(contentTlv.get(tlv_error_code)), std::runtime_error,
344 [](const auto& e) { return true; });
345 }
tylerliu0b6d0db2020-09-28 17:52:02 -0700346 });
Zhiyi Zhang01e91a32020-09-29 12:10:00 -0700347 face.receive(*interest1);
348 face.receive(*interest2);
349 face.receive(*interest3);
tylerliu0b6d0db2020-09-28 17:52:02 -0700350 advanceClocks(time::milliseconds(20), 60);
tylerliu0b6d0db2020-09-28 17:52:02 -0700351}
352
tylerliu0b6d0db2020-09-28 17:52:02 -0700353BOOST_AUTO_TEST_CASE(HandleNewWithInvalidLength1)
354{
355 auto identity = addIdentity(Name("/ndn"));
356 auto key = identity.getDefaultKey();
357 auto cert = key.getDefaultCertificate();
358
359 util::DummyClientFace face(io, m_keyChain, {true, true});
Zhiyi Zhang9829da92020-09-30 16:19:34 -0700360 CaModule ca(face, m_keyChain, "tests/unit-tests/config-files/config-ca-1");
tylerliu0b6d0db2020-09-28 17:52:02 -0700361 advanceClocks(time::milliseconds(20), 60);
362
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700363 CaProfile item;
tylerliu0b6d0db2020-09-28 17:52:02 -0700364 item.m_caPrefix = Name("/ndn");
Zhiyi Zhang9829da92020-09-30 16:19:34 -0700365 item.m_cert = std::make_shared<security::v2::Certificate>(cert);
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700366 RequesterState state(m_keyChain, item, RequestType::NEW);
367
tylerliu0b6d0db2020-09-28 17:52:02 -0700368 auto current_tp = time::system_clock::now();
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700369 auto interest1 = Requester::genNewInterest(state, Name("/ndn"), current_tp, current_tp + time::days(1));
370 auto interest2 = Requester::genNewInterest(state, Name("/ndn/a/b/c/d"), current_tp, current_tp + time::days(1));
tylerliu0b6d0db2020-09-28 17:52:02 -0700371 face.onSendData.connect([&](const Data& response) {
Zhiyi Zhang01e91a32020-09-29 12:10:00 -0700372 auto contentTlv = response.getContent();
373 contentTlv.parse();
374 auto errorCode = static_cast<ErrorCode>(readNonNegativeInteger(contentTlv.get(tlv_error_code)));
375 BOOST_CHECK(errorCode != ErrorCode::NO_ERROR);
tylerliu0b6d0db2020-09-28 17:52:02 -0700376 });
377 face.receive(*interest1);
378 face.receive(*interest2);
379
380 advanceClocks(time::milliseconds(20), 60);
381}
382
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700383BOOST_AUTO_TEST_CASE(HandleChallenge)
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +0800384{
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700385 auto identity = addIdentity(Name("/ndn"));
386 auto key = identity.getDefaultKey();
387 auto cert = key.getDefaultCertificate();
388
Zhiyi Zhang22998612020-09-25 14:43:23 -0700389 util::DummyClientFace face(io, m_keyChain, {true, true});
Zhiyi Zhang9829da92020-09-30 16:19:34 -0700390 CaModule ca(face, m_keyChain, "tests/unit-tests/config-files/config-ca-1", "ca-storage-memory");
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +0800391 advanceClocks(time::milliseconds(20), 60);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700392
393 // generate NEW Interest
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700394 CaProfile item;
Suyong Won256c9062020-05-11 02:45:56 -0700395 item.m_caPrefix = Name("/ndn");
Zhiyi Zhang9829da92020-09-30 16:19:34 -0700396 item.m_cert = std::make_shared<security::v2::Certificate>(cert);
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700397 RequesterState state(m_keyChain, item, RequestType::NEW);
398
399 auto newInterest = Requester::genNewInterest(state, Name("/ndn/zhiyi"), time::system_clock::now(),
400 time::system_clock::now() + time::days(1));
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700401
402 // generate CHALLENGE Interest
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700403 shared_ptr<Interest> challengeInterest = nullptr;
404 shared_ptr<Interest> challengeInterest2 = nullptr;
405 shared_ptr<Interest> challengeInterest3 = nullptr;
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +0800406
407 int count = 0;
Zhiyi Zhangfc1678a2020-05-12 16:52:14 -0700408 face.onSendData.connect([&](const Data& response) {
swa770de007bc2020-03-24 21:26:21 -0700409 if (Name("/ndn/CA/NEW").isPrefixOf(response.getName())) {
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700410 auto challengeList = Requester::onNewRenewRevokeResponse(state, response);
411 auto paramList = Requester::selectOrContinueChallenge(state, "pin");
412 challengeInterest = Requester::genChallengeInterest(state, std::move(paramList));
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700413 }
swa770de007bc2020-03-24 21:26:21 -0700414 else if (Name("/ndn/CA/CHALLENGE").isPrefixOf(response.getName()) && count == 0) {
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +0800415 count++;
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700416 BOOST_CHECK(security::verifySignature(response, cert));
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +0800417
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700418 Requester::onChallengeResponse(state, response);
419 BOOST_CHECK(state.m_status == Status::CHALLENGE);
420 BOOST_CHECK_EQUAL(state.m_challengeStatus, ChallengePin::NEED_CODE);
421 auto paramList = Requester::selectOrContinueChallenge(state, "pin");
422 challengeInterest2 = Requester::genChallengeInterest(state, std::move(paramList));
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700423 }
swa770de007bc2020-03-24 21:26:21 -0700424 else if (Name("/ndn/CA/CHALLENGE").isPrefixOf(response.getName()) && count == 1) {
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700425 count++;
426 BOOST_CHECK(security::verifySignature(response, cert));
427
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700428 Requester::onChallengeResponse(state, response);
429 BOOST_CHECK(state.m_status == Status::CHALLENGE);
430 BOOST_CHECK_EQUAL(state.m_challengeStatus, ChallengePin::WRONG_CODE);
Davide Pesavento914d05f2019-07-13 16:20:19 -0400431
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700432 auto paramList = Requester::selectOrContinueChallenge(state, "pin");
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700433 auto request = ca.getCertificateRequest(*challengeInterest2);
Zhiyi Zhanga749f442020-09-29 17:19:51 -0700434 auto secret = request.m_challengeState->m_secrets.get(ChallengePin::PARAMETER_KEY_CODE, "");
Zhiyi Zhang46049832020-09-28 17:08:12 -0700435 std::get<1>(paramList[0]) = secret;
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700436 challengeInterest3 = Requester::genChallengeInterest(state, std::move(paramList));
437 std::cout << "CHALLENGE Interest Size: " << challengeInterest3->wireEncode().size() << std::endl;
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700438 }
swa770de007bc2020-03-24 21:26:21 -0700439 else if (Name("/ndn/CA/CHALLENGE").isPrefixOf(response.getName()) && count == 2) {
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700440 count++;
441 BOOST_CHECK(security::verifySignature(response, cert));
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700442 Requester::onChallengeResponse(state, response);
443 BOOST_CHECK(state.m_status == Status::SUCCESS);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700444 }
Davide Pesavento914d05f2019-07-13 16:20:19 -0400445 });
446
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700447 face.receive(*newInterest);
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +0800448 advanceClocks(time::milliseconds(20), 60);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700449 face.receive(*challengeInterest);
450 advanceClocks(time::milliseconds(20), 60);
451 face.receive(*challengeInterest2);
452 advanceClocks(time::milliseconds(20), 60);
453 face.receive(*challengeInterest3);
454 advanceClocks(time::milliseconds(20), 60);
455 BOOST_CHECK_EQUAL(count, 3);
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +0800456}
457
tylerliu182bc532020-09-25 01:54:45 -0700458BOOST_AUTO_TEST_CASE(HandleRevoke)
459{
460 auto identity = addIdentity(Name("/ndn"));
461 auto key = identity.getDefaultKey();
462 auto cert = key.getDefaultCertificate();
463
Zhiyi Zhang46049832020-09-28 17:08:12 -0700464 util::DummyClientFace face(io, {true, true});
Zhiyi Zhang9829da92020-09-30 16:19:34 -0700465 CaModule ca(face, m_keyChain, "tests/unit-tests/config-files/config-ca-1", "ca-storage-memory");
tylerliu182bc532020-09-25 01:54:45 -0700466 advanceClocks(time::milliseconds(20), 60);
467
468 //generate a certificate
469 auto clientIdentity = m_keyChain.createIdentity("/ndn/qwerty");
470 auto clientKey = clientIdentity.getDefaultKey();
471 security::v2::Certificate clientCert;
472 clientCert.setName(Name(clientKey.getName()).append("cert-request").appendVersion());
473 clientCert.setContentType(tlv::ContentType_Key);
474 clientCert.setFreshnessPeriod(time::hours(24));
475 clientCert.setContent(clientKey.getPublicKey().data(), clientKey.getPublicKey().size());
476 SignatureInfo signatureInfo;
477 signatureInfo.setValidityPeriod(security::ValidityPeriod(time::system_clock::now(),
Zhiyi Zhang46049832020-09-28 17:08:12 -0700478 time::system_clock::now() + time::hours(10)));
tylerliu182bc532020-09-25 01:54:45 -0700479 m_keyChain.sign(clientCert, signingByKey(clientKey.getName()).setSignatureInfo(signatureInfo));
tylerliu8704d032020-06-23 10:18:15 -0700480 CaState certRequest(Name("/ndn"), "122", RequestType::NEW, Status::SUCCESS, clientCert, makeEmptyBlock(tlv::ContentType_Key));
tylerliu182bc532020-09-25 01:54:45 -0700481 auto issuedCert = ca.issueCertificate(certRequest);
482
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700483 CaProfile item;
Zhiyi Zhang9829da92020-09-30 16:19:34 -0700484 item.m_caPrefix = Name("/ndn");
485 item.m_cert = std::make_shared<security::v2::Certificate>(cert);
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700486 RequesterState state(m_keyChain, item, RequestType::REVOKE);
tylerliu182bc532020-09-25 01:54:45 -0700487
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700488 auto interest = Requester::genRevokeInterest(state, issuedCert);
tylerliu182bc532020-09-25 01:54:45 -0700489
490 int count = 0;
Zhiyi Zhang46049832020-09-28 17:08:12 -0700491 face.onSendData.connect([&](const Data& response) {
tylerliu182bc532020-09-25 01:54:45 -0700492 count++;
493 BOOST_CHECK(security::verifySignature(response, cert));
494 auto contentBlock = response.getContent();
495 contentBlock.parse();
496
497 BOOST_CHECK(readString(contentBlock.get(tlv_ecdh_pub)) != "");
498 BOOST_CHECK(readString(contentBlock.get(tlv_salt)) != "");
499 BOOST_CHECK(readString(contentBlock.get(tlv_request_id)) != "");
500
501 auto challengeBlockCount = 0;
502 for (auto const& element : contentBlock.elements()) {
Zhiyi Zhang46049832020-09-28 17:08:12 -0700503 if (element.type() == tlv_challenge) {
504 challengeBlockCount++;
505 }
tylerliu182bc532020-09-25 01:54:45 -0700506 }
507
508 BOOST_CHECK(challengeBlockCount != 0);
509
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700510 auto challengeList = Requester::onNewRenewRevokeResponse(state, response);
tylerliu8e170d62020-09-30 01:31:53 -0700511 auto ca_encryption_key = ca.getCaStorage()->getRequest(readString(contentBlock.get(tlv_request_id))).m_encryptionKey;
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700512 BOOST_CHECK_EQUAL_COLLECTIONS(state.m_aesKey, state.m_aesKey + sizeof(state.m_aesKey),
tylerliu8e170d62020-09-30 01:31:53 -0700513 ca_encryption_key.value(), ca_encryption_key.value() + ca_encryption_key.value_size());
tylerliu182bc532020-09-25 01:54:45 -0700514 });
515 face.receive(*interest);
516
517 advanceClocks(time::milliseconds(20), 60);
518 BOOST_CHECK_EQUAL(count, 1);
519}
520
521BOOST_AUTO_TEST_CASE(HandleRevokeWithBadCert)
522{
523 auto identity = addIdentity(Name("/ndn"));
524 auto key = identity.getDefaultKey();
525 auto cert = key.getDefaultCertificate();
526
Zhiyi Zhang46049832020-09-28 17:08:12 -0700527 util::DummyClientFace face(io, {true, true});
Zhiyi Zhang9829da92020-09-30 16:19:34 -0700528 CaModule ca(face, m_keyChain, "tests/unit-tests/config-files/config-ca-1", "ca-storage-memory");
tylerliu182bc532020-09-25 01:54:45 -0700529 advanceClocks(time::milliseconds(20), 60);
530
Zhiyi Zhang3e8ca252020-09-30 17:18:38 -0700531 // generate a certificate
tylerliu182bc532020-09-25 01:54:45 -0700532 auto clientIdentity = m_keyChain.createIdentity("/ndn/qwerty");
533 auto clientKey = clientIdentity.getDefaultKey();
534 security::v2::Certificate clientCert;
535 clientCert.setName(Name(clientKey.getName()).append("NDNCERT").append(std::to_string(1473283247810732701)));
536 clientCert.setContentType(tlv::ContentType_Key);
537 clientCert.setFreshnessPeriod(time::hours(24));
538 clientCert.setContent(clientKey.getPublicKey().data(), clientKey.getPublicKey().size());
539 SignatureInfo signatureInfo;
540 signatureInfo.setValidityPeriod(security::ValidityPeriod(time::system_clock::now(),
Zhiyi Zhang46049832020-09-28 17:08:12 -0700541 time::system_clock::now() + time::hours(10)));
tylerliu182bc532020-09-25 01:54:45 -0700542 m_keyChain.sign(clientCert, signingByKey(clientKey.getName()).setSignatureInfo(signatureInfo));
543
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700544 CaProfile item;
Zhiyi Zhang9829da92020-09-30 16:19:34 -0700545 item.m_caPrefix = Name("/ndn");
546 item.m_cert = std::make_shared<security::v2::Certificate>(cert);
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700547 RequesterState state(m_keyChain, item, RequestType::NEW);
tylerliu182bc532020-09-25 01:54:45 -0700548
Zhiyi Zhang1d3dcd22020-10-01 22:25:43 -0700549 auto interest = Requester::genRevokeInterest(state, clientCert);
tylerliu182bc532020-09-25 01:54:45 -0700550
Zhiyi Zhang3e8ca252020-09-30 17:18:38 -0700551 bool receiveData = false;
Zhiyi Zhang46049832020-09-28 17:08:12 -0700552 face.onSendData.connect([&](const Data& response) {
Zhiyi Zhang3e8ca252020-09-30 17:18:38 -0700553 receiveData = true;
554 auto contentTlv = response.getContent();
555 contentTlv.parse();
556 BOOST_CHECK(static_cast<ErrorCode>(readNonNegativeInteger(contentTlv.get(tlv_error_code))) != ErrorCode::NO_ERROR);
tylerliu182bc532020-09-25 01:54:45 -0700557 });
558 face.receive(*interest);
559
560 advanceClocks(time::milliseconds(20), 60);
Zhiyi Zhang3e8ca252020-09-30 17:18:38 -0700561 BOOST_CHECK_EQUAL(receiveData, true);
tylerliu182bc532020-09-25 01:54:45 -0700562}
563
Zhiyi Zhang46049832020-09-28 17:08:12 -0700564BOOST_AUTO_TEST_SUITE_END() // TestCaModule
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800565
Zhiyi Zhangfc1678a2020-05-12 16:52:14 -0700566} // namespace tests
567} // namespace ndncert
568} // namespace ndn