blob: 147c663ecf9ffe593fe0481339c944d60db2e14f [file] [log] [blame]
Alexander Afanasyev1a21e102018-06-13 20:33:21 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Davide Pesavento9062a502020-01-04 17:14:04 -05002/*
3 * Copyright (c) 2014-2020, Regents of the University of California
Alexander Afanasyev1a21e102018-06-13 20:33:21 -04004 *
5 * NAC library is free software: you can redistribute it and/or modify it under the
6 * terms of the GNU Lesser General Public License as published by the Free Software
7 * Foundation, either version 3 of the License, or (at your option) any later version.
8 *
9 * NAC library is distributed in the hope that it will be useful, but WITHOUT ANY
10 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
11 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
12 *
13 * You should have received copies of the GNU General Public License and GNU Lesser
14 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
15 * <http://www.gnu.org/licenses/>.
16 *
17 * See AUTHORS.md for complete list of NAC library authors and contributors.
18 */
19
20#include "encryptor.hpp"
21
Davide Pesaventoba3f6892020-12-08 22:18:35 -050022#include "tests/boost-test.hpp"
23#include "tests/dummy-forwarder.hpp"
24#include "tests/io-key-chain-fixture.hpp"
25#include "tests/unit/static-data.hpp"
Alexander Afanasyev1a21e102018-06-13 20:33:21 -040026
27#include <iostream>
28#include <ndn-cxx/util/string-helper.hpp>
29
30namespace ndn {
31namespace nac {
32namespace tests {
33
Davide Pesaventoba3f6892020-12-08 22:18:35 -050034class EncryptorStaticDataEnvironment : public IoKeyChainFixture
Alexander Afanasyev1a21e102018-06-13 20:33:21 -040035{
36public:
Alexander Afanasyevda366d82018-06-29 18:18:02 -040037 EncryptorStaticDataEnvironment(bool shouldPublishData)
Alexander Afanasyev1a21e102018-06-13 20:33:21 -040038 : fw(m_io, m_keyChain)
39 , imsFace(static_cast<util::DummyClientFace&>(fw.addFace()))
40 {
Alexander Afanasyevda366d82018-06-29 18:18:02 -040041 if (shouldPublishData) {
42 publishData();
Alexander Afanasyev1a21e102018-06-13 20:33:21 -040043 }
44
Davide Pesaventoba3f6892020-12-08 22:18:35 -050045 auto serveFromIms = [this] (const Name&, const Interest& interest) {
Alexander Afanasyev1a21e102018-06-13 20:33:21 -040046 auto data = m_ims.find(interest);
47 if (data != nullptr) {
48 imsFace.put(*data);
49 }
50 };
51 imsFace.setInterestFilter("/", serveFromIms, [] (auto...) {});
52 advanceClocks(1_ms, 10);
Alexander Afanasyevda366d82018-06-29 18:18:02 -040053
54 imsFace.sentData.clear();
55 imsFace.sentInterests.clear();
56 }
57
58 void
59 publishData()
60 {
61 StaticData data;
62 for (const auto& block : data.managerPackets) {
Davide Pesaventoba3f6892020-12-08 22:18:35 -050063 m_ims.insert(*make_shared<Data>(block));
Alexander Afanasyevda366d82018-06-29 18:18:02 -040064 }
65 advanceClocks(1_ms, 10);
Alexander Afanasyev1a21e102018-06-13 20:33:21 -040066 }
67
68public:
69 DummyForwarder fw;
70 util::DummyClientFace& imsFace;
71 InMemoryStoragePersistent m_ims;
72};
73
Alexander Afanasyevda366d82018-06-29 18:18:02 -040074template<bool shouldPublishData = true>
75class EncryptorFixture : public EncryptorStaticDataEnvironment
Alexander Afanasyev1a21e102018-06-13 20:33:21 -040076{
77public:
78 EncryptorFixture()
Alexander Afanasyevda366d82018-06-29 18:18:02 -040079 : EncryptorStaticDataEnvironment(shouldPublishData)
80 , face(static_cast<util::DummyClientFace&>(fw.addFace()))
Alexander Afanasyev1a21e102018-06-13 20:33:21 -040081 , encryptor("/access/policy/identity/NAC/dataset", "/some/ck/prefix", signingWithSha256(),
Alexander Afanasyevda366d82018-06-29 18:18:02 -040082 [=] (const ErrorCode& code, const std::string& error) {
83 onFailure(code, error);
84 },
Alexander Afanasyev1a21e102018-06-13 20:33:21 -040085 validator, m_keyChain, face)
86 {
87 advanceClocks(1_ms, 10);
88 }
89
90public:
91 util::DummyClientFace& face;
92 ValidatorNull validator;
93 Encryptor encryptor;
Alexander Afanasyevda366d82018-06-29 18:18:02 -040094 util::Signal<EncryptorFixture, ErrorCode, std::string> onFailure;
Alexander Afanasyev1a21e102018-06-13 20:33:21 -040095};
96
Alexander Afanasyevda366d82018-06-29 18:18:02 -040097BOOST_FIXTURE_TEST_SUITE(TestEncryptor, EncryptorFixture<>)
Alexander Afanasyev1a21e102018-06-13 20:33:21 -040098
99BOOST_AUTO_TEST_CASE(EncryptAndPublishedCk)
100{
Alexander Afanasyevc9934282018-07-17 18:41:36 -0400101 encryptor.m_kek.reset();
102 BOOST_CHECK_EQUAL(encryptor.m_isKekRetrievalInProgress, false);
103 encryptor.regenerateCk();
104 BOOST_CHECK_EQUAL(encryptor.m_isKekRetrievalInProgress, true);
105
Alexander Afanasyev1a21e102018-06-13 20:33:21 -0400106 std::string plaintext = "Data to encrypt";
107 auto block = encryptor.encrypt(reinterpret_cast<const uint8_t*>(plaintext.data()), plaintext.size());
108
109 EncryptedContent content(block);
110 auto ckPrefix = content.getKeyLocator();
111 BOOST_CHECK_EQUAL(ckPrefix.getPrefix(-1), "/some/ck/prefix/CK");
112
113 BOOST_CHECK(content.hasIv());
114 BOOST_CHECK_NE(std::string(reinterpret_cast<const char*>(content.getPayload().value()),
115 content.getPayload().value_size()),
116 plaintext);
117
118 advanceClocks(1_ms, 10);
119
120 // check that KEK interests has been sent
121 BOOST_CHECK_EQUAL(face.sentInterests.at(0).getName().getPrefix(6),
122 Name("/access/policy/identity/NAC/dataset/KEK"));
123
124 auto kek = imsFace.sentData.at(0);
125 BOOST_CHECK_EQUAL(kek.getName().getPrefix(6), Name("/access/policy/identity/NAC/dataset/KEK"));
126 BOOST_CHECK_EQUAL(kek.getName().size(), 7);
127
128 face.sentData.clear();
129 face.sentInterests.clear();
130
131 face.receive(Interest(ckPrefix)
132 .setCanBePrefix(true).setMustBeFresh(true));
133 advanceClocks(1_ms, 10);
134
135 auto ckName = face.sentData.at(0).getName();
136 BOOST_CHECK_EQUAL(ckName.getPrefix(4), "/some/ck/prefix/CK");
137 BOOST_CHECK_EQUAL(ckName.get(5), name::Component("ENCRYPTED-BY"));
138
139 auto extractedKek = ckName.getSubName(6);
140 BOOST_CHECK_EQUAL(extractedKek, kek.getName());
Alexander Afanasyevc9934282018-07-17 18:41:36 -0400141
142 BOOST_CHECK_EQUAL(encryptor.m_isKekRetrievalInProgress, false);
Alexander Afanasyev1a21e102018-06-13 20:33:21 -0400143}
144
Alexander Afanasyevda366d82018-06-29 18:18:02 -0400145BOOST_FIXTURE_TEST_CASE(KekRetrievalFailure, EncryptorFixture<false>)
Alexander Afanasyev1a21e102018-06-13 20:33:21 -0400146{
Alexander Afanasyevda366d82018-06-29 18:18:02 -0400147 size_t nErrors = 0;
Davide Pesaventoba3f6892020-12-08 22:18:35 -0500148 onFailure.connect([&] (auto&&...) { ++nErrors; });
Alexander Afanasyevda366d82018-06-29 18:18:02 -0400149
150 std::string plaintext = "Data to encrypt";
151 auto block = encryptor.encrypt(reinterpret_cast<const uint8_t*>(plaintext.data()), plaintext.size());
Alexander Afanasyev1a21e102018-06-13 20:33:21 -0400152 advanceClocks(1_ms, 10);
153
Alexander Afanasyevda366d82018-06-29 18:18:02 -0400154 // check that KEK interests has been sent
155 BOOST_CHECK_EQUAL(face.sentInterests.at(0).getName().getPrefix(6), Name("/access/policy/identity/NAC/dataset/KEK"));
156
157 // and failed
158 BOOST_CHECK_EQUAL(imsFace.sentData.size(), 0);
159
160 advanceClocks(1_s, 13); // 4_s default interest lifetime x 3
161 BOOST_CHECK_EQUAL(nErrors, 1);
162 BOOST_CHECK_EQUAL(imsFace.sentData.size(), 0);
163
164 advanceClocks(1_s, 730); // 60 seconds between attempts + ~12 seconds for each attempt
165 BOOST_CHECK_EQUAL(nErrors, 11);
166 BOOST_CHECK_EQUAL(imsFace.sentData.size(), 0);
167
168 // check recovery
169
170 publishData();
171
172 advanceClocks(1_s, 73);
173
174 auto kek = imsFace.sentData.at(0);
175 BOOST_CHECK_EQUAL(kek.getName().getPrefix(6), Name("/access/policy/identity/NAC/dataset/KEK"));
176 BOOST_CHECK_EQUAL(kek.getName().size(), 7);
177}
178
179BOOST_AUTO_TEST_CASE(EnumerateDataFromIms)
180{
181 encryptor.regenerateCk();
182 advanceClocks(1_ms, 10);
183
184 encryptor.regenerateCk();
Alexander Afanasyev1a21e102018-06-13 20:33:21 -0400185 advanceClocks(1_ms, 10);
186
187 BOOST_CHECK_EQUAL(encryptor.size(), 3);
188 size_t nCk = 0;
189 for (const auto& data : encryptor) {
190 BOOST_TEST_MESSAGE(data.getName());
191 if (data.getName().getPrefix(4) == Name("/some/ck/prefix/CK")) {
192 ++nCk;
193 }
194 }
195 BOOST_CHECK_EQUAL(nCk, 3);
196}
197
198BOOST_AUTO_TEST_CASE(DumpPackets) // use this to update content of other test cases
199{
200 if (std::getenv("NAC_DUMP_PACKETS") == nullptr) {
201 return;
202 }
203
Davide Pesaventoba3f6892020-12-08 22:18:35 -0500204 const auto plaintext = "Data to encrypt"s;
Alexander Afanasyev1a21e102018-06-13 20:33:21 -0400205
Davide Pesaventoba3f6892020-12-08 22:18:35 -0500206 std::cerr << "const std::vector<Block> encryptedBlobs = {\n";
Alexander Afanasyev1a21e102018-06-13 20:33:21 -0400207 for (size_t i = 0; i < 3; ++i) {
Davide Pesaventoba3f6892020-12-08 22:18:35 -0500208 std::cerr << " \"";
Alexander Afanasyev1a21e102018-06-13 20:33:21 -0400209 auto block = encryptor.encrypt(reinterpret_cast<const uint8_t*>(plaintext.data()), plaintext.size());
210 printHex(std::cerr, block.wireEncode().wire(), block.wireEncode().size(), true);
Davide Pesaventoba3f6892020-12-08 22:18:35 -0500211 std::cerr << "\"_block,\n";
Alexander Afanasyev1a21e102018-06-13 20:33:21 -0400212
Alexander Afanasyevda366d82018-06-29 18:18:02 -0400213 encryptor.regenerateCk();
Alexander Afanasyev1a21e102018-06-13 20:33:21 -0400214 advanceClocks(1_ms, 10);
215 }
Davide Pesaventoba3f6892020-12-08 22:18:35 -0500216 std::cerr << "};\n\n";
Alexander Afanasyev1a21e102018-06-13 20:33:21 -0400217
Davide Pesaventoba3f6892020-12-08 22:18:35 -0500218 std::cerr << "const std::vector<Block> encryptorPackets = {\n";
Alexander Afanasyev1a21e102018-06-13 20:33:21 -0400219 for (const auto& data : encryptor) {
Davide Pesaventoba3f6892020-12-08 22:18:35 -0500220 std::cerr << " \"";
Alexander Afanasyev1a21e102018-06-13 20:33:21 -0400221 printHex(std::cerr, data.wireEncode().wire(), data.wireEncode().size(), true);
Davide Pesaventoba3f6892020-12-08 22:18:35 -0500222 std::cerr << "\"_block,\n";
Alexander Afanasyev1a21e102018-06-13 20:33:21 -0400223 }
Davide Pesaventoba3f6892020-12-08 22:18:35 -0500224 std::cerr << "};\n\n";
Alexander Afanasyev1a21e102018-06-13 20:33:21 -0400225}
226
227BOOST_AUTO_TEST_SUITE_END()
228
229} // namespace tests
230} // namespace nac
231} // namespace ndn