blob: 1aa76b891eed34f18d88400e5bcd449528bc4fa3 [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/*
Davide Pesavento809f7542021-03-24 18:53:05 -04003 * Copyright (c) 2013-2021 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"
laqinfan56a812d2019-06-03 15:33:58 -050023#include "ndn-cxx/security/transform/private-key.hpp"
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050024#include "ndn-cxx/security/verification-helpers.hpp"
Yingdi Yufe4733a2015-10-22 14:24:12 -070025
Davide Pesavento7e780642018-11-24 15:51:34 -050026#include "tests/boost-test.hpp"
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050027#include "tests/key-chain-fixture.hpp"
Davide Pesavento7e780642018-11-24 15:51:34 -050028#include "tests/unit/test-home-env-saver.hpp"
Yingdi Yufe4733a2015-10-22 14:24:12 -070029
Davide Pesavento73710362020-12-04 16:10:03 -050030#include <boost/mpl/vector.hpp>
31
Yingdi Yufe4733a2015-10-22 14:24:12 -070032namespace ndn {
33namespace security {
Alexander Afanasyev09236c22020-06-03 13:42:38 -040034inline namespace v2 {
Yingdi Yufe4733a2015-10-22 14:24:12 -070035namespace tests {
36
37using namespace ndn::tests;
38
39BOOST_AUTO_TEST_SUITE(Security)
Yingdi Yufe4733a2015-10-22 14:24:12 -070040BOOST_FIXTURE_TEST_SUITE(TestKeyChain, TestHomeEnvSaver)
41
42template<class Path>
43class TestHomeAndPibFixture : public TestHomeFixture<Path>
44{
45public:
46 TestHomeAndPibFixture()
47 {
48 unsetenv("NDN_CLIENT_PIB");
49 unsetenv("NDN_CLIENT_TPM");
50 }
Alexander Afanasyev80782e02017-01-04 13:16:54 -080051
52 ~TestHomeAndPibFixture()
53 {
Alexander Afanasyev57d02b62018-06-15 18:19:50 -040054 try {
55 const_cast<std::string&>(KeyChain::getDefaultPibLocator()).clear();
56 }
57 catch (const KeyChain::Error&) {
58 // ignore
59 }
60
61 try {
62 const_cast<std::string&>(KeyChain::getDefaultTpmLocator()).clear();
63 }
64 catch (const KeyChain::Error&) {
65 // ignore
66 }
Alexander Afanasyev80782e02017-01-04 13:16:54 -080067 }
Yingdi Yufe4733a2015-10-22 14:24:12 -070068};
69
70struct PibPathConfigFileHome
71{
72 const std::string PATH = "build/config-file-home/";
73};
74
75BOOST_FIXTURE_TEST_CASE(ConstructorNormalConfig, TestHomeAndPibFixture<PibPathConfigFileHome>)
76{
77 createClientConf({"pib=pib-memory:", "tpm=tpm-memory:"});
78
79 BOOST_REQUIRE_NO_THROW(KeyChain());
80
81 KeyChain keyChain;
82 BOOST_CHECK_EQUAL(keyChain.getPib().getPibLocator(), "pib-memory:");
83 BOOST_CHECK_EQUAL(keyChain.getPib().getTpmLocator(), "tpm-memory:");
84 BOOST_CHECK_EQUAL(keyChain.getTpm().getTpmLocator(), "tpm-memory:");
85}
86
87struct PibPathConfigFileEmptyHome
88{
89 const std::string PATH = "build/config-file-empty-home/";
90};
91
92BOOST_FIXTURE_TEST_CASE(ConstructorEmptyConfig, TestHomeAndPibFixture<PibPathConfigFileEmptyHome>)
93{
94 createClientConf({"pib=pib-memory:"});
95
Alexander Afanasyev0cf887d2017-03-26 16:58:59 -050096#if defined(NDN_CXX_HAVE_OSX_FRAMEWORKS)
Yingdi Yufe4733a2015-10-22 14:24:12 -070097 std::string oldHOME;
98 if (std::getenv("OLD_HOME"))
99 oldHOME = std::getenv("OLD_HOME");
100
101 std::string HOME;
102 if (std::getenv("HOME"))
103 HOME = std::getenv("HOME");
104
105 if (!oldHOME.empty())
106 setenv("HOME", oldHOME.c_str(), 1);
107 else
108 unsetenv("HOME");
109#endif
110
111 BOOST_REQUIRE_NO_THROW(KeyChain());
112 KeyChain keyChain;
113 BOOST_CHECK_EQUAL(keyChain.getPib().getPibLocator(), "pib-memory:");
114
Alexander Afanasyev0cf887d2017-03-26 16:58:59 -0500115#if defined(NDN_CXX_HAVE_OSX_FRAMEWORKS)
Yingdi Yufe4733a2015-10-22 14:24:12 -0700116 BOOST_CHECK_EQUAL(keyChain.getPib().getTpmLocator(), "tpm-osxkeychain:");
117 BOOST_CHECK_EQUAL(keyChain.getTpm().getTpmLocator(), "tpm-osxkeychain:");
118#else
119 BOOST_CHECK_EQUAL(keyChain.getPib().getTpmLocator(), "tpm-file:");
120 BOOST_CHECK_EQUAL(keyChain.getTpm().getTpmLocator(), "tpm-file:");
121#endif
122
Alexander Afanasyev0cf887d2017-03-26 16:58:59 -0500123#if defined(NDN_CXX_HAVE_OSX_FRAMEWORKS)
Yingdi Yufe4733a2015-10-22 14:24:12 -0700124 if (!HOME.empty())
125 setenv("HOME", HOME.c_str(), 1);
126 else
127 unsetenv("HOME");
128
129 if (!oldHOME.empty())
130 setenv("OLD_HOME", oldHOME.c_str(), 1);
131 else
132 unsetenv("OLD_HOME");
133#endif
134}
135
136struct PibPathConfigFileEmpty2Home
137{
138 const std::string PATH = "build/config-file-empty2-home/";
139};
140
Davide Pesavento73710362020-12-04 16:10:03 -0500141BOOST_FIXTURE_TEST_CASE(ConstructorEmptyConfig2, TestHomeAndPibFixture<PibPathConfigFileEmpty2Home>)
Yingdi Yufe4733a2015-10-22 14:24:12 -0700142{
143 createClientConf({"tpm=tpm-memory:"});
144
145 BOOST_REQUIRE_NO_THROW(KeyChain());
146
147 KeyChain keyChain;
148 BOOST_CHECK_EQUAL(keyChain.getPib().getPibLocator(), "pib-sqlite3:");
149 BOOST_CHECK_EQUAL(keyChain.getPib().getTpmLocator(), "tpm-memory:");
150 BOOST_CHECK_EQUAL(keyChain.getTpm().getTpmLocator(), "tpm-memory:");
151}
152
153struct PibPathConfigFileMalformedHome
154{
155 const std::string PATH = "build/config-file-malformed-home/";
156};
157
Davide Pesavento73710362020-12-04 16:10:03 -0500158BOOST_FIXTURE_TEST_CASE(ConstructorBadConfig, TestHomeAndPibFixture<PibPathConfigFileMalformedHome>)
Yingdi Yufe4733a2015-10-22 14:24:12 -0700159{
160 createClientConf({"pib=lord", "tpm=ring"});
Davide Pesavento73710362020-12-04 16:10:03 -0500161 BOOST_CHECK_THROW(KeyChain(), KeyChain::Error); // Wrong configuration. Error expected.
Yingdi Yufe4733a2015-10-22 14:24:12 -0700162}
163
164struct PibPathConfigFileMalformed2Home
165{
166 const std::string PATH = "build/config-file-malformed2-home/";
167};
168
Davide Pesavento73710362020-12-04 16:10:03 -0500169BOOST_FIXTURE_TEST_CASE(ConstructorBadConfig2, TestHomeAndPibFixture<PibPathConfigFileMalformed2Home>)
Yingdi Yufe4733a2015-10-22 14:24:12 -0700170{
171 createClientConf({"pib=pib-sqlite3:%PATH%", "tpm=just-wrong"});
Davide Pesavento73710362020-12-04 16:10:03 -0500172 BOOST_CHECK_THROW(KeyChain(), KeyChain::Error); // Wrong configuration. Error expected.
Yingdi Yufe4733a2015-10-22 14:24:12 -0700173}
174
Alexander Afanasyev57d02b62018-06-15 18:19:50 -0400175struct PibPathConfigFileNonCanonicalTpm
176{
177 const std::string PATH = "build/config-file-non-canonical-tpm/";
178};
179
180BOOST_FIXTURE_TEST_CASE(ConstructorNonCanonicalTpm, TestHomeAndPibFixture<PibPathConfigFileNonCanonicalTpm>) // Bug 4297
181{
182 createClientConf({"pib=pib-sqlite3:", "tpm=tpm-file"});
183
184 {
185 KeyChain keyChain;
186 keyChain.createIdentity("/test");
187 BOOST_CHECK_EQUAL(keyChain.getPib().getPibLocator(), "pib-sqlite3:");
188 BOOST_CHECK_EQUAL(keyChain.getTpm().getTpmLocator(), "tpm-file:");
189 }
190
191 {
192 KeyChain keyChain;
193 BOOST_CHECK_EQUAL(keyChain.getPib().getPibLocator(), "pib-sqlite3:");
194 BOOST_CHECK_EQUAL(keyChain.getTpm().getTpmLocator(), "tpm-file:");
195 BOOST_CHECK(keyChain.getPib().getIdentities().find("/test") != keyChain.getPib().getIdentities().end());
196 }
197}
198
Yingdi Yufe4733a2015-10-22 14:24:12 -0700199BOOST_AUTO_TEST_CASE(KeyChainWithCustomTpmAndPib)
200{
201 BOOST_REQUIRE_NO_THROW((KeyChain("pib-memory", "tpm-memory")));
202 BOOST_REQUIRE_NO_THROW((KeyChain("pib-memory:", "tpm-memory:")));
203 BOOST_REQUIRE_NO_THROW((KeyChain("pib-memory:/something", "tpm-memory:/something")));
204
205 KeyChain keyChain("pib-memory", "tpm-memory");
206 BOOST_CHECK_EQUAL(keyChain.getPib().getPibLocator(), "pib-memory:");
207 BOOST_CHECK_EQUAL(keyChain.getPib().getTpmLocator(), "tpm-memory:");
208 BOOST_CHECK_EQUAL(keyChain.getTpm().getTpmLocator(), "tpm-memory:");
209}
210
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500211BOOST_FIXTURE_TEST_CASE(SigningWithCorruptedPibTpm, KeyChainFixture)
Alexander Afanasyevf601e192020-06-02 16:41:07 -0400212{
213 Identity id = m_keyChain.createIdentity("/test");
214
215 Data data("/foobar");
216 BOOST_CHECK_NO_THROW(m_keyChain.sign(data, signingByIdentity(id)));
217
218 // now, "corrupting TPM"
219 const_cast<Tpm&>(m_keyChain.getTpm()).deleteKey(id.getDefaultKey().getName());
220
221 BOOST_CHECK_NO_THROW(id.getDefaultKey());
222 BOOST_CHECK_THROW(m_keyChain.sign(data, signingByIdentity(id)), KeyChain::InvalidSigningInfoError);
223}
224
Davide Pesavento73710362020-12-04 16:10:03 -0500225BOOST_FIXTURE_TEST_CASE(SigningWithNonExistingIdentity, KeyChainFixture)
226{
227 Data data("/test/data");
228 BOOST_CHECK_THROW(m_keyChain.sign(data, signingByIdentity("/non-existing/identity")),
229 KeyChain::InvalidSigningInfoError);
230}
231
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500232BOOST_FIXTURE_TEST_CASE(Management, KeyChainFixture)
Yingdi Yufe4733a2015-10-22 14:24:12 -0700233{
234 Name identityName("/test/id");
235 Name identity2Name("/test/id2");
236
237 BOOST_CHECK_EQUAL(m_keyChain.getPib().getIdentities().size(), 0);
238 BOOST_REQUIRE_THROW(m_keyChain.getPib().getDefaultIdentity(), Pib::Error);
239
240 // Create identity
241 Identity id = m_keyChain.createIdentity(identityName);
242 BOOST_CHECK(id);
243 BOOST_CHECK(m_keyChain.getPib().getIdentities().find(identityName) != m_keyChain.getPib().getIdentities().end());
244 // The first added identity becomes the default identity
laqinfan56a812d2019-06-03 15:33:58 -0500245 BOOST_CHECK_NO_THROW(m_keyChain.getPib().getDefaultIdentity());
Yingdi Yufe4733a2015-10-22 14:24:12 -0700246 // The default key of the added identity must exist
laqinfan56a812d2019-06-03 15:33:58 -0500247 Key key = id.getDefaultKey();
Yingdi Yufe4733a2015-10-22 14:24:12 -0700248 // The default certificate of the default key must exist
laqinfan56a812d2019-06-03 15:33:58 -0500249 BOOST_CHECK_NO_THROW(key.getDefaultCertificate());
Yingdi Yufe4733a2015-10-22 14:24:12 -0700250
251 // Delete key
252 Name key1Name = key.getName();
253 BOOST_CHECK_NO_THROW(id.getKey(key1Name));
254 BOOST_CHECK_EQUAL(id.getKeys().size(), 1);
255 m_keyChain.deleteKey(id, key);
256 // The key instance should not be valid any more
257 BOOST_CHECK(!key);
258 BOOST_CHECK_THROW(id.getKey(key1Name), Pib::Error);
259 BOOST_CHECK_EQUAL(id.getKeys().size(), 0);
260
261 // Create another key
262 m_keyChain.createKey(id);
263 // The added key becomes the default key.
Yingdi Yufe4733a2015-10-22 14:24:12 -0700264 Key key2 = id.getDefaultKey();
265 BOOST_REQUIRE(key2);
266 BOOST_CHECK_NE(key2.getName(), key1Name);
267 BOOST_CHECK_EQUAL(id.getKeys().size(), 1);
laqinfan56a812d2019-06-03 15:33:58 -0500268 BOOST_CHECK_NO_THROW(key2.getDefaultCertificate());
Yingdi Yufe4733a2015-10-22 14:24:12 -0700269
270 // Create the third key
271 Key key3 = m_keyChain.createKey(id);
Junxiao Shi72c0c642018-04-20 15:41:09 +0000272 BOOST_CHECK_NE(key3.getName(), key2.getName());
Yingdi Yufe4733a2015-10-22 14:24:12 -0700273 // The added key will not be the default key, because the default key already exists
Junxiao Shi72c0c642018-04-20 15:41:09 +0000274 BOOST_CHECK_EQUAL(id.getDefaultKey().getName(), key2.getName());
Yingdi Yufe4733a2015-10-22 14:24:12 -0700275 BOOST_CHECK_EQUAL(id.getKeys().size(), 2);
laqinfan56a812d2019-06-03 15:33:58 -0500276 BOOST_CHECK_NO_THROW(key3.getDefaultCertificate());
Yingdi Yufe4733a2015-10-22 14:24:12 -0700277
278 // Delete cert
279 BOOST_CHECK_EQUAL(key3.getCertificates().size(), 1);
280 Certificate key3Cert1 = *key3.getCertificates().begin();
281 Name key3CertName = key3Cert1.getName();
282 m_keyChain.deleteCertificate(key3, key3CertName);
283 BOOST_CHECK_EQUAL(key3.getCertificates().size(), 0);
284 BOOST_REQUIRE_THROW(key3.getDefaultCertificate(), Pib::Error);
285
286 // Add cert
287 m_keyChain.addCertificate(key3, key3Cert1);
288 BOOST_CHECK_EQUAL(key3.getCertificates().size(), 1);
laqinfan56a812d2019-06-03 15:33:58 -0500289 BOOST_CHECK_NO_THROW(key3.getDefaultCertificate());
Alexander Afanasyeva10b2ff2017-01-30 12:44:15 -0800290 m_keyChain.addCertificate(key3, key3Cert1); // overwriting the cert should work
Yingdi Yufe4733a2015-10-22 14:24:12 -0700291 BOOST_CHECK_EQUAL(key3.getCertificates().size(), 1);
292 // Add another cert
293 Certificate key3Cert2 = key3Cert1;
294 Name key3Cert2Name = key3.getName();
295 key3Cert2Name.append("Self");
296 key3Cert2Name.appendVersion();
297 key3Cert2.setName(key3Cert2Name);
298 m_keyChain.addCertificate(key3, key3Cert2);
299 BOOST_CHECK_EQUAL(key3.getCertificates().size(), 2);
Davide Pesavento81bd6962020-06-17 16:03:23 -0400300 // Add empty cert
301 Certificate key3Cert3 = key3Cert1;
302 key3Cert3.unsetContent();
303 BOOST_CHECK_THROW(m_keyChain.addCertificate(key3, key3Cert3), std::invalid_argument);
Yingdi Yufe4733a2015-10-22 14:24:12 -0700304
305 // Default certificate setting
306 BOOST_CHECK_EQUAL(key3.getDefaultCertificate().getName(), key3CertName);
307 m_keyChain.setDefaultCertificate(key3, key3Cert2);
308 BOOST_CHECK_EQUAL(key3.getDefaultCertificate().getName(), key3Cert2Name);
309
310 // Default key setting
311 BOOST_CHECK_EQUAL(id.getDefaultKey().getName(), key2.getName());
312 m_keyChain.setDefaultKey(id, key3);
313 BOOST_CHECK_EQUAL(id.getDefaultKey().getName(), key3.getName());
314
315 // Default identity setting
316 Identity id2 = m_keyChain.createIdentity(identity2Name);
317 BOOST_CHECK_EQUAL(m_keyChain.getPib().getDefaultIdentity().getName(), id.getName());
318 m_keyChain.setDefaultIdentity(id2);
319 BOOST_CHECK_EQUAL(m_keyChain.getPib().getDefaultIdentity().getName(), id2.getName());
320
321 // Delete identity
322 m_keyChain.deleteIdentity(id);
323 // The identity instance should not be valid any more
324 BOOST_CHECK(!id);
Davide Pesavento73710362020-12-04 16:10:03 -0500325 BOOST_CHECK_THROW(m_keyChain.getPib().getIdentity(identityName), Pib::Error);
Yingdi Yufe4733a2015-10-22 14:24:12 -0700326 BOOST_CHECK(m_keyChain.getPib().getIdentities().find(identityName) == m_keyChain.getPib().getIdentities().end());
327}
328
Davide Pesavento73710362020-12-04 16:10:03 -0500329struct DataPkt
Yingdi Yufe4733a2015-10-22 14:24:12 -0700330{
Davide Pesavento73710362020-12-04 16:10:03 -0500331 Data packet{"/data"};
332 SignedInterestFormat sigFormat = SignedInterestFormat::V02; // irrelevant for Data
Yingdi Yufe4733a2015-10-22 14:24:12 -0700333
Davide Pesavento73710362020-12-04 16:10:03 -0500334 SignatureInfo
335 getSignatureInfo() const
336 {
337 return packet.getSignatureInfo();
338 }
339};
laqinfan56a812d2019-06-03 15:33:58 -0500340
Davide Pesavento73710362020-12-04 16:10:03 -0500341struct InterestV02Pkt
342{
343 Interest packet = Interest{"/interest02"}.setCanBePrefix(false);
344 SignedInterestFormat sigFormat = SignedInterestFormat::V02;
Eric Newberryb74bbda2020-06-18 19:33:58 -0700345
Davide Pesavento73710362020-12-04 16:10:03 -0500346 SignatureInfo
347 getSignatureInfo() const
348 {
349 return SignatureInfo(packet.getName()[signed_interest::POS_SIG_INFO].blockFromValue());
350 }
351};
Eric Newberryb74bbda2020-06-18 19:33:58 -0700352
Davide Pesavento73710362020-12-04 16:10:03 -0500353struct InterestV03Pkt
354{
355 Interest packet = Interest{"/interest03"}.setCanBePrefix(false);
356 SignedInterestFormat sigFormat = SignedInterestFormat::V03;
Eric Newberryb74bbda2020-06-18 19:33:58 -0700357
Davide Pesavento73710362020-12-04 16:10:03 -0500358 SignatureInfo
359 getSignatureInfo() const
360 {
361 return packet.getSignatureInfo().value(); // use .value() for checked access
362 }
363};
Eric Newberryb74bbda2020-06-18 19:33:58 -0700364
Davide Pesavento73710362020-12-04 16:10:03 -0500365template<typename KeyParams>
366struct DefaultIdentity
367{
368 Identity
369 operator()(KeyChain& keyChain) const
370 {
371 auto id = keyChain.createIdentity("/id", KeyParams());
372 BOOST_ASSERT(keyChain.getPib().getDefaultIdentity() == id);
373 return id;
374 }
375};
Eric Newberryb74bbda2020-06-18 19:33:58 -0700376
Davide Pesavento73710362020-12-04 16:10:03 -0500377template<typename KeyParams>
378struct NonDefaultIdentity
379{
380 Identity
381 operator()(KeyChain& keyChain) const
382 {
383 auto id = keyChain.createIdentity("/id");
384 auto id2 = keyChain.createIdentity("/id2", KeyParams());
385 BOOST_ASSERT(keyChain.getPib().getDefaultIdentity() == id);
386 return id2;
387 }
388};
Eric Newberryb74bbda2020-06-18 19:33:58 -0700389
Davide Pesavento73710362020-12-04 16:10:03 -0500390template<typename KeyParams>
391struct DefaultKey
392{
393 Key
394 operator()(KeyChain&, const Identity& id) const
395 {
396 auto key = id.getDefaultKey();
397 BOOST_ASSERT(key.getKeyType() == KeyParams().getKeyType());
398 return key;
399 }
400};
Eric Newberryb74bbda2020-06-18 19:33:58 -0700401
Davide Pesavento73710362020-12-04 16:10:03 -0500402template<typename KeyParams>
403struct NonDefaultKey
404{
405 Key
406 operator()(KeyChain& keyChain, const Identity& id) const
407 {
408 auto key2 = keyChain.createKey(id, KeyParams());
409 BOOST_ASSERT(id.getDefaultKey() != key2);
410 return key2;
411 }
412};
Eric Newberryb74bbda2020-06-18 19:33:58 -0700413
Davide Pesavento73710362020-12-04 16:10:03 -0500414template<typename PacketType,
415 template<typename> class IdentityMaker = DefaultIdentity,
416 template<typename> class KeyMaker = DefaultKey,
417 typename AsymmetricKeyParams = EcKeyParams,
418 uint32_t SignatureTypeTlvValue = tlv::SignatureSha256WithEcdsa>
419struct AsymmetricSigningBase : protected KeyChainFixture, protected PacketType
420{
421 const Identity id = IdentityMaker<AsymmetricKeyParams>()(m_keyChain);
422 const Key key = KeyMaker<AsymmetricKeyParams>()(m_keyChain, id);
423 const Certificate cert = key.getDefaultCertificate();
424
425 const uint32_t expectedSigType = SignatureTypeTlvValue;
426 const bool shouldHaveKeyLocator = true;
427 const optional<KeyLocator> expectedKeyLocator = cert.getName().getPrefix(-2);
428
429 bool
430 verify(const SigningInfo&) const
431 {
432 return verifySignature(this->packet, key);
433 }
434};
435
436template<typename PacketType,
437 typename AsymmetricKeyParams,
438 uint32_t SignatureTypeTlvValue>
439struct AsymmetricSigning : protected AsymmetricSigningBase<PacketType, DefaultIdentity, DefaultKey,
440 AsymmetricKeyParams, SignatureTypeTlvValue>
441{
442 const std::vector<SigningInfo> signingInfos = {
Yingdi Yufe4733a2015-10-22 14:24:12 -0700443 SigningInfo(),
Davide Pesavento73710362020-12-04 16:10:03 -0500444 SigningInfo(""),
Yingdi Yufe4733a2015-10-22 14:24:12 -0700445
Davide Pesavento73710362020-12-04 16:10:03 -0500446 SigningInfo(this->id),
447 SigningInfo(SigningInfo::SIGNER_TYPE_ID, this->id.getName()),
448 SigningInfo("id:" + this->id.getName().toUri()),
449 signingByIdentity(this->id),
450 signingByIdentity(this->id.getName()),
Yingdi Yufe4733a2015-10-22 14:24:12 -0700451
Davide Pesavento73710362020-12-04 16:10:03 -0500452 SigningInfo(this->key),
453 SigningInfo(SigningInfo::SIGNER_TYPE_KEY, this->key.getName()),
454 SigningInfo("key:" + this->key.getName().toUri()),
455 signingByKey(this->key),
456 signingByKey(this->key.getName()),
Alexander Afanasyevd6d78aa2017-01-02 18:14:23 -0800457
Davide Pesavento73710362020-12-04 16:10:03 -0500458 SigningInfo(SigningInfo::SIGNER_TYPE_CERT, this->cert.getName()),
459 SigningInfo("cert:" + this->cert.getName().toUri()),
460 signingByCertificate(this->cert),
461 signingByCertificate(this->cert.getName()),
462 };
463};
Yingdi Yufe4733a2015-10-22 14:24:12 -0700464
Davide Pesavento73710362020-12-04 16:10:03 -0500465template<typename PacketType>
466using RsaSigning = AsymmetricSigning<PacketType, RsaKeyParams, tlv::SignatureSha256WithRsa>;
Alexander Afanasyevd6d78aa2017-01-02 18:14:23 -0800467
Davide Pesavento73710362020-12-04 16:10:03 -0500468template<typename PacketType>
469using EcdsaSigning = AsymmetricSigning<PacketType, EcKeyParams, tlv::SignatureSha256WithEcdsa>;
Yingdi Yufe4733a2015-10-22 14:24:12 -0700470
Davide Pesavento73710362020-12-04 16:10:03 -0500471template<typename PacketType>
472struct SigningWithNonDefaultIdentity : protected AsymmetricSigningBase<PacketType, NonDefaultIdentity>
473{
474 const std::vector<SigningInfo> signingInfos = {
475 signingByIdentity(this->id),
476 signingByIdentity(this->id.getName()),
477 signingByKey(this->key),
478 signingByCertificate(this->cert),
479 };
480};
481
482template<typename PacketType>
483struct SigningWithNonDefaultKey : protected AsymmetricSigningBase<PacketType, NonDefaultIdentity, NonDefaultKey>
484{
485 const std::vector<SigningInfo> signingInfos = {
486 signingByKey(this->key),
487 signingByKey(this->key.getName()),
488 signingByCertificate(this->cert),
489 };
490};
491
492template<typename PacketType,
493 DigestAlgorithm DigestAlgo = DigestAlgorithm::SHA256,
494 uint32_t SignatureTypeTlvValue = tlv::SignatureHmacWithSha256>
495struct HmacSigning : protected KeyChainFixture, protected PacketType
496{
497 const std::vector<SigningInfo> signingInfos = {
498 SigningInfo(SigningInfo::SIGNER_TYPE_HMAC, m_keyChain.createHmacKey()),
laqinfan56a812d2019-06-03 15:33:58 -0500499 SigningInfo("hmac-sha256:QjM3NEEyNkE3MTQ5MDQzN0FBMDI0RTRGQURENUI0OTdGREZGMUE4RUE2RkYxMkY2RkI2NUFGMjcyMEI1OUNDRg=="),
Davide Pesavento73710362020-12-04 16:10:03 -0500500 };
laqinfan56a812d2019-06-03 15:33:58 -0500501
Davide Pesavento73710362020-12-04 16:10:03 -0500502 const uint32_t expectedSigType = SignatureTypeTlvValue;
503 const bool shouldHaveKeyLocator = true;
504 const optional<KeyLocator> expectedKeyLocator = nullopt; // don't check KeyLocator value
505
506 bool
507 verify(const SigningInfo& si) const
508 {
509 return verifySignature(this->packet, m_keyChain.getTpm(), si.getSignerName(), DigestAlgo);
510 }
511};
512
513template<typename PacketType>
514struct Sha256Signing : protected KeyChainFixture, protected PacketType
515{
516 const std::vector<SigningInfo> signingInfos = {
Yingdi Yufe4733a2015-10-22 14:24:12 -0700517 SigningInfo(SigningInfo::SIGNER_TYPE_SHA256),
Davide Pesavento73710362020-12-04 16:10:03 -0500518 SigningInfo("id:" + SigningInfo::getDigestSha256Identity().toUri()),
Yingdi Yufe4733a2015-10-22 14:24:12 -0700519 signingWithSha256()
520 };
521
Davide Pesavento73710362020-12-04 16:10:03 -0500522 const uint32_t expectedSigType = tlv::DigestSha256;
523 const bool shouldHaveKeyLocator = false;
524 const optional<KeyLocator> expectedKeyLocator = nullopt;
Yingdi Yufe4733a2015-10-22 14:24:12 -0700525
Davide Pesavento73710362020-12-04 16:10:03 -0500526 bool
527 verify(const SigningInfo&) const
528 {
Davide Pesavento809f7542021-03-24 18:53:05 -0400529 return verifySignature(this->packet, nullopt);
Davide Pesavento73710362020-12-04 16:10:03 -0500530 }
531};
Yingdi Yufe4733a2015-10-22 14:24:12 -0700532
Davide Pesavento73710362020-12-04 16:10:03 -0500533using SigningTests = boost::mpl::vector<
534 RsaSigning<DataPkt>,
535 RsaSigning<InterestV02Pkt>,
536 RsaSigning<InterestV03Pkt>,
537 EcdsaSigning<DataPkt>,
538 EcdsaSigning<InterestV02Pkt>,
539 EcdsaSigning<InterestV03Pkt>,
540 HmacSigning<DataPkt>,
541 HmacSigning<InterestV02Pkt>,
542 HmacSigning<InterestV03Pkt>,
543 Sha256Signing<DataPkt>,
544 Sha256Signing<InterestV02Pkt>,
545 Sha256Signing<InterestV03Pkt>,
546 SigningWithNonDefaultIdentity<DataPkt>,
Davide Pesavento809f7542021-03-24 18:53:05 -0400547 SigningWithNonDefaultIdentity<InterestV03Pkt>,
548 SigningWithNonDefaultKey<DataPkt>,
549 SigningWithNonDefaultKey<InterestV03Pkt>
Davide Pesavento73710362020-12-04 16:10:03 -0500550>;
Eric Newberryb74bbda2020-06-18 19:33:58 -0700551
Davide Pesavento73710362020-12-04 16:10:03 -0500552BOOST_FIXTURE_TEST_CASE_TEMPLATE(SigningInterface, T, SigningTests, T)
553{
554 BOOST_TEST_CONTEXT("Packet = " << this->packet.getName()) {
555 for (auto signingInfo : this->signingInfos) {
556 signingInfo.setSignedInterestFormat(this->sigFormat);
557
558 BOOST_TEST_CONTEXT("SigningInfo = " << signingInfo) {
559 this->m_keyChain.sign(this->packet, signingInfo);
560
561 auto sigInfo = this->getSignatureInfo();
562 BOOST_CHECK_EQUAL(sigInfo.getSignatureType(), this->expectedSigType);
563 BOOST_CHECK_EQUAL(sigInfo.hasKeyLocator(), this->shouldHaveKeyLocator);
564 if (this->expectedKeyLocator) {
565 BOOST_CHECK_EQUAL(sigInfo.getKeyLocator(), *this->expectedKeyLocator);
566 }
567 BOOST_CHECK(this->verify(signingInfo));
Eric Newberryb74bbda2020-06-18 19:33:58 -0700568 }
Yingdi Yufe4733a2015-10-22 14:24:12 -0700569 }
570 }
571}
572
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500573BOOST_FIXTURE_TEST_CASE(ImportPrivateKey, KeyChainFixture)
laqinfan56a812d2019-06-03 15:33:58 -0500574{
575 Name keyName("/test/device2");
576 std::string rawKey("nPSNOHyZKsg2WLqHAs7MXGb0sjQb4zCT");
577 auto key = make_shared<transform::PrivateKey>();
578 key->loadRaw(KeyType::HMAC, reinterpret_cast<const uint8_t*>(rawKey.data()), rawKey.size());
579
580 m_keyChain.importPrivateKey(keyName, key);
581 BOOST_CHECK_EQUAL(m_keyChain.getTpm().hasKey(keyName), true);
582 BOOST_CHECK_THROW(m_keyChain.importPrivateKey(keyName, key), KeyChain::Error);
583}
584
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500585BOOST_FIXTURE_TEST_CASE(ExportImport, KeyChainFixture)
Yingdi Yufe4733a2015-10-22 14:24:12 -0700586{
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500587 Identity id = m_keyChain.createIdentity("/TestKeyChain/ExportIdentity");
Yingdi Yufe4733a2015-10-22 14:24:12 -0700588 Certificate cert = id.getDefaultKey().getDefaultCertificate();
589
590 shared_ptr<SafeBag> exported = m_keyChain.exportSafeBag(cert, "1234", 4);
591 Block block = exported->wireEncode();
592
593 m_keyChain.deleteIdentity(id);
Davide Pesavento82d6a4c2017-12-23 19:47:20 -0500594 BOOST_CHECK_THROW(m_keyChain.exportSafeBag(cert, "1234", 4), KeyChain::Error);
Yingdi Yufe4733a2015-10-22 14:24:12 -0700595
596 BOOST_CHECK_EQUAL(m_keyChain.getTpm().hasKey(cert.getKeyName()), false);
597 BOOST_CHECK_EQUAL(m_keyChain.getPib().getIdentities().size(), 0);
598
599 SafeBag imported;
600 imported.wireDecode(block);
601 m_keyChain.importSafeBag(imported, "1234", 4);
Davide Pesavento82d6a4c2017-12-23 19:47:20 -0500602 BOOST_CHECK_THROW(m_keyChain.importSafeBag(imported, "1234", 4), KeyChain::Error);
Yingdi Yufe4733a2015-10-22 14:24:12 -0700603
604 BOOST_CHECK_EQUAL(m_keyChain.getTpm().hasKey(cert.getKeyName()), true);
605 BOOST_CHECK_EQUAL(m_keyChain.getPib().getIdentities().size(), 1);
Yingdi Yufe4733a2015-10-22 14:24:12 -0700606 Identity newId = m_keyChain.getPib().getIdentity(cert.getIdentity());
607 BOOST_CHECK_EQUAL(newId.getKeys().size(), 1);
Yingdi Yufe4733a2015-10-22 14:24:12 -0700608 Key newKey = newId.getKey(cert.getKeyName());
609 BOOST_CHECK_EQUAL(newKey.getCertificates().size(), 1);
laqinfan56a812d2019-06-03 15:33:58 -0500610 BOOST_CHECK_NO_THROW(newKey.getCertificate(cert.getName()));
Yingdi Yufe4733a2015-10-22 14:24:12 -0700611
612 m_keyChain.deleteIdentity(newId);
613 BOOST_CHECK_EQUAL(m_keyChain.getPib().getIdentities().size(), 0);
614 BOOST_CHECK_EQUAL(m_keyChain.getTpm().hasKey(cert.getKeyName()), false);
615}
616
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500617BOOST_FIXTURE_TEST_CASE(SelfSignedCertValidity, KeyChainFixture)
Alexander Afanasyevf8379172017-01-11 16:56:04 -0800618{
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500619 Certificate cert = m_keyChain.createIdentity("/Security/TestKeyChain/SelfSignedCertValidity")
Alexander Afanasyevf8379172017-01-11 16:56:04 -0800620 .getDefaultKey()
621 .getDefaultCertificate();
622 BOOST_CHECK(cert.isValid());
Davide Pesavento0f830802018-01-16 23:58:58 -0500623 BOOST_CHECK(cert.isValid(time::system_clock::now() + 10 * 365_days));
624 BOOST_CHECK_GT(cert.getValidityPeriod().getPeriod().second, time::system_clock::now() + 10 * 365_days);
Alexander Afanasyevf8379172017-01-11 16:56:04 -0800625}
626
Yingdi Yufe4733a2015-10-22 14:24:12 -0700627BOOST_AUTO_TEST_SUITE_END() // TestKeyChain
Yingdi Yufe4733a2015-10-22 14:24:12 -0700628BOOST_AUTO_TEST_SUITE_END() // Security
629
630} // namespace tests
Alexander Afanasyev09236c22020-06-03 13:42:38 -0400631} // inline namespace v2
Yingdi Yufe4733a2015-10-22 14:24:12 -0700632} // namespace security
633} // namespace ndn