blob: b6dd0c6c392f50b804687b8e0e2b2f24159a9487 [file] [log] [blame]
Yingdi Yufe4733a2015-10-22 14:24:12 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Davide Pesavento82d6a4c2017-12-23 19:47:20 -05002/*
Eric Newberrya3c8bd12020-05-15 17:27:07 -07003 * Copyright (c) 2013-2020 Regents of the University of California.
Yingdi Yufe4733a2015-10-22 14:24:12 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6 *
7 * 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.
20 */
21
Alexander Afanasyev09236c22020-06-03 13:42:38 -040022#include "ndn-cxx/security/key-chain.hpp"
Davide Pesavento7e780642018-11-24 15:51:34 -050023#include "ndn-cxx/security/signing-helpers.hpp"
24#include "ndn-cxx/security/verification-helpers.hpp"
laqinfan56a812d2019-06-03 15:33:58 -050025#include "ndn-cxx/security/transform/private-key.hpp"
Yingdi Yufe4733a2015-10-22 14:24:12 -070026
Davide Pesavento7e780642018-11-24 15:51:34 -050027#include "tests/boost-test.hpp"
28#include "tests/identity-management-fixture.hpp"
29#include "tests/unit/test-home-env-saver.hpp"
Yingdi Yufe4733a2015-10-22 14:24:12 -070030
31namespace ndn {
32namespace security {
Alexander Afanasyev09236c22020-06-03 13:42:38 -040033inline namespace v2 {
Yingdi Yufe4733a2015-10-22 14:24:12 -070034namespace tests {
35
36using namespace ndn::tests;
37
38BOOST_AUTO_TEST_SUITE(Security)
Yingdi Yufe4733a2015-10-22 14:24:12 -070039BOOST_FIXTURE_TEST_SUITE(TestKeyChain, TestHomeEnvSaver)
40
41template<class Path>
42class TestHomeAndPibFixture : public TestHomeFixture<Path>
43{
44public:
45 TestHomeAndPibFixture()
46 {
47 unsetenv("NDN_CLIENT_PIB");
48 unsetenv("NDN_CLIENT_TPM");
49 }
Alexander Afanasyev80782e02017-01-04 13:16:54 -080050
51 ~TestHomeAndPibFixture()
52 {
Alexander Afanasyev57d02b62018-06-15 18:19:50 -040053 try {
54 const_cast<std::string&>(KeyChain::getDefaultPibLocator()).clear();
55 }
56 catch (const KeyChain::Error&) {
57 // ignore
58 }
59
60 try {
61 const_cast<std::string&>(KeyChain::getDefaultTpmLocator()).clear();
62 }
63 catch (const KeyChain::Error&) {
64 // ignore
65 }
Alexander Afanasyev80782e02017-01-04 13:16:54 -080066 }
Yingdi Yufe4733a2015-10-22 14:24:12 -070067};
68
69struct PibPathConfigFileHome
70{
71 const std::string PATH = "build/config-file-home/";
72};
73
74BOOST_FIXTURE_TEST_CASE(ConstructorNormalConfig, TestHomeAndPibFixture<PibPathConfigFileHome>)
75{
76 createClientConf({"pib=pib-memory:", "tpm=tpm-memory:"});
77
78 BOOST_REQUIRE_NO_THROW(KeyChain());
79
80 KeyChain keyChain;
81 BOOST_CHECK_EQUAL(keyChain.getPib().getPibLocator(), "pib-memory:");
82 BOOST_CHECK_EQUAL(keyChain.getPib().getTpmLocator(), "tpm-memory:");
83 BOOST_CHECK_EQUAL(keyChain.getTpm().getTpmLocator(), "tpm-memory:");
84}
85
86struct PibPathConfigFileEmptyHome
87{
88 const std::string PATH = "build/config-file-empty-home/";
89};
90
91BOOST_FIXTURE_TEST_CASE(ConstructorEmptyConfig, TestHomeAndPibFixture<PibPathConfigFileEmptyHome>)
92{
93 createClientConf({"pib=pib-memory:"});
94
Alexander Afanasyev0cf887d2017-03-26 16:58:59 -050095#if defined(NDN_CXX_HAVE_OSX_FRAMEWORKS)
Yingdi Yufe4733a2015-10-22 14:24:12 -070096 std::string oldHOME;
97 if (std::getenv("OLD_HOME"))
98 oldHOME = std::getenv("OLD_HOME");
99
100 std::string HOME;
101 if (std::getenv("HOME"))
102 HOME = std::getenv("HOME");
103
104 if (!oldHOME.empty())
105 setenv("HOME", oldHOME.c_str(), 1);
106 else
107 unsetenv("HOME");
108#endif
109
110 BOOST_REQUIRE_NO_THROW(KeyChain());
111 KeyChain keyChain;
112 BOOST_CHECK_EQUAL(keyChain.getPib().getPibLocator(), "pib-memory:");
113
Alexander Afanasyev0cf887d2017-03-26 16:58:59 -0500114#if defined(NDN_CXX_HAVE_OSX_FRAMEWORKS)
Yingdi Yufe4733a2015-10-22 14:24:12 -0700115 BOOST_CHECK_EQUAL(keyChain.getPib().getTpmLocator(), "tpm-osxkeychain:");
116 BOOST_CHECK_EQUAL(keyChain.getTpm().getTpmLocator(), "tpm-osxkeychain:");
117#else
118 BOOST_CHECK_EQUAL(keyChain.getPib().getTpmLocator(), "tpm-file:");
119 BOOST_CHECK_EQUAL(keyChain.getTpm().getTpmLocator(), "tpm-file:");
120#endif
121
Alexander Afanasyev0cf887d2017-03-26 16:58:59 -0500122#if defined(NDN_CXX_HAVE_OSX_FRAMEWORKS)
Yingdi Yufe4733a2015-10-22 14:24:12 -0700123 if (!HOME.empty())
124 setenv("HOME", HOME.c_str(), 1);
125 else
126 unsetenv("HOME");
127
128 if (!oldHOME.empty())
129 setenv("OLD_HOME", oldHOME.c_str(), 1);
130 else
131 unsetenv("OLD_HOME");
132#endif
133}
134
135struct PibPathConfigFileEmpty2Home
136{
137 const std::string PATH = "build/config-file-empty2-home/";
138};
139
140BOOST_FIXTURE_TEST_CASE(ConstructorEmpty2Config, TestHomeAndPibFixture<PibPathConfigFileEmpty2Home>)
141{
142 createClientConf({"tpm=tpm-memory:"});
143
144 BOOST_REQUIRE_NO_THROW(KeyChain());
145
146 KeyChain keyChain;
147 BOOST_CHECK_EQUAL(keyChain.getPib().getPibLocator(), "pib-sqlite3:");
148 BOOST_CHECK_EQUAL(keyChain.getPib().getTpmLocator(), "tpm-memory:");
149 BOOST_CHECK_EQUAL(keyChain.getTpm().getTpmLocator(), "tpm-memory:");
150}
151
152struct PibPathConfigFileMalformedHome
153{
154 const std::string PATH = "build/config-file-malformed-home/";
155};
156
157BOOST_FIXTURE_TEST_CASE(ConstructorMalConfig, TestHomeAndPibFixture<PibPathConfigFileMalformedHome>)
158{
159 createClientConf({"pib=lord", "tpm=ring"});
160
161 BOOST_REQUIRE_THROW(KeyChain(), KeyChain::Error); // Wrong configuration. Error expected.
162}
163
164struct PibPathConfigFileMalformed2Home
165{
166 const std::string PATH = "build/config-file-malformed2-home/";
167};
168
169BOOST_FIXTURE_TEST_CASE(ConstructorMal2Config, TestHomeAndPibFixture<PibPathConfigFileMalformed2Home>)
170{
171 createClientConf({"pib=pib-sqlite3:%PATH%", "tpm=just-wrong"});
172
173 BOOST_REQUIRE_THROW(KeyChain(), KeyChain::Error); // Wrong configuration. Error expected.
174}
175
Alexander Afanasyev57d02b62018-06-15 18:19:50 -0400176struct PibPathConfigFileNonCanonicalTpm
177{
178 const std::string PATH = "build/config-file-non-canonical-tpm/";
179};
180
181BOOST_FIXTURE_TEST_CASE(ConstructorNonCanonicalTpm, TestHomeAndPibFixture<PibPathConfigFileNonCanonicalTpm>) // Bug 4297
182{
183 createClientConf({"pib=pib-sqlite3:", "tpm=tpm-file"});
184
185 {
186 KeyChain keyChain;
187 keyChain.createIdentity("/test");
188 BOOST_CHECK_EQUAL(keyChain.getPib().getPibLocator(), "pib-sqlite3:");
189 BOOST_CHECK_EQUAL(keyChain.getTpm().getTpmLocator(), "tpm-file:");
190 }
191
192 {
193 KeyChain keyChain;
194 BOOST_CHECK_EQUAL(keyChain.getPib().getPibLocator(), "pib-sqlite3:");
195 BOOST_CHECK_EQUAL(keyChain.getTpm().getTpmLocator(), "tpm-file:");
196 BOOST_CHECK(keyChain.getPib().getIdentities().find("/test") != keyChain.getPib().getIdentities().end());
197 }
198}
199
Yingdi Yufe4733a2015-10-22 14:24:12 -0700200BOOST_AUTO_TEST_CASE(KeyChainWithCustomTpmAndPib)
201{
202 BOOST_REQUIRE_NO_THROW((KeyChain("pib-memory", "tpm-memory")));
203 BOOST_REQUIRE_NO_THROW((KeyChain("pib-memory:", "tpm-memory:")));
204 BOOST_REQUIRE_NO_THROW((KeyChain("pib-memory:/something", "tpm-memory:/something")));
205
206 KeyChain keyChain("pib-memory", "tpm-memory");
207 BOOST_CHECK_EQUAL(keyChain.getPib().getPibLocator(), "pib-memory:");
208 BOOST_CHECK_EQUAL(keyChain.getPib().getTpmLocator(), "tpm-memory:");
209 BOOST_CHECK_EQUAL(keyChain.getTpm().getTpmLocator(), "tpm-memory:");
210}
211
Alexander Afanasyevf601e192020-06-02 16:41:07 -0400212BOOST_FIXTURE_TEST_CASE(SigningWithCorruptedPibTpm, IdentityManagementFixture)
213{
214 Identity id = m_keyChain.createIdentity("/test");
215
216 Data data("/foobar");
217 BOOST_CHECK_NO_THROW(m_keyChain.sign(data, signingByIdentity(id)));
218
219 // now, "corrupting TPM"
220 const_cast<Tpm&>(m_keyChain.getTpm()).deleteKey(id.getDefaultKey().getName());
221
222 BOOST_CHECK_NO_THROW(id.getDefaultKey());
223 BOOST_CHECK_THROW(m_keyChain.sign(data, signingByIdentity(id)), KeyChain::InvalidSigningInfoError);
224}
225
Yingdi Yufe4733a2015-10-22 14:24:12 -0700226BOOST_FIXTURE_TEST_CASE(Management, IdentityManagementFixture)
227{
228 Name identityName("/test/id");
229 Name identity2Name("/test/id2");
230
231 BOOST_CHECK_EQUAL(m_keyChain.getPib().getIdentities().size(), 0);
232 BOOST_REQUIRE_THROW(m_keyChain.getPib().getDefaultIdentity(), Pib::Error);
233
234 // Create identity
235 Identity id = m_keyChain.createIdentity(identityName);
236 BOOST_CHECK(id);
237 BOOST_CHECK(m_keyChain.getPib().getIdentities().find(identityName) != m_keyChain.getPib().getIdentities().end());
238 // The first added identity becomes the default identity
laqinfan56a812d2019-06-03 15:33:58 -0500239 BOOST_CHECK_NO_THROW(m_keyChain.getPib().getDefaultIdentity());
Yingdi Yufe4733a2015-10-22 14:24:12 -0700240 // The default key of the added identity must exist
laqinfan56a812d2019-06-03 15:33:58 -0500241 Key key = id.getDefaultKey();
Yingdi Yufe4733a2015-10-22 14:24:12 -0700242 // The default certificate of the default key must exist
laqinfan56a812d2019-06-03 15:33:58 -0500243 BOOST_CHECK_NO_THROW(key.getDefaultCertificate());
Yingdi Yufe4733a2015-10-22 14:24:12 -0700244
245 // Delete key
246 Name key1Name = key.getName();
247 BOOST_CHECK_NO_THROW(id.getKey(key1Name));
248 BOOST_CHECK_EQUAL(id.getKeys().size(), 1);
249 m_keyChain.deleteKey(id, key);
250 // The key instance should not be valid any more
251 BOOST_CHECK(!key);
252 BOOST_CHECK_THROW(id.getKey(key1Name), Pib::Error);
253 BOOST_CHECK_EQUAL(id.getKeys().size(), 0);
254
255 // Create another key
256 m_keyChain.createKey(id);
257 // The added key becomes the default key.
Yingdi Yufe4733a2015-10-22 14:24:12 -0700258 Key key2 = id.getDefaultKey();
259 BOOST_REQUIRE(key2);
260 BOOST_CHECK_NE(key2.getName(), key1Name);
261 BOOST_CHECK_EQUAL(id.getKeys().size(), 1);
laqinfan56a812d2019-06-03 15:33:58 -0500262 BOOST_CHECK_NO_THROW(key2.getDefaultCertificate());
Yingdi Yufe4733a2015-10-22 14:24:12 -0700263
264 // Create the third key
265 Key key3 = m_keyChain.createKey(id);
Junxiao Shi72c0c642018-04-20 15:41:09 +0000266 BOOST_CHECK_NE(key3.getName(), key2.getName());
Yingdi Yufe4733a2015-10-22 14:24:12 -0700267 // The added key will not be the default key, because the default key already exists
Junxiao Shi72c0c642018-04-20 15:41:09 +0000268 BOOST_CHECK_EQUAL(id.getDefaultKey().getName(), key2.getName());
Yingdi Yufe4733a2015-10-22 14:24:12 -0700269 BOOST_CHECK_EQUAL(id.getKeys().size(), 2);
laqinfan56a812d2019-06-03 15:33:58 -0500270 BOOST_CHECK_NO_THROW(key3.getDefaultCertificate());
Yingdi Yufe4733a2015-10-22 14:24:12 -0700271
272 // Delete cert
273 BOOST_CHECK_EQUAL(key3.getCertificates().size(), 1);
274 Certificate key3Cert1 = *key3.getCertificates().begin();
275 Name key3CertName = key3Cert1.getName();
276 m_keyChain.deleteCertificate(key3, key3CertName);
277 BOOST_CHECK_EQUAL(key3.getCertificates().size(), 0);
278 BOOST_REQUIRE_THROW(key3.getDefaultCertificate(), Pib::Error);
279
280 // Add cert
281 m_keyChain.addCertificate(key3, key3Cert1);
282 BOOST_CHECK_EQUAL(key3.getCertificates().size(), 1);
laqinfan56a812d2019-06-03 15:33:58 -0500283 BOOST_CHECK_NO_THROW(key3.getDefaultCertificate());
Alexander Afanasyeva10b2ff2017-01-30 12:44:15 -0800284 m_keyChain.addCertificate(key3, key3Cert1); // overwriting the cert should work
Yingdi Yufe4733a2015-10-22 14:24:12 -0700285 BOOST_CHECK_EQUAL(key3.getCertificates().size(), 1);
286 // Add another cert
287 Certificate key3Cert2 = key3Cert1;
288 Name key3Cert2Name = key3.getName();
289 key3Cert2Name.append("Self");
290 key3Cert2Name.appendVersion();
291 key3Cert2.setName(key3Cert2Name);
292 m_keyChain.addCertificate(key3, key3Cert2);
293 BOOST_CHECK_EQUAL(key3.getCertificates().size(), 2);
Davide Pesavento81bd6962020-06-17 16:03:23 -0400294 // Add empty cert
295 Certificate key3Cert3 = key3Cert1;
296 key3Cert3.unsetContent();
297 BOOST_CHECK_THROW(m_keyChain.addCertificate(key3, key3Cert3), std::invalid_argument);
Yingdi Yufe4733a2015-10-22 14:24:12 -0700298
299 // Default certificate setting
300 BOOST_CHECK_EQUAL(key3.getDefaultCertificate().getName(), key3CertName);
301 m_keyChain.setDefaultCertificate(key3, key3Cert2);
302 BOOST_CHECK_EQUAL(key3.getDefaultCertificate().getName(), key3Cert2Name);
303
304 // Default key setting
305 BOOST_CHECK_EQUAL(id.getDefaultKey().getName(), key2.getName());
306 m_keyChain.setDefaultKey(id, key3);
307 BOOST_CHECK_EQUAL(id.getDefaultKey().getName(), key3.getName());
308
309 // Default identity setting
310 Identity id2 = m_keyChain.createIdentity(identity2Name);
311 BOOST_CHECK_EQUAL(m_keyChain.getPib().getDefaultIdentity().getName(), id.getName());
312 m_keyChain.setDefaultIdentity(id2);
313 BOOST_CHECK_EQUAL(m_keyChain.getPib().getDefaultIdentity().getName(), id2.getName());
314
315 // Delete identity
316 m_keyChain.deleteIdentity(id);
317 // The identity instance should not be valid any more
318 BOOST_CHECK(!id);
319 BOOST_REQUIRE_THROW(m_keyChain.getPib().getIdentity(identityName), Pib::Error);
320 BOOST_CHECK(m_keyChain.getPib().getIdentities().find(identityName) == m_keyChain.getPib().getIdentities().end());
321}
322
323BOOST_FIXTURE_TEST_CASE(GeneralSigningInterface, IdentityManagementFixture)
324{
325 Identity id = addIdentity("/id");
326 Key key = id.getDefaultKey();
327 Certificate cert = key.getDefaultCertificate();
328
laqinfan56a812d2019-06-03 15:33:58 -0500329 Name hmacKeyName = m_keyChain.createHmacKey();
330 const Tpm& tpm = m_keyChain.getTpm();
331
332 std::vector<SigningInfo> signingInfos = {
Eric Newberryb74bbda2020-06-18 19:33:58 -0700333 // New signed Interest format
334 SigningInfo().setSignedInterestFormat(SignedInterestFormat::V03),
335
336 SigningInfo(SigningInfo::SIGNER_TYPE_ID, id.getName())
337 .setSignedInterestFormat(SignedInterestFormat::V03),
338 signingByIdentity(id.getName()).setSignedInterestFormat(SignedInterestFormat::V03),
339
340 SigningInfo(id).setSignedInterestFormat(SignedInterestFormat::V03),
341 signingByIdentity(id).setSignedInterestFormat(SignedInterestFormat::V03),
342
343 SigningInfo(SigningInfo::SIGNER_TYPE_KEY, key.getName())
344 .setSignedInterestFormat(SignedInterestFormat::V03),
345 signingByKey(key.getName()).setSignedInterestFormat(SignedInterestFormat::V03),
346
347 SigningInfo(key).setSignedInterestFormat(SignedInterestFormat::V03),
348 signingByKey(key).setSignedInterestFormat(SignedInterestFormat::V03),
349
350 SigningInfo(SigningInfo::SIGNER_TYPE_CERT, cert.getName())
351 .setSignedInterestFormat(SignedInterestFormat::V03),
352 signingByCertificate(cert.getName()).setSignedInterestFormat(SignedInterestFormat::V03),
353 signingByCertificate(cert).setSignedInterestFormat(SignedInterestFormat::V03),
354
355 SigningInfo(SigningInfo::SIGNER_TYPE_HMAC, hmacKeyName)
356 .setSignedInterestFormat(SignedInterestFormat::V03),
357 SigningInfo("hmac-sha256:QjM3NEEyNkE3MTQ5MDQzN0FBMDI0RTRGQURENUI0OTdGREZGMUE4RUE2RkYxMkY2RkI2NUFGMjcyMEI1OUNDRg==")
358 .setSignedInterestFormat(SignedInterestFormat::V03),
359
360 SigningInfo(SigningInfo::SIGNER_TYPE_SHA256)
361 .setSignedInterestFormat(SignedInterestFormat::V03),
362 signingWithSha256().setSignedInterestFormat(SignedInterestFormat::V03),
363
364 // Deprecated signed Interest format
Yingdi Yufe4733a2015-10-22 14:24:12 -0700365 SigningInfo(),
366
367 SigningInfo(SigningInfo::SIGNER_TYPE_ID, id.getName()),
368 signingByIdentity(id.getName()),
369
Alexander Afanasyevd6d78aa2017-01-02 18:14:23 -0800370 SigningInfo(id),
371 signingByIdentity(id),
372
Yingdi Yufe4733a2015-10-22 14:24:12 -0700373 SigningInfo(SigningInfo::SIGNER_TYPE_KEY, key.getName()),
374 signingByKey(key.getName()),
375
Alexander Afanasyevd6d78aa2017-01-02 18:14:23 -0800376 SigningInfo(key),
377 signingByKey(key),
378
Yingdi Yufe4733a2015-10-22 14:24:12 -0700379 SigningInfo(SigningInfo::SIGNER_TYPE_CERT, cert.getName()),
380 signingByCertificate(cert.getName()),
Alexander Afanasyevd6d78aa2017-01-02 18:14:23 -0800381 signingByCertificate(cert),
Yingdi Yufe4733a2015-10-22 14:24:12 -0700382
laqinfan56a812d2019-06-03 15:33:58 -0500383 SigningInfo(SigningInfo::SIGNER_TYPE_HMAC, hmacKeyName),
384 SigningInfo("hmac-sha256:QjM3NEEyNkE3MTQ5MDQzN0FBMDI0RTRGQURENUI0OTdGREZGMUE4RUE2RkYxMkY2RkI2NUFGMjcyMEI1OUNDRg=="),
385
Yingdi Yufe4733a2015-10-22 14:24:12 -0700386 SigningInfo(SigningInfo::SIGNER_TYPE_SHA256),
387 signingWithSha256()
388 };
389
390 for (const auto& signingInfo : signingInfos) {
391 BOOST_TEST_MESSAGE("SigningInfo: " << signingInfo);
392 Data data("/data");
393 Interest interest("/interest");
Eric Newberryb74bbda2020-06-18 19:33:58 -0700394 interest.setCanBePrefix(false);
Yingdi Yufe4733a2015-10-22 14:24:12 -0700395
Eric Newberryb74bbda2020-06-18 19:33:58 -0700396 m_keyChain.sign(data, signingInfo);
397 m_keyChain.sign(interest, signingInfo);
Yingdi Yufe4733a2015-10-22 14:24:12 -0700398
399 if (signingInfo.getSignerType() == SigningInfo::SIGNER_TYPE_SHA256) {
Davide Pesavento14c56cd2020-05-21 01:44:03 -0400400 BOOST_CHECK_EQUAL(data.getSignatureType(), tlv::DigestSha256);
Eric Newberryb74bbda2020-06-18 19:33:58 -0700401
402 if (signingInfo.getSignedInterestFormat() == SignedInterestFormat::V03) {
403 BOOST_REQUIRE(interest.getSignatureInfo() != nullopt);
404 BOOST_CHECK_EQUAL(interest.getSignatureInfo()->getSignatureType(), tlv::DigestSha256);
405 }
406 else {
407 SignatureInfo sigInfo(interest.getName()[signed_interest::POS_SIG_INFO].blockFromValue());
408 BOOST_CHECK_EQUAL(sigInfo.getSignatureType(), tlv::DigestSha256);
409 }
Yingdi Yufe4733a2015-10-22 14:24:12 -0700410
Alexander Afanasyev574aa862017-01-10 19:53:28 -0800411 BOOST_CHECK(verifyDigest(data, DigestAlgorithm::SHA256));
412 BOOST_CHECK(verifyDigest(interest, DigestAlgorithm::SHA256));
Yingdi Yufe4733a2015-10-22 14:24:12 -0700413 }
laqinfan56a812d2019-06-03 15:33:58 -0500414 else if (signingInfo.getSignerType() == SigningInfo::SIGNER_TYPE_HMAC) {
415 Name keyName = signingInfo.getSignerName();
Davide Pesavento14c56cd2020-05-21 01:44:03 -0400416 BOOST_CHECK_EQUAL(data.getSignatureType(), tlv::SignatureHmacWithSha256);
laqinfan56a812d2019-06-03 15:33:58 -0500417
Eric Newberryb74bbda2020-06-18 19:33:58 -0700418 if (signingInfo.getSignedInterestFormat() == SignedInterestFormat::V03) {
419 BOOST_REQUIRE(interest.getSignatureInfo() != nullopt);
420 BOOST_CHECK_EQUAL(interest.getSignatureInfo()->getSignatureType(),
421 tlv::SignatureHmacWithSha256);
422 }
423 else {
424 SignatureInfo sigInfo(interest.getName()[signed_interest::POS_SIG_INFO].blockFromValue());
425 BOOST_CHECK_EQUAL(sigInfo.getSignatureType(), tlv::SignatureHmacWithSha256);
426 }
427
428 BOOST_CHECK(verifySignature(data, tpm, keyName, DigestAlgorithm::SHA256));
429 BOOST_CHECK(verifySignature(interest, tpm, keyName, DigestAlgorithm::SHA256));
laqinfan56a812d2019-06-03 15:33:58 -0500430 }
Yingdi Yufe4733a2015-10-22 14:24:12 -0700431 else {
Davide Pesavento14c56cd2020-05-21 01:44:03 -0400432 BOOST_CHECK_EQUAL(data.getSignatureType(), tlv::SignatureSha256WithEcdsa);
Eric Newberryb74bbda2020-06-18 19:33:58 -0700433
434 if (signingInfo.getSignedInterestFormat() == SignedInterestFormat::V03) {
435 BOOST_REQUIRE(interest.getSignatureInfo() != nullopt);
436 BOOST_CHECK_EQUAL(interest.getSignatureInfo()->getSignatureType(),
437 tlv::SignatureSha256WithEcdsa);
438 }
439 else {
440 SignatureInfo sigInfo(interest.getName()[signed_interest::POS_SIG_INFO].blockFromValue());
441 BOOST_CHECK_EQUAL(sigInfo.getSignatureType(), tlv::SignatureSha256WithEcdsa);
442 }
Yingdi Yufe4733a2015-10-22 14:24:12 -0700443
Davide Pesavento14c56cd2020-05-21 01:44:03 -0400444 BOOST_CHECK_EQUAL(data.getKeyLocator()->getName(), cert.getName().getPrefix(-2));
Eric Newberryb74bbda2020-06-18 19:33:58 -0700445
446 if (signingInfo.getSignedInterestFormat() == SignedInterestFormat::V03) {
447 BOOST_CHECK_EQUAL(interest.getSignatureInfo()->getKeyLocator().getName(),
448 cert.getName().getPrefix(-2));
449 }
450 else {
451 SignatureInfo sigInfo(interest.getName()[signed_interest::POS_SIG_INFO].blockFromValue());
452 BOOST_CHECK_EQUAL(sigInfo.getKeyLocator().getName(), cert.getName().getPrefix(-2));
453 }
Yingdi Yufe4733a2015-10-22 14:24:12 -0700454
Alexander Afanasyev574aa862017-01-10 19:53:28 -0800455 BOOST_CHECK(verifySignature(data, key));
456 BOOST_CHECK(verifySignature(interest, key));
Yingdi Yufe4733a2015-10-22 14:24:12 -0700457 }
458 }
459}
460
461BOOST_FIXTURE_TEST_CASE(PublicKeySigningDefaults, IdentityManagementFixture)
462{
463 Data data("/test/data");
464
465 // Identity will be created with generated key and self-signed cert with default parameters
466 BOOST_CHECK_THROW(m_keyChain.sign(data, signingByIdentity("/non-existing/identity")), KeyChain::InvalidSigningInfoError);
467
Spyridon Mastorakis1ece2e32015-08-27 18:52:21 -0700468 // Create identity with EC key and the corresponding self-signed certificate
469 Identity id = addIdentity("/ndn/test/ec", EcKeyParams());
Yingdi Yufe4733a2015-10-22 14:24:12 -0700470 BOOST_CHECK_NO_THROW(m_keyChain.sign(data, signingByIdentity(id.getName())));
Davide Pesavento14c56cd2020-05-21 01:44:03 -0400471 BOOST_CHECK_EQUAL(data.getSignatureType(),
Spyridon Mastorakis1ece2e32015-08-27 18:52:21 -0700472 KeyChain::getSignatureType(EcKeyParams().getKeyType(), DigestAlgorithm::SHA256));
Davide Pesavento14c56cd2020-05-21 01:44:03 -0400473 BOOST_REQUIRE(data.getKeyLocator().has_value());
474 BOOST_CHECK(id.getName().isPrefixOf(data.getKeyLocator()->getName()));
Yingdi Yufe4733a2015-10-22 14:24:12 -0700475
476 // Create identity with RSA key and the corresponding self-signed certificate
477 id = addIdentity("/ndn/test/rsa", RsaKeyParams());
478 BOOST_CHECK_NO_THROW(m_keyChain.sign(data, signingByIdentity(id.getName())));
Davide Pesavento14c56cd2020-05-21 01:44:03 -0400479 BOOST_CHECK_EQUAL(data.getSignatureType(),
Yingdi Yufe4733a2015-10-22 14:24:12 -0700480 KeyChain::getSignatureType(RsaKeyParams().getKeyType(), DigestAlgorithm::SHA256));
Davide Pesavento14c56cd2020-05-21 01:44:03 -0400481 BOOST_REQUIRE(data.getKeyLocator().has_value());
482 BOOST_CHECK(id.getName().isPrefixOf(data.getKeyLocator()->getName()));
Yingdi Yufe4733a2015-10-22 14:24:12 -0700483}
484
laqinfan56a812d2019-06-03 15:33:58 -0500485BOOST_FIXTURE_TEST_CASE(ImportPrivateKey, IdentityManagementFixture)
486{
487 Name keyName("/test/device2");
488 std::string rawKey("nPSNOHyZKsg2WLqHAs7MXGb0sjQb4zCT");
489 auto key = make_shared<transform::PrivateKey>();
490 key->loadRaw(KeyType::HMAC, reinterpret_cast<const uint8_t*>(rawKey.data()), rawKey.size());
491
492 m_keyChain.importPrivateKey(keyName, key);
493 BOOST_CHECK_EQUAL(m_keyChain.getTpm().hasKey(keyName), true);
494 BOOST_CHECK_THROW(m_keyChain.importPrivateKey(keyName, key), KeyChain::Error);
495}
496
Yingdi Yufe4733a2015-10-22 14:24:12 -0700497BOOST_FIXTURE_TEST_CASE(ExportImport, IdentityManagementFixture)
498{
laqinfan56a812d2019-06-03 15:33:58 -0500499 Identity id = addIdentity("/TestKeyChain/ExportIdentity");
Yingdi Yufe4733a2015-10-22 14:24:12 -0700500 Certificate cert = id.getDefaultKey().getDefaultCertificate();
501
502 shared_ptr<SafeBag> exported = m_keyChain.exportSafeBag(cert, "1234", 4);
503 Block block = exported->wireEncode();
504
505 m_keyChain.deleteIdentity(id);
Davide Pesavento82d6a4c2017-12-23 19:47:20 -0500506 BOOST_CHECK_THROW(m_keyChain.exportSafeBag(cert, "1234", 4), KeyChain::Error);
Yingdi Yufe4733a2015-10-22 14:24:12 -0700507
508 BOOST_CHECK_EQUAL(m_keyChain.getTpm().hasKey(cert.getKeyName()), false);
509 BOOST_CHECK_EQUAL(m_keyChain.getPib().getIdentities().size(), 0);
510
511 SafeBag imported;
512 imported.wireDecode(block);
513 m_keyChain.importSafeBag(imported, "1234", 4);
Davide Pesavento82d6a4c2017-12-23 19:47:20 -0500514 BOOST_CHECK_THROW(m_keyChain.importSafeBag(imported, "1234", 4), KeyChain::Error);
Yingdi Yufe4733a2015-10-22 14:24:12 -0700515
516 BOOST_CHECK_EQUAL(m_keyChain.getTpm().hasKey(cert.getKeyName()), true);
517 BOOST_CHECK_EQUAL(m_keyChain.getPib().getIdentities().size(), 1);
Yingdi Yufe4733a2015-10-22 14:24:12 -0700518 Identity newId = m_keyChain.getPib().getIdentity(cert.getIdentity());
519 BOOST_CHECK_EQUAL(newId.getKeys().size(), 1);
Yingdi Yufe4733a2015-10-22 14:24:12 -0700520 Key newKey = newId.getKey(cert.getKeyName());
521 BOOST_CHECK_EQUAL(newKey.getCertificates().size(), 1);
laqinfan56a812d2019-06-03 15:33:58 -0500522 BOOST_CHECK_NO_THROW(newKey.getCertificate(cert.getName()));
Yingdi Yufe4733a2015-10-22 14:24:12 -0700523
524 m_keyChain.deleteIdentity(newId);
525 BOOST_CHECK_EQUAL(m_keyChain.getPib().getIdentities().size(), 0);
526 BOOST_CHECK_EQUAL(m_keyChain.getTpm().hasKey(cert.getKeyName()), false);
527}
528
Alexander Afanasyevf8379172017-01-11 16:56:04 -0800529BOOST_FIXTURE_TEST_CASE(SelfSignedCertValidity, IdentityManagementFixture)
530{
Alexander Afanasyev09236c22020-06-03 13:42:38 -0400531 Certificate cert = addIdentity("/Security/TestKeyChain/SelfSignedCertValidity")
Alexander Afanasyevf8379172017-01-11 16:56:04 -0800532 .getDefaultKey()
533 .getDefaultCertificate();
534 BOOST_CHECK(cert.isValid());
Davide Pesavento0f830802018-01-16 23:58:58 -0500535 BOOST_CHECK(cert.isValid(time::system_clock::now() + 10 * 365_days));
536 BOOST_CHECK_GT(cert.getValidityPeriod().getPeriod().second, time::system_clock::now() + 10 * 365_days);
Alexander Afanasyevf8379172017-01-11 16:56:04 -0800537}
538
Yingdi Yufe4733a2015-10-22 14:24:12 -0700539BOOST_AUTO_TEST_SUITE_END() // TestKeyChain
Yingdi Yufe4733a2015-10-22 14:24:12 -0700540BOOST_AUTO_TEST_SUITE_END() // Security
541
542} // namespace tests
Alexander Afanasyev09236c22020-06-03 13:42:38 -0400543} // inline namespace v2
Yingdi Yufe4733a2015-10-22 14:24:12 -0700544} // namespace security
545} // namespace ndn