blob: d364dcfa746cd84b6b17b5feb658b56b553bd85b [file] [log] [blame]
Alexander Afanasyevc169a812014-05-20 20:37:29 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Yingdi Yu8dceb1d2014-02-18 12:45:10 -08002/**
Alexander Afanasyev34a37632015-01-16 17:37:36 -08003 * Copyright (c) 2013-2015 Regents of the University of California.
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07006 *
Alexander Afanasyevc169a812014-05-20 20:37:29 -04007 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library 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 Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
Yingdi Yu8dceb1d2014-02-18 12:45:10 -080020 */
21
Yingdi Yu8dceb1d2014-02-18 12:45:10 -080022#include "security/key-chain.hpp"
Steve DiBenedettoa8659ff2014-12-04 14:50:28 -070023#include "../util/test-home-environment-fixture.hpp"
Yingdi Yuf56c68f2014-04-24 21:50:13 -070024#include <boost/filesystem.hpp>
Yingdi Yu8dceb1d2014-02-18 12:45:10 -080025
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -070026#include "boost-test.hpp"
Alexander Afanasyev07113802015-01-15 19:14:36 -080027#include "dummy-keychain.hpp"
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -070028
Yingdi Yu8dceb1d2014-02-18 12:45:10 -080029namespace ndn {
Yingdi Yuf56c68f2014-04-24 21:50:13 -070030namespace tests {
Yingdi Yu8dceb1d2014-02-18 12:45:10 -080031
Spyridon Mastorakis429634f2015-02-19 17:35:33 -080032BOOST_FIXTURE_TEST_SUITE(SecurityKeyChain, util::TestHomeEnvironmentFixture)
Yingdi Yuf56c68f2014-04-24 21:50:13 -070033
34BOOST_AUTO_TEST_CASE(ConstructorNormalConfig)
35{
36 using namespace boost::filesystem;
37
Alexander Afanasyev8b1674a2014-05-15 00:58:43 -070038 setenv("TEST_HOME", "tests/unit-tests/security/config-file-home", 1);
Yingdi Yuf56c68f2014-04-24 21:50:13 -070039
40 BOOST_REQUIRE_NO_THROW(KeyChain());
41
Alexander Afanasyev07113802015-01-15 19:14:36 -080042 KeyChain keyChain;
43 BOOST_CHECK_EQUAL(keyChain.getPib().getPibLocator(),
44 "pib-sqlite3:/tmp/test/ndn-cxx/keychain/sqlite3-file/");
45 BOOST_CHECK_EQUAL(keyChain.getPib().getTpmLocator(),
46 "tpm-file:/tmp/test/ndn-cxx/keychain/sqlite3-file/");
47 BOOST_CHECK_EQUAL(keyChain.getTpm().getTpmLocator(),
48 "tpm-file:/tmp/test/ndn-cxx/keychain/sqlite3-file/");
49
Yingdi Yuf56c68f2014-04-24 21:50:13 -070050 path pibPath(absolute(std::getenv("TEST_HOME")));
51 pibPath /= ".ndn/ndnsec-public-info.db";
52
53 boost::filesystem::remove(pibPath);
54}
55
56BOOST_AUTO_TEST_CASE(ConstructorEmptyConfig)
57{
58 using namespace boost::filesystem;
59
Alexander Afanasyev8b1674a2014-05-15 00:58:43 -070060 setenv("TEST_HOME", "tests/unit-tests/security/config-file-empty-home", 1);
Yingdi Yuf56c68f2014-04-24 21:50:13 -070061
Yingdi Yu41546342014-11-30 23:37:53 -080062#if defined(NDN_CXX_HAVE_OSX_SECURITY)
63 std::string oldHOME;
64 if (std::getenv("OLD_HOME"))
65 oldHOME = std::getenv("OLD_HOME");
66
67 std::string HOME;
68 if (std::getenv("HOME"))
69 HOME = std::getenv("HOME");
70
71 if (!oldHOME.empty())
72 setenv("HOME", oldHOME.c_str(), 1);
73 else
74 unsetenv("HOME");
75#endif
76
77 BOOST_REQUIRE_NO_THROW(KeyChain());
Alexander Afanasyev07113802015-01-15 19:14:36 -080078 KeyChain keyChain;
79 BOOST_CHECK_EQUAL(keyChain.getPib().getPibLocator(),
80 "pib-sqlite3:/tmp/test/ndn-cxx/keychain/sqlite3-empty/");
81
82#if defined(NDN_CXX_HAVE_OSX_SECURITY)
83 BOOST_CHECK_EQUAL(keyChain.getPib().getTpmLocator(), "tpm-osxkeychain:");
84 BOOST_CHECK_EQUAL(keyChain.getTpm().getTpmLocator(), "tpm-osxkeychain:");
85#else
86 BOOST_CHECK_EQUAL(keyChain.getPib().getTpmLocator(),
87 "tpm-file:");
88 BOOST_CHECK_EQUAL(keyChain.getTpm().getTpmLocator(),
89 "tpm-file:");
90#endif
Yingdi Yu41546342014-11-30 23:37:53 -080091
92#if defined(NDN_CXX_HAVE_OSX_SECURITY)
93 if (!HOME.empty())
94 setenv("HOME", HOME.c_str(), 1);
95 else
96 unsetenv("HOME");
97#endif
98
99 path pibPath(absolute(std::getenv("TEST_HOME")));
100 pibPath /= ".ndn/ndnsec-public-info.db";
101
102 boost::filesystem::remove(pibPath);
103}
104
105BOOST_AUTO_TEST_CASE(ConstructorEmpty2Config)
106{
107 using namespace boost::filesystem;
108
109 setenv("TEST_HOME", "tests/unit-tests/security/config-file-empty2-home", 1);
110
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700111 BOOST_REQUIRE_NO_THROW(KeyChain());
112
Alexander Afanasyev07113802015-01-15 19:14:36 -0800113 KeyChain keyChain;
114 BOOST_CHECK_EQUAL(keyChain.getPib().getPibLocator(),
115 "pib-sqlite3:");
116 BOOST_CHECK_EQUAL(keyChain.getPib().getTpmLocator(),
117 "tpm-file:/tmp/test/ndn-cxx/keychain/empty-file/");
118 BOOST_CHECK_EQUAL(keyChain.getTpm().getTpmLocator(),
119 "tpm-file:/tmp/test/ndn-cxx/keychain/empty-file/");
120
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700121 path pibPath(absolute(std::getenv("TEST_HOME")));
122 pibPath /= ".ndn/ndnsec-public-info.db";
123
124 boost::filesystem::remove(pibPath);
125}
126
127BOOST_AUTO_TEST_CASE(ConstructorMalConfig)
128{
129 using namespace boost::filesystem;
130
Alexander Afanasyev8b1674a2014-05-15 00:58:43 -0700131 setenv("TEST_HOME", "tests/unit-tests/security/config-file-malformed-home", 1);
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700132
133 BOOST_REQUIRE_THROW(KeyChain(), KeyChain::Error); // Wrong configuration. Error expected.
134}
135
136BOOST_AUTO_TEST_CASE(ConstructorMal2Config)
137{
138 using namespace boost::filesystem;
139
Alexander Afanasyev8b1674a2014-05-15 00:58:43 -0700140 setenv("TEST_HOME", "tests/unit-tests/security/config-file-malformed2-home", 1);
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700141
142 BOOST_REQUIRE_THROW(KeyChain(), KeyChain::Error); // Wrong configuration. Error expected.
143}
144
145BOOST_AUTO_TEST_CASE(ExportIdentity)
146{
Yingdi Yu41546342014-11-30 23:37:53 -0800147 KeyChain keyChain;
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800148
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700149 Name identity("/TestKeyChain/ExportIdentity/");
150 identity.appendVersion();
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800151 keyChain.createIdentity(identity);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700152
Yingdi Yu64c3fb42014-02-26 17:30:04 -0800153 shared_ptr<SecuredBag> exported = keyChain.exportIdentity(identity, "1234");
154
155 Block block = exported->wireEncode();
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800156
157 Name keyName = keyChain.getDefaultKeyNameForIdentity(identity);
158 Name certName = keyChain.getDefaultCertificateNameForKey(keyName);
159
160 keyChain.deleteIdentity(identity);
161
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700162 BOOST_CHECK_EQUAL(keyChain.doesIdentityExist(identity), false);
163 BOOST_CHECK_EQUAL(keyChain.doesPublicKeyExist(keyName), false);
164 BOOST_CHECK_EQUAL(keyChain.doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE), false);
165 BOOST_CHECK_EQUAL(keyChain.doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC), false);
166 BOOST_CHECK_EQUAL(keyChain.doesCertificateExist(certName), false);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800167
Yingdi Yu64c3fb42014-02-26 17:30:04 -0800168 SecuredBag imported;
169 imported.wireDecode(block);
170 keyChain.importIdentity(imported, "1234");
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800171
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700172 BOOST_CHECK(keyChain.doesIdentityExist(identity));
173 BOOST_CHECK(keyChain.doesPublicKeyExist(keyName));
174 BOOST_CHECK(keyChain.doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE));
175 BOOST_CHECK(keyChain.doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC));
176 BOOST_CHECK(keyChain.doesCertificateExist(certName));
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800177
178 keyChain.deleteIdentity(identity);
179
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700180 BOOST_CHECK_EQUAL(keyChain.doesIdentityExist(identity), false);
181 BOOST_CHECK_EQUAL(keyChain.doesPublicKeyExist(keyName), false);
182 BOOST_CHECK_EQUAL(keyChain.doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE), false);
183 BOOST_CHECK_EQUAL(keyChain.doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC), false);
184 BOOST_CHECK_EQUAL(keyChain.doesCertificateExist(certName), false);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800185}
186
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700187BOOST_AUTO_TEST_CASE(PrepareIdentityCertificate)
Yingdi Yuc55680b2014-02-26 12:31:35 -0800188{
Yingdi Yu41546342014-11-30 23:37:53 -0800189 KeyChain keyChain;
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700190
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700191 Name identity("/TestKeyChain/PrepareIdentityCertificate/");
192 identity.appendVersion();
Yingdi Yuc55680b2014-02-26 12:31:35 -0800193 keyChain.createIdentity(identity);
194
Junxiao Shi8ca43252015-06-11 21:29:43 -0700195 std::vector<CertificateSubjectDescription> subjectDescription;
Yingdi Yuc55680b2014-02-26 12:31:35 -0800196 Name lowerIdentity = identity;
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700197 lowerIdentity.append("Lower").appendVersion();
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700198 Name lowerKeyName = keyChain.generateRsaKeyPair(lowerIdentity, true);
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700199 shared_ptr<IdentityCertificate> idCert =
200 keyChain.prepareUnsignedIdentityCertificate(lowerKeyName, identity,
201 time::system_clock::now(),
202 time::system_clock::now() + time::days(365),
203 subjectDescription);
Yingdi Yuc55680b2014-02-26 12:31:35 -0800204 BOOST_CHECK(static_cast<bool>(idCert));
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700205 BOOST_CHECK_EQUAL(idCert->getName().getPrefix(5),
206 Name().append(identity).append("KEY").append("Lower"));
Junxiao Shi8ca43252015-06-11 21:29:43 -0700207 BOOST_CHECK(idCert->getFreshnessPeriod() >= time::milliseconds::zero());
Yingdi Yuc55680b2014-02-26 12:31:35 -0800208
Yingdi Yu0eb5d722014-06-10 15:06:25 -0700209 shared_ptr<IdentityCertificate> idCert11 =
210 keyChain.prepareUnsignedIdentityCertificate(lowerKeyName, identity,
211 time::system_clock::now(),
212 time::system_clock::now() + time::days(365),
213 subjectDescription,
214 lowerIdentity);
215 BOOST_CHECK(static_cast<bool>(idCert11));
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700216 BOOST_CHECK_EQUAL(idCert11->getName().getPrefix(6),
Yingdi Yu0eb5d722014-06-10 15:06:25 -0700217 Name().append(lowerIdentity).append("KEY"));
Yingdi Yuc55680b2014-02-26 12:31:35 -0800218
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700219 Name anotherIdentity("/TestKeyChain/PrepareIdentityCertificate/Another/");
220 anotherIdentity.appendVersion();
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700221 Name anotherKeyName = keyChain.generateRsaKeyPair(anotherIdentity, true);
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700222 shared_ptr<IdentityCertificate> idCert2 =
223 keyChain.prepareUnsignedIdentityCertificate(anotherKeyName, identity,
224 time::system_clock::now(),
225 time::system_clock::now() + time::days(365),
226 subjectDescription);
Yingdi Yuc55680b2014-02-26 12:31:35 -0800227 BOOST_CHECK(static_cast<bool>(idCert2));
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700228 BOOST_CHECK_EQUAL(idCert2->getName().getPrefix(5), Name().append(anotherIdentity).append("KEY"));
Yingdi Yuc55680b2014-02-26 12:31:35 -0800229
230
231 Name wrongKeyName1;
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700232 shared_ptr<IdentityCertificate> idCert3 =
233 keyChain.prepareUnsignedIdentityCertificate(wrongKeyName1, identity,
234 time::system_clock::now(),
235 time::system_clock::now() + time::days(365),
236 subjectDescription);
237 BOOST_CHECK_EQUAL(static_cast<bool>(idCert3), false);
Yingdi Yuc55680b2014-02-26 12:31:35 -0800238
239
240 Name wrongKeyName2("/TestKeyChain/PrepareIdentityCertificate");
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700241 shared_ptr<IdentityCertificate> idCert4 =
242 keyChain.prepareUnsignedIdentityCertificate(wrongKeyName2, identity,
243 time::system_clock::now(),
244 time::system_clock::now() + time::days(365),
245 subjectDescription);
246 BOOST_CHECK_EQUAL(static_cast<bool>(idCert4), false);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700247
Yingdi Yuc55680b2014-02-26 12:31:35 -0800248
249 Name wrongKeyName3("/TestKeyChain/PrepareIdentityCertificate/ksk-1234");
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700250 shared_ptr<IdentityCertificate> idCert5 =
251 keyChain.prepareUnsignedIdentityCertificate(wrongKeyName3, identity,
252 time::system_clock::now(),
253 time::system_clock::now() + time::days(365),
254 subjectDescription);
255 BOOST_CHECK_EQUAL(static_cast<bool>(idCert5), false);
Yingdi Yuc55680b2014-02-26 12:31:35 -0800256
257 keyChain.deleteIdentity(identity);
258 keyChain.deleteIdentity(lowerIdentity);
259 keyChain.deleteIdentity(anotherIdentity);
260}
261
Yingdi Yu41546342014-11-30 23:37:53 -0800262BOOST_AUTO_TEST_CASE(Delete)
263{
264 KeyChain keyChain;
265
266 Name identity("/TestSecPublicInfoSqlite3/Delete");
267 identity.appendVersion();
268
269 Name certName1;
270 BOOST_REQUIRE_NO_THROW(certName1 = keyChain.createIdentity(identity));
271
272 Name keyName1 = IdentityCertificate::certificateNameToPublicKeyName(certName1);
273 Name keyName2;
274 BOOST_REQUIRE_NO_THROW(keyName2 = keyChain.generateRsaKeyPairAsDefault(identity));
275
276 shared_ptr<IdentityCertificate> cert2;
277 BOOST_REQUIRE_NO_THROW(cert2 = keyChain.selfSign(keyName2));
278 Name certName2 = cert2->getName();
279 BOOST_REQUIRE_NO_THROW(keyChain.addCertificateAsKeyDefault(*cert2));
280
281 Name keyName3;
282 BOOST_REQUIRE_NO_THROW(keyName3 = keyChain.generateRsaKeyPairAsDefault(identity));
283
284 shared_ptr<IdentityCertificate> cert3;
285 BOOST_REQUIRE_NO_THROW(cert3 = keyChain.selfSign(keyName3));
286 Name certName3 = cert3->getName();
287 BOOST_REQUIRE_NO_THROW(keyChain.addCertificateAsKeyDefault(*cert3));
288 shared_ptr<IdentityCertificate> cert4;
289 BOOST_REQUIRE_NO_THROW(cert4 = keyChain.selfSign(keyName3));
290 Name certName4 = cert4->getName();
291 BOOST_REQUIRE_NO_THROW(keyChain.addCertificateAsKeyDefault(*cert4));
292 shared_ptr<IdentityCertificate> cert5;
293 BOOST_REQUIRE_NO_THROW(cert5 = keyChain.selfSign(keyName3));
294 Name certName5 = cert5->getName();
295 BOOST_REQUIRE_NO_THROW(keyChain.addCertificateAsKeyDefault(*cert5));
296
297 BOOST_CHECK_EQUAL(keyChain.doesIdentityExist(identity), true);
298 BOOST_CHECK_EQUAL(keyChain.doesPublicKeyExist(keyName1), true);
299 BOOST_CHECK_EQUAL(keyChain.doesPublicKeyExist(keyName2), true);
300 BOOST_CHECK_EQUAL(keyChain.doesPublicKeyExist(keyName3), true);
301 BOOST_CHECK_EQUAL(keyChain.doesCertificateExist(certName1), true);
302 BOOST_CHECK_EQUAL(keyChain.doesCertificateExist(certName2), true);
303 BOOST_CHECK_EQUAL(keyChain.doesCertificateExist(certName3), true);
304 BOOST_CHECK_EQUAL(keyChain.doesCertificateExist(certName4), true);
305 BOOST_CHECK_EQUAL(keyChain.doesCertificateExist(certName5), true);
306
307 BOOST_REQUIRE_NO_THROW(keyChain.deleteCertificate(certName5));
308 BOOST_CHECK_EQUAL(keyChain.doesCertificateExist(certName5), false);
309 BOOST_CHECK_EQUAL(keyChain.doesCertificateExist(certName3), true);
310 BOOST_CHECK_EQUAL(keyChain.doesCertificateExist(certName4), true);
311 BOOST_CHECK_EQUAL(keyChain.doesPublicKeyExist(keyName3), true);
312
313 BOOST_REQUIRE_NO_THROW(keyChain.deleteKey(keyName3));
314 BOOST_CHECK_EQUAL(keyChain.doesCertificateExist(certName4), false);
315 BOOST_CHECK_EQUAL(keyChain.doesCertificateExist(certName3), false);
316 BOOST_CHECK_EQUAL(keyChain.doesPublicKeyExist(keyName3), false);
317 BOOST_CHECK_EQUAL(keyChain.doesPublicKeyExist(keyName2), true);
318 BOOST_CHECK_EQUAL(keyChain.doesPublicKeyExist(keyName1), true);
319 BOOST_CHECK_EQUAL(keyChain.doesIdentityExist(identity), true);
320
321 BOOST_REQUIRE_NO_THROW(keyChain.deleteIdentity(identity));
322 BOOST_CHECK_EQUAL(keyChain.doesCertificateExist(certName2), false);
323 BOOST_CHECK_EQUAL(keyChain.doesPublicKeyExist(keyName2), false);
324 BOOST_CHECK_EQUAL(keyChain.doesCertificateExist(certName1), false);
325 BOOST_CHECK_EQUAL(keyChain.doesPublicKeyExist(keyName1), false);
326 BOOST_CHECK_EQUAL(keyChain.doesIdentityExist(identity), false);
327}
328
Alexander Afanasyev07113802015-01-15 19:14:36 -0800329BOOST_AUTO_TEST_CASE(KeyChainWithCustomTpmAndPib)
330{
331 BOOST_REQUIRE_NO_THROW((KeyChain("pib-dummy", "tpm-dummy")));
Alexander Afanasyev34a37632015-01-16 17:37:36 -0800332 BOOST_REQUIRE_NO_THROW((KeyChain("pib-dummy2", "tpm-dummy2")));
Alexander Afanasyev07113802015-01-15 19:14:36 -0800333 BOOST_REQUIRE_NO_THROW((KeyChain("dummy", "dummy")));
334 BOOST_REQUIRE_NO_THROW((KeyChain("dummy:", "dummy:")));
335 BOOST_REQUIRE_NO_THROW((KeyChain("dummy:/something", "dummy:/something")));
336
337 KeyChain keyChain("dummy", "dummy");
Alexander Afanasyev34a37632015-01-16 17:37:36 -0800338 BOOST_CHECK_EQUAL(keyChain.getPib().getPibLocator(), "pib-dummy:");
339 BOOST_CHECK_EQUAL(keyChain.getPib().getTpmLocator(), "tpm-dummy:");
340 BOOST_CHECK_EQUAL(keyChain.getTpm().getTpmLocator(), "tpm-dummy:");
Alexander Afanasyev07113802015-01-15 19:14:36 -0800341 BOOST_CHECK_EQUAL(keyChain.getDefaultIdentity(), "/dummy/key");
342}
343
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800344BOOST_AUTO_TEST_SUITE_END()
345
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700346} // namespace tests
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800347} // namespace ndn