blob: 233d28507b7bb871824125db082e200ef2bc0f21 [file] [log] [blame]
Zhiyi Zhang5f133622015-10-17 08:49:54 +08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Zhiyi Zhang19a11d22018-04-12 22:58:20 -07003 * Copyright (c) 2014-2018, Regents of the University of California
Zhiyi Zhang5f133622015-10-17 08:49:54 +08004 *
Alexander Afanasyev9091d832018-04-18 17:21:08 -04005 * This file is part of NAC (Name-Based Access Control for NDN).
6 * See AUTHORS.md for complete list of NAC authors and contributors.
Zhiyi Zhang5f133622015-10-17 08:49:54 +08007 *
Alexander Afanasyev9091d832018-04-18 17:21:08 -04008 * NAC is free software: you can redistribute it and/or modify it under the terms
Zhiyi Zhang5f133622015-10-17 08:49:54 +08009 * of the GNU General Public License as published by the Free Software Foundation,
10 * either version 3 of the License, or (at your option) any later version.
11 *
Alexander Afanasyev9091d832018-04-18 17:21:08 -040012 * NAC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
Zhiyi Zhang5f133622015-10-17 08:49:54 +080013 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
Alexander Afanasyev9091d832018-04-18 17:21:08 -040017 * NAC, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
Zhiyi Zhang5f133622015-10-17 08:49:54 +080018 *
Zhiyi Zhang19a11d22018-04-12 22:58:20 -070019 * @author Zhiyi Zhang <zhiyi@cs.ucla.edu>
Zhiyi Zhang5f133622015-10-17 08:49:54 +080020 * @author Yingdi Yu <yingdi@cs.ucla.edu>
21 */
22
23#include "consumer.hpp"
24#include "boost-test.hpp"
Zhiyi Zhang5f133622015-10-17 08:49:54 +080025#include "unit-test-time-fixture.hpp"
Zhiyi Zhang19a11d22018-04-12 22:58:20 -070026#include "algo/encryptor.hpp"
Zhiyi Zhang5f133622015-10-17 08:49:54 +080027
28#include <ndn-cxx/security/key-chain.hpp>
29#include <ndn-cxx/util/dummy-client-face.hpp>
30#include <ndn-cxx/util/time-unit-test-clock.hpp>
Zhiyi Zhang5f133622015-10-17 08:49:54 +080031#include <boost/asio.hpp>
Zhiyi Zhang19a11d22018-04-12 22:58:20 -070032#include <boost/filesystem.hpp>
Zhiyi Zhang5f133622015-10-17 08:49:54 +080033
34namespace ndn {
Alexander Afanasyev9091d832018-04-18 17:21:08 -040035namespace nac {
Zhiyi Zhang5f133622015-10-17 08:49:54 +080036namespace tests {
37
Zhiyi Zhang19a11d22018-04-12 22:58:20 -070038static const uint8_t DATA_CONTEN[] = {0xcb, 0xe5, 0x6a, 0x80, 0x41, 0x24, 0x58, 0x23,
39 0x84, 0x14, 0x15, 0x61, 0x80, 0xb9, 0x5e, 0xbd,
40 0xce, 0x32, 0xb4, 0xbe, 0xbc, 0x91, 0x31, 0xd6,
41 0x19, 0x00, 0x80, 0x8b, 0xfa, 0x00, 0x05, 0x9c};
Zhiyi Zhang5f133622015-10-17 08:49:54 +080042
Zhiyi Zhang19a11d22018-04-12 22:58:20 -070043static const uint8_t AES_KEY[] =
44 {0xdd, 0x60, 0x77, 0xec, 0xa9, 0x6b, 0x23, 0x1b, 0x40, 0x6b, 0x5a, 0xf8, 0x7d, 0x3d, 0x55, 0x32};
Zhiyi Zhang5f133622015-10-17 08:49:54 +080045
Zhiyi Zhang19a11d22018-04-12 22:58:20 -070046static const uint8_t IV[] =
47 {0x73, 0x6f, 0x6d, 0x65, 0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72};
Zhiyi Zhang5f133622015-10-17 08:49:54 +080048
49class ConsumerFixture : public UnitTestTimeFixture
50{
51public:
52 ConsumerFixture()
53 : tmpPath(boost::filesystem::path(TMP_TESTS_PATH))
Junxiao Shic1264c82016-07-14 15:04:07 +000054 , face1(io, keyChain, {true, true})
55 , face2(io, keyChain, {true, true})
Zhiyi Zhang5f133622015-10-17 08:49:54 +080056 , readInterestOffset1(0)
57 , readDataOffset1(0)
58 , readInterestOffset2(0)
59 , readDataOffset2(0)
60 , groupName("/Prefix/READ")
61 , contentName("/Prefix/SAMPLE/Content")
62 , cKeyName("/Prefix/SAMPLE/Content/C-KEY/1")
63 , eKeyName("/Prefix/READ/E-KEY/1/2")
64 , dKeyName("/Prefix/READ/D-KEY/1/2")
65 , uKeyName("/U/Key")
66 , uName("/U")
67 {
68 boost::filesystem::create_directories(tmpPath);
69
70 // generate e/d key
Zhiyi Zhang5f133622015-10-17 08:49:54 +080071 RsaKeyParams params;
Zhiyi Zhang19a11d22018-04-12 22:58:20 -070072 fixtureDKeyBuf = algo::Rsa::generateKey(params).getKeyBits();
Zhiyi Zhang5f133622015-10-17 08:49:54 +080073 fixtureEKeyBuf = algo::Rsa::deriveEncryptKey(fixtureDKeyBuf).getKeyBits();
74
75 // generate user key
Zhiyi Zhang19a11d22018-04-12 22:58:20 -070076 fixtureUDKeyBuf = algo::Rsa::generateKey(params).getKeyBits();
Zhiyi Zhang5f133622015-10-17 08:49:54 +080077 fixtureUEKeyBuf = algo::Rsa::deriveEncryptKey(fixtureUDKeyBuf).getKeyBits();
78
79 // load C-KEY
80 fixtureCKeyBuf = Buffer(AES_KEY, sizeof(AES_KEY));
81 }
82
83 ~ConsumerFixture()
84 {
85 boost::filesystem::remove_all(tmpPath);
86 }
87
88 shared_ptr<Data>
89 createEncryptedContent()
90 {
91 shared_ptr<Data> contentData = make_shared<Data>(contentName);
92 algo::EncryptParams eparams(tlv::AlgorithmAesCbc);
93 eparams.setIV(IV, sizeof(IV));
Zhiyi Zhang19a11d22018-04-12 22:58:20 -070094 algo::encryptData(*contentData,
95 DATA_CONTEN,
96 sizeof(DATA_CONTEN),
97 cKeyName,
98 fixtureCKeyBuf.data(),
99 fixtureCKeyBuf.size(),
100 eparams);
Zhiyi Zhang5f133622015-10-17 08:49:54 +0800101 keyChain.sign(*contentData);
102 return contentData;
103 }
104
105 shared_ptr<Data>
106 createEncryptedCKey()
107 {
108 shared_ptr<Data> cKeyData = make_shared<Data>(cKeyName);
109 algo::EncryptParams eparams(tlv::AlgorithmRsaOaep);
Zhiyi Zhang19a11d22018-04-12 22:58:20 -0700110 algo::encryptData(*cKeyData,
111 fixtureCKeyBuf.data(),
112 fixtureCKeyBuf.size(),
113 dKeyName,
114 fixtureEKeyBuf.data(),
115 fixtureEKeyBuf.size(),
116 eparams);
Zhiyi Zhang5f133622015-10-17 08:49:54 +0800117 keyChain.sign(*cKeyData);
118 return cKeyData;
119 }
120
121 shared_ptr<Data>
122 createEncryptedDKey()
123 {
124 shared_ptr<Data> dKeyData = make_shared<Data>(dKeyName);
125 algo::EncryptParams eparams(tlv::AlgorithmRsaOaep);
Zhiyi Zhang19a11d22018-04-12 22:58:20 -0700126 algo::encryptData(*dKeyData,
127 fixtureDKeyBuf.data(),
128 fixtureDKeyBuf.size(),
129 uKeyName,
130 fixtureUEKeyBuf.data(),
131 fixtureUEKeyBuf.size(),
132 eparams);
Zhiyi Zhang5f133622015-10-17 08:49:54 +0800133 keyChain.sign(*dKeyData);
134 return dKeyData;
135 }
136
137 bool
138 passPacket()
139 {
140 bool hasPassed = false;
141
Junxiao Shic1264c82016-07-14 15:04:07 +0000142 checkFace(face1.sentInterests, readInterestOffset1, face2, hasPassed);
143 checkFace(face1.sentData, readDataOffset1, face2, hasPassed);
144 checkFace(face2.sentInterests, readInterestOffset2, face1, hasPassed);
145 checkFace(face2.sentData, readDataOffset2, face1, hasPassed);
Zhiyi Zhang5f133622015-10-17 08:49:54 +0800146
147 return hasPassed;
148 }
149
150 template<typename Packet>
151 void
152 checkFace(std::vector<Packet>& receivedPackets,
153 size_t& readPacketOffset,
154 util::DummyClientFace& receiver,
155 bool& hasPassed)
156 {
157 while (receivedPackets.size() > readPacketOffset) {
158 receiver.receive(receivedPackets[readPacketOffset]);
159 readPacketOffset++;
160 hasPassed = true;
161 }
162 }
163
164public:
165 boost::filesystem::path tmpPath;
166
Junxiao Shic1264c82016-07-14 15:04:07 +0000167 util::DummyClientFace face1;
168 util::DummyClientFace face2;
Zhiyi Zhang5f133622015-10-17 08:49:54 +0800169
170 size_t readInterestOffset1;
171 size_t readDataOffset1;
172 size_t readInterestOffset2;
173 size_t readDataOffset2;
174
175 KeyChain keyChain;
176
177 Buffer fixtureCKeyBuf;
178 Buffer fixtureEKeyBuf;
179 Buffer fixtureDKeyBuf;
180 Buffer fixtureUEKeyBuf;
181 Buffer fixtureUDKeyBuf;
182
183 Name groupName;
184 Name contentName;
185 Name cKeyName;
186 Name eKeyName;
187 Name dKeyName;
188 Name uKeyName;
189 Name uName;
190};
191
192BOOST_FIXTURE_TEST_SUITE(TestConsumer, ConsumerFixture)
193
194BOOST_AUTO_TEST_CASE(DecryptContent)
195{
196 std::string dbDir = tmpPath.c_str();
197 dbDir += "/test.db";
198
199 // generate AES key pairs
200 Buffer aesKeyBuf = Buffer(AES_KEY, sizeof(AES_KEY));
201
202 // generate C-KEY packet
203 auto cKeyData = createEncryptedCKey();
204 // generate Content packet
205 auto contentData = createEncryptedContent();
206
207 // create consumer
Junxiao Shic1264c82016-07-14 15:04:07 +0000208 Consumer consumer(face1, Name("/Group"), Name("/U"), dbDir);
Zhiyi Zhang5f133622015-10-17 08:49:54 +0800209
210 // decrypt
211 consumer.decrypt(cKeyData->getContent().blockFromValue(),
212 fixtureDKeyBuf,
Zhiyi Zhang19a11d22018-04-12 22:58:20 -0700213 [=] (const Buffer& result) {
214 BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(),
215 result.end(),
Zhiyi Zhang5f133622015-10-17 08:49:54 +0800216 aesKeyBuf.begin(),
217 aesKeyBuf.end());
218 },
Zhiyi Zhang19a11d22018-04-12 22:58:20 -0700219 [=] (const ErrorCode&, const std::string&) { BOOST_CHECK(false); });
Zhiyi Zhang5f133622015-10-17 08:49:54 +0800220
221 // decrypt
222 consumer.decrypt(contentData->getContent().blockFromValue(),
223 fixtureCKeyBuf,
Zhiyi Zhang19a11d22018-04-12 22:58:20 -0700224 [=] (const Buffer& result) {
225 BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(),
226 result.end(),
Zhiyi Zhang5f133622015-10-17 08:49:54 +0800227 DATA_CONTEN,
228 DATA_CONTEN + sizeof(DATA_CONTEN));
229 },
Zhiyi Zhang19a11d22018-04-12 22:58:20 -0700230 [=] (const ErrorCode&, const std::string&) { BOOST_CHECK(false); });
Zhiyi Zhang5f133622015-10-17 08:49:54 +0800231}
232
233BOOST_AUTO_TEST_CASE(Consume)
234{
235 auto contentData = createEncryptedContent();
236 auto cKeyData = createEncryptedCKey();
237 auto dKeyData = createEncryptedDKey();
238
239 int contentCount = 0;
240 int cKeyCount = 0;
241 int dKeyCount = 0;
242
243 Name prefix("/Prefix");
244 // prepare face1
Junxiao Shic1264c82016-07-14 15:04:07 +0000245 face1.setInterestFilter(prefix,
246 [&] (const InterestFilter&, const Interest& i) {
247 if (i.matchesData(*contentData)) {
248 contentCount = 1;
249 face1.put(*contentData);
250 return;
251 }
252 if (i.matchesData(*cKeyData)) {
253 cKeyCount = 1;
254 face1.put(*cKeyData);
255 return;
256 }
257 if (i.matchesData(*dKeyData)) {
258 dKeyCount = 1;
259 face1.put(*dKeyData);
260 return;
261 }
262 return;
263 },
264 RegisterPrefixSuccessCallback(),
Zhiyi Zhang19a11d22018-04-12 22:58:20 -0700265 [] (const Name&, const std::string& e) {});
Zhiyi Zhang5f133622015-10-17 08:49:54 +0800266
267 do {
268 advanceClocks(time::milliseconds(10), 20);
269 } while (passPacket());
270
271 // create consumer
272 std::string dbDir = tmpPath.c_str();
273 dbDir += "/test.db";
Junxiao Shic1264c82016-07-14 15:04:07 +0000274 Consumer consumer(face2, groupName, uName, dbDir);
Zhiyi Zhang5f133622015-10-17 08:49:54 +0800275 consumer.addDecryptionKey(uKeyName, fixtureUDKeyBuf);
276
277 int finalCount = 0;
278 consumer.consume(contentName,
Zhiyi Zhang19a11d22018-04-12 22:58:20 -0700279 [&] (const Data& data, const Buffer& result) {
Zhiyi Zhang5f133622015-10-17 08:49:54 +0800280 finalCount = 1;
Zhiyi Zhang19a11d22018-04-12 22:58:20 -0700281 BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(),
282 result.end(),
Zhiyi Zhang5f133622015-10-17 08:49:54 +0800283 DATA_CONTEN,
284 DATA_CONTEN + sizeof(DATA_CONTEN));
285 },
Zhiyi Zhang19a11d22018-04-12 22:58:20 -0700286 [&] (const ErrorCode& code, const std::string& str) { BOOST_CHECK(false); });
Zhiyi Zhang5f133622015-10-17 08:49:54 +0800287
288 do {
289 advanceClocks(time::milliseconds(10), 20);
290 } while (passPacket());
291
292 BOOST_CHECK_EQUAL(contentCount, 1);
293 BOOST_CHECK_EQUAL(cKeyCount, 1);
294 BOOST_CHECK_EQUAL(dKeyCount, 1);
295 BOOST_CHECK_EQUAL(finalCount, 1);
296}
297
Yingdi Yu48967a62016-03-11 22:04:14 -0800298BOOST_AUTO_TEST_CASE(CosumerWithLink)
299{
300 auto contentData = createEncryptedContent();
301 auto cKeyData = createEncryptedCKey();
302 auto dKeyData = createEncryptedDKey();
303
304 int contentCount = 0;
305 int cKeyCount = 0;
306 int dKeyCount = 0;
307 int resultCount = 0;
308
309 Name prefix("/Prefix");
310 // prepare face1
311 face1.setInterestFilter(prefix,
312 [&] (const InterestFilter&, const Interest& i) {
Zhiyi Zhang19a11d22018-04-12 22:58:20 -0700313 BOOST_CHECK(i.getForwardingHint().size() == 3);
Yingdi Yu48967a62016-03-11 22:04:14 -0800314 if (i.matchesData(*contentData)) {
315 contentCount++;
316 face1.put(*contentData);
317 return;
318 }
319 if (i.matchesData(*cKeyData)) {
320 cKeyCount++;
321 face1.put(*cKeyData);
322 return;
323 }
324 if (i.matchesData(*dKeyData)) {
325 dKeyCount++;
326 face1.put(*dKeyData);
327 return;
328 }
329 return;
330 },
331 RegisterPrefixSuccessCallback(),
Zhiyi Zhang19a11d22018-04-12 22:58:20 -0700332 [] (const Name&, const std::string& e) {});
Yingdi Yu48967a62016-03-11 22:04:14 -0800333
334 do {
335 advanceClocks(time::milliseconds(10), 20);
336 } while (passPacket());
337
338 // create consumer
339 std::string dbDir = tmpPath.c_str();
340 dbDir += "/test.db";
341
342 Link ckeylink("ckey", {{10, "/ckey1"}, {20, "/ckey2"}, {100, "/ckey3"}});
343 Link dkeylink("dkey", {{10, "/dkey1"}, {20, "/dkey2"}, {100, "/dkey3"}});
344 Link datalink("data", {{10, "/data1"}, {20, "/data2"}, {100, "/data3"}});
345 keyChain.sign(ckeylink);
346 keyChain.sign(dkeylink);
347 keyChain.sign(datalink);
348
349 Consumer consumer(face2, groupName, uName, dbDir, ckeylink, dkeylink);
350 consumer.addDecryptionKey(uKeyName, fixtureUDKeyBuf);
351
352 consumer.consume(contentName,
Zhiyi Zhang19a11d22018-04-12 22:58:20 -0700353 [&] (const Data& data, const Buffer& result) {
Yingdi Yu48967a62016-03-11 22:04:14 -0800354 BOOST_CHECK(true);
355 resultCount++;
356 },
Zhiyi Zhang19a11d22018-04-12 22:58:20 -0700357 [] (const ErrorCode& code, const std::string& str) { BOOST_CHECK(false); },
Yingdi Yu48967a62016-03-11 22:04:14 -0800358 datalink);
359
360 do {
361 advanceClocks(time::milliseconds(10), 200);
362 } while (passPacket());
363
364 BOOST_CHECK_EQUAL(resultCount, 1);
365 BOOST_CHECK_EQUAL(contentCount, 1);
366 BOOST_CHECK_EQUAL(cKeyCount, 1);
367 BOOST_CHECK_EQUAL(dKeyCount, 1);
368}
369
Zhiyi Zhang5f133622015-10-17 08:49:54 +0800370BOOST_AUTO_TEST_SUITE_END()
371
Zhiyi Zhang19a11d22018-04-12 22:58:20 -0700372} // namespace tests
Alexander Afanasyev9091d832018-04-18 17:21:08 -0400373} // namespace nac
Zhiyi Zhang5f133622015-10-17 08:49:54 +0800374} // namespace ndn