blob: ee3e28ef32621aa5290398989f6d201a7905a005 [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"
Davide Pesavento94dfcf12021-09-26 14:18:45 -040023#include "ndn-cxx/security/impl/openssl.hpp"
laqinfan56a812d2019-06-03 15:33:58 -050024#include "ndn-cxx/security/transform/private-key.hpp"
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050025#include "ndn-cxx/security/verification-helpers.hpp"
Yingdi Yufe4733a2015-10-22 14:24:12 -070026
Davide Pesavento7e780642018-11-24 15:51:34 -050027#include "tests/boost-test.hpp"
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050028#include "tests/key-chain-fixture.hpp"
Davide Pesavento7e780642018-11-24 15:51:34 -050029#include "tests/unit/test-home-env-saver.hpp"
Yingdi Yufe4733a2015-10-22 14:24:12 -070030
Davide Pesavento73710362020-12-04 16:10:03 -050031#include <boost/mpl/vector.hpp>
32
Yingdi Yufe4733a2015-10-22 14:24:12 -070033namespace ndn {
34namespace security {
Alexander Afanasyev09236c22020-06-03 13:42:38 -040035inline namespace v2 {
Yingdi Yufe4733a2015-10-22 14:24:12 -070036namespace tests {
37
38using namespace ndn::tests;
39
40BOOST_AUTO_TEST_SUITE(Security)
Yingdi Yufe4733a2015-10-22 14:24:12 -070041BOOST_FIXTURE_TEST_SUITE(TestKeyChain, TestHomeEnvSaver)
42
43template<class Path>
44class TestHomeAndPibFixture : public TestHomeFixture<Path>
45{
46public:
47 TestHomeAndPibFixture()
48 {
49 unsetenv("NDN_CLIENT_PIB");
50 unsetenv("NDN_CLIENT_TPM");
51 }
Alexander Afanasyev80782e02017-01-04 13:16:54 -080052
53 ~TestHomeAndPibFixture()
54 {
Alexander Afanasyev57d02b62018-06-15 18:19:50 -040055 try {
56 const_cast<std::string&>(KeyChain::getDefaultPibLocator()).clear();
57 }
58 catch (const KeyChain::Error&) {
59 // ignore
60 }
61
62 try {
63 const_cast<std::string&>(KeyChain::getDefaultTpmLocator()).clear();
64 }
65 catch (const KeyChain::Error&) {
66 // ignore
67 }
Alexander Afanasyev80782e02017-01-04 13:16:54 -080068 }
Yingdi Yufe4733a2015-10-22 14:24:12 -070069};
70
71struct PibPathConfigFileHome
72{
73 const std::string PATH = "build/config-file-home/";
74};
75
76BOOST_FIXTURE_TEST_CASE(ConstructorNormalConfig, TestHomeAndPibFixture<PibPathConfigFileHome>)
77{
78 createClientConf({"pib=pib-memory:", "tpm=tpm-memory:"});
79
80 BOOST_REQUIRE_NO_THROW(KeyChain());
81
82 KeyChain keyChain;
83 BOOST_CHECK_EQUAL(keyChain.getPib().getPibLocator(), "pib-memory:");
84 BOOST_CHECK_EQUAL(keyChain.getPib().getTpmLocator(), "tpm-memory:");
85 BOOST_CHECK_EQUAL(keyChain.getTpm().getTpmLocator(), "tpm-memory:");
86}
87
88struct PibPathConfigFileEmptyHome
89{
90 const std::string PATH = "build/config-file-empty-home/";
91};
92
93BOOST_FIXTURE_TEST_CASE(ConstructorEmptyConfig, TestHomeAndPibFixture<PibPathConfigFileEmptyHome>)
94{
95 createClientConf({"pib=pib-memory:"});
96
Alexander Afanasyev0cf887d2017-03-26 16:58:59 -050097#if defined(NDN_CXX_HAVE_OSX_FRAMEWORKS)
Yingdi Yufe4733a2015-10-22 14:24:12 -070098 std::string oldHOME;
99 if (std::getenv("OLD_HOME"))
100 oldHOME = std::getenv("OLD_HOME");
101
102 std::string HOME;
103 if (std::getenv("HOME"))
104 HOME = std::getenv("HOME");
105
106 if (!oldHOME.empty())
107 setenv("HOME", oldHOME.c_str(), 1);
108 else
109 unsetenv("HOME");
110#endif
111
112 BOOST_REQUIRE_NO_THROW(KeyChain());
113 KeyChain keyChain;
114 BOOST_CHECK_EQUAL(keyChain.getPib().getPibLocator(), "pib-memory:");
115
Alexander Afanasyev0cf887d2017-03-26 16:58:59 -0500116#if defined(NDN_CXX_HAVE_OSX_FRAMEWORKS)
Yingdi Yufe4733a2015-10-22 14:24:12 -0700117 BOOST_CHECK_EQUAL(keyChain.getPib().getTpmLocator(), "tpm-osxkeychain:");
118 BOOST_CHECK_EQUAL(keyChain.getTpm().getTpmLocator(), "tpm-osxkeychain:");
119#else
120 BOOST_CHECK_EQUAL(keyChain.getPib().getTpmLocator(), "tpm-file:");
121 BOOST_CHECK_EQUAL(keyChain.getTpm().getTpmLocator(), "tpm-file:");
122#endif
123
Alexander Afanasyev0cf887d2017-03-26 16:58:59 -0500124#if defined(NDN_CXX_HAVE_OSX_FRAMEWORKS)
Yingdi Yufe4733a2015-10-22 14:24:12 -0700125 if (!HOME.empty())
126 setenv("HOME", HOME.c_str(), 1);
127 else
128 unsetenv("HOME");
129
130 if (!oldHOME.empty())
131 setenv("OLD_HOME", oldHOME.c_str(), 1);
132 else
133 unsetenv("OLD_HOME");
134#endif
135}
136
137struct PibPathConfigFileEmpty2Home
138{
139 const std::string PATH = "build/config-file-empty2-home/";
140};
141
Davide Pesavento73710362020-12-04 16:10:03 -0500142BOOST_FIXTURE_TEST_CASE(ConstructorEmptyConfig2, TestHomeAndPibFixture<PibPathConfigFileEmpty2Home>)
Yingdi Yufe4733a2015-10-22 14:24:12 -0700143{
144 createClientConf({"tpm=tpm-memory:"});
145
146 BOOST_REQUIRE_NO_THROW(KeyChain());
147
148 KeyChain keyChain;
149 BOOST_CHECK_EQUAL(keyChain.getPib().getPibLocator(), "pib-sqlite3:");
150 BOOST_CHECK_EQUAL(keyChain.getPib().getTpmLocator(), "tpm-memory:");
151 BOOST_CHECK_EQUAL(keyChain.getTpm().getTpmLocator(), "tpm-memory:");
152}
153
154struct PibPathConfigFileMalformedHome
155{
156 const std::string PATH = "build/config-file-malformed-home/";
157};
158
Davide Pesavento73710362020-12-04 16:10:03 -0500159BOOST_FIXTURE_TEST_CASE(ConstructorBadConfig, TestHomeAndPibFixture<PibPathConfigFileMalformedHome>)
Yingdi Yufe4733a2015-10-22 14:24:12 -0700160{
161 createClientConf({"pib=lord", "tpm=ring"});
Davide Pesavento73710362020-12-04 16:10:03 -0500162 BOOST_CHECK_THROW(KeyChain(), KeyChain::Error); // Wrong configuration. Error expected.
Yingdi Yufe4733a2015-10-22 14:24:12 -0700163}
164
165struct PibPathConfigFileMalformed2Home
166{
167 const std::string PATH = "build/config-file-malformed2-home/";
168};
169
Davide Pesavento73710362020-12-04 16:10:03 -0500170BOOST_FIXTURE_TEST_CASE(ConstructorBadConfig2, TestHomeAndPibFixture<PibPathConfigFileMalformed2Home>)
Yingdi Yufe4733a2015-10-22 14:24:12 -0700171{
172 createClientConf({"pib=pib-sqlite3:%PATH%", "tpm=just-wrong"});
Davide Pesavento73710362020-12-04 16:10:03 -0500173 BOOST_CHECK_THROW(KeyChain(), KeyChain::Error); // Wrong configuration. Error expected.
Yingdi Yufe4733a2015-10-22 14:24:12 -0700174}
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
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500212BOOST_FIXTURE_TEST_CASE(SigningWithCorruptedPibTpm, KeyChainFixture)
Alexander Afanasyevf601e192020-06-02 16:41:07 -0400213{
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
Davide Pesavento73710362020-12-04 16:10:03 -0500226BOOST_FIXTURE_TEST_CASE(SigningWithNonExistingIdentity, KeyChainFixture)
227{
228 Data data("/test/data");
229 BOOST_CHECK_THROW(m_keyChain.sign(data, signingByIdentity("/non-existing/identity")),
230 KeyChain::InvalidSigningInfoError);
231}
232
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500233BOOST_FIXTURE_TEST_CASE(Management, KeyChainFixture)
Yingdi Yufe4733a2015-10-22 14:24:12 -0700234{
235 Name identityName("/test/id");
236 Name identity2Name("/test/id2");
237
238 BOOST_CHECK_EQUAL(m_keyChain.getPib().getIdentities().size(), 0);
239 BOOST_REQUIRE_THROW(m_keyChain.getPib().getDefaultIdentity(), Pib::Error);
240
241 // Create identity
242 Identity id = m_keyChain.createIdentity(identityName);
243 BOOST_CHECK(id);
244 BOOST_CHECK(m_keyChain.getPib().getIdentities().find(identityName) != m_keyChain.getPib().getIdentities().end());
245 // The first added identity becomes the default identity
laqinfan56a812d2019-06-03 15:33:58 -0500246 BOOST_CHECK_NO_THROW(m_keyChain.getPib().getDefaultIdentity());
Yingdi Yufe4733a2015-10-22 14:24:12 -0700247 // The default key of the added identity must exist
laqinfan56a812d2019-06-03 15:33:58 -0500248 Key key = id.getDefaultKey();
Yingdi Yufe4733a2015-10-22 14:24:12 -0700249 // The default certificate of the default key must exist
laqinfan56a812d2019-06-03 15:33:58 -0500250 BOOST_CHECK_NO_THROW(key.getDefaultCertificate());
Yingdi Yufe4733a2015-10-22 14:24:12 -0700251
252 // Delete key
253 Name key1Name = key.getName();
254 BOOST_CHECK_NO_THROW(id.getKey(key1Name));
255 BOOST_CHECK_EQUAL(id.getKeys().size(), 1);
256 m_keyChain.deleteKey(id, key);
257 // The key instance should not be valid any more
258 BOOST_CHECK(!key);
259 BOOST_CHECK_THROW(id.getKey(key1Name), Pib::Error);
260 BOOST_CHECK_EQUAL(id.getKeys().size(), 0);
261
262 // Create another key
263 m_keyChain.createKey(id);
264 // The added key becomes the default key.
Yingdi Yufe4733a2015-10-22 14:24:12 -0700265 Key key2 = id.getDefaultKey();
266 BOOST_REQUIRE(key2);
267 BOOST_CHECK_NE(key2.getName(), key1Name);
268 BOOST_CHECK_EQUAL(id.getKeys().size(), 1);
laqinfan56a812d2019-06-03 15:33:58 -0500269 BOOST_CHECK_NO_THROW(key2.getDefaultCertificate());
Yingdi Yufe4733a2015-10-22 14:24:12 -0700270
271 // Create the third key
272 Key key3 = m_keyChain.createKey(id);
Junxiao Shi72c0c642018-04-20 15:41:09 +0000273 BOOST_CHECK_NE(key3.getName(), key2.getName());
Yingdi Yufe4733a2015-10-22 14:24:12 -0700274 // The added key will not be the default key, because the default key already exists
Junxiao Shi72c0c642018-04-20 15:41:09 +0000275 BOOST_CHECK_EQUAL(id.getDefaultKey().getName(), key2.getName());
Yingdi Yufe4733a2015-10-22 14:24:12 -0700276 BOOST_CHECK_EQUAL(id.getKeys().size(), 2);
laqinfan56a812d2019-06-03 15:33:58 -0500277 BOOST_CHECK_NO_THROW(key3.getDefaultCertificate());
Yingdi Yufe4733a2015-10-22 14:24:12 -0700278
279 // Delete cert
280 BOOST_CHECK_EQUAL(key3.getCertificates().size(), 1);
281 Certificate key3Cert1 = *key3.getCertificates().begin();
282 Name key3CertName = key3Cert1.getName();
283 m_keyChain.deleteCertificate(key3, key3CertName);
284 BOOST_CHECK_EQUAL(key3.getCertificates().size(), 0);
285 BOOST_REQUIRE_THROW(key3.getDefaultCertificate(), Pib::Error);
286
287 // Add cert
288 m_keyChain.addCertificate(key3, key3Cert1);
289 BOOST_CHECK_EQUAL(key3.getCertificates().size(), 1);
laqinfan56a812d2019-06-03 15:33:58 -0500290 BOOST_CHECK_NO_THROW(key3.getDefaultCertificate());
Alexander Afanasyeva10b2ff2017-01-30 12:44:15 -0800291 m_keyChain.addCertificate(key3, key3Cert1); // overwriting the cert should work
Yingdi Yufe4733a2015-10-22 14:24:12 -0700292 BOOST_CHECK_EQUAL(key3.getCertificates().size(), 1);
293 // Add another cert
294 Certificate key3Cert2 = key3Cert1;
295 Name key3Cert2Name = key3.getName();
296 key3Cert2Name.append("Self");
297 key3Cert2Name.appendVersion();
298 key3Cert2.setName(key3Cert2Name);
299 m_keyChain.addCertificate(key3, key3Cert2);
300 BOOST_CHECK_EQUAL(key3.getCertificates().size(), 2);
Davide Pesavento81bd6962020-06-17 16:03:23 -0400301 // Add empty cert
302 Certificate key3Cert3 = key3Cert1;
303 key3Cert3.unsetContent();
304 BOOST_CHECK_THROW(m_keyChain.addCertificate(key3, key3Cert3), std::invalid_argument);
Yingdi Yufe4733a2015-10-22 14:24:12 -0700305
306 // Default certificate setting
307 BOOST_CHECK_EQUAL(key3.getDefaultCertificate().getName(), key3CertName);
308 m_keyChain.setDefaultCertificate(key3, key3Cert2);
309 BOOST_CHECK_EQUAL(key3.getDefaultCertificate().getName(), key3Cert2Name);
310
311 // Default key setting
312 BOOST_CHECK_EQUAL(id.getDefaultKey().getName(), key2.getName());
313 m_keyChain.setDefaultKey(id, key3);
314 BOOST_CHECK_EQUAL(id.getDefaultKey().getName(), key3.getName());
315
316 // Default identity setting
317 Identity id2 = m_keyChain.createIdentity(identity2Name);
318 BOOST_CHECK_EQUAL(m_keyChain.getPib().getDefaultIdentity().getName(), id.getName());
319 m_keyChain.setDefaultIdentity(id2);
320 BOOST_CHECK_EQUAL(m_keyChain.getPib().getDefaultIdentity().getName(), id2.getName());
321
322 // Delete identity
323 m_keyChain.deleteIdentity(id);
324 // The identity instance should not be valid any more
325 BOOST_CHECK(!id);
Davide Pesavento73710362020-12-04 16:10:03 -0500326 BOOST_CHECK_THROW(m_keyChain.getPib().getIdentity(identityName), Pib::Error);
Yingdi Yufe4733a2015-10-22 14:24:12 -0700327 BOOST_CHECK(m_keyChain.getPib().getIdentities().find(identityName) == m_keyChain.getPib().getIdentities().end());
328}
329
Davide Pesavento73710362020-12-04 16:10:03 -0500330struct DataPkt
Yingdi Yufe4733a2015-10-22 14:24:12 -0700331{
Davide Pesavento73710362020-12-04 16:10:03 -0500332 Data packet{"/data"};
333 SignedInterestFormat sigFormat = SignedInterestFormat::V02; // irrelevant for Data
Yingdi Yufe4733a2015-10-22 14:24:12 -0700334
Davide Pesavento73710362020-12-04 16:10:03 -0500335 SignatureInfo
336 getSignatureInfo() const
337 {
338 return packet.getSignatureInfo();
339 }
340};
laqinfan56a812d2019-06-03 15:33:58 -0500341
Davide Pesavento73710362020-12-04 16:10:03 -0500342struct InterestV02Pkt
343{
344 Interest packet = Interest{"/interest02"}.setCanBePrefix(false);
345 SignedInterestFormat sigFormat = SignedInterestFormat::V02;
Eric Newberryb74bbda2020-06-18 19:33:58 -0700346
Davide Pesavento73710362020-12-04 16:10:03 -0500347 SignatureInfo
348 getSignatureInfo() const
349 {
350 return SignatureInfo(packet.getName()[signed_interest::POS_SIG_INFO].blockFromValue());
351 }
352};
Eric Newberryb74bbda2020-06-18 19:33:58 -0700353
Davide Pesavento73710362020-12-04 16:10:03 -0500354struct InterestV03Pkt
355{
356 Interest packet = Interest{"/interest03"}.setCanBePrefix(false);
357 SignedInterestFormat sigFormat = SignedInterestFormat::V03;
Eric Newberryb74bbda2020-06-18 19:33:58 -0700358
Davide Pesavento73710362020-12-04 16:10:03 -0500359 SignatureInfo
360 getSignatureInfo() const
361 {
362 return packet.getSignatureInfo().value(); // use .value() for checked access
363 }
364};
Eric Newberryb74bbda2020-06-18 19:33:58 -0700365
Davide Pesavento73710362020-12-04 16:10:03 -0500366template<typename KeyParams>
367struct DefaultIdentity
368{
369 Identity
370 operator()(KeyChain& keyChain) const
371 {
372 auto id = keyChain.createIdentity("/id", KeyParams());
373 BOOST_ASSERT(keyChain.getPib().getDefaultIdentity() == id);
374 return id;
375 }
376};
Eric Newberryb74bbda2020-06-18 19:33:58 -0700377
Davide Pesavento73710362020-12-04 16:10:03 -0500378template<typename KeyParams>
379struct NonDefaultIdentity
380{
381 Identity
382 operator()(KeyChain& keyChain) const
383 {
384 auto id = keyChain.createIdentity("/id");
385 auto id2 = keyChain.createIdentity("/id2", KeyParams());
386 BOOST_ASSERT(keyChain.getPib().getDefaultIdentity() == id);
387 return id2;
388 }
389};
Eric Newberryb74bbda2020-06-18 19:33:58 -0700390
Davide Pesavento73710362020-12-04 16:10:03 -0500391template<typename KeyParams>
392struct DefaultKey
393{
394 Key
395 operator()(KeyChain&, const Identity& id) const
396 {
397 auto key = id.getDefaultKey();
398 BOOST_ASSERT(key.getKeyType() == KeyParams().getKeyType());
399 return key;
400 }
401};
Eric Newberryb74bbda2020-06-18 19:33:58 -0700402
Davide Pesavento73710362020-12-04 16:10:03 -0500403template<typename KeyParams>
404struct NonDefaultKey
405{
406 Key
407 operator()(KeyChain& keyChain, const Identity& id) const
408 {
409 auto key2 = keyChain.createKey(id, KeyParams());
410 BOOST_ASSERT(id.getDefaultKey() != key2);
411 return key2;
412 }
413};
Eric Newberryb74bbda2020-06-18 19:33:58 -0700414
Davide Pesavento73710362020-12-04 16:10:03 -0500415template<typename PacketType,
416 template<typename> class IdentityMaker = DefaultIdentity,
417 template<typename> class KeyMaker = DefaultKey,
418 typename AsymmetricKeyParams = EcKeyParams,
419 uint32_t SignatureTypeTlvValue = tlv::SignatureSha256WithEcdsa>
420struct AsymmetricSigningBase : protected KeyChainFixture, protected PacketType
421{
422 const Identity id = IdentityMaker<AsymmetricKeyParams>()(m_keyChain);
423 const Key key = KeyMaker<AsymmetricKeyParams>()(m_keyChain, id);
424 const Certificate cert = key.getDefaultCertificate();
425
426 const uint32_t expectedSigType = SignatureTypeTlvValue;
427 const bool shouldHaveKeyLocator = true;
428 const optional<KeyLocator> expectedKeyLocator = cert.getName().getPrefix(-2);
429
430 bool
431 verify(const SigningInfo&) const
432 {
433 return verifySignature(this->packet, key);
434 }
435};
436
437template<typename PacketType,
438 typename AsymmetricKeyParams,
439 uint32_t SignatureTypeTlvValue>
440struct AsymmetricSigning : protected AsymmetricSigningBase<PacketType, DefaultIdentity, DefaultKey,
441 AsymmetricKeyParams, SignatureTypeTlvValue>
442{
443 const std::vector<SigningInfo> signingInfos = {
Yingdi Yufe4733a2015-10-22 14:24:12 -0700444 SigningInfo(),
Davide Pesavento73710362020-12-04 16:10:03 -0500445 SigningInfo(""),
Yingdi Yufe4733a2015-10-22 14:24:12 -0700446
Davide Pesavento73710362020-12-04 16:10:03 -0500447 SigningInfo(this->id),
448 SigningInfo(SigningInfo::SIGNER_TYPE_ID, this->id.getName()),
449 SigningInfo("id:" + this->id.getName().toUri()),
450 signingByIdentity(this->id),
451 signingByIdentity(this->id.getName()),
Yingdi Yufe4733a2015-10-22 14:24:12 -0700452
Davide Pesavento73710362020-12-04 16:10:03 -0500453 SigningInfo(this->key),
454 SigningInfo(SigningInfo::SIGNER_TYPE_KEY, this->key.getName()),
455 SigningInfo("key:" + this->key.getName().toUri()),
456 signingByKey(this->key),
457 signingByKey(this->key.getName()),
Alexander Afanasyevd6d78aa2017-01-02 18:14:23 -0800458
Davide Pesavento73710362020-12-04 16:10:03 -0500459 SigningInfo(SigningInfo::SIGNER_TYPE_CERT, this->cert.getName()),
460 SigningInfo("cert:" + this->cert.getName().toUri()),
461 signingByCertificate(this->cert),
462 signingByCertificate(this->cert.getName()),
463 };
464};
Yingdi Yufe4733a2015-10-22 14:24:12 -0700465
Davide Pesavento73710362020-12-04 16:10:03 -0500466template<typename PacketType>
467using RsaSigning = AsymmetricSigning<PacketType, RsaKeyParams, tlv::SignatureSha256WithRsa>;
Alexander Afanasyevd6d78aa2017-01-02 18:14:23 -0800468
Davide Pesavento73710362020-12-04 16:10:03 -0500469template<typename PacketType>
470using EcdsaSigning = AsymmetricSigning<PacketType, EcKeyParams, tlv::SignatureSha256WithEcdsa>;
Yingdi Yufe4733a2015-10-22 14:24:12 -0700471
Davide Pesavento73710362020-12-04 16:10:03 -0500472template<typename PacketType>
473struct SigningWithNonDefaultIdentity : protected AsymmetricSigningBase<PacketType, NonDefaultIdentity>
474{
475 const std::vector<SigningInfo> signingInfos = {
476 signingByIdentity(this->id),
477 signingByIdentity(this->id.getName()),
478 signingByKey(this->key),
479 signingByCertificate(this->cert),
480 };
481};
482
483template<typename PacketType>
484struct SigningWithNonDefaultKey : protected AsymmetricSigningBase<PacketType, NonDefaultIdentity, NonDefaultKey>
485{
486 const std::vector<SigningInfo> signingInfos = {
487 signingByKey(this->key),
488 signingByKey(this->key.getName()),
489 signingByCertificate(this->cert),
490 };
491};
492
493template<typename PacketType,
494 DigestAlgorithm DigestAlgo = DigestAlgorithm::SHA256,
495 uint32_t SignatureTypeTlvValue = tlv::SignatureHmacWithSha256>
496struct HmacSigning : protected KeyChainFixture, protected PacketType
497{
498 const std::vector<SigningInfo> signingInfos = {
499 SigningInfo(SigningInfo::SIGNER_TYPE_HMAC, m_keyChain.createHmacKey()),
laqinfan56a812d2019-06-03 15:33:58 -0500500 SigningInfo("hmac-sha256:QjM3NEEyNkE3MTQ5MDQzN0FBMDI0RTRGQURENUI0OTdGREZGMUE4RUE2RkYxMkY2RkI2NUFGMjcyMEI1OUNDRg=="),
Davide Pesavento73710362020-12-04 16:10:03 -0500501 };
laqinfan56a812d2019-06-03 15:33:58 -0500502
Davide Pesavento73710362020-12-04 16:10:03 -0500503 const uint32_t expectedSigType = SignatureTypeTlvValue;
504 const bool shouldHaveKeyLocator = true;
505 const optional<KeyLocator> expectedKeyLocator = nullopt; // don't check KeyLocator value
506
507 bool
508 verify(const SigningInfo& si) const
509 {
510 return verifySignature(this->packet, m_keyChain.getTpm(), si.getSignerName(), DigestAlgo);
511 }
512};
513
514template<typename PacketType>
515struct Sha256Signing : protected KeyChainFixture, protected PacketType
516{
517 const std::vector<SigningInfo> signingInfos = {
Yingdi Yufe4733a2015-10-22 14:24:12 -0700518 SigningInfo(SigningInfo::SIGNER_TYPE_SHA256),
Davide Pesavento73710362020-12-04 16:10:03 -0500519 SigningInfo("id:" + SigningInfo::getDigestSha256Identity().toUri()),
Yingdi Yufe4733a2015-10-22 14:24:12 -0700520 signingWithSha256()
521 };
522
Davide Pesavento73710362020-12-04 16:10:03 -0500523 const uint32_t expectedSigType = tlv::DigestSha256;
524 const bool shouldHaveKeyLocator = false;
525 const optional<KeyLocator> expectedKeyLocator = nullopt;
Yingdi Yufe4733a2015-10-22 14:24:12 -0700526
Davide Pesavento73710362020-12-04 16:10:03 -0500527 bool
528 verify(const SigningInfo&) const
529 {
Davide Pesavento809f7542021-03-24 18:53:05 -0400530 return verifySignature(this->packet, nullopt);
Davide Pesavento73710362020-12-04 16:10:03 -0500531 }
532};
Yingdi Yufe4733a2015-10-22 14:24:12 -0700533
Davide Pesavento73710362020-12-04 16:10:03 -0500534using SigningTests = boost::mpl::vector<
535 RsaSigning<DataPkt>,
536 RsaSigning<InterestV02Pkt>,
537 RsaSigning<InterestV03Pkt>,
538 EcdsaSigning<DataPkt>,
539 EcdsaSigning<InterestV02Pkt>,
540 EcdsaSigning<InterestV03Pkt>,
Davide Pesavento94dfcf12021-09-26 14:18:45 -0400541#if OPENSSL_VERSION_NUMBER < 0x30000000L // FIXME #5154
Davide Pesavento73710362020-12-04 16:10:03 -0500542 HmacSigning<DataPkt>,
543 HmacSigning<InterestV02Pkt>,
544 HmacSigning<InterestV03Pkt>,
Davide Pesavento94dfcf12021-09-26 14:18:45 -0400545#endif
Davide Pesavento73710362020-12-04 16:10:03 -0500546 Sha256Signing<DataPkt>,
547 Sha256Signing<InterestV02Pkt>,
548 Sha256Signing<InterestV03Pkt>,
549 SigningWithNonDefaultIdentity<DataPkt>,
Davide Pesavento809f7542021-03-24 18:53:05 -0400550 SigningWithNonDefaultIdentity<InterestV03Pkt>,
551 SigningWithNonDefaultKey<DataPkt>,
552 SigningWithNonDefaultKey<InterestV03Pkt>
Davide Pesavento73710362020-12-04 16:10:03 -0500553>;
Eric Newberryb74bbda2020-06-18 19:33:58 -0700554
Davide Pesavento73710362020-12-04 16:10:03 -0500555BOOST_FIXTURE_TEST_CASE_TEMPLATE(SigningInterface, T, SigningTests, T)
556{
557 BOOST_TEST_CONTEXT("Packet = " << this->packet.getName()) {
558 for (auto signingInfo : this->signingInfos) {
559 signingInfo.setSignedInterestFormat(this->sigFormat);
560
561 BOOST_TEST_CONTEXT("SigningInfo = " << signingInfo) {
562 this->m_keyChain.sign(this->packet, signingInfo);
563
564 auto sigInfo = this->getSignatureInfo();
565 BOOST_CHECK_EQUAL(sigInfo.getSignatureType(), this->expectedSigType);
566 BOOST_CHECK_EQUAL(sigInfo.hasKeyLocator(), this->shouldHaveKeyLocator);
567 if (this->expectedKeyLocator) {
568 BOOST_CHECK_EQUAL(sigInfo.getKeyLocator(), *this->expectedKeyLocator);
569 }
570 BOOST_CHECK(this->verify(signingInfo));
Eric Newberryb74bbda2020-06-18 19:33:58 -0700571 }
Yingdi Yufe4733a2015-10-22 14:24:12 -0700572 }
573 }
574}
575
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500576BOOST_FIXTURE_TEST_CASE(ImportPrivateKey, KeyChainFixture)
laqinfan56a812d2019-06-03 15:33:58 -0500577{
578 Name keyName("/test/device2");
579 std::string rawKey("nPSNOHyZKsg2WLqHAs7MXGb0sjQb4zCT");
580 auto key = make_shared<transform::PrivateKey>();
581 key->loadRaw(KeyType::HMAC, reinterpret_cast<const uint8_t*>(rawKey.data()), rawKey.size());
582
583 m_keyChain.importPrivateKey(keyName, key);
584 BOOST_CHECK_EQUAL(m_keyChain.getTpm().hasKey(keyName), true);
585 BOOST_CHECK_THROW(m_keyChain.importPrivateKey(keyName, key), KeyChain::Error);
586}
587
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500588BOOST_FIXTURE_TEST_CASE(ExportImport, KeyChainFixture)
Yingdi Yufe4733a2015-10-22 14:24:12 -0700589{
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500590 Identity id = m_keyChain.createIdentity("/TestKeyChain/ExportIdentity");
Yingdi Yufe4733a2015-10-22 14:24:12 -0700591 Certificate cert = id.getDefaultKey().getDefaultCertificate();
592
593 shared_ptr<SafeBag> exported = m_keyChain.exportSafeBag(cert, "1234", 4);
594 Block block = exported->wireEncode();
595
596 m_keyChain.deleteIdentity(id);
Davide Pesavento82d6a4c2017-12-23 19:47:20 -0500597 BOOST_CHECK_THROW(m_keyChain.exportSafeBag(cert, "1234", 4), KeyChain::Error);
Yingdi Yufe4733a2015-10-22 14:24:12 -0700598
599 BOOST_CHECK_EQUAL(m_keyChain.getTpm().hasKey(cert.getKeyName()), false);
600 BOOST_CHECK_EQUAL(m_keyChain.getPib().getIdentities().size(), 0);
601
602 SafeBag imported;
603 imported.wireDecode(block);
604 m_keyChain.importSafeBag(imported, "1234", 4);
Davide Pesavento82d6a4c2017-12-23 19:47:20 -0500605 BOOST_CHECK_THROW(m_keyChain.importSafeBag(imported, "1234", 4), KeyChain::Error);
Yingdi Yufe4733a2015-10-22 14:24:12 -0700606
607 BOOST_CHECK_EQUAL(m_keyChain.getTpm().hasKey(cert.getKeyName()), true);
608 BOOST_CHECK_EQUAL(m_keyChain.getPib().getIdentities().size(), 1);
Yingdi Yufe4733a2015-10-22 14:24:12 -0700609 Identity newId = m_keyChain.getPib().getIdentity(cert.getIdentity());
610 BOOST_CHECK_EQUAL(newId.getKeys().size(), 1);
Yingdi Yufe4733a2015-10-22 14:24:12 -0700611 Key newKey = newId.getKey(cert.getKeyName());
612 BOOST_CHECK_EQUAL(newKey.getCertificates().size(), 1);
laqinfan56a812d2019-06-03 15:33:58 -0500613 BOOST_CHECK_NO_THROW(newKey.getCertificate(cert.getName()));
Yingdi Yufe4733a2015-10-22 14:24:12 -0700614
615 m_keyChain.deleteIdentity(newId);
616 BOOST_CHECK_EQUAL(m_keyChain.getPib().getIdentities().size(), 0);
617 BOOST_CHECK_EQUAL(m_keyChain.getTpm().hasKey(cert.getKeyName()), false);
618}
619
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500620BOOST_FIXTURE_TEST_CASE(SelfSignedCertValidity, KeyChainFixture)
Alexander Afanasyevf8379172017-01-11 16:56:04 -0800621{
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500622 Certificate cert = m_keyChain.createIdentity("/Security/TestKeyChain/SelfSignedCertValidity")
Alexander Afanasyevf8379172017-01-11 16:56:04 -0800623 .getDefaultKey()
624 .getDefaultCertificate();
625 BOOST_CHECK(cert.isValid());
Davide Pesavento0f830802018-01-16 23:58:58 -0500626 BOOST_CHECK(cert.isValid(time::system_clock::now() + 10 * 365_days));
627 BOOST_CHECK_GT(cert.getValidityPeriod().getPeriod().second, time::system_clock::now() + 10 * 365_days);
Alexander Afanasyevf8379172017-01-11 16:56:04 -0800628}
629
Yingdi Yufe4733a2015-10-22 14:24:12 -0700630BOOST_AUTO_TEST_SUITE_END() // TestKeyChain
Yingdi Yufe4733a2015-10-22 14:24:12 -0700631BOOST_AUTO_TEST_SUITE_END() // Security
632
633} // namespace tests
Alexander Afanasyev09236c22020-06-03 13:42:38 -0400634} // inline namespace v2
Yingdi Yufe4733a2015-10-22 14:24:12 -0700635} // namespace security
636} // namespace ndn