blob: f7f39ce44cf261e72fad153e6117197ac983469b [file] [log] [blame]
Zhiyi Zhang5f133622015-10-17 08:49:54 +08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Junxiao Shic1264c82016-07-14 15:04:07 +00003 * Copyright (c) 2014-2016, Regents of the University of California
Zhiyi Zhang5f133622015-10-17 08:49:54 +08004 *
5 * This file is part of ndn-group-encrypt (Group-based Encryption Protocol for NDN).
6 * See AUTHORS.md for complete list of ndn-group-encrypt authors and contributors.
7 *
8 * ndn-group-encrypt is free software: you can redistribute it and/or modify it under the terms
9 * 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 *
12 * ndn-group-encrypt is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 * 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
17 * ndn-group-encrypt, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
18 *
19 * @author Zhiyi Zhang <dreamerbarrychang@gmail.com>
20 * @author Yingdi Yu <yingdi@cs.ucla.edu>
21 */
22
23#include "consumer.hpp"
24#include "boost-test.hpp"
25#include "algo/encryptor.hpp"
26#include "unit-test-time-fixture.hpp"
27
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>
31#include <boost/filesystem.hpp>
32#include <boost/asio.hpp>
33
34namespace ndn {
35namespace gep {
36namespace tests {
37
38static const uint8_t DATA_CONTEN[] = {
39 0xcb, 0xe5, 0x6a, 0x80, 0x41, 0x24, 0x58, 0x23,
40 0x84, 0x14, 0x15, 0x61, 0x80, 0xb9, 0x5e, 0xbd,
41 0xce, 0x32, 0xb4, 0xbe, 0xbc, 0x91, 0x31, 0xd6,
42 0x19, 0x00, 0x80, 0x8b, 0xfa, 0x00, 0x05, 0x9c
43};
44
45static const uint8_t AES_KEY[] = {
46 0xdd, 0x60, 0x77, 0xec, 0xa9, 0x6b, 0x23, 0x1b,
47 0x40, 0x6b, 0x5a, 0xf8, 0x7d, 0x3d, 0x55, 0x32
48};
49
50static const uint8_t IV[] = {
51 0x73, 0x6f, 0x6d, 0x65, 0x72, 0x61, 0x6e, 0x64,
52 0x6f, 0x6d, 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72
53};
54
55class ConsumerFixture : public UnitTestTimeFixture
56{
57public:
58 ConsumerFixture()
59 : tmpPath(boost::filesystem::path(TMP_TESTS_PATH))
Junxiao Shic1264c82016-07-14 15:04:07 +000060 , face1(io, keyChain, {true, true})
61 , face2(io, keyChain, {true, true})
Zhiyi Zhang5f133622015-10-17 08:49:54 +080062 , readInterestOffset1(0)
63 , readDataOffset1(0)
64 , readInterestOffset2(0)
65 , readDataOffset2(0)
66 , groupName("/Prefix/READ")
67 , contentName("/Prefix/SAMPLE/Content")
68 , cKeyName("/Prefix/SAMPLE/Content/C-KEY/1")
69 , eKeyName("/Prefix/READ/E-KEY/1/2")
70 , dKeyName("/Prefix/READ/D-KEY/1/2")
71 , uKeyName("/U/Key")
72 , uName("/U")
73 {
74 boost::filesystem::create_directories(tmpPath);
75
76 // generate e/d key
77 RandomNumberGenerator rng;
78 RsaKeyParams params;
79 fixtureDKeyBuf = algo::Rsa::generateKey(rng, params).getKeyBits();
80 fixtureEKeyBuf = algo::Rsa::deriveEncryptKey(fixtureDKeyBuf).getKeyBits();
81
82 // generate user key
83 fixtureUDKeyBuf = algo::Rsa::generateKey(rng, params).getKeyBits();
84 fixtureUEKeyBuf = algo::Rsa::deriveEncryptKey(fixtureUDKeyBuf).getKeyBits();
85
86 // load C-KEY
87 fixtureCKeyBuf = Buffer(AES_KEY, sizeof(AES_KEY));
88 }
89
90 ~ConsumerFixture()
91 {
92 boost::filesystem::remove_all(tmpPath);
93 }
94
95 shared_ptr<Data>
96 createEncryptedContent()
97 {
98 shared_ptr<Data> contentData = make_shared<Data>(contentName);
99 algo::EncryptParams eparams(tlv::AlgorithmAesCbc);
100 eparams.setIV(IV, sizeof(IV));
101 algo::encryptData(*contentData, DATA_CONTEN, sizeof(DATA_CONTEN), cKeyName,
102 fixtureCKeyBuf.buf(), fixtureCKeyBuf.size(), eparams);
103 keyChain.sign(*contentData);
104 return contentData;
105 }
106
107 shared_ptr<Data>
108 createEncryptedCKey()
109 {
110 shared_ptr<Data> cKeyData = make_shared<Data>(cKeyName);
111 algo::EncryptParams eparams(tlv::AlgorithmRsaOaep);
112 algo::encryptData(*cKeyData, fixtureCKeyBuf.buf(), fixtureCKeyBuf.size(), dKeyName,
113 fixtureEKeyBuf.buf(), fixtureEKeyBuf.size(), eparams);
114 keyChain.sign(*cKeyData);
115 return cKeyData;
116 }
117
118 shared_ptr<Data>
119 createEncryptedDKey()
120 {
121 shared_ptr<Data> dKeyData = make_shared<Data>(dKeyName);
122 algo::EncryptParams eparams(tlv::AlgorithmRsaOaep);
123 algo::encryptData(*dKeyData, fixtureDKeyBuf.buf(), fixtureDKeyBuf.size(), uKeyName,
124 fixtureUEKeyBuf.buf(), fixtureUEKeyBuf.size(), eparams);
125 keyChain.sign(*dKeyData);
126 return dKeyData;
127 }
128
129 bool
130 passPacket()
131 {
132 bool hasPassed = false;
133
Junxiao Shic1264c82016-07-14 15:04:07 +0000134 checkFace(face1.sentInterests, readInterestOffset1, face2, hasPassed);
135 checkFace(face1.sentData, readDataOffset1, face2, hasPassed);
136 checkFace(face2.sentInterests, readInterestOffset2, face1, hasPassed);
137 checkFace(face2.sentData, readDataOffset2, face1, hasPassed);
Zhiyi Zhang5f133622015-10-17 08:49:54 +0800138
139 return hasPassed;
140 }
141
142 template<typename Packet>
143 void
144 checkFace(std::vector<Packet>& receivedPackets,
145 size_t& readPacketOffset,
146 util::DummyClientFace& receiver,
147 bool& hasPassed)
148 {
149 while (receivedPackets.size() > readPacketOffset) {
150 receiver.receive(receivedPackets[readPacketOffset]);
151 readPacketOffset++;
152 hasPassed = true;
153 }
154 }
155
156public:
157 boost::filesystem::path tmpPath;
158
Junxiao Shic1264c82016-07-14 15:04:07 +0000159 util::DummyClientFace face1;
160 util::DummyClientFace face2;
Zhiyi Zhang5f133622015-10-17 08:49:54 +0800161
162 size_t readInterestOffset1;
163 size_t readDataOffset1;
164 size_t readInterestOffset2;
165 size_t readDataOffset2;
166
167 KeyChain keyChain;
168
169 Buffer fixtureCKeyBuf;
170 Buffer fixtureEKeyBuf;
171 Buffer fixtureDKeyBuf;
172 Buffer fixtureUEKeyBuf;
173 Buffer fixtureUDKeyBuf;
174
175 Name groupName;
176 Name contentName;
177 Name cKeyName;
178 Name eKeyName;
179 Name dKeyName;
180 Name uKeyName;
181 Name uName;
182};
183
184BOOST_FIXTURE_TEST_SUITE(TestConsumer, ConsumerFixture)
185
186BOOST_AUTO_TEST_CASE(DecryptContent)
187{
188 std::string dbDir = tmpPath.c_str();
189 dbDir += "/test.db";
190
191 // generate AES key pairs
192 Buffer aesKeyBuf = Buffer(AES_KEY, sizeof(AES_KEY));
193
194 // generate C-KEY packet
195 auto cKeyData = createEncryptedCKey();
196 // generate Content packet
197 auto contentData = createEncryptedContent();
198
199 // create consumer
Junxiao Shic1264c82016-07-14 15:04:07 +0000200 Consumer consumer(face1, Name("/Group"), Name("/U"), dbDir);
Zhiyi Zhang5f133622015-10-17 08:49:54 +0800201
202 // decrypt
203 consumer.decrypt(cKeyData->getContent().blockFromValue(),
204 fixtureDKeyBuf,
205 [=](const Buffer& result){
206 BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(), result.end(),
207 aesKeyBuf.begin(),
208 aesKeyBuf.end());
209 },
210 [=](const ErrorCode&, const std::string&){
211 BOOST_CHECK(false);
212 });
213
214 // decrypt
215 consumer.decrypt(contentData->getContent().blockFromValue(),
216 fixtureCKeyBuf,
217 [=](const Buffer& result){
218 BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(), result.end(),
219 DATA_CONTEN,
220 DATA_CONTEN + sizeof(DATA_CONTEN));
221 },
222 [=](const ErrorCode&, const std::string&){
223 BOOST_CHECK(false);
224 });
225}
226
227BOOST_AUTO_TEST_CASE(Consume)
228{
229 auto contentData = createEncryptedContent();
230 auto cKeyData = createEncryptedCKey();
231 auto dKeyData = createEncryptedDKey();
232
233 int contentCount = 0;
234 int cKeyCount = 0;
235 int dKeyCount = 0;
236
237 Name prefix("/Prefix");
238 // prepare face1
Junxiao Shic1264c82016-07-14 15:04:07 +0000239 face1.setInterestFilter(prefix,
240 [&] (const InterestFilter&, const Interest& i) {
241 if (i.matchesData(*contentData)) {
242 contentCount = 1;
243 face1.put(*contentData);
244 return;
245 }
246 if (i.matchesData(*cKeyData)) {
247 cKeyCount = 1;
248 face1.put(*cKeyData);
249 return;
250 }
251 if (i.matchesData(*dKeyData)) {
252 dKeyCount = 1;
253 face1.put(*dKeyData);
254 return;
255 }
256 return;
257 },
258 RegisterPrefixSuccessCallback(),
259 [] (const Name&, const std::string& e) { });
Zhiyi Zhang5f133622015-10-17 08:49:54 +0800260
261 do {
262 advanceClocks(time::milliseconds(10), 20);
263 } while (passPacket());
264
265 // create consumer
266 std::string dbDir = tmpPath.c_str();
267 dbDir += "/test.db";
Junxiao Shic1264c82016-07-14 15:04:07 +0000268 Consumer consumer(face2, groupName, uName, dbDir);
Zhiyi Zhang5f133622015-10-17 08:49:54 +0800269 consumer.addDecryptionKey(uKeyName, fixtureUDKeyBuf);
270
271 int finalCount = 0;
272 consumer.consume(contentName,
273 [&](const Data& data, const Buffer& result){
274 finalCount = 1;
275 BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(), result.end(),
276 DATA_CONTEN,
277 DATA_CONTEN + sizeof(DATA_CONTEN));
278 },
279 [&](const ErrorCode& code, const std::string& str){
280 BOOST_CHECK(false);
281 });
282
283 do {
284 advanceClocks(time::milliseconds(10), 20);
285 } while (passPacket());
286
287 BOOST_CHECK_EQUAL(contentCount, 1);
288 BOOST_CHECK_EQUAL(cKeyCount, 1);
289 BOOST_CHECK_EQUAL(dKeyCount, 1);
290 BOOST_CHECK_EQUAL(finalCount, 1);
291}
292
293BOOST_AUTO_TEST_SUITE_END()
294
295} // namespace test
296} // namespace gep
297} // namespace ndn