Rename 'tests/unit-tests' directory to 'tests/unit'
Change-Id: I78ea29938259fac288781bed12fb2399ac7eba26
diff --git a/tests/unit/security/command-interest-signer.t.cpp b/tests/unit/security/command-interest-signer.t.cpp
new file mode 100644
index 0000000..784a209
--- /dev/null
+++ b/tests/unit/security/command-interest-signer.t.cpp
@@ -0,0 +1,69 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/command-interest-signer.hpp"
+#include "security/signing-helpers.hpp"
+
+#include "boost-test.hpp"
+#include "../identity-management-time-fixture.hpp"
+
+namespace ndn {
+namespace security {
+namespace tests {
+
+using namespace ndn::tests;
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_FIXTURE_TEST_SUITE(TestCommandInterestSigner, IdentityManagementTimeFixture)
+
+BOOST_AUTO_TEST_CASE(Basic)
+{
+ addIdentity("/test");
+
+ CommandInterestSigner signer(m_keyChain);
+ Interest i1 = signer.makeCommandInterest("/hello/world");
+ BOOST_CHECK_EQUAL(i1.getName().size(), 6);
+ BOOST_CHECK_EQUAL(i1.getName().at(command_interest::POS_SIG_VALUE).blockFromValue().type(), tlv::SignatureValue);
+ BOOST_CHECK_EQUAL(i1.getName().at(command_interest::POS_SIG_INFO).blockFromValue().type(), tlv::SignatureInfo);
+
+ time::milliseconds timestamp = toUnixTimestamp(time::system_clock::now());
+ BOOST_CHECK_EQUAL(i1.getName().at(command_interest::POS_TIMESTAMP).toNumber(), timestamp.count());
+
+ Interest i2 = signer.makeCommandInterest("/hello/world/!", signingByIdentity("/test"));
+ BOOST_CHECK_EQUAL(i2.getName().size(), 7);
+ BOOST_CHECK_EQUAL(i2.getName().at(command_interest::POS_SIG_VALUE).blockFromValue().type(), tlv::SignatureValue);
+ BOOST_CHECK_EQUAL(i2.getName().at(command_interest::POS_SIG_INFO).blockFromValue().type(), tlv::SignatureInfo);
+ BOOST_CHECK_GT(i2.getName().at(command_interest::POS_TIMESTAMP), i1.getName().at(command_interest::POS_TIMESTAMP));
+ BOOST_CHECK_NE(i2.getName().at(command_interest::POS_RANDOM_VAL),
+ i1.getName().at(command_interest::POS_RANDOM_VAL)); // this sometimes can fail
+
+ advanceClocks(100_s);
+
+ i2 = signer.makeCommandInterest("/hello/world/!");
+ BOOST_CHECK_GT(i2.getName().at(command_interest::POS_TIMESTAMP), i1.getName().at(command_interest::POS_TIMESTAMP));
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestCommandInterestSigner
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/config-file-readme.txt b/tests/unit/security/config-file-readme.txt
new file mode 100644
index 0000000..44e5f61
--- /dev/null
+++ b/tests/unit/security/config-file-readme.txt
@@ -0,0 +1,11 @@
+In test, we set a test-specific "HOME", which cause OS X keychain look for the
+default keychain of a "different" user. If the default keychain does not exist,
+all subsequent calls to OS X keychain will fail. User interaction (such as
+specifying password) is required to create a keychain. However, user interaction
+is not feasible in automated tests.
+
+This problem is caused by the OS X system assumption that one user must have a
+login keychain, which is also the user's default keychain, because a user
+account is always created with a login keychain as default. Thus OS X system
+infers a user according to the HOME env, and did not expect user to change the
+HOME env in normal use.
diff --git a/tests/unit/security/digest-sha256.t.cpp b/tests/unit/security/digest-sha256.t.cpp
new file mode 100644
index 0000000..7c1d236
--- /dev/null
+++ b/tests/unit/security/digest-sha256.t.cpp
@@ -0,0 +1,74 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/digest-sha256.hpp"
+#include "security/verification-helpers.hpp"
+#include "util/sha256.hpp"
+#include "util/string-helper.hpp"
+
+#include "identity-management-fixture.hpp"
+#include "boost-test.hpp"
+
+namespace ndn {
+namespace security {
+namespace tests {
+
+using namespace ndn::tests;
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_FIXTURE_TEST_SUITE(TestDigestSha256, IdentityManagementFixture)
+
+BOOST_AUTO_TEST_CASE(Sha256)
+{
+ char content[6] = "1234\n";
+ ConstBufferPtr buf = util::Sha256::computeDigest(reinterpret_cast<uint8_t*>(content), 5);
+
+ BOOST_CHECK_EQUAL(toHex(buf->data(), buf->size(), false),
+ "a883dafc480d466ee04e0d6da986bd78eb1fdd2178d04693723da3a8f95d42f4");
+}
+
+BOOST_AUTO_TEST_CASE(DataSignature)
+{
+ Name name("/TestSignatureSha/Basic");
+ Data testData(name);
+ char content[5] = "1234";
+ testData.setContent(reinterpret_cast<uint8_t*>(content), 5);
+ m_keyChain.sign(testData, security::SigningInfo(security::SigningInfo::SIGNER_TYPE_SHA256));
+
+ BOOST_CHECK_THROW(testData.getSignature().getKeyLocator(), ndn::SignatureInfo::Error);
+ verifyDigest(testData, DigestAlgorithm::SHA256);
+}
+
+BOOST_AUTO_TEST_CASE(InterestSignature)
+{
+ Name name("/SecurityTestDigestSha256/InterestSignature/Interest1");
+ Interest testInterest(name);
+
+ m_keyChain.sign(testInterest, security::SigningInfo(security::SigningInfo::SIGNER_TYPE_SHA256));
+ verifyDigest(testInterest, DigestAlgorithm::SHA256);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestDigestSha256
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/key-params.t.cpp b/tests/unit/security/key-params.t.cpp
new file mode 100644
index 0000000..991c346
--- /dev/null
+++ b/tests/unit/security/key-params.t.cpp
@@ -0,0 +1,122 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/key-params.hpp"
+
+#include "boost-test.hpp"
+
+#include <boost/lexical_cast.hpp>
+
+namespace ndn {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(TestKeyParams)
+
+BOOST_AUTO_TEST_CASE(Rsa)
+{
+ RsaKeyParams params;
+ BOOST_CHECK_EQUAL(params.getKeyType(), KeyType::RSA);
+ BOOST_CHECK_EQUAL(params.getKeySize(), 2048);
+ BOOST_CHECK(params.getKeyIdType() == KeyIdType::RANDOM);
+
+ RsaKeyParams params2(4096, KeyIdType::SHA256);
+ BOOST_CHECK_EQUAL(params2.getKeyType(), KeyType::RSA);
+ BOOST_CHECK_EQUAL(params2.getKeySize(), 4096);
+ BOOST_CHECK(params2.getKeyIdType() == KeyIdType::SHA256);
+
+ BOOST_CHECK_THROW(RsaKeyParams(1024), KeyParams::Error);
+
+ name::Component keyId("keyId");
+ RsaKeyParams params4(keyId);
+ BOOST_CHECK(params4.getKeyType() == KeyType::RSA);
+ BOOST_CHECK_EQUAL(params4.getKeySize(), 2048);
+ BOOST_CHECK(params4.getKeyIdType() == KeyIdType::USER_SPECIFIED);
+ BOOST_CHECK_EQUAL(params4.getKeyId(), keyId);
+}
+
+BOOST_AUTO_TEST_CASE(Ec)
+{
+ EcKeyParams params;
+ BOOST_CHECK_EQUAL(params.getKeyType(), KeyType::EC);
+ BOOST_CHECK_EQUAL(params.getKeySize(), 256);
+ BOOST_CHECK(params.getKeyIdType() == KeyIdType::RANDOM);
+
+ EcKeyParams params2(384, KeyIdType::SHA256);
+ BOOST_CHECK_EQUAL(params2.getKeyType(), KeyType::EC);
+ BOOST_CHECK_EQUAL(params2.getKeySize(), 384);
+ BOOST_CHECK(params2.getKeyIdType() == KeyIdType::SHA256);
+
+ BOOST_CHECK_THROW(EcKeyParams(3), KeyParams::Error);
+
+ name::Component keyId("keyId");
+ EcKeyParams params4(keyId);
+ BOOST_CHECK(params4.getKeyType() == KeyType::EC);
+ BOOST_CHECK_EQUAL(params4.getKeySize(), 256);
+ BOOST_CHECK(params4.getKeyIdType() == KeyIdType::USER_SPECIFIED);
+ BOOST_CHECK_EQUAL(params4.getKeyId(), keyId);
+}
+
+BOOST_AUTO_TEST_CASE(Aes)
+{
+ name::Component keyId("keyId");
+ AesKeyParams params(keyId);
+ BOOST_CHECK_EQUAL(params.getKeyType(), KeyType::AES);
+ BOOST_CHECK_EQUAL(params.getKeySize(), 128);
+ BOOST_CHECK_EQUAL(params.getKeyIdType(), KeyIdType::USER_SPECIFIED);
+
+ AesKeyParams params2(keyId, 192);
+ BOOST_CHECK(params2.getKeyType() == KeyType::AES);
+ BOOST_CHECK_EQUAL(params2.getKeySize(), 192);
+ BOOST_CHECK(params.getKeyIdType() == KeyIdType::USER_SPECIFIED);
+
+ AesKeyParams params3(keyId, 256);
+ BOOST_CHECK_EQUAL(params3.getKeyType(), KeyType::AES);
+ BOOST_CHECK_EQUAL(params3.getKeySize(), 256);
+ BOOST_CHECK(params.getKeyIdType() == KeyIdType::USER_SPECIFIED);
+
+ BOOST_CHECK_THROW(AesKeyParams(keyId, 4), KeyParams::Error);
+
+ AesKeyParams params5(keyId);
+ BOOST_CHECK_EQUAL(params5.getKeyType(), KeyType::AES);
+ BOOST_CHECK_EQUAL(params5.getKeySize(), 128);
+ BOOST_CHECK_EQUAL(params5.getKeyIdType(), KeyIdType::USER_SPECIFIED);
+ BOOST_CHECK_EQUAL(params5.getKeyId(), keyId);
+
+ AesKeyParams params6(192);
+ BOOST_CHECK(params6.getKeyType() == KeyType::AES);
+ BOOST_CHECK_EQUAL(params6.getKeySize(), 192);
+ BOOST_CHECK(params6.getKeyIdType() == KeyIdType::RANDOM);
+}
+
+BOOST_AUTO_TEST_CASE(KeyIdTypeInfo)
+{
+ BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(KeyIdType::USER_SPECIFIED), "USER_SPECIFIED");
+ BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(KeyIdType::SHA256), "SHA256");
+ BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(KeyIdType::RANDOM), "RANDOM");
+ BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(static_cast<KeyIdType>(12345)), "12345");
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestKeyParams
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace ndn
diff --git a/tests/unit/security/pib/certificate-container.t.cpp b/tests/unit/security/pib/certificate-container.t.cpp
new file mode 100644
index 0000000..6614531
--- /dev/null
+++ b/tests/unit/security/pib/certificate-container.t.cpp
@@ -0,0 +1,167 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/pib/certificate-container.hpp"
+#include "security/pib/pib.hpp"
+#include "security/pib/pib-memory.hpp"
+
+#include "boost-test.hpp"
+#include "pib-data-fixture.hpp"
+
+namespace ndn {
+namespace security {
+namespace pib {
+namespace tests {
+
+using namespace ndn::security::tests;
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(Pib)
+BOOST_FIXTURE_TEST_SUITE(TestCertificateContainer, PibDataFixture)
+
+using pib::Pib;
+
+BOOST_AUTO_TEST_CASE(Basic)
+{
+ auto pibImpl = make_shared<PibMemory>();
+
+ // start with an empty container
+ CertificateContainer container(id1Key1Name, pibImpl);
+ BOOST_CHECK_EQUAL(container.size(), 0);
+ BOOST_CHECK_EQUAL(container.getCache().size(), 0);
+
+ // add one cert
+ container.add(id1Key1Cert1);
+ BOOST_CHECK_EQUAL(container.size(), 1);
+ BOOST_CHECK_EQUAL(container.getCache().size(), 1);
+ BOOST_CHECK(container.find(id1Key1Cert1.getName()) != container.end());
+
+ // add the same cert again
+ container.add(id1Key1Cert1);
+ BOOST_CHECK_EQUAL(container.size(), 1);
+ BOOST_CHECK_EQUAL(container.getCache().size(), 1);
+ BOOST_CHECK(container.find(id1Key1Cert1.getName()) != container.end());
+
+ // add another cert
+ container.add(id1Key1Cert2);
+ BOOST_CHECK_EQUAL(container.size(), 2);
+ BOOST_CHECK_EQUAL(container.getCache().size(), 2);
+ BOOST_CHECK(container.find(id1Key1Cert1.getName()) != container.end());
+ BOOST_CHECK(container.find(id1Key1Cert2.getName()) != container.end());
+
+ // get certs
+ BOOST_REQUIRE_NO_THROW(container.get(id1Key1Cert1.getName()));
+ BOOST_REQUIRE_NO_THROW(container.get(id1Key1Cert2.getName()));
+ Name id1Key1Cert3Name = id1Key1Name;
+ id1Key1Cert3Name.append("issuer").appendVersion(3);
+ BOOST_CHECK_THROW(container.get(id1Key1Cert3Name), Pib::Error);
+
+ // check cert
+ v2::Certificate cert1 = container.get(id1Key1Cert1.getName());
+ v2::Certificate cert2 = container.get(id1Key1Cert2.getName());
+ BOOST_CHECK_EQUAL(cert1, id1Key1Cert1);
+ BOOST_CHECK_EQUAL(cert2, id1Key1Cert2);
+
+ // create another container from the same PibImpl
+ // cache should be empty
+ CertificateContainer container2(id1Key1Name, pibImpl);
+ BOOST_CHECK_EQUAL(container2.size(), 2);
+ BOOST_CHECK_EQUAL(container2.getCache().size(), 0);
+
+ // get certificate, cache should be filled
+ BOOST_REQUIRE_NO_THROW(container2.get(id1Key1Cert1.getName()));
+ BOOST_CHECK_EQUAL(container2.size(), 2);
+ BOOST_CHECK_EQUAL(container2.getCache().size(), 1);
+
+ BOOST_REQUIRE_NO_THROW(container2.get(id1Key1Cert2.getName()));
+ BOOST_CHECK_EQUAL(container2.size(), 2);
+ BOOST_CHECK_EQUAL(container2.getCache().size(), 2);
+
+ // remove a certificate
+ container2.remove(id1Key1Cert1.getName());
+ BOOST_CHECK_EQUAL(container2.size(), 1);
+ BOOST_CHECK_EQUAL(container2.getCache().size(), 1);
+ BOOST_CHECK(container2.find(id1Key1Cert1.getName()) == container2.end());
+ BOOST_CHECK(container2.find(id1Key1Cert2.getName()) != container2.end());
+
+ // remove another certificate
+ container2.remove(id1Key1Cert2.getName());
+ BOOST_CHECK_EQUAL(container2.size(), 0);
+ BOOST_CHECK_EQUAL(container2.getCache().size(), 0);
+ BOOST_CHECK(container2.find(id1Key1Cert2.getName()) == container2.end());
+}
+
+BOOST_AUTO_TEST_CASE(Errors)
+{
+ auto pibImpl = make_shared<PibMemory>();
+
+ CertificateContainer container(id1Key1Name, pibImpl);
+
+ BOOST_CHECK_THROW(container.add(id1Key2Cert1), std::invalid_argument);
+ BOOST_CHECK_THROW(container.remove(id1Key2Cert1.getName()), std::invalid_argument);
+ BOOST_CHECK_THROW(container.get(id1Key2Cert1.getName()), std::invalid_argument);
+}
+
+BOOST_AUTO_TEST_CASE(Iterator)
+{
+ auto pibImpl = make_shared<PibMemory>();
+
+ // start with an empty container
+ CertificateContainer container(id1Key1Name, pibImpl);
+ container.add(id1Key1Cert1);
+ container.add(id1Key1Cert2);
+
+ std::set<Name> certNames;
+ certNames.insert(id1Key1Cert1.getName());
+ certNames.insert(id1Key1Cert2.getName());
+
+ CertificateContainer::const_iterator it = container.begin();
+ std::set<Name>::const_iterator testIt = certNames.begin();
+ BOOST_CHECK_EQUAL((*it).getName(), *testIt);
+ it++;
+ testIt++;
+ BOOST_CHECK_EQUAL((*it).getName(), *testIt);
+ ++it;
+ testIt++;
+ BOOST_CHECK(it == container.end());
+
+ size_t count = 0;
+ testIt = certNames.begin();
+ for (const auto& cert : container) {
+ BOOST_CHECK_EQUAL(cert.getName(), *testIt);
+ testIt++;
+ count++;
+ }
+ BOOST_CHECK_EQUAL(count, 2);
+
+ BOOST_CHECK(CertificateContainer::const_iterator() == CertificateContainer::const_iterator());
+ BOOST_CHECK(CertificateContainer::const_iterator() == container.end());
+ BOOST_CHECK(container.end() == CertificateContainer::const_iterator());
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestCertificateContainer
+BOOST_AUTO_TEST_SUITE_END() // Pib
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace pib
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/pib/detail/identity-impl.t.cpp b/tests/unit/security/pib/detail/identity-impl.t.cpp
new file mode 100644
index 0000000..209a6b6
--- /dev/null
+++ b/tests/unit/security/pib/detail/identity-impl.t.cpp
@@ -0,0 +1,160 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/pib/detail/identity-impl.hpp"
+#include "security/pib/pib.hpp"
+#include "security/pib/pib-memory.hpp"
+
+#include "boost-test.hpp"
+#include "../pib-data-fixture.hpp"
+
+namespace ndn {
+namespace security {
+namespace pib {
+namespace detail {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(Pib)
+BOOST_AUTO_TEST_SUITE(Detail)
+BOOST_FIXTURE_TEST_SUITE(TestIdentityImpl, ndn::security::tests::PibDataFixture)
+
+using security::Pib;
+
+BOOST_AUTO_TEST_CASE(Basic)
+{
+ auto pibImpl = make_shared<pib::PibMemory>();
+ IdentityImpl identity1(id1, pibImpl, true);
+
+ BOOST_CHECK_EQUAL(identity1.getName(), id1);
+}
+
+BOOST_AUTO_TEST_CASE(KeyOperation)
+{
+ auto pibImpl = make_shared<pib::PibMemory>();
+ IdentityImpl identity1(id1, pibImpl, true);
+ BOOST_CHECK_NO_THROW(IdentityImpl(id1, pibImpl, false));
+
+ // identity does not have any key
+ BOOST_CHECK_EQUAL(identity1.getKeys().size(), 0);
+
+ // get non-existing key, throw Pib::Error
+ BOOST_CHECK_THROW(identity1.getKey(id1Key1Name), Pib::Error);
+ // get default key, throw Pib::Error
+ BOOST_CHECK_THROW(identity1.getDefaultKey(), Pib::Error);
+ // set non-existing key as default key, throw Pib::Error
+ BOOST_REQUIRE_THROW(identity1.setDefaultKey(id1Key1Name), Pib::Error);
+
+ // add key
+ identity1.addKey(id1Key1.data(), id1Key1.size(), id1Key1Name);
+ BOOST_CHECK_NO_THROW(identity1.getKey(id1Key1Name));
+
+ // new key becomes default key when there is no default key
+ BOOST_REQUIRE_NO_THROW(identity1.getDefaultKey());
+ const Key& defaultKey0 = identity1.getDefaultKey();
+ BOOST_CHECK_EQUAL(defaultKey0.getName(), id1Key1Name);
+ BOOST_CHECK(defaultKey0.getPublicKey() == id1Key1);
+
+ // remove key
+ identity1.removeKey(id1Key1Name);
+ BOOST_CHECK_THROW(identity1.getKey(id1Key1Name), Pib::Error);
+ BOOST_CHECK_THROW(identity1.getDefaultKey(), Pib::Error);
+
+ // set default key directly
+ BOOST_REQUIRE_NO_THROW(identity1.setDefaultKey(id1Key1.data(), id1Key1.size(), id1Key1Name));
+ BOOST_REQUIRE_NO_THROW(identity1.getDefaultKey());
+ BOOST_CHECK_NO_THROW(identity1.getKey(id1Key1Name));
+
+ // check default key
+ const Key& defaultKey1 = identity1.getDefaultKey();
+ BOOST_CHECK_EQUAL(defaultKey1.getName(), id1Key1Name);
+ BOOST_CHECK(defaultKey1.getPublicKey() == id1Key1);
+
+ // add another key
+ identity1.addKey(id1Key2.data(), id1Key2.size(), id1Key2Name);
+ BOOST_CHECK_EQUAL(identity1.getKeys().size(), 2);
+
+ // set default key through name
+ BOOST_REQUIRE_NO_THROW(identity1.setDefaultKey(id1Key2Name));
+ BOOST_REQUIRE_NO_THROW(identity1.getDefaultKey());
+ const Key& defaultKey2 = identity1.getDefaultKey();
+ BOOST_CHECK_EQUAL(defaultKey2.getName(), id1Key2Name);
+ BOOST_CHECK(defaultKey2.getPublicKey() == id1Key2);
+
+ // remove key
+ identity1.removeKey(id1Key1Name);
+ BOOST_CHECK_THROW(identity1.getKey(id1Key1Name), Pib::Error);
+ BOOST_CHECK_EQUAL(identity1.getKeys().size(), 1);
+
+ // set default key directly again, change the default setting
+ BOOST_REQUIRE_NO_THROW(identity1.setDefaultKey(id1Key1.data(), id1Key1.size(), id1Key1Name));
+ const Key& defaultKey3 = identity1.getDefaultKey();
+ BOOST_CHECK_EQUAL(defaultKey3.getName(), id1Key1Name);
+ BOOST_CHECK(defaultKey3.getPublicKey() == id1Key1);
+ BOOST_CHECK_EQUAL(identity1.getKeys().size(), 2);
+
+ // remove all keys
+ identity1.removeKey(id1Key1Name);
+ BOOST_CHECK_THROW(identity1.getKey(id1Key1Name), Pib::Error);
+ BOOST_CHECK_EQUAL(identity1.getKeys().size(), 1);
+ identity1.removeKey(id1Key2Name);
+ BOOST_CHECK_THROW(identity1.getKey(id1Key2Name), Pib::Error);
+ BOOST_CHECK_EQUAL(identity1.getKeys().size(), 0);
+ BOOST_CHECK_THROW(identity1.getDefaultKey(), Pib::Error);
+}
+
+BOOST_AUTO_TEST_CASE(Overwrite)
+{
+ auto pibImpl = make_shared<pib::PibMemory>();
+ IdentityImpl identity1(id1, pibImpl, true);
+
+ identity1.addKey(id1Key1.data(), id1Key1.size(), id1Key1Name);
+ BOOST_CHECK(identity1.getKey(id1Key1Name).getPublicKey() == id1Key1);
+
+ identity1.addKey(id1Key2.data(), id1Key2.size(), id1Key1Name); // overwriting key should work
+ BOOST_CHECK(identity1.getKey(id1Key1Name).getPublicKey() == id1Key2);
+}
+
+BOOST_AUTO_TEST_CASE(Errors)
+{
+ auto pibImpl = make_shared<pib::PibMemory>();
+
+ BOOST_CHECK_THROW(IdentityImpl(id1, pibImpl, false), Pib::Error);
+ IdentityImpl identity1(id1, pibImpl, true);
+
+ identity1.addKey(id1Key1.data(), id1Key1.size(), id1Key1Name);
+ BOOST_CHECK_THROW(identity1.addKey(id2Key1.data(), id2Key1.size(), id2Key1Name), std::invalid_argument);
+ BOOST_CHECK_THROW(identity1.removeKey(id2Key1Name), std::invalid_argument);
+ BOOST_CHECK_THROW(identity1.getKey(id2Key1Name), std::invalid_argument);
+ BOOST_CHECK_THROW(identity1.setDefaultKey(id2Key1.data(), id2Key1.size(), id2Key1Name), std::invalid_argument);
+ BOOST_CHECK_THROW(identity1.setDefaultKey(id2Key1Name), std::invalid_argument);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestIdentityImpl
+BOOST_AUTO_TEST_SUITE_END() // Detail
+BOOST_AUTO_TEST_SUITE_END() // Pib
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace detail
+} // namespace pib
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/pib/detail/key-impl.t.cpp b/tests/unit/security/pib/detail/key-impl.t.cpp
new file mode 100644
index 0000000..517ea60
--- /dev/null
+++ b/tests/unit/security/pib/detail/key-impl.t.cpp
@@ -0,0 +1,200 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/pib/detail/key-impl.hpp"
+#include "security/pib/pib.hpp"
+#include "security/pib/pib-memory.hpp"
+#include "../pib-data-fixture.hpp"
+
+#include "boost-test.hpp"
+#include "identity-management-fixture.hpp"
+
+namespace ndn {
+namespace security {
+namespace pib {
+namespace detail {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(Pib)
+BOOST_AUTO_TEST_SUITE(Detail)
+BOOST_FIXTURE_TEST_SUITE(TestKeyImpl, security::tests::PibDataFixture)
+
+using security::Pib;
+
+BOOST_AUTO_TEST_CASE(Basic)
+{
+ auto pibImpl = make_shared<pib::PibMemory>();
+ KeyImpl key11(id1Key1Name, id1Key1.data(), id1Key1.size(), pibImpl);
+
+ BOOST_CHECK_EQUAL(key11.getName(), id1Key1Name);
+ BOOST_CHECK_EQUAL(key11.getIdentity(), id1);
+ BOOST_CHECK_EQUAL(key11.getKeyType(), KeyType::EC);
+ BOOST_CHECK(key11.getPublicKey() == id1Key1);
+
+ KeyImpl key11Bak(id1Key1Name, pibImpl);
+ BOOST_CHECK_EQUAL(key11Bak.getName(), id1Key1Name);
+ BOOST_CHECK_EQUAL(key11Bak.getIdentity(), id1);
+ BOOST_CHECK_EQUAL(key11Bak.getKeyType(), KeyType::EC);
+ BOOST_CHECK(key11Bak.getPublicKey() == id1Key1);
+}
+
+BOOST_AUTO_TEST_CASE(CertificateOperation)
+{
+ auto pibImpl = make_shared<pib::PibMemory>();
+ KeyImpl key11(id1Key1Name, id1Key1.data(), id1Key1.size(), pibImpl);
+ BOOST_CHECK_NO_THROW(KeyImpl(id1Key1Name, pibImpl));
+
+ // key does not have any certificate
+ BOOST_CHECK_EQUAL(key11.getCertificates().size(), 0);
+
+ // get non-existing certificate, throw Pib::Error
+ BOOST_CHECK_THROW(key11.getCertificate(id1Key1Cert1.getName()), Pib::Error);
+ // get default certificate, throw Pib::Error
+ BOOST_CHECK_THROW(key11.getDefaultCertificate(), Pib::Error);
+ // set non-existing certificate as default certificate, throw Pib::Error
+ BOOST_REQUIRE_THROW(key11.setDefaultCertificate(id1Key1Cert1.getName()), Pib::Error);
+
+ // add certificate
+ key11.addCertificate(id1Key1Cert1);
+ BOOST_CHECK_NO_THROW(key11.getCertificate(id1Key1Cert1.getName()));
+
+ // new certificate becomes default certificate when there was no default certificate
+ BOOST_REQUIRE_NO_THROW(key11.getDefaultCertificate());
+ const auto& defaultCert0 = key11.getDefaultCertificate();
+ BOOST_CHECK_EQUAL(defaultCert0.getName(), id1Key1Cert1.getName());
+ BOOST_CHECK_EQUAL(defaultCert0, id1Key1Cert1);
+
+ // remove certificate
+ key11.removeCertificate(id1Key1Cert1.getName());
+ BOOST_CHECK_THROW(key11.getCertificate(id1Key1Cert1.getName()), Pib::Error);
+ BOOST_CHECK_THROW(key11.getDefaultCertificate(), Pib::Error);
+
+ // set default certificate directly
+ BOOST_REQUIRE_NO_THROW(key11.setDefaultCertificate(id1Key1Cert1));
+ BOOST_REQUIRE_NO_THROW(key11.getDefaultCertificate());
+ BOOST_CHECK_NO_THROW(key11.getCertificate(id1Key1Cert1.getName()));
+
+ // check default cert
+ const auto& defaultCert1 = key11.getDefaultCertificate();
+ BOOST_CHECK_EQUAL(defaultCert1.getName(), id1Key1Cert1.getName());
+ BOOST_CHECK_EQUAL(defaultCert1, id1Key1Cert1);
+
+ // add another certificate
+ key11.addCertificate(id1Key1Cert2);
+ BOOST_CHECK_EQUAL(key11.getCertificates().size(), 2);
+
+ // set default certificate through name
+ BOOST_REQUIRE_NO_THROW(key11.setDefaultCertificate(id1Key1Cert2.getName()));
+ BOOST_REQUIRE_NO_THROW(key11.getDefaultCertificate());
+ const auto& defaultCert2 = key11.getDefaultCertificate();
+ BOOST_CHECK_EQUAL(defaultCert2.getName(), id1Key1Cert2.getName());
+ BOOST_CHECK_EQUAL(defaultCert2, id1Key1Cert2);
+
+ // remove certificate
+ key11.removeCertificate(id1Key1Cert1.getName());
+ BOOST_CHECK_THROW(key11.getCertificate(id1Key1Cert1.getName()), Pib::Error);
+ BOOST_CHECK_EQUAL(key11.getCertificates().size(), 1);
+
+ // set default certificate directly again, change the default setting
+ BOOST_REQUIRE_NO_THROW(key11.setDefaultCertificate(id1Key1Cert1));
+ const auto& defaultCert3 = key11.getDefaultCertificate();
+ BOOST_CHECK_EQUAL(defaultCert3.getName(), id1Key1Cert1.getName());
+ BOOST_CHECK_EQUAL(defaultCert3, id1Key1Cert1);
+ BOOST_CHECK_EQUAL(key11.getCertificates().size(), 2);
+
+ // remove all certificates
+ key11.removeCertificate(id1Key1Cert1.getName());
+ BOOST_CHECK_THROW(key11.getCertificate(id1Key1Cert1.getName()), Pib::Error);
+ BOOST_CHECK_EQUAL(key11.getCertificates().size(), 1);
+ key11.removeCertificate(id1Key1Cert2.getName());
+ BOOST_CHECK_THROW(key11.getCertificate(id1Key1Cert2.getName()), Pib::Error);
+ BOOST_CHECK_THROW(key11.getDefaultCertificate(), Pib::Error);
+ BOOST_CHECK_EQUAL(key11.getCertificates().size(), 0);
+}
+
+class OverwriteFixture : public ndn::security::tests::PibDataFixture,
+ public ndn::tests::IdentityManagementFixture
+{
+};
+
+BOOST_FIXTURE_TEST_CASE(Overwrite, OverwriteFixture)
+{
+ auto pibImpl = make_shared<pib::PibMemory>();
+
+ BOOST_CHECK_THROW(KeyImpl(id1Key1Name, pibImpl), Pib::Error);
+ KeyImpl(id1Key1Name, id1Key1.data(), id1Key1.size(), pibImpl);
+ KeyImpl key1(id1Key1Name, pibImpl);
+
+ KeyImpl(id1Key1Name, id1Key2.data(), id1Key2.size(), pibImpl); // overwriting of the key should work
+ KeyImpl key2(id1Key1Name, pibImpl);
+
+ BOOST_CHECK(key1.getPublicKey() != key2.getPublicKey()); // key1 cached the original public key
+ BOOST_CHECK(key2.getPublicKey() == id1Key2);
+
+ key1.addCertificate(id1Key1Cert1);
+ BOOST_CHECK_EQUAL(key1.getCertificate(id1Key1Cert1.getName()), id1Key1Cert1);
+
+ auto otherCert = id1Key1Cert1;
+ SignatureInfo info;
+ info.setValidityPeriod(ValidityPeriod(time::system_clock::now(),
+ time::system_clock::now() + 1_s));
+ m_keyChain.sign(otherCert, SigningInfo().setSignatureInfo(info));
+
+ BOOST_CHECK_EQUAL(otherCert.getName(), id1Key1Cert1.getName());
+ BOOST_CHECK(otherCert.getContent() == id1Key1Cert1.getContent());
+ BOOST_CHECK_NE(otherCert, id1Key1Cert1);
+
+ key1.addCertificate(otherCert);
+
+ BOOST_CHECK_EQUAL(key1.getCertificate(id1Key1Cert1.getName()), otherCert);
+}
+
+BOOST_AUTO_TEST_CASE(Errors)
+{
+ auto pibImpl = make_shared<pib::PibMemory>();
+
+ BOOST_CHECK_THROW(KeyImpl(id1Key1Name, pibImpl), Pib::Error);
+ KeyImpl key11(id1Key1Name, id1Key1.data(), id1Key1.size(), pibImpl);
+
+ BOOST_CHECK_THROW(KeyImpl(Name("/wrong"), pibImpl), std::invalid_argument);
+ BOOST_CHECK_THROW(KeyImpl(Name("/wrong"), id1Key1.data(), id1Key1.size(), pibImpl), std::invalid_argument);
+ Buffer wrongKey;
+ BOOST_CHECK_THROW(KeyImpl(id1Key2Name, wrongKey.data(), wrongKey.size(), pibImpl), std::invalid_argument);
+
+ key11.addCertificate(id1Key1Cert1);
+ BOOST_CHECK_THROW(key11.addCertificate(id1Key2Cert1), std::invalid_argument);
+ BOOST_CHECK_THROW(key11.removeCertificate(id1Key2Cert1.getName()), std::invalid_argument);
+ BOOST_CHECK_THROW(key11.getCertificate(id1Key2Cert1.getName()), std::invalid_argument);
+ BOOST_CHECK_THROW(key11.setDefaultCertificate(id1Key2Cert1), std::invalid_argument);
+ BOOST_CHECK_THROW(key11.setDefaultCertificate(id1Key2Cert1.getName()), std::invalid_argument);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestKeyImpl
+BOOST_AUTO_TEST_SUITE_END() // Detail
+BOOST_AUTO_TEST_SUITE_END() // Pib
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace detail
+} // namespace pib
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/pib/identity-container.t.cpp b/tests/unit/security/pib/identity-container.t.cpp
new file mode 100644
index 0000000..e821970
--- /dev/null
+++ b/tests/unit/security/pib/identity-container.t.cpp
@@ -0,0 +1,156 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/pib/identity-container.hpp"
+#include "security/pib/pib.hpp"
+#include "security/pib/pib-memory.hpp"
+
+#include "boost-test.hpp"
+#include "pib-data-fixture.hpp"
+
+namespace ndn {
+namespace security {
+namespace pib {
+namespace tests {
+
+using namespace ndn::security::tests;
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(Pib)
+BOOST_FIXTURE_TEST_SUITE(TestIdentityContainer, PibDataFixture)
+
+using pib::Pib;
+
+BOOST_AUTO_TEST_CASE(Basic)
+{
+ auto pibImpl = make_shared<PibMemory>();
+
+ // start with an empty container
+ IdentityContainer container(pibImpl);
+ BOOST_CHECK_EQUAL(container.size(), 0);
+ BOOST_CHECK_EQUAL(container.getLoadedIdentities().size(), 0);
+
+ // add the first identity
+ Identity identity11 = container.add(id1);
+ BOOST_CHECK_EQUAL(identity11.getName(), id1);
+ BOOST_CHECK_EQUAL(container.size(), 1);
+ BOOST_CHECK_EQUAL(container.getLoadedIdentities().size(), 1);
+ BOOST_CHECK(container.find(id1) != container.end());
+
+ // add the same identity again
+ Identity identity12 = container.add(id1);
+ BOOST_CHECK_EQUAL(identity12.getName(), id1);
+ BOOST_CHECK_EQUAL(container.size(), 1);
+ BOOST_CHECK_EQUAL(container.getLoadedIdentities().size(), 1);
+ BOOST_CHECK(container.find(id1) != container.end());
+
+ // add the second identity
+ Identity identity21 = container.add(id2);
+ BOOST_CHECK_EQUAL(identity21.getName(), id2);
+ BOOST_CHECK_EQUAL(container.size(), 2);
+ BOOST_CHECK_EQUAL(container.getLoadedIdentities().size(), 2);
+ BOOST_CHECK(container.find(id1) != container.end());
+ BOOST_CHECK(container.find(id2) != container.end());
+
+ // get identities
+ BOOST_REQUIRE_NO_THROW(container.get(id1));
+ BOOST_REQUIRE_NO_THROW(container.get(id2));
+ BOOST_CHECK_THROW(container.get(Name("/non-existing")), Pib::Error);
+
+ // check identity
+ Identity identity1 = container.get(id1);
+ Identity identity2 = container.get(id2);
+ BOOST_CHECK_EQUAL(identity1.getName(), id1);
+ BOOST_CHECK_EQUAL(identity2.getName(), id2);
+
+ // create another container from the same PibImpl
+ // cache should be empty
+ IdentityContainer container2(pibImpl);
+ BOOST_CHECK_EQUAL(container2.size(), 2);
+ BOOST_CHECK_EQUAL(container2.getLoadedIdentities().size(), 0);
+
+ // get key, cache should be filled
+ BOOST_REQUIRE_NO_THROW(container2.get(id1));
+ BOOST_CHECK_EQUAL(container2.size(), 2);
+ BOOST_CHECK_EQUAL(container2.getLoadedIdentities().size(), 1);
+
+ BOOST_REQUIRE_NO_THROW(container2.get(id2));
+ BOOST_CHECK_EQUAL(container2.size(), 2);
+ BOOST_CHECK_EQUAL(container2.getLoadedIdentities().size(), 2);
+
+ // remove a key
+ container2.remove(id1);
+ BOOST_CHECK_EQUAL(container2.size(), 1);
+ BOOST_CHECK_EQUAL(container2.getLoadedIdentities().size(), 1);
+ BOOST_CHECK(container2.find(id1) == container2.end());
+ BOOST_CHECK(container2.find(id2) != container2.end());
+
+ // remove another key
+ container2.remove(id2);
+ BOOST_CHECK_EQUAL(container2.size(), 0);
+ BOOST_CHECK_EQUAL(container2.getLoadedIdentities().size(), 0);
+ BOOST_CHECK(container2.find(id2) == container2.end());
+
+}
+
+BOOST_AUTO_TEST_CASE(Iterator)
+{
+ auto pibImpl = make_shared<PibMemory>();
+ IdentityContainer container(pibImpl);
+ container.add(id1);
+ container.add(id2);
+
+ std::set<Name> idNames;
+ idNames.insert(id1);
+ idNames.insert(id2);
+
+ IdentityContainer::const_iterator it = container.begin();
+ std::set<Name>::const_iterator testIt = idNames.begin();
+ BOOST_CHECK_EQUAL((*it).getName(), *testIt);
+ it++;
+ testIt++;
+ BOOST_CHECK_EQUAL((*it).getName(), *testIt);
+ ++it;
+ testIt++;
+ BOOST_CHECK(it == container.end());
+
+ size_t count = 0;
+ testIt = idNames.begin();
+ for (const auto& identity : container) {
+ BOOST_CHECK_EQUAL(identity.getName(), *testIt);
+ testIt++;
+ count++;
+ }
+ BOOST_CHECK_EQUAL(count, 2);
+
+ BOOST_CHECK(IdentityContainer::const_iterator() == IdentityContainer::const_iterator());
+ BOOST_CHECK(IdentityContainer::const_iterator() == container.end());
+ BOOST_CHECK(container.end() == IdentityContainer::const_iterator());
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestIdentityContainer
+BOOST_AUTO_TEST_SUITE_END() // Pib
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace pib
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/pib/identity.t.cpp b/tests/unit/security/pib/identity.t.cpp
new file mode 100644
index 0000000..d10c7bf
--- /dev/null
+++ b/tests/unit/security/pib/identity.t.cpp
@@ -0,0 +1,101 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/pib/identity.hpp"
+#include "security/pib/pib.hpp"
+#include "security/pib/pib-memory.hpp"
+#include "security/pib/detail/identity-impl.hpp"
+
+#include "boost-test.hpp"
+#include "pib-data-fixture.hpp"
+
+namespace ndn {
+namespace security {
+namespace pib {
+namespace tests {
+
+using namespace ndn::security::tests;
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(Pib)
+BOOST_FIXTURE_TEST_SUITE(TestIdentity, PibDataFixture)
+
+using pib::Pib;
+
+BOOST_AUTO_TEST_CASE(ValidityChecking)
+{
+ using security::pib::detail::IdentityImpl;
+
+ Identity id;
+
+ BOOST_CHECK_EQUAL(static_cast<bool>(id), false);
+ BOOST_CHECK_EQUAL(!id, true);
+
+ if (id)
+ BOOST_CHECK(false);
+ else
+ BOOST_CHECK(true);
+
+ auto identityImpl = make_shared<IdentityImpl>(id1, make_shared<PibMemory>(), true);
+ id = Identity(identityImpl);
+
+ BOOST_CHECK_EQUAL(static_cast<bool>(id), true);
+ BOOST_CHECK_EQUAL(!id, false);
+
+ if (id)
+ BOOST_CHECK(true);
+ else
+ BOOST_CHECK(false);
+}
+
+/**
+ * pib::Identity is a wrapper of pib::detail::IdentityImpl. Since the functionalities of
+ * IdentityImpl have already been tested in detail/identity-impl.t.cpp, we only test the shared
+ * property of pib::Identity in this test case.
+ */
+BOOST_AUTO_TEST_CASE(Share)
+{
+ using security::pib::detail::IdentityImpl;
+
+ auto identityImpl = make_shared<IdentityImpl>(id1, make_shared<pib::PibMemory>(), true);
+ Identity identity1(identityImpl);
+ Identity identity2(identityImpl);
+ BOOST_CHECK_EQUAL(identity1, identity2);
+ BOOST_CHECK_NE(identity1, Identity());
+ BOOST_CHECK_EQUAL(Identity(), Identity());
+
+ identity1.addKey(id1Key1.data(), id1Key1.size(), id1Key1Name);
+ BOOST_CHECK_NO_THROW(identity2.getKey(id1Key1Name));
+ identity2.removeKey(id1Key1Name);
+ BOOST_CHECK_THROW(identity1.getKey(id1Key1Name), Pib::Error);
+
+ identity1.setDefaultKey(id1Key1.data(), id1Key1.size(), id1Key1Name);
+ BOOST_CHECK_NO_THROW(identity2.getDefaultKey());
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestIdentity
+BOOST_AUTO_TEST_SUITE_END() // Pib
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace pib
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/pib/key-container.t.cpp b/tests/unit/security/pib/key-container.t.cpp
new file mode 100644
index 0000000..2afd3e2
--- /dev/null
+++ b/tests/unit/security/pib/key-container.t.cpp
@@ -0,0 +1,174 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/pib/key-container.hpp"
+#include "security/pib/pib.hpp"
+#include "security/pib/pib-memory.hpp"
+
+#include "boost-test.hpp"
+#include "pib-data-fixture.hpp"
+
+namespace ndn {
+namespace security {
+namespace pib {
+namespace tests {
+
+using namespace ndn::security::tests;
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(Pib)
+BOOST_FIXTURE_TEST_SUITE(TestKeyContainer, PibDataFixture)
+
+using pib::Pib;
+
+BOOST_AUTO_TEST_CASE(Basic)
+{
+ auto pibImpl = make_shared<PibMemory>();
+
+ // start with an empty container
+ KeyContainer container(id1, pibImpl);
+ BOOST_CHECK_EQUAL(container.size(), 0);
+ BOOST_CHECK_EQUAL(container.getLoadedKeys().size(), 0);
+
+ // add the first key
+ Key key11 = container.add(id1Key1.data(), id1Key1.size(), id1Key1Name);
+ BOOST_CHECK_EQUAL(key11.getName(), id1Key1Name);
+ BOOST_CHECK(key11.getPublicKey() == id1Key1);
+ BOOST_CHECK_EQUAL(container.size(), 1);
+ BOOST_CHECK_EQUAL(container.getLoadedKeys().size(), 1);
+ BOOST_CHECK(container.find(id1Key1Name) != container.end());
+
+ // add the same key again
+ Key key12 = container.add(id1Key1.data(), id1Key1.size(), id1Key1Name);
+ BOOST_CHECK_EQUAL(key12.getName(), id1Key1Name);
+ BOOST_CHECK(key12.getPublicKey() == id1Key1);
+ BOOST_CHECK_EQUAL(container.size(), 1);
+ BOOST_CHECK_EQUAL(container.getLoadedKeys().size(), 1);
+ BOOST_CHECK(container.find(id1Key1Name) != container.end());
+
+ // add the second key
+ Key key21 = container.add(id1Key2.data(), id1Key2.size(), id1Key2Name);
+ BOOST_CHECK_EQUAL(key21.getName(), id1Key2Name);
+ BOOST_CHECK(key21.getPublicKey() == id1Key2);
+ BOOST_CHECK_EQUAL(container.size(), 2);
+ BOOST_CHECK_EQUAL(container.getLoadedKeys().size(), 2);
+ BOOST_CHECK(container.find(id1Key1Name) != container.end());
+ BOOST_CHECK(container.find(id1Key2Name) != container.end());
+
+ // get keys
+ BOOST_REQUIRE_NO_THROW(container.get(id1Key1Name));
+ BOOST_REQUIRE_NO_THROW(container.get(id1Key2Name));
+ Name id1Key3Name = v2::constructKeyName(id1, name::Component("non-existing-id"));
+ BOOST_CHECK_THROW(container.get(id1Key3Name), Pib::Error);
+
+ // check key
+ Key key1 = container.get(id1Key1Name);
+ Key key2 = container.get(id1Key2Name);
+ BOOST_CHECK_EQUAL(key1.getName(), id1Key1Name);
+ BOOST_CHECK(key1.getPublicKey() == id1Key1);
+ BOOST_CHECK_EQUAL(key2.getName(), id1Key2Name);
+ BOOST_CHECK(key2.getPublicKey() == id1Key2);
+
+ // create another container from the same PibImpl
+ // cache should be empty
+ KeyContainer container2(id1, pibImpl);
+ BOOST_CHECK_EQUAL(container2.size(), 2);
+ BOOST_CHECK_EQUAL(container2.getLoadedKeys().size(), 0);
+
+ // get key, cache should be filled
+ BOOST_REQUIRE_NO_THROW(container2.get(id1Key1Name));
+ BOOST_CHECK_EQUAL(container2.size(), 2);
+ BOOST_CHECK_EQUAL(container2.getLoadedKeys().size(), 1);
+
+ BOOST_REQUIRE_NO_THROW(container2.get(id1Key2Name));
+ BOOST_CHECK_EQUAL(container2.size(), 2);
+ BOOST_CHECK_EQUAL(container2.getLoadedKeys().size(), 2);
+
+ // remove a key
+ container2.remove(id1Key1Name);
+ BOOST_CHECK_EQUAL(container2.size(), 1);
+ BOOST_CHECK_EQUAL(container2.getLoadedKeys().size(), 1);
+ BOOST_CHECK(container2.find(id1Key1Name) == container2.end());
+ BOOST_CHECK(container2.find(id1Key2Name) != container2.end());
+
+ // remove another key
+ container2.remove(id1Key2Name);
+ BOOST_CHECK_EQUAL(container2.size(), 0);
+ BOOST_CHECK_EQUAL(container2.getLoadedKeys().size(), 0);
+ BOOST_CHECK(container2.find(id1Key2Name) == container2.end());
+}
+
+BOOST_AUTO_TEST_CASE(Errors)
+{
+ auto pibImpl = make_shared<PibMemory>();
+
+ KeyContainer container(id1, pibImpl);
+
+ BOOST_CHECK_THROW(container.add(id2Key1.data(), id2Key1.size(), id2Key1Name), std::invalid_argument);
+ BOOST_CHECK_THROW(container.remove(id2Key1Name), std::invalid_argument);
+ BOOST_CHECK_THROW(container.get(id2Key1Name), std::invalid_argument);
+}
+
+BOOST_AUTO_TEST_CASE(Iterator)
+{
+ auto pibImpl = make_shared<PibMemory>();
+ KeyContainer container(id1, pibImpl);
+
+ container.add(id1Key1.data(), id1Key1.size(), id1Key1Name);
+ container.add(id1Key2.data(), id1Key2.size(), id1Key2Name);
+
+ std::set<Name> keyNames;
+ keyNames.insert(id1Key1Name);
+ keyNames.insert(id1Key2Name);
+
+ KeyContainer::const_iterator it = container.begin();
+ std::set<Name>::const_iterator testIt = keyNames.begin();
+ BOOST_CHECK_EQUAL((*it).getName(), *testIt);
+ it++;
+ testIt++;
+ BOOST_CHECK_EQUAL((*it).getName(), *testIt);
+ ++it;
+ testIt++;
+ BOOST_CHECK(it == container.end());
+
+ size_t count = 0;
+ testIt = keyNames.begin();
+ for (const auto& key : container) {
+ BOOST_CHECK_EQUAL(key.getIdentity(), id1);
+ BOOST_CHECK_EQUAL(key.getName(), *testIt);
+ testIt++;
+ count++;
+ }
+ BOOST_CHECK_EQUAL(count, 2);
+
+ BOOST_CHECK(KeyContainer::const_iterator() == KeyContainer::const_iterator());
+ BOOST_CHECK(KeyContainer::const_iterator() == container.end());
+ BOOST_CHECK(container.end() == KeyContainer::const_iterator());
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestKeyContainer
+BOOST_AUTO_TEST_SUITE_END() // Pib
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace pib
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/pib/key.t.cpp b/tests/unit/security/pib/key.t.cpp
new file mode 100644
index 0000000..3c5d207
--- /dev/null
+++ b/tests/unit/security/pib/key.t.cpp
@@ -0,0 +1,122 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/pib/key.hpp"
+#include "security/pib/pib.hpp"
+#include "security/pib/pib-memory.hpp"
+#include "security/pib/detail/key-impl.hpp"
+
+#include "boost-test.hpp"
+#include "pib-data-fixture.hpp"
+
+namespace ndn {
+namespace security {
+namespace pib {
+namespace tests {
+
+using namespace ndn::security::tests;
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(Pib)
+BOOST_FIXTURE_TEST_SUITE(TestKey, PibDataFixture)
+
+using pib::Pib;
+
+BOOST_AUTO_TEST_CASE(ValidityChecking)
+{
+ using security::pib::detail::KeyImpl;
+
+ Key key;
+
+ BOOST_CHECK_EQUAL(static_cast<bool>(key), false);
+ BOOST_CHECK_EQUAL(!key, true);
+
+ if (key)
+ BOOST_CHECK(false);
+ else
+ BOOST_CHECK(true);
+
+ auto keyImpl = make_shared<KeyImpl>(id1Key1Name, id1Key1.data(), id1Key1.size(),
+ make_shared<pib::PibMemory>());
+ key = Key(keyImpl);
+
+ BOOST_CHECK_EQUAL(static_cast<bool>(key), true);
+ BOOST_CHECK_EQUAL(!key, false);
+
+ if (key)
+ BOOST_CHECK(true);
+ else
+ BOOST_CHECK(false);
+}
+
+/**
+ * pib::Key is a wrapper of pib::detail::KeyImpl. Since the functionalities of KeyImpl
+ * have already been tested in detail/key-impl.t.cpp, we only test the shared property
+ * of pib::Key in this test case.
+ */
+
+BOOST_AUTO_TEST_CASE(Share)
+{
+ using security::pib::detail::KeyImpl;
+
+ auto keyImpl = make_shared<KeyImpl>(id1Key1Name, id1Key1.data(), id1Key1.size(),
+ make_shared<pib::PibMemory>());
+ Key key1(keyImpl);
+ Key key2(keyImpl);
+ BOOST_CHECK_EQUAL(key1, key2);
+ BOOST_CHECK_NE(key1, Key());
+ BOOST_CHECK_EQUAL(Key(), Key());
+
+ key1.addCertificate(id1Key1Cert1);
+ BOOST_CHECK_NO_THROW(key2.getCertificate(id1Key1Cert1.getName()));
+ key2.removeCertificate(id1Key1Cert1.getName());
+ BOOST_CHECK_THROW(key1.getCertificate(id1Key1Cert1.getName()), Pib::Error);
+
+ key1.setDefaultCertificate(id1Key1Cert1);
+ BOOST_CHECK_NO_THROW(key2.getDefaultCertificate());
+}
+
+BOOST_AUTO_TEST_CASE(Helpers)
+{
+ BOOST_CHECK_EQUAL(v2::constructKeyName("/hello", name::Component("world")), "/hello/KEY/world");
+
+ BOOST_CHECK_EQUAL(v2::isValidKeyName("/hello"), false);
+ BOOST_CHECK_EQUAL(v2::isValidKeyName("/hello/KEY"), false);
+ BOOST_CHECK_EQUAL(v2::isValidKeyName("/hello/KEY/world"), true);
+
+ BOOST_CHECK_EQUAL(v2::isValidKeyName("/KEY/hello"), true);
+ BOOST_CHECK_EQUAL(v2::isValidKeyName("/hello/world/KEY/!"), true);
+
+ BOOST_CHECK_EQUAL(v2::extractIdentityFromKeyName("/KEY/hello"), "/");
+ BOOST_CHECK_EQUAL(v2::extractIdentityFromKeyName("/hello/KEY/world"), "/hello");
+ BOOST_CHECK_EQUAL(v2::extractIdentityFromKeyName("/hello/world/KEY/!"), "/hello/world");
+
+ BOOST_CHECK_THROW(v2::extractIdentityFromKeyName("/hello"), std::invalid_argument);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestKey
+BOOST_AUTO_TEST_SUITE_END() // Pib
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace pib
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/pib/pib-data-fixture.cpp b/tests/unit/security/pib/pib-data-fixture.cpp
new file mode 100644
index 0000000..91e5b34
--- /dev/null
+++ b/tests/unit/security/pib/pib-data-fixture.cpp
@@ -0,0 +1,429 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "pib-data-fixture.hpp"
+#include "../../identity-management-time-fixture.hpp"
+
+// #include "security/pib/pib-memory.hpp"
+// #include "security/tpm/tpm.hpp"
+// #include "security/tpm/back-end-mem.hpp"
+// #include <fstream>
+
+namespace ndn {
+namespace security {
+namespace tests {
+
+// class TestCertDataGenerator
+// {
+// public:
+// TestCertDataGenerator()
+// : tpm("test", "test", make_unique<tpm::BackEndMem>())
+// {
+// }
+
+// void
+// printTestDataForId(const std::string& prefix, const Name& id)
+// {
+// for (int keyId : {1, 2}) {
+// Name keyName = tpm.createKey(id, EcKeyParams(name::Component::fromNumber(keyId)));
+
+// for (int certVersion : {1, 2}) {
+// Name certName = keyName;
+// certName
+// .append("issuer")
+// .appendVersion(certVersion);
+// v2::Certificate cert;
+// cert.setName(certName);
+// cert.setFreshnessPeriod(1_h);
+// cert.setContent(tpm.getPublicKey(keyName));
+
+// // @TODO sign using the new KeyChain
+// SignatureInfo info;
+// info.setSignatureType(tlv::SignatureSha256WithEcdsa);
+// info.setKeyLocator(KeyLocator(keyName));
+// info.setValidityPeriod(ValidityPeriod(time::fromIsoString("20170102T000000"),
+// time::fromIsoString("20180102T000000")));
+// cert.setSignature(Signature(info, Block()));
+
+// EncodingBuffer buf;
+// cert.wireEncode(buf, true);
+
+// cert.setSignatureValue(Block(tlv::SignatureValue,
+// tpm.sign(buf.buf(), buf.size(), keyName, DigestAlgorithm::SHA256)));
+
+// printBytes(prefix + "_KEY" + to_string(keyId) + "_CERT" + to_string(certVersion),
+// cert.wireEncode());
+// }
+// }
+// }
+
+// static void
+// printBytes(const std::string& name, const Block& block)
+// {
+// printBytes(name, block.wire(), block.size());
+// }
+
+// static void
+// printBytes(const std::string& name, const Buffer& buffer)
+// {
+// printBytes(name, buffer.buf(), buffer.size());
+// }
+
+// static void
+// printBytes(const std::string& name, const uint8_t* buf, size_t size)
+// {
+// std::cout << "\nconst uint8_t " << name << "[] = {\n"
+// << " ";
+
+// std::string hex = toHex(buf, size);
+
+// for (size_t i = 0; i < hex.size(); i++) {
+// if (i > 0 && i % 40 == 0)
+// std::cout << "\n ";
+
+// std::cout << "0x" << hex[i];
+// std::cout << hex[++i];
+
+// if ((i + 1) != hex.size())
+// std::cout << ", ";
+// }
+// std::cout << "\n"
+// << "};" << std::endl;
+// }
+
+// public:
+// pib::PibMemory pib;
+// Tpm tpm;
+// };
+
+// // The test data can be generated using this test case
+// BOOST_FIXTURE_TEST_CASE(GenerateTestCertData, TestCertDataGenerator)
+// {
+// printTestDataForId("ID1", Name("/pib/interface/id/1"));
+// printTestDataForId("ID2", Name("/pib/interface/id/2"));
+// }
+
+const uint8_t ID1_KEY1_CERT1[] = {
+ 0x06, 0xFD, 0x02, 0x25, 0x07, 0x2B, 0x08, 0x03, 0x70, 0x69, 0x62, 0x08, 0x09, 0x69, 0x6E, 0x74, 0x65, 0x72, 0x66, 0x61,
+ 0x63, 0x65, 0x08, 0x02, 0x69, 0x64, 0x08, 0x01, 0x31, 0x08, 0x03, 0x4B, 0x45, 0x59, 0x08, 0x01, 0x01, 0x08, 0x06, 0x69,
+ 0x73, 0x73, 0x75, 0x65, 0x72, 0x08, 0x02, 0xFD, 0x01, 0x14, 0x09, 0x18, 0x01, 0x02, 0x19, 0x04, 0x00, 0x36, 0xEE, 0x80,
+ 0x15, 0xFD, 0x01, 0x4F, 0x30, 0x82, 0x01, 0x4B, 0x30, 0x82, 0x01, 0x03, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02,
+ 0x01, 0x30, 0x81, 0xF7, 0x02, 0x01, 0x01, 0x30, 0x2C, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x01, 0x01, 0x02, 0x21,
+ 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x30, 0x5B, 0x04, 0x20, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x04, 0x20, 0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A, 0x93, 0xE7, 0xB3,
+ 0xEB, 0xBD, 0x55, 0x76, 0x98, 0x86, 0xBC, 0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53, 0xB0, 0xF6, 0x3B, 0xCE, 0x3C, 0x3E, 0x27,
+ 0xD2, 0x60, 0x4B, 0x03, 0x15, 0x00, 0xC4, 0x9D, 0x36, 0x08, 0x86, 0xE7, 0x04, 0x93, 0x6A, 0x66, 0x78, 0xE1, 0x13, 0x9D,
+ 0x26, 0xB7, 0x81, 0x9F, 0x7E, 0x90, 0x04, 0x41, 0x04, 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, 0xBC, 0xE6,
+ 0xE5, 0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0, 0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2,
+ 0x96, 0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, 0x9B, 0x8E, 0xE7, 0xEB, 0x4A, 0x7C, 0x0F, 0x9E, 0x16, 0x2B, 0xCE, 0x33,
+ 0x57, 0x6B, 0x31, 0x5E, 0xCE, 0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51, 0xF5, 0x02, 0x21, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84,
+ 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51, 0x02, 0x01, 0x01, 0x03, 0x42, 0x00, 0x04, 0xCB, 0x46, 0xF7, 0x16, 0x2E,
+ 0x83, 0x3D, 0x5E, 0x4A, 0x80, 0x6A, 0x78, 0xB7, 0xA8, 0x7A, 0x15, 0x95, 0x2D, 0x23, 0xA8, 0x41, 0xF7, 0x62, 0xE4, 0x0E,
+ 0x66, 0x36, 0xB3, 0xF3, 0x14, 0xD6, 0xB3, 0xAB, 0x19, 0x26, 0x9D, 0x5A, 0x8A, 0x51, 0xD4, 0x4E, 0xBA, 0xBE, 0x13, 0x96,
+ 0xCA, 0x38, 0x52, 0x16, 0xE4, 0x3D, 0xB0, 0x88, 0xBA, 0xBB, 0x7B, 0x97, 0x00, 0xA5, 0x95, 0x97, 0x4E, 0xE8, 0xF6, 0x16,
+ 0x50, 0x1B, 0x01, 0x03, 0x1C, 0x21, 0x07, 0x1F, 0x08, 0x03, 0x70, 0x69, 0x62, 0x08, 0x09, 0x69, 0x6E, 0x74, 0x65, 0x72,
+ 0x66, 0x61, 0x63, 0x65, 0x08, 0x02, 0x69, 0x64, 0x08, 0x01, 0x31, 0x08, 0x03, 0x4B, 0x45, 0x59, 0x08, 0x01, 0x01, 0xFD,
+ 0x00, 0xFD, 0x26, 0xFD, 0x00, 0xFE, 0x0F, 0x32, 0x30, 0x31, 0x37, 0x30, 0x31, 0x30, 0x32, 0x54, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0xFD, 0x00, 0xFF, 0x0F, 0x32, 0x30, 0x31, 0x38, 0x30, 0x31, 0x30, 0x32, 0x54, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x17, 0x46, 0x30, 0x44, 0x02, 0x20, 0x53, 0xC8, 0xAD, 0x88, 0xBA, 0x52, 0x29, 0x68, 0xFF, 0x74, 0xA8, 0x39, 0x7F,
+ 0x2C, 0xE2, 0x8E, 0x04, 0xC1, 0x78, 0x36, 0x46, 0x89, 0x38, 0x58, 0x45, 0x22, 0x44, 0xA3, 0xC8, 0xC1, 0xFF, 0x72, 0x02,
+ 0x20, 0x23, 0x9D, 0xE4, 0x92, 0x00, 0xF1, 0x43, 0x69, 0xF7, 0x32, 0xF6, 0xAA, 0x8C, 0xFD, 0x7F, 0x2B, 0xFB, 0xD2, 0x40,
+ 0x6A, 0x1E, 0xA3, 0xE5, 0xF0, 0xF8, 0x2B, 0x92, 0x99, 0x6B, 0xDB, 0xE2, 0x6D
+};
+
+const uint8_t ID1_KEY1_CERT2[] = {
+ 0x06, 0xFD, 0x02, 0x26, 0x07, 0x2B, 0x08, 0x03, 0x70, 0x69, 0x62, 0x08, 0x09, 0x69, 0x6E, 0x74, 0x65, 0x72, 0x66, 0x61,
+ 0x63, 0x65, 0x08, 0x02, 0x69, 0x64, 0x08, 0x01, 0x31, 0x08, 0x03, 0x4B, 0x45, 0x59, 0x08, 0x01, 0x01, 0x08, 0x06, 0x69,
+ 0x73, 0x73, 0x75, 0x65, 0x72, 0x08, 0x02, 0xFD, 0x02, 0x14, 0x09, 0x18, 0x01, 0x02, 0x19, 0x04, 0x00, 0x36, 0xEE, 0x80,
+ 0x15, 0xFD, 0x01, 0x4F, 0x30, 0x82, 0x01, 0x4B, 0x30, 0x82, 0x01, 0x03, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02,
+ 0x01, 0x30, 0x81, 0xF7, 0x02, 0x01, 0x01, 0x30, 0x2C, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x01, 0x01, 0x02, 0x21,
+ 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x30, 0x5B, 0x04, 0x20, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x04, 0x20, 0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A, 0x93, 0xE7, 0xB3,
+ 0xEB, 0xBD, 0x55, 0x76, 0x98, 0x86, 0xBC, 0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53, 0xB0, 0xF6, 0x3B, 0xCE, 0x3C, 0x3E, 0x27,
+ 0xD2, 0x60, 0x4B, 0x03, 0x15, 0x00, 0xC4, 0x9D, 0x36, 0x08, 0x86, 0xE7, 0x04, 0x93, 0x6A, 0x66, 0x78, 0xE1, 0x13, 0x9D,
+ 0x26, 0xB7, 0x81, 0x9F, 0x7E, 0x90, 0x04, 0x41, 0x04, 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, 0xBC, 0xE6,
+ 0xE5, 0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0, 0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2,
+ 0x96, 0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, 0x9B, 0x8E, 0xE7, 0xEB, 0x4A, 0x7C, 0x0F, 0x9E, 0x16, 0x2B, 0xCE, 0x33,
+ 0x57, 0x6B, 0x31, 0x5E, 0xCE, 0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51, 0xF5, 0x02, 0x21, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84,
+ 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51, 0x02, 0x01, 0x01, 0x03, 0x42, 0x00, 0x04, 0xCB, 0x46, 0xF7, 0x16, 0x2E,
+ 0x83, 0x3D, 0x5E, 0x4A, 0x80, 0x6A, 0x78, 0xB7, 0xA8, 0x7A, 0x15, 0x95, 0x2D, 0x23, 0xA8, 0x41, 0xF7, 0x62, 0xE4, 0x0E,
+ 0x66, 0x36, 0xB3, 0xF3, 0x14, 0xD6, 0xB3, 0xAB, 0x19, 0x26, 0x9D, 0x5A, 0x8A, 0x51, 0xD4, 0x4E, 0xBA, 0xBE, 0x13, 0x96,
+ 0xCA, 0x38, 0x52, 0x16, 0xE4, 0x3D, 0xB0, 0x88, 0xBA, 0xBB, 0x7B, 0x97, 0x00, 0xA5, 0x95, 0x97, 0x4E, 0xE8, 0xF6, 0x16,
+ 0x50, 0x1B, 0x01, 0x03, 0x1C, 0x21, 0x07, 0x1F, 0x08, 0x03, 0x70, 0x69, 0x62, 0x08, 0x09, 0x69, 0x6E, 0x74, 0x65, 0x72,
+ 0x66, 0x61, 0x63, 0x65, 0x08, 0x02, 0x69, 0x64, 0x08, 0x01, 0x31, 0x08, 0x03, 0x4B, 0x45, 0x59, 0x08, 0x01, 0x01, 0xFD,
+ 0x00, 0xFD, 0x26, 0xFD, 0x00, 0xFE, 0x0F, 0x32, 0x30, 0x31, 0x37, 0x30, 0x31, 0x30, 0x32, 0x54, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0xFD, 0x00, 0xFF, 0x0F, 0x32, 0x30, 0x31, 0x38, 0x30, 0x31, 0x30, 0x32, 0x54, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x17, 0x47, 0x30, 0x45, 0x02, 0x21, 0x00, 0xB2, 0x93, 0xCD, 0x3D, 0x01, 0x00, 0xB5, 0xF1, 0x75, 0x22, 0x68, 0x9F,
+ 0xE4, 0x5E, 0x0A, 0x76, 0x34, 0xBC, 0x9D, 0xCF, 0x9A, 0x4C, 0x21, 0x3F, 0xA5, 0x12, 0x51, 0xF7, 0x3A, 0x5E, 0x37, 0x7D,
+ 0x02, 0x20, 0x33, 0xA9, 0xA9, 0x8F, 0xD8, 0x2E, 0xED, 0x3C, 0xE5, 0x18, 0x94, 0x59, 0x28, 0xEA, 0x82, 0x38, 0x5B, 0x20,
+ 0xE4, 0xBF, 0x15, 0xF4, 0x0D, 0x45, 0xAE, 0x8B, 0x63, 0x19, 0x79, 0x78, 0x50, 0x3A
+};
+
+const uint8_t ID1_KEY2_CERT1[] = {
+ 0x06, 0xFD, 0x02, 0x25, 0x07, 0x2B, 0x08, 0x03, 0x70, 0x69, 0x62, 0x08, 0x09, 0x69, 0x6E, 0x74, 0x65, 0x72, 0x66, 0x61,
+ 0x63, 0x65, 0x08, 0x02, 0x69, 0x64, 0x08, 0x01, 0x31, 0x08, 0x03, 0x4B, 0x45, 0x59, 0x08, 0x01, 0x02, 0x08, 0x06, 0x69,
+ 0x73, 0x73, 0x75, 0x65, 0x72, 0x08, 0x02, 0xFD, 0x01, 0x14, 0x09, 0x18, 0x01, 0x02, 0x19, 0x04, 0x00, 0x36, 0xEE, 0x80,
+ 0x15, 0xFD, 0x01, 0x4F, 0x30, 0x82, 0x01, 0x4B, 0x30, 0x82, 0x01, 0x03, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02,
+ 0x01, 0x30, 0x81, 0xF7, 0x02, 0x01, 0x01, 0x30, 0x2C, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x01, 0x01, 0x02, 0x21,
+ 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x30, 0x5B, 0x04, 0x20, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x04, 0x20, 0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A, 0x93, 0xE7, 0xB3,
+ 0xEB, 0xBD, 0x55, 0x76, 0x98, 0x86, 0xBC, 0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53, 0xB0, 0xF6, 0x3B, 0xCE, 0x3C, 0x3E, 0x27,
+ 0xD2, 0x60, 0x4B, 0x03, 0x15, 0x00, 0xC4, 0x9D, 0x36, 0x08, 0x86, 0xE7, 0x04, 0x93, 0x6A, 0x66, 0x78, 0xE1, 0x13, 0x9D,
+ 0x26, 0xB7, 0x81, 0x9F, 0x7E, 0x90, 0x04, 0x41, 0x04, 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, 0xBC, 0xE6,
+ 0xE5, 0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0, 0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2,
+ 0x96, 0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, 0x9B, 0x8E, 0xE7, 0xEB, 0x4A, 0x7C, 0x0F, 0x9E, 0x16, 0x2B, 0xCE, 0x33,
+ 0x57, 0x6B, 0x31, 0x5E, 0xCE, 0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51, 0xF5, 0x02, 0x21, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84,
+ 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51, 0x02, 0x01, 0x01, 0x03, 0x42, 0x00, 0x04, 0x34, 0xAA, 0x4B, 0x1A, 0x97,
+ 0x4A, 0x6B, 0x6F, 0x3F, 0xB3, 0xC9, 0xD1, 0x39, 0x9F, 0x1E, 0x49, 0xB6, 0x6E, 0x19, 0x97, 0x13, 0x5E, 0xFA, 0xE6, 0xD3,
+ 0xFE, 0xF3, 0xB0, 0xCA, 0x80, 0x09, 0x31, 0xCA, 0x50, 0x5C, 0xE6, 0x57, 0xBF, 0x13, 0x16, 0xCE, 0x3E, 0xF1, 0xD4, 0x23,
+ 0xF8, 0x7F, 0x31, 0xFA, 0x13, 0x39, 0x09, 0xED, 0xC6, 0x74, 0x3D, 0xFD, 0x1A, 0x0B, 0xC7, 0xC1, 0x01, 0x15, 0x7F, 0x16,
+ 0x50, 0x1B, 0x01, 0x03, 0x1C, 0x21, 0x07, 0x1F, 0x08, 0x03, 0x70, 0x69, 0x62, 0x08, 0x09, 0x69, 0x6E, 0x74, 0x65, 0x72,
+ 0x66, 0x61, 0x63, 0x65, 0x08, 0x02, 0x69, 0x64, 0x08, 0x01, 0x31, 0x08, 0x03, 0x4B, 0x45, 0x59, 0x08, 0x01, 0x02, 0xFD,
+ 0x00, 0xFD, 0x26, 0xFD, 0x00, 0xFE, 0x0F, 0x32, 0x30, 0x31, 0x37, 0x30, 0x31, 0x30, 0x32, 0x54, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0xFD, 0x00, 0xFF, 0x0F, 0x32, 0x30, 0x31, 0x38, 0x30, 0x31, 0x30, 0x32, 0x54, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x17, 0x46, 0x30, 0x44, 0x02, 0x20, 0x71, 0x3A, 0xB4, 0x19, 0x4B, 0xB3, 0x25, 0xA5, 0x03, 0x23, 0x8C, 0xC1, 0xB9,
+ 0x68, 0xC1, 0x41, 0x4B, 0xED, 0x13, 0xCC, 0x87, 0x16, 0xB5, 0x13, 0x87, 0xA0, 0x54, 0xA2, 0x9F, 0xF0, 0xD7, 0x72, 0x02,
+ 0x20, 0x4B, 0xEF, 0xB5, 0x6A, 0x8C, 0x40, 0x71, 0x17, 0xD2, 0x4F, 0xB6, 0x0F, 0xBE, 0x60, 0x1A, 0x46, 0x9B, 0x78, 0x15,
+ 0x46, 0x09, 0xC2, 0x7A, 0x80, 0xD4, 0xE6, 0x71, 0x52, 0xD6, 0x83, 0x4B, 0x04
+};
+
+const uint8_t ID1_KEY2_CERT2[] = {
+ 0x06, 0xFD, 0x02, 0x26, 0x07, 0x2B, 0x08, 0x03, 0x70, 0x69, 0x62, 0x08, 0x09, 0x69, 0x6E, 0x74, 0x65, 0x72, 0x66, 0x61,
+ 0x63, 0x65, 0x08, 0x02, 0x69, 0x64, 0x08, 0x01, 0x31, 0x08, 0x03, 0x4B, 0x45, 0x59, 0x08, 0x01, 0x02, 0x08, 0x06, 0x69,
+ 0x73, 0x73, 0x75, 0x65, 0x72, 0x08, 0x02, 0xFD, 0x02, 0x14, 0x09, 0x18, 0x01, 0x02, 0x19, 0x04, 0x00, 0x36, 0xEE, 0x80,
+ 0x15, 0xFD, 0x01, 0x4F, 0x30, 0x82, 0x01, 0x4B, 0x30, 0x82, 0x01, 0x03, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02,
+ 0x01, 0x30, 0x81, 0xF7, 0x02, 0x01, 0x01, 0x30, 0x2C, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x01, 0x01, 0x02, 0x21,
+ 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x30, 0x5B, 0x04, 0x20, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x04, 0x20, 0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A, 0x93, 0xE7, 0xB3,
+ 0xEB, 0xBD, 0x55, 0x76, 0x98, 0x86, 0xBC, 0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53, 0xB0, 0xF6, 0x3B, 0xCE, 0x3C, 0x3E, 0x27,
+ 0xD2, 0x60, 0x4B, 0x03, 0x15, 0x00, 0xC4, 0x9D, 0x36, 0x08, 0x86, 0xE7, 0x04, 0x93, 0x6A, 0x66, 0x78, 0xE1, 0x13, 0x9D,
+ 0x26, 0xB7, 0x81, 0x9F, 0x7E, 0x90, 0x04, 0x41, 0x04, 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, 0xBC, 0xE6,
+ 0xE5, 0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0, 0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2,
+ 0x96, 0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, 0x9B, 0x8E, 0xE7, 0xEB, 0x4A, 0x7C, 0x0F, 0x9E, 0x16, 0x2B, 0xCE, 0x33,
+ 0x57, 0x6B, 0x31, 0x5E, 0xCE, 0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51, 0xF5, 0x02, 0x21, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84,
+ 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51, 0x02, 0x01, 0x01, 0x03, 0x42, 0x00, 0x04, 0x34, 0xAA, 0x4B, 0x1A, 0x97,
+ 0x4A, 0x6B, 0x6F, 0x3F, 0xB3, 0xC9, 0xD1, 0x39, 0x9F, 0x1E, 0x49, 0xB6, 0x6E, 0x19, 0x97, 0x13, 0x5E, 0xFA, 0xE6, 0xD3,
+ 0xFE, 0xF3, 0xB0, 0xCA, 0x80, 0x09, 0x31, 0xCA, 0x50, 0x5C, 0xE6, 0x57, 0xBF, 0x13, 0x16, 0xCE, 0x3E, 0xF1, 0xD4, 0x23,
+ 0xF8, 0x7F, 0x31, 0xFA, 0x13, 0x39, 0x09, 0xED, 0xC6, 0x74, 0x3D, 0xFD, 0x1A, 0x0B, 0xC7, 0xC1, 0x01, 0x15, 0x7F, 0x16,
+ 0x50, 0x1B, 0x01, 0x03, 0x1C, 0x21, 0x07, 0x1F, 0x08, 0x03, 0x70, 0x69, 0x62, 0x08, 0x09, 0x69, 0x6E, 0x74, 0x65, 0x72,
+ 0x66, 0x61, 0x63, 0x65, 0x08, 0x02, 0x69, 0x64, 0x08, 0x01, 0x31, 0x08, 0x03, 0x4B, 0x45, 0x59, 0x08, 0x01, 0x02, 0xFD,
+ 0x00, 0xFD, 0x26, 0xFD, 0x00, 0xFE, 0x0F, 0x32, 0x30, 0x31, 0x37, 0x30, 0x31, 0x30, 0x32, 0x54, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0xFD, 0x00, 0xFF, 0x0F, 0x32, 0x30, 0x31, 0x38, 0x30, 0x31, 0x30, 0x32, 0x54, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x17, 0x47, 0x30, 0x45, 0x02, 0x21, 0x00, 0xD2, 0x90, 0x8C, 0xA3, 0x52, 0x2F, 0x79, 0xB3, 0xD7, 0x39, 0xE1, 0x6C,
+ 0x7F, 0xA0, 0xDF, 0xD1, 0x3E, 0x0F, 0x70, 0xBE, 0xF5, 0xDB, 0x08, 0xDF, 0xE1, 0x0B, 0xDF, 0x79, 0x99, 0xFE, 0x5C, 0xDC,
+ 0x02, 0x20, 0x3D, 0xD4, 0x7C, 0xD1, 0x83, 0xBE, 0x29, 0xBB, 0x73, 0xA3, 0x82, 0xE5, 0xE6, 0x83, 0xA1, 0xC1, 0xBC, 0xF6,
+ 0x84, 0x42, 0x85, 0x00, 0x92, 0x4B, 0xA2, 0xA8, 0xCA, 0x10, 0x7B, 0x92, 0x89, 0xB0
+};
+
+const uint8_t ID2_KEY1_CERT1[] = {
+ 0x06, 0xFD, 0x02, 0x25, 0x07, 0x2B, 0x08, 0x03, 0x70, 0x69, 0x62, 0x08, 0x09, 0x69, 0x6E, 0x74, 0x65, 0x72, 0x66, 0x61,
+ 0x63, 0x65, 0x08, 0x02, 0x69, 0x64, 0x08, 0x01, 0x32, 0x08, 0x03, 0x4B, 0x45, 0x59, 0x08, 0x01, 0x01, 0x08, 0x06, 0x69,
+ 0x73, 0x73, 0x75, 0x65, 0x72, 0x08, 0x02, 0xFD, 0x01, 0x14, 0x09, 0x18, 0x01, 0x02, 0x19, 0x04, 0x00, 0x36, 0xEE, 0x80,
+ 0x15, 0xFD, 0x01, 0x4F, 0x30, 0x82, 0x01, 0x4B, 0x30, 0x82, 0x01, 0x03, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02,
+ 0x01, 0x30, 0x81, 0xF7, 0x02, 0x01, 0x01, 0x30, 0x2C, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x01, 0x01, 0x02, 0x21,
+ 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x30, 0x5B, 0x04, 0x20, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x04, 0x20, 0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A, 0x93, 0xE7, 0xB3,
+ 0xEB, 0xBD, 0x55, 0x76, 0x98, 0x86, 0xBC, 0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53, 0xB0, 0xF6, 0x3B, 0xCE, 0x3C, 0x3E, 0x27,
+ 0xD2, 0x60, 0x4B, 0x03, 0x15, 0x00, 0xC4, 0x9D, 0x36, 0x08, 0x86, 0xE7, 0x04, 0x93, 0x6A, 0x66, 0x78, 0xE1, 0x13, 0x9D,
+ 0x26, 0xB7, 0x81, 0x9F, 0x7E, 0x90, 0x04, 0x41, 0x04, 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, 0xBC, 0xE6,
+ 0xE5, 0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0, 0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2,
+ 0x96, 0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, 0x9B, 0x8E, 0xE7, 0xEB, 0x4A, 0x7C, 0x0F, 0x9E, 0x16, 0x2B, 0xCE, 0x33,
+ 0x57, 0x6B, 0x31, 0x5E, 0xCE, 0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51, 0xF5, 0x02, 0x21, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84,
+ 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51, 0x02, 0x01, 0x01, 0x03, 0x42, 0x00, 0x04, 0xAC, 0x62, 0xD7, 0x31, 0x3B,
+ 0x19, 0x1F, 0x44, 0x76, 0x6E, 0x79, 0x03, 0xB9, 0xC8, 0x26, 0xC4, 0x1E, 0x38, 0x3A, 0x41, 0xFE, 0xB4, 0x72, 0xA2, 0x36,
+ 0xBB, 0x82, 0x9C, 0xB9, 0x07, 0x62, 0x6F, 0x1C, 0x79, 0x12, 0xCA, 0x9C, 0x3D, 0xAA, 0x7A, 0x96, 0xFF, 0xAF, 0x5B, 0x6F,
+ 0xE1, 0x72, 0x60, 0xB0, 0x7F, 0x44, 0x38, 0x05, 0x21, 0xCC, 0x49, 0x78, 0x89, 0xC1, 0xEF, 0xEE, 0x81, 0x8E, 0xF5, 0x16,
+ 0x50, 0x1B, 0x01, 0x03, 0x1C, 0x21, 0x07, 0x1F, 0x08, 0x03, 0x70, 0x69, 0x62, 0x08, 0x09, 0x69, 0x6E, 0x74, 0x65, 0x72,
+ 0x66, 0x61, 0x63, 0x65, 0x08, 0x02, 0x69, 0x64, 0x08, 0x01, 0x32, 0x08, 0x03, 0x4B, 0x45, 0x59, 0x08, 0x01, 0x01, 0xFD,
+ 0x00, 0xFD, 0x26, 0xFD, 0x00, 0xFE, 0x0F, 0x32, 0x30, 0x31, 0x37, 0x30, 0x31, 0x30, 0x32, 0x54, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0xFD, 0x00, 0xFF, 0x0F, 0x32, 0x30, 0x31, 0x38, 0x30, 0x31, 0x30, 0x32, 0x54, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x17, 0x46, 0x30, 0x44, 0x02, 0x20, 0x16, 0xC0, 0xF4, 0xE3, 0x15, 0x43, 0x6E, 0x27, 0x33, 0x7C, 0x46, 0x4D, 0x35,
+ 0xA7, 0x8B, 0x0C, 0xE3, 0x27, 0x63, 0x4B, 0xB2, 0xB6, 0x4F, 0x06, 0x90, 0x2A, 0xD8, 0x54, 0x92, 0xE8, 0xBA, 0xBE, 0x02,
+ 0x20, 0x67, 0xA6, 0x55, 0x8D, 0x16, 0x0E, 0x1E, 0x9E, 0x10, 0x0E, 0xB9, 0x3C, 0xEF, 0xEE, 0xB5, 0xF7, 0x9C, 0xB3, 0x1D,
+ 0x04, 0xF1, 0xD4, 0xB5, 0x9F, 0xD4, 0x13, 0xBB, 0xFF, 0xA7, 0x58, 0xAE, 0xCB
+};
+
+const uint8_t ID2_KEY1_CERT2[] = {
+ 0x06, 0xFD, 0x02, 0x26, 0x07, 0x2B, 0x08, 0x03, 0x70, 0x69, 0x62, 0x08, 0x09, 0x69, 0x6E, 0x74, 0x65, 0x72, 0x66, 0x61,
+ 0x63, 0x65, 0x08, 0x02, 0x69, 0x64, 0x08, 0x01, 0x32, 0x08, 0x03, 0x4B, 0x45, 0x59, 0x08, 0x01, 0x01, 0x08, 0x06, 0x69,
+ 0x73, 0x73, 0x75, 0x65, 0x72, 0x08, 0x02, 0xFD, 0x02, 0x14, 0x09, 0x18, 0x01, 0x02, 0x19, 0x04, 0x00, 0x36, 0xEE, 0x80,
+ 0x15, 0xFD, 0x01, 0x4F, 0x30, 0x82, 0x01, 0x4B, 0x30, 0x82, 0x01, 0x03, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02,
+ 0x01, 0x30, 0x81, 0xF7, 0x02, 0x01, 0x01, 0x30, 0x2C, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x01, 0x01, 0x02, 0x21,
+ 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x30, 0x5B, 0x04, 0x20, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x04, 0x20, 0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A, 0x93, 0xE7, 0xB3,
+ 0xEB, 0xBD, 0x55, 0x76, 0x98, 0x86, 0xBC, 0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53, 0xB0, 0xF6, 0x3B, 0xCE, 0x3C, 0x3E, 0x27,
+ 0xD2, 0x60, 0x4B, 0x03, 0x15, 0x00, 0xC4, 0x9D, 0x36, 0x08, 0x86, 0xE7, 0x04, 0x93, 0x6A, 0x66, 0x78, 0xE1, 0x13, 0x9D,
+ 0x26, 0xB7, 0x81, 0x9F, 0x7E, 0x90, 0x04, 0x41, 0x04, 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, 0xBC, 0xE6,
+ 0xE5, 0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0, 0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2,
+ 0x96, 0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, 0x9B, 0x8E, 0xE7, 0xEB, 0x4A, 0x7C, 0x0F, 0x9E, 0x16, 0x2B, 0xCE, 0x33,
+ 0x57, 0x6B, 0x31, 0x5E, 0xCE, 0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51, 0xF5, 0x02, 0x21, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84,
+ 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51, 0x02, 0x01, 0x01, 0x03, 0x42, 0x00, 0x04, 0xAC, 0x62, 0xD7, 0x31, 0x3B,
+ 0x19, 0x1F, 0x44, 0x76, 0x6E, 0x79, 0x03, 0xB9, 0xC8, 0x26, 0xC4, 0x1E, 0x38, 0x3A, 0x41, 0xFE, 0xB4, 0x72, 0xA2, 0x36,
+ 0xBB, 0x82, 0x9C, 0xB9, 0x07, 0x62, 0x6F, 0x1C, 0x79, 0x12, 0xCA, 0x9C, 0x3D, 0xAA, 0x7A, 0x96, 0xFF, 0xAF, 0x5B, 0x6F,
+ 0xE1, 0x72, 0x60, 0xB0, 0x7F, 0x44, 0x38, 0x05, 0x21, 0xCC, 0x49, 0x78, 0x89, 0xC1, 0xEF, 0xEE, 0x81, 0x8E, 0xF5, 0x16,
+ 0x50, 0x1B, 0x01, 0x03, 0x1C, 0x21, 0x07, 0x1F, 0x08, 0x03, 0x70, 0x69, 0x62, 0x08, 0x09, 0x69, 0x6E, 0x74, 0x65, 0x72,
+ 0x66, 0x61, 0x63, 0x65, 0x08, 0x02, 0x69, 0x64, 0x08, 0x01, 0x32, 0x08, 0x03, 0x4B, 0x45, 0x59, 0x08, 0x01, 0x01, 0xFD,
+ 0x00, 0xFD, 0x26, 0xFD, 0x00, 0xFE, 0x0F, 0x32, 0x30, 0x31, 0x37, 0x30, 0x31, 0x30, 0x32, 0x54, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0xFD, 0x00, 0xFF, 0x0F, 0x32, 0x30, 0x31, 0x38, 0x30, 0x31, 0x30, 0x32, 0x54, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x17, 0x47, 0x30, 0x45, 0x02, 0x21, 0x00, 0xF2, 0x0D, 0x1D, 0x60, 0x0B, 0x2D, 0x97, 0x3A, 0x6B, 0xEE, 0xEC, 0x56,
+ 0xD1, 0x64, 0xBF, 0xED, 0x68, 0xB7, 0x10, 0x0B, 0xDF, 0x81, 0x29, 0xCD, 0xB0, 0xBB, 0x87, 0x0D, 0xDA, 0x12, 0x52, 0xCC,
+ 0x02, 0x20, 0x64, 0x33, 0x4E, 0x91, 0xAF, 0x81, 0xF4, 0xE7, 0xAD, 0x38, 0x8E, 0xBF, 0x79, 0xA7, 0x70, 0x1E, 0xD6, 0x71,
+ 0x7E, 0xF5, 0xEB, 0x92, 0x56, 0x5F, 0xC7, 0x05, 0xDC, 0x27, 0xE5, 0x11, 0xC2, 0x43
+};
+
+const uint8_t ID2_KEY2_CERT1[] = {
+ 0x06, 0xFD, 0x02, 0x26, 0x07, 0x2B, 0x08, 0x03, 0x70, 0x69, 0x62, 0x08, 0x09, 0x69, 0x6E, 0x74, 0x65, 0x72, 0x66, 0x61,
+ 0x63, 0x65, 0x08, 0x02, 0x69, 0x64, 0x08, 0x01, 0x32, 0x08, 0x03, 0x4B, 0x45, 0x59, 0x08, 0x01, 0x02, 0x08, 0x06, 0x69,
+ 0x73, 0x73, 0x75, 0x65, 0x72, 0x08, 0x02, 0xFD, 0x01, 0x14, 0x09, 0x18, 0x01, 0x02, 0x19, 0x04, 0x00, 0x36, 0xEE, 0x80,
+ 0x15, 0xFD, 0x01, 0x4F, 0x30, 0x82, 0x01, 0x4B, 0x30, 0x82, 0x01, 0x03, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02,
+ 0x01, 0x30, 0x81, 0xF7, 0x02, 0x01, 0x01, 0x30, 0x2C, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x01, 0x01, 0x02, 0x21,
+ 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x30, 0x5B, 0x04, 0x20, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x04, 0x20, 0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A, 0x93, 0xE7, 0xB3,
+ 0xEB, 0xBD, 0x55, 0x76, 0x98, 0x86, 0xBC, 0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53, 0xB0, 0xF6, 0x3B, 0xCE, 0x3C, 0x3E, 0x27,
+ 0xD2, 0x60, 0x4B, 0x03, 0x15, 0x00, 0xC4, 0x9D, 0x36, 0x08, 0x86, 0xE7, 0x04, 0x93, 0x6A, 0x66, 0x78, 0xE1, 0x13, 0x9D,
+ 0x26, 0xB7, 0x81, 0x9F, 0x7E, 0x90, 0x04, 0x41, 0x04, 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, 0xBC, 0xE6,
+ 0xE5, 0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0, 0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2,
+ 0x96, 0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, 0x9B, 0x8E, 0xE7, 0xEB, 0x4A, 0x7C, 0x0F, 0x9E, 0x16, 0x2B, 0xCE, 0x33,
+ 0x57, 0x6B, 0x31, 0x5E, 0xCE, 0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51, 0xF5, 0x02, 0x21, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84,
+ 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51, 0x02, 0x01, 0x01, 0x03, 0x42, 0x00, 0x04, 0x2C, 0xC3, 0xAF, 0xA8, 0x73,
+ 0xF2, 0x61, 0xCF, 0x48, 0x04, 0x0F, 0x9D, 0xD3, 0xAF, 0x0B, 0xC6, 0x2F, 0x4D, 0xDA, 0x0E, 0x4C, 0x66, 0x1D, 0x03, 0x9D,
+ 0xFE, 0x2C, 0x0B, 0xB6, 0x25, 0x60, 0xBC, 0xFA, 0xDA, 0xFE, 0x6F, 0x43, 0xFA, 0x95, 0x45, 0x57, 0x8A, 0x25, 0xEC, 0x0F,
+ 0xF2, 0xB7, 0x43, 0x85, 0x0D, 0x0B, 0x8D, 0x97, 0x40, 0x83, 0x4C, 0x28, 0x1B, 0xD4, 0x2E, 0x99, 0x2C, 0x73, 0x7D, 0x16,
+ 0x50, 0x1B, 0x01, 0x03, 0x1C, 0x21, 0x07, 0x1F, 0x08, 0x03, 0x70, 0x69, 0x62, 0x08, 0x09, 0x69, 0x6E, 0x74, 0x65, 0x72,
+ 0x66, 0x61, 0x63, 0x65, 0x08, 0x02, 0x69, 0x64, 0x08, 0x01, 0x32, 0x08, 0x03, 0x4B, 0x45, 0x59, 0x08, 0x01, 0x02, 0xFD,
+ 0x00, 0xFD, 0x26, 0xFD, 0x00, 0xFE, 0x0F, 0x32, 0x30, 0x31, 0x37, 0x30, 0x31, 0x30, 0x32, 0x54, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0xFD, 0x00, 0xFF, 0x0F, 0x32, 0x30, 0x31, 0x38, 0x30, 0x31, 0x30, 0x32, 0x54, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x17, 0x47, 0x30, 0x45, 0x02, 0x20, 0x56, 0x34, 0x49, 0xAC, 0x72, 0x4E, 0x58, 0x24, 0x6F, 0x14, 0xEE, 0xD3, 0x01,
+ 0x5B, 0xD4, 0x0A, 0x26, 0x2B, 0x6A, 0xD1, 0xB3, 0x33, 0x69, 0x4D, 0x64, 0x0C, 0xAA, 0xAE, 0x63, 0x59, 0x6A, 0xFD, 0x02,
+ 0x21, 0x00, 0xFD, 0xB9, 0x9E, 0x37, 0x70, 0x9C, 0xE2, 0x7A, 0x0A, 0xFD, 0x64, 0x99, 0x1B, 0xA3, 0x78, 0x83, 0x09, 0xC6,
+ 0xA0, 0x6D, 0x7A, 0x55, 0x8F, 0x6C, 0x35, 0xAB, 0x63, 0x78, 0x9D, 0xF3, 0xDC, 0xBC
+};
+
+const uint8_t ID2_KEY2_CERT2[] = {
+ 0x06, 0xFD, 0x02, 0x27, 0x07, 0x2B, 0x08, 0x03, 0x70, 0x69, 0x62, 0x08, 0x09, 0x69, 0x6E, 0x74, 0x65, 0x72, 0x66, 0x61,
+ 0x63, 0x65, 0x08, 0x02, 0x69, 0x64, 0x08, 0x01, 0x32, 0x08, 0x03, 0x4B, 0x45, 0x59, 0x08, 0x01, 0x02, 0x08, 0x06, 0x69,
+ 0x73, 0x73, 0x75, 0x65, 0x72, 0x08, 0x02, 0xFD, 0x02, 0x14, 0x09, 0x18, 0x01, 0x02, 0x19, 0x04, 0x00, 0x36, 0xEE, 0x80,
+ 0x15, 0xFD, 0x01, 0x4F, 0x30, 0x82, 0x01, 0x4B, 0x30, 0x82, 0x01, 0x03, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02,
+ 0x01, 0x30, 0x81, 0xF7, 0x02, 0x01, 0x01, 0x30, 0x2C, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x01, 0x01, 0x02, 0x21,
+ 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x30, 0x5B, 0x04, 0x20, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x04, 0x20, 0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A, 0x93, 0xE7, 0xB3,
+ 0xEB, 0xBD, 0x55, 0x76, 0x98, 0x86, 0xBC, 0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53, 0xB0, 0xF6, 0x3B, 0xCE, 0x3C, 0x3E, 0x27,
+ 0xD2, 0x60, 0x4B, 0x03, 0x15, 0x00, 0xC4, 0x9D, 0x36, 0x08, 0x86, 0xE7, 0x04, 0x93, 0x6A, 0x66, 0x78, 0xE1, 0x13, 0x9D,
+ 0x26, 0xB7, 0x81, 0x9F, 0x7E, 0x90, 0x04, 0x41, 0x04, 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, 0xBC, 0xE6,
+ 0xE5, 0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0, 0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2,
+ 0x96, 0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, 0x9B, 0x8E, 0xE7, 0xEB, 0x4A, 0x7C, 0x0F, 0x9E, 0x16, 0x2B, 0xCE, 0x33,
+ 0x57, 0x6B, 0x31, 0x5E, 0xCE, 0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51, 0xF5, 0x02, 0x21, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84,
+ 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51, 0x02, 0x01, 0x01, 0x03, 0x42, 0x00, 0x04, 0x2C, 0xC3, 0xAF, 0xA8, 0x73,
+ 0xF2, 0x61, 0xCF, 0x48, 0x04, 0x0F, 0x9D, 0xD3, 0xAF, 0x0B, 0xC6, 0x2F, 0x4D, 0xDA, 0x0E, 0x4C, 0x66, 0x1D, 0x03, 0x9D,
+ 0xFE, 0x2C, 0x0B, 0xB6, 0x25, 0x60, 0xBC, 0xFA, 0xDA, 0xFE, 0x6F, 0x43, 0xFA, 0x95, 0x45, 0x57, 0x8A, 0x25, 0xEC, 0x0F,
+ 0xF2, 0xB7, 0x43, 0x85, 0x0D, 0x0B, 0x8D, 0x97, 0x40, 0x83, 0x4C, 0x28, 0x1B, 0xD4, 0x2E, 0x99, 0x2C, 0x73, 0x7D, 0x16,
+ 0x50, 0x1B, 0x01, 0x03, 0x1C, 0x21, 0x07, 0x1F, 0x08, 0x03, 0x70, 0x69, 0x62, 0x08, 0x09, 0x69, 0x6E, 0x74, 0x65, 0x72,
+ 0x66, 0x61, 0x63, 0x65, 0x08, 0x02, 0x69, 0x64, 0x08, 0x01, 0x32, 0x08, 0x03, 0x4B, 0x45, 0x59, 0x08, 0x01, 0x02, 0xFD,
+ 0x00, 0xFD, 0x26, 0xFD, 0x00, 0xFE, 0x0F, 0x32, 0x30, 0x31, 0x37, 0x30, 0x31, 0x30, 0x32, 0x54, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0xFD, 0x00, 0xFF, 0x0F, 0x32, 0x30, 0x31, 0x38, 0x30, 0x31, 0x30, 0x32, 0x54, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x17, 0x48, 0x30, 0x46, 0x02, 0x21, 0x00, 0xB3, 0xF5, 0x96, 0x19, 0xE7, 0xF9, 0x6B, 0xCF, 0x14, 0x64, 0xB1, 0x08,
+ 0xFA, 0xFF, 0xB3, 0x52, 0x8B, 0x41, 0xCB, 0xE7, 0xE0, 0x3D, 0x14, 0x7B, 0xC2, 0xD0, 0xC8, 0x89, 0x88, 0xFA, 0x95, 0x73,
+ 0x02, 0x21, 0x00, 0xEC, 0x8E, 0x0C, 0x8B, 0x8C, 0x18, 0x8D, 0x00, 0x7C, 0x12, 0x68, 0x57, 0x87, 0xB1, 0x99, 0x69, 0xDA,
+ 0x46, 0xEF, 0x14, 0x2D, 0x04, 0x18, 0xBE, 0x1D, 0xAE, 0x79, 0x49, 0xFD, 0x22, 0x8E, 0xBB
+};
+
+PibDataFixture::PibDataFixture()
+ : id1Key1Cert1(Block(ID1_KEY1_CERT1, sizeof(ID1_KEY1_CERT1)))
+ , id1Key1Cert2(Block(ID1_KEY1_CERT2, sizeof(ID1_KEY1_CERT2)))
+ , id1Key2Cert1(Block(ID1_KEY2_CERT1, sizeof(ID1_KEY2_CERT1)))
+ , id1Key2Cert2(Block(ID1_KEY2_CERT2, sizeof(ID1_KEY2_CERT2)))
+
+ , id2Key1Cert1(Block(ID2_KEY1_CERT1, sizeof(ID2_KEY1_CERT1)))
+ , id2Key1Cert2(Block(ID2_KEY1_CERT2, sizeof(ID2_KEY1_CERT2)))
+ , id2Key2Cert1(Block(ID2_KEY2_CERT1, sizeof(ID2_KEY2_CERT1)))
+ , id2Key2Cert2(Block(ID2_KEY2_CERT2, sizeof(ID2_KEY2_CERT2)))
+
+ , id1(id1Key1Cert1.getIdentity())
+ , id2(id2Key1Cert1.getIdentity())
+
+ , id1Key1Name(id1Key1Cert1.getKeyName())
+ , id1Key2Name(id1Key2Cert1.getKeyName())
+
+ , id2Key1Name(id2Key1Cert1.getKeyName())
+ , id2Key2Name(id2Key2Cert1.getKeyName())
+
+ , id1Key1(id1Key1Cert1.getPublicKey())
+ , id1Key2(id1Key2Cert1.getPublicKey())
+ , id2Key1(id2Key1Cert1.getPublicKey())
+ , id2Key2(id2Key2Cert1.getPublicKey())
+{
+ BOOST_ASSERT(id1Key1Cert1.getPublicKey() == id1Key1Cert2.getPublicKey());
+ BOOST_ASSERT(id1Key2Cert1.getPublicKey() == id1Key2Cert2.getPublicKey());
+ BOOST_ASSERT(id2Key1Cert1.getPublicKey() == id2Key1Cert2.getPublicKey());
+ BOOST_ASSERT(id2Key2Cert1.getPublicKey() == id2Key2Cert2.getPublicKey());
+
+ BOOST_ASSERT(id1Key1Cert1.getPublicKey() == id1Key1);
+ BOOST_ASSERT(id1Key1Cert2.getPublicKey() == id1Key1);
+ BOOST_ASSERT(id1Key2Cert1.getPublicKey() == id1Key2);
+ BOOST_ASSERT(id1Key2Cert2.getPublicKey() == id1Key2);
+
+ BOOST_ASSERT(id2Key1Cert1.getPublicKey() == id2Key1);
+ BOOST_ASSERT(id2Key1Cert2.getPublicKey() == id2Key1);
+ BOOST_ASSERT(id2Key2Cert1.getPublicKey() == id2Key2);
+ BOOST_ASSERT(id2Key2Cert2.getPublicKey() == id2Key2);
+
+ BOOST_ASSERT(id1Key1Cert2.getIdentity() == id1);
+ BOOST_ASSERT(id1Key2Cert1.getIdentity() == id1);
+ BOOST_ASSERT(id1Key2Cert2.getIdentity() == id1);
+
+ BOOST_ASSERT(id2Key1Cert2.getIdentity() == id2);
+ BOOST_ASSERT(id2Key2Cert1.getIdentity() == id2);
+ BOOST_ASSERT(id2Key2Cert2.getIdentity() == id2);
+
+ BOOST_ASSERT(id1Key1Cert2.getKeyName() == id1Key1Name);
+ BOOST_ASSERT(id1Key2Cert2.getKeyName() == id1Key2Name);
+
+ BOOST_ASSERT(id2Key1Cert2.getKeyName() == id2Key1Name);
+ BOOST_ASSERT(id2Key2Cert2.getKeyName() == id2Key2Name);
+}
+
+} // namespace tests
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/pib/pib-data-fixture.hpp b/tests/unit/security/pib/pib-data-fixture.hpp
new file mode 100644
index 0000000..2328702
--- /dev/null
+++ b/tests/unit/security/pib/pib-data-fixture.hpp
@@ -0,0 +1,66 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_TESTS_SECURITY_PIB_DATA_FIXTURE_HPP
+#define NDN_TESTS_SECURITY_PIB_DATA_FIXTURE_HPP
+
+#include "security/v2/certificate.hpp"
+
+#include "boost-test.hpp"
+
+namespace ndn {
+namespace security {
+namespace tests {
+
+class PibDataFixture
+{
+public:
+ PibDataFixture();
+
+public:
+ v2::Certificate id1Key1Cert1;
+ v2::Certificate id1Key1Cert2;
+ v2::Certificate id1Key2Cert1;
+ v2::Certificate id1Key2Cert2;
+ v2::Certificate id2Key1Cert1;
+ v2::Certificate id2Key1Cert2;
+ v2::Certificate id2Key2Cert1;
+ v2::Certificate id2Key2Cert2;
+
+ Name id1;
+ Name id2;
+
+ Name id1Key1Name;
+ Name id1Key2Name;
+ Name id2Key1Name;
+ Name id2Key2Name;
+
+ Buffer id1Key1;
+ Buffer id1Key2;
+ Buffer id2Key1;
+ Buffer id2Key2;
+};
+
+} // namespace tests
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_TESTS_SECURITY_PIB_DATA_FIXTURE_HPP
diff --git a/tests/unit/security/pib/pib-impl.t.cpp b/tests/unit/security/pib/pib-impl.t.cpp
new file mode 100644
index 0000000..6094b0e
--- /dev/null
+++ b/tests/unit/security/pib/pib-impl.t.cpp
@@ -0,0 +1,350 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/pib/pib-memory.hpp"
+#include "security/pib/pib-sqlite3.hpp"
+#include "security/pib/pib.hpp"
+#include "security/security-common.hpp"
+
+#include "boost-test.hpp"
+#include "pib-data-fixture.hpp"
+
+#include <boost/filesystem.hpp>
+#include <boost/mpl/list.hpp>
+
+namespace ndn {
+namespace security {
+namespace pib {
+namespace tests {
+
+using namespace ndn::security::tests;
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(Pib)
+BOOST_AUTO_TEST_SUITE(TestPibImpl)
+
+using pib::Pib;
+
+class PibMemoryFixture : public PibDataFixture
+{
+public:
+ PibMemory pib;
+};
+
+class PibSqlite3Fixture : public PibDataFixture
+{
+public:
+ PibSqlite3Fixture()
+ : tmpPath(boost::filesystem::path(UNIT_TEST_CONFIG_PATH) / "DbTest")
+ , pib(tmpPath.c_str())
+ {
+ }
+
+ ~PibSqlite3Fixture()
+ {
+ boost::filesystem::remove_all(tmpPath);
+ }
+
+public:
+ boost::filesystem::path tmpPath;
+ PibSqlite3 pib;
+};
+
+typedef boost::mpl::list<PibMemoryFixture,
+ PibSqlite3Fixture> PibImpls;
+
+BOOST_FIXTURE_TEST_CASE_TEMPLATE(TpmLocator, T, PibImpls, T)
+{
+ // Basic getting and setting
+ BOOST_CHECK_NO_THROW(this->pib.getTpmLocator());
+
+ BOOST_CHECK_NO_THROW(this->pib.setTpmLocator("tpmLocator"));
+ BOOST_CHECK_EQUAL(this->pib.getTpmLocator(), "tpmLocator");
+
+ // Add cert, and do not change TPM locator
+ this->pib.addCertificate(this->id1Key1Cert1);
+ BOOST_CHECK(this->pib.hasIdentity(this->id1));
+ BOOST_CHECK(this->pib.hasKey(this->id1Key1Name));
+ BOOST_CHECK(this->pib.hasCertificate(this->id1Key1Cert1.getName()));
+
+ // Set TPM locator to the same value, nothing should change
+ this->pib.setTpmLocator("tpmLocator");
+ BOOST_CHECK(this->pib.hasIdentity(this->id1));
+ BOOST_CHECK(this->pib.hasKey(this->id1Key1Name));
+ BOOST_CHECK(this->pib.hasCertificate(this->id1Key1Cert1.getName()));
+
+ // Change TPM locator (contents of PIB should not change)
+ this->pib.setTpmLocator("newTpmLocator");
+ BOOST_CHECK(this->pib.hasIdentity(this->id1));
+ BOOST_CHECK(this->pib.hasKey(this->id1Key1Name));
+ BOOST_CHECK(this->pib.hasCertificate(this->id1Key1Cert1.getName()));
+}
+
+BOOST_FIXTURE_TEST_CASE_TEMPLATE(IdentityManagement, T, PibImpls, T)
+{
+ // no default setting, throw Error
+ BOOST_CHECK_THROW(this->pib.getDefaultIdentity(), Pib::Error);
+
+ // check id1, which should not exist
+ BOOST_CHECK_EQUAL(this->pib.hasIdentity(this->id1), false);
+
+ // add id1, should be default
+ this->pib.addIdentity(this->id1);
+ BOOST_CHECK_EQUAL(this->pib.hasIdentity(this->id1), true);
+ BOOST_CHECK_NO_THROW(this->pib.getDefaultIdentity());
+ BOOST_CHECK_EQUAL(this->pib.getDefaultIdentity(), this->id1);
+
+ // add id2, should not be default
+ this->pib.addIdentity(this->id2);
+ BOOST_CHECK_EQUAL(this->pib.hasIdentity(this->id2), true);
+ BOOST_CHECK_EQUAL(this->pib.getDefaultIdentity(), this->id1);
+
+ // set id2 explicitly as default
+ this->pib.setDefaultIdentity(this->id2);
+ BOOST_CHECK_EQUAL(this->pib.getDefaultIdentity(), this->id2);
+
+ // remove id2, should not have default identity
+ this->pib.removeIdentity(this->id2);
+ BOOST_CHECK_EQUAL(this->pib.hasIdentity(this->id2), false);
+ BOOST_CHECK_THROW(this->pib.getDefaultIdentity(), Pib::Error);
+
+ // add id2 again, should be default
+ this->pib.addIdentity(this->id2);
+ BOOST_CHECK_EQUAL(this->pib.getDefaultIdentity(), this->id2);
+
+ // get all identities, should contain id1 and id2
+ std::set<Name> idNames = this->pib.getIdentities();
+ BOOST_CHECK_EQUAL(idNames.size(), 2);
+ BOOST_CHECK_EQUAL(idNames.count(this->id1), 1);
+ BOOST_CHECK_EQUAL(idNames.count(this->id2), 1);
+}
+
+BOOST_FIXTURE_TEST_CASE_TEMPLATE(ClearIdentities, T, PibImpls, T)
+{
+ this->pib.setTpmLocator("tpmLocator");
+
+ // Add id, key, and cert
+ this->pib.addCertificate(this->id1Key1Cert1);
+ BOOST_CHECK(this->pib.hasIdentity(this->id1));
+ BOOST_CHECK(this->pib.hasKey(this->id1Key1Name));
+ BOOST_CHECK(this->pib.hasCertificate(this->id1Key1Cert1.getName()));
+
+ // Clear identities
+ this->pib.clearIdentities();
+ BOOST_CHECK_EQUAL(this->pib.getIdentities().size(), 0);
+ BOOST_CHECK_EQUAL(this->pib.getKeysOfIdentity(this->id1).size(), 0);
+ BOOST_CHECK_EQUAL(this->pib.getCertificatesOfKey(this->id1Key1Name).size(), 0);
+ BOOST_CHECK_EQUAL(this->pib.getTpmLocator(), "tpmLocator");
+}
+
+BOOST_FIXTURE_TEST_CASE_TEMPLATE(KeyManagement, T, PibImpls, T)
+{
+ // no default setting, throw Error
+ BOOST_CHECK_THROW(this->pib.getDefaultKeyOfIdentity(this->id1), Pib::Error);
+
+ // check id1Key1, should not exist, neither should id1.
+ BOOST_CHECK_EQUAL(this->pib.hasKey(this->id1Key1Name), false);
+ BOOST_CHECK_EQUAL(this->pib.hasIdentity(this->id1), false);
+
+ // add id1Key1, should be default, id1 should be added implicitly
+ this->pib.addKey(this->id1, this->id1Key1Name, this->id1Key1.data(), this->id1Key1.size());
+ BOOST_CHECK_EQUAL(this->pib.hasKey(this->id1Key1Name), true);
+ BOOST_CHECK_EQUAL(this->pib.hasIdentity(this->id1), true);
+ const Buffer& keyBits = this->pib.getKeyBits(this->id1Key1Name);
+ BOOST_CHECK(keyBits == this->id1Key1);
+ BOOST_CHECK_NO_THROW(this->pib.getDefaultKeyOfIdentity(this->id1));
+ BOOST_CHECK_EQUAL(this->pib.getDefaultKeyOfIdentity(this->id1), this->id1Key1Name);
+
+ // add id1Key2, should not be default
+ this->pib.addKey(this->id1, this->id1Key2Name, this->id1Key2.data(), this->id1Key2.size());
+ BOOST_CHECK_EQUAL(this->pib.hasKey(this->id1Key2Name), true);
+ BOOST_CHECK_EQUAL(this->pib.getDefaultKeyOfIdentity(this->id1), this->id1Key1Name);
+
+ // set id1Key2 explicitly as default
+ this->pib.setDefaultKeyOfIdentity(this->id1, this->id1Key2Name);
+ BOOST_CHECK_EQUAL(this->pib.getDefaultKeyOfIdentity(this->id1), this->id1Key2Name);
+
+ // set a non-existing key as default, throw Error
+ BOOST_CHECK_THROW(this->pib.setDefaultKeyOfIdentity(this->id1, Name("/non-existing")),
+ Pib::Error);
+
+ // remove id1Key2, should not have default key
+ this->pib.removeKey(this->id1Key2Name);
+ BOOST_CHECK_EQUAL(this->pib.hasKey(this->id1Key2Name), false);
+ BOOST_CHECK_THROW(this->pib.getKeyBits(this->id1Key2Name), Pib::Error);
+ BOOST_CHECK_THROW(this->pib.getDefaultKeyOfIdentity(this->id1), Pib::Error);
+
+ // add id1Key2 back, should be default
+ this->pib.addKey(this->id1, this->id1Key2Name, this->id1Key2.data(), this->id1Key2.size());
+ BOOST_CHECK_NO_THROW(this->pib.getKeyBits(this->id1Key2Name));
+ BOOST_CHECK_EQUAL(this->pib.getDefaultKeyOfIdentity(this->id1), this->id1Key2Name);
+
+ // get all the keys: id1Key1 and id1Key2
+ std::set<Name> keyNames = this->pib.getKeysOfIdentity(this->id1);
+ BOOST_CHECK_EQUAL(keyNames.size(), 2);
+ BOOST_CHECK_EQUAL(keyNames.count(this->id1Key1Name), 1);
+ BOOST_CHECK_EQUAL(keyNames.count(this->id1Key2Name), 1);
+
+ // remove id1, should remove all the keys
+ this->pib.removeIdentity(this->id1);
+ keyNames = this->pib.getKeysOfIdentity(this->id1);
+ BOOST_CHECK_EQUAL(keyNames.size(), 0);
+}
+
+BOOST_FIXTURE_TEST_CASE_TEMPLATE(CertificateManagement, T, PibImpls, T)
+{
+ // no default setting, throw Error
+ BOOST_CHECK_THROW(this->pib.getDefaultCertificateOfKey(this->id1Key1Name), Pib::Error);
+
+ // check id1Key1Cert1, should not exist, neither should id1 and id1Key1
+ BOOST_CHECK_EQUAL(this->pib.hasCertificate(this->id1Key1Cert1.getName()), false);
+ BOOST_CHECK_EQUAL(this->pib.hasIdentity(this->id1), false);
+ BOOST_CHECK_EQUAL(this->pib.hasKey(this->id1Key1Name), false);
+
+ // add id1Key1Cert1, should be default, id1 and id1Key1 should be added implicitly
+ this->pib.addCertificate(this->id1Key1Cert1);
+ BOOST_CHECK_EQUAL(this->pib.hasCertificate(this->id1Key1Cert1.getName()), true);
+ BOOST_CHECK_EQUAL(this->pib.hasIdentity(this->id1), true);
+ BOOST_CHECK_EQUAL(this->pib.hasKey(this->id1Key1Name), true);
+ BOOST_CHECK_EQUAL(this->pib.getCertificate(this->id1Key1Cert1.getName()).wireEncode(),
+ this->id1Key1Cert1.wireEncode());
+ BOOST_CHECK_NO_THROW(this->pib.getDefaultCertificateOfKey(this->id1Key1Name));
+ BOOST_CHECK_EQUAL(this->pib.getDefaultCertificateOfKey(this->id1Key1Name), this->id1Key1Cert1);
+
+ // add id1Key1Cert2, should not be default
+ this->pib.addCertificate(this->id1Key1Cert2);
+ BOOST_CHECK_EQUAL(this->pib.hasCertificate(this->id1Key1Cert2.getName()), true);
+ BOOST_CHECK_EQUAL(this->pib.getDefaultCertificateOfKey(this->id1Key1Name), this->id1Key1Cert1);
+
+ // set id1Key1Cert2 explicitly as default
+ this->pib.setDefaultCertificateOfKey(this->id1Key1Name, this->id1Key1Cert2.getName());
+ BOOST_CHECK_EQUAL(this->pib.getDefaultCertificateOfKey(this->id1Key1Name), this->id1Key1Cert2);
+
+ // set a non-existing cert as default, throw Error
+ BOOST_CHECK_THROW(this->pib.setDefaultCertificateOfKey(this->id1Key1Name, Name("/non-existing")),
+ Pib::Error);
+
+ // remove id1Key1Cert2, should not have default cert
+ this->pib.removeCertificate(this->id1Key1Cert2.getName());
+ BOOST_CHECK_EQUAL(this->pib.hasCertificate(this->id1Key1Cert2.getName()), false);
+ BOOST_CHECK_THROW(this->pib.getCertificate(this->id1Key1Cert2.getName()), Pib::Error);
+ BOOST_CHECK_THROW(this->pib.getDefaultCertificateOfKey(this->id1Key1Name), Pib::Error);
+
+ // add id1Key1Cert2, should be default
+ this->pib.addCertificate(this->id1Key1Cert2);
+ BOOST_CHECK_NO_THROW(this->pib.getCertificate(this->id1Key1Cert1.getName()));
+ BOOST_CHECK_EQUAL(this->pib.getDefaultCertificateOfKey(this->id1Key1Name), this->id1Key1Cert2);
+
+ // get all certificates: id1Key1Cert1 and id1Key1Cert2
+ std::set<Name> certNames = this->pib.getCertificatesOfKey(this->id1Key1Name);
+ BOOST_CHECK_EQUAL(certNames.size(), 2);
+ BOOST_CHECK_EQUAL(certNames.count(this->id1Key1Cert1.getName()), 1);
+ BOOST_CHECK_EQUAL(certNames.count(this->id1Key1Cert2.getName()), 1);
+
+ // remove id1Key1, should remove all the certs
+ this->pib.removeKey(this->id1Key1Name);
+ certNames = this->pib.getCertificatesOfKey(this->id1Key1Name);
+ BOOST_CHECK_EQUAL(certNames.size(), 0);
+}
+
+BOOST_FIXTURE_TEST_CASE_TEMPLATE(DefaultsManagement, T, PibImpls, T)
+{
+ this->pib.addIdentity(this->id1);
+ BOOST_CHECK_EQUAL(this->pib.getDefaultIdentity(), this->id1);
+
+ this->pib.addIdentity(this->id2);
+ BOOST_CHECK_EQUAL(this->pib.getDefaultIdentity(), this->id1);
+
+ this->pib.removeIdentity(this->id1);
+ BOOST_CHECK_THROW(this->pib.getDefaultIdentity(), Pib::Error);
+
+ this->pib.addKey(this->id2, this->id2Key1Name, this->id2Key1.data(), this->id2Key1.size());
+ BOOST_CHECK_EQUAL(this->pib.getDefaultIdentity(), this->id2);
+ BOOST_CHECK_EQUAL(this->pib.getDefaultKeyOfIdentity(this->id2), this->id2Key1Name);
+
+ this->pib.addKey(this->id2, this->id2Key2Name, this->id2Key2.data(), this->id2Key2.size());
+ BOOST_CHECK_EQUAL(this->pib.getDefaultKeyOfIdentity(this->id2), this->id2Key1Name);
+
+ this->pib.removeKey(this->id2Key1Name);
+ BOOST_CHECK_THROW(this->pib.getDefaultKeyOfIdentity(this->id2), Pib::Error);
+
+ this->pib.addCertificate(this->id2Key2Cert1);
+ BOOST_CHECK_EQUAL(this->pib.getDefaultKeyOfIdentity(this->id2), this->id2Key2Name);
+ BOOST_CHECK_EQUAL(this->pib.getDefaultCertificateOfKey(this->id2Key2Name).getName(), this->id2Key2Cert1.getName());
+
+ this->pib.addCertificate(this->id2Key2Cert2);
+ BOOST_CHECK_EQUAL(this->pib.getDefaultCertificateOfKey(this->id2Key2Name).getName(), this->id2Key2Cert1.getName());
+
+ this->pib.removeCertificate(this->id2Key2Cert2.getName());
+ BOOST_CHECK_EQUAL(this->pib.getDefaultCertificateOfKey(this->id2Key2Name).getName(), this->id2Key2Cert1.getName());
+}
+
+BOOST_FIXTURE_TEST_CASE_TEMPLATE(Overwrite, T, PibImpls, T)
+{
+ // check id1Key1, should not exist
+ this->pib.removeIdentity(this->id1);
+ BOOST_CHECK_EQUAL(this->pib.hasKey(this->id1Key1Name), false);
+
+ // add id1Key1
+ this->pib.addKey(this->id1, this->id1Key1Name, this->id1Key1.data(), this->id1Key1.size());
+ BOOST_CHECK_EQUAL(this->pib.hasKey(this->id1Key1Name), true);
+ const Buffer& keyBits = this->pib.getKeyBits(this->id1Key1Name);
+ BOOST_CHECK(keyBits == this->id1Key1);
+
+ // check overwrite, add a key with the same name.
+ this->pib.addKey(this->id1, this->id1Key1Name, this->id1Key2.data(), this->id1Key2.size());
+ const Buffer& keyBits2 = this->pib.getKeyBits(this->id1Key1Name);
+ BOOST_CHECK(keyBits2 == this->id1Key2);
+
+ // check id1Key1Cert1, should not exist
+ this->pib.removeIdentity(this->id1);
+ BOOST_CHECK_EQUAL(this->pib.hasCertificate(this->id1Key1Cert1.getName()), false);
+
+ // add id1Key1Cert1
+ this->pib.addKey(this->id1, this->id1Key1Name, this->id1Key1.data(), this->id1Key1.size());
+ this->pib.addCertificate(this->id1Key1Cert1);
+ BOOST_CHECK_EQUAL(this->pib.hasCertificate(this->id1Key1Cert1.getName()), true);
+
+ auto cert = this->pib.getCertificate(this->id1Key1Cert1.getName());
+ BOOST_CHECK_EQUAL(cert.wireEncode(), this->id1Key1Cert1.wireEncode());
+
+ // Create a fake cert with the same name
+ auto cert2 = this->id1Key2Cert1;
+ cert2.setName(this->id1Key1Cert1.getName());
+ cert2.setSignature(this->id1Key2Cert1.getSignature());
+ this->pib.addCertificate(cert2);
+
+ auto cert3 = this->pib.getCertificate(this->id1Key1Cert1.getName());
+ BOOST_CHECK_EQUAL(cert3.wireEncode(), cert2.wireEncode());
+
+ // both key and certificate are overwritten
+ Buffer keyBits3 = this->pib.getKeyBits(this->id1Key1Name);
+ BOOST_CHECK(keyBits3 == this->id1Key2);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestPibImpl
+BOOST_AUTO_TEST_SUITE_END() // Pib
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace pib
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/pib/pib-memory.t.cpp b/tests/unit/security/pib/pib-memory.t.cpp
new file mode 100644
index 0000000..72b0db8
--- /dev/null
+++ b/tests/unit/security/pib/pib-memory.t.cpp
@@ -0,0 +1,44 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/pib/pib-memory.hpp"
+
+#include "boost-test.hpp"
+
+namespace ndn {
+namespace security {
+namespace pib {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(Pib)
+BOOST_AUTO_TEST_SUITE(TestPibMemory)
+
+// Functionality is tested as part of pib-impl.t.cpp
+
+BOOST_AUTO_TEST_SUITE_END() // TestPibMemory
+BOOST_AUTO_TEST_SUITE_END() // Pib
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace pib
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/pib/pib-sqlite3.t.cpp b/tests/unit/security/pib/pib-sqlite3.t.cpp
new file mode 100644
index 0000000..b46cb50
--- /dev/null
+++ b/tests/unit/security/pib/pib-sqlite3.t.cpp
@@ -0,0 +1,44 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/pib/pib-sqlite3.hpp"
+
+#include "boost-test.hpp"
+
+namespace ndn {
+namespace security {
+namespace pib {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(Pib)
+BOOST_AUTO_TEST_SUITE(TestPibSqlite3)
+
+// Functionality is tested as part of pib-impl.t.cpp
+
+BOOST_AUTO_TEST_SUITE_END() // TestPibSqlite3
+BOOST_AUTO_TEST_SUITE_END() // Pib
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace pib
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/pib/pib.t.cpp b/tests/unit/security/pib/pib.t.cpp
new file mode 100644
index 0000000..0ce5afc
--- /dev/null
+++ b/tests/unit/security/pib/pib.t.cpp
@@ -0,0 +1,143 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/pib/pib.hpp"
+#include "security/pib/pib-memory.hpp"
+
+#include "boost-test.hpp"
+#include "pib-data-fixture.hpp"
+
+namespace ndn {
+namespace security {
+namespace pib {
+namespace tests {
+
+using namespace ndn::security::tests;
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(Pib)
+BOOST_FIXTURE_TEST_SUITE(TestPib, PibDataFixture)
+
+using pib::Pib;
+
+BOOST_AUTO_TEST_CASE(ValidityChecking)
+{
+ Pib pib("pib-memory", "", make_shared<PibMemory>());
+
+ Identity id = pib.addIdentity(id1);
+
+ BOOST_CHECK_EQUAL(static_cast<bool>(id), true);
+ BOOST_CHECK_EQUAL(!id, false);
+
+ if (id)
+ BOOST_CHECK(true);
+ else
+ BOOST_CHECK(false);
+
+ // key
+ Key key = id.addKey(id1Key1.data(), id1Key1.size(), id1Key1Name);
+
+ BOOST_CHECK_EQUAL(static_cast<bool>(key), true);
+ BOOST_CHECK_EQUAL(!key, false);
+
+ if (key)
+ BOOST_CHECK(true);
+ else
+ BOOST_CHECK(false);
+}
+
+BOOST_AUTO_TEST_CASE(TpmLocator)
+{
+ Pib pib("pib-memory", "", make_shared<PibMemory>());
+
+ BOOST_CHECK_EQUAL(pib.getPibLocator(), "pib-memory:");
+ BOOST_CHECK_THROW(pib.getTpmLocator(), Pib::Error);
+
+ pib.setTpmLocator("test-tpm-locator");
+ BOOST_CHECK_NO_THROW(pib.getTpmLocator());
+
+ BOOST_CHECK_THROW(pib.getIdentity(id1), Pib::Error);
+ pib.addIdentity(id1);
+ BOOST_CHECK_NO_THROW(pib.getIdentity(id1));
+
+ pib.setTpmLocator("another-tpm-locator");
+ BOOST_CHECK_THROW(pib.getIdentity(id1), Pib::Error);
+
+ pib.addIdentity(id1);
+ BOOST_CHECK_NO_THROW(pib.getIdentity(id1));
+ pib.reset();
+ BOOST_CHECK_THROW(pib.getIdentity(id1), Pib::Error);
+ BOOST_CHECK_THROW(pib.getTpmLocator(), Pib::Error);
+}
+
+BOOST_AUTO_TEST_CASE(IdentityOperations)
+{
+ Pib pib("pib-memory", "", make_shared<PibMemory>());
+ BOOST_CHECK_EQUAL(pib.getIdentities().size(), 0);
+
+ // get non-existing identity, throw Pib::Error
+ BOOST_CHECK_THROW(pib.getIdentity(id1), Pib::Error);
+ // get default identity when it is not set yet, throw Pib::Error
+ BOOST_CHECK_THROW(pib.getDefaultIdentity(), Pib::Error);
+
+ // add identity
+ pib.addIdentity(id1);
+ BOOST_CHECK_NO_THROW(pib.getIdentity(id1));
+ BOOST_CHECK_EQUAL(pib.getIdentities().size(), 1);
+
+ // new key becomes default key when there was no default key
+ BOOST_REQUIRE_NO_THROW(pib.getDefaultIdentity());
+ BOOST_CHECK_EQUAL(pib.getDefaultIdentity().getName(), id1);
+
+ // remove identity
+ pib.removeIdentity(id1);
+ BOOST_CHECK_THROW(pib.getIdentity(id1), Pib::Error);
+ BOOST_CHECK_THROW(pib.getDefaultIdentity(), Pib::Error);
+ BOOST_CHECK_EQUAL(pib.getIdentities().size(), 0);
+
+ // set default identity
+ BOOST_REQUIRE_NO_THROW(pib.setDefaultIdentity(id1));
+ BOOST_REQUIRE_NO_THROW(pib.getDefaultIdentity());
+ BOOST_CHECK_EQUAL(pib.getDefaultIdentity().getName(), id1);
+ BOOST_CHECK_EQUAL(pib.getIdentities().size(), 1);
+ BOOST_REQUIRE_NO_THROW(pib.setDefaultIdentity(id2));
+ BOOST_REQUIRE_NO_THROW(pib.getDefaultIdentity());
+ BOOST_CHECK_EQUAL(pib.getDefaultIdentity().getName(), id2);
+ BOOST_CHECK_EQUAL(pib.getIdentities().size(), 2);
+
+ // remove default identity
+ pib.removeIdentity(id2);
+ BOOST_CHECK_THROW(pib.getIdentity(id2), Pib::Error);
+ BOOST_CHECK_THROW(pib.getDefaultIdentity(), Pib::Error);
+ BOOST_CHECK_EQUAL(pib.getIdentities().size(), 1);
+ pib.removeIdentity(id1);
+ BOOST_CHECK_THROW(pib.getIdentity(id1), Pib::Error);
+ BOOST_CHECK_EQUAL(pib.getIdentities().size(), 0);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestPib
+BOOST_AUTO_TEST_SUITE_END() // Pib
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace pib
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/safe-bag.t.cpp b/tests/unit/security/safe-bag.t.cpp
new file mode 100644
index 0000000..0423c69
--- /dev/null
+++ b/tests/unit/security/safe-bag.t.cpp
@@ -0,0 +1,170 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ *
+ * @author Zhiyi Zhang <dreamerbarrychang@gmail.com>
+ */
+
+#include "security/safe-bag.hpp"
+
+#include "boost-test.hpp"
+
+namespace ndn {
+namespace security {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(TestSafeBag)
+
+const uint8_t CERT[] = {
+ 0x06, 0xc8, // Data
+ 0x07, 0x14, // Name
+ 0x08, 0x05,
+ 0x6c, 0x6f, 0x63, 0x61, 0x6c,
+ 0x08, 0x03,
+ 0x6e, 0x64, 0x6e,
+ 0x08, 0x06,
+ 0x70, 0x72, 0x65, 0x66, 0x69, 0x78,
+ 0x14, 0x07, // MetaInfo
+ 0x18, 0x01, // ContentType
+ 0x02,
+ 0x19, 0x02, // FreshnessPeriod
+ 0x27, 0x10,
+ 0x15, 0x08, // Content
+ 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x21,
+ 0x16, 0x1b, // SignatureInfo
+ 0x1b, 0x01, // SignatureType
+ 0x01,
+ 0x1c, 0x16, // KeyLocator
+ 0x07, 0x14, // Name
+ 0x08, 0x04,
+ 0x74, 0x65, 0x73, 0x74,
+ 0x08, 0x03,
+ 0x6b, 0x65, 0x79,
+ 0x08, 0x07,
+ 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x6f, 0x72,
+ 0x17, 0x80, // SignatureValue
+ 0x2f, 0xd6, 0xf1, 0x6e, 0x80, 0x6f, 0x10, 0xbe, 0xb1, 0x6f, 0x3e, 0x31, 0xec,
+ 0xe3, 0xb9, 0xea, 0x83, 0x30, 0x40, 0x03, 0xfc, 0xa0, 0x13, 0xd9, 0xb3, 0xc6,
+ 0x25, 0x16, 0x2d, 0xa6, 0x58, 0x41, 0x69, 0x62, 0x56, 0xd8, 0xb3, 0x6a, 0x38,
+ 0x76, 0x56, 0xea, 0x61, 0xb2, 0x32, 0x70, 0x1c, 0xb6, 0x4d, 0x10, 0x1d, 0xdc,
+ 0x92, 0x8e, 0x52, 0xa5, 0x8a, 0x1d, 0xd9, 0x96, 0x5e, 0xc0, 0x62, 0x0b, 0xcf,
+ 0x3a, 0x9d, 0x7f, 0xca, 0xbe, 0xa1, 0x41, 0x71, 0x85, 0x7a, 0x8b, 0x5d, 0xa9,
+ 0x64, 0xd6, 0x66, 0xb4, 0xe9, 0x8d, 0x0c, 0x28, 0x43, 0xee, 0xa6, 0x64, 0xe8,
+ 0x55, 0xf6, 0x1c, 0x19, 0x0b, 0xef, 0x99, 0x25, 0x1e, 0xdc, 0x78, 0xb3, 0xa7,
+ 0xaa, 0x0d, 0x14, 0x58, 0x30, 0xe5, 0x37, 0x6a, 0x6d, 0xdb, 0x56, 0xac, 0xa3,
+ 0xfc, 0x90, 0x7a, 0xb8, 0x66, 0x9c, 0x0e, 0xf6, 0xb7, 0x64, 0xd1
+};
+
+const uint8_t ENCRYPTED_KEY_BAG[] = {
+ 0x2f, 0xd6, 0xf1, 0x6e, 0x80, 0x6f, 0x10, 0xbe
+};
+
+const uint8_t SAFE_BAG[] = {
+ 0x80, 0xd4, // SafeBag
+ 0x06, 0xc8, // Data
+ 0x07, 0x14, // Name
+ 0x08, 0x05,
+ 0x6c, 0x6f, 0x63, 0x61, 0x6c,
+ 0x08, 0x03,
+ 0x6e, 0x64, 0x6e,
+ 0x08, 0x06,
+ 0x70, 0x72, 0x65, 0x66, 0x69, 0x78,
+ 0x14, 0x07, // MetaInfo
+ 0x18, 0x01, // ContentType
+ 0x02,
+ 0x19, 0x02, // FreshnessPeriod
+ 0x27, 0x10,
+ 0x15, 0x08, // Content
+ 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x21,
+ 0x16, 0x1b, // SignatureInfo
+ 0x1b, 0x01, // SignatureType
+ 0x01,
+ 0x1c, 0x16, // KeyLocator
+ 0x07, 0x14, // Name
+ 0x08, 0x04,
+ 0x74, 0x65, 0x73, 0x74,
+ 0x08, 0x03,
+ 0x6b, 0x65, 0x79,
+ 0x08, 0x07,
+ 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x6f, 0x72,
+ 0x17, 0x80, // SignatureValue
+ 0x2f, 0xd6, 0xf1, 0x6e, 0x80, 0x6f, 0x10, 0xbe, 0xb1, 0x6f, 0x3e, 0x31, 0xec,
+ 0xe3, 0xb9, 0xea, 0x83, 0x30, 0x40, 0x03, 0xfc, 0xa0, 0x13, 0xd9, 0xb3, 0xc6,
+ 0x25, 0x16, 0x2d, 0xa6, 0x58, 0x41, 0x69, 0x62, 0x56, 0xd8, 0xb3, 0x6a, 0x38,
+ 0x76, 0x56, 0xea, 0x61, 0xb2, 0x32, 0x70, 0x1c, 0xb6, 0x4d, 0x10, 0x1d, 0xdc,
+ 0x92, 0x8e, 0x52, 0xa5, 0x8a, 0x1d, 0xd9, 0x96, 0x5e, 0xc0, 0x62, 0x0b, 0xcf,
+ 0x3a, 0x9d, 0x7f, 0xca, 0xbe, 0xa1, 0x41, 0x71, 0x85, 0x7a, 0x8b, 0x5d, 0xa9,
+ 0x64, 0xd6, 0x66, 0xb4, 0xe9, 0x8d, 0x0c, 0x28, 0x43, 0xee, 0xa6, 0x64, 0xe8,
+ 0x55, 0xf6, 0x1c, 0x19, 0x0b, 0xef, 0x99, 0x25, 0x1e, 0xdc, 0x78, 0xb3, 0xa7,
+ 0xaa, 0x0d, 0x14, 0x58, 0x30, 0xe5, 0x37, 0x6a, 0x6d, 0xdb, 0x56, 0xac, 0xa3,
+ 0xfc, 0x90, 0x7a, 0xb8, 0x66, 0x9c, 0x0e, 0xf6, 0xb7, 0x64, 0xd1,
+ 0x81, 0x08, // EncryptedKeyBag
+ 0x2f, 0xd6, 0xf1, 0x6e, 0x80, 0x6f, 0x10, 0xbe
+};
+
+BOOST_AUTO_TEST_CASE(Constructor)
+{
+ Block dataBlock(CERT, sizeof(CERT));
+ Data data(dataBlock);
+ SafeBag safeBag1(data, ENCRYPTED_KEY_BAG, sizeof(ENCRYPTED_KEY_BAG));
+
+ Block safeBagBlock(SAFE_BAG, sizeof(SAFE_BAG));
+ SafeBag safeBag2(safeBagBlock);
+
+ Buffer buffer(ENCRYPTED_KEY_BAG, sizeof(ENCRYPTED_KEY_BAG));
+ SafeBag safeBag3(data, buffer);
+
+ BOOST_CHECK(safeBag1.getCertificate() == data);
+ BOOST_CHECK(safeBag1.getEncryptedKeyBag() == buffer);
+ BOOST_CHECK(safeBag2.getCertificate() == data);
+ BOOST_CHECK(safeBag2.getEncryptedKeyBag() == buffer);
+ BOOST_CHECK(safeBag3.getCertificate() == data);
+ BOOST_CHECK(safeBag3.getEncryptedKeyBag() == buffer);
+}
+
+BOOST_AUTO_TEST_CASE(EncoderAndDecoder)
+{
+ Block dataBlock(CERT, sizeof(CERT));
+ Data data(dataBlock);
+ SafeBag safeBag(data, ENCRYPTED_KEY_BAG, sizeof(ENCRYPTED_KEY_BAG));
+
+ // wire encode
+ Block wireBlock = safeBag.wireEncode();
+ Block block(SAFE_BAG, sizeof(SAFE_BAG));
+
+ // check safe bag block
+ BOOST_CHECK_EQUAL(wireBlock, block);
+
+ // wire decode
+ SafeBag safeBag2;
+ safeBag2.wireDecode(wireBlock);
+
+ // check equal
+ Buffer buffer1 = safeBag2.getEncryptedKeyBag();
+ Buffer buffer2(ENCRYPTED_KEY_BAG, sizeof(ENCRYPTED_KEY_BAG));
+ BOOST_CHECK(buffer1 == buffer2);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestSafeBag
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/signature-sha256-with-ecdsa.t.cpp b/tests/unit/security/signature-sha256-with-ecdsa.t.cpp
new file mode 100644
index 0000000..2f90302
--- /dev/null
+++ b/tests/unit/security/signature-sha256-with-ecdsa.t.cpp
@@ -0,0 +1,154 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/signature-sha256-with-ecdsa.hpp"
+#include "security/verification-helpers.hpp"
+#include "util/scheduler.hpp"
+
+#include "boost-test.hpp"
+#include "../identity-management-time-fixture.hpp"
+#include "make-interest-data.hpp"
+
+namespace ndn {
+namespace security {
+namespace tests {
+
+using namespace ndn::tests;
+
+class SignatureSha256EcdsaTimeFixture : public IdentityManagementTimeFixture
+{
+public:
+ SignatureSha256EcdsaTimeFixture()
+ : scheduler(io)
+ {
+ }
+
+public:
+ Scheduler scheduler;
+};
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_FIXTURE_TEST_SUITE(TestSignatureSha256WithEcdsa, SignatureSha256EcdsaTimeFixture)
+
+const uint8_t sigInfo[] = {
+ 0x16, 0x1b, // SignatureInfo
+ 0x1b, 0x01, // SignatureType
+ 0x03,
+ 0x1c, 0x16, // KeyLocator
+ 0x07, 0x14, // Name: /test/key/locator
+ 0x08, 0x04,
+ 0x74, 0x65, 0x73, 0x74,
+ 0x08, 0x03,
+ 0x6b, 0x65, 0x79,
+ 0x08, 0x07,
+ 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x6f, 0x72
+};
+
+const uint8_t sigValue[] = {
+ 0x17, 0x40, // SignatureValue
+ 0x2f, 0xd6, 0xf1, 0x6e, 0x80, 0x6f, 0x10, 0xbe, 0xb1, 0x6f, 0x3e, 0x31, 0xec,
+ 0xe3, 0xb9, 0xea, 0x83, 0x30, 0x40, 0x03, 0xfc, 0xa0, 0x13, 0xd9, 0xb3, 0xc6,
+ 0x25, 0x16, 0x2d, 0xa6, 0x58, 0x41, 0x69, 0x62, 0x56, 0xd8, 0xb3, 0x6a, 0x38,
+ 0x76, 0x56, 0xea, 0x61, 0xb2, 0x32, 0x70, 0x1c, 0xb6, 0x4d, 0x10, 0x1d, 0xdc,
+ 0x92, 0x8e, 0x52, 0xa5, 0x8a, 0x1d, 0xd9, 0x96, 0x5e, 0xc0, 0x62, 0x0b
+};
+
+
+BOOST_AUTO_TEST_CASE(Decoding)
+{
+ Block sigInfoBlock(sigInfo, sizeof(sigInfo));
+ Block sigValueBlock(sigValue, sizeof(sigValue));
+
+ Signature sig(sigInfoBlock, sigValueBlock);
+ BOOST_CHECK_NO_THROW(SignatureSha256WithEcdsa{sig});
+ BOOST_CHECK_NO_THROW(sig.getKeyLocator());
+}
+
+BOOST_AUTO_TEST_CASE(Encoding)
+{
+ Name name("/test/key/locator");
+ KeyLocator keyLocator(name);
+
+ SignatureSha256WithEcdsa sig(keyLocator);
+
+ BOOST_CHECK_NO_THROW(sig.getKeyLocator());
+
+ const Block& encodeSigInfoBlock = sig.getInfo();
+
+ Block sigInfoBlock(sigInfo, sizeof(sigInfo));
+
+ BOOST_CHECK_EQUAL_COLLECTIONS(sigInfoBlock.wire(),
+ sigInfoBlock.wire() + sigInfoBlock.size(),
+ encodeSigInfoBlock.wire(),
+ encodeSigInfoBlock.wire() + encodeSigInfoBlock.size());
+
+ sig.setKeyLocator(Name("/test/another/key/locator"));
+
+ const Block& encodeSigInfoBlock2 = sig.getInfo();
+ BOOST_CHECK_NE(sigInfoBlock, encodeSigInfoBlock2);
+}
+
+BOOST_AUTO_TEST_CASE(DataSignature)
+{
+ Identity identity = addIdentity("/SecurityTestSignatureSha256WithEcdsa/DataSignature", EcKeyParams());
+
+ Data testData("/SecurityTestSignatureSha256WithEcdsa/DataSignature/Data1");
+ char content[5] = "1234";
+ testData.setContent(reinterpret_cast<uint8_t*>(content), 5);
+ BOOST_CHECK_NO_THROW(m_keyChain.sign(testData, security::SigningInfo(identity)));
+ Block dataBlock(testData.wireEncode().wire(), testData.wireEncode().size());
+
+ Data testData2;
+ testData2.wireDecode(dataBlock);
+ BOOST_CHECK(verifySignature(testData2, identity.getDefaultKey()));
+}
+
+BOOST_AUTO_TEST_CASE(InterestSignature)
+{
+ Identity identity = addIdentity("/SecurityTestSignatureSha256WithEcdsa/InterestSignature", EcKeyParams());
+
+ auto interest = makeInterest("/SecurityTestSignatureSha256WithEcdsa/InterestSignature/Interest1");
+ auto interest11 = makeInterest("/SecurityTestSignatureSha256WithEcdsa/InterestSignature/Interest1");
+
+ scheduler.scheduleEvent(100_ms, [&] {
+ m_keyChain.sign(*interest, security::SigningInfo(identity));
+ });
+
+ advanceClocks(100_ms);
+ scheduler.scheduleEvent(100_ms, [&] {
+ m_keyChain.sign(*interest11, security::SigningInfo(identity));
+ });
+
+ advanceClocks(100_ms);
+
+ Block interestBlock(interest->wireEncode().wire(), interest->wireEncode().size());
+
+ Interest interest2;
+ interest2.wireDecode(interestBlock);
+ BOOST_CHECK(verifySignature(interest2, identity.getDefaultKey()));
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestSignatureSha256WithEcdsa
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/signature-sha256-with-rsa.t.cpp b/tests/unit/security/signature-sha256-with-rsa.t.cpp
new file mode 100644
index 0000000..7de3774
--- /dev/null
+++ b/tests/unit/security/signature-sha256-with-rsa.t.cpp
@@ -0,0 +1,159 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/signature-sha256-with-rsa.hpp"
+#include "security/verification-helpers.hpp"
+#include "util/scheduler.hpp"
+
+#include "boost-test.hpp"
+#include "../identity-management-time-fixture.hpp"
+#include "make-interest-data.hpp"
+
+namespace ndn {
+namespace security {
+namespace tests {
+
+using namespace ndn::tests;
+
+class SignatureSha256RsaTimeFixture : public IdentityManagementTimeFixture
+{
+public:
+ SignatureSha256RsaTimeFixture()
+ : scheduler(io)
+ {
+ }
+
+public:
+ Scheduler scheduler;
+};
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_FIXTURE_TEST_SUITE(TestSignatureSha256WithRsa, SignatureSha256RsaTimeFixture)
+
+const uint8_t sigInfo[] = {
+ 0x16, 0x1b, // SignatureInfo
+ 0x1b, 0x01, // SignatureType
+ 0x01,
+ 0x1c, 0x16, // KeyLocator
+ 0x07, 0x14, // Name
+ 0x08, 0x04,
+ 0x74, 0x65, 0x73, 0x74,
+ 0x08, 0x03,
+ 0x6b, 0x65, 0x79,
+ 0x08, 0x07,
+ 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x6f, 0x72
+};
+
+const uint8_t sigValue[] = {
+0x17, 0x80, // SignatureValue
+ 0x2f, 0xd6, 0xf1, 0x6e, 0x80, 0x6f, 0x10, 0xbe, 0xb1, 0x6f, 0x3e, 0x31, 0xec,
+ 0xe3, 0xb9, 0xea, 0x83, 0x30, 0x40, 0x03, 0xfc, 0xa0, 0x13, 0xd9, 0xb3, 0xc6,
+ 0x25, 0x16, 0x2d, 0xa6, 0x58, 0x41, 0x69, 0x62, 0x56, 0xd8, 0xb3, 0x6a, 0x38,
+ 0x76, 0x56, 0xea, 0x61, 0xb2, 0x32, 0x70, 0x1c, 0xb6, 0x4d, 0x10, 0x1d, 0xdc,
+ 0x92, 0x8e, 0x52, 0xa5, 0x8a, 0x1d, 0xd9, 0x96, 0x5e, 0xc0, 0x62, 0x0b, 0xcf,
+ 0x3a, 0x9d, 0x7f, 0xca, 0xbe, 0xa1, 0x41, 0x71, 0x85, 0x7a, 0x8b, 0x5d, 0xa9,
+ 0x64, 0xd6, 0x66, 0xb4, 0xe9, 0x8d, 0x0c, 0x28, 0x43, 0xee, 0xa6, 0x64, 0xe8,
+ 0x55, 0xf6, 0x1c, 0x19, 0x0b, 0xef, 0x99, 0x25, 0x1e, 0xdc, 0x78, 0xb3, 0xa7,
+ 0xaa, 0x0d, 0x14, 0x58, 0x30, 0xe5, 0x37, 0x6a, 0x6d, 0xdb, 0x56, 0xac, 0xa3,
+ 0xfc, 0x90, 0x7a, 0xb8, 0x66, 0x9c, 0x0e, 0xf6, 0xb7, 0x64, 0xd1
+};
+
+
+BOOST_AUTO_TEST_CASE(Decoding)
+{
+ Block sigInfoBlock(sigInfo, sizeof(sigInfo));
+ Block sigValueBlock(sigValue, sizeof(sigValue));
+
+ Signature sig(sigInfoBlock, sigValueBlock);
+ BOOST_CHECK_NO_THROW(SignatureSha256WithRsa{sig});
+ BOOST_CHECK_NO_THROW(sig.getKeyLocator());
+}
+
+BOOST_AUTO_TEST_CASE(Encoding)
+{
+ Name name("/test/key/locator");
+ KeyLocator keyLocator(name);
+
+ SignatureSha256WithRsa sig(keyLocator);
+
+ BOOST_CHECK_NO_THROW(sig.getKeyLocator());
+
+ const Block& encodeSigInfoBlock = sig.getInfo();
+
+ Block sigInfoBlock(sigInfo, sizeof(sigInfo));
+
+ BOOST_CHECK_EQUAL_COLLECTIONS(sigInfoBlock.wire(),
+ sigInfoBlock.wire() + sigInfoBlock.size(),
+ encodeSigInfoBlock.wire(),
+ encodeSigInfoBlock.wire() + encodeSigInfoBlock.size());
+
+ sig.setKeyLocator(Name("/test/another/key/locator"));
+
+ const Block& encodeSigInfoBlock2 = sig.getInfo();
+ BOOST_CHECK_NE(sigInfoBlock, encodeSigInfoBlock2);
+}
+
+BOOST_AUTO_TEST_CASE(DataSignature)
+{
+ Identity identity = addIdentity("/SecurityTestSignatureSha256WithRsa/DataSignature", RsaKeyParams());
+
+ Data testData("/SecurityTestSignatureSha256WithRsa/DataSignature/Data1");
+ char content[5] = "1234";
+ testData.setContent(reinterpret_cast<uint8_t*>(content), 5);
+ BOOST_CHECK_NO_THROW(m_keyChain.sign(testData, security::SigningInfo(identity)));
+ Block dataBlock(testData.wireEncode().wire(), testData.wireEncode().size());
+
+ Data testData2;
+ testData2.wireDecode(dataBlock);
+ BOOST_CHECK(verifySignature(testData2, identity.getDefaultKey()));
+}
+
+BOOST_AUTO_TEST_CASE(InterestSignature)
+{
+ Identity identity = addIdentity("/SecurityTestSignatureSha256WithRsa/InterestSignature", RsaKeyParams());
+
+ auto interest = makeInterest("/SecurityTestSignatureSha256WithRsa/InterestSignature/Interest1");
+ auto interest11 = makeInterest("/SecurityTestSignatureSha256WithRsa/InterestSignature/Interest1");
+
+ scheduler.scheduleEvent(100_ms, [&] {
+ m_keyChain.sign(*interest, security::SigningInfo(identity));
+ });
+
+ advanceClocks(100_ms);
+ scheduler.scheduleEvent(100_ms, [&] {
+ m_keyChain.sign(*interest11, security::SigningInfo(identity));
+ });
+
+ advanceClocks(100_ms);
+
+ Block interestBlock(interest->wireEncode().wire(), interest->wireEncode().size());
+
+ Interest interest2;
+ interest2.wireDecode(interestBlock);
+ BOOST_CHECK(verifySignature(interest2, identity.getDefaultKey()));
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestSignatureSha256WithRsa
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/signing-helpers.t.cpp b/tests/unit/security/signing-helpers.t.cpp
new file mode 100644
index 0000000..af2c568
--- /dev/null
+++ b/tests/unit/security/signing-helpers.t.cpp
@@ -0,0 +1,71 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/signing-helpers.hpp"
+
+#include "boost-test.hpp"
+
+namespace ndn {
+namespace security {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(TestSigningHelpers)
+
+// update of this test case deferred until the new IdentityManagementFixture is available
+
+BOOST_AUTO_TEST_CASE(Identity)
+{
+ Name identity("/identity");
+ SigningInfo info = signingByIdentity(identity);
+ BOOST_CHECK_EQUAL(info.getSignerType(), SigningInfo::SIGNER_TYPE_ID);
+ BOOST_CHECK_EQUAL(info.getSignerName(), identity);
+}
+
+BOOST_AUTO_TEST_CASE(Key)
+{
+ Name key("/key");
+ SigningInfo info = signingByKey(key);
+ BOOST_CHECK_EQUAL(info.getSignerType(), SigningInfo::SIGNER_TYPE_KEY);
+ BOOST_CHECK_EQUAL(info.getSignerName(), key);
+}
+
+BOOST_AUTO_TEST_CASE(Certificate)
+{
+ Name cert("/cert");
+ SigningInfo info = signingByCertificate(cert);
+ BOOST_CHECK_EQUAL(info.getSignerType(), SigningInfo::SIGNER_TYPE_CERT);
+ BOOST_CHECK_EQUAL(info.getSignerName(), cert);
+}
+
+BOOST_AUTO_TEST_CASE(Sha256)
+{
+ SigningInfo info = signingWithSha256();
+ BOOST_CHECK_EQUAL(info.getSignerType(), SigningInfo::SIGNER_TYPE_SHA256);
+ BOOST_CHECK_EQUAL(info.getSignerName(), SigningInfo::getEmptyName());
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestSigningHelpers
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/signing-info.t.cpp b/tests/unit/security/signing-info.t.cpp
new file mode 100644
index 0000000..fc6f627
--- /dev/null
+++ b/tests/unit/security/signing-info.t.cpp
@@ -0,0 +1,250 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/signing-info.hpp"
+
+#include "boost-test.hpp"
+
+#include <boost/lexical_cast.hpp>
+#include <sstream>
+
+namespace ndn {
+namespace security {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(TestSigningInfo)
+
+BOOST_AUTO_TEST_CASE(Basic)
+{
+ Name id("/my-identity");
+ Name key("/my-key");
+ Name cert("/my-cert");
+
+ SigningInfo info;
+
+ BOOST_CHECK_EQUAL(info.getSignerType(), SigningInfo::SIGNER_TYPE_NULL);
+ BOOST_CHECK_EQUAL(info.getSignerName(), SigningInfo::getEmptyName());
+ BOOST_CHECK_EQUAL(info.getDigestAlgorithm(), DigestAlgorithm::SHA256);
+
+ const SignatureInfo& sigInfo = info.getSignatureInfo();
+ BOOST_CHECK_EQUAL(sigInfo.getSignatureType(), -1);
+ BOOST_CHECK_EQUAL(sigInfo.hasKeyLocator(), false);
+
+ info.setSigningIdentity(id);
+ BOOST_CHECK_EQUAL(info.getSignerType(), SigningInfo::SIGNER_TYPE_ID);
+ BOOST_CHECK_EQUAL(info.getSignerName(), id);
+ BOOST_CHECK_EQUAL(info.getDigestAlgorithm(), DigestAlgorithm::SHA256);
+
+ SigningInfo infoId(SigningInfo::SIGNER_TYPE_ID, id);
+ BOOST_CHECK_EQUAL(infoId.getSignerType(), SigningInfo::SIGNER_TYPE_ID);
+ BOOST_CHECK_EQUAL(infoId.getSignerName(), id);
+ BOOST_CHECK_EQUAL(infoId.getDigestAlgorithm(), DigestAlgorithm::SHA256);
+
+ info.setSigningKeyName(key);
+ BOOST_CHECK_EQUAL(info.getSignerType(), SigningInfo::SIGNER_TYPE_KEY);
+ BOOST_CHECK_EQUAL(info.getSignerName(), key);
+ BOOST_CHECK_EQUAL(info.getDigestAlgorithm(), DigestAlgorithm::SHA256);
+
+ SigningInfo infoKey(SigningInfo::SIGNER_TYPE_KEY, key);
+ BOOST_CHECK_EQUAL(infoKey.getSignerType(), SigningInfo::SIGNER_TYPE_KEY);
+ BOOST_CHECK_EQUAL(infoKey.getSignerName(), key);
+ BOOST_CHECK_EQUAL(infoKey.getDigestAlgorithm(), DigestAlgorithm::SHA256);
+
+ info.setSigningCertName(cert);
+ BOOST_CHECK_EQUAL(info.getSignerType(), SigningInfo::SIGNER_TYPE_CERT);
+ BOOST_CHECK_EQUAL(info.getSignerName(), cert);
+ BOOST_CHECK_EQUAL(info.getDigestAlgorithm(), DigestAlgorithm::SHA256);
+
+ SigningInfo infoCert(SigningInfo::SIGNER_TYPE_CERT, cert);
+ BOOST_CHECK_EQUAL(infoCert.getSignerType(), SigningInfo::SIGNER_TYPE_CERT);
+ BOOST_CHECK_EQUAL(infoCert.getSignerName(), cert);
+ BOOST_CHECK_EQUAL(infoCert.getDigestAlgorithm(), DigestAlgorithm::SHA256);
+
+ info.setSha256Signing();
+ BOOST_CHECK_EQUAL(info.getSignerType(), SigningInfo::SIGNER_TYPE_SHA256);
+ BOOST_CHECK_EQUAL(info.getSignerName(), SigningInfo::getEmptyName());
+ BOOST_CHECK_EQUAL(info.getDigestAlgorithm(), DigestAlgorithm::SHA256);
+
+ SigningInfo infoSha(SigningInfo::SIGNER_TYPE_SHA256);
+ BOOST_CHECK_EQUAL(infoSha.getSignerType(), SigningInfo::SIGNER_TYPE_SHA256);
+ BOOST_CHECK_EQUAL(infoSha.getSignerName(), SigningInfo::getEmptyName());
+ BOOST_CHECK_EQUAL(infoSha.getDigestAlgorithm(), DigestAlgorithm::SHA256);
+}
+
+BOOST_AUTO_TEST_CASE(CustomSignatureInfo)
+{
+ SigningInfo info1;
+ BOOST_CHECK_EQUAL(info1.getSignatureInfo(), SignatureInfo());
+
+ SignatureInfo si;
+ si.setKeyLocator(Name("ndn:/test/key/locator"));
+ info1.setSignatureInfo(si);
+
+ BOOST_CHECK_EQUAL(info1.getSignatureInfo(), si);
+
+ SigningInfo info2(SigningInfo::SIGNER_TYPE_NULL, SigningInfo::getEmptyName(), si);
+ BOOST_CHECK_EQUAL(info2.getSignatureInfo(), si);
+}
+
+BOOST_AUTO_TEST_CASE(FromString)
+{
+ SigningInfo infoDefault("");
+ BOOST_CHECK_EQUAL(infoDefault.getSignerType(), SigningInfo::SIGNER_TYPE_NULL);
+ BOOST_CHECK_EQUAL(infoDefault.getSignerName(), SigningInfo::getEmptyName());
+ BOOST_CHECK_EQUAL(infoDefault.getDigestAlgorithm(), DigestAlgorithm::SHA256);
+
+ SigningInfo infoId("id:/my-identity");
+ BOOST_CHECK_EQUAL(infoId.getSignerType(), SigningInfo::SIGNER_TYPE_ID);
+ BOOST_CHECK_EQUAL(infoId.getSignerName(), "/my-identity");
+ BOOST_CHECK_EQUAL(infoId.getDigestAlgorithm(), DigestAlgorithm::SHA256);
+
+ SigningInfo infoKey("key:/my-key");
+ BOOST_CHECK_EQUAL(infoKey.getSignerType(), SigningInfo::SIGNER_TYPE_KEY);
+ BOOST_CHECK_EQUAL(infoKey.getSignerName(), "/my-key");
+ BOOST_CHECK_EQUAL(infoKey.getDigestAlgorithm(), DigestAlgorithm::SHA256);
+
+ SigningInfo infoCert("cert:/my-cert");
+ BOOST_CHECK_EQUAL(infoCert.getSignerType(), SigningInfo::SIGNER_TYPE_CERT);
+ BOOST_CHECK_EQUAL(infoCert.getSignerName(), "/my-cert");
+ BOOST_CHECK_EQUAL(infoCert.getDigestAlgorithm(), DigestAlgorithm::SHA256);
+
+ SigningInfo infoSha("id:/localhost/identity/digest-sha256");
+ BOOST_CHECK_EQUAL(infoSha.getSignerType(), SigningInfo::SIGNER_TYPE_SHA256);
+ BOOST_CHECK_EQUAL(infoSha.getSignerName(), SigningInfo::getEmptyName());
+ BOOST_CHECK_EQUAL(infoSha.getDigestAlgorithm(), DigestAlgorithm::SHA256);
+}
+
+BOOST_AUTO_TEST_CASE(ToString)
+{
+ // We can't use lexical_cast due to Boost Bug 6298.
+ std::stringstream ss;
+ ss << SigningInfo();
+ BOOST_CHECK_EQUAL(ss.str(), "");
+
+ BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(
+ SigningInfo(SigningInfo::SIGNER_TYPE_ID, "/my-identity")), "id:/my-identity");
+ BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(
+ SigningInfo(SigningInfo::SIGNER_TYPE_KEY, "/my-key")), "key:/my-key");
+ BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(
+ SigningInfo(SigningInfo::SIGNER_TYPE_CERT, "/my-cert")), "cert:/my-cert");
+ BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(
+ SigningInfo(SigningInfo::SIGNER_TYPE_SHA256)),
+ "id:/localhost/identity/digest-sha256");
+}
+
+BOOST_AUTO_TEST_CASE(Chaining)
+{
+ SigningInfo info = SigningInfo()
+ .setSigningIdentity("/identity")
+ .setSigningKeyName("/key/name")
+ .setSigningCertName("/cert/name")
+ .setPibIdentity(Identity())
+ .setPibKey(Key())
+ .setSha256Signing()
+ .setDigestAlgorithm(DigestAlgorithm::SHA256)
+ .setSignatureInfo(SignatureInfo());
+
+ BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(info), "id:/localhost/identity/digest-sha256");
+}
+
+BOOST_AUTO_TEST_CASE(OperatorEquals)
+{
+ // Check name equality
+ SigningInfo info1("id:/my-id");
+ SigningInfo info2("id:/my-id");
+ BOOST_CHECK_EQUAL(info1, info2);
+ // Change name, check inequality
+ info2 = SigningInfo("id:/not-same-id");
+ BOOST_CHECK_NE(info1, info2);
+
+ // Check name, digest algo equality
+ info1 = SigningInfo("id:/my-id");
+ info2 = SigningInfo("id:/my-id");
+ info1.setDigestAlgorithm(DigestAlgorithm::SHA256);
+ info2.setDigestAlgorithm(DigestAlgorithm::SHA256);
+ BOOST_CHECK_EQUAL(info1, info2);
+ // Change digest algo, check inequality
+ info2.setDigestAlgorithm(DigestAlgorithm::NONE);
+ BOOST_CHECK_NE(info1, info2);
+
+ // Check name, digest algo, signature info equality
+ info1 = SigningInfo("id:/my-id");
+ info2 = SigningInfo("id:/my-id");
+ info1.setDigestAlgorithm(DigestAlgorithm::SHA256);
+ info2.setDigestAlgorithm(DigestAlgorithm::SHA256);
+ SignatureInfo sigInfo1(tlv::DigestSha256);
+ info1.setSignatureInfo(sigInfo1);
+ info2.setSignatureInfo(sigInfo1);
+ BOOST_CHECK_EQUAL(info1, info2);
+ // Change signature info, check inequality
+ SignatureInfo sigInfo2(tlv::SignatureSha256WithRsa);
+ info2.setSignatureInfo(sigInfo2);
+ BOOST_CHECK_NE(info1, info2);
+}
+
+BOOST_AUTO_TEST_CASE(OperatorEqualsDifferentTypes)
+{
+ SigningInfo info1("key:/my-id/KEY/1");
+ SigningInfo info2("key:/my-id/KEY/1");
+ // Check equality for key type
+ BOOST_CHECK_EQUAL(info1, info2);
+ info2 = SigningInfo("id:/my-id");
+ // Change signature type, check inequality
+ BOOST_CHECK_NE(info1, info2);
+ info2 = SigningInfo("key:/not-same-id/KEY/1");
+ // Change key name, check inequality
+ BOOST_CHECK_NE(info1, info2);
+
+ info1 = SigningInfo("cert:/my-id/KEY/1/self/%FD01");
+ info2 = SigningInfo("cert:/my-id/KEY/1/self/%FD01");
+ // Check equality for cert type
+ BOOST_CHECK_EQUAL(info1, info2);
+ info2 = SigningInfo("cert:/not-my-id/KEY/1/other/%FD01");
+ // Change cert name, check inequality
+ BOOST_CHECK_NE(info1, info2);
+ info2 = SigningInfo("id:/my-id");
+ // Change signature type, check inequality
+ BOOST_CHECK_NE(info1, info2);
+
+ info1 = SigningInfo(SigningInfo::SIGNER_TYPE_NULL);
+ info2 = SigningInfo(SigningInfo::SIGNER_TYPE_NULL);
+ // Check equality for null type
+ BOOST_CHECK_EQUAL(info1, info2);
+ info2 = SigningInfo("id:/my-id");
+ // Change signature type, check inequality
+ BOOST_CHECK_NE(info1, info2);
+
+ info1 = SigningInfo(SigningInfo::SIGNER_TYPE_SHA256);
+ info2 = SigningInfo(SigningInfo::SIGNER_TYPE_SHA256);
+ // Check equality for SHA256 digest type
+ BOOST_CHECK_EQUAL(info1, info2);
+ info2 = SigningInfo("id:/my-id");
+ // Change signature type, check inequality
+ BOOST_CHECK_NE(info1, info2);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestSigningInfo
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/tmp-home/.ndn/client.conf b/tests/unit/security/tmp-home/.ndn/client.conf
new file mode 100644
index 0000000..b832cfc
--- /dev/null
+++ b/tests/unit/security/tmp-home/.ndn/client.conf
@@ -0,0 +1,2 @@
+pib=pib-sqlite3:/tmp/test/ndn-cxx/keychain
+tpm=tpm-file:/tmp/test/ndn-cxx/keychain
\ No newline at end of file
diff --git a/tests/unit/security/tpm/back-end-wrapper-file.hpp b/tests/unit/security/tpm/back-end-wrapper-file.hpp
new file mode 100644
index 0000000..dabd6d3
--- /dev/null
+++ b/tests/unit/security/tpm/back-end-wrapper-file.hpp
@@ -0,0 +1,72 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_TESTS_SECURITY_TPM_BACK_END_WRAPPER_FILE_HPP
+#define NDN_TESTS_SECURITY_TPM_BACK_END_WRAPPER_FILE_HPP
+
+#include "security/tpm/back-end-file.hpp"
+#include <boost/filesystem.hpp>
+
+namespace ndn {
+namespace security {
+namespace tpm {
+namespace tests {
+
+/**
+ * @brief A wrapper of tpm::BackEndFile for unit test template.
+ */
+class BackEndWrapperFile
+{
+public:
+ BackEndWrapperFile()
+ : m_tmpPath(boost::filesystem::path(UNIT_TEST_CONFIG_PATH) / "TpmFileTest")
+ , m_impl(make_unique<BackEndFile>(m_tmpPath.string()))
+ {
+ }
+
+ ~BackEndWrapperFile()
+ {
+ boost::filesystem::remove_all(m_tmpPath);
+ }
+
+ BackEnd&
+ getTpm()
+ {
+ return *m_impl;
+ }
+
+ std::string
+ getScheme() const
+ {
+ return "tpm-file";
+ }
+
+private:
+ const boost::filesystem::path m_tmpPath;
+ const unique_ptr<BackEnd> m_impl;
+};
+
+} // namespace tests
+} // namespace tpm
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_TESTS_SECURITY_TPM_BACK_END_WRAPPER_FILE_HPP
diff --git a/tests/unit/security/tpm/back-end-wrapper-mem.hpp b/tests/unit/security/tpm/back-end-wrapper-mem.hpp
new file mode 100644
index 0000000..ddf629b
--- /dev/null
+++ b/tests/unit/security/tpm/back-end-wrapper-mem.hpp
@@ -0,0 +1,64 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_TESTS_SECURITY_TPM_BACK_END_WRAPPER_MEM_HPP
+#define NDN_TESTS_SECURITY_TPM_BACK_END_WRAPPER_MEM_HPP
+
+#include "security/tpm/back-end-mem.hpp"
+
+namespace ndn {
+namespace security {
+namespace tpm {
+namespace tests {
+
+/**
+ * @brief A wrapper of tpm::BackEndMem for unit test template.
+ */
+class BackEndWrapperMem
+{
+public:
+ BackEndWrapperMem()
+ : m_impl(make_unique<BackEndMem>())
+ {
+ }
+
+ BackEnd&
+ getTpm()
+ {
+ return *m_impl;
+ }
+
+ std::string
+ getScheme() const
+ {
+ return "tpm-memory";
+ }
+
+private:
+ const unique_ptr<BackEnd> m_impl;
+};
+
+} // namespace tests
+} // namespace tpm
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_TESTS_SECURITY_TPM_BACK_END_WRAPPER_MEM_HPP
diff --git a/tests/unit/security/tpm/back-end-wrapper-osx.hpp b/tests/unit/security/tpm/back-end-wrapper-osx.hpp
new file mode 100644
index 0000000..6d7d35b
--- /dev/null
+++ b/tests/unit/security/tpm/back-end-wrapper-osx.hpp
@@ -0,0 +1,88 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_TESTS_SECURITY_TPM_BACK_END_WRAPPER_OSX_HPP
+#define NDN_TESTS_SECURITY_TPM_BACK_END_WRAPPER_OSX_HPP
+
+#include "security/tpm/back-end-osx.hpp"
+#include "security/tpm/key-handle-osx.hpp"
+
+#include <cstdlib>
+
+namespace ndn {
+namespace security {
+namespace tpm {
+namespace tests {
+
+/**
+ * @brief A wrapper of tpm::BackEndOsx for unit test template.
+ */
+class BackEndWrapperOsx
+{
+public:
+ BackEndWrapperOsx()
+ {
+ std::string oldHOME;
+ if (std::getenv("OLD_HOME"))
+ oldHOME = std::getenv("OLD_HOME");
+
+ if (std::getenv("HOME"))
+ m_HOME = std::getenv("HOME");
+
+ if (!oldHOME.empty())
+ setenv("HOME", oldHOME.data(), 1);
+ else
+ unsetenv("HOME");
+
+ m_impl = make_unique<BackEndOsx>();
+ }
+
+ ~BackEndWrapperOsx()
+ {
+ if (!m_HOME.empty())
+ setenv("HOME", m_HOME.data(), 1);
+ else
+ unsetenv("HOME");
+ }
+
+ BackEnd&
+ getTpm()
+ {
+ return *m_impl;
+ }
+
+ std::string
+ getScheme() const
+ {
+ return "tpm-osxkeychain";
+ }
+
+private:
+ std::string m_HOME;
+ unique_ptr<BackEnd> m_impl;
+};
+
+} // namespace tests
+} // namespace tpm
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_TESTS_SECURITY_TPM_BACK_END_WRAPPER_OSX_HPP
diff --git a/tests/unit/security/tpm/back-end.t.cpp b/tests/unit/security/tpm/back-end.t.cpp
new file mode 100644
index 0000000..5512ebd
--- /dev/null
+++ b/tests/unit/security/tpm/back-end.t.cpp
@@ -0,0 +1,279 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/tpm/back-end.hpp"
+
+#include "encoding/buffer-stream.hpp"
+#include "security/pib/key.hpp"
+#include "security/tpm/key-handle.hpp"
+#include "security/tpm/tpm.hpp"
+#include "security/transform/bool-sink.hpp"
+#include "security/transform/buffer-source.hpp"
+#include "security/transform/private-key.hpp"
+#include "security/transform/public-key.hpp"
+#include "security/transform/verifier-filter.hpp"
+
+#include "back-end-wrapper-file.hpp"
+#include "back-end-wrapper-mem.hpp"
+#ifdef NDN_CXX_HAVE_OSX_FRAMEWORKS
+#include "back-end-wrapper-osx.hpp"
+#endif // NDN_CXX_HAVE_OSX_FRAMEWORKS
+
+#include "boost-test.hpp"
+
+#include <boost/mpl/vector.hpp>
+#include <set>
+
+namespace ndn {
+namespace security {
+namespace tpm {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(Tpm)
+BOOST_AUTO_TEST_SUITE(TestBackEnd)
+
+using tpm::Tpm;
+
+using TestBackEnds = boost::mpl::vector<
+#ifdef NDN_CXX_HAVE_OSX_FRAMEWORKS
+ BackEndWrapperOsx,
+#endif // NDN_CXX_HAVE_OSX_FRAMEWORKS
+ BackEndWrapperMem,
+ BackEndWrapperFile>;
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(KeyManagement, T, TestBackEnds)
+{
+ T wrapper;
+ BackEnd& tpm = wrapper.getTpm();
+
+ Name identity("/Test/KeyName");
+ name::Component keyId("1");
+ Name keyName = v2::constructKeyName(identity, keyId);
+
+ // key should not exist
+ BOOST_CHECK_EQUAL(tpm.hasKey(keyName), false);
+ BOOST_CHECK(tpm.getKeyHandle(keyName) == nullptr);
+
+ // create key, should exist
+ BOOST_CHECK(tpm.createKey(identity, RsaKeyParams(keyId)) != nullptr);
+ BOOST_CHECK(tpm.hasKey(keyName));
+ BOOST_CHECK(tpm.getKeyHandle(keyName) != nullptr);
+
+ // create a key with the same name, should throw error
+ BOOST_CHECK_THROW(tpm.createKey(identity, RsaKeyParams(keyId)), Tpm::Error);
+
+ // delete key, should not exist
+ tpm.deleteKey(keyName);
+ BOOST_CHECK_EQUAL(tpm.hasKey(keyName), false);
+ BOOST_CHECK(tpm.getKeyHandle(keyName) == nullptr);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(RsaSigning, T, TestBackEnds)
+{
+ T wrapper;
+ BackEnd& tpm = wrapper.getTpm();
+
+ // create an RSA key
+ Name identity("/Test/KeyName");
+ unique_ptr<KeyHandle> key = tpm.createKey(identity, RsaKeyParams());
+ Name keyName = key->getKeyName();
+
+ const uint8_t content[] = {0x01, 0x02, 0x03, 0x04};
+ Block sigBlock(tlv::SignatureValue, key->sign(DigestAlgorithm::SHA256, content, sizeof(content)));
+
+ transform::PublicKey pubKey;
+ ConstBufferPtr pubKeyBits = key->derivePublicKey();
+ pubKey.loadPkcs8(pubKeyBits->data(), pubKeyBits->size());
+
+ bool result;
+ {
+ using namespace transform;
+ bufferSource(content, sizeof(content)) >>
+ verifierFilter(DigestAlgorithm::SHA256, pubKey, sigBlock.value(), sigBlock.value_size()) >>
+ boolSink(result);
+ }
+ BOOST_CHECK_EQUAL(result, true);
+
+ tpm.deleteKey(keyName);
+ BOOST_CHECK_EQUAL(tpm.hasKey(keyName), false);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(RsaDecryption, T, TestBackEnds)
+{
+ T wrapper;
+ BackEnd& tpm = wrapper.getTpm();
+
+ // create an RSA key
+ Name identity("/Test/KeyName");
+ unique_ptr<KeyHandle> key = tpm.createKey(identity, RsaKeyParams());
+ Name keyName = key->getKeyName();
+
+ const uint8_t content[] = {0x01, 0x02, 0x03, 0x04};
+
+ transform::PublicKey pubKey;
+ ConstBufferPtr pubKeyBits = key->derivePublicKey();
+ pubKey.loadPkcs8(pubKeyBits->data(), pubKeyBits->size());
+
+ ConstBufferPtr cipherText = pubKey.encrypt(content, sizeof(content));
+ ConstBufferPtr plainText = key->decrypt(cipherText->data(), cipherText->size());
+
+ BOOST_CHECK_EQUAL_COLLECTIONS(content, content + sizeof(content),
+ plainText->begin(), plainText->end());
+
+ tpm.deleteKey(keyName);
+ BOOST_CHECK_EQUAL(tpm.hasKey(keyName), false);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(EcdsaSigning, T, TestBackEnds)
+{
+ T wrapper;
+ BackEnd& tpm = wrapper.getTpm();
+
+ // create an EC key
+ Name identity("/Test/Ec/KeyName");
+ unique_ptr<KeyHandle> key = tpm.createKey(identity, EcKeyParams());
+ Name ecKeyName = key->getKeyName();
+
+ const uint8_t content[] = {0x01, 0x02, 0x03, 0x04};
+ Block sigBlock(tlv::SignatureValue, key->sign(DigestAlgorithm::SHA256, content, sizeof(content)));
+
+ transform::PublicKey pubKey;
+ ConstBufferPtr pubKeyBits = key->derivePublicKey();
+ pubKey.loadPkcs8(pubKeyBits->data(), pubKeyBits->size());
+
+ bool result;
+ {
+ using namespace transform;
+ bufferSource(content, sizeof(content)) >> verifierFilter(DigestAlgorithm::SHA256, pubKey,
+ sigBlock.value(), sigBlock.value_size())
+ >> boolSink(result);
+ }
+ BOOST_CHECK_EQUAL(result, true);
+
+ tpm.deleteKey(ecKeyName);
+ BOOST_CHECK_EQUAL(tpm.hasKey(ecKeyName), false);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(ImportExport, T, TestBackEnds)
+{
+ const std::string privKeyPkcs1 =
+ "MIIEpAIBAAKCAQEAw0WM1/WhAxyLtEqsiAJgWDZWuzkYpeYVdeeZcqRZzzfRgBQT\n"
+ "sNozS5t4HnwTZhwwXbH7k3QN0kRTV826Xobws3iigohnM9yTK+KKiayPhIAm/+5H\n"
+ "GT6SgFJhYhqo1/upWdueojil6RP4/AgavHhopxlAVbk6G9VdVnlQcQ5Zv0OcGi73\n"
+ "c+EnYD/YgURYGSngUi/Ynsh779p2U69/te9gZwIL5PuE9BiO6I39cL9z7EK1SfZh\n"
+ "OWvDe/qH7YhD/BHwcWit8FjRww1glwRVTJsA9rH58ynaAix0tcR/nBMRLUX+e3rU\n"
+ "RHg6UbSjJbdb9qmKM1fTGHKUzL/5pMG6uBU0ywIDAQABAoIBADQkckOIl4IZMUTn\n"
+ "W8LFv6xOdkJwMKC8G6bsPRFbyY+HvC2TLt7epSvfS+f4AcYWaOPcDu2E49vt2sNr\n"
+ "cASly8hgwiRRAB3dHH9vcsboiTo8bi2RFvMqvjv9w3tK2yMxVDtmZamzrrnaV3YV\n"
+ "Q+5nyKo2F/PMDjQ4eUAKDOzjhBuKHsZBTFnA1MFNI+UKj5X4Yp64DFmKlxTX/U2b\n"
+ "wzVywo5hzx2Uhw51jmoLls4YUvMJXD0wW5ZtYRuPogXvXb/of9ef/20/wU11WFKg\n"
+ "Xb4gfR8zUXaXS1sXcnVm3+24vIs9dApUwykuoyjOqxWqcHRec2QT2FxVGkFEraze\n"
+ "CPa4rMECgYEA5Y8CywomIcTgerFGFCeMHJr8nQGqY2V/owFb3k9maczPnC9p4a9R\n"
+ "c5szLxA9FMYFxurQZMBWSEG2JS1HR2mnjigx8UKjYML/A+rvvjZOMe4M6Sy2ggh4\n"
+ "SkLZKpWTzjTe07ByM/j5v/SjNZhWAG7sw4/LmPGRQkwJv+KZhGojuOkCgYEA2cOF\n"
+ "T6cJRv6kvzTz9S0COZOVm+euJh/BXp7oAsAmbNfOpckPMzqHXy8/wpdKl6AAcB57\n"
+ "OuztlNfV1D7qvbz7JuRlYwQ0cEfBgbZPcz1p18HHDXhwn57ZPb8G33Yh9Omg0HNA\n"
+ "Imb4LsVuSqxA6NwSj7cpRekgTedrhLFPJ+Ydb5MCgYEAsM3Q7OjILcIg0t6uht9e\n"
+ "vrlwTsz1mtCV2co2I6crzdj9HeI2vqf1KAElDt6G7PUHhglcr/yjd8uEqmWRPKNX\n"
+ "ddnnfVZB10jYeP/93pac6z/Zmc3iU4yKeUe7U10ZFf0KkiiYDQd59CpLef/2XScS\n"
+ "HB0oRofnxRQjfjLc4muNT+ECgYEAlcDk06MOOTly+F8lCc1bA1dgAmgwFd2usDBd\n"
+ "Y07a3e0HGnGLN3Kfl7C5i0tZq64HvxLnMd2vgLVxQlXGPpdQrC1TH+XLXg+qnlZO\n"
+ "ivSH7i0/gx75bHvj75eH1XK65V8pDVDEoSPottllAIs21CxLw3N1ObOZWJm2EfmR\n"
+ "cuHICmsCgYAtFJ1idqMoHxES3mlRpf2JxyQudP3SCm2WpGmqVzhRYInqeatY5sUd\n"
+ "lPLHm/p77RT7EyxQHTlwn8FJPuM/4ZH1rQd/vB+Y8qAtYJCexDMsbvLW+Js+VOvk\n"
+ "jweEC0nrcL31j9mF0vz5E6tfRu4hhJ6L4yfWs0gSejskeVB/w8QY4g==\n";
+ const std::string password("password");
+ const std::string wrongPassword("wrong");
+
+ T wrapper;
+ BackEnd& tpm = wrapper.getTpm();
+
+ Name keyName("/Test/KeyName/KEY/1");
+ tpm.deleteKey(keyName);
+ BOOST_REQUIRE_EQUAL(tpm.hasKey(keyName), false);
+
+ transform::PrivateKey sKey;
+ sKey.loadPkcs1Base64(reinterpret_cast<const uint8_t*>(privKeyPkcs1.data()), privKeyPkcs1.size());
+ OBufferStream os;
+ sKey.savePkcs8(os, password.data(), password.size());
+ auto pkcs8 = os.buf();
+
+ // import with wrong password
+ BOOST_CHECK_THROW(tpm.importKey(keyName, pkcs8->data(), pkcs8->size(), wrongPassword.data(), wrongPassword.size()),
+ BackEnd::Error);
+ BOOST_CHECK_EQUAL(tpm.hasKey(keyName), false);
+
+ // import with correct password
+ tpm.importKey(keyName, pkcs8->data(), pkcs8->size(), password.data(), password.size());
+ BOOST_CHECK_EQUAL(tpm.hasKey(keyName), true);
+
+ // import already present key
+ BOOST_CHECK_THROW(tpm.importKey(keyName, pkcs8->data(), pkcs8->size(), password.data(), password.size()),
+ BackEnd::Error);
+
+ // test derivePublicKey with the imported key
+ auto keyHdl = tpm.getKeyHandle(keyName);
+ auto pubKey = keyHdl->derivePublicKey();
+ BOOST_CHECK(pubKey != nullptr);
+
+ // export
+ auto exportedKey = tpm.exportKey(keyName, password.data(), password.size());
+ BOOST_CHECK_EQUAL(tpm.hasKey(keyName), true);
+
+ transform::PrivateKey sKey2;
+ sKey2.loadPkcs8(exportedKey->data(), exportedKey->size(), password.data(), password.size());
+ OBufferStream os2;
+ sKey.savePkcs1Base64(os2);
+ auto pkcs1 = os2.buf();
+
+ // verify that the exported key is identical to the key that was imported
+ BOOST_CHECK_EQUAL_COLLECTIONS(privKeyPkcs1.begin(), privKeyPkcs1.end(),
+ pkcs1->begin(), pkcs1->end());
+
+ // export nonexistent key
+ tpm.deleteKey(keyName);
+ BOOST_CHECK_EQUAL(tpm.hasKey(keyName), false);
+ BOOST_CHECK_THROW(tpm.exportKey(keyName, password.data(), password.size()), BackEnd::Error);
+}
+
+BOOST_AUTO_TEST_CASE(RandomKeyId)
+{
+ BackEndWrapperMem wrapper;
+ BackEnd& tpm = wrapper.getTpm();
+ Name identity("/Test/KeyName");
+
+ std::set<Name> keyNames;
+ for (int i = 0; i < 100; i++) {
+ auto key = tpm.createKey(identity, RsaKeyParams());
+ Name keyName = key->getKeyName();
+ BOOST_CHECK(keyNames.insert(keyName).second);
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestBackEnd
+BOOST_AUTO_TEST_SUITE_END() // Tpm
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace tpm
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/transform.t.cpp b/tests/unit/security/transform.t.cpp
new file mode 100644
index 0000000..1d55464
--- /dev/null
+++ b/tests/unit/security/transform.t.cpp
@@ -0,0 +1,86 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/transform.hpp"
+
+#include "boost-test.hpp"
+
+namespace ndn {
+namespace security {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(TestTransform)
+
+BOOST_AUTO_TEST_CASE(SymbolVisibility)
+{
+ transform::BufferSource* bufferSource = nullptr;
+ BOOST_CHECK(bufferSource == nullptr);
+
+ transform::StreamSource* streamSource = nullptr;
+ BOOST_CHECK(streamSource == nullptr);
+
+ transform::StepSource* stepSource = nullptr;
+ BOOST_CHECK(stepSource == nullptr);
+
+ transform::BoolSink* boolSink = nullptr;
+ BOOST_CHECK(boolSink == nullptr);
+
+ transform::StreamSink* streamSink = nullptr;
+ BOOST_CHECK(streamSink == nullptr);
+
+ transform::HexEncode* hexEncode = nullptr;
+ BOOST_CHECK(hexEncode == nullptr);
+
+ transform::StripSpace* stripSpace = nullptr;
+ BOOST_CHECK(stripSpace == nullptr);
+
+ transform::HexDecode* hexDecode = nullptr;
+ BOOST_CHECK(hexDecode == nullptr);
+
+ transform::Base64Encode* base64Encode = nullptr;
+ BOOST_CHECK(base64Encode == nullptr);
+
+ transform::Base64Decode* base64Decode = nullptr;
+ BOOST_CHECK(base64Decode == nullptr);
+
+ transform::DigestFilter* digestFilter = nullptr;
+ BOOST_CHECK(digestFilter == nullptr);
+
+ transform::HmacFilter* hmacFilter = nullptr;
+ BOOST_CHECK(hmacFilter == nullptr);
+
+ transform::BlockCipher* blockCipher = nullptr;
+ BOOST_CHECK(blockCipher == nullptr);
+
+ transform::SignerFilter* signerFilter = nullptr;
+ BOOST_CHECK(signerFilter == nullptr);
+
+ transform::VerifierFilter* verifierFilter = nullptr;
+ BOOST_CHECK(verifierFilter == nullptr);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestTransform
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/transform/base64-decode.t.cpp b/tests/unit/security/transform/base64-decode.t.cpp
new file mode 100644
index 0000000..ecaa17c
--- /dev/null
+++ b/tests/unit/security/transform/base64-decode.t.cpp
@@ -0,0 +1,181 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/transform/base64-decode.hpp"
+#include "security/transform/buffer-source.hpp"
+#include "security/transform/step-source.hpp"
+#include "security/transform/stream-sink.hpp"
+#include "encoding/buffer-stream.hpp"
+
+#include "boost-test.hpp"
+
+namespace ndn {
+namespace security {
+namespace transform {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(Transform)
+BOOST_AUTO_TEST_SUITE(TestBase64Decode)
+
+BOOST_AUTO_TEST_CASE(Basic)
+{
+ std::string in =
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n"
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n"
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8=\n";
+
+ uint8_t out[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+ };
+
+ OBufferStream os;
+ bufferSource(in) >> base64Decode() >> streamSink(os);
+
+ ConstBufferPtr buf1 = os.buf();
+ BOOST_CHECK_EQUAL_COLLECTIONS(out, out + sizeof(out), buf1->begin(), buf1->end());
+}
+
+BOOST_AUTO_TEST_CASE(NoNewLine)
+{
+ std::string in =
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P"
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P"
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8=";
+
+ uint8_t out[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+ };
+
+ OBufferStream os;
+ bufferSource(in) >> base64Decode(false) >> streamSink(os);
+
+ ConstBufferPtr buf1 = os.buf();
+ BOOST_CHECK_EQUAL_COLLECTIONS(out, out + sizeof(out), buf1->begin(), buf1->end());
+}
+
+BOOST_AUTO_TEST_CASE(StepByStep)
+{
+ std::string in =
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n"
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n"
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n"
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n"
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n"
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n"
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n"
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n";
+
+ uint8_t out[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+ };
+
+ const uint8_t* input = reinterpret_cast<const uint8_t*>(in.data());
+ OBufferStream os;
+ StepSource source;
+ source >> base64Decode() >> streamSink(os);
+ source.write(input, 65); // complete line with "\n"
+ source.write(input + 65, 64); // complete line without "\n"
+ source.write(input + 129, 1); // single "\n"
+ source.write(input + 130, 35); // front of a line
+ source.write(input + 165, 30); // end of a line with "\n"
+ source.write(input + 195, 25); // front of a line
+ source.write(input + 220, 20); // middle of a line
+ source.write(input + 240, 19); // end of a line without "\n"
+ source.write(input + 259, 101); // "\n" plus one and half line
+ source.write(input + 360, 65); // end of a line plus front of another line
+ source.write(input + 425, 95); // remaining
+ source.end();
+
+ ConstBufferPtr buf1 = os.buf();
+ BOOST_CHECK_EQUAL_COLLECTIONS(out, out + sizeof(out), buf1->begin(), buf1->end());
+}
+
+BOOST_AUTO_TEST_CASE(EmptyInput)
+{
+ OBufferStream os;
+ StepSource source;
+ source >> base64Decode() >> streamSink(os);
+ source.end();
+ BOOST_CHECK_EQUAL(os.buf()->size(), 0);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestBase64Decode
+BOOST_AUTO_TEST_SUITE_END() // Transform
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace transform
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/transform/base64-encode.t.cpp b/tests/unit/security/transform/base64-encode.t.cpp
new file mode 100644
index 0000000..d52ac0b
--- /dev/null
+++ b/tests/unit/security/transform/base64-encode.t.cpp
@@ -0,0 +1,178 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/transform/base64-encode.hpp"
+#include "security/transform/buffer-source.hpp"
+#include "security/transform/step-source.hpp"
+#include "security/transform/stream-sink.hpp"
+#include "encoding/buffer-stream.hpp"
+
+#include "boost-test.hpp"
+
+namespace ndn {
+namespace security {
+namespace transform {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(Transform)
+BOOST_AUTO_TEST_SUITE(TestBase64Encode)
+
+BOOST_AUTO_TEST_CASE(Basic)
+{
+ uint8_t in[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+ };
+
+ std::string out =
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n"
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n"
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8=\n";
+
+ OBufferStream os;
+ bufferSource(in, sizeof(in)) >> base64Encode() >> streamSink(os);
+
+ ConstBufferPtr buf1 = os.buf();
+ BOOST_CHECK_EQUAL_COLLECTIONS(out.begin(), out.end(), buf1->begin(), buf1->end());
+}
+
+BOOST_AUTO_TEST_CASE(NoNewLine)
+{
+ uint8_t in[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+ };
+
+ std::string out =
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P"
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P"
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8=";
+
+ OBufferStream os;
+ BufferSource(in, sizeof(in)) >> base64Encode(false) >> streamSink(os);
+
+ ConstBufferPtr buf1 = os.buf();
+ BOOST_CHECK_EQUAL_COLLECTIONS(out.begin(), out.end(), buf1->begin(), buf1->end());
+}
+
+BOOST_AUTO_TEST_CASE(StepByStep)
+{
+ uint8_t in[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+ };
+
+ std::string out =
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n"
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n"
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n"
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n"
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n"
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n"
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n"
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n";
+
+ OBufferStream os;
+ StepSource source;
+ source >> base64Encode() >> streamSink(os);
+ source.write(in, 64); // complete chunk
+ source.write(in + 64, 32); // first half of a chunk
+ source.write(in + 96, 32); // second half of a chunk
+ source.write(in + 128, 24); // front of a chunk
+ source.write(in + 152, 20); // middle of a chunk
+ source.write(in + 172, 20); // end of a chunk
+ source.write(in + 192, 63); // odd number of bytes
+ source.write(in + 255, 85); // one and half chunk
+ source.write(in + 340, 44); // remaining part
+ source.end();
+
+ ConstBufferPtr buf1 = os.buf();
+ BOOST_CHECK_EQUAL_COLLECTIONS(out.begin(), out.end(), buf1->begin(), buf1->end());
+}
+
+BOOST_AUTO_TEST_CASE(EmptyInput)
+{
+ OBufferStream os;
+ StepSource source;
+ source >> base64Encode() >> streamSink(os);
+ source.end();
+ BOOST_CHECK_EQUAL(os.buf()->size(), 0);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestBase64Encode
+BOOST_AUTO_TEST_SUITE_END() // Transform
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace transform
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/transform/block-cipher.t.cpp b/tests/unit/security/transform/block-cipher.t.cpp
new file mode 100644
index 0000000..379093d
--- /dev/null
+++ b/tests/unit/security/transform/block-cipher.t.cpp
@@ -0,0 +1,112 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/transform/block-cipher.hpp"
+
+#include "encoding/buffer-stream.hpp"
+#include "security/transform/buffer-source.hpp"
+#include "security/transform/stream-sink.hpp"
+
+#include "boost-test.hpp"
+
+namespace ndn {
+namespace security {
+namespace transform {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(Transform)
+BOOST_AUTO_TEST_SUITE(TestBlockCipher)
+
+BOOST_AUTO_TEST_CASE(AesCbc)
+{
+ const uint8_t key[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+ };
+ const uint8_t iv[] = {
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
+ };
+ const uint8_t plainText[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+ };
+ //
+ // You can use the following shell one-liner to calculate the ciphertext:
+ // echo ${plaintext} | xxd -p -r | openssl enc -aes-128-cbc -K ${key} -iv ${iv} | xxd -i
+ //
+ const uint8_t cipherText[] = {
+ 0x07, 0x4d, 0x32, 0x68, 0xc3, 0x40, 0x64, 0x43,
+ 0x1e, 0x66, 0x4c, 0x25, 0x66, 0x42, 0x0f, 0x59,
+ 0x0a, 0x51, 0x19, 0x07, 0x67, 0x5c, 0x0e, 0xfa,
+ 0xa6, 0x8c, 0xbb, 0xaf, 0xfd, 0xea, 0x47, 0xd4,
+ 0xc7, 0x2c, 0x12, 0x34, 0x79, 0xde, 0xec, 0xc8,
+ 0x75, 0x33, 0x8f, 0x6b, 0xd6, 0x55, 0xf3, 0xfa
+ };
+
+ // encrypt
+ OBufferStream os;
+ bufferSource(plainText, sizeof(plainText)) >>
+ blockCipher(BlockCipherAlgorithm::AES_CBC, CipherOperator::ENCRYPT,
+ key, sizeof(key), iv, sizeof(iv)) >> streamSink(os);
+
+ auto buf = os.buf();
+ BOOST_CHECK_EQUAL_COLLECTIONS(cipherText, cipherText + sizeof(cipherText),
+ buf->begin(), buf->end());
+
+ // decrypt
+ OBufferStream os2;
+ bufferSource(cipherText, sizeof(cipherText)) >>
+ blockCipher(BlockCipherAlgorithm::AES_CBC, CipherOperator::DECRYPT,
+ key, sizeof(key), iv, sizeof(iv)) >> streamSink(os2);
+
+ auto buf2 = os2.buf();
+ BOOST_CHECK_EQUAL_COLLECTIONS(plainText, plainText + sizeof(plainText),
+ buf2->begin(), buf2->end());
+
+ // invalid key length
+ const uint8_t badKey[] = {0x00, 0x01, 0x02, 0x03};
+ BOOST_CHECK_THROW(BlockCipher(BlockCipherAlgorithm::AES_CBC, CipherOperator::ENCRYPT,
+ badKey, sizeof(badKey), iv, sizeof(iv)), Error);
+
+ // wrong iv length
+ const uint8_t badIv[] = {0x00, 0x01, 0x02, 0x03};
+ BOOST_CHECK_THROW(BlockCipher(BlockCipherAlgorithm::AES_CBC, CipherOperator::ENCRYPT,
+ key, sizeof(key), badIv, sizeof(badIv)), Error);
+}
+
+BOOST_AUTO_TEST_CASE(InvalidAlgorithm)
+{
+ BOOST_CHECK_THROW(BlockCipher(BlockCipherAlgorithm::NONE, CipherOperator::ENCRYPT,
+ nullptr, 0, nullptr, 0), Error);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestBlockCipher
+BOOST_AUTO_TEST_SUITE_END() // Transform
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace transform
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/transform/bool-sink.t.cpp b/tests/unit/security/transform/bool-sink.t.cpp
new file mode 100644
index 0000000..2ce633f
--- /dev/null
+++ b/tests/unit/security/transform/bool-sink.t.cpp
@@ -0,0 +1,63 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/transform/bool-sink.hpp"
+
+#include "boost-test.hpp"
+
+namespace ndn {
+namespace security {
+namespace transform {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(Transform)
+BOOST_AUTO_TEST_SUITE(TestBoolSink)
+
+BOOST_AUTO_TEST_CASE(Basic)
+{
+ uint8_t in1[] = {0x00, 0x01};
+ bool value1 = true;
+ BoolSink sink1(value1);
+ BOOST_CHECK_EQUAL(sink1.write(in1, 1), 1);
+ BOOST_CHECK_EQUAL(sink1.write(in1 + 1, 1), 1);
+ sink1.end();
+ BOOST_CHECK_EQUAL(value1, false);
+ BOOST_CHECK_THROW(sink1.write(in1 + 1, 1), transform::Error);
+
+ uint8_t in2[] = {0x01, 0x00};
+ bool value2 = false;
+ BoolSink sink2(value2);
+ BOOST_CHECK_EQUAL(sink2.write(in2, 1), 1);
+ BOOST_CHECK_EQUAL(sink2.write(in2 + 1, 1), 1);
+ sink2.end();
+ BOOST_CHECK_EQUAL(value2, true);
+ BOOST_CHECK_THROW(sink2.write(in2 + 1, 1), transform::Error);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestBoolSink
+BOOST_AUTO_TEST_SUITE_END() // Transform
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace transform
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/transform/buffer-source.t.cpp b/tests/unit/security/transform/buffer-source.t.cpp
new file mode 100644
index 0000000..cb7e7f4
--- /dev/null
+++ b/tests/unit/security/transform/buffer-source.t.cpp
@@ -0,0 +1,89 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/transform/buffer-source.hpp"
+#include "security/transform/stream-sink.hpp"
+
+#include "boost-test.hpp"
+
+namespace ndn {
+namespace security {
+namespace transform {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(Transform)
+BOOST_AUTO_TEST_SUITE(TestBufferSource)
+
+BOOST_AUTO_TEST_CASE(Basic)
+{
+ uint8_t in[16] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+ };
+
+ std::ostringstream os1;
+ bufferSource(in, sizeof(in)) >> streamSink(os1);
+ std::string out1 = os1.str();
+ BOOST_CHECK_EQUAL_COLLECTIONS(in, in + sizeof(in), out1.begin(), out1.end());
+
+ std::string in2 =
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567";
+
+ std::ostringstream os2;
+ bufferSource(in2) >> streamSink(os2);
+ std::string out2 = os2.str();
+ BOOST_CHECK_EQUAL_COLLECTIONS(in2.begin(), in2.end(), out2.begin(), out2.end());
+
+ Buffer in3(in, sizeof(in));
+ std::ostringstream os3;
+ bufferSource(in3) >> streamSink(os3);
+ std::string out3 = os3.str();
+ BOOST_CHECK_EQUAL_COLLECTIONS(in3.begin(), in3.end(), out3.begin(), out3.end());
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestBufferSource
+BOOST_AUTO_TEST_SUITE_END() // Transform
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace transform
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/transform/digest-filter.t.cpp b/tests/unit/security/transform/digest-filter.t.cpp
new file mode 100644
index 0000000..5c0aaca
--- /dev/null
+++ b/tests/unit/security/transform/digest-filter.t.cpp
@@ -0,0 +1,222 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/transform/digest-filter.hpp"
+
+#include "encoding/buffer-stream.hpp"
+#include "security/detail/openssl.hpp"
+#include "security/transform/buffer-source.hpp"
+#include "security/transform/step-source.hpp"
+#include "security/transform/stream-sink.hpp"
+
+#include "boost-test.hpp"
+
+namespace ndn {
+namespace security {
+namespace transform {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(Transform)
+BOOST_AUTO_TEST_SUITE(TestDigestFilter)
+
+static const uint8_t in[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+};
+static const uint8_t out[] = {
+ 0x3e, 0x14, 0xfd, 0x66, 0x9a, 0x79, 0x80, 0x65,
+ 0xc4, 0x0d, 0x61, 0xf8, 0x6a, 0xc7, 0x98, 0x29,
+ 0xc0, 0x6b, 0x90, 0x8f, 0xbb, 0x19, 0xa0, 0x85,
+ 0xf7, 0xfa, 0x7b, 0x2d, 0xd6, 0x8c, 0xd5, 0xa3
+};
+
+BOOST_AUTO_TEST_CASE(BufferInput)
+{
+ OBufferStream os;
+ bufferSource(in, sizeof(in)) >> digestFilter(DigestAlgorithm::SHA256) >> streamSink(os);
+ BOOST_CHECK_EQUAL_COLLECTIONS(out, out + sizeof(out), os.buf()->begin(), os.buf()->end());
+}
+
+BOOST_AUTO_TEST_CASE(StepInput)
+{
+ StepSource source;
+ OBufferStream os;
+ source >> digestFilter(DigestAlgorithm::SHA256) >> streamSink(os);
+ source.write(in, 32);
+ source.write(in + 32, 1);
+ source.write(in + 33, 2);
+ source.write(in + 35, 3);
+ source.write(in + 38, 26);
+ source.write(in + 64, 64);
+ source.end();
+ BOOST_CHECK_EQUAL_COLLECTIONS(out, out + sizeof(out), os.buf()->begin(), os.buf()->end());
+}
+
+BOOST_AUTO_TEST_CASE(AlgorithmNone)
+{
+ BOOST_CHECK_THROW(DigestFilter{DigestAlgorithm::NONE}, Error);
+}
+
+BOOST_AUTO_TEST_CASE(AlgorithmSha224)
+{
+ const uint8_t out[] = {
+ 0xd1, 0x4a, 0x02, 0x8c, 0x2a, 0x3a, 0x2b, 0xc9, 0x47, 0x61, 0x02, 0xbb, 0x28, 0x82, 0x34, 0xc4,
+ 0x15, 0xa2, 0xb0, 0x1f, 0x82, 0x8e, 0xa6, 0x2a, 0xc5, 0xb3, 0xe4, 0x2f,
+ };
+ OBufferStream os;
+ bufferSource("") >> digestFilter(DigestAlgorithm::SHA224) >> streamSink(os);
+ BOOST_CHECK_EQUAL_COLLECTIONS(out, out + sizeof(out), os.buf()->begin(), os.buf()->end());
+}
+
+BOOST_AUTO_TEST_CASE(AlgorithmSha256)
+{
+ const uint8_t out[] = {
+ 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
+ 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55,
+ };
+ OBufferStream os;
+ bufferSource("") >> digestFilter(DigestAlgorithm::SHA256) >> streamSink(os);
+ BOOST_CHECK_EQUAL_COLLECTIONS(out, out + sizeof(out), os.buf()->begin(), os.buf()->end());
+}
+
+BOOST_AUTO_TEST_CASE(AlgorithmSha384)
+{
+ const uint8_t out[] = {
+ 0x38, 0xb0, 0x60, 0xa7, 0x51, 0xac, 0x96, 0x38, 0x4c, 0xd9, 0x32, 0x7e, 0xb1, 0xb1, 0xe3, 0x6a,
+ 0x21, 0xfd, 0xb7, 0x11, 0x14, 0xbe, 0x07, 0x43, 0x4c, 0x0c, 0xc7, 0xbf, 0x63, 0xf6, 0xe1, 0xda,
+ 0x27, 0x4e, 0xde, 0xbf, 0xe7, 0x6f, 0x65, 0xfb, 0xd5, 0x1a, 0xd2, 0xf1, 0x48, 0x98, 0xb9, 0x5b,
+ };
+ OBufferStream os;
+ bufferSource("") >> digestFilter(DigestAlgorithm::SHA384) >> streamSink(os);
+ BOOST_CHECK_EQUAL_COLLECTIONS(out, out + sizeof(out), os.buf()->begin(), os.buf()->end());
+}
+
+BOOST_AUTO_TEST_CASE(AlgorithmSha512)
+{
+ const uint8_t out[] = {
+ 0xcf, 0x83, 0xe1, 0x35, 0x7e, 0xef, 0xb8, 0xbd, 0xf1, 0x54, 0x28, 0x50, 0xd6, 0x6d, 0x80, 0x07,
+ 0xd6, 0x20, 0xe4, 0x05, 0x0b, 0x57, 0x15, 0xdc, 0x83, 0xf4, 0xa9, 0x21, 0xd3, 0x6c, 0xe9, 0xce,
+ 0x47, 0xd0, 0xd1, 0x3c, 0x5d, 0x85, 0xf2, 0xb0, 0xff, 0x83, 0x18, 0xd2, 0x87, 0x7e, 0xec, 0x2f,
+ 0x63, 0xb9, 0x31, 0xbd, 0x47, 0x41, 0x7a, 0x81, 0xa5, 0x38, 0x32, 0x7a, 0xf9, 0x27, 0xda, 0x3e,
+ };
+ OBufferStream os;
+ bufferSource("") >> digestFilter(DigestAlgorithm::SHA512) >> streamSink(os);
+ BOOST_CHECK_EQUAL_COLLECTIONS(out, out + sizeof(out), os.buf()->begin(), os.buf()->end());
+}
+
+#if OPENSSL_VERSION_NUMBER >= 0x1010000fL && !defined(OPENSSL_NO_BLAKE2)
+BOOST_AUTO_TEST_CASE(AlgorithmBlake2b_512)
+{
+ const uint8_t out[] = {
+ 0x78, 0x6a, 0x02, 0xf7, 0x42, 0x01, 0x59, 0x03, 0xc6, 0xc6, 0xfd, 0x85, 0x25, 0x52, 0xd2, 0x72,
+ 0x91, 0x2f, 0x47, 0x40, 0xe1, 0x58, 0x47, 0x61, 0x8a, 0x86, 0xe2, 0x17, 0xf7, 0x1f, 0x54, 0x19,
+ 0xd2, 0x5e, 0x10, 0x31, 0xaf, 0xee, 0x58, 0x53, 0x13, 0x89, 0x64, 0x44, 0x93, 0x4e, 0xb0, 0x4b,
+ 0x90, 0x3a, 0x68, 0x5b, 0x14, 0x48, 0xb7, 0x55, 0xd5, 0x6f, 0x70, 0x1a, 0xfe, 0x9b, 0xe2, 0xce,
+ };
+ OBufferStream os;
+ bufferSource("") >> digestFilter(DigestAlgorithm::BLAKE2B_512) >> streamSink(os);
+ BOOST_CHECK_EQUAL_COLLECTIONS(out, out + sizeof(out), os.buf()->begin(), os.buf()->end());
+}
+
+BOOST_AUTO_TEST_CASE(AlgorithmBlake2s_256)
+{
+ const uint8_t out[] = {
+ 0x69, 0x21, 0x7a, 0x30, 0x79, 0x90, 0x80, 0x94, 0xe1, 0x11, 0x21, 0xd0, 0x42, 0x35, 0x4a, 0x7c,
+ 0x1f, 0x55, 0xb6, 0x48, 0x2c, 0xa1, 0xa5, 0x1e, 0x1b, 0x25, 0x0d, 0xfd, 0x1e, 0xd0, 0xee, 0xf9,
+ };
+ OBufferStream os;
+ bufferSource("") >> digestFilter(DigestAlgorithm::BLAKE2S_256) >> streamSink(os);
+ BOOST_CHECK_EQUAL_COLLECTIONS(out, out + sizeof(out), os.buf()->begin(), os.buf()->end());
+}
+#endif // OPENSSL_VERSION_NUMBER >= 0x1010000fL && !defined(OPENSSL_NO_BLAKE2)
+
+#if OPENSSL_VERSION_NUMBER >= 0x10101001L
+BOOST_AUTO_TEST_CASE(AlgorithmSha3_224)
+{
+ const uint8_t out[] = {
+ 0x6b, 0x4e, 0x03, 0x42, 0x36, 0x67, 0xdb, 0xb7, 0x3b, 0x6e, 0x15, 0x45, 0x4f, 0x0e, 0xb1, 0xab,
+ 0xd4, 0x59, 0x7f, 0x9a, 0x1b, 0x07, 0x8e, 0x3f, 0x5b, 0x5a, 0x6b, 0xc7,
+ };
+ OBufferStream os;
+ bufferSource("") >> digestFilter(DigestAlgorithm::SHA3_224) >> streamSink(os);
+ BOOST_CHECK_EQUAL_COLLECTIONS(out, out + sizeof(out), os.buf()->begin(), os.buf()->end());
+}
+
+BOOST_AUTO_TEST_CASE(AlgorithmSha3_256)
+{
+ const uint8_t out[] = {
+ 0xa7, 0xff, 0xc6, 0xf8, 0xbf, 0x1e, 0xd7, 0x66, 0x51, 0xc1, 0x47, 0x56, 0xa0, 0x61, 0xd6, 0x62,
+ 0xf5, 0x80, 0xff, 0x4d, 0xe4, 0x3b, 0x49, 0xfa, 0x82, 0xd8, 0x0a, 0x4b, 0x80, 0xf8, 0x43, 0x4a,
+ };
+ OBufferStream os;
+ bufferSource("") >> digestFilter(DigestAlgorithm::SHA3_256) >> streamSink(os);
+ BOOST_CHECK_EQUAL_COLLECTIONS(out, out + sizeof(out), os.buf()->begin(), os.buf()->end());
+}
+
+BOOST_AUTO_TEST_CASE(AlgorithmSha3_384)
+{
+ const uint8_t out[] = {
+ 0x0c, 0x63, 0xa7, 0x5b, 0x84, 0x5e, 0x4f, 0x7d, 0x01, 0x10, 0x7d, 0x85, 0x2e, 0x4c, 0x24, 0x85,
+ 0xc5, 0x1a, 0x50, 0xaa, 0xaa, 0x94, 0xfc, 0x61, 0x99, 0x5e, 0x71, 0xbb, 0xee, 0x98, 0x3a, 0x2a,
+ 0xc3, 0x71, 0x38, 0x31, 0x26, 0x4a, 0xdb, 0x47, 0xfb, 0x6b, 0xd1, 0xe0, 0x58, 0xd5, 0xf0, 0x04,
+ };
+ OBufferStream os;
+ bufferSource("") >> digestFilter(DigestAlgorithm::SHA3_384) >> streamSink(os);
+ BOOST_CHECK_EQUAL_COLLECTIONS(out, out + sizeof(out), os.buf()->begin(), os.buf()->end());
+}
+
+BOOST_AUTO_TEST_CASE(AlgorithmSha3_512)
+{
+ const uint8_t out[] = {
+ 0xa6, 0x9f, 0x73, 0xcc, 0xa2, 0x3a, 0x9a, 0xc5, 0xc8, 0xb5, 0x67, 0xdc, 0x18, 0x5a, 0x75, 0x6e,
+ 0x97, 0xc9, 0x82, 0x16, 0x4f, 0xe2, 0x58, 0x59, 0xe0, 0xd1, 0xdc, 0xc1, 0x47, 0x5c, 0x80, 0xa6,
+ 0x15, 0xb2, 0x12, 0x3a, 0xf1, 0xf5, 0xf9, 0x4c, 0x11, 0xe3, 0xe9, 0x40, 0x2c, 0x3a, 0xc5, 0x58,
+ 0xf5, 0x00, 0x19, 0x9d, 0x95, 0xb6, 0xd3, 0xe3, 0x01, 0x75, 0x85, 0x86, 0x28, 0x1d, 0xcd, 0x26,
+ };
+ OBufferStream os;
+ bufferSource("") >> digestFilter(DigestAlgorithm::SHA3_512) >> streamSink(os);
+ BOOST_CHECK_EQUAL_COLLECTIONS(out, out + sizeof(out), os.buf()->begin(), os.buf()->end());
+}
+#endif // OPENSSL_VERSION_NUMBER >= 0x10101001L
+
+BOOST_AUTO_TEST_SUITE_END() // TestDigestFilter
+BOOST_AUTO_TEST_SUITE_END() // Transform
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace transform
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/transform/hex-decode.t.cpp b/tests/unit/security/transform/hex-decode.t.cpp
new file mode 100644
index 0000000..3c05ab4
--- /dev/null
+++ b/tests/unit/security/transform/hex-decode.t.cpp
@@ -0,0 +1,294 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/transform/hex-decode.hpp"
+#include "security/transform/buffer-source.hpp"
+#include "security/transform/step-source.hpp"
+#include "security/transform/stream-sink.hpp"
+#include "encoding/buffer-stream.hpp"
+
+#include "boost-test.hpp"
+
+namespace ndn {
+namespace security {
+namespace transform {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(Transform)
+BOOST_AUTO_TEST_SUITE(TestHexDecode)
+
+BOOST_AUTO_TEST_CASE(Basic)
+{
+ std::string in =
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f";
+
+ uint8_t out[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+ };
+
+ OBufferStream os;
+ bufferSource(in) >> hexDecode() >> streamSink(os);
+
+ ConstBufferPtr buf1 = os.buf();
+ BOOST_CHECK_EQUAL_COLLECTIONS(out, out + sizeof(out), buf1->begin(), buf1->end());
+}
+
+BOOST_AUTO_TEST_CASE(UpperCase)
+{
+ std::string in =
+ "000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F"
+ "000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F"
+ "000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F"
+ "000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F";
+
+ uint8_t out[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+ };
+
+ OBufferStream os;
+ bufferSource(in) >> hexDecode() >> streamSink(os);
+
+ ConstBufferPtr buf1 = os.buf();
+ BOOST_CHECK_EQUAL_COLLECTIONS(out, out + sizeof(out), buf1->begin(), buf1->end());
+}
+
+BOOST_AUTO_TEST_CASE(MixCase)
+{
+ std::string in =
+ "000102030405060708090a0b0c0d0e0f"
+ "101112131415161718191a1b1c1d1e1f"
+ "202122232425262728292a2b2c2d2e2f"
+ "303132333435363738393a3b3c3d3e3f"
+ "404142434445464748494a4b4c4d4e4f"
+ "505152535455565758595a5b5c5d5e5f"
+ "606162636465666768696a6b6c6d6e6f"
+ "707172737475767778797a7b7c7d7e7f"
+ "808182838485868788898a8b8c8d8e8f"
+ "909192939495969798999a9b9c9d9e9f"
+ "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"
+ "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
+ "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
+ "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
+ "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
+ "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"
+ "000102030405060708090A0B0C0D0E0F"
+ "101112131415161718191A1B1C1D1E1F"
+ "202122232425262728292A2B2C2D2E2F"
+ "303132333435363738393A3B3C3D3E3F"
+ "404142434445464748494A4B4C4D4E4F"
+ "505152535455565758595A5B5C5D5E5F"
+ "606162636465666768696A6B6C6D6E6F"
+ "707172737475767778797A7B7C7D7E7F"
+ "808182838485868788898A8B8C8D8E8F"
+ "909192939495969798999A9B9C9D9E9F"
+ "A0A1A2A3A4A5A6A7A8A9AAABACADAEAF"
+ "B0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF"
+ "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF"
+ "D0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF"
+ "E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF"
+ "F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF"
+ "aaabacadaeafaAaBaCaD"
+ "babbbcbdbebfbAbBbCbD"
+ "cacbcccdcecfcAcBcCcD"
+ "dadbdcdddedfdAdBdCdD"
+ "eaebecedeeefeAeBeCeD"
+ "fafbfcfdfefffAfBfCfD"
+ "AaAbAcAdAeAfAAABACAD"
+ "BaBbBcBdBeBfBABBBCBD"
+ "CaCbCcCdCeCfCACBCCCD"
+ "DaDbDcDdDeDfDADBDCDD";
+
+ uint8_t out[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
+ 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
+ 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
+ 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
+ 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
+ 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
+ 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
+ 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
+ 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
+ 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
+ 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
+ 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
+ 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
+ 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xAA, 0xAB, 0xAC, 0xAD,
+ 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xBA, 0xBB, 0xBC, 0xBD,
+ 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xCA, 0xCB, 0xCC, 0xCD,
+ 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xDA, 0xDB, 0xDC, 0xDD,
+ 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xEA, 0xEB, 0xEC, 0xED,
+ 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, 0xFA, 0xFB, 0xFC, 0xFD,
+ 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xAA, 0xAB, 0xAC, 0xAD,
+ 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xBA, 0xBB, 0xBC, 0xBD,
+ 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xCA, 0xCB, 0xCC, 0xCD,
+ 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xDA, 0xDB, 0xDC, 0xDD
+ };
+
+ OBufferStream os;
+ bufferSource(in) >> hexDecode() >> streamSink(os);
+
+ ConstBufferPtr buf1 = os.buf();
+ BOOST_CHECK_EQUAL_COLLECTIONS(out, out + sizeof(out), buf1->begin(), buf1->end());
+}
+
+
+BOOST_AUTO_TEST_CASE(StepByStep)
+{
+ std::string in =
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f";
+
+ uint8_t out[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+ };
+
+ const uint8_t* input = reinterpret_cast<const uint8_t*>(in.data());
+ OBufferStream os;
+ StepSource source;
+ source >> hexDecode() >> streamSink(os);
+ source.write(input, 128); // complete chunk
+ source.write(input + 128, 64); // first half of a chunk
+ source.write(input + 192, 64); // second half of a chunk
+ source.write(input + 256, 127); // odd number of byets
+ source.write(input + 383, 192); // one and half chunk
+ source.write(input + 575, 193); // remaining part
+ source.end();
+
+ ConstBufferPtr buf1 = os.buf();
+ BOOST_CHECK_EQUAL_COLLECTIONS(out, out + sizeof(out), buf1->begin(), buf1->end());
+}
+
+BOOST_AUTO_TEST_CASE(OddByte)
+{
+ std::string in1 = "0001020304050";
+
+ OBufferStream os1;
+ BOOST_REQUIRE_THROW(bufferSource(in1) >> hexDecode() >> streamSink(os1), transform::Error);
+
+ std::string in2 = "0001020304xy";
+
+ OBufferStream os2;
+ BOOST_REQUIRE_THROW(bufferSource(in2) >> hexDecode() >> streamSink(os2), transform::Error);
+}
+
+BOOST_AUTO_TEST_CASE(EmptyInput)
+{
+ OBufferStream os;
+ StepSource source;
+ source >> hexDecode() >> streamSink(os);
+ source.end();
+ BOOST_CHECK_EQUAL(os.buf()->size(), 0);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestHexDecode
+BOOST_AUTO_TEST_SUITE_END() // Transform
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace transform
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/transform/hex-encode.t.cpp b/tests/unit/security/transform/hex-encode.t.cpp
new file mode 100644
index 0000000..26f6321
--- /dev/null
+++ b/tests/unit/security/transform/hex-encode.t.cpp
@@ -0,0 +1,184 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/transform/hex-encode.hpp"
+#include "security/transform/buffer-source.hpp"
+#include "security/transform/step-source.hpp"
+#include "security/transform/stream-sink.hpp"
+#include "encoding/buffer-stream.hpp"
+
+#include "boost-test.hpp"
+
+namespace ndn {
+namespace security {
+namespace transform {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(Transform)
+BOOST_AUTO_TEST_SUITE(TestHexEncode)
+
+BOOST_AUTO_TEST_CASE(Basic)
+{
+ uint8_t in[128] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+ };
+
+ std::string out =
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f";
+
+ OBufferStream os;
+ bufferSource(in, sizeof(in)) >> hexEncode() >> streamSink(os);
+
+ ConstBufferPtr buf1 = os.buf();
+ BOOST_CHECK_EQUAL_COLLECTIONS(out.begin(), out.end(), buf1->begin(), buf1->end());
+}
+
+BOOST_AUTO_TEST_CASE(UpperCase)
+{
+ uint8_t in[128] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+ };
+
+ std::string out =
+ "000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F"
+ "000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F"
+ "000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F"
+ "000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F";
+
+ OBufferStream os;
+ bufferSource(in, sizeof(in)) >> hexEncode(true) >> streamSink(os);
+
+ ConstBufferPtr buf1 = os.buf();
+ BOOST_CHECK_EQUAL_COLLECTIONS(out.begin(), out.end(), buf1->begin(), buf1->end());
+}
+
+BOOST_AUTO_TEST_CASE(StepByStep)
+{
+ uint8_t in[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+ };
+
+ std::string out =
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f";
+
+ OBufferStream os;
+ StepSource source;
+ source >> hexEncode() >> streamSink(os);
+ source.write(in, 64); // complete chunk
+ source.write(in + 64, 32); // first half of a chunk
+ source.write(in + 96, 32); // second half of a chunk
+ source.write(in + 128, 20); // front of a chunk
+ source.write(in + 148, 20); // middle of a chunk
+ source.write(in + 168, 24); // end of a chunk
+ source.write(in + 192, 63); // odd number of bytes
+ source.write(in + 255, 85); // one and half chunk
+ source.write(in + 340, 44); // remaining part
+ source.end();
+
+ ConstBufferPtr buf1 = os.buf();
+ BOOST_CHECK_EQUAL_COLLECTIONS(out.begin(), out.end(), buf1->begin(), buf1->end());
+}
+
+BOOST_AUTO_TEST_CASE(EmptyInput)
+{
+ OBufferStream os;
+ StepSource source;
+ source >> hexEncode() >> streamSink(os);
+ source.end();
+ BOOST_CHECK_EQUAL(os.buf()->size(), 0);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestHexEncode
+BOOST_AUTO_TEST_SUITE_END() // Transform
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace transform
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/transform/hmac-filter.t.cpp b/tests/unit/security/transform/hmac-filter.t.cpp
new file mode 100644
index 0000000..1ed5e25
--- /dev/null
+++ b/tests/unit/security/transform/hmac-filter.t.cpp
@@ -0,0 +1,111 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/transform/hmac-filter.hpp"
+
+#include "encoding/buffer-stream.hpp"
+#include "security/transform/buffer-source.hpp"
+#include "security/transform/step-source.hpp"
+#include "security/transform/stream-sink.hpp"
+
+#include "boost-test.hpp"
+
+namespace ndn {
+namespace security {
+namespace transform {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(Transform)
+BOOST_AUTO_TEST_SUITE(TestHmacFilter)
+
+static const uint8_t key[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+};
+static const uint8_t data[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+};
+static const uint8_t digest[] = {
+ 0x9f, 0x3a, 0xa2, 0x88, 0x26, 0xb3, 0x74, 0x85,
+ 0xca, 0x05, 0x01, 0x4d, 0x71, 0x42, 0xb3, 0xea,
+ 0x3f, 0xfb, 0xda, 0x5a, 0x35, 0xbf, 0xd2, 0x0f,
+ 0x2f, 0x9c, 0x8f, 0xcc, 0x6d, 0x30, 0x48, 0x54
+};
+
+BOOST_AUTO_TEST_CASE(Basic)
+{
+ OBufferStream os;
+ bufferSource(data, sizeof(data)) >> hmacFilter(DigestAlgorithm::SHA256, key, sizeof(key)) >> streamSink(os);
+
+ ConstBufferPtr buf = os.buf();
+ BOOST_CHECK_EQUAL_COLLECTIONS(digest, digest + sizeof(digest), buf->begin(), buf->end());
+}
+
+BOOST_AUTO_TEST_CASE(StepByStep)
+{
+ OBufferStream os;
+ StepSource source;
+ source >> hmacFilter(DigestAlgorithm::SHA256, key, sizeof(key)) >> streamSink(os);
+ source.write(data, 1);
+ source.write(data + 1, 2);
+ source.write(data + 3, 3);
+ source.write(data + 6, 4);
+ source.write(data + 10, 5);
+ source.write(data + 15, 1);
+ source.end();
+
+ ConstBufferPtr buf = os.buf();
+ BOOST_CHECK_EQUAL_COLLECTIONS(digest, digest + sizeof(digest), buf->begin(), buf->end());
+}
+
+BOOST_AUTO_TEST_CASE(EmptyInput)
+{
+ const uint8_t digest[] = {
+ 0x07, 0xEF, 0xF8, 0xB3, 0x26, 0xB7, 0x79, 0x8C,
+ 0x9C, 0xCF, 0xCB, 0xDB, 0xE5, 0x79, 0x48, 0x9A,
+ 0xC7, 0x85, 0xA7, 0x99, 0x5A, 0x04, 0x61, 0x8B,
+ 0x1A, 0x28, 0x13, 0xC2, 0x67, 0x44, 0x77, 0x7D
+ };
+
+ OBufferStream os;
+ StepSource source;
+ source >> hmacFilter(DigestAlgorithm::SHA256, key, sizeof(key)) >> streamSink(os);
+ source.end();
+
+ ConstBufferPtr buf = os.buf();
+ BOOST_CHECK_EQUAL_COLLECTIONS(digest, digest + sizeof(digest), buf->begin(), buf->end());
+}
+
+BOOST_AUTO_TEST_CASE(InvalidAlgorithm)
+{
+ BOOST_CHECK_THROW(HmacFilter(DigestAlgorithm::NONE, key, sizeof(key)), Error);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestHmacFilter
+BOOST_AUTO_TEST_SUITE_END() // Transform
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace transform
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/transform/private-key.t.cpp b/tests/unit/security/transform/private-key.t.cpp
new file mode 100644
index 0000000..ee956f9
--- /dev/null
+++ b/tests/unit/security/transform/private-key.t.cpp
@@ -0,0 +1,401 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/transform/private-key.hpp"
+
+#include "encoding/buffer-stream.hpp"
+#include "security/key-params.hpp"
+#include "security/transform.hpp"
+
+#include "boost-test.hpp"
+#include <boost/mpl/vector.hpp>
+
+#include <sstream>
+
+namespace ndn {
+namespace security {
+namespace transform {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(Transform)
+BOOST_AUTO_TEST_SUITE(TestPrivateKey)
+
+struct RsaKeyTestData
+{
+ const std::string privateKeyPkcs1 =
+ "MIIEpAIBAAKCAQEAw0WM1/WhAxyLtEqsiAJgWDZWuzkYpeYVdeeZcqRZzzfRgBQT\n"
+ "sNozS5t4HnwTZhwwXbH7k3QN0kRTV826Xobws3iigohnM9yTK+KKiayPhIAm/+5H\n"
+ "GT6SgFJhYhqo1/upWdueojil6RP4/AgavHhopxlAVbk6G9VdVnlQcQ5Zv0OcGi73\n"
+ "c+EnYD/YgURYGSngUi/Ynsh779p2U69/te9gZwIL5PuE9BiO6I39cL9z7EK1SfZh\n"
+ "OWvDe/qH7YhD/BHwcWit8FjRww1glwRVTJsA9rH58ynaAix0tcR/nBMRLUX+e3rU\n"
+ "RHg6UbSjJbdb9qmKM1fTGHKUzL/5pMG6uBU0ywIDAQABAoIBADQkckOIl4IZMUTn\n"
+ "W8LFv6xOdkJwMKC8G6bsPRFbyY+HvC2TLt7epSvfS+f4AcYWaOPcDu2E49vt2sNr\n"
+ "cASly8hgwiRRAB3dHH9vcsboiTo8bi2RFvMqvjv9w3tK2yMxVDtmZamzrrnaV3YV\n"
+ "Q+5nyKo2F/PMDjQ4eUAKDOzjhBuKHsZBTFnA1MFNI+UKj5X4Yp64DFmKlxTX/U2b\n"
+ "wzVywo5hzx2Uhw51jmoLls4YUvMJXD0wW5ZtYRuPogXvXb/of9ef/20/wU11WFKg\n"
+ "Xb4gfR8zUXaXS1sXcnVm3+24vIs9dApUwykuoyjOqxWqcHRec2QT2FxVGkFEraze\n"
+ "CPa4rMECgYEA5Y8CywomIcTgerFGFCeMHJr8nQGqY2V/owFb3k9maczPnC9p4a9R\n"
+ "c5szLxA9FMYFxurQZMBWSEG2JS1HR2mnjigx8UKjYML/A+rvvjZOMe4M6Sy2ggh4\n"
+ "SkLZKpWTzjTe07ByM/j5v/SjNZhWAG7sw4/LmPGRQkwJv+KZhGojuOkCgYEA2cOF\n"
+ "T6cJRv6kvzTz9S0COZOVm+euJh/BXp7oAsAmbNfOpckPMzqHXy8/wpdKl6AAcB57\n"
+ "OuztlNfV1D7qvbz7JuRlYwQ0cEfBgbZPcz1p18HHDXhwn57ZPb8G33Yh9Omg0HNA\n"
+ "Imb4LsVuSqxA6NwSj7cpRekgTedrhLFPJ+Ydb5MCgYEAsM3Q7OjILcIg0t6uht9e\n"
+ "vrlwTsz1mtCV2co2I6crzdj9HeI2vqf1KAElDt6G7PUHhglcr/yjd8uEqmWRPKNX\n"
+ "ddnnfVZB10jYeP/93pac6z/Zmc3iU4yKeUe7U10ZFf0KkiiYDQd59CpLef/2XScS\n"
+ "HB0oRofnxRQjfjLc4muNT+ECgYEAlcDk06MOOTly+F8lCc1bA1dgAmgwFd2usDBd\n"
+ "Y07a3e0HGnGLN3Kfl7C5i0tZq64HvxLnMd2vgLVxQlXGPpdQrC1TH+XLXg+qnlZO\n"
+ "ivSH7i0/gx75bHvj75eH1XK65V8pDVDEoSPottllAIs21CxLw3N1ObOZWJm2EfmR\n"
+ "cuHICmsCgYAtFJ1idqMoHxES3mlRpf2JxyQudP3SCm2WpGmqVzhRYInqeatY5sUd\n"
+ "lPLHm/p77RT7EyxQHTlwn8FJPuM/4ZH1rQd/vB+Y8qAtYJCexDMsbvLW+Js+VOvk\n"
+ "jweEC0nrcL31j9mF0vz5E6tfRu4hhJ6L4yfWs0gSejskeVB/w8QY4g==\n";
+ const std::string privateKeyPkcs8 =
+ "MIIFCzA9BgkqhkiG9w0BBQ0wMDAbBgkqhkiG9w0BBQwwDgQIOKYJXvB6p8kCAggA\n"
+ "MBEGBSsOAwIHBAiQgMK8kQXTyASCBMjeNiKYYw5/yHgs9BfSGrpqvV0LkkgMQNUW\n"
+ "R4ZY8fuNjZynd+PxDuw2pyrv1Yv3jc+tupwUehZEzYOnGd53wQAuLO+Z0TBgRFN7\n"
+ "Lhk+AxlT7hu0xaB3ZpJ/uvWpgEJHsq/aB/GYgyzXcQo2AiqzERVpMCWJVmE1L977\n"
+ "CHwJmLm5mxclVLYp1UK5lkIBFu/M4nPavmNmYNUU1LOrXRo56TlJ2kUp8gQyQI1P\n"
+ "VPxi4chmlsr/OnQ2d1eZN+euFm0CS+yP+LFgI9ZqdyH1w+J43SXdHDzauVcZp7oa\n"
+ "Kw24OrhHfolLAnQIECXEJYeT7tZmhC4O9V6B18PFVyxWnEU4eFNpFE8kYSmm8Um2\n"
+ "buvDKI71q43hm23moYT9uIM1f4M8UkoOliJGrlf4xgEcmDuokEX01PdOq1gc4nvG\n"
+ "0DCwDI9cOsyn8cxhk9UVtFgzuG/seuznxIv1F5H0hzYOyloStXxRisJES0kgByBt\n"
+ "FFTfyoFKRrmCjRIygwVKUSkSDR0DlQS5ZLvQyIswnSQFwxAHqfvoSL4dB9UAIAQ+\n"
+ "ALVF1maaHgptbL6Ifqf0GFCv0hdNCVNDNCdy8R+S6nEYE+YdYSIdT1L88KD5PjU3\n"
+ "YY/CMnxhTncMaT4acPO1UUYuSGRZ/JL6E0ihoqIU+bqUgLSHNzhPySPfN9uqN61Y\n"
+ "HFBtxeEPWKU0f/JPkRBMmZdMI1/OVmA3QHSRBydI+CQN8no2gZRFoVbHTkG8IMpE\n"
+ "1fiDJpwFkpzIv/JPiTSE7DeBH5NJk1bgu7TcuZfa4unyAqss0UuLnXzS06TppkUj\n"
+ "QGft0g8VPW56eli6B4xrSzzuvAdbrxsVfxdmtHPyYxLb3/UG1g4x/H/yULhx7x9P\n"
+ "iI6cw6JUE+8bwJV2ZIlHXXHO+wUp/gCFJ6MHo9wkR1QvnHP2ClJAzBm9OvYnUx2Y\n"
+ "SX0HxEowW8BkhxOF184LEmxeua0yyZUqCdrYmErp7x9EY/LhD1zBwH8OGRa0qzmR\n"
+ "VKxAPKihkb9OgxcUKbvKePx3k2cQ7fbCUspGPm4Kn1zwMgRAZ4fz/o8Lnwc8MSY3\n"
+ "lPWnmLTFu420SRH2g9N0o/r195hiZ5cc+KfF4pwZWKbEbKFk/UfXA9vmOi7BBtDJ\n"
+ "RWshOINhzMU6Ij3KuaEpHni1HoHjw0SQ97ow2x/aB8k2QC28tbsa49lD2KKJku6b\n"
+ "2Or89adwFKqMgS2IXfXMXs/iG5EFLYN6r8e40Dn5f1vJfRLJl03XByIfT2n92pw3\n"
+ "fP7muOIKLUsEKjOrmn94NwMlfeW13oQHEH2KjPOWFS/tyJHDdVU+of4COH5yg59a\n"
+ "TZqFkOTGeliE1O+6sfF9fRuVxFUF3D8Hpr0JIjdc6+3RgIlGsXc8BwiSjDSI2XW+\n"
+ "vo75/2zPU9t8OeXEIJk2CQGyqLwUJ6dyi/yDRrvZAgjrUvbpcxydnBAHrLbLUGXJ\n"
+ "aEHH2tjEtnTqVyTchr1yHoupcFOCkA0dAA66XqwcssQxJiMGrWTpCbgd9mrTXQaZ\n"
+ "U7afFN1jpO78tgBQUUpImXdHLLsqdN5tefqjileZGZ9x3/C6TNAfDwYJdsicNNn5\n"
+ "y+JVsbltfLWlJxb9teb3dtQiFlJ7ofprLJnJVqI/Js8lozY+KaxV2vtbZkcD4dM=\n";
+ const std::string publicKeyPkcs8 =
+ "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw0WM1/WhAxyLtEqsiAJg\n"
+ "WDZWuzkYpeYVdeeZcqRZzzfRgBQTsNozS5t4HnwTZhwwXbH7k3QN0kRTV826Xobw\n"
+ "s3iigohnM9yTK+KKiayPhIAm/+5HGT6SgFJhYhqo1/upWdueojil6RP4/AgavHho\n"
+ "pxlAVbk6G9VdVnlQcQ5Zv0OcGi73c+EnYD/YgURYGSngUi/Ynsh779p2U69/te9g\n"
+ "ZwIL5PuE9BiO6I39cL9z7EK1SfZhOWvDe/qH7YhD/BHwcWit8FjRww1glwRVTJsA\n"
+ "9rH58ynaAix0tcR/nBMRLUX+e3rURHg6UbSjJbdb9qmKM1fTGHKUzL/5pMG6uBU0\n"
+ "ywIDAQAB\n";
+};
+
+struct EcKeyTestData
+{
+ const std::string privateKeyPkcs1 =
+ "MIIBaAIBAQQgRxwcbzK9RV6AHYFsDcykI86o3M/a1KlJn0z8PcLMBZOggfowgfcC\n"
+ "AQEwLAYHKoZIzj0BAQIhAP////8AAAABAAAAAAAAAAAAAAAA////////////////\n"
+ "MFsEIP////8AAAABAAAAAAAAAAAAAAAA///////////////8BCBaxjXYqjqT57Pr\n"
+ "vVV2mIa8ZR0GsMxTsPY7zjw+J9JgSwMVAMSdNgiG5wSTamZ44ROdJreBn36QBEEE\n"
+ "axfR8uEsQkf4vOblY6RA8ncDfYEt6zOg9KE5RdiYwpZP40Li/hp/m47n60p8D54W\n"
+ "K84zV2sxXs7LtkBoN79R9QIhAP////8AAAAA//////////+85vqtpxeehPO5ysL8\n"
+ "YyVRAgEBoUQDQgAEaG4WJuDAt0QkEM4t29KDUdzkQlMPGrqWzkWhgt9OGnwc6O7A\n"
+ "ZLPSrDyhwyrKS7XLRXml5DisQ93RvByll32y8A==\n";
+ const std::string privateKeyPkcs8 =
+ "MIIBwzA9BgkqhkiG9w0BBQ0wMDAbBgkqhkiG9w0BBQwwDgQIVHkBzLGtDvICAggA\n"
+ "MBEGBSsOAwIHBAhk6g9eI3toNwSCAYDd+LWPDBTrKV7vUyxTvDbpUd0eXfh73DKA\n"
+ "MHkdHuVmhpmpBbsF9XvaFuL8J/1xi1Yl2XGw8j3WyrprD2YEhl/+zKjNbdTDJmNO\n"
+ "SlomuwWb5AVCJ9reT94zIXKCnexUcyBFS7ep+P4dwuef0VjzprjfmnAZHrP+u594\n"
+ "ELHpKwi0ZpQLtcJjjud13bn43vbXb+aU7jmPV5lU2XP8TxaQJiYIibNEh1Y3TZGr\n"
+ "akJormYvhaYbiZkKLHQ9AvQMEjhoIW5WCB3q+tKZUKTzcQpjNnf9FOTeKN3jk3Kd\n"
+ "2OmibPZcbMJdgCD/nRVn1cBo7Hjn3IMjgtszQHtEUphOQiAkOJUnKmy9MTYqtcNN\n"
+ "6cuFItbu4QvbVwailgdUjOYwIJCmIxExlPV0ohS24pFGsO03Yn7W8rBB9VWENYmG\n"
+ "HkZIbGsHv7O9Wy7fv+FJgZkjeti0807IsNXSJl8LUK0ZIhAR7OU8uONWMsbHdQnk\n"
+ "q1HB1ZKa52ugACl7g/DF9b7CoSAjFeE=\n";
+ const std::string publicKeyPkcs8 =
+ "MIIBSzCCAQMGByqGSM49AgEwgfcCAQEwLAYHKoZIzj0BAQIhAP////8AAAABAAAA\n"
+ "AAAAAAAAAAAA////////////////MFsEIP////8AAAABAAAAAAAAAAAAAAAA////\n"
+ "///////////8BCBaxjXYqjqT57PrvVV2mIa8ZR0GsMxTsPY7zjw+J9JgSwMVAMSd\n"
+ "NgiG5wSTamZ44ROdJreBn36QBEEEaxfR8uEsQkf4vOblY6RA8ncDfYEt6zOg9KE5\n"
+ "RdiYwpZP40Li/hp/m47n60p8D54WK84zV2sxXs7LtkBoN79R9QIhAP////8AAAAA\n"
+ "//////////+85vqtpxeehPO5ysL8YyVRAgEBA0IABGhuFibgwLdEJBDOLdvSg1Hc\n"
+ "5EJTDxq6ls5FoYLfThp8HOjuwGSz0qw8ocMqyku1y0V5peQ4rEPd0bwcpZd9svA=\n";
+};
+
+using KeyTestDataSets = boost::mpl::vector<RsaKeyTestData, EcKeyTestData>;
+
+static void
+checkPkcs8Encoding(ConstBufferPtr encoding, const std::string& password, ConstBufferPtr pkcs1)
+{
+ PrivateKey sKey;
+ sKey.loadPkcs8(encoding->data(), encoding->size(), password.c_str(), password.size());
+ OBufferStream os;
+ sKey.savePkcs1(os);
+ BOOST_CHECK_EQUAL_COLLECTIONS(pkcs1->begin(), pkcs1->end(),
+ os.buf()->begin(), os.buf()->end());
+}
+
+static void
+checkPkcs8Base64Encoding(ConstBufferPtr encoding, const std::string& password, ConstBufferPtr pkcs1)
+{
+ OBufferStream os;
+ bufferSource(*encoding) >> base64Decode() >> streamSink(os);
+ checkPkcs8Encoding(os.buf(), password, pkcs1);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(SaveLoad, T, KeyTestDataSets)
+{
+ T dataSet;
+
+ const uint8_t* sKeyPkcs1Base64 = reinterpret_cast<const uint8_t*>(dataSet.privateKeyPkcs1.c_str());
+ size_t sKeyPkcs1Base64Len = dataSet.privateKeyPkcs1.size();
+ OBufferStream os;
+ bufferSource(sKeyPkcs1Base64, sKeyPkcs1Base64Len) >> base64Decode() >> streamSink(os);
+ ConstBufferPtr sKeyPkcs1Buf = os.buf();
+ const uint8_t* sKeyPkcs1 = sKeyPkcs1Buf->data();
+ size_t sKeyPkcs1Len = sKeyPkcs1Buf->size();
+
+ // load key in base64-encoded pkcs1 format
+ PrivateKey sKey;
+ BOOST_CHECK_NO_THROW(sKey.loadPkcs1Base64(sKeyPkcs1Base64, sKeyPkcs1Base64Len));
+
+ std::stringstream ss2(dataSet.privateKeyPkcs1);
+ PrivateKey sKey2;
+ BOOST_CHECK_NO_THROW(sKey2.loadPkcs1Base64(ss2));
+
+ // load key in pkcs1 format
+ PrivateKey sKey3;
+ BOOST_CHECK_NO_THROW(sKey3.loadPkcs1(sKeyPkcs1, sKeyPkcs1Len));
+
+ std::stringstream ss4;
+ ss4.write(reinterpret_cast<const char*>(sKeyPkcs1), sKeyPkcs1Len);
+ PrivateKey sKey4;
+ BOOST_CHECK_NO_THROW(sKey4.loadPkcs1(ss4));
+
+ // save key in base64-encoded pkcs1 format
+ OBufferStream os2;
+ BOOST_REQUIRE_NO_THROW(sKey.savePkcs1Base64(os2));
+ BOOST_CHECK_EQUAL_COLLECTIONS(sKeyPkcs1Base64, sKeyPkcs1Base64 + sKeyPkcs1Base64Len,
+ os2.buf()->begin(), os2.buf()->end());
+
+ // save key in pkcs1 format
+ OBufferStream os3;
+ BOOST_REQUIRE_NO_THROW(sKey.savePkcs1(os3));
+ BOOST_CHECK_EQUAL_COLLECTIONS(sKeyPkcs1, sKeyPkcs1 + sKeyPkcs1Len,
+ os3.buf()->begin(), os3.buf()->end());
+
+ const uint8_t* sKeyPkcs8Base64 = reinterpret_cast<const uint8_t*>(dataSet.privateKeyPkcs8.c_str());
+ size_t sKeyPkcs8Base64Len = dataSet.privateKeyPkcs8.size();
+ OBufferStream os4;
+ bufferSource(sKeyPkcs8Base64, sKeyPkcs8Base64Len) >> base64Decode() >> streamSink(os4);
+ const uint8_t* sKeyPkcs8 = os4.buf()->data();
+ size_t sKeyPkcs8Len = os4.buf()->size();
+
+ std::string password("password");
+ std::string wrongpw("wrongpw");
+ auto pwCallback = [&password] (char* buf, size_t size, int) -> int {
+ BOOST_REQUIRE_LE(password.size(), size);
+ std::copy(password.begin(), password.end(), buf);
+ return static_cast<int>(password.size());
+ };
+
+ // load key in base64-encoded pkcs8 format
+ PrivateKey sKey5;
+ BOOST_CHECK_NO_THROW(sKey5.loadPkcs8Base64(sKeyPkcs8Base64, sKeyPkcs8Base64Len,
+ password.c_str(), password.size()));
+
+ PrivateKey sKey6;
+ BOOST_CHECK_NO_THROW(sKey6.loadPkcs8Base64(sKeyPkcs8Base64, sKeyPkcs8Base64Len, pwCallback));
+
+ std::stringstream ss7(dataSet.privateKeyPkcs8);
+ PrivateKey sKey7;
+ BOOST_CHECK_NO_THROW(sKey7.loadPkcs8Base64(ss7, password.c_str(), password.size()));
+
+ std::stringstream ss8(dataSet.privateKeyPkcs8);
+ PrivateKey sKey8;
+ BOOST_CHECK_NO_THROW(sKey8.loadPkcs8Base64(ss8, pwCallback));
+
+ // load key in pkcs8 format
+ PrivateKey sKey9;
+ BOOST_CHECK_NO_THROW(sKey9.loadPkcs8(sKeyPkcs8, sKeyPkcs8Len, password.c_str(), password.size()));
+
+ PrivateKey sKey10;
+ BOOST_CHECK_NO_THROW(sKey10.loadPkcs8(sKeyPkcs8, sKeyPkcs8Len, pwCallback));
+
+ std::stringstream ss11;
+ ss11.write(reinterpret_cast<const char*>(sKeyPkcs8), sKeyPkcs8Len);
+ PrivateKey sKey11;
+ BOOST_CHECK_NO_THROW(sKey11.loadPkcs8(ss11, password.c_str(), password.size()));
+
+ std::stringstream ss12;
+ ss12.write(reinterpret_cast<const char*>(sKeyPkcs8), sKeyPkcs8Len);
+ PrivateKey sKey12;
+ BOOST_CHECK_NO_THROW(sKey12.loadPkcs8(ss12, pwCallback));
+
+ // load key using wrong password, Error is expected
+ PrivateKey sKey13;
+ BOOST_CHECK_THROW(sKey13.loadPkcs8Base64(sKeyPkcs8Base64, sKeyPkcs8Base64Len, wrongpw.c_str(), wrongpw.size()),
+ PrivateKey::Error);
+
+ // save key in base64-encoded pkcs8 format
+ OBufferStream os14;
+ BOOST_REQUIRE_NO_THROW(sKey.savePkcs8Base64(os14, password.c_str(), password.size()));
+ checkPkcs8Base64Encoding(os14.buf(), password, sKeyPkcs1Buf);
+
+ OBufferStream os15;
+ BOOST_REQUIRE_NO_THROW(sKey.savePkcs8Base64(os15, pwCallback));
+ checkPkcs8Base64Encoding(os15.buf(), password, sKeyPkcs1Buf);
+
+ // save key in pkcs8 format
+ OBufferStream os16;
+ BOOST_REQUIRE_NO_THROW(sKey.savePkcs8(os16, password.c_str(), password.size()));
+ checkPkcs8Encoding(os16.buf(), password, sKeyPkcs1Buf);
+
+ OBufferStream os17;
+ BOOST_REQUIRE_NO_THROW(sKey.savePkcs8(os17, pwCallback));
+ checkPkcs8Encoding(os17.buf(), password, sKeyPkcs1Buf);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(DerivePublicKey, T, KeyTestDataSets)
+{
+ T dataSet;
+
+ const uint8_t* sKeyPkcs1Base64 = reinterpret_cast<const uint8_t*>(dataSet.privateKeyPkcs1.c_str());
+ size_t sKeyPkcs1Base64Len = dataSet.privateKeyPkcs1.size();
+ PrivateKey sKey;
+ sKey.loadPkcs1Base64(sKeyPkcs1Base64, sKeyPkcs1Base64Len);
+
+ // derive public key and compare
+ ConstBufferPtr pKeyBits = sKey.derivePublicKey();
+ OBufferStream os;
+ bufferSource(dataSet.publicKeyPkcs8) >> base64Decode() >> streamSink(os);
+ BOOST_CHECK_EQUAL_COLLECTIONS(pKeyBits->begin(), pKeyBits->end(),
+ os.buf()->begin(), os.buf()->end());
+}
+
+BOOST_AUTO_TEST_CASE(RsaDecryption)
+{
+ RsaKeyTestData dataSet;
+
+ PrivateKey sKey;
+ sKey.loadPkcs1Base64(reinterpret_cast<const uint8_t*>(dataSet.privateKeyPkcs1.c_str()),
+ dataSet.privateKeyPkcs1.size());
+ BOOST_CHECK_EQUAL(sKey.getKeyType(), KeyType::RSA);
+
+ const uint8_t plainText[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
+
+ const std::string cipherTextBase64 =
+ "i2XNpZ2JbLa4JmBTdDrGmsd4/0C+p+BSCpW3MuPBNe5uChQ0eRO1dvjTnEqwSECY\n"
+ "38en9JZwcyb0It/TSFNXHlq+Z1ZpffnjIJxQR9HcgwvwQJh6WRH0vu38tvGkGuNv\n"
+ "60Rdn85hqSy1CikmXCeWXL9yCqeqcP21R94G/T3FuA+c1FtFko8KOzCwvrTXMO6n\n"
+ "5PNsqlLXabSGr+jz4EwOsSCgPkiDf9U6tXoSPRA2/YvqFQdaiUXIVlomESvaqqZ8\n"
+ "FxPs2BON0lobM8gT+xdzbRKofp+rNjNK+5uWyeOnXJwzCszh17cdJl2BH1dZwaVD\n"
+ "PmTiSdeDQXZ94U5boDQ4Aw==\n";
+ OBufferStream os;
+ bufferSource(cipherTextBase64) >> base64Decode() >> streamSink(os);
+
+ auto decrypted = sKey.decrypt(os.buf()->data(), os.buf()->size());
+ BOOST_CHECK_EQUAL_COLLECTIONS(plainText, plainText + sizeof(plainText),
+ decrypted->begin(), decrypted->end());
+}
+
+BOOST_AUTO_TEST_CASE(RsaEncryptDecrypt)
+{
+ RsaKeyTestData dataSet;
+
+ PublicKey pKey;
+ pKey.loadPkcs8Base64(reinterpret_cast<const uint8_t*>(dataSet.publicKeyPkcs8.c_str()),
+ dataSet.publicKeyPkcs8.size());
+ BOOST_CHECK_EQUAL(pKey.getKeyType(), KeyType::RSA);
+
+ PrivateKey sKey;
+ sKey.loadPkcs1Base64(reinterpret_cast<const uint8_t*>(dataSet.privateKeyPkcs1.c_str()),
+ dataSet.privateKeyPkcs1.size());
+ BOOST_CHECK_EQUAL(sKey.getKeyType(), KeyType::RSA);
+
+ const uint8_t plainText[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
+
+ auto cipherText = pKey.encrypt(plainText, sizeof(plainText));
+ auto decrypted = sKey.decrypt(cipherText->data(), cipherText->size());
+ BOOST_CHECK_EQUAL_COLLECTIONS(plainText, plainText + sizeof(plainText),
+ decrypted->begin(), decrypted->end());
+}
+
+BOOST_AUTO_TEST_CASE(UnsupportedEcDecryption)
+{
+ EcKeyTestData dataSet;
+
+ PrivateKey sKey;
+ sKey.loadPkcs1Base64(reinterpret_cast<const uint8_t*>(dataSet.privateKeyPkcs1.c_str()),
+ dataSet.privateKeyPkcs1.size());
+ BOOST_CHECK_EQUAL(sKey.getKeyType(), KeyType::EC);
+
+ OBufferStream os;
+ bufferSource("Y2lhbyFob2xhIWhlbGxvIQ==") >> base64Decode() >> streamSink(os);
+
+ BOOST_CHECK_THROW(sKey.decrypt(os.buf()->data(), os.buf()->size()), PrivateKey::Error);
+}
+
+using KeyParams = boost::mpl::vector<RsaKeyParams, EcKeyParams>;
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(GenerateKey, T, KeyParams)
+{
+ unique_ptr<PrivateKey> sKey = generatePrivateKey(T());
+ PublicKey pKey;
+ ConstBufferPtr pKeyBits = sKey->derivePublicKey();
+ pKey.loadPkcs8(pKeyBits->data(), pKeyBits->size());
+
+ const uint8_t data[] = {0x01, 0x02, 0x03, 0x04};
+ OBufferStream os;
+ BOOST_REQUIRE_NO_THROW(bufferSource(data, sizeof(data)) >>
+ signerFilter(DigestAlgorithm::SHA256, *sKey) >>
+ streamSink(os));
+
+ ConstBufferPtr sig = os.buf();
+ bool result = false;
+ BOOST_REQUIRE_NO_THROW(bufferSource(data, sizeof(data)) >>
+ verifierFilter(DigestAlgorithm::SHA256, pKey, sig->data(), sig->size()) >>
+ boolSink(result));
+ BOOST_CHECK(result);
+
+ unique_ptr<PrivateKey> sKey2 = generatePrivateKey(T());
+
+ OBufferStream os1;
+ sKey->savePkcs1(os1);
+ ConstBufferPtr key1Pkcs1 = os1.buf();
+
+ OBufferStream os2;
+ sKey2->savePkcs1(os2);
+ ConstBufferPtr key2Pkcs1 = os2.buf();
+
+ BOOST_CHECK(*key1Pkcs1 != *key2Pkcs1);
+}
+
+BOOST_AUTO_TEST_CASE(UnsupportedKeyType)
+{
+ BOOST_CHECK_THROW(generatePrivateKey(AesKeyParams()), std::invalid_argument);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestPrivateKey
+BOOST_AUTO_TEST_SUITE_END() // Transform
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace transform
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/transform/public-key.t.cpp b/tests/unit/security/transform/public-key.t.cpp
new file mode 100644
index 0000000..f9d3304
--- /dev/null
+++ b/tests/unit/security/transform/public-key.t.cpp
@@ -0,0 +1,132 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/transform/public-key.hpp"
+
+#include "encoding/buffer-stream.hpp"
+#include "security/transform.hpp"
+
+#include "boost-test.hpp"
+#include <boost/mpl/vector.hpp>
+
+#include <sstream>
+
+namespace ndn {
+namespace security {
+namespace transform {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(Transform)
+BOOST_AUTO_TEST_SUITE(TestPublicKey)
+
+struct RsaKeyTestData
+{
+ const std::string publicKeyPkcs8 =
+ "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw0WM1/WhAxyLtEqsiAJg\n"
+ "WDZWuzkYpeYVdeeZcqRZzzfRgBQTsNozS5t4HnwTZhwwXbH7k3QN0kRTV826Xobw\n"
+ "s3iigohnM9yTK+KKiayPhIAm/+5HGT6SgFJhYhqo1/upWdueojil6RP4/AgavHho\n"
+ "pxlAVbk6G9VdVnlQcQ5Zv0OcGi73c+EnYD/YgURYGSngUi/Ynsh779p2U69/te9g\n"
+ "ZwIL5PuE9BiO6I39cL9z7EK1SfZhOWvDe/qH7YhD/BHwcWit8FjRww1glwRVTJsA\n"
+ "9rH58ynaAix0tcR/nBMRLUX+e3rURHg6UbSjJbdb9qmKM1fTGHKUzL/5pMG6uBU0\n"
+ "ywIDAQAB\n";
+};
+
+struct EcKeyTestData
+{
+ const std::string publicKeyPkcs8 =
+ "MIIBSzCCAQMGByqGSM49AgEwgfcCAQEwLAYHKoZIzj0BAQIhAP////8AAAABAAAA\n"
+ "AAAAAAAAAAAA////////////////MFsEIP////8AAAABAAAAAAAAAAAAAAAA////\n"
+ "///////////8BCBaxjXYqjqT57PrvVV2mIa8ZR0GsMxTsPY7zjw+J9JgSwMVAMSd\n"
+ "NgiG5wSTamZ44ROdJreBn36QBEEEaxfR8uEsQkf4vOblY6RA8ncDfYEt6zOg9KE5\n"
+ "RdiYwpZP40Li/hp/m47n60p8D54WK84zV2sxXs7LtkBoN79R9QIhAP////8AAAAA\n"
+ "//////////+85vqtpxeehPO5ysL8YyVRAgEBA0IABGhuFibgwLdEJBDOLdvSg1Hc\n"
+ "5EJTDxq6ls5FoYLfThp8HOjuwGSz0qw8ocMqyku1y0V5peQ4rEPd0bwcpZd9svA=\n";
+};
+
+using KeyTestDataSets = boost::mpl::vector<RsaKeyTestData, EcKeyTestData>;
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(SaveLoad, T, KeyTestDataSets)
+{
+ T dataSet;
+
+ const uint8_t* pKeyPkcs8Base64 = reinterpret_cast<const uint8_t*>(dataSet.publicKeyPkcs8.c_str());
+ size_t pKeyPkcs8Base64Len = dataSet.publicKeyPkcs8.size();
+ OBufferStream os;
+ bufferSource(pKeyPkcs8Base64, pKeyPkcs8Base64Len) >> base64Decode() >> streamSink(os);
+ ConstBufferPtr pKeyPkcs8Buf = os.buf();
+ const uint8_t* pKeyPkcs8 = pKeyPkcs8Buf->data();
+ size_t pKeyPkcs8Len = pKeyPkcs8Buf->size();
+
+ PublicKey pKey1;
+ BOOST_CHECK_NO_THROW(pKey1.loadPkcs8Base64(pKeyPkcs8Base64, pKeyPkcs8Base64Len));
+
+ std::stringstream ss2(dataSet.publicKeyPkcs8);
+ PublicKey pKey2;
+ BOOST_CHECK_NO_THROW(pKey2.loadPkcs8Base64(ss2));
+
+ PublicKey pKey3;
+ BOOST_CHECK_NO_THROW(pKey3.loadPkcs8(pKeyPkcs8, pKeyPkcs8Len));
+
+ std::stringstream ss4;
+ ss4.write(reinterpret_cast<const char*>(pKeyPkcs8), pKeyPkcs8Len);
+ PublicKey pKey4;
+ BOOST_CHECK_NO_THROW(pKey4.loadPkcs8(ss4));
+
+ OBufferStream os5;
+ BOOST_REQUIRE_NO_THROW(pKey1.savePkcs8Base64(os5));
+ BOOST_CHECK_EQUAL_COLLECTIONS(pKeyPkcs8Base64, pKeyPkcs8Base64 + pKeyPkcs8Base64Len,
+ os5.buf()->begin(), os5.buf()->end());
+
+ OBufferStream os6;
+ BOOST_REQUIRE_NO_THROW(pKey1.savePkcs8(os6));
+ BOOST_CHECK_EQUAL_COLLECTIONS(pKeyPkcs8, pKeyPkcs8 + pKeyPkcs8Len,
+ os6.buf()->begin(), os6.buf()->end());
+}
+
+// NOTE: We cannot test RSA encryption by comparing the computed ciphertext to
+// a known-good one, because OAEP padding is randomized and would produce
+// different results every time. An encrypt/decrypt round-trip test is
+// performed in private-key.t.cpp
+
+BOOST_AUTO_TEST_CASE(UnsupportedEcEncryption)
+{
+ EcKeyTestData dataSet;
+
+ PublicKey pKey;
+ pKey.loadPkcs8Base64(reinterpret_cast<const uint8_t*>(dataSet.publicKeyPkcs8.c_str()),
+ dataSet.publicKeyPkcs8.size());
+ BOOST_CHECK_EQUAL(pKey.getKeyType(), KeyType::EC);
+
+ OBufferStream os;
+ bufferSource("Y2lhbyFob2xhIWhlbGxvIQ==") >> base64Decode() >> streamSink(os);
+
+ BOOST_CHECK_THROW(pKey.encrypt(os.buf()->data(), os.buf()->size()), PublicKey::Error);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestPublicKey
+BOOST_AUTO_TEST_SUITE_END() // Transform
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace transform
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/transform/signer-filter.t.cpp b/tests/unit/security/transform/signer-filter.t.cpp
new file mode 100644
index 0000000..51a98f0
--- /dev/null
+++ b/tests/unit/security/transform/signer-filter.t.cpp
@@ -0,0 +1,146 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/transform/signer-filter.hpp"
+
+#include "encoding/buffer-stream.hpp"
+#include "security/transform/base64-decode.hpp"
+#include "security/transform/buffer-source.hpp"
+#include "security/transform/private-key.hpp"
+#include "security/transform/stream-sink.hpp"
+#include "security/verification-helpers.hpp"
+
+#include "boost-test.hpp"
+
+namespace ndn {
+namespace security {
+namespace transform {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(Transform)
+BOOST_AUTO_TEST_SUITE(TestSignerFilter)
+
+BOOST_AUTO_TEST_CASE(Rsa)
+{
+ const std::string publicKeyPkcs8 =
+ "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw0WM1/WhAxyLtEqsiAJg\n"
+ "WDZWuzkYpeYVdeeZcqRZzzfRgBQTsNozS5t4HnwTZhwwXbH7k3QN0kRTV826Xobw\n"
+ "s3iigohnM9yTK+KKiayPhIAm/+5HGT6SgFJhYhqo1/upWdueojil6RP4/AgavHho\n"
+ "pxlAVbk6G9VdVnlQcQ5Zv0OcGi73c+EnYD/YgURYGSngUi/Ynsh779p2U69/te9g\n"
+ "ZwIL5PuE9BiO6I39cL9z7EK1SfZhOWvDe/qH7YhD/BHwcWit8FjRww1glwRVTJsA\n"
+ "9rH58ynaAix0tcR/nBMRLUX+e3rURHg6UbSjJbdb9qmKM1fTGHKUzL/5pMG6uBU0\n"
+ "ywIDAQAB\n";
+ const std::string privateKeyPkcs1 =
+ "MIIEpAIBAAKCAQEAw0WM1/WhAxyLtEqsiAJgWDZWuzkYpeYVdeeZcqRZzzfRgBQT\n"
+ "sNozS5t4HnwTZhwwXbH7k3QN0kRTV826Xobws3iigohnM9yTK+KKiayPhIAm/+5H\n"
+ "GT6SgFJhYhqo1/upWdueojil6RP4/AgavHhopxlAVbk6G9VdVnlQcQ5Zv0OcGi73\n"
+ "c+EnYD/YgURYGSngUi/Ynsh779p2U69/te9gZwIL5PuE9BiO6I39cL9z7EK1SfZh\n"
+ "OWvDe/qH7YhD/BHwcWit8FjRww1glwRVTJsA9rH58ynaAix0tcR/nBMRLUX+e3rU\n"
+ "RHg6UbSjJbdb9qmKM1fTGHKUzL/5pMG6uBU0ywIDAQABAoIBADQkckOIl4IZMUTn\n"
+ "W8LFv6xOdkJwMKC8G6bsPRFbyY+HvC2TLt7epSvfS+f4AcYWaOPcDu2E49vt2sNr\n"
+ "cASly8hgwiRRAB3dHH9vcsboiTo8bi2RFvMqvjv9w3tK2yMxVDtmZamzrrnaV3YV\n"
+ "Q+5nyKo2F/PMDjQ4eUAKDOzjhBuKHsZBTFnA1MFNI+UKj5X4Yp64DFmKlxTX/U2b\n"
+ "wzVywo5hzx2Uhw51jmoLls4YUvMJXD0wW5ZtYRuPogXvXb/of9ef/20/wU11WFKg\n"
+ "Xb4gfR8zUXaXS1sXcnVm3+24vIs9dApUwykuoyjOqxWqcHRec2QT2FxVGkFEraze\n"
+ "CPa4rMECgYEA5Y8CywomIcTgerFGFCeMHJr8nQGqY2V/owFb3k9maczPnC9p4a9R\n"
+ "c5szLxA9FMYFxurQZMBWSEG2JS1HR2mnjigx8UKjYML/A+rvvjZOMe4M6Sy2ggh4\n"
+ "SkLZKpWTzjTe07ByM/j5v/SjNZhWAG7sw4/LmPGRQkwJv+KZhGojuOkCgYEA2cOF\n"
+ "T6cJRv6kvzTz9S0COZOVm+euJh/BXp7oAsAmbNfOpckPMzqHXy8/wpdKl6AAcB57\n"
+ "OuztlNfV1D7qvbz7JuRlYwQ0cEfBgbZPcz1p18HHDXhwn57ZPb8G33Yh9Omg0HNA\n"
+ "Imb4LsVuSqxA6NwSj7cpRekgTedrhLFPJ+Ydb5MCgYEAsM3Q7OjILcIg0t6uht9e\n"
+ "vrlwTsz1mtCV2co2I6crzdj9HeI2vqf1KAElDt6G7PUHhglcr/yjd8uEqmWRPKNX\n"
+ "ddnnfVZB10jYeP/93pac6z/Zmc3iU4yKeUe7U10ZFf0KkiiYDQd59CpLef/2XScS\n"
+ "HB0oRofnxRQjfjLc4muNT+ECgYEAlcDk06MOOTly+F8lCc1bA1dgAmgwFd2usDBd\n"
+ "Y07a3e0HGnGLN3Kfl7C5i0tZq64HvxLnMd2vgLVxQlXGPpdQrC1TH+XLXg+qnlZO\n"
+ "ivSH7i0/gx75bHvj75eH1XK65V8pDVDEoSPottllAIs21CxLw3N1ObOZWJm2EfmR\n"
+ "cuHICmsCgYAtFJ1idqMoHxES3mlRpf2JxyQudP3SCm2WpGmqVzhRYInqeatY5sUd\n"
+ "lPLHm/p77RT7EyxQHTlwn8FJPuM/4ZH1rQd/vB+Y8qAtYJCexDMsbvLW+Js+VOvk\n"
+ "jweEC0nrcL31j9mF0vz5E6tfRu4hhJ6L4yfWs0gSejskeVB/w8QY4g==\n";
+ const uint8_t data[] = {0x01, 0x02, 0x03, 0x04};
+
+ OBufferStream os1;
+ bufferSource(publicKeyPkcs8) >> base64Decode() >> streamSink(os1);
+ auto pubKey = os1.buf();
+
+ PrivateKey sKey;
+ sKey.loadPkcs1Base64(reinterpret_cast<const uint8_t*>(privateKeyPkcs1.data()), privateKeyPkcs1.size());
+
+ BOOST_CHECK_THROW(SignerFilter(DigestAlgorithm::NONE, sKey), Error);
+
+ OBufferStream os2;
+ bufferSource(data, sizeof(data)) >> signerFilter(DigestAlgorithm::SHA256, sKey) >> streamSink(os2);
+ auto sig = os2.buf();
+
+ BOOST_CHECK(verifySignature(data, sizeof(data), sig->data(), sig->size(), pubKey->data(), pubKey->size()));
+}
+
+BOOST_AUTO_TEST_CASE(Ecdsa)
+{
+ const std::string privateKeyPkcs1 =
+ "MIIBaAIBAQQgRxwcbzK9RV6AHYFsDcykI86o3M/a1KlJn0z8PcLMBZOggfowgfcC\n"
+ "AQEwLAYHKoZIzj0BAQIhAP////8AAAABAAAAAAAAAAAAAAAA////////////////\n"
+ "MFsEIP////8AAAABAAAAAAAAAAAAAAAA///////////////8BCBaxjXYqjqT57Pr\n"
+ "vVV2mIa8ZR0GsMxTsPY7zjw+J9JgSwMVAMSdNgiG5wSTamZ44ROdJreBn36QBEEE\n"
+ "axfR8uEsQkf4vOblY6RA8ncDfYEt6zOg9KE5RdiYwpZP40Li/hp/m47n60p8D54W\n"
+ "K84zV2sxXs7LtkBoN79R9QIhAP////8AAAAA//////////+85vqtpxeehPO5ysL8\n"
+ "YyVRAgEBoUQDQgAEaG4WJuDAt0QkEM4t29KDUdzkQlMPGrqWzkWhgt9OGnwc6O7A\n"
+ "ZLPSrDyhwyrKS7XLRXml5DisQ93RvByll32y8A==\n";
+ const std::string publicKeyPkcs8 =
+ "MIIBSzCCAQMGByqGSM49AgEwgfcCAQEwLAYHKoZIzj0BAQIhAP////8AAAABAAAA\n"
+ "AAAAAAAAAAAA////////////////MFsEIP////8AAAABAAAAAAAAAAAAAAAA////\n"
+ "///////////8BCBaxjXYqjqT57PrvVV2mIa8ZR0GsMxTsPY7zjw+J9JgSwMVAMSd\n"
+ "NgiG5wSTamZ44ROdJreBn36QBEEEaxfR8uEsQkf4vOblY6RA8ncDfYEt6zOg9KE5\n"
+ "RdiYwpZP40Li/hp/m47n60p8D54WK84zV2sxXs7LtkBoN79R9QIhAP////8AAAAA\n"
+ "//////////+85vqtpxeehPO5ysL8YyVRAgEBA0IABGhuFibgwLdEJBDOLdvSg1Hc\n"
+ "5EJTDxq6ls5FoYLfThp8HOjuwGSz0qw8ocMqyku1y0V5peQ4rEPd0bwcpZd9svA=\n";
+ const uint8_t data[] = {0x01, 0x02, 0x03, 0x04};
+
+ OBufferStream os1;
+ bufferSource(publicKeyPkcs8) >> base64Decode() >> streamSink(os1);
+ auto pubKey = os1.buf();
+
+ PrivateKey sKey;
+ sKey.loadPkcs1Base64(reinterpret_cast<const uint8_t*>(privateKeyPkcs1.data()), privateKeyPkcs1.size());
+
+ BOOST_CHECK_THROW(SignerFilter(DigestAlgorithm::NONE, sKey), Error);
+
+ OBufferStream os2;
+ bufferSource(data, sizeof(data)) >> signerFilter(DigestAlgorithm::SHA256, sKey) >> streamSink(os2);
+ auto sig = os2.buf();
+
+ BOOST_CHECK(verifySignature(data, sizeof(data), sig->data(), sig->size(), pubKey->data(), pubKey->size()));
+}
+
+BOOST_AUTO_TEST_CASE(InvalidKey)
+{
+ PrivateKey sKey;
+ BOOST_CHECK_THROW(SignerFilter(DigestAlgorithm::SHA256, sKey), Error);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestSignerFilter
+BOOST_AUTO_TEST_SUITE_END() // Transform
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace transform
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/transform/step-source.t.cpp b/tests/unit/security/transform/step-source.t.cpp
new file mode 100644
index 0000000..43c6655
--- /dev/null
+++ b/tests/unit/security/transform/step-source.t.cpp
@@ -0,0 +1,91 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/transform/step-source.hpp"
+#include "security/transform/stream-sink.hpp"
+
+#include "boost-test.hpp"
+
+#include <sstream>
+
+namespace ndn {
+namespace security {
+namespace transform {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(Transform)
+BOOST_AUTO_TEST_SUITE(TestStepSource)
+
+BOOST_AUTO_TEST_CASE(Basic)
+{
+ const std::string input =
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567";
+ const uint8_t* buf = reinterpret_cast<const uint8_t*>(input.data());
+
+ std::ostringstream os;
+ StepSource ss;
+ ss >> streamSink(os);
+ BOOST_CHECK_EQUAL(ss.write(buf, 320), 320);
+ BOOST_CHECK_EQUAL(ss.write(buf + 320, 320), 320);
+ BOOST_CHECK_EQUAL(ss.write(buf + 640, 320), 320);
+ BOOST_CHECK_EQUAL(ss.write(buf + 960, 320), 320);
+ ss.end();
+ BOOST_CHECK_THROW(ss.write(buf + 960, 320), transform::Error);
+ BOOST_CHECK_EQUAL(os.str(), input);
+}
+
+BOOST_AUTO_TEST_CASE(EmptyInput)
+{
+ std::ostringstream os;
+ StepSource ss;
+ ss >> streamSink(os);
+ ss.end();
+ BOOST_CHECK_EQUAL(os.str(), "");
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestStepSource
+BOOST_AUTO_TEST_SUITE_END() // Transform
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace transform
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/transform/stream-sink.t.cpp b/tests/unit/security/transform/stream-sink.t.cpp
new file mode 100644
index 0000000..753ea35
--- /dev/null
+++ b/tests/unit/security/transform/stream-sink.t.cpp
@@ -0,0 +1,60 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/transform/stream-sink.hpp"
+
+#include "boost-test.hpp"
+
+namespace ndn {
+namespace security {
+namespace transform {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(Transform)
+BOOST_AUTO_TEST_SUITE(TestStreamSink)
+
+BOOST_AUTO_TEST_CASE(Basic)
+{
+ uint8_t in[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x20, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+ };
+ std::ostringstream os;
+ StreamSink sink(os);
+ BOOST_CHECK_EQUAL(sink.write(in, 4), 4);
+ BOOST_CHECK_EQUAL(sink.write(in + 4, 4), 4);
+ BOOST_CHECK_EQUAL(sink.write(in + 8, 4), 4);
+ BOOST_CHECK_EQUAL(sink.write(in + 12, 4), 4);
+ sink.end();
+ std::string out = os.str();
+ BOOST_CHECK_EQUAL_COLLECTIONS(in, in + sizeof(in), out.begin(), out.end());
+ BOOST_CHECK_THROW(sink.write(in + 8, 8), transform::Error);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestStreamSink
+BOOST_AUTO_TEST_SUITE_END() // Transform
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace transform
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/transform/stream-source.t.cpp b/tests/unit/security/transform/stream-source.t.cpp
new file mode 100644
index 0000000..ae385b1
--- /dev/null
+++ b/tests/unit/security/transform/stream-source.t.cpp
@@ -0,0 +1,99 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/transform/stream-source.hpp"
+#include "security/transform/stream-sink.hpp"
+
+#include "boost-test.hpp"
+#include <boost/mpl/integral_c.hpp>
+#include <boost/mpl/vector.hpp>
+
+namespace ndn {
+namespace security {
+namespace transform {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(Transform)
+BOOST_AUTO_TEST_SUITE(TestStreamSource)
+
+BOOST_AUTO_TEST_CASE(Basic)
+{
+ std::string input =
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "01234567012345670123456701234567 1234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567";
+
+ std::stringstream is(input);
+ std::stringstream os;
+ streamSource(is) >> streamSink(os);
+ std::string output = os.str();
+
+ BOOST_CHECK_EQUAL(input, output);
+}
+
+BOOST_AUTO_TEST_CASE(EmptyStream)
+{
+ std::stringstream is;
+ std::stringstream os;
+ streamSource(is) >> streamSink(os);
+
+ BOOST_CHECK_EQUAL(os.str(), "");
+}
+
+typedef boost::mpl::vector<
+ boost::mpl::integral_c<std::ios_base::iostate, std::ios_base::badbit>,
+ boost::mpl::integral_c<std::ios_base::iostate, std::ios_base::failbit>
+> BadBits;
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(BadStream, BadBit, BadBits)
+{
+ std::stringstream is;
+ is.setstate(BadBit::value);
+ std::stringstream os;
+ BOOST_CHECK_THROW(streamSource(is) >> streamSink(os), transform::Error);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestStreamSource
+BOOST_AUTO_TEST_SUITE_END() // Transform
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace transform
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/transform/strip-space.t.cpp b/tests/unit/security/transform/strip-space.t.cpp
new file mode 100644
index 0000000..db8fa84
--- /dev/null
+++ b/tests/unit/security/transform/strip-space.t.cpp
@@ -0,0 +1,77 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/transform/strip-space.hpp"
+#include "security/transform/step-source.hpp"
+#include "security/transform/stream-sink.hpp"
+#include "encoding/buffer-stream.hpp"
+
+#include "boost-test.hpp"
+
+namespace ndn {
+namespace security {
+namespace transform {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(Transform)
+BOOST_AUTO_TEST_SUITE(TestStripSpace)
+
+BOOST_AUTO_TEST_CASE(Basic)
+{
+ const char* input = R"STR(
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
+ incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
+ exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute
+ irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
+ pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia
+ deserunt mollit anim id est laborum.
+ )STR";
+ size_t inputLen = strlen(input);
+
+ OBufferStream os;
+ StepSource source;
+ source >> stripSpace() >> streamSink(os);
+
+ for (size_t offset = 0; offset < inputLen; offset += 40) {
+ source.write(reinterpret_cast<const uint8_t*>(input + offset),
+ std::min<size_t>(40, inputLen - offset));
+ }
+ source.end();
+
+ std::string expected(
+ "Loremipsumdolorsitamet,consecteturadipiscingelit,seddoeiusmodtemporincididuntutl"
+ "aboreetdoloremagnaaliqua.Utenimadminimveniam,quisnostrudexercitationullamcolabor"
+ "isnisiutaliquipexeacommodoconsequat.Duisauteiruredolorinreprehenderitinvoluptate"
+ "velitessecillumdoloreeufugiatnullapariatur.Excepteursintoccaecatcupidatatnonproi"
+ "dent,suntinculpaquiofficiadeseruntmollitanimidestlaborum.");
+ ConstBufferPtr buf = os.buf();
+ BOOST_CHECK_EQUAL(std::string(buf->get<char>(), buf->size()), expected);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestStripSpace
+BOOST_AUTO_TEST_SUITE_END() // Transform
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace transform
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/transform/verifier-filter.t.cpp b/tests/unit/security/transform/verifier-filter.t.cpp
new file mode 100644
index 0000000..1b74690
--- /dev/null
+++ b/tests/unit/security/transform/verifier-filter.t.cpp
@@ -0,0 +1,165 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/transform/verifier-filter.hpp"
+
+#include "encoding/buffer-stream.hpp"
+#include "security/transform/base64-decode.hpp"
+#include "security/transform/bool-sink.hpp"
+#include "security/transform/buffer-source.hpp"
+#include "security/transform/private-key.hpp"
+#include "security/transform/public-key.hpp"
+#include "security/transform/signer-filter.hpp"
+#include "security/transform/stream-sink.hpp"
+
+#include "boost-test.hpp"
+
+namespace ndn {
+namespace security {
+namespace transform {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(Transform)
+BOOST_AUTO_TEST_SUITE(TestVerifierFilter)
+
+BOOST_AUTO_TEST_CASE(Rsa)
+{
+ const std::string publicKeyPkcs8 =
+ "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw0WM1/WhAxyLtEqsiAJg\n"
+ "WDZWuzkYpeYVdeeZcqRZzzfRgBQTsNozS5t4HnwTZhwwXbH7k3QN0kRTV826Xobw\n"
+ "s3iigohnM9yTK+KKiayPhIAm/+5HGT6SgFJhYhqo1/upWdueojil6RP4/AgavHho\n"
+ "pxlAVbk6G9VdVnlQcQ5Zv0OcGi73c+EnYD/YgURYGSngUi/Ynsh779p2U69/te9g\n"
+ "ZwIL5PuE9BiO6I39cL9z7EK1SfZhOWvDe/qH7YhD/BHwcWit8FjRww1glwRVTJsA\n"
+ "9rH58ynaAix0tcR/nBMRLUX+e3rURHg6UbSjJbdb9qmKM1fTGHKUzL/5pMG6uBU0\n"
+ "ywIDAQAB\n";
+ const std::string privateKeyPkcs1 =
+ "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDDRYzX9aEDHIu0\n"
+ "SqyIAmBYNla7ORil5hV155lypFnPN9GAFBOw2jNLm3gefBNmHDBdsfuTdA3SRFNX\n"
+ "zbpehvCzeKKCiGcz3JMr4oqJrI+EgCb/7kcZPpKAUmFiGqjX+6lZ256iOKXpE/j8\n"
+ "CBq8eGinGUBVuTob1V1WeVBxDlm/Q5waLvdz4SdgP9iBRFgZKeBSL9ieyHvv2nZT\n"
+ "r3+172BnAgvk+4T0GI7ojf1wv3PsQrVJ9mE5a8N7+oftiEP8EfBxaK3wWNHDDWCX\n"
+ "BFVMmwD2sfnzKdoCLHS1xH+cExEtRf57etREeDpRtKMlt1v2qYozV9MYcpTMv/mk\n"
+ "wbq4FTTLAgMBAAECggEANCRyQ4iXghkxROdbwsW/rE52QnAwoLwbpuw9EVvJj4e8\n"
+ "LZMu3t6lK99L5/gBxhZo49wO7YTj2+3aw2twBKXLyGDCJFEAHd0cf29yxuiJOjxu\n"
+ "LZEW8yq+O/3De0rbIzFUO2ZlqbOuudpXdhVD7mfIqjYX88wONDh5QAoM7OOEG4oe\n"
+ "xkFMWcDUwU0j5QqPlfhinrgMWYqXFNf9TZvDNXLCjmHPHZSHDnWOaguWzhhS8wlc\n"
+ "PTBblm1hG4+iBe9dv+h/15//bT/BTXVYUqBdviB9HzNRdpdLWxdydWbf7bi8iz10\n"
+ "ClTDKS6jKM6rFapwdF5zZBPYXFUaQUStrN4I9riswQKBgQDljwLLCiYhxOB6sUYU\n"
+ "J4wcmvydAapjZX+jAVveT2ZpzM+cL2nhr1FzmzMvED0UxgXG6tBkwFZIQbYlLUdH\n"
+ "aaeOKDHxQqNgwv8D6u++Nk4x7gzpLLaCCHhKQtkqlZPONN7TsHIz+Pm/9KM1mFYA\n"
+ "buzDj8uY8ZFCTAm/4pmEaiO46QKBgQDZw4VPpwlG/qS/NPP1LQI5k5Wb564mH8Fe\n"
+ "nugCwCZs186lyQ8zOodfLz/Cl0qXoABwHns67O2U19XUPuq9vPsm5GVjBDRwR8GB\n"
+ "tk9zPWnXwccNeHCfntk9vwbfdiH06aDQc0AiZvguxW5KrEDo3BKPtylF6SBN52uE\n"
+ "sU8n5h1vkwKBgQCwzdDs6MgtwiDS3q6G316+uXBOzPWa0JXZyjYjpyvN2P0d4ja+\n"
+ "p/UoASUO3obs9QeGCVyv/KN3y4SqZZE8o1d12ed9VkHXSNh4//3elpzrP9mZzeJT\n"
+ "jIp5R7tTXRkV/QqSKJgNB3n0Kkt5//ZdJxIcHShGh+fFFCN+Mtzia41P4QKBgQCV\n"
+ "wOTTow45OXL4XyUJzVsDV2ACaDAV3a6wMF1jTtrd7QcacYs3cp+XsLmLS1mrrge/\n"
+ "Eucx3a+AtXFCVcY+l1CsLVMf5cteD6qeVk6K9IfuLT+DHvlse+Pvl4fVcrrlXykN\n"
+ "UMShI+i22WUAizbULEvDc3U5s5lYmbYR+ZFy4cgKawKBgC0UnWJ2oygfERLeaVGl\n"
+ "/YnHJC50/dIKbZakaapXOFFgiep5q1jmxR2U8seb+nvtFPsTLFAdOXCfwUk+4z/h\n"
+ "kfWtB3+8H5jyoC1gkJ7EMyxu8tb4mz5U6+SPB4QLSetwvfWP2YXS/PkTq19G7iGE\n"
+ "novjJ9azSBJ6OyR5UH/DxBji\n";
+ const uint8_t data[] = {0x01, 0x02, 0x03, 0x04};
+
+ OBufferStream os1;
+ bufferSource(publicKeyPkcs8) >> base64Decode() >> streamSink(os1);
+ auto pubKey = os1.buf();
+
+ PublicKey pKey;
+ pKey.loadPkcs8(pubKey->data(), pubKey->size());
+
+ PrivateKey sKey;
+ sKey.loadPkcs1Base64(reinterpret_cast<const uint8_t*>(privateKeyPkcs1.data()), privateKeyPkcs1.size());
+
+ OBufferStream os2;
+ bufferSource(data, sizeof(data)) >> signerFilter(DigestAlgorithm::SHA256, sKey) >> streamSink(os2);
+ auto sig = os2.buf();
+
+ BOOST_CHECK_THROW(VerifierFilter(DigestAlgorithm::NONE, pKey, sig->data(), sig->size()), Error);
+
+ bool result = false;
+ bufferSource(data, sizeof(data)) >>
+ verifierFilter(DigestAlgorithm::SHA256, pKey, sig->data(), sig->size()) >>
+ boolSink(result);
+
+ BOOST_CHECK_EQUAL(result, true);
+}
+
+BOOST_AUTO_TEST_CASE(Ecdsa)
+{
+ const std::string privateKeyPkcs1 =
+ "MIIBeQIBADCCAQMGByqGSM49AgEwgfcCAQEwLAYHKoZIzj0BAQIhAP////8AAAAB\n"
+ "AAAAAAAAAAAAAAAA////////////////MFsEIP////8AAAABAAAAAAAAAAAAAAAA\n"
+ "///////////////8BCBaxjXYqjqT57PrvVV2mIa8ZR0GsMxTsPY7zjw+J9JgSwMV\n"
+ "AMSdNgiG5wSTamZ44ROdJreBn36QBEEEaxfR8uEsQkf4vOblY6RA8ncDfYEt6zOg\n"
+ "9KE5RdiYwpZP40Li/hp/m47n60p8D54WK84zV2sxXs7LtkBoN79R9QIhAP////8A\n"
+ "AAAA//////////+85vqtpxeehPO5ysL8YyVRAgEBBG0wawIBAQQgRxwcbzK9RV6A\n"
+ "HYFsDcykI86o3M/a1KlJn0z8PcLMBZOhRANCAARobhYm4MC3RCQQzi3b0oNR3ORC\n"
+ "Uw8aupbORaGC304afBzo7sBks9KsPKHDKspLtctFeaXkOKxD3dG8HKWXfbLw\n";
+ const std::string publicKeyPkcs8 =
+ "MIIBSzCCAQMGByqGSM49AgEwgfcCAQEwLAYHKoZIzj0BAQIhAP////8AAAABAAAA\n"
+ "AAAAAAAAAAAA////////////////MFsEIP////8AAAABAAAAAAAAAAAAAAAA////\n"
+ "///////////8BCBaxjXYqjqT57PrvVV2mIa8ZR0GsMxTsPY7zjw+J9JgSwMVAMSd\n"
+ "NgiG5wSTamZ44ROdJreBn36QBEEEaxfR8uEsQkf4vOblY6RA8ncDfYEt6zOg9KE5\n"
+ "RdiYwpZP40Li/hp/m47n60p8D54WK84zV2sxXs7LtkBoN79R9QIhAP////8AAAAA\n"
+ "//////////+85vqtpxeehPO5ysL8YyVRAgEBA0IABGhuFibgwLdEJBDOLdvSg1Hc\n"
+ "5EJTDxq6ls5FoYLfThp8HOjuwGSz0qw8ocMqyku1y0V5peQ4rEPd0bwcpZd9svA=\n";
+ const uint8_t data[] = {0x01, 0x02, 0x03, 0x04};
+
+ OBufferStream os1;
+ bufferSource(publicKeyPkcs8) >> base64Decode() >> streamSink(os1);
+ auto pubKey = os1.buf();
+
+ PublicKey pKey;
+ pKey.loadPkcs8(pubKey->data(), pubKey->size());
+
+ PrivateKey sKey;
+ sKey.loadPkcs1Base64(reinterpret_cast<const uint8_t*>(privateKeyPkcs1.data()), privateKeyPkcs1.size());
+
+ OBufferStream os2;
+ bufferSource(data, sizeof(data)) >> signerFilter(DigestAlgorithm::SHA256, sKey) >> streamSink(os2);
+ auto sig = os2.buf();
+
+ BOOST_CHECK_THROW(VerifierFilter(DigestAlgorithm::NONE, pKey, sig->data(), sig->size()), Error);
+
+ bool result = false;
+ bufferSource(data, sizeof(data)) >>
+ verifierFilter(DigestAlgorithm::SHA256, pKey, sig->data(), sig->size()) >>
+ boolSink(result);
+
+ BOOST_CHECK_EQUAL(result, true);
+}
+
+BOOST_AUTO_TEST_CASE(InvalidKey)
+{
+ PublicKey pKey;
+ BOOST_CHECK_THROW(VerifierFilter(DigestAlgorithm::SHA256, pKey, nullptr, 0), Error);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestVerifierFilter
+BOOST_AUTO_TEST_SUITE_END() // Transform
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace transform
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/v2/additional-description.t.cpp b/tests/unit/security/v2/additional-description.t.cpp
new file mode 100644
index 0000000..7ceee8c
--- /dev/null
+++ b/tests/unit/security/v2/additional-description.t.cpp
@@ -0,0 +1,103 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/v2/additional-description.hpp"
+
+#include "boost-test.hpp"
+
+namespace ndn {
+namespace security {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(TestAdditionalDescription)
+
+const uint8_t description[] = {
+ 0xfd, 0x01, 0x02, 0x28,
+ 0xfd, 0x02, 0x00, 0x10, // DescriptionEntry
+ 0xfd, 0x02, 0x01, 0x04, // DescriptionKey
+ 0x6b, 0x65, 0x79, 0x31, // "key1"
+ 0xfd, 0x02, 0x02, 0x04, // DescriptionValue
+ 0x76, 0x61, 0x6c, 0x31, // "val1"
+ 0xfd, 0x02, 0x00, 0x10, // DescriptionEntry
+ 0xfd, 0x02, 0x01, 0x04, // DescriptionKey
+ 0x6b, 0x65, 0x79, 0x32, // "key2"
+ 0xfd, 0x02, 0x02, 0x04, // DescriptionValue
+ 0x76, 0x61, 0x6c, 0x32, // "val2"
+};
+
+const std::string text = "((key1:val1), (key2:val2))";
+
+BOOST_AUTO_TEST_CASE(Basic)
+{
+ AdditionalDescription aDescription;
+
+ aDescription.set("key2", "val2");
+ aDescription.set("key1", "val1");
+
+ BOOST_REQUIRE_NO_THROW(aDescription.get("key1"));
+ BOOST_REQUIRE_NO_THROW(aDescription.get("key2"));
+ BOOST_REQUIRE_THROW(aDescription.get("key3"), AdditionalDescription::Error);
+
+ BOOST_CHECK_EQUAL(aDescription.has("key1"), true);
+ BOOST_CHECK_EQUAL(aDescription.has("key2"), true);
+ BOOST_CHECK_EQUAL(aDescription.has("key3"), false);
+
+ auto val1 = aDescription.get("key1");
+ auto val2 = aDescription.get("key2");
+
+ BOOST_CHECK_EQUAL(val1, "val1");
+ BOOST_CHECK_EQUAL(val2, "val2");
+
+ auto it = aDescription.begin();
+ BOOST_CHECK_EQUAL(it->second, "val1");
+ it++;
+ BOOST_CHECK_EQUAL(it->second, "val2");
+ it++;
+ BOOST_CHECK(it == aDescription.end());
+
+ BOOST_CHECK_EQUAL_COLLECTIONS(aDescription.wireEncode().wire(),
+ aDescription.wireEncode().wire() + aDescription.wireEncode().size(),
+ description,
+ description + sizeof(description));
+
+ BOOST_REQUIRE_NO_THROW(AdditionalDescription(Block(description, sizeof(description))));
+ AdditionalDescription aDescription2(Block(description, sizeof(description)));
+
+ BOOST_CHECK_EQUAL(aDescription2, aDescription);
+
+ AdditionalDescription aDescription3;
+ aDescription3.set("key3", "val3");
+ aDescription3.set("key2", "val2");
+
+ BOOST_CHECK_NE(aDescription2, aDescription3);
+
+ std::ostringstream os;
+ os << aDescription;
+ BOOST_CHECK_EQUAL(os.str(), text);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestAdditionalDescription
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/v2/certificate-bundle-fetcher.t.cpp b/tests/unit/security/v2/certificate-bundle-fetcher.t.cpp
new file mode 100644
index 0000000..d2e0565
--- /dev/null
+++ b/tests/unit/security/v2/certificate-bundle-fetcher.t.cpp
@@ -0,0 +1,191 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/v2/certificate-bundle-fetcher.hpp"
+#include "security/v2/validation-policy-simple-hierarchy.hpp"
+#include "util/regex/regex-pattern-list-matcher.hpp"
+#include "lp/nack.hpp"
+
+#include "boost-test.hpp"
+#include "validator-fixture.hpp"
+
+namespace ndn {
+namespace security {
+namespace v2 {
+namespace tests {
+
+using namespace ndn::tests;
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(V2)
+BOOST_AUTO_TEST_SUITE(TestCertificateBundleFetcher)
+
+class CertificateBundleFetcherWrapper : public CertificateBundleFetcher
+{
+public:
+ CertificateBundleFetcherWrapper(Face& face)
+ : CertificateBundleFetcher(make_unique<CertificateFetcherFromNetwork>(face), face)
+ {
+ }
+};
+
+class Bundle
+{
+};
+
+class Cert
+{
+};
+
+class Timeout
+{
+};
+
+class Nack
+{
+};
+
+template<class Response>
+class CertificateBundleFetcherFixture : public HierarchicalValidatorFixture<ValidationPolicySimpleHierarchy,
+ CertificateBundleFetcherWrapper>
+{
+public:
+ CertificateBundleFetcherFixture()
+ : data("/Security/V2/ValidatorFixture/Sub1/Sub3/Data")
+ {
+ subSubIdentity = addSubCertificate("/Security/V2/ValidatorFixture/Sub1/Sub3", subIdentity);
+ cache.insert(subSubIdentity.getDefaultKey().getDefaultCertificate());
+
+ m_keyChain.sign(data, signingByIdentity(subSubIdentity));
+ bundleRegexMatcher = make_shared<RegexPatternListMatcher>("<>*<_BUNDLE><>*", nullptr);
+ processInterest = [this] (const Interest& interest) {
+ // check if the interest is for Bundle or individual certificates
+ if (bundleRegexMatcher->match(interest.getName(), 0, interest.getName().size())) {
+ makeResponse(interest);
+ }
+ else {
+ auto cert = cache.find(interest);
+ if (cert == nullptr) {
+ return;
+ }
+ face.receive(*cert);
+ }
+ };
+ }
+
+ void
+ makeResponse(const Interest& interest);
+
+public:
+ Data data;
+ Identity subSubIdentity;
+ shared_ptr<RegexPatternListMatcher> bundleRegexMatcher;
+};
+
+template<>
+void
+CertificateBundleFetcherFixture<Bundle>::makeResponse(const Interest& interest)
+{
+ Block certList = Block(tlv::Content);
+ Name bundleName(interest.getName());
+
+ if (!bundleName.get(-1).isSegment() || bundleName.get(-1).toSegment() == 0) {
+ Block subSubCert = subSubIdentity.getDefaultKey().getDefaultCertificate().wireEncode();
+ certList.push_back(subSubCert);
+
+ if (!bundleName.get(-1).isSegment()) {
+ bundleName
+ .appendVersion()
+ .appendSegment(0);
+ }
+ }
+ else {
+ Block subCert = subIdentity.getDefaultKey().getDefaultCertificate().wireEncode();
+ Block anchor = identity.getDefaultKey().getDefaultCertificate().wireEncode();
+ certList.push_back(subCert);
+ certList.push_back(anchor);
+ }
+
+ shared_ptr<Data> certBundle = make_shared<Data>();
+ certBundle->setName(bundleName);
+ certBundle->setFreshnessPeriod(100_s);
+ certBundle->setContent(certList);
+ certBundle->setFinalBlock(name::Component::fromSegment(1));
+
+ m_keyChain.sign(*certBundle, signingWithSha256());
+
+ face.receive(*certBundle);
+}
+
+template<>
+void
+CertificateBundleFetcherFixture<Timeout>::makeResponse(const Interest& interest)
+{
+ this->advanceClocks(200_s);
+}
+
+template<>
+void
+CertificateBundleFetcherFixture<Nack>::makeResponse(const Interest& interest)
+{
+ lp::Nack nack(interest);
+ nack.setHeader(lp::NackHeader().setReason(lp::NackReason::NO_ROUTE));
+ face.receive(nack);
+}
+
+BOOST_FIXTURE_TEST_CASE(ValidateSuccessWithBundle, CertificateBundleFetcherFixture<Bundle>)
+{
+ VALIDATE_SUCCESS(this->data, "Should get accepted, as interest brings the bundle segments");
+ BOOST_CHECK_EQUAL(this->face.sentInterests.size(), 2); // produced bundle has 2 segments
+
+ for (const auto& sentInterest : this->face.sentInterests) {
+ BOOST_CHECK(this->bundleRegexMatcher->match(sentInterest.getName(), 0, sentInterest.getName().size()));
+ }
+}
+
+using SuccessWithoutBundle = boost::mpl::vector<Nack, Timeout>;
+
+BOOST_FIXTURE_TEST_CASE_TEMPLATE(ValidateSuccessWithoutBundle, T, SuccessWithoutBundle, CertificateBundleFetcherFixture<T>)
+{
+ VALIDATE_SUCCESS(this->data, "Should get accepted, as interest brings the certs");
+ BOOST_CHECK_EQUAL(this->face.sentInterests.size(), 4); // since interest for Bundle fails, each cert is retrieved
+
+ bool toggle = true;
+ for (const auto& sentInterest : this->face.sentInterests) {
+ if (toggle) {
+ // every alternate interest is going to be that of a bundle
+ BOOST_CHECK(this->bundleRegexMatcher->match(sentInterest.getName(), 0, sentInterest.getName().size()));
+ }
+ else {
+ BOOST_CHECK(!this->bundleRegexMatcher->match(sentInterest.getName(), 0, sentInterest.getName().size()));
+ }
+ toggle = !toggle;
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestCertificateBundleFetcher
+BOOST_AUTO_TEST_SUITE_END() // V2
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace v2
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/v2/certificate-cache.t.cpp b/tests/unit/security/v2/certificate-cache.t.cpp
new file mode 100644
index 0000000..4ae3505
--- /dev/null
+++ b/tests/unit/security/v2/certificate-cache.t.cpp
@@ -0,0 +1,108 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/v2/certificate-cache.hpp"
+
+#include "../../identity-management-time-fixture.hpp"
+#include "boost-test.hpp"
+
+namespace ndn {
+namespace security {
+namespace v2 {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(V2)
+
+class CertificateCacheFixture : public ndn::tests::IdentityManagementTimeFixture
+{
+public:
+ CertificateCacheFixture()
+ : certCache(10_s)
+ {
+ identity = addIdentity("/TestCertificateCache/");
+ cert = identity.getDefaultKey().getDefaultCertificate();
+ }
+
+public:
+ CertificateCache certCache;
+ Identity identity;
+ Certificate cert;
+};
+
+BOOST_FIXTURE_TEST_SUITE(TestCertificateCache, CertificateCacheFixture)
+
+BOOST_AUTO_TEST_CASE(RemovalTime)
+{
+ // Cache lifetime is capped to 10 seconds during cache construction
+
+ BOOST_CHECK_NO_THROW(certCache.insert(cert));
+ BOOST_CHECK(certCache.find(cert.getName()) != nullptr);
+
+ advanceClocks(11_s, 1);
+ BOOST_CHECK(certCache.find(cert.getName()) == nullptr);
+
+ BOOST_CHECK_NO_THROW(certCache.insert(cert));
+ BOOST_CHECK(certCache.find(cert.getName()) != nullptr);
+
+ advanceClocks(5_s);
+ BOOST_CHECK(certCache.find(cert.getName()) != nullptr);
+
+ advanceClocks(15_s);
+ BOOST_CHECK(certCache.find(cert.getName()) == nullptr);
+}
+
+BOOST_AUTO_TEST_CASE(FindByInterest)
+{
+ BOOST_CHECK_NO_THROW(certCache.insert(cert));
+
+ // Find by interest
+ BOOST_CHECK(certCache.find(Interest(cert.getIdentity())) != nullptr);
+ BOOST_CHECK(certCache.find(Interest(cert.getKeyName())) != nullptr);
+ BOOST_CHECK(certCache.find(Interest(Name(cert.getName()).appendVersion())) == nullptr);
+
+ advanceClocks(12_s);
+ BOOST_CHECK(certCache.find(Interest(cert.getIdentity())) == nullptr);
+
+ Certificate cert3 = addCertificate(identity.getDefaultKey(), "3");
+ Certificate cert4 = addCertificate(identity.getDefaultKey(), "4");
+ Certificate cert5 = addCertificate(identity.getDefaultKey(), "5");
+
+ certCache.insert(cert3);
+ certCache.insert(cert4);
+ certCache.insert(cert5);
+
+ Interest interest4(cert3.getKeyName());
+ interest4.setExclude(Exclude().excludeOne(cert3.getName().at(Certificate::ISSUER_ID_OFFSET)));
+ BOOST_CHECK(certCache.find(interest4) != nullptr);
+ BOOST_CHECK_NE(certCache.find(interest4)->getName(), cert3.getName());
+
+ // TODO cover more cases with different interests
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestCertificateCache
+BOOST_AUTO_TEST_SUITE_END() // V2
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace v2
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/v2/certificate-fetcher-direct-fetch.t.cpp b/tests/unit/security/v2/certificate-fetcher-direct-fetch.t.cpp
new file mode 100644
index 0000000..68fe6b1
--- /dev/null
+++ b/tests/unit/security/v2/certificate-fetcher-direct-fetch.t.cpp
@@ -0,0 +1,205 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/v2/certificate-fetcher-direct-fetch.hpp"
+#include "security/v2/validation-policy-simple-hierarchy.hpp"
+#include "lp/nack.hpp"
+#include "lp/tags.hpp"
+
+#include "boost-test.hpp"
+#include "validator-fixture.hpp"
+
+#include <boost/range/adaptor/strided.hpp>
+#include <boost/range/adaptor/sliced.hpp>
+
+namespace ndn {
+namespace security {
+namespace v2 {
+namespace tests {
+
+using namespace ndn::tests;
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(V2)
+BOOST_AUTO_TEST_SUITE(TestCertificateFetcherDirectFetch)
+
+class Cert
+{
+};
+
+class Timeout
+{
+};
+
+class Nack
+{
+};
+
+template<class Response>
+class CertificateFetcherDirectFetchFixture : public HierarchicalValidatorFixture<ValidationPolicySimpleHierarchy,
+ CertificateFetcherDirectFetch>
+{
+public:
+ CertificateFetcherDirectFetchFixture()
+ : data("/Security/V2/ValidatorFixture/Sub1/Sub3/Data")
+ , interest("/Security/V2/ValidatorFixture/Sub1/Sub3/Interest")
+ , interestNoTag("/Security/V2/ValidatorFixture/Sub1/Sub3/Interest2")
+ {
+ Identity subSubIdentity = addSubCertificate("/Security/V2/ValidatorFixture/Sub1/Sub3", subIdentity);
+ cache.insert(subSubIdentity.getDefaultKey().getDefaultCertificate());
+
+ m_keyChain.sign(data, signingByIdentity(subSubIdentity));
+ m_keyChain.sign(interest, signingByIdentity(subSubIdentity));
+ m_keyChain.sign(interestNoTag, signingByIdentity(subSubIdentity));
+
+ data.setTag(make_shared<lp::IncomingFaceIdTag>(123));
+ interest.setTag(make_shared<lp::IncomingFaceIdTag>(123));
+
+ processInterest = [this] (const Interest& interest) {
+ auto nextHopFaceIdTag = interest.template getTag<lp::NextHopFaceIdTag>();
+ if (nextHopFaceIdTag == nullptr) {
+ makeResponse(interest); // respond only to the "infrastructure" interest
+ }
+ };
+ }
+
+ void
+ makeResponse(const Interest& interest);
+
+public:
+ Data data;
+ Interest interest;
+ Interest interestNoTag;
+};
+
+template<>
+void
+CertificateFetcherDirectFetchFixture<Cert>::makeResponse(const Interest& interest)
+{
+ auto cert = cache.find(interest);
+ if (cert == nullptr) {
+ return;
+ }
+ face.receive(*cert);
+}
+
+template<>
+void
+CertificateFetcherDirectFetchFixture<Timeout>::makeResponse(const Interest& interest)
+{
+ // do nothing
+}
+
+template<>
+void
+CertificateFetcherDirectFetchFixture<Nack>::makeResponse(const Interest& interest)
+{
+ lp::Nack nack(interest);
+ nack.setHeader(lp::NackHeader().setReason(lp::NackReason::NO_ROUTE));
+ face.receive(nack);
+}
+
+using Failures = boost::mpl::vector<Timeout, Nack>;
+
+BOOST_FIXTURE_TEST_CASE(ValidateSuccessData, CertificateFetcherDirectFetchFixture<Cert>)
+{
+ VALIDATE_SUCCESS(this->data, "Should get accepted, normal and/or direct interests bring certs");
+ BOOST_CHECK_EQUAL(this->face.sentInterests.size(), 4);
+
+ // odd interests
+ for (const auto& sentInterest : this->face.sentInterests | boost::adaptors::strided(2)) {
+ BOOST_CHECK(sentInterest.template getTag<lp::NextHopFaceIdTag>() != nullptr);
+ }
+
+ // even interests
+ for (const auto& sentInterest : this->face.sentInterests |
+ boost::adaptors::sliced(1, this->face.sentInterests.size()) |
+ boost::adaptors::strided(2)) {
+ BOOST_CHECK(sentInterest.template getTag<lp::NextHopFaceIdTag>() == nullptr);
+ }
+}
+
+BOOST_FIXTURE_TEST_CASE_TEMPLATE(ValidateFailureData, T, Failures, CertificateFetcherDirectFetchFixture<T>)
+{
+ VALIDATE_FAILURE(this->data, "Should fail, as all interests either NACKed or timeout");
+ // Direct fetcher sends two interests each time - to network and face
+ // 3 retries on nack or timeout (2 * (1 + 3) = 4)
+ BOOST_CHECK_EQUAL(this->face.sentInterests.size(), 8);
+
+ // odd interests
+ for (const auto& sentInterest : this->face.sentInterests | boost::adaptors::strided(2)) {
+ BOOST_CHECK(sentInterest.template getTag<lp::NextHopFaceIdTag>() != nullptr);
+ }
+
+ // even interests
+ for (const auto& sentInterest : this->face.sentInterests |
+ boost::adaptors::sliced(1, this->face.sentInterests.size()) |
+ boost::adaptors::strided(2)) {
+ BOOST_CHECK(sentInterest.template getTag<lp::NextHopFaceIdTag>() == nullptr);
+ }
+}
+
+BOOST_FIXTURE_TEST_CASE(ValidateSuccessInterest, CertificateFetcherDirectFetchFixture<Cert>)
+{
+ VALIDATE_SUCCESS(this->interest, "Should get accepted, normal and/or direct interests bring certs");
+ BOOST_CHECK_EQUAL(this->face.sentInterests.size(), 4);
+
+ // odd interests
+ for (const auto& sentInterest : this->face.sentInterests | boost::adaptors::strided(2)) {
+ BOOST_CHECK(sentInterest.template getTag<lp::NextHopFaceIdTag>() != nullptr);
+ }
+
+ // even interests
+ for (const auto& sentInterest : this->face.sentInterests |
+ boost::adaptors::sliced(1, this->face.sentInterests.size()) |
+ boost::adaptors::strided(2)) {
+ BOOST_CHECK(sentInterest.template getTag<lp::NextHopFaceIdTag>() == nullptr);
+ }
+}
+
+BOOST_FIXTURE_TEST_CASE_TEMPLATE(ValidateFailureInterest, T, Failures, CertificateFetcherDirectFetchFixture<T>)
+{
+ VALIDATE_FAILURE(this->interest, "Should fail, as all interests either NACKed or timeout");
+ // Direct fetcher sends two interests each time - to network and face
+ // 3 retries on nack or timeout (2 * (1 + 3) = 4)
+ BOOST_CHECK_EQUAL(this->face.sentInterests.size(), 8);
+
+ // odd interests
+ for (const auto& sentInterest : this->face.sentInterests | boost::adaptors::strided(2)) {
+ BOOST_CHECK(sentInterest.template getTag<lp::NextHopFaceIdTag>() != nullptr);
+ }
+
+ // even interests
+ for (const auto& sentInterest : this->face.sentInterests |
+ boost::adaptors::sliced(1, this->face.sentInterests.size()) |
+ boost::adaptors::strided(2)) {
+ BOOST_CHECK(sentInterest.template getTag<lp::NextHopFaceIdTag>() == nullptr);
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestCertificateFetcherDirectFetch
+BOOST_AUTO_TEST_SUITE_END() // V2
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace v2
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/v2/certificate-fetcher-from-network.t.cpp b/tests/unit/security/v2/certificate-fetcher-from-network.t.cpp
new file mode 100644
index 0000000..5a6b395
--- /dev/null
+++ b/tests/unit/security/v2/certificate-fetcher-from-network.t.cpp
@@ -0,0 +1,140 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/v2/certificate-fetcher-from-network.hpp"
+#include "security/v2/validation-policy-simple-hierarchy.hpp"
+#include "lp/nack.hpp"
+
+#include "boost-test.hpp"
+#include "validator-fixture.hpp"
+
+namespace ndn {
+namespace security {
+namespace v2 {
+namespace tests {
+
+using namespace ndn::tests;
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(V2)
+BOOST_AUTO_TEST_SUITE(TestCertificateFetcherFromNetwork)
+
+class Cert
+{
+};
+
+class Timeout
+{
+};
+
+class Nack
+{
+};
+
+template<class Response>
+class CertificateFetcherFromNetworkFixture : public HierarchicalValidatorFixture<ValidationPolicySimpleHierarchy,
+ CertificateFetcherFromNetwork>
+{
+public:
+ CertificateFetcherFromNetworkFixture()
+ : data("/Security/V2/ValidatorFixture/Sub1/Sub3/Data")
+ , interest("/Security/V2/ValidatorFixture/Sub1/Sub3/Interest")
+ {
+ Identity subSubIdentity = addSubCertificate("/Security/V2/ValidatorFixture/Sub1/Sub3", subIdentity);
+ cache.insert(subSubIdentity.getDefaultKey().getDefaultCertificate());
+
+ m_keyChain.sign(data, signingByIdentity(subSubIdentity));
+ m_keyChain.sign(interest, signingByIdentity(subSubIdentity));
+
+ processInterest = bind(&CertificateFetcherFromNetworkFixture<Response>::makeResponse, this, _1);
+ }
+
+ void
+ makeResponse(const Interest& interest);
+
+public:
+ Data data;
+ Interest interest;
+};
+
+template<>
+void
+CertificateFetcherFromNetworkFixture<Cert>::makeResponse(const Interest& interest)
+{
+ auto cert = cache.find(interest);
+ if (cert == nullptr) {
+ return;
+ }
+ face.receive(*cert);
+}
+
+template<>
+void
+CertificateFetcherFromNetworkFixture<Timeout>::makeResponse(const Interest& interest)
+{
+ // do nothing
+}
+
+template<>
+void
+CertificateFetcherFromNetworkFixture<Nack>::makeResponse(const Interest& interest)
+{
+ lp::Nack nack(interest);
+ nack.setHeader(lp::NackHeader().setReason(lp::NackReason::NO_ROUTE));
+ face.receive(nack);
+}
+
+using Failures = boost::mpl::vector<Timeout, Nack>;
+
+BOOST_FIXTURE_TEST_CASE(ValidateSuccess, CertificateFetcherFromNetworkFixture<Cert>)
+{
+ VALIDATE_SUCCESS(this->data, "Should get accepted, as normal interests bring cert");
+ BOOST_CHECK_EQUAL(this->face.sentInterests.size(), 2);
+ this->face.sentInterests.clear();
+
+ this->advanceClocks(1_h, 2); // expire validator caches
+
+ VALIDATE_SUCCESS(this->interest, "Should get accepted, as interests bring certs");
+ BOOST_CHECK_EQUAL(this->face.sentInterests.size(), 2);
+}
+
+BOOST_FIXTURE_TEST_CASE_TEMPLATE(ValidateFailure, T, Failures, CertificateFetcherFromNetworkFixture<T>)
+{
+ VALIDATE_FAILURE(this->data, "Should fail, as interests don't bring data");
+ // first interest + 3 retries
+ BOOST_CHECK_EQUAL(this->face.sentInterests.size(), 4);
+
+ this->face.sentInterests.clear();
+
+ this->advanceClocks(1_h, 2); // expire validator caches
+
+ VALIDATE_FAILURE(this->interest, "Should fail, as interests don't bring data");
+ BOOST_CHECK_EQUAL(this->face.sentInterests.size(), 4);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestCertificateFetcherFromNetwork
+BOOST_AUTO_TEST_SUITE_END() // V2
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace v2
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/v2/certificate-fetcher-offline.t.cpp b/tests/unit/security/v2/certificate-fetcher-offline.t.cpp
new file mode 100644
index 0000000..102a308
--- /dev/null
+++ b/tests/unit/security/v2/certificate-fetcher-offline.t.cpp
@@ -0,0 +1,75 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/v2/certificate-fetcher-offline.hpp"
+#include "security/v2/validation-policy-simple-hierarchy.hpp"
+
+#include "boost-test.hpp"
+#include "validator-fixture.hpp"
+
+namespace ndn {
+namespace security {
+namespace v2 {
+namespace tests {
+
+using namespace ndn::tests;
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(V2)
+
+class CertificateFetcherOfflineWrapper : public CertificateFetcherOffline
+{
+public:
+ CertificateFetcherOfflineWrapper(Face&)
+ {
+ }
+};
+
+using CertificateFetcherOfflineFixture = HierarchicalValidatorFixture<ValidationPolicySimpleHierarchy,
+ CertificateFetcherOfflineWrapper>;
+
+BOOST_FIXTURE_TEST_SUITE(TestCertificateFetcherOffline, CertificateFetcherOfflineFixture)
+
+typedef boost::mpl::vector<Interest, Data> Packets;
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(Validate, Packet, Packets)
+{
+ Packet unsignedPacket("/Security/V2/ValidatorFixture/Sub1/Packet");
+
+ Packet packet = unsignedPacket;
+ m_keyChain.sign(packet, signingByIdentity(subIdentity));
+ VALIDATE_FAILURE(packet, "Should fail, as no cert should be requested");
+ BOOST_CHECK_EQUAL(this->face.sentInterests.size(), 0);
+
+ packet = unsignedPacket;
+ m_keyChain.sign(packet, signingByIdentity(identity));
+ VALIDATE_SUCCESS(packet, "Should succeed, as signed by trust anchor");
+ BOOST_CHECK_EQUAL(this->face.sentInterests.size(), 0);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestCertificateFetcherOffline
+BOOST_AUTO_TEST_SUITE_END() // V2
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace v2
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/v2/certificate.t.cpp b/tests/unit/security/v2/certificate.t.cpp
new file mode 100644
index 0000000..e677aed
--- /dev/null
+++ b/tests/unit/security/v2/certificate.t.cpp
@@ -0,0 +1,291 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ *
+ * @author Zhiyi Zhang <dreamerbarrychang@gmail.com>
+ */
+
+#include "security/v2/certificate.hpp"
+
+#include "boost-test.hpp"
+#include "../../unit-test-time-fixture.hpp"
+
+#include <boost/lexical_cast.hpp>
+
+namespace ndn {
+namespace security {
+namespace v2 {
+namespace tests {
+
+using namespace ndn::tests;
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(V2)
+BOOST_FIXTURE_TEST_SUITE(TestCertificate, UnitTestTimeFixture)
+
+const uint8_t PUBLIC_KEY[] = {
+ 0x30, 0x81, 0x9d, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x01, 0x05, 0x00, 0x03, 0x81, 0x8b, 0x00, 0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0x9e,
+ 0x06, 0x3e, 0x47, 0x85, 0xb2, 0x34, 0x37, 0xaa, 0x85, 0x47, 0xac, 0x03, 0x24, 0x83, 0xb5,
+ 0x9c, 0xa8, 0x05, 0x3a, 0x24, 0x1e, 0xeb, 0x89, 0x01, 0xbb, 0xe9, 0x9b, 0xb2, 0xc3, 0x22,
+ 0xac, 0x68, 0xe3, 0xf0, 0x6c, 0x02, 0xce, 0x68, 0xa6, 0xc4, 0xd0, 0xa7, 0x06, 0x90, 0x9c,
+ 0xaa, 0x1b, 0x08, 0x1d, 0x8b, 0x43, 0x9a, 0x33, 0x67, 0x44, 0x6d, 0x21, 0xa3, 0x1b, 0x88,
+ 0x9a, 0x97, 0x5e, 0x59, 0xc4, 0x15, 0x0b, 0xd9, 0x2c, 0xbd, 0x51, 0x07, 0x61, 0x82, 0xad,
+ 0xc1, 0xb8, 0xd7, 0xbf, 0x9b, 0xcf, 0x7d, 0x24, 0xc2, 0x63, 0xf3, 0x97, 0x17, 0xeb, 0xfe,
+ 0x62, 0x25, 0xba, 0x5b, 0x4d, 0x8a, 0xc2, 0x7a, 0xbd, 0x43, 0x8a, 0x8f, 0xb8, 0xf2, 0xf1,
+ 0xc5, 0x6a, 0x30, 0xd3, 0x50, 0x8c, 0xc8, 0x9a, 0xdf, 0xef, 0xed, 0x35, 0xe7, 0x7a, 0x62,
+ 0xea, 0x76, 0x7c, 0xbb, 0x08, 0x26, 0xc7, 0x02, 0x01, 0x11
+};
+
+const uint8_t SIG_INFO[] = {
+ 0x16, 0x55, 0x1B, 0x01, 0x01, 0x1C, 0x26, 0x07, 0x24, 0x08, 0x03, 0x6E, 0x64, 0x6E, 0x08, 0x05,
+ 0x73, 0x69, 0x74, 0x65, 0x31, 0x08, 0x11, 0x6B, 0x73, 0x6B, 0x2D, 0x32, 0x35, 0x31, 0x36, 0x34,
+ 0x32, 0x35, 0x33, 0x37, 0x37, 0x30, 0x39, 0x34, 0x08, 0x03, 0x4B, 0x45, 0x59, 0xFD, 0x00, 0xFD,
+ 0x26, 0xFD, 0x00, 0xFE, 0x0F, 0x32, 0x30, 0x31, 0x35, 0x30, 0x38, 0x31, 0x34, 0x54, 0x32, 0x32,
+ 0x33, 0x37, 0x33, 0x39, 0xFD, 0x00, 0xFF, 0x0F, 0x32, 0x30, 0x31, 0x35, 0x30, 0x38, 0x31, 0x38,
+ 0x54, 0x32, 0x32, 0x33, 0x37, 0x33, 0x38
+};
+
+const uint8_t SIG_VALUE[] = {
+ 0x17, 0x80, // SignatureValue
+ 0x2f, 0xd6, 0xf1, 0x6e, 0x80, 0x6f, 0x10, 0xbe, 0xb1, 0x6f, 0x3e, 0x31, 0xec,
+ 0xe3, 0xb9, 0xea, 0x83, 0x30, 0x40, 0x03, 0xfc, 0xa0, 0x13, 0xd9, 0xb3, 0xc6,
+ 0x25, 0x16, 0x2d, 0xa6, 0x58, 0x41, 0x69, 0x62, 0x56, 0xd8, 0xb3, 0x6a, 0x38,
+ 0x76, 0x56, 0xea, 0x61, 0xb2, 0x32, 0x70, 0x1c, 0xb6, 0x4d, 0x10, 0x1d, 0xdc,
+ 0x92, 0x8e, 0x52, 0xa5, 0x8a, 0x1d, 0xd9, 0x96, 0x5e, 0xc0, 0x62, 0x0b, 0xcf,
+ 0x3a, 0x9d, 0x7f, 0xca, 0xbe, 0xa1, 0x41, 0x71, 0x85, 0x7a, 0x8b, 0x5d, 0xa9,
+ 0x64, 0xd6, 0x66, 0xb4, 0xe9, 0x8d, 0x0c, 0x28, 0x43, 0xee, 0xa6, 0x64, 0xe8,
+ 0x55, 0xf6, 0x1c, 0x19, 0x0b, 0xef, 0x99, 0x25, 0x1e, 0xdc, 0x78, 0xb3, 0xa7,
+ 0xaa, 0x0d, 0x14, 0x58, 0x30, 0xe5, 0x37, 0x6a, 0x6d, 0xdb, 0x56, 0xac, 0xa3,
+ 0xfc, 0x90, 0x7a, 0xb8, 0x66, 0x9c, 0x0e, 0xf6, 0xb7, 0x64, 0xd1
+};
+
+const uint8_t CERT[] = {
+ 0x06, 0xFD, 0x01, 0xBB, // Data
+ 0x07, 0x33, // Name /ndn/site1/KEY/ksk-1416425377094/0123/%FD%00%00%01I%C9%8B
+ 0x08, 0x03, 0x6E, 0x64, 0x6E,
+ 0x08, 0x05, 0x73, 0x69, 0x74, 0x65, 0x31,
+ 0x08, 0x03, 0x4B, 0x45, 0x59,
+ 0x08, 0x11,
+ 0x6B, 0x73, 0x6B, 0x2D, 0x31, 0x34, 0x31, 0x36, 0x34, 0x32, 0x35, 0x33, 0x37, 0x37, 0x30, 0x39,
+ 0x34,
+ 0x08, 0x04, 0x30, 0x31, 0x32, 0x33,
+ 0x08, 0x07, 0xFD, 0x00, 0x00, 0x01, 0x49, 0xC9, 0x8B,
+ 0x14, 0x09, // MetaInfo
+ 0x18, 0x01, 0x02, // ContentType = Key
+ 0x19, 0x04, 0x00, 0x36, 0xEE, 0x80, // FreshnessPeriod = 3600000 ms
+ 0x15, 0xA0, // Content
+ 0x30, 0x81, 0x9D, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01,
+ 0x05, 0x00, 0x03, 0x81, 0x8B, 0x00, 0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0x9E, 0x06, 0x3E,
+ 0x47, 0x85, 0xB2, 0x34, 0x37, 0xAA, 0x85, 0x47, 0xAC, 0x03, 0x24, 0x83, 0xB5, 0x9C, 0xA8, 0x05,
+ 0x3A, 0x24, 0x1E, 0xEB, 0x89, 0x01, 0xBB, 0xE9, 0x9B, 0xB2, 0xC3, 0x22, 0xAC, 0x68, 0xE3, 0xF0,
+ 0x6C, 0x02, 0xCE, 0x68, 0xA6, 0xC4, 0xD0, 0xA7, 0x06, 0x90, 0x9C, 0xAA, 0x1B, 0x08, 0x1D, 0x8B,
+ 0x43, 0x9A, 0x33, 0x67, 0x44, 0x6D, 0x21, 0xA3, 0x1B, 0x88, 0x9A, 0x97, 0x5E, 0x59, 0xC4, 0x15,
+ 0x0B, 0xD9, 0x2C, 0xBD, 0x51, 0x07, 0x61, 0x82, 0xAD, 0xC1, 0xB8, 0xD7, 0xBF, 0x9B, 0xCF, 0x7D,
+ 0x24, 0xC2, 0x63, 0xF3, 0x97, 0x17, 0xEB, 0xFE, 0x62, 0x25, 0xBA, 0x5B, 0x4D, 0x8A, 0xC2, 0x7A,
+ 0xBD, 0x43, 0x8A, 0x8F, 0xB8, 0xF2, 0xF1, 0xC5, 0x6A, 0x30, 0xD3, 0x50, 0x8C, 0xC8, 0x9A, 0xDF,
+ 0xEF, 0xED, 0x35, 0xE7, 0x7A, 0x62, 0xEA, 0x76, 0x7C, 0xBB, 0x08, 0x26, 0xC7, 0x02, 0x01, 0x11,
+ 0x16, 0x55, // SignatureInfo
+ 0x1B, 0x01, 0x01, // SignatureType
+ 0x1C, 0x26, // KeyLocator: /ndn/site1/KEY/ksk-2516425377094
+ 0x07, 0x24,
+ 0x08, 0x03, 0x6E, 0x64, 0x6E,
+ 0x08, 0x05, 0x73, 0x69, 0x74, 0x65, 0x31,
+ 0x08, 0x03, 0x4B, 0x45, 0x59,
+ 0x08, 0x11,
+ 0x6B, 0x73, 0x6B, 0x2D, 0x32, 0x35, 0x31, 0x36, 0x34, 0x32, 0x35, 0x33, 0x37, 0x37, 0x30, 0x39,
+ 0x34,
+ 0xFD, 0x00, 0xFD, 0x26, // ValidityPeriod: (20150814T223739, 20150818T223738)
+ 0xFD, 0x00, 0xFE, 0x0F,
+ 0x32, 0x30, 0x31, 0x35, 0x30, 0x38, 0x31, 0x34, 0x54, 0x32, 0x32, 0x33, 0x37, 0x33, 0x39,
+ 0xFD, 0x00, 0xFF, 0x0F,
+ 0x32, 0x30, 0x31, 0x35, 0x30, 0x38, 0x31, 0x38, 0x54, 0x32, 0x32, 0x33, 0x37, 0x33, 0x38,
+ 0x17, 0x80, // SignatureValue
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+Signature
+generateFakeSignature()
+{
+ Block block1(SIG_INFO, sizeof(SIG_INFO));
+ SignatureInfo signatureInfo(block1);
+
+ Name keyLocatorName("/ndn/site1/KEY/ksk-2516425377094");
+ KeyLocator keyLocator(keyLocatorName);
+ signatureInfo.setKeyLocator(keyLocator);
+
+ ValidityPeriod period(time::fromIsoString("20141111T050000"), time::fromIsoString("20141111T060000"));
+ signatureInfo.setValidityPeriod(period);
+
+ Signature signature(signatureInfo);
+ Block block2(SIG_VALUE, sizeof(SIG_VALUE));
+ signature.setValue(block2);
+
+ return signature;
+}
+
+BOOST_AUTO_TEST_CASE(Construction)
+{
+ Block block(CERT, sizeof(CERT));
+ Certificate certificate(block);
+
+ BOOST_CHECK_EQUAL(certificate.getName(), "/ndn/site1/KEY/ksk-1416425377094/0123/%FD%00%00%01I%C9%8B");
+ BOOST_CHECK_EQUAL(certificate.getKeyName(), "/ndn/site1/KEY/ksk-1416425377094");
+ BOOST_CHECK_EQUAL(certificate.getIdentity(), "/ndn/site1");
+ BOOST_CHECK_EQUAL(certificate.getIssuerId(), name::Component("0123"));
+ BOOST_CHECK_EQUAL(certificate.getKeyId(), name::Component("ksk-1416425377094"));
+ BOOST_CHECK_EQUAL(certificate.getSignature().getKeyLocator().getName(), "/ndn/site1/KEY/ksk-2516425377094");
+ BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(certificate.getValidityPeriod()), "(20150814T223739, 20150818T223738)");
+
+ BOOST_CHECK_THROW(certificate.getExtension(12345), ndn::SignatureInfo::Error);
+ BOOST_CHECK_NO_THROW(certificate.getPublicKey());
+
+ Data data(block);
+ Certificate certificate2(std::move(data));
+ BOOST_CHECK_EQUAL(certificate, certificate2);
+}
+
+BOOST_AUTO_TEST_CASE(Setters)
+{
+ Certificate certificate;
+ certificate.setName("/ndn/site1/KEY/ksk-1416425377094/0123/%FD%00%00%01I%C9%8B");
+ certificate.setFreshnessPeriod(1_h);
+ certificate.setContent(PUBLIC_KEY, sizeof(PUBLIC_KEY));
+ certificate.setSignature(generateFakeSignature());
+
+ BOOST_CHECK_EQUAL(certificate.getName(), "/ndn/site1/KEY/ksk-1416425377094/0123/%FD%00%00%01I%C9%8B");
+ BOOST_CHECK_EQUAL(certificate.getKeyName(), "/ndn/site1/KEY/ksk-1416425377094");
+ BOOST_CHECK_EQUAL(certificate.getIdentity(), "/ndn/site1");
+ BOOST_CHECK_EQUAL(certificate.getIssuerId(), name::Component("0123"));
+ BOOST_CHECK_EQUAL(certificate.getKeyId(), name::Component("ksk-1416425377094"));
+ BOOST_CHECK_EQUAL(certificate.getSignature().getKeyLocator().getName(), "/ndn/site1/KEY/ksk-2516425377094");
+ BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(certificate.getValidityPeriod()), "(20141111T050000, 20141111T060000)");
+
+ BOOST_CHECK_THROW(certificate.getExtension(12345), ndn::SignatureInfo::Error);
+ BOOST_CHECK_NO_THROW(certificate.getPublicKey());
+}
+
+BOOST_AUTO_TEST_CASE(ValidityPeriodChecking)
+{
+ Certificate certificate;
+ certificate.setName("/ndn/site1/KEY/ksk-1416425377094/0123/%FD%00%00%01I%C9%8B");
+ certificate.setFreshnessPeriod(1_h);
+ certificate.setContent(PUBLIC_KEY, sizeof(PUBLIC_KEY));
+ certificate.setSignature(generateFakeSignature());
+
+ BOOST_CHECK_EQUAL(certificate.isValid(), true);
+ BOOST_CHECK_EQUAL(certificate.isValid(time::fromIsoString("20141111T045959")), false);
+ BOOST_CHECK_EQUAL(certificate.isValid(time::fromIsoString("20141111T060001")), false);
+}
+
+// This fixture prepares a well-formed certificate. A test case then modifies one of the
+// fields, and verifies the Certificate class correctly identifies the certificate as
+// malformed.
+class InvalidCertFixture
+{
+public:
+ InvalidCertFixture()
+ {
+ Certificate certBase(Block(CERT, sizeof(CERT)));
+ BOOST_CHECK_NO_THROW((Certificate(certBase)));
+
+ m_certBase = Data(certBase);
+ m_certBase.setSignature(generateFakeSignature());
+
+ BOOST_CHECK_NO_THROW((Certificate(m_certBase)));
+ }
+
+public:
+ Data m_certBase;
+};
+
+BOOST_FIXTURE_TEST_CASE(InvalidName, InvalidCertFixture)
+{
+ Data data(m_certBase);
+ data.setName("/ndn/site1/ksk-1416425377094/0123/%FD%00%00%01I%C9%8B");
+ data.setSignature(generateFakeSignature());
+
+ BOOST_CHECK_THROW((Certificate(data)), Certificate::Error);
+ BOOST_CHECK_THROW((Certificate(std::move(data))), Certificate::Error);
+}
+
+BOOST_FIXTURE_TEST_CASE(InvalidType, InvalidCertFixture)
+{
+ Data data(m_certBase);
+ data.setContentType(tlv::ContentType_Blob);
+ data.setSignature(generateFakeSignature());
+
+ BOOST_CHECK_THROW((Certificate(data)), Certificate::Error);
+ BOOST_CHECK_THROW((Certificate(std::move(data))), Certificate::Error);
+}
+
+BOOST_FIXTURE_TEST_CASE(EmptyContent, InvalidCertFixture)
+{
+ Data data(m_certBase);
+ data.setContent(nullptr, 0);
+ data.setSignature(generateFakeSignature());
+
+ BOOST_CHECK_THROW((Certificate(data)), Certificate::Error);
+ BOOST_CHECK_THROW((Certificate(std::move(data))), Certificate::Error);
+
+ Certificate cert(m_certBase);
+ cert.setContent(nullptr, 0);
+ cert.setSignature(generateFakeSignature());
+ BOOST_CHECK_THROW(cert.getPublicKey(), Certificate::Error);
+}
+
+BOOST_AUTO_TEST_CASE(PrintCertificateInfo)
+{
+ const std::string expectedCertificateInfo = std::string(R"INFO(
+Certificate name:
+ /ndn/site1/KEY/ksk-1416425377094/0123/%FD%00%00%01I%C9%8B
+Validity:
+ NotBefore: 20150814T223739
+ NotAfter: 20150818T223738
+Public key bits:
+ MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCeBj5HhbI0N6qFR6wDJIO1nKgF
+ OiQe64kBu+mbssMirGjj8GwCzmimxNCnBpCcqhsIHYtDmjNnRG0hoxuImpdeWcQV
+ C9ksvVEHYYKtwbjXv5vPfSTCY/OXF+v+YiW6W02Kwnq9Q4qPuPLxxWow01CMyJrf
+ 7+0153pi6nZ8uwgmxwIBEQ==
+Signature Information:
+ Signature Type: SignatureSha256WithRsa
+ Key Locator: Name=/ndn/site1/KEY/ksk-2516425377094
+)INFO").substr(1);
+
+ Certificate certificate(Block(CERT, sizeof(CERT)));
+ BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(certificate), expectedCertificateInfo);
+
+ // @todo Check output formats of other certificates
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestCertificate
+BOOST_AUTO_TEST_SUITE_END() // V2
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace v2
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/v2/key-chain.t.cpp b/tests/unit/security/v2/key-chain.t.cpp
new file mode 100644
index 0000000..649ef7b
--- /dev/null
+++ b/tests/unit/security/v2/key-chain.t.cpp
@@ -0,0 +1,445 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/v2/key-chain.hpp"
+#include "security/signing-helpers.hpp"
+#include "security/verification-helpers.hpp"
+
+#include "boost-test.hpp"
+#include "identity-management-fixture.hpp"
+#include "../../test-home-env-saver.hpp"
+
+namespace ndn {
+namespace security {
+namespace v2 {
+namespace tests {
+
+using namespace ndn::tests;
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(V2)
+BOOST_FIXTURE_TEST_SUITE(TestKeyChain, TestHomeEnvSaver)
+
+template<class Path>
+class TestHomeAndPibFixture : public TestHomeFixture<Path>
+{
+public:
+ TestHomeAndPibFixture()
+ {
+ unsetenv("NDN_CLIENT_PIB");
+ unsetenv("NDN_CLIENT_TPM");
+ }
+
+ ~TestHomeAndPibFixture()
+ {
+ try {
+ const_cast<std::string&>(KeyChain::getDefaultPibLocator()).clear();
+ }
+ catch (const KeyChain::Error&) {
+ // ignore
+ }
+
+ try {
+ const_cast<std::string&>(KeyChain::getDefaultTpmLocator()).clear();
+ }
+ catch (const KeyChain::Error&) {
+ // ignore
+ }
+ }
+};
+
+struct PibPathConfigFileHome
+{
+ const std::string PATH = "build/config-file-home/";
+};
+
+BOOST_FIXTURE_TEST_CASE(ConstructorNormalConfig, TestHomeAndPibFixture<PibPathConfigFileHome>)
+{
+ createClientConf({"pib=pib-memory:", "tpm=tpm-memory:"});
+
+ BOOST_REQUIRE_NO_THROW(KeyChain());
+
+ KeyChain keyChain;
+ BOOST_CHECK_EQUAL(keyChain.getPib().getPibLocator(), "pib-memory:");
+ BOOST_CHECK_EQUAL(keyChain.getPib().getTpmLocator(), "tpm-memory:");
+ BOOST_CHECK_EQUAL(keyChain.getTpm().getTpmLocator(), "tpm-memory:");
+}
+
+struct PibPathConfigFileEmptyHome
+{
+ const std::string PATH = "build/config-file-empty-home/";
+};
+
+BOOST_FIXTURE_TEST_CASE(ConstructorEmptyConfig, TestHomeAndPibFixture<PibPathConfigFileEmptyHome>)
+{
+ createClientConf({"pib=pib-memory:"});
+
+#if defined(NDN_CXX_HAVE_OSX_FRAMEWORKS)
+ std::string oldHOME;
+ if (std::getenv("OLD_HOME"))
+ oldHOME = std::getenv("OLD_HOME");
+
+ std::string HOME;
+ if (std::getenv("HOME"))
+ HOME = std::getenv("HOME");
+
+ if (!oldHOME.empty())
+ setenv("HOME", oldHOME.c_str(), 1);
+ else
+ unsetenv("HOME");
+#endif
+
+ BOOST_REQUIRE_NO_THROW(KeyChain());
+ KeyChain keyChain;
+ BOOST_CHECK_EQUAL(keyChain.getPib().getPibLocator(), "pib-memory:");
+
+#if defined(NDN_CXX_HAVE_OSX_FRAMEWORKS)
+ BOOST_CHECK_EQUAL(keyChain.getPib().getTpmLocator(), "tpm-osxkeychain:");
+ BOOST_CHECK_EQUAL(keyChain.getTpm().getTpmLocator(), "tpm-osxkeychain:");
+#else
+ BOOST_CHECK_EQUAL(keyChain.getPib().getTpmLocator(), "tpm-file:");
+ BOOST_CHECK_EQUAL(keyChain.getTpm().getTpmLocator(), "tpm-file:");
+#endif
+
+#if defined(NDN_CXX_HAVE_OSX_FRAMEWORKS)
+ if (!HOME.empty())
+ setenv("HOME", HOME.c_str(), 1);
+ else
+ unsetenv("HOME");
+
+ if (!oldHOME.empty())
+ setenv("OLD_HOME", oldHOME.c_str(), 1);
+ else
+ unsetenv("OLD_HOME");
+#endif
+}
+
+struct PibPathConfigFileEmpty2Home
+{
+ const std::string PATH = "build/config-file-empty2-home/";
+};
+
+BOOST_FIXTURE_TEST_CASE(ConstructorEmpty2Config, TestHomeAndPibFixture<PibPathConfigFileEmpty2Home>)
+{
+ createClientConf({"tpm=tpm-memory:"});
+
+ BOOST_REQUIRE_NO_THROW(KeyChain());
+
+ KeyChain keyChain;
+ BOOST_CHECK_EQUAL(keyChain.getPib().getPibLocator(), "pib-sqlite3:");
+ BOOST_CHECK_EQUAL(keyChain.getPib().getTpmLocator(), "tpm-memory:");
+ BOOST_CHECK_EQUAL(keyChain.getTpm().getTpmLocator(), "tpm-memory:");
+}
+
+struct PibPathConfigFileMalformedHome
+{
+ const std::string PATH = "build/config-file-malformed-home/";
+};
+
+BOOST_FIXTURE_TEST_CASE(ConstructorMalConfig, TestHomeAndPibFixture<PibPathConfigFileMalformedHome>)
+{
+ createClientConf({"pib=lord", "tpm=ring"});
+
+ BOOST_REQUIRE_THROW(KeyChain(), KeyChain::Error); // Wrong configuration. Error expected.
+}
+
+struct PibPathConfigFileMalformed2Home
+{
+ const std::string PATH = "build/config-file-malformed2-home/";
+};
+
+BOOST_FIXTURE_TEST_CASE(ConstructorMal2Config, TestHomeAndPibFixture<PibPathConfigFileMalformed2Home>)
+{
+ createClientConf({"pib=pib-sqlite3:%PATH%", "tpm=just-wrong"});
+
+ BOOST_REQUIRE_THROW(KeyChain(), KeyChain::Error); // Wrong configuration. Error expected.
+}
+
+struct PibPathConfigFileNonCanonicalTpm
+{
+ const std::string PATH = "build/config-file-non-canonical-tpm/";
+};
+
+BOOST_FIXTURE_TEST_CASE(ConstructorNonCanonicalTpm, TestHomeAndPibFixture<PibPathConfigFileNonCanonicalTpm>) // Bug 4297
+{
+ createClientConf({"pib=pib-sqlite3:", "tpm=tpm-file"});
+
+ {
+ KeyChain keyChain;
+ keyChain.createIdentity("/test");
+ BOOST_CHECK_EQUAL(keyChain.getPib().getPibLocator(), "pib-sqlite3:");
+ BOOST_CHECK_EQUAL(keyChain.getTpm().getTpmLocator(), "tpm-file:");
+ }
+
+ {
+ KeyChain keyChain;
+ BOOST_CHECK_EQUAL(keyChain.getPib().getPibLocator(), "pib-sqlite3:");
+ BOOST_CHECK_EQUAL(keyChain.getTpm().getTpmLocator(), "tpm-file:");
+ BOOST_CHECK(keyChain.getPib().getIdentities().find("/test") != keyChain.getPib().getIdentities().end());
+ }
+}
+
+BOOST_AUTO_TEST_CASE(KeyChainWithCustomTpmAndPib)
+{
+ BOOST_REQUIRE_NO_THROW((KeyChain("pib-memory", "tpm-memory")));
+ BOOST_REQUIRE_NO_THROW((KeyChain("pib-memory:", "tpm-memory:")));
+ BOOST_REQUIRE_NO_THROW((KeyChain("pib-memory:/something", "tpm-memory:/something")));
+
+ KeyChain keyChain("pib-memory", "tpm-memory");
+ BOOST_CHECK_EQUAL(keyChain.getPib().getPibLocator(), "pib-memory:");
+ BOOST_CHECK_EQUAL(keyChain.getPib().getTpmLocator(), "tpm-memory:");
+ BOOST_CHECK_EQUAL(keyChain.getTpm().getTpmLocator(), "tpm-memory:");
+}
+
+BOOST_FIXTURE_TEST_CASE(Management, IdentityManagementFixture)
+{
+ Name identityName("/test/id");
+ Name identity2Name("/test/id2");
+
+ BOOST_CHECK_EQUAL(m_keyChain.getPib().getIdentities().size(), 0);
+ BOOST_REQUIRE_THROW(m_keyChain.getPib().getDefaultIdentity(), Pib::Error);
+
+ // Create identity
+ Identity id = m_keyChain.createIdentity(identityName);
+ BOOST_CHECK(id);
+ BOOST_CHECK(m_keyChain.getPib().getIdentities().find(identityName) != m_keyChain.getPib().getIdentities().end());
+ // The first added identity becomes the default identity
+ BOOST_REQUIRE_NO_THROW(m_keyChain.getPib().getDefaultIdentity());
+ // The default key of the added identity must exist
+ Key key;
+ BOOST_REQUIRE_NO_THROW(key = id.getDefaultKey());
+ // The default certificate of the default key must exist
+ BOOST_REQUIRE_NO_THROW(key.getDefaultCertificate());
+
+ // Delete key
+ Name key1Name = key.getName();
+ BOOST_CHECK_NO_THROW(id.getKey(key1Name));
+ BOOST_CHECK_EQUAL(id.getKeys().size(), 1);
+ m_keyChain.deleteKey(id, key);
+ // The key instance should not be valid any more
+ BOOST_CHECK(!key);
+ BOOST_CHECK_THROW(id.getKey(key1Name), Pib::Error);
+ BOOST_CHECK_EQUAL(id.getKeys().size(), 0);
+
+ // Create another key
+ m_keyChain.createKey(id);
+ // The added key becomes the default key.
+ BOOST_REQUIRE_NO_THROW(id.getDefaultKey());
+ Key key2 = id.getDefaultKey();
+ BOOST_REQUIRE(key2);
+ BOOST_CHECK_NE(key2.getName(), key1Name);
+ BOOST_CHECK_EQUAL(id.getKeys().size(), 1);
+ BOOST_REQUIRE_NO_THROW(key2.getDefaultCertificate());
+
+ // Create the third key
+ Key key3 = m_keyChain.createKey(id);
+ BOOST_CHECK_NE(key3.getName(), key2.getName());
+ // The added key will not be the default key, because the default key already exists
+ BOOST_CHECK_EQUAL(id.getDefaultKey().getName(), key2.getName());
+ BOOST_CHECK_EQUAL(id.getKeys().size(), 2);
+ BOOST_REQUIRE_NO_THROW(key3.getDefaultCertificate());
+
+ // Delete cert
+ BOOST_CHECK_EQUAL(key3.getCertificates().size(), 1);
+ Certificate key3Cert1 = *key3.getCertificates().begin();
+ Name key3CertName = key3Cert1.getName();
+ m_keyChain.deleteCertificate(key3, key3CertName);
+ BOOST_CHECK_EQUAL(key3.getCertificates().size(), 0);
+ BOOST_REQUIRE_THROW(key3.getDefaultCertificate(), Pib::Error);
+
+ // Add cert
+ m_keyChain.addCertificate(key3, key3Cert1);
+ BOOST_CHECK_EQUAL(key3.getCertificates().size(), 1);
+ BOOST_REQUIRE_NO_THROW(key3.getDefaultCertificate());
+ m_keyChain.addCertificate(key3, key3Cert1); // overwriting the cert should work
+ BOOST_CHECK_EQUAL(key3.getCertificates().size(), 1);
+ // Add another cert
+ Certificate key3Cert2 = key3Cert1;
+ Name key3Cert2Name = key3.getName();
+ key3Cert2Name.append("Self");
+ key3Cert2Name.appendVersion();
+ key3Cert2.setName(key3Cert2Name);
+ m_keyChain.addCertificate(key3, key3Cert2);
+ BOOST_CHECK_EQUAL(key3.getCertificates().size(), 2);
+
+ // Default certificate setting
+ BOOST_CHECK_EQUAL(key3.getDefaultCertificate().getName(), key3CertName);
+ m_keyChain.setDefaultCertificate(key3, key3Cert2);
+ BOOST_CHECK_EQUAL(key3.getDefaultCertificate().getName(), key3Cert2Name);
+
+ // Default key setting
+ BOOST_CHECK_EQUAL(id.getDefaultKey().getName(), key2.getName());
+ m_keyChain.setDefaultKey(id, key3);
+ BOOST_CHECK_EQUAL(id.getDefaultKey().getName(), key3.getName());
+
+ // Default identity setting
+ Identity id2 = m_keyChain.createIdentity(identity2Name);
+ BOOST_CHECK_EQUAL(m_keyChain.getPib().getDefaultIdentity().getName(), id.getName());
+ m_keyChain.setDefaultIdentity(id2);
+ BOOST_CHECK_EQUAL(m_keyChain.getPib().getDefaultIdentity().getName(), id2.getName());
+
+ // Delete identity
+ m_keyChain.deleteIdentity(id);
+ // The identity instance should not be valid any more
+ BOOST_CHECK(!id);
+ BOOST_REQUIRE_THROW(m_keyChain.getPib().getIdentity(identityName), Pib::Error);
+ BOOST_CHECK(m_keyChain.getPib().getIdentities().find(identityName) == m_keyChain.getPib().getIdentities().end());
+}
+
+BOOST_FIXTURE_TEST_CASE(GeneralSigningInterface, IdentityManagementFixture)
+{
+ Identity id = addIdentity("/id");
+ Key key = id.getDefaultKey();
+ Certificate cert = key.getDefaultCertificate();
+
+ std::list<SigningInfo> signingInfos = {
+ SigningInfo(),
+
+ SigningInfo(SigningInfo::SIGNER_TYPE_ID, id.getName()),
+ signingByIdentity(id.getName()),
+
+ SigningInfo(id),
+ signingByIdentity(id),
+
+ SigningInfo(SigningInfo::SIGNER_TYPE_KEY, key.getName()),
+ signingByKey(key.getName()),
+
+ SigningInfo(key),
+ signingByKey(key),
+
+ SigningInfo(SigningInfo::SIGNER_TYPE_CERT, cert.getName()),
+ signingByCertificate(cert.getName()),
+ signingByCertificate(cert),
+
+ SigningInfo(SigningInfo::SIGNER_TYPE_SHA256),
+ signingWithSha256()
+ };
+
+ for (const auto& signingInfo : signingInfos) {
+ BOOST_TEST_MESSAGE("SigningInfo: " << signingInfo);
+ Data data("/data");
+ Interest interest("/interest");
+
+ if (signingInfo.getSignerType() == SigningInfo::SIGNER_TYPE_NULL) {
+ m_keyChain.sign(data);
+ m_keyChain.sign(interest);
+ }
+ else {
+ m_keyChain.sign(data, signingInfo);
+ m_keyChain.sign(interest, signingInfo);
+ }
+
+ Signature interestSignature(interest.getName()[-2].blockFromValue(), interest.getName()[-1].blockFromValue());
+
+ if (signingInfo.getSignerType() == SigningInfo::SIGNER_TYPE_SHA256) {
+ BOOST_CHECK_EQUAL(data.getSignature().getType(), tlv::DigestSha256);
+ BOOST_CHECK_EQUAL(interestSignature.getType(), tlv::DigestSha256);
+
+ BOOST_CHECK(verifyDigest(data, DigestAlgorithm::SHA256));
+ BOOST_CHECK(verifyDigest(interest, DigestAlgorithm::SHA256));
+ }
+ else {
+ BOOST_CHECK_EQUAL(data.getSignature().getType(), tlv::SignatureSha256WithEcdsa);
+ BOOST_CHECK_EQUAL(interestSignature.getType(), tlv::SignatureSha256WithEcdsa);
+
+ BOOST_CHECK_EQUAL(data.getSignature().getKeyLocator().getName(), cert.getName().getPrefix(-2));
+ BOOST_CHECK_EQUAL(interestSignature.getKeyLocator().getName(), cert.getName().getPrefix(-2));
+
+ BOOST_CHECK(verifySignature(data, key));
+ BOOST_CHECK(verifySignature(interest, key));
+ }
+ }
+}
+
+BOOST_FIXTURE_TEST_CASE(PublicKeySigningDefaults, IdentityManagementFixture)
+{
+ Data data("/test/data");
+
+ // Identity will be created with generated key and self-signed cert with default parameters
+ BOOST_CHECK_THROW(m_keyChain.sign(data, signingByIdentity("/non-existing/identity")), KeyChain::InvalidSigningInfoError);
+
+ // Create identity with EC key and the corresponding self-signed certificate
+ Identity id = addIdentity("/ndn/test/ec", EcKeyParams());
+ BOOST_CHECK_NO_THROW(m_keyChain.sign(data, signingByIdentity(id.getName())));
+ BOOST_CHECK_EQUAL(data.getSignature().getType(),
+ KeyChain::getSignatureType(EcKeyParams().getKeyType(), DigestAlgorithm::SHA256));
+ BOOST_CHECK(id.getName().isPrefixOf(data.getSignature().getKeyLocator().getName()));
+
+ // Create identity with RSA key and the corresponding self-signed certificate
+ id = addIdentity("/ndn/test/rsa", RsaKeyParams());
+ BOOST_CHECK_NO_THROW(m_keyChain.sign(data, signingByIdentity(id.getName())));
+ BOOST_CHECK_EQUAL(data.getSignature().getType(),
+ KeyChain::getSignatureType(RsaKeyParams().getKeyType(), DigestAlgorithm::SHA256));
+ BOOST_CHECK(id.getName().isPrefixOf(data.getSignature().getKeyLocator().getName()));
+}
+
+BOOST_FIXTURE_TEST_CASE(ExportImport, IdentityManagementFixture)
+{
+ Identity id = addIdentity("/TestKeyChain/ExportIdentity/");
+ Certificate cert = id.getDefaultKey().getDefaultCertificate();
+
+ shared_ptr<SafeBag> exported = m_keyChain.exportSafeBag(cert, "1234", 4);
+ Block block = exported->wireEncode();
+
+ m_keyChain.deleteIdentity(id);
+ BOOST_CHECK_THROW(m_keyChain.exportSafeBag(cert, "1234", 4), KeyChain::Error);
+
+ BOOST_CHECK_EQUAL(m_keyChain.getTpm().hasKey(cert.getKeyName()), false);
+ BOOST_CHECK_EQUAL(m_keyChain.getPib().getIdentities().size(), 0);
+
+ SafeBag imported;
+ imported.wireDecode(block);
+ m_keyChain.importSafeBag(imported, "1234", 4);
+ BOOST_CHECK_THROW(m_keyChain.importSafeBag(imported, "1234", 4), KeyChain::Error);
+
+ BOOST_CHECK_EQUAL(m_keyChain.getTpm().hasKey(cert.getKeyName()), true);
+ BOOST_CHECK_EQUAL(m_keyChain.getPib().getIdentities().size(), 1);
+ BOOST_REQUIRE_NO_THROW(m_keyChain.getPib().getIdentity(cert.getIdentity()));
+ Identity newId = m_keyChain.getPib().getIdentity(cert.getIdentity());
+ BOOST_CHECK_EQUAL(newId.getKeys().size(), 1);
+ BOOST_REQUIRE_NO_THROW(newId.getKey(cert.getKeyName()));
+ Key newKey = newId.getKey(cert.getKeyName());
+ BOOST_CHECK_EQUAL(newKey.getCertificates().size(), 1);
+ BOOST_REQUIRE_NO_THROW(newKey.getCertificate(cert.getName()));
+
+ m_keyChain.deleteIdentity(newId);
+ BOOST_CHECK_EQUAL(m_keyChain.getPib().getIdentities().size(), 0);
+ BOOST_CHECK_EQUAL(m_keyChain.getTpm().hasKey(cert.getKeyName()), false);
+}
+
+BOOST_FIXTURE_TEST_CASE(SelfSignedCertValidity, IdentityManagementFixture)
+{
+ Certificate cert = addIdentity("/Security/V2/TestKeyChain/SelfSignedCertValidity")
+ .getDefaultKey()
+ .getDefaultCertificate();
+ BOOST_CHECK(cert.isValid());
+ BOOST_CHECK(cert.isValid(time::system_clock::now() + 10 * 365_days));
+ BOOST_CHECK_GT(cert.getValidityPeriod().getPeriod().second, time::system_clock::now() + 10 * 365_days);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestKeyChain
+BOOST_AUTO_TEST_SUITE_END() // V2
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace v2
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/v2/trust-anchor-container.t.cpp b/tests/unit/security/v2/trust-anchor-container.t.cpp
new file mode 100644
index 0000000..efd6ca3
--- /dev/null
+++ b/tests/unit/security/v2/trust-anchor-container.t.cpp
@@ -0,0 +1,198 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/v2/trust-anchor-container.hpp"
+#include "util/io.hpp"
+
+#include "../../identity-management-time-fixture.hpp"
+#include "boost-test.hpp"
+
+#include <boost/filesystem.hpp>
+
+namespace ndn {
+namespace security {
+namespace v2 {
+namespace tests {
+
+using namespace ndn::tests;
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(V2)
+
+/**
+ * This fixture creates a directory and prepares two certificates.
+ * cert1 is written to a file under the directory, while cert2 is not.
+ */
+class AnchorContainerTestFixture : public IdentityManagementTimeFixture
+{
+public:
+ AnchorContainerTestFixture()
+ {
+ namespace fs = boost::filesystem;
+
+ fs::create_directory(fs::path(UNIT_TEST_CONFIG_PATH));
+
+ certDirPath = fs::path(UNIT_TEST_CONFIG_PATH) / "test-cert-dir";
+ fs::create_directory(certDirPath);
+
+ certPath1 = fs::path(UNIT_TEST_CONFIG_PATH) / "test-cert-dir" / "trust-anchor-1.cert";
+ certPath2 = fs::path(UNIT_TEST_CONFIG_PATH) / "test-cert-dir" / "trust-anchor-2.cert";
+
+ identity1 = addIdentity("/TestAnchorContainer/First");
+ cert1 = identity1.getDefaultKey().getDefaultCertificate();
+ saveCertToFile(cert1, certPath1.string());
+
+ identity2 = addIdentity("/TestAnchorContainer/Second");
+ cert2 = identity2.getDefaultKey().getDefaultCertificate();
+ saveCertToFile(cert2, certPath2.string());
+ }
+
+ ~AnchorContainerTestFixture()
+ {
+ boost::filesystem::remove_all(UNIT_TEST_CONFIG_PATH);
+ }
+
+public:
+ TrustAnchorContainer anchorContainer;
+
+ boost::filesystem::path certDirPath;
+ boost::filesystem::path certPath1;
+ boost::filesystem::path certPath2;
+
+ Identity identity1;
+ Identity identity2;
+
+ Certificate cert1;
+ Certificate cert2;
+};
+
+BOOST_FIXTURE_TEST_SUITE(TestTrustAnchorContainer, AnchorContainerTestFixture)
+
+// one static group and one dynamic group created from file
+BOOST_AUTO_TEST_CASE(Insert)
+{
+ // Static
+ anchorContainer.insert("group1", Certificate(cert1));
+ BOOST_CHECK(anchorContainer.find(cert1.getName()) != nullptr);
+ BOOST_CHECK(anchorContainer.find(identity1.getName()) != nullptr);
+ const Certificate* cert = anchorContainer.find(cert1.getName());
+ BOOST_CHECK_NO_THROW(anchorContainer.insert("group1", Certificate(cert1)));
+ BOOST_CHECK_EQUAL(cert, anchorContainer.find(cert1.getName())); // still the same instance of the certificate
+ // cannot add dynamic group when static already exists
+ BOOST_CHECK_THROW(anchorContainer.insert("group1", certPath1.string(), 1_s), TrustAnchorContainer::Error);
+ BOOST_CHECK_EQUAL(anchorContainer.getGroup("group1").size(), 1);
+ BOOST_CHECK_EQUAL(anchorContainer.size(), 1);
+
+ // From file
+ anchorContainer.insert("group2", certPath2.string(), 1_s);
+ BOOST_CHECK(anchorContainer.find(cert2.getName()) != nullptr);
+ BOOST_CHECK(anchorContainer.find(identity2.getName()) != nullptr);
+ BOOST_CHECK_THROW(anchorContainer.insert("group2", Certificate(cert2)), TrustAnchorContainer::Error);
+ BOOST_CHECK_THROW(anchorContainer.insert("group2", certPath2.string(), 1_s), TrustAnchorContainer::Error);
+ BOOST_CHECK_EQUAL(anchorContainer.getGroup("group2").size(), 1);
+ BOOST_CHECK_EQUAL(anchorContainer.size(), 2);
+
+ boost::filesystem::remove(certPath2);
+ advanceClocks(1_s, 11);
+
+ BOOST_CHECK(anchorContainer.find(identity2.getName()) == nullptr);
+ BOOST_CHECK(anchorContainer.find(cert2.getName()) == nullptr);
+ BOOST_CHECK_EQUAL(anchorContainer.getGroup("group2").size(), 0);
+ BOOST_CHECK_EQUAL(anchorContainer.size(), 1);
+
+ TrustAnchorGroup& group = anchorContainer.getGroup("group1");
+ auto staticGroup = dynamic_cast<StaticTrustAnchorGroup*>(&group);
+ BOOST_REQUIRE(staticGroup != nullptr);
+ BOOST_CHECK_EQUAL(staticGroup->size(), 1);
+ staticGroup->remove(cert1.getName());
+ BOOST_CHECK_EQUAL(staticGroup->size(), 0);
+ BOOST_CHECK_EQUAL(anchorContainer.size(), 0);
+
+ BOOST_CHECK_THROW(anchorContainer.getGroup("non-existing-group"), TrustAnchorContainer::Error);
+}
+
+BOOST_AUTO_TEST_CASE(DynamicAnchorFromDir)
+{
+ boost::filesystem::remove(certPath2);
+
+ anchorContainer.insert("group", certDirPath.string(), 1_s, true /* isDir */);
+
+ BOOST_CHECK(anchorContainer.find(identity1.getName()) != nullptr);
+ BOOST_CHECK(anchorContainer.find(identity2.getName()) == nullptr);
+ BOOST_CHECK_EQUAL(anchorContainer.getGroup("group").size(), 1);
+
+ saveCertToFile(cert2, certPath2.string());
+
+ advanceClocks(100_ms, 11);
+
+ BOOST_CHECK(anchorContainer.find(identity1.getName()) != nullptr);
+ BOOST_CHECK(anchorContainer.find(identity2.getName()) != nullptr);
+ BOOST_CHECK_EQUAL(anchorContainer.getGroup("group").size(), 2);
+
+ boost::filesystem::remove_all(certDirPath);
+
+ advanceClocks(100_ms, 11);
+
+ BOOST_CHECK(anchorContainer.find(identity1.getName()) == nullptr);
+ BOOST_CHECK(anchorContainer.find(identity2.getName()) == nullptr);
+ BOOST_CHECK_EQUAL(anchorContainer.getGroup("group").size(), 0);
+}
+
+BOOST_FIXTURE_TEST_CASE(FindByInterest, AnchorContainerTestFixture)
+{
+ anchorContainer.insert("group1", certPath1.string(), 1_s);
+ Interest interest(identity1.getName());
+ BOOST_CHECK(anchorContainer.find(interest) != nullptr);
+ Interest interest1(identity1.getName().getPrefix(-1));
+ BOOST_CHECK(anchorContainer.find(interest1) != nullptr);
+ Interest interest2(Name(identity1.getName()).appendVersion());
+ BOOST_CHECK(anchorContainer.find(interest2) == nullptr);
+
+ Certificate cert3 = addCertificate(identity1.getDefaultKey(), "3");
+ Certificate cert4 = addCertificate(identity1.getDefaultKey(), "4");
+ Certificate cert5 = addCertificate(identity1.getDefaultKey(), "5");
+
+ Certificate cert3Copy = cert3;
+ anchorContainer.insert("group2", std::move(cert3Copy));
+ anchorContainer.insert("group3", std::move(cert4));
+ anchorContainer.insert("group4", std::move(cert5));
+
+ Interest interest3(cert3.getKeyName());
+ const Certificate* foundCert = anchorContainer.find(interest3);
+ BOOST_REQUIRE(foundCert != nullptr);
+ BOOST_CHECK(interest3.getName().isPrefixOf(foundCert->getName()));
+ BOOST_CHECK_EQUAL(foundCert->getName(), cert3.getName());
+
+ interest3.setExclude(Exclude().excludeOne(cert3.getName().at(Certificate::ISSUER_ID_OFFSET)));
+ foundCert = anchorContainer.find(interest3);
+ BOOST_REQUIRE(foundCert != nullptr);
+ BOOST_CHECK(interest3.getName().isPrefixOf(foundCert->getName()));
+ BOOST_CHECK_NE(foundCert->getName(), cert3.getName());
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestTrustAnchorContainer
+BOOST_AUTO_TEST_SUITE_END() // Detail
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace v2
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/v2/validation-error.t.cpp b/tests/unit/security/v2/validation-error.t.cpp
new file mode 100644
index 0000000..1db3aac
--- /dev/null
+++ b/tests/unit/security/v2/validation-error.t.cpp
@@ -0,0 +1,61 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/v2/validation-error.hpp"
+
+#include "boost-test.hpp"
+#include <boost/lexical_cast.hpp>
+
+namespace ndn {
+namespace security {
+namespace v2 {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(V2)
+BOOST_AUTO_TEST_SUITE(TestValidationError)
+
+BOOST_AUTO_TEST_CASE(Basic)
+{
+ ValidationError e1{ValidationError::Code::INVALID_SIGNATURE};
+ BOOST_CHECK_EQUAL(e1.getCode(), 1);
+ BOOST_CHECK_EQUAL(e1.getInfo(), "");
+ BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(e1), "Invalid signature");
+
+ ValidationError e2{ValidationError::Code::NO_SIGNATURE, "message"};
+ BOOST_CHECK_EQUAL(e2.getCode(), 2);
+ BOOST_CHECK_EQUAL(e2.getInfo(), "message");
+ BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(e2), "Missing signature (message)");
+
+ ValidationError e3{65535, "other message"};
+ BOOST_CHECK_EQUAL(e3.getCode(), 65535);
+ BOOST_CHECK_EQUAL(e3.getInfo(), "other message");
+ BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(e3), "Custom error code 65535 (other message)");
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestValidationError
+BOOST_AUTO_TEST_SUITE_END() // V2
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace v2
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/v2/validation-policy-accept-all.t.cpp b/tests/unit/security/v2/validation-policy-accept-all.t.cpp
new file mode 100644
index 0000000..61466d6
--- /dev/null
+++ b/tests/unit/security/v2/validation-policy-accept-all.t.cpp
@@ -0,0 +1,79 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/v2/validation-policy-accept-all.hpp"
+
+#include "boost-test.hpp"
+#include "validator-fixture.hpp"
+
+#include <boost/mpl/vector.hpp>
+
+namespace ndn {
+namespace security {
+namespace v2 {
+namespace tests {
+
+using namespace ndn::tests;
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(V2)
+
+class ValidationPolicyAcceptAllFixture : public ValidatorFixture<ValidationPolicyAcceptAll>
+{
+public:
+ ValidationPolicyAcceptAllFixture()
+ {
+ identity = addIdentity("/Security/V2/TestValidationPolicyAcceptAll");
+ // don't add trust anchors
+ }
+
+public:
+ Identity identity;
+};
+
+BOOST_FIXTURE_TEST_SUITE(TestValidationPolicyAcceptAll, ValidationPolicyAcceptAllFixture)
+
+typedef boost::mpl::vector<Interest, Data> Packets;
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(Validate, Packet, Packets)
+{
+ Packet unsignedPacket("/Security/V2/TestValidationPolicyAcceptAll/Sub/Packet");
+
+ Packet packet = unsignedPacket;
+ VALIDATE_SUCCESS(packet, "Should accept unsigned");
+
+ packet = unsignedPacket;
+ m_keyChain.sign(packet, signingWithSha256());
+ VALIDATE_SUCCESS(packet, "Should accept Sha256Digest signature");
+
+ packet = unsignedPacket;
+ m_keyChain.sign(packet, signingByIdentity(identity));
+ VALIDATE_SUCCESS(packet, "Should accept signature while no trust anchors configured");
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestValidationPolicyAcceptAll
+BOOST_AUTO_TEST_SUITE_END() // V2
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace v2
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/v2/validation-policy-command-interest.t.cpp b/tests/unit/security/v2/validation-policy-command-interest.t.cpp
new file mode 100644
index 0000000..7bd42ea
--- /dev/null
+++ b/tests/unit/security/v2/validation-policy-command-interest.t.cpp
@@ -0,0 +1,485 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/v2/validation-policy-command-interest.hpp"
+#include "security/v2/validation-policy-simple-hierarchy.hpp"
+#include "security/v2/validation-policy-accept-all.hpp"
+#include "security/command-interest-signer.hpp"
+#include "security/signing-helpers.hpp"
+
+#include "boost-test.hpp"
+#include "validator-fixture.hpp"
+#include "make-interest-data.hpp"
+
+#include <boost/lexical_cast.hpp>
+#include <boost/mpl/vector.hpp>
+
+namespace ndn {
+namespace security {
+namespace v2 {
+namespace tests {
+
+using namespace ndn::tests;
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(V2)
+
+class DefaultOptions
+{
+public:
+ static ValidationPolicyCommandInterest::Options
+ getOptions()
+ {
+ return {};
+ }
+};
+
+template<class T, class InnerPolicy>
+class CommandInterestPolicyWrapper : public ValidationPolicyCommandInterest
+{
+public:
+ CommandInterestPolicyWrapper()
+ : ValidationPolicyCommandInterest(make_unique<InnerPolicy>(), T::getOptions())
+ {
+ }
+};
+
+template<class T, class InnerPolicy = ValidationPolicySimpleHierarchy>
+class ValidationPolicyCommandInterestFixture : public HierarchicalValidatorFixture<CommandInterestPolicyWrapper<T, InnerPolicy>>
+{
+public:
+ ValidationPolicyCommandInterestFixture()
+ : m_signer(this->m_keyChain)
+ {
+ }
+
+ Interest
+ makeCommandInterest(const Identity& identity)
+ {
+ return m_signer.makeCommandInterest(Name(identity.getName()).append("CMD"),
+ signingByIdentity(identity));
+ }
+
+public:
+ CommandInterestSigner m_signer;
+};
+
+BOOST_FIXTURE_TEST_SUITE(TestValidationPolicyCommandInterest, ValidationPolicyCommandInterestFixture<DefaultOptions>)
+
+BOOST_AUTO_TEST_SUITE(Accepts)
+
+BOOST_AUTO_TEST_CASE(Basic)
+{
+ auto i1 = makeCommandInterest(identity);
+ VALIDATE_SUCCESS(i1, "Should succeed (within grace period)");
+ VALIDATE_FAILURE(i1, "Should fail (replay attack)");
+
+ advanceClocks(5_ms);
+ auto i2 = makeCommandInterest(identity);
+ VALIDATE_SUCCESS(i2, "Should succeed (timestamp larger than previous)");
+
+ auto i3 = m_signer.makeCommandInterest(Name(identity.getName()).append("CMD"), signingWithSha256());
+ VALIDATE_FAILURE(i3, "Should fail (Sha256 signature violates policy)");
+}
+
+BOOST_AUTO_TEST_CASE(DataPassthru)
+{
+ Data d1("/Security/V2/ValidatorFixture/Sub1");
+ m_keyChain.sign(d1);
+ VALIDATE_SUCCESS(d1, "Should succeed (fallback on inner validation policy for data)");
+}
+
+using ValidationPolicyAcceptAllCommands = ValidationPolicyCommandInterestFixture<DefaultOptions,
+ ValidationPolicyAcceptAll>;
+
+BOOST_FIXTURE_TEST_CASE(SignedWithSha256, ValidationPolicyAcceptAllCommands) // Bug 4635
+{
+ auto i1 = m_signer.makeCommandInterest("/hello/world/CMD", signingWithSha256());
+ VALIDATE_SUCCESS(i1, "Should succeed (within grace period)");
+ VALIDATE_FAILURE(i1, "Should fail (replay attack)");
+
+ advanceClocks(5_ms);
+ auto i2 = m_signer.makeCommandInterest("/hello/world/CMD", signingWithSha256());
+ VALIDATE_SUCCESS(i2, "Should succeed (timestamp larger than previous)");
+}
+
+BOOST_AUTO_TEST_SUITE_END() // Accepts
+
+BOOST_AUTO_TEST_SUITE(Rejects)
+
+BOOST_AUTO_TEST_CASE(NameTooShort)
+{
+ auto i1 = makeInterest("/name/too/short");
+ VALIDATE_FAILURE(*i1, "Should fail (name is too short)");
+}
+
+BOOST_AUTO_TEST_CASE(BadTimestamp)
+{
+ auto i1 = makeCommandInterest(identity);
+ setNameComponent(i1, command_interest::POS_TIMESTAMP, "not-timestamp");
+ VALIDATE_FAILURE(i1, "Should fail (timestamp is missing)");
+}
+
+BOOST_AUTO_TEST_CASE(BadSigInfo)
+{
+ auto i1 = makeCommandInterest(identity);
+ setNameComponent(i1, command_interest::POS_SIG_INFO, "not-SignatureInfo");
+ VALIDATE_FAILURE(i1, "Should fail (signature info is missing)");
+}
+
+BOOST_AUTO_TEST_CASE(MissingKeyLocator)
+{
+ auto i1 = makeCommandInterest(identity);
+ SignatureInfo sigInfo(tlv::SignatureSha256WithRsa);
+ setNameComponent(i1, command_interest::POS_SIG_INFO,
+ sigInfo.wireEncode().begin(), sigInfo.wireEncode().end());
+ VALIDATE_FAILURE(i1, "Should fail (missing KeyLocator)");
+}
+
+BOOST_AUTO_TEST_CASE(BadKeyLocatorType)
+{
+ auto i1 = makeCommandInterest(identity);
+ KeyLocator kl;
+ kl.setKeyDigest(makeBinaryBlock(tlv::KeyDigest, "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD", 8));
+ SignatureInfo sigInfo(tlv::SignatureSha256WithRsa);
+ sigInfo.setKeyLocator(kl);
+ setNameComponent(i1, command_interest::POS_SIG_INFO,
+ sigInfo.wireEncode().begin(), sigInfo.wireEncode().end());
+ VALIDATE_FAILURE(i1, "Should fail (bad KeyLocator type)");
+}
+
+BOOST_AUTO_TEST_CASE(BadCertName)
+{
+ auto i1 = makeCommandInterest(identity);
+ KeyLocator kl;
+ kl.setName("/bad/cert/name");
+ SignatureInfo sigInfo(tlv::SignatureSha256WithRsa);
+ sigInfo.setKeyLocator(kl);
+ setNameComponent(i1, command_interest::POS_SIG_INFO,
+ sigInfo.wireEncode().begin(), sigInfo.wireEncode().end());
+ VALIDATE_FAILURE(i1, "Should fail (bad certificate name)");
+}
+
+BOOST_AUTO_TEST_CASE(InnerPolicyReject)
+{
+ auto i1 = makeCommandInterest(otherIdentity);
+ VALIDATE_FAILURE(i1, "Should fail (inner policy should reject)");
+}
+
+class GracePeriod15Sec
+{
+public:
+ static ValidationPolicyCommandInterest::Options
+ getOptions()
+ {
+ ValidationPolicyCommandInterest::Options options;
+ options.gracePeriod = 15_s;
+ return options;
+ }
+};
+
+BOOST_FIXTURE_TEST_CASE(TimestampOutOfGracePositive, ValidationPolicyCommandInterestFixture<GracePeriod15Sec>)
+{
+ auto i1 = makeCommandInterest(identity); // signed at 0s
+ advanceClocks(16_s); // verifying at +16s
+ VALIDATE_FAILURE(i1, "Should fail (timestamp outside the grace period)");
+ rewindClockAfterValidation();
+
+ auto i2 = makeCommandInterest(identity); // signed at +16s
+ VALIDATE_SUCCESS(i2, "Should succeed");
+}
+
+BOOST_FIXTURE_TEST_CASE(TimestampOutOfGraceNegative, ValidationPolicyCommandInterestFixture<GracePeriod15Sec>)
+{
+ auto i1 = makeCommandInterest(identity); // signed at 0s
+ advanceClocks(1_s);
+ auto i2 = makeCommandInterest(identity); // signed at +1s
+ advanceClocks(1_s);
+ auto i3 = makeCommandInterest(identity); // signed at +2s
+
+ systemClock->advance(-18_s); // verifying at -16s
+ VALIDATE_FAILURE(i1, "Should fail (timestamp outside the grace period)");
+ rewindClockAfterValidation();
+
+ // CommandInterestValidator should not remember i1's timestamp
+ VALIDATE_FAILURE(i2, "Should fail (timestamp outside the grace period)");
+ rewindClockAfterValidation();
+
+ // CommandInterestValidator should not remember i2's timestamp, and should treat i3 as initial
+ advanceClocks(18_s); // verifying at +2s
+ VALIDATE_SUCCESS(i3, "Should succeed");
+}
+
+BOOST_AUTO_TEST_CASE(TimestampReorderEqual)
+{
+ auto i1 = makeCommandInterest(identity); // signed at 0s
+ VALIDATE_SUCCESS(i1, "Should succeed");
+
+ auto i2 = makeCommandInterest(identity); // signed at 0s
+ setNameComponent(i2, command_interest::POS_TIMESTAMP,
+ i1.getName()[command_interest::POS_TIMESTAMP]);
+ VALIDATE_FAILURE(i2, "Should fail (timestamp reordered)");
+
+ advanceClocks(2_s);
+ auto i3 = makeCommandInterest(identity); // signed at +2s
+ VALIDATE_SUCCESS(i3, "Should succeed");
+}
+
+BOOST_AUTO_TEST_CASE(TimestampReorderNegative)
+{
+ auto i2 = makeCommandInterest(identity); // signed at 0ms
+ advanceClocks(200_ms);
+ auto i3 = makeCommandInterest(identity); // signed at +200ms
+ advanceClocks(900_ms);
+ auto i1 = makeCommandInterest(identity); // signed at +1100ms
+ advanceClocks(300_ms);
+ auto i4 = makeCommandInterest(identity); // signed at +1400ms
+
+ systemClock->advance(-300_ms); // verifying at +1100ms
+ VALIDATE_SUCCESS(i1, "Should succeed");
+ rewindClockAfterValidation();
+
+ systemClock->advance(-1100_ms); // verifying at 0ms
+ VALIDATE_FAILURE(i2, "Should fail (timestamp reordered)");
+ rewindClockAfterValidation();
+
+ // CommandInterestValidator should not remember i2's timestamp
+ advanceClocks(200_ms); // verifying at +200ms
+ VALIDATE_FAILURE(i3, "Should fail (timestamp reordered)");
+ rewindClockAfterValidation();
+
+ advanceClocks(1200_ms); // verifying at 1400ms
+ VALIDATE_SUCCESS(i4, "Should succeed");
+}
+
+BOOST_AUTO_TEST_SUITE_END() // Rejects
+
+BOOST_AUTO_TEST_SUITE(Options)
+
+template<class T>
+class GracePeriod
+{
+public:
+ static ValidationPolicyCommandInterest::Options
+ getOptions()
+ {
+ ValidationPolicyCommandInterest::Options options;
+ options.gracePeriod = time::seconds(T::value);
+ return options;
+ }
+};
+
+typedef boost::mpl::vector<
+ GracePeriod<boost::mpl::int_<0>>,
+ GracePeriod<boost::mpl::int_<-1>>
+> GraceNonPositiveValues;
+
+BOOST_FIXTURE_TEST_CASE_TEMPLATE(GraceNonPositive, GracePeriod, GraceNonPositiveValues,
+ ValidationPolicyCommandInterestFixture<GracePeriod>)
+{
+ auto i1 = this->makeCommandInterest(this->identity); // signed at 0ms
+ auto i2 = this->makeCommandInterest(this->subIdentity); // signed at 0ms
+ for (auto interest : {&i1, &i2}) {
+ setNameComponent(*interest, command_interest::POS_TIMESTAMP,
+ name::Component::fromNumber(time::toUnixTimestamp(time::system_clock::now()).count()));
+ } // ensure timestamps are exactly 0ms
+
+ VALIDATE_SUCCESS(i1, "Should succeed when validating at 0ms");
+ this->rewindClockAfterValidation();
+
+ this->advanceClocks(1_ms);
+ VALIDATE_FAILURE(i2, "Should fail when validating at 1ms");
+}
+
+class LimitedRecordsOptions
+{
+public:
+ static ValidationPolicyCommandInterest::Options
+ getOptions()
+ {
+ ValidationPolicyCommandInterest::Options options;
+ options.gracePeriod = 15_s;
+ options.maxRecords = 3;
+ return options;
+ }
+};
+
+BOOST_FIXTURE_TEST_CASE(LimitedRecords, ValidationPolicyCommandInterestFixture<LimitedRecordsOptions>)
+{
+ Identity id1 = this->addSubCertificate("/Security/V2/ValidatorFixture/Sub1", identity);
+ this->cache.insert(id1.getDefaultKey().getDefaultCertificate());
+ Identity id2 = this->addSubCertificate("/Security/V2/ValidatorFixture/Sub2", identity);
+ this->cache.insert(id2.getDefaultKey().getDefaultCertificate());
+ Identity id3 = this->addSubCertificate("/Security/V2/ValidatorFixture/Sub3", identity);
+ this->cache.insert(id3.getDefaultKey().getDefaultCertificate());
+ Identity id4 = this->addSubCertificate("/Security/V2/ValidatorFixture/Sub4", identity);
+ this->cache.insert(id4.getDefaultKey().getDefaultCertificate());
+
+ auto i1 = makeCommandInterest(id2);
+ auto i2 = makeCommandInterest(id3);
+ auto i3 = makeCommandInterest(id4);
+ auto i00 = makeCommandInterest(id1); // signed at 0s
+ advanceClocks(1_s);
+ auto i01 = makeCommandInterest(id1); // signed at 1s
+ advanceClocks(1_s);
+ auto i02 = makeCommandInterest(id1); // signed at 2s
+
+ VALIDATE_SUCCESS(i00, "Should succeed");
+ rewindClockAfterValidation();
+
+ VALIDATE_SUCCESS(i02, "Should succeed");
+ rewindClockAfterValidation();
+
+ VALIDATE_SUCCESS(i1, "Should succeed");
+ rewindClockAfterValidation();
+
+ VALIDATE_SUCCESS(i2, "Should succeed");
+ rewindClockAfterValidation();
+
+ VALIDATE_SUCCESS(i3, "Should succeed, forgets identity id1");
+ rewindClockAfterValidation();
+
+ VALIDATE_SUCCESS(i01, "Should succeed despite timestamp is reordered, because record has been evicted");
+}
+
+class UnlimitedRecordsOptions
+{
+public:
+ static ValidationPolicyCommandInterest::Options
+ getOptions()
+ {
+ ValidationPolicyCommandInterest::Options options;
+ options.gracePeriod = 15_s;
+ options.maxRecords = -1;
+ return options;
+ }
+};
+
+BOOST_FIXTURE_TEST_CASE(UnlimitedRecords, ValidationPolicyCommandInterestFixture<UnlimitedRecordsOptions>)
+{
+ std::vector<Identity> identities;
+ for (int i = 0; i < 20; ++i) {
+ Identity id = this->addSubCertificate("/Security/V2/ValidatorFixture/Sub" + to_string(i), identity);
+ this->cache.insert(id.getDefaultKey().getDefaultCertificate());
+ identities.push_back(id);
+ }
+
+ auto i1 = makeCommandInterest(identities.at(0)); // signed at 0s
+ advanceClocks(1_s);
+ for (int i = 0; i < 20; ++i) {
+ auto i2 = makeCommandInterest(identities.at(i)); // signed at +1s
+
+ VALIDATE_SUCCESS(i2, "Should succeed");
+ rewindClockAfterValidation();
+ }
+ VALIDATE_FAILURE(i1, "Should fail (timestamp reorder)");
+}
+
+class ZeroRecordsOptions
+{
+public:
+ static ValidationPolicyCommandInterest::Options
+ getOptions()
+ {
+ ValidationPolicyCommandInterest::Options options;
+ options.gracePeriod = 15_s;
+ options.maxRecords = 0;
+ return options;
+ }
+};
+
+BOOST_FIXTURE_TEST_CASE(ZeroRecords, ValidationPolicyCommandInterestFixture<ZeroRecordsOptions>)
+{
+ auto i1 = makeCommandInterest(identity); // signed at 0s
+ advanceClocks(1_s);
+ auto i2 = makeCommandInterest(identity); // signed at +1s
+ VALIDATE_SUCCESS(i2, "Should succeed");
+ rewindClockAfterValidation();
+
+ VALIDATE_SUCCESS(i1, "Should succeed despite timestamp is reordered, because record isn't kept");
+}
+
+class LimitedRecordLifetimeOptions
+{
+public:
+ static ValidationPolicyCommandInterest::Options
+ getOptions()
+ {
+ ValidationPolicyCommandInterest::Options options;
+ options.gracePeriod = 400_s;
+ options.recordLifetime = 300_s;
+ return options;
+ }
+};
+
+BOOST_FIXTURE_TEST_CASE(LimitedRecordLifetime, ValidationPolicyCommandInterestFixture<LimitedRecordLifetimeOptions>)
+{
+ auto i1 = makeCommandInterest(identity); // signed at 0s
+ advanceClocks(240_s);
+ auto i2 = makeCommandInterest(identity); // signed at +240s
+ advanceClocks(120_s);
+ auto i3 = makeCommandInterest(identity); // signed at +360s
+
+ systemClock->advance(-360_s); // rewind system clock to 0s
+ VALIDATE_SUCCESS(i1, "Should succeed");
+ rewindClockAfterValidation();
+
+ VALIDATE_SUCCESS(i3, "Should succeed");
+ rewindClockAfterValidation();
+
+ advanceClocks(30_s, 301_s); // advance steady clock by 301s, and system clock to +301s
+ VALIDATE_SUCCESS(i2, "Should succeed despite timestamp is reordered, because record has been expired");
+}
+
+class ZeroRecordLifetimeOptions
+{
+public:
+ static ValidationPolicyCommandInterest::Options
+ getOptions()
+ {
+ ValidationPolicyCommandInterest::Options options;
+ options.gracePeriod = 15_s;
+ options.recordLifetime = time::seconds::zero();
+ return options;
+ }
+};
+
+BOOST_FIXTURE_TEST_CASE(ZeroRecordLifetime, ValidationPolicyCommandInterestFixture<ZeroRecordLifetimeOptions>)
+{
+ auto i1 = makeCommandInterest(identity); // signed at 0s
+ advanceClocks(1_s);
+ auto i2 = makeCommandInterest(identity); // signed at +1s
+ VALIDATE_SUCCESS(i2, "Should succeed");
+ rewindClockAfterValidation();
+
+ VALIDATE_SUCCESS(i1, "Should succeed despite timestamp is reordered, because record has been expired");
+}
+
+BOOST_AUTO_TEST_SUITE_END() // Options
+
+BOOST_AUTO_TEST_SUITE_END() // TestValidationPolicyCommandInterest
+BOOST_AUTO_TEST_SUITE_END() // V2
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace v2
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/v2/validation-policy-config.t.cpp b/tests/unit/security/v2/validation-policy-config.t.cpp
new file mode 100644
index 0000000..cca3e7a
--- /dev/null
+++ b/tests/unit/security/v2/validation-policy-config.t.cpp
@@ -0,0 +1,539 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/v2/validation-policy-config.hpp"
+#include "security/transform/base64-encode.hpp"
+#include "security/transform/buffer-source.hpp"
+#include "security/transform/stream-sink.hpp"
+#include "util/logger.hpp"
+#include "util/io.hpp"
+
+#include "boost-test.hpp"
+#include "validator-config/common.hpp"
+#include "validator-fixture.hpp"
+
+namespace ndn {
+namespace security {
+namespace v2 {
+namespace validator_config {
+namespace tests {
+
+using namespace ndn::tests;
+using namespace ndn::security::v2::tests;
+
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(V2)
+BOOST_AUTO_TEST_SUITE(TestValidationPolicyConfig)
+
+template<typename Packet>
+class PacketName;
+
+template<>
+class PacketName<Interest>
+{
+public:
+ static std::string
+ getName()
+ {
+ return "interest";
+ }
+};
+
+template<>
+class PacketName<Data>
+{
+public:
+ static std::string
+ getName()
+ {
+ return "data";
+ }
+};
+
+template<typename PacketType>
+class ValidationPolicyConfigFixture : public HierarchicalValidatorFixture<ValidationPolicyConfig>
+{
+public:
+ ValidationPolicyConfigFixture()
+ : path(boost::filesystem::path(UNIT_TEST_CONFIG_PATH) / "security" / "v2" / "validation-policy-config")
+ {
+ boost::filesystem::create_directories(path);
+ baseConfig = R"CONF(
+ rule
+ {
+ id test-rule-id
+ for )CONF" + PacketName<Packet>::getName() + R"CONF(
+ filter
+ {
+ type name
+ name )CONF" + identity.getName().toUri() + R"CONF(
+ relation is-prefix-of
+ }
+ checker
+ {
+ type hierarchical
+ sig-type rsa-sha256
+ }
+ }
+ )CONF";
+ }
+
+ ~ValidationPolicyConfigFixture()
+ {
+ boost::filesystem::remove_all(path);
+ }
+
+public:
+ using Packet = PacketType;
+
+ const boost::filesystem::path path;
+ std::string baseConfig;
+};
+
+template<typename PacketType>
+class LoadStringWithFileAnchor : public ValidationPolicyConfigFixture<PacketType>
+{
+public:
+ LoadStringWithFileAnchor()
+ {
+ BOOST_CHECK_EQUAL(this->policy.m_isConfigured, false);
+
+ this->saveCertificate(this->identity, (this->path / "identity.ndncert").string());
+ this->policy.load(this->baseConfig + R"CONF(
+ trust-anchor
+ {
+ type file
+ file-name "trust-anchor.ndncert"
+ }
+ )CONF", (this->path / "test-config").string());
+
+ BOOST_CHECK_EQUAL(this->policy.m_isConfigured, true);
+ BOOST_CHECK_EQUAL(this->policy.m_shouldBypass, false);
+ }
+};
+
+template<typename PacketType>
+class LoadFileWithFileAnchor : public ValidationPolicyConfigFixture<PacketType>
+{
+public:
+ LoadFileWithFileAnchor()
+ {
+ std::string configFile = (this->path / "config.conf").string();
+ {
+ std::ofstream config(configFile.c_str());
+ config << this->baseConfig << R"CONF(
+ trust-anchor
+ {
+ type file
+ file-name "trust-anchor.ndncert"
+ }
+ )CONF";
+ }
+ this->saveCertificate(this->identity, (this->path / "identity.ndncert").string());
+
+ BOOST_CHECK_EQUAL(this->policy.m_isConfigured, false);
+
+ this->policy.load(configFile);
+
+ BOOST_CHECK_EQUAL(this->policy.m_isConfigured, true);
+ BOOST_CHECK_EQUAL(this->policy.m_shouldBypass, false);
+ }
+};
+
+template<typename PacketType>
+class LoadSectionWithFileAnchor : public ValidationPolicyConfigFixture<PacketType>
+{
+public:
+ LoadSectionWithFileAnchor()
+ {
+ auto section = makeSection(this->baseConfig + R"CONF(
+ trust-anchor
+ {
+ type file
+ file-name "trust-anchor.ndncert"
+ }
+ )CONF");
+
+ this->saveCertificate(this->identity, (this->path / "identity.ndncert").string());
+
+ BOOST_CHECK_EQUAL(this->policy.m_isConfigured, false);
+
+ this->policy.load(section, (this->path / "test-config").string());
+
+ BOOST_CHECK_EQUAL(this->policy.m_isConfigured, true);
+ BOOST_CHECK_EQUAL(this->policy.m_shouldBypass, false);
+ }
+};
+
+template<typename PacketType>
+class LoadStringWithBase64Anchor : public ValidationPolicyConfigFixture<PacketType>
+{
+public:
+ LoadStringWithBase64Anchor()
+ {
+ BOOST_CHECK_EQUAL(this->policy.m_isConfigured, false);
+
+ std::ostringstream os;
+ using namespace ndn::security::transform;
+ const auto& cert = this->identity.getDefaultKey().getDefaultCertificate();
+ bufferSource(cert.wireEncode().wire(), cert.wireEncode().size()) >> base64Encode(false) >> streamSink(os);
+
+ this->policy.load(this->baseConfig + R"CONF(
+ trust-anchor
+ {
+ type base64
+ base64-string ")CONF" + os.str() + R"CONF("
+ }
+ )CONF", (this->path / "test-config").string());
+
+ BOOST_CHECK_EQUAL(this->policy.m_isConfigured, true);
+ BOOST_CHECK_EQUAL(this->policy.m_shouldBypass, false);
+ }
+};
+
+class NoRefresh
+{
+public:
+ static std::string
+ getRefreshString()
+ {
+ return "";
+ }
+};
+
+class Refresh1h
+{
+public:
+ static std::string
+ getRefreshString()
+ {
+ return "refresh 1h";
+ }
+
+ static time::milliseconds
+ getRefreshTime()
+ {
+ return 1_h;
+ }
+};
+
+class Refresh1m
+{
+public:
+ static std::string
+ getRefreshString()
+ {
+ return "refresh 1m";
+ }
+
+ static time::milliseconds
+ getRefreshTime()
+ {
+ return 1_min;
+ }
+};
+
+class Refresh1s
+{
+public:
+ static std::string
+ getRefreshString()
+ {
+ return "refresh 1s";
+ }
+
+ static time::milliseconds
+ getRefreshTime()
+ {
+ return 1_s;
+ }
+};
+
+template<typename PacketType, typename Refresh = NoRefresh>
+class LoadStringWithDirAnchor : public ValidationPolicyConfigFixture<PacketType>
+{
+public:
+ LoadStringWithDirAnchor()
+ {
+ BOOST_CHECK_EQUAL(this->policy.m_isConfigured, false);
+
+ boost::filesystem::create_directories(this->path / "keys");
+ this->saveCertificate(this->identity, (this->path / "keys" / "identity.ndncert").string());
+
+ this->policy.load(this->baseConfig + R"CONF(
+ trust-anchor
+ {
+ type dir
+ dir keys
+ )CONF" + Refresh::getRefreshString() + R"CONF(
+ }
+ )CONF", (this->path / "test-config").string());
+
+ BOOST_CHECK_EQUAL(this->policy.m_isConfigured, true);
+ BOOST_CHECK_EQUAL(this->policy.m_shouldBypass, false);
+ }
+};
+
+using DataPolicies = boost::mpl::vector<LoadStringWithFileAnchor<Data>,
+ LoadFileWithFileAnchor<Data>,
+ LoadSectionWithFileAnchor<Data>,
+ LoadStringWithBase64Anchor<Data>,
+ LoadStringWithDirAnchor<Data>,
+ LoadStringWithDirAnchor<Data, Refresh1h>,
+ LoadStringWithDirAnchor<Data, Refresh1m>,
+ LoadStringWithDirAnchor<Data, Refresh1s>
+ >;
+
+using InterestPolicies = boost::mpl::vector<LoadStringWithFileAnchor<Interest>,
+ LoadFileWithFileAnchor<Interest>,
+ LoadSectionWithFileAnchor<Interest>,
+ LoadStringWithBase64Anchor<Interest>,
+ LoadStringWithDirAnchor<Interest>,
+ LoadStringWithDirAnchor<Interest, Refresh1h>,
+ LoadStringWithDirAnchor<Interest, Refresh1m>,
+ LoadStringWithDirAnchor<Interest, Refresh1s>
+ >;
+
+BOOST_FIXTURE_TEST_CASE_TEMPLATE(ValidateData, Policy, DataPolicies, Policy)
+{
+ BOOST_CHECK_EQUAL(this->policy.m_dataRules.size(), 1);
+ BOOST_CHECK_EQUAL(this->policy.m_interestRules.size(), 0);
+
+ using Packet = typename Policy::Packet;
+ Packet unsignedPacket("/Security/V2/ValidatorFixture/Sub1/Sub2/Packet");
+
+ Packet packet = unsignedPacket;
+ VALIDATE_FAILURE(packet, "Unsigned");
+
+ packet = unsignedPacket;
+ this->m_keyChain.sign(packet, signingWithSha256());
+ VALIDATE_FAILURE(packet, "Policy doesn't accept Sha256Digest signature");
+
+ packet = unsignedPacket;
+ this->m_keyChain.sign(packet, signingByIdentity(this->identity));
+ VALIDATE_SUCCESS(packet, "Should get accepted, as signed by the anchor");
+
+ packet = unsignedPacket;
+ this->m_keyChain.sign(packet, signingByIdentity(this->subIdentity));
+ VALIDATE_SUCCESS(packet, "Should get accepted, as signed by the policy-compliant cert");
+
+ packet = unsignedPacket;
+ this->m_keyChain.sign(packet, signingByIdentity(this->otherIdentity));
+ VALIDATE_FAILURE(packet, "Should fail, as signed by the policy-violating cert");
+
+ packet = unsignedPacket;
+ this->m_keyChain.sign(packet, signingByIdentity(this->subSelfSignedIdentity));
+ VALIDATE_FAILURE(packet, "Should fail, because subSelfSignedIdentity is not a trust anchor");
+}
+
+BOOST_FIXTURE_TEST_CASE_TEMPLATE(ValidateInterest, Policy, InterestPolicies, Policy)
+{
+ BOOST_CHECK_EQUAL(this->policy.m_dataRules.size(), 0);
+ BOOST_CHECK_EQUAL(this->policy.m_interestRules.size(), 1);
+
+ using Packet = typename Policy::Packet;
+ Packet unsignedPacket("/Security/V2/ValidatorFixture/Sub1/Sub2/Packet");
+
+ Packet packet = unsignedPacket;
+ VALIDATE_FAILURE(packet, "Unsigned");
+
+ packet = unsignedPacket;
+ this->m_keyChain.sign(packet, signingWithSha256());
+ VALIDATE_FAILURE(packet, "Policy doesn't accept Sha256Digest signature");
+
+ packet = unsignedPacket;
+ this->m_keyChain.sign(packet, signingByIdentity(this->identity));
+ VALIDATE_SUCCESS(packet, "Should get accepted, as signed by the anchor");
+
+ packet = unsignedPacket;
+ this->m_keyChain.sign(packet, signingByIdentity(this->subIdentity));
+ VALIDATE_FAILURE(packet, "Should fail, as there is no matching rule for data");
+
+ packet = unsignedPacket;
+ this->m_keyChain.sign(packet, signingByIdentity(this->otherIdentity));
+ VALIDATE_FAILURE(packet, "Should fail, as signed by the policy-violating cert");
+
+ packet = unsignedPacket;
+ this->m_keyChain.sign(packet, signingByIdentity(this->subSelfSignedIdentity));
+ VALIDATE_FAILURE(packet, "Should fail, because subSelfSignedIdentity is not a trust anchor");
+}
+
+BOOST_FIXTURE_TEST_CASE(Reload, HierarchicalValidatorFixture<ValidationPolicyConfig>)
+{
+ BOOST_CHECK_EQUAL(this->policy.m_isConfigured, false);
+ this->policy.load(R"CONF(
+ rule
+ {
+ id test-rule-data-id
+ for data
+ filter
+ {
+ type name
+ name /foo/bar
+ relation is-prefix-of
+ }
+ checker
+ {
+ type hierarchical
+ sig-type rsa-sha256
+ }
+ }
+ rule
+ {
+ id test-rule-interest-id
+ for interest
+ filter
+ {
+ type name
+ name /foo/bar
+ relation is-prefix-of
+ }
+ checker
+ {
+ type hierarchical
+ sig-type rsa-sha256
+ }
+ }
+ trust-anchor
+ {
+ type dir
+ dir keys
+ refresh 1h
+ }
+ )CONF", "test-config");
+ BOOST_CHECK_EQUAL(this->policy.m_isConfigured, true);
+ BOOST_CHECK_EQUAL(this->policy.m_shouldBypass, false);
+ BOOST_CHECK_EQUAL(this->policy.m_dataRules.size(), 1);
+ BOOST_CHECK_EQUAL(this->policy.m_interestRules.size(), 1);
+
+ this->policy.load(R"CONF(
+ trust-anchor
+ {
+ type any
+ }
+ )CONF", "test-config");
+ BOOST_CHECK_EQUAL(this->policy.m_isConfigured, true);
+ BOOST_CHECK_EQUAL(this->policy.m_shouldBypass, true);
+ BOOST_CHECK_EQUAL(this->policy.m_dataRules.size(), 0);
+ BOOST_CHECK_EQUAL(this->policy.m_interestRules.size(), 0);
+}
+
+using Packets = boost::mpl::vector<Interest, Data>;
+
+BOOST_FIXTURE_TEST_CASE_TEMPLATE(TrustAnchorWildcard, Packet, Packets, ValidationPolicyConfigFixture<Packet>)
+{
+ this->policy.load(R"CONF(
+ trust-anchor
+ {
+ type any
+ }
+ )CONF", "test-config");
+
+ BOOST_CHECK_EQUAL(this->policy.m_isConfigured, true);
+ BOOST_CHECK_EQUAL(this->policy.m_shouldBypass, true);
+ BOOST_CHECK_EQUAL(this->policy.m_dataRules.size(), 0);
+ BOOST_CHECK_EQUAL(this->policy.m_interestRules.size(), 0);
+
+ Packet unsignedPacket("/Security/V2/ValidatorFixture/Sub1/Sub2/Packet");
+
+ Packet packet = unsignedPacket;
+ VALIDATE_SUCCESS(packet, "Policy should accept everything");
+
+ packet = unsignedPacket;
+ this->m_keyChain.sign(packet, signingWithSha256());
+ VALIDATE_SUCCESS(packet, "Policy should accept everything");
+
+ packet = unsignedPacket;
+ this->m_keyChain.sign(packet, signingByIdentity(this->identity));
+ VALIDATE_SUCCESS(packet, "Policy should accept everything");
+
+ packet = unsignedPacket;
+ this->m_keyChain.sign(packet, signingByIdentity(this->subIdentity));
+ VALIDATE_SUCCESS(packet, "Policy should accept everything");
+
+ packet = unsignedPacket;
+ this->m_keyChain.sign(packet, signingByIdentity(this->otherIdentity));
+ VALIDATE_SUCCESS(packet, "Policy should accept everything");
+
+ packet = unsignedPacket;
+ this->m_keyChain.sign(packet, signingByIdentity(this->subSelfSignedIdentity));
+ VALIDATE_SUCCESS(packet, "Policy should accept everything");
+}
+
+using RefreshPolicies = boost::mpl::vector<Refresh1h, Refresh1m, Refresh1s>;
+
+// Somehow, didn't work without this wrapper
+template<typename RefreshPolicy>
+class RefreshPolicyFixture : public LoadStringWithDirAnchor<Data, RefreshPolicy>
+{
+public:
+};
+
+BOOST_FIXTURE_TEST_CASE_TEMPLATE(ValidateRefresh, Refresh, RefreshPolicies, RefreshPolicyFixture<Refresh>)
+{
+ using Packet = Data;
+ Packet unsignedPacket("/Security/V2/ValidatorFixture/Sub1/Sub2/Packet");
+
+ boost::filesystem::remove(this->path / "keys" / "identity.ndncert");
+ this->advanceClocks(Refresh::getRefreshTime(), 3);
+
+ Packet packet = unsignedPacket;
+ this->m_keyChain.sign(packet, signingByIdentity(this->identity));
+ VALIDATE_FAILURE(packet, "Should fail, as the trust anchor should no longer exist");
+
+ packet = unsignedPacket;
+ this->m_keyChain.sign(packet, signingByIdentity(this->subIdentity));
+ VALIDATE_FAILURE(packet, "Should fail, as the trust anchor should no longer exist");
+}
+
+BOOST_FIXTURE_TEST_CASE(OrphanedPolicyLoad, HierarchicalValidatorFixture<ValidationPolicyConfig>) // Bug #4758
+{
+ ValidationPolicyConfig policy1;
+ BOOST_CHECK_THROW(policy1.load("trust-anchor { type any }", "test-config"), Error);
+
+ // Reloading would have triggered a segfault
+ BOOST_CHECK_THROW(policy1.load("trust-anchor { type any }", "test-config"), Error);
+
+ ValidationPolicyConfig policy2;
+
+ std::string config = R"CONF(
+ trust-anchor
+ {
+ type dir
+ dir keys
+ refresh 1h
+ }
+ )CONF";
+
+ // Inserting trust anchor would have triggered a segfault
+ BOOST_CHECK_THROW(policy2.load(config, "test-config"), Error);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestValidationPolicyConfig
+BOOST_AUTO_TEST_SUITE_END() // V2
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace validator_config
+} // namespace v2
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/v2/validation-policy-simple-hierarchy.t.cpp b/tests/unit/security/v2/validation-policy-simple-hierarchy.t.cpp
new file mode 100644
index 0000000..8661ac5
--- /dev/null
+++ b/tests/unit/security/v2/validation-policy-simple-hierarchy.t.cpp
@@ -0,0 +1,80 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/v2/validation-policy-simple-hierarchy.hpp"
+
+#include "boost-test.hpp"
+#include "validator-fixture.hpp"
+
+#include <boost/mpl/vector.hpp>
+
+namespace ndn {
+namespace security {
+namespace v2 {
+namespace tests {
+
+using namespace ndn::tests;
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(V2)
+BOOST_FIXTURE_TEST_SUITE(TestValidationPolicySimpleHierarchy,
+ HierarchicalValidatorFixture<ValidationPolicySimpleHierarchy>)
+
+typedef boost::mpl::vector<Interest, Data> Packets;
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(Validate, Packet, Packets)
+{
+ Packet unsignedPacket("/Security/V2/ValidatorFixture/Sub1/Sub2/Packet");
+
+ Packet packet = unsignedPacket;
+ VALIDATE_FAILURE(packet, "Unsigned");
+
+ packet = unsignedPacket;
+ m_keyChain.sign(packet, signingWithSha256());
+ VALIDATE_FAILURE(packet, "Policy doesn't accept Sha256Digest signature");
+
+ packet = unsignedPacket;
+ m_keyChain.sign(packet, signingByIdentity(identity));
+ VALIDATE_SUCCESS(packet, "Should get accepted, as signed by the anchor");
+
+ packet = unsignedPacket;
+ m_keyChain.sign(packet, signingByIdentity(subIdentity));
+ VALIDATE_SUCCESS(packet, "Should get accepted, as signed by the policy-compliant cert");
+
+ packet = unsignedPacket;
+ m_keyChain.sign(packet, signingByIdentity(otherIdentity));
+ VALIDATE_FAILURE(packet, "Should fail, as signed by the policy-violating cert");
+
+ packet = unsignedPacket;
+ m_keyChain.sign(packet, signingByIdentity(subSelfSignedIdentity));
+ VALIDATE_FAILURE(packet, "Should fail, because subSelfSignedIdentity is not a trust anchor");
+
+ // TODO add checks with malformed packets
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestValidator
+BOOST_AUTO_TEST_SUITE_END() // V2
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace v2
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/v2/validator-config/checker.t.cpp b/tests/unit/security/v2/validator-config/checker.t.cpp
new file mode 100644
index 0000000..2170908
--- /dev/null
+++ b/tests/unit/security/v2/validator-config/checker.t.cpp
@@ -0,0 +1,374 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/v2/validator-config/checker.hpp"
+#include "security/command-interest-signer.hpp"
+#include "security/v2/validation-policy.hpp"
+#include "security/v2/validation-state.hpp"
+
+#include "boost-test.hpp"
+#include "common.hpp"
+#include "identity-management-fixture.hpp"
+#include "../validator-fixture.hpp"
+
+namespace ndn {
+namespace security {
+namespace v2 {
+namespace validator_config {
+namespace tests {
+
+using namespace ndn::tests;
+using namespace ndn::security::v2::tests;
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(V2)
+BOOST_AUTO_TEST_SUITE(ValidatorConfig)
+
+class CheckerFixture : public IdentityManagementFixture
+{
+public:
+ CheckerFixture()
+ {
+ names.push_back("/foo/bar");
+ names.push_back("/foo/bar/bar");
+ names.push_back("/foo");
+ names.push_back("/other/prefix");
+ }
+
+ Name
+ makeSignedInterestName(const Name& name)
+ {
+ return Name(name).append("SignatureInfo").append("SignatureValue");
+ }
+
+ Name
+ makeKeyLocatorName(const Name& name)
+ {
+ return Name(name).append("KEY").append("v=1");
+ }
+
+public:
+ std::vector<Name> names;
+};
+
+BOOST_FIXTURE_TEST_SUITE(TestChecker, CheckerFixture)
+
+class NameRelationEqual : public CheckerFixture
+{
+public:
+ NameRelationEqual()
+ : checker("/foo/bar", NameRelation::EQUAL)
+ {
+ }
+
+public:
+ NameRelationChecker checker;
+ std::vector<std::vector<bool>> outcomes = {{true, false, false, false},
+ {true, false, false, false},
+ {true, false, false, false},
+ {true, false, false, false}};
+};
+
+class NameRelationIsPrefixOf : public CheckerFixture
+{
+public:
+ NameRelationIsPrefixOf()
+ : checker("/foo/bar", NameRelation::IS_PREFIX_OF)
+ {
+ }
+
+public:
+ NameRelationChecker checker;
+ std::vector<std::vector<bool>> outcomes = {{true, true, false, false},
+ {true, true, false, false},
+ {true, true, false, false},
+ {true, true, false, false}};
+};
+
+class NameRelationIsStrictPrefixOf : public CheckerFixture
+{
+public:
+ NameRelationIsStrictPrefixOf()
+ : checker("/foo/bar", NameRelation::IS_STRICT_PREFIX_OF)
+ {
+ }
+
+public:
+ NameRelationChecker checker;
+ std::vector<std::vector<bool>> outcomes = {{false, true, false, false},
+ {false, true, false, false},
+ {false, true, false, false},
+ {false, true, false, false}};
+};
+
+class RegexEqual : public CheckerFixture
+{
+public:
+ RegexEqual()
+ : checker(Regex("^<foo><bar><KEY><>$"))
+ {
+ }
+
+public:
+ RegexChecker checker;
+ std::vector<std::vector<bool>> outcomes = {{true, false, false, false},
+ {true, false, false, false},
+ {true, false, false, false},
+ {true, false, false, false}};
+};
+
+class RegexIsPrefixOf : public CheckerFixture
+{
+public:
+ RegexIsPrefixOf()
+ : checker(Regex("^<foo><bar><>*<KEY><>$"))
+ {
+ }
+
+public:
+ RegexChecker checker;
+ std::vector<std::vector<bool>> outcomes = {{true, true, false, false},
+ {true, true, false, false},
+ {true, true, false, false},
+ {true, true, false, false}};
+};
+
+class RegexIsStrictPrefixOf : public CheckerFixture
+{
+public:
+ RegexIsStrictPrefixOf()
+ : checker(Regex("^<foo><bar><>+<KEY><>$"))
+ {
+ }
+
+public:
+ RegexChecker checker;
+ std::vector<std::vector<bool>> outcomes = {{false, true, false, false},
+ {false, true, false, false},
+ {false, true, false, false},
+ {false, true, false, false}};
+};
+
+class HyperRelationEqual : public CheckerFixture
+{
+public:
+ HyperRelationEqual()
+ : checker("^(<>+)$", "\\1", "^(<>+)<KEY><>$", "\\1", NameRelation::EQUAL)
+ {
+ }
+
+public:
+ HyperRelationChecker checker;
+ std::vector<std::vector<bool>> outcomes = {{true, false, false, false},
+ {false, true, false, false},
+ {false, false, true, false},
+ {false, false, false, true}};
+};
+
+class HyperRelationIsPrefixOf : public CheckerFixture
+{
+public:
+ HyperRelationIsPrefixOf()
+ : checker("^(<>+)$", "\\1", "^(<>+)<KEY><>$", "\\1", NameRelation::IS_PREFIX_OF)
+ {
+ }
+
+public:
+ HyperRelationChecker checker;
+ std::vector<std::vector<bool>> outcomes = {{true, false, true, false},
+ {true, true, true, false},
+ {false, false, true, false},
+ {false, false, false, true}};
+};
+
+class HyperRelationIsStrictPrefixOf : public CheckerFixture
+{
+public:
+ HyperRelationIsStrictPrefixOf()
+ : checker("^(<>+)$", "\\1", "^(<>+)<KEY><>$", "\\1", NameRelation::IS_STRICT_PREFIX_OF)
+ {
+ }
+
+public:
+ HyperRelationChecker checker;
+ std::vector<std::vector<bool>> outcomes = {{false, false, true, false},
+ {true, false, true, false},
+ {false, false, false, false},
+ {false, false, false, false}};
+};
+
+class Hierarchical : public CheckerFixture
+{
+public:
+ Hierarchical()
+ : checkerPtr(Checker::create(makeSection(R"CONF(
+ type hierarchical
+ sig-type rsa-sha256
+ )CONF"), "test-config"))
+ , checker(*checkerPtr)
+ {
+ }
+
+public:
+ std::unique_ptr<Checker> checkerPtr;
+ Checker& checker;
+
+ std::vector<std::vector<bool>> outcomes = {{true, false, true, false},
+ {true, true, true, false},
+ {false, false, true, false},
+ {false, false, false, true}};
+};
+
+class CustomizedNameRelation : public CheckerFixture
+{
+public:
+ CustomizedNameRelation()
+ : checkerPtr(Checker::create(makeSection(R"CONF(
+ type customized
+ sig-type rsa-sha256
+ key-locator
+ {
+ type name
+ name /foo/bar
+ relation equal
+ }
+ )CONF"), "test-config"))
+ , checker(*checkerPtr)
+ {
+ }
+
+public:
+ std::unique_ptr<Checker> checkerPtr;
+ Checker& checker;
+
+ std::vector<std::vector<bool>> outcomes = {{true, false, false, false},
+ {true, false, false, false},
+ {true, false, false, false},
+ {true, false, false, false}};
+};
+
+class CustomizedRegex : public CheckerFixture
+{
+public:
+ CustomizedRegex()
+ : checkerPtr(Checker::create(makeSection(R"CONF(
+ type customized
+ sig-type rsa-sha256
+ key-locator
+ {
+ type name
+ regex ^<foo><bar><KEY><>$
+ }
+ )CONF"), "test-config"))
+ , checker(*checkerPtr)
+ {
+ }
+
+public:
+ std::unique_ptr<Checker> checkerPtr;
+ Checker& checker;
+
+ std::vector<std::vector<bool>> outcomes = {{true, false, false, false},
+ {true, false, false, false},
+ {true, false, false, false},
+ {true, false, false, false}};
+};
+
+class CustomizedHyperRelation : public CheckerFixture
+{
+public:
+ CustomizedHyperRelation()
+ : checkerPtr(Checker::create(makeSection(R"CONF(
+ type customized
+ sig-type rsa-sha256
+ key-locator
+ {
+ type name
+ hyper-relation
+ {
+ k-regex ^(<>+)<KEY><>$
+ k-expand \\1
+ h-relation is-prefix-of
+ p-regex ^(<>+)$
+ p-expand \\1
+ }
+ }
+ )CONF"), "test-config"))
+ , checker(*checkerPtr)
+ {
+ }
+
+public:
+ std::unique_ptr<Checker> checkerPtr;
+ Checker& checker;
+
+ std::vector<std::vector<bool>> outcomes = {{true, false, true, false},
+ {true, true, true, false},
+ {false, false, true, false},
+ {false, false, false, true}};
+};
+
+
+using Tests = boost::mpl::vector<NameRelationEqual, NameRelationIsPrefixOf, NameRelationIsStrictPrefixOf,
+ RegexEqual, RegexIsPrefixOf, RegexIsStrictPrefixOf,
+ HyperRelationEqual, HyperRelationIsPrefixOf, HyperRelationIsStrictPrefixOf,
+ Hierarchical,
+ CustomizedNameRelation, CustomizedRegex, CustomizedHyperRelation>;
+
+
+BOOST_FIXTURE_TEST_CASE_TEMPLATE(Checks, T, Tests, T)
+{
+ BOOST_ASSERT(this->outcomes.size() == this->names.size());
+ for (size_t i = 0; i < this->names.size(); ++i) {
+ BOOST_ASSERT(this->outcomes[i].size() == this->names.size());
+ for (size_t j = 0; j < this->names.size(); ++j) {
+ const Name& pktName = this->names[i];
+ Name klName = this->makeKeyLocatorName(this->names[j]);
+ bool expectedOutcome = this->outcomes[i][j];
+
+ auto dataState = make_shared<DummyValidationState>();
+ BOOST_CHECK_EQUAL(this->checker.check(tlv::Data, pktName, klName, dataState), expectedOutcome);
+ BOOST_CHECK_EQUAL(boost::logic::indeterminate(dataState->getOutcome()), expectedOutcome);
+ if (boost::logic::indeterminate(dataState->getOutcome()) == !expectedOutcome) {
+ BOOST_CHECK_EQUAL(dataState->getOutcome(), !expectedOutcome);
+ }
+
+ auto interestState = make_shared<DummyValidationState>();
+ BOOST_CHECK_EQUAL(this->checker.check(tlv::Interest, this->makeSignedInterestName(pktName),
+ klName, interestState), expectedOutcome);
+ BOOST_CHECK_EQUAL(boost::logic::indeterminate(interestState->getOutcome()), expectedOutcome);
+ if (boost::logic::indeterminate(interestState->getOutcome()) == !expectedOutcome) {
+ BOOST_CHECK_EQUAL(interestState->getOutcome(), !expectedOutcome);
+ }
+ }
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestChecker
+BOOST_AUTO_TEST_SUITE_END() // ValidatorConfig
+BOOST_AUTO_TEST_SUITE_END() // V2
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace validator_config
+} // namespace v2
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/v2/validator-config/common.hpp b/tests/unit/security/v2/validator-config/common.hpp
new file mode 100644
index 0000000..231e8eb
--- /dev/null
+++ b/tests/unit/security/v2/validator-config/common.hpp
@@ -0,0 +1,48 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_TESTS_SECURITY_V2_VALIDATOR_CONFIG_COMMON_HPP
+#define NDN_TESTS_SECURITY_V2_VALIDATOR_CONFIG_COMMON_HPP
+
+#include <boost/property_tree/info_parser.hpp>
+
+namespace ndn {
+namespace security {
+namespace v2 {
+namespace validator_config {
+namespace tests {
+
+inline ConfigSection
+makeSection(const std::string& config)
+{
+ std::istringstream inputStream(config);
+ ConfigSection section;
+ boost::property_tree::read_info(inputStream, section);
+ return section;
+}
+
+} // namespace tests
+} // namespace validator_config
+} // namespace v2
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_TESTS_SECURITY_V2_VALIDATOR_CONFIG_COMMON_HPP
diff --git a/tests/unit/security/v2/validator-config/filter.t.cpp b/tests/unit/security/v2/validator-config/filter.t.cpp
new file mode 100644
index 0000000..fbd1264
--- /dev/null
+++ b/tests/unit/security/v2/validator-config/filter.t.cpp
@@ -0,0 +1,201 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/v2/validator-config/filter.hpp"
+#include "security/command-interest-signer.hpp"
+
+#include "boost-test.hpp"
+#include "common.hpp"
+#include "identity-management-fixture.hpp"
+
+namespace ndn {
+namespace security {
+namespace v2 {
+namespace validator_config {
+namespace tests {
+
+using namespace ndn::tests;
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(V2)
+BOOST_AUTO_TEST_SUITE(ValidatorConfig)
+
+class FilterFixture : public IdentityManagementFixture
+{
+public:
+ Interest
+ makeSignedInterest(const Name& name)
+ {
+ Interest interest(name);
+ m_keyChain.sign(interest);
+ return interest;
+ }
+};
+
+BOOST_FIXTURE_TEST_SUITE(TestFilter, FilterFixture)
+
+#define CHECK_FOR_MATCHES(filter, same, longer, shorter, different) \
+ BOOST_CHECK_EQUAL(filter.match(tlv::Interest, makeSignedInterest("/foo/bar").getName()), same); \
+ BOOST_CHECK_EQUAL(filter.match(tlv::Data, Data("/foo/bar").getName()), same); \
+ BOOST_CHECK_EQUAL(filter.match(tlv::Interest, makeSignedInterest("/foo/bar/bar").getName()), longer); \
+ BOOST_CHECK_EQUAL(filter.match(tlv::Data, Data("/foo/bar/bar").getName()), longer); \
+ BOOST_CHECK_EQUAL(filter.match(tlv::Interest, makeSignedInterest("/foo").getName()), shorter); \
+ BOOST_CHECK_EQUAL(filter.match(tlv::Data, Data("/foo").getName()), shorter); \
+ BOOST_CHECK_EQUAL(filter.match(tlv::Interest, makeSignedInterest("/other/prefix").getName()), different); \
+ BOOST_CHECK_EQUAL(filter.match(tlv::Data, Data("/other/prefix").getName()), different);
+
+BOOST_AUTO_TEST_CASE(RelationName)
+{
+ RelationNameFilter f1("/foo/bar", NameRelation::EQUAL);
+ CHECK_FOR_MATCHES(f1, true, false, false, false);
+
+ RelationNameFilter f2("/foo/bar", NameRelation::IS_PREFIX_OF);
+ CHECK_FOR_MATCHES(f2, true, true, false, false);
+
+ RelationNameFilter f3("/foo/bar", NameRelation::IS_STRICT_PREFIX_OF);
+ CHECK_FOR_MATCHES(f3, false, true, false, false);
+}
+
+BOOST_AUTO_TEST_CASE(RegexName)
+{
+ RegexNameFilter f1(Regex("^<foo><bar>$"));
+ CHECK_FOR_MATCHES(f1, true, false, false, false);
+
+ RegexNameFilter f2(Regex("^<foo><bar><>*$"));
+ CHECK_FOR_MATCHES(f2, true, true, false, false);
+
+ RegexNameFilter f3(Regex("^<foo><bar><>+$"));
+ CHECK_FOR_MATCHES(f3, false, true, false, false);
+}
+
+BOOST_FIXTURE_TEST_SUITE(Create, FilterFixture)
+
+BOOST_AUTO_TEST_CASE(Errors)
+{
+ BOOST_CHECK_THROW(Filter::create(makeSection(""), "test-config"), Error);
+ BOOST_CHECK_THROW(Filter::create(makeSection("type unknown"), "test-config"), Error);
+ BOOST_CHECK_THROW(Filter::create(makeSection("type name"), "test-config"), Error);
+
+ std::string config = R"CONF(
+ type name
+ not-name-or-regex stuff
+ )CONF";
+ BOOST_CHECK_THROW(Filter::create(makeSection(config), "test-config"), Error);
+
+ config = R"CONF(
+ type name
+ name /foo/bar
+ )CONF";
+ BOOST_CHECK_THROW(Filter::create(makeSection(config), "test-config"), Error);
+
+ config = R"CONF(
+ type name
+ name /foo/bar
+ not-relation stuff
+ )CONF";
+ BOOST_CHECK_THROW(Filter::create(makeSection(config), "test-config"), Error);
+
+ config = R"CONF(
+ type name
+ name /foo/bar
+ relation equal
+ not-end stuff
+ )CONF";
+ BOOST_CHECK_THROW(Filter::create(makeSection(config), "test-config"), Error);
+
+ config = R"CONF(
+ type name
+ regex ^<foo><bar>$
+ not-end stuff
+ )CONF";
+ BOOST_CHECK_THROW(Filter::create(makeSection(config), "test-config"), Error);
+}
+
+BOOST_AUTO_TEST_CASE(NameFilter)
+{
+ std::string config = R"CONF(
+ type name
+ name /foo/bar
+ relation equal
+ )CONF";
+ auto f1 = Filter::create(makeSection(config), "test-config");
+ CHECK_FOR_MATCHES((*f1), true, false, false, false);
+
+ config = R"CONF(
+ type name
+ name /foo/bar
+ relation is-prefix-of
+ )CONF";
+ auto f2 = Filter::create(makeSection(config), "test-config");
+ CHECK_FOR_MATCHES((*f2), true, true, false, false);
+
+ config = R"CONF(
+ type name
+ name /foo/bar
+ relation is-strict-prefix-of
+ )CONF";
+ auto f3 = Filter::create(makeSection(config), "test-config");
+ CHECK_FOR_MATCHES((*f3), false, true, false, false);
+}
+
+BOOST_AUTO_TEST_CASE(RegexFilter)
+{
+ std::string config = R"CONF(
+ type name
+ regex ^<foo><bar>$
+ )CONF";
+ auto f1 = Filter::create(makeSection(config), "test-config");
+ CHECK_FOR_MATCHES((*f1), true, false, false, false);
+
+ config = R"CONF(
+ type name
+ regex ^<foo><bar><>*$
+ )CONF";
+ auto f2 = Filter::create(makeSection(config), "test-config");
+ CHECK_FOR_MATCHES((*f2), true, true, false, false);
+
+ config = R"CONF(
+ type name
+ regex ^<foo><bar><>+$
+ )CONF";
+ auto f3 = Filter::create(makeSection(config), "test-config");
+ CHECK_FOR_MATCHES((*f3), false, true, false, false);
+
+ config = R"CONF(
+ type name
+ regex ^<>*$
+ )CONF";
+ auto f4 = Filter::create(makeSection(config), "test-config");
+ CHECK_FOR_MATCHES((*f4), true, true, true, true);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // Create
+
+BOOST_AUTO_TEST_SUITE_END() // TestFilter
+BOOST_AUTO_TEST_SUITE_END() // ValidatorConfig
+BOOST_AUTO_TEST_SUITE_END() // V2
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace validator_config
+} // namespace v2
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/v2/validator-config/name-relation.t.cpp b/tests/unit/security/v2/validator-config/name-relation.t.cpp
new file mode 100644
index 0000000..157b55a
--- /dev/null
+++ b/tests/unit/security/v2/validator-config/name-relation.t.cpp
@@ -0,0 +1,79 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/v2/validator-config/name-relation.hpp"
+
+#include "boost-test.hpp"
+
+#include <boost/lexical_cast.hpp>
+
+namespace ndn {
+namespace security {
+namespace v2 {
+namespace validator_config {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(V2)
+BOOST_AUTO_TEST_SUITE(ValidatorConfig)
+BOOST_AUTO_TEST_SUITE(TestNameRelation)
+
+BOOST_AUTO_TEST_CASE(ToString)
+{
+ BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(NameRelation::EQUAL), "equal");
+ BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(NameRelation::IS_PREFIX_OF),
+ "is-prefix-of");
+ BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(NameRelation::IS_STRICT_PREFIX_OF),
+ "is-strict-prefix-of");
+}
+
+BOOST_AUTO_TEST_CASE(FromString)
+{
+ BOOST_CHECK_EQUAL(getNameRelationFromString("equal"), NameRelation::EQUAL);
+ BOOST_CHECK_EQUAL(getNameRelationFromString("is-prefix-of"), NameRelation::IS_PREFIX_OF);
+ BOOST_CHECK_EQUAL(getNameRelationFromString("is-strict-prefix-of"), NameRelation::IS_STRICT_PREFIX_OF);
+ BOOST_CHECK_THROW(getNameRelationFromString("unknown"), validator_config::Error);
+}
+
+BOOST_AUTO_TEST_CASE(CheckRelation)
+{
+ BOOST_CHECK(checkNameRelation(NameRelation::EQUAL, "/prefix", "/prefix"));
+ BOOST_CHECK(!checkNameRelation(NameRelation::EQUAL, "/prefix", "/prefix/other"));
+
+ BOOST_CHECK(checkNameRelation(NameRelation::IS_PREFIX_OF, "/prefix", "/prefix"));
+ BOOST_CHECK(checkNameRelation(NameRelation::IS_PREFIX_OF, "/prefix", "/prefix/other"));
+ BOOST_CHECK(!checkNameRelation(NameRelation::IS_PREFIX_OF, "/prefix/other", "/prefix"));
+
+ BOOST_CHECK(!checkNameRelation(NameRelation::IS_STRICT_PREFIX_OF, "/prefix", "/prefix"));
+ BOOST_CHECK(checkNameRelation(NameRelation::IS_STRICT_PREFIX_OF, "/prefix", "/prefix/other"));
+ BOOST_CHECK(!checkNameRelation(NameRelation::IS_STRICT_PREFIX_OF, "/prefix/other", "/prefix"));
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestNameRelation
+BOOST_AUTO_TEST_SUITE_END() // ValidatorConfig
+BOOST_AUTO_TEST_SUITE_END() // V2
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace validator_config
+} // namespace v2
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/v2/validator-config/rule.t.cpp b/tests/unit/security/v2/validator-config/rule.t.cpp
new file mode 100644
index 0000000..bb78dfe
--- /dev/null
+++ b/tests/unit/security/v2/validator-config/rule.t.cpp
@@ -0,0 +1,209 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/v2/validator-config/rule.hpp"
+
+#include "boost-test.hpp"
+#include "common.hpp"
+#include "identity-management-fixture.hpp"
+#include "../validator-fixture.hpp"
+
+#include <boost/mpl/vector_c.hpp>
+
+namespace ndn {
+namespace security {
+namespace v2 {
+namespace validator_config {
+namespace tests {
+
+using namespace ndn::tests;
+using namespace ndn::security::v2::tests;
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(V2)
+BOOST_AUTO_TEST_SUITE(ValidatorConfig)
+
+template<uint32_t PktType>
+class RuleFixture : public IdentityManagementFixture
+{
+public:
+ RuleFixture()
+ : rule(ruleId, PktType)
+ , pktName("/foo/bar")
+ {
+ if (PktType == tlv::Interest) {
+ pktName = Name("/foo/bar/SigInfo/SigValue");
+ }
+ }
+
+public:
+ const std::string ruleId = "rule-id";
+ Rule rule;
+ Name pktName;
+};
+
+using PktTypes = boost::mpl::vector_c<uint32_t, tlv::Data, tlv::Interest>;
+
+BOOST_AUTO_TEST_SUITE(TestRule)
+
+BOOST_FIXTURE_TEST_CASE(Errors, RuleFixture<tlv::Data>)
+{
+ BOOST_CHECK_THROW(rule.match(tlv::Interest, this->pktName), Error);
+
+ auto state = make_shared<DummyValidationState>();
+ BOOST_CHECK_THROW(rule.check(tlv::Interest, this->pktName, "/foo/bar", state), Error);
+}
+
+BOOST_FIXTURE_TEST_CASE_TEMPLATE(Constructor, PktType, PktTypes, RuleFixture<PktType::value>)
+{
+ BOOST_CHECK_EQUAL(this->rule.getId(), this->ruleId);
+ BOOST_CHECK_EQUAL(this->rule.getPktType(), PktType::value);
+}
+
+BOOST_FIXTURE_TEST_CASE_TEMPLATE(EmptyRule, PktType, PktTypes, RuleFixture<PktType::value>)
+{
+ BOOST_CHECK_EQUAL(this->rule.match(PktType::value, this->pktName), true);
+
+ auto state = make_shared<DummyValidationState>();
+ BOOST_CHECK_EQUAL(this->rule.check(PktType::value, this->pktName, "/foo/bar", state), false);
+}
+
+BOOST_FIXTURE_TEST_CASE_TEMPLATE(Filters, PktType, PktTypes, RuleFixture<PktType::value>)
+{
+ this->rule.addFilter(make_unique<RegexNameFilter>(Regex("^<foo><bar>$")));
+
+ BOOST_CHECK_EQUAL(this->rule.match(PktType::value, this->pktName), true);
+ BOOST_CHECK_EQUAL(this->rule.match(PktType::value, "/not" + this->pktName.toUri()), false);
+
+ this->rule.addFilter(make_unique<RegexNameFilter>(Regex("^<not><foo><bar>$")));
+
+ BOOST_CHECK_EQUAL(this->rule.match(PktType::value, this->pktName), true);
+ BOOST_CHECK_EQUAL(this->rule.match(PktType::value, "/not" + this->pktName.toUri()), true);
+
+ auto state = make_shared<DummyValidationState>();
+ BOOST_CHECK_EQUAL(this->rule.check(PktType::value, this->pktName, "/foo/bar", state), false);
+}
+
+BOOST_FIXTURE_TEST_CASE_TEMPLATE(Checkers, PktType, PktTypes, RuleFixture<PktType::value>)
+{
+ this->rule.addChecker(make_unique<HyperRelationChecker>("^(<>+)$", "\\1",
+ "^<not>?(<>+)$", "\\1",
+ NameRelation::EQUAL));
+
+ auto state = make_shared<DummyValidationState>();
+ BOOST_CHECK_EQUAL(this->rule.check(PktType::value, this->pktName, "/foo/bar", state), true);
+
+ state = make_shared<DummyValidationState>();
+ BOOST_CHECK_EQUAL(this->rule.check(PktType::value, this->pktName, "/not/foo/bar", state), true);
+
+ this->rule.addChecker(make_unique<HyperRelationChecker>("^(<>+)$", "\\1",
+ "^(<>+)$", "\\1",
+ NameRelation::EQUAL));
+ state = make_shared<DummyValidationState>();
+ BOOST_CHECK_EQUAL(this->rule.check(PktType::value, this->pktName, "/foo/bar", state), true);
+
+ state = make_shared<DummyValidationState>();
+ BOOST_CHECK_EQUAL(this->rule.check(PktType::value, this->pktName, "/not/foo/bar", state), false);
+}
+
+BOOST_AUTO_TEST_SUITE(Create)
+
+BOOST_AUTO_TEST_CASE(Errors)
+{
+ BOOST_CHECK_THROW(Rule::create(makeSection(""), "test-config"), Error);
+
+ std::string config = R"CONF(
+ id rule-id
+ for something
+ )CONF";
+ BOOST_CHECK_THROW(Rule::create(makeSection(config), "test-config"), Error);
+
+ config = R"CONF(
+ id rule-id
+ for data
+ )CONF";
+ BOOST_CHECK_THROW(Rule::create(makeSection(config), "test-config"), Error); // at least one checker required
+
+ config = R"CONF(
+ id rule-id
+ for data
+ checker
+ {
+ type hierarchical
+ sig-type rsa-sha256
+ }
+ other stuff
+ )CONF";
+ BOOST_CHECK_THROW(Rule::create(makeSection(config), "test-config"), Error);
+}
+
+BOOST_FIXTURE_TEST_CASE_TEMPLATE(FilterAndChecker, PktType, PktTypes, RuleFixture<PktType::value>)
+{
+ std::string config = R"CONF(
+ id rule-id
+ for )CONF" + (PktType::value == tlv::Data ? "data"s : "interest"s) + R"CONF(
+ filter
+ {
+ type name
+ regex ^<foo><bar>$
+ }
+ checker
+ {
+ type customized
+ sig-type rsa-sha256
+ key-locator
+ {
+ type name
+ hyper-relation
+ {
+ k-regex ^(<>+)$
+ k-expand \\1
+ h-relation equal
+ p-regex ^(<>+)$
+ p-expand \\1
+ }
+ }
+ }
+ )CONF";
+ auto rule = Rule::create(makeSection(config), "test-config");
+
+ BOOST_CHECK_EQUAL(rule->match(PktType::value, this->pktName), true);
+ BOOST_CHECK_EQUAL(rule->match(PktType::value, "/not" + this->pktName.toUri()), false);
+
+ auto state = make_shared<DummyValidationState>();
+ BOOST_CHECK_EQUAL(rule->check(PktType::value, this->pktName, "/foo/bar", state), true);
+
+ state = make_shared<DummyValidationState>();
+ BOOST_CHECK_EQUAL(rule->check(PktType::value, this->pktName, "/not/foo/bar", state), false);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // Create
+
+BOOST_AUTO_TEST_SUITE_END() // TestRule
+BOOST_AUTO_TEST_SUITE_END() // ValidatorConfig
+BOOST_AUTO_TEST_SUITE_END() // V2
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace validator_config
+} // namespace v2
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/v2/validator-fixture.hpp b/tests/unit/security/v2/validator-fixture.hpp
new file mode 100644
index 0000000..c9a5763
--- /dev/null
+++ b/tests/unit/security/v2/validator-fixture.hpp
@@ -0,0 +1,183 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_TESTS_SECURITY_V2_VALIDATOR_FIXTURE_HPP
+#define NDN_TESTS_SECURITY_V2_VALIDATOR_FIXTURE_HPP
+
+#include "security/v2/validator.hpp"
+#include "security/v2/certificate-fetcher-from-network.hpp"
+#include "util/dummy-client-face.hpp"
+
+#include "../../identity-management-time-fixture.hpp"
+
+#include <boost/lexical_cast.hpp>
+
+namespace ndn {
+namespace security {
+namespace v2 {
+namespace tests {
+
+template<class ValidationPolicy, class CertificateFetcher = CertificateFetcherFromNetwork>
+class ValidatorFixture : public ndn::tests::IdentityManagementTimeFixture
+{
+public:
+ ValidatorFixture()
+ : face(io, {true, true})
+ , validator(make_unique<ValidationPolicy>(), make_unique<CertificateFetcher>(face))
+ , policy(static_cast<ValidationPolicy&>(validator.getPolicy()))
+ , cache(100_days)
+ {
+ processInterest = [this] (const Interest& interest) {
+ auto cert = cache.find(interest);
+ if (cert != nullptr) {
+ face.receive(*cert);
+ }
+ };
+ }
+
+ virtual
+ ~ValidatorFixture() = default;
+
+ template<class Packet>
+ void
+ validate(const Packet& packet, const std::string& msg, bool expectSuccess, int line)
+ {
+ std::string detailedInfo = msg + " on line " + to_string(line);
+ size_t nCallbacks = 0;
+ this->validator.validate(packet,
+ [&] (const Packet&) {
+ ++nCallbacks;
+ BOOST_CHECK_MESSAGE(expectSuccess,
+ (expectSuccess ? "OK: " : "FAILED: ") + detailedInfo);
+ },
+ [&] (const Packet&, const ValidationError& error) {
+ ++nCallbacks;
+ BOOST_CHECK_MESSAGE(!expectSuccess,
+ (!expectSuccess ? "OK: " : "FAILED: ") + detailedInfo +
+ (expectSuccess ? " (" + boost::lexical_cast<std::string>(error) + ")" : ""));
+ });
+
+ mockNetworkOperations();
+ BOOST_CHECK_EQUAL(nCallbacks, 1);
+ }
+
+ void
+ mockNetworkOperations()
+ {
+ util::signal::ScopedConnection connection = face.onSendInterest.connect([this] (const Interest& interest) {
+ if (processInterest != nullptr) {
+ io.post(bind(processInterest, interest));
+ }
+ });
+ advanceClocks(time::milliseconds(s_mockPeriod), s_mockTimes);
+ }
+
+ /** \brief undo clock advancement of mockNetworkOperations
+ */
+ void
+ rewindClockAfterValidation()
+ {
+ this->systemClock->advance(time::milliseconds(s_mockPeriod * s_mockTimes * -1));
+ }
+
+public:
+ util::DummyClientFace face;
+ std::function<void(const Interest& interest)> processInterest;
+ Validator validator;
+ ValidationPolicy& policy;
+
+ CertificateCache cache;
+
+private:
+ const static int s_mockPeriod;
+ const static int s_mockTimes;
+};
+
+template<class ValidationPolicy, class CertificateFetcher>
+const int ValidatorFixture<ValidationPolicy, CertificateFetcher>::s_mockPeriod = 250;
+
+template<class ValidationPolicy, class CertificateFetcher>
+const int ValidatorFixture<ValidationPolicy, CertificateFetcher>::s_mockTimes = 200;
+
+template<class ValidationPolicy, class CertificateFetcher = CertificateFetcherFromNetwork>
+class HierarchicalValidatorFixture : public ValidatorFixture<ValidationPolicy, CertificateFetcher>
+{
+public:
+ HierarchicalValidatorFixture()
+ {
+ identity = this->addIdentity("/Security/V2/ValidatorFixture");
+ subIdentity = this->addSubCertificate("/Security/V2/ValidatorFixture/Sub1", identity);
+ subSelfSignedIdentity = this->addIdentity("/Security/V2/ValidatorFixture/Sub1/Sub2");
+ otherIdentity = this->addIdentity("/Security/V2/OtherIdentity");
+
+ this->validator.loadAnchor("", Certificate(identity.getDefaultKey().getDefaultCertificate()));
+
+ this->cache.insert(identity.getDefaultKey().getDefaultCertificate());
+ this->cache.insert(subIdentity.getDefaultKey().getDefaultCertificate());
+ this->cache.insert(subSelfSignedIdentity.getDefaultKey().getDefaultCertificate());
+ this->cache.insert(otherIdentity.getDefaultKey().getDefaultCertificate());
+ }
+
+public:
+ Identity identity;
+ Identity subIdentity;
+ Identity subSelfSignedIdentity;
+ Identity otherIdentity;
+};
+
+#define VALIDATE_SUCCESS(packet, message) this->template validate(packet, message, true, __LINE__)
+#define VALIDATE_FAILURE(packet, message) this->template validate(packet, message, false, __LINE__)
+
+class DummyValidationState : public ValidationState
+{
+public:
+ ~DummyValidationState()
+ {
+ m_outcome = false;
+ }
+
+ void
+ fail(const ValidationError& error) override
+ {
+ // BOOST_TEST_MESSAGE(error);
+ m_outcome = false;
+ }
+
+private:
+ void
+ verifyOriginalPacket(const Certificate& trustedCert) override
+ {
+ // do nothing
+ }
+
+ void
+ bypassValidation() override
+ {
+ // do nothing
+ }
+};
+
+} // namespace tests
+} // namespace v2
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_TESTS_SECURITY_V2_VALIDATOR_FIXTURE_HPP
diff --git a/tests/unit/security/v2/validator.t.cpp b/tests/unit/security/v2/validator.t.cpp
new file mode 100644
index 0000000..ff33984
--- /dev/null
+++ b/tests/unit/security/v2/validator.t.cpp
@@ -0,0 +1,344 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/v2/validator.hpp"
+#include "security/v2/validation-policy-simple-hierarchy.hpp"
+
+#include "boost-test.hpp"
+#include "validator-fixture.hpp"
+
+namespace ndn {
+namespace security {
+namespace v2 {
+namespace tests {
+
+using namespace ndn::tests;
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(V2)
+BOOST_FIXTURE_TEST_SUITE(TestValidator, HierarchicalValidatorFixture<ValidationPolicySimpleHierarchy>)
+
+BOOST_AUTO_TEST_CASE(ConstructorSetValidator)
+{
+ auto middlePolicy = make_unique<ValidationPolicySimpleHierarchy>();
+ auto innerPolicy = make_unique<ValidationPolicySimpleHierarchy>();
+
+ validator.getPolicy().setInnerPolicy(std::move(middlePolicy));
+ validator.getPolicy().setInnerPolicy(std::move(innerPolicy));
+
+ BOOST_CHECK(validator.getPolicy().m_validator != nullptr);
+ BOOST_CHECK(validator.getPolicy().getInnerPolicy().m_validator != nullptr);
+ BOOST_CHECK(validator.getPolicy().getInnerPolicy().getInnerPolicy().m_validator != nullptr);
+}
+
+BOOST_AUTO_TEST_CASE(Timeouts)
+{
+ processInterest = nullptr; // no response for all interests
+
+ Data data("/Security/V2/ValidatorFixture/Sub1/Sub2/Data");
+ m_keyChain.sign(data, signingByIdentity(subIdentity));
+
+ VALIDATE_FAILURE(data, "Should fail to retrieve certificate");
+ BOOST_CHECK_GT(face.sentInterests.size(), 1);
+}
+
+BOOST_AUTO_TEST_CASE(NackedInterests)
+{
+ processInterest = [this] (const Interest& interest) {
+ lp::Nack nack(interest);
+ nack.setReason(lp::NackReason::NO_ROUTE);
+ face.receive(nack);
+ };
+
+ Data data("/Security/V2/ValidatorFixture/Sub1/Sub2/Data");
+ m_keyChain.sign(data, signingByIdentity(subIdentity));
+
+ VALIDATE_FAILURE(data, "All interests should get NACKed");
+ // 1 for the first interest, 3 for the retries on nack
+ BOOST_CHECK_EQUAL(face.sentInterests.size(), 4);
+}
+
+BOOST_AUTO_TEST_CASE(MalformedCert)
+{
+ Data malformedCert = subIdentity.getDefaultKey().getDefaultCertificate();
+ malformedCert.setContentType(tlv::ContentType_Blob);
+ m_keyChain.sign(malformedCert, signingByIdentity(identity));
+ // wrong content type & missing ValidityPeriod
+ BOOST_REQUIRE_THROW(Certificate(malformedCert.wireEncode()), tlv::Error);
+
+ auto originalProcessInterest = processInterest;
+ processInterest = [this, &originalProcessInterest, &malformedCert] (const Interest& interest) {
+ if (interest.getName().isPrefixOf(malformedCert.getName())) {
+ face.receive(malformedCert);
+ }
+ else {
+ originalProcessInterest(interest);
+ }
+ };
+
+ Data data("/Security/V2/ValidatorFixture/Sub1/Sub2/Data");
+ m_keyChain.sign(data, signingByIdentity(subIdentity));
+
+ VALIDATE_FAILURE(data, "Signed by a malformed certificate");
+ BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
+}
+
+BOOST_AUTO_TEST_CASE(ExpiredCert)
+{
+ Data expiredCert = subIdentity.getDefaultKey().getDefaultCertificate();
+ SignatureInfo info;
+ info.setValidityPeriod(ValidityPeriod(time::system_clock::now() - 2_h,
+ time::system_clock::now() - 1_h));
+ m_keyChain.sign(expiredCert, signingByIdentity(identity).setSignatureInfo(info));
+ BOOST_REQUIRE_NO_THROW(Certificate(expiredCert.wireEncode()));
+
+ auto originalProcessInterest = processInterest;
+ processInterest = [this, &originalProcessInterest, &expiredCert] (const Interest& interest) {
+ if (interest.getName().isPrefixOf(expiredCert.getName())) {
+ face.receive(expiredCert);
+ }
+ else {
+ originalProcessInterest(interest);
+ }
+ };
+
+ Data data("/Security/V2/ValidatorFixture/Sub1/Sub2/Data");
+ m_keyChain.sign(data, signingByIdentity(subIdentity));
+
+ VALIDATE_FAILURE(data, "Signed by an expired certificate");
+ BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
+}
+
+BOOST_AUTO_TEST_CASE(ResetAnchors)
+{
+ validator.resetAnchors();
+
+ Data data("/Security/V2/ValidatorFixture/Sub1/Sub2/Data");
+ m_keyChain.sign(data, signingByIdentity(subIdentity));
+ VALIDATE_FAILURE(data, "Should fail, as no anchors configured");
+}
+
+BOOST_AUTO_TEST_CASE(TrustedCertCaching)
+{
+ Data data("/Security/V2/ValidatorFixture/Sub1/Sub2/Data");
+ m_keyChain.sign(data, signingByIdentity(subIdentity));
+
+ VALIDATE_SUCCESS(data, "Should get accepted, as signed by the policy-compliant cert");
+ BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
+ face.sentInterests.clear();
+
+ processInterest = nullptr; // disable data responses from mocked network
+
+ VALIDATE_SUCCESS(data, "Should get accepted, based on the cached trusted cert");
+ BOOST_CHECK_EQUAL(face.sentInterests.size(), 0);
+ face.sentInterests.clear();
+
+ advanceClocks(1_h, 2); // expire trusted cache
+
+ VALIDATE_FAILURE(data, "Should try and fail to retrieve certs");
+ BOOST_CHECK_GT(face.sentInterests.size(), 1);
+ face.sentInterests.clear();
+}
+
+BOOST_AUTO_TEST_CASE(ResetVerifiedCertificates)
+{
+ Data data("/Security/V2/ValidatorFixture/Sub1/Sub2/Data");
+ m_keyChain.sign(data, signingByIdentity(subIdentity));
+ VALIDATE_SUCCESS(data, "Should get accepted, as signed by the policy-compliant cert");
+
+ // reset anchors
+ validator.resetAnchors();
+ VALIDATE_SUCCESS(data, "Should get accepted, as signed by the cert in trusted cache");
+
+ // reset trusted cache
+ validator.resetVerifiedCertificates();
+ VALIDATE_FAILURE(data, "Should fail, as no trusted cache or anchors");
+}
+
+BOOST_AUTO_TEST_CASE(UntrustedCertCaching)
+{
+ Data data("/Security/V2/ValidatorFixture/Sub1/Sub2/Data");
+ m_keyChain.sign(data, signingByIdentity(subSelfSignedIdentity));
+
+ VALIDATE_FAILURE(data, "Should fail, as signed by the policy-violating cert");
+ BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
+ face.sentInterests.clear();
+
+ processInterest = nullptr; // disable data responses from mocked network
+
+ VALIDATE_FAILURE(data, "Should fail again, but no network operations expected");
+ BOOST_CHECK_EQUAL(face.sentInterests.size(), 0);
+ face.sentInterests.clear();
+
+ advanceClocks(10_min, 2); // expire untrusted cache
+
+ VALIDATE_FAILURE(data, "Should try and fail to retrieve certs");
+ BOOST_CHECK_GT(face.sentInterests.size(), 1);
+ face.sentInterests.clear();
+}
+
+class ValidationPolicySimpleHierarchyForInterestOnly : public ValidationPolicySimpleHierarchy
+{
+public:
+ void
+ checkPolicy(const Data& data, const shared_ptr<ValidationState>& state,
+ const ValidationContinuation& continueValidation) override
+ {
+ continueValidation(nullptr, state);
+ }
+};
+
+BOOST_FIXTURE_TEST_CASE(ValidateInterestsButBypassForData,
+ HierarchicalValidatorFixture<ValidationPolicySimpleHierarchyForInterestOnly>)
+{
+ Interest interest("/Security/V2/ValidatorFixture/Sub1/Sub2/Interest");
+ Data data("/Security/V2/ValidatorFixture/Sub1/Sub2/Interest");
+
+ VALIDATE_FAILURE(interest, "Unsigned");
+ VALIDATE_SUCCESS(data, "Policy requests validation bypassing for all data");
+ BOOST_CHECK_EQUAL(face.sentInterests.size(), 0);
+ face.sentInterests.clear();
+
+ interest = Interest("/Security/V2/ValidatorFixture/Sub1/Sub2/Interest");
+ m_keyChain.sign(interest, signingWithSha256());
+ m_keyChain.sign(data, signingWithSha256());
+ VALIDATE_FAILURE(interest, "Required KeyLocator/Name missing (not passed to policy)");
+ VALIDATE_SUCCESS(data, "Policy requests validation bypassing for all data");
+ BOOST_CHECK_EQUAL(face.sentInterests.size(), 0);
+ face.sentInterests.clear();
+
+ m_keyChain.sign(interest, signingByIdentity(identity));
+ m_keyChain.sign(data, signingByIdentity(identity));
+ VALIDATE_SUCCESS(interest, "Should get accepted, as signed by the anchor");
+ VALIDATE_SUCCESS(data, "Policy requests validation bypassing for all data");
+ BOOST_CHECK_EQUAL(face.sentInterests.size(), 0);
+ face.sentInterests.clear();
+
+ m_keyChain.sign(interest, signingByIdentity(subIdentity));
+ m_keyChain.sign(data, signingByIdentity(subIdentity));
+ VALIDATE_FAILURE(interest, "Should fail, as policy is not allowed to create new trust anchors");
+ VALIDATE_SUCCESS(data, "Policy requests validation bypassing for all data");
+ BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
+ face.sentInterests.clear();
+
+ m_keyChain.sign(interest, signingByIdentity(otherIdentity));
+ m_keyChain.sign(data, signingByIdentity(otherIdentity));
+ VALIDATE_FAILURE(interest, "Should fail, as signed by the policy-violating cert");
+ VALIDATE_SUCCESS(data, "Policy requests validation bypassing for all data");
+ // no network operations expected, as certificate is not validated by the policy
+ BOOST_CHECK_EQUAL(face.sentInterests.size(), 0);
+ face.sentInterests.clear();
+
+ advanceClocks(1_h, 2); // expire trusted cache
+
+ m_keyChain.sign(interest, signingByIdentity(subSelfSignedIdentity));
+ m_keyChain.sign(data, signingByIdentity(subSelfSignedIdentity));
+ VALIDATE_FAILURE(interest, "Should fail, as policy is not allowed to create new trust anchors");
+ VALIDATE_SUCCESS(data, "Policy requests validation bypassing for all data");
+ BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
+ face.sentInterests.clear();
+}
+
+BOOST_AUTO_TEST_CASE(InfiniteCertChain)
+{
+ processInterest = [this] (const Interest& interest) {
+ // create another key for the same identity and sign it properly
+ Key parentKey = m_keyChain.createKey(subIdentity);
+ Key requestedKey = subIdentity.getKey(interest.getName());
+
+ Name certificateName = requestedKey.getName();
+ certificateName
+ .append("looper")
+ .appendVersion();
+ v2::Certificate certificate;
+ certificate.setName(certificateName);
+
+ // set metainfo
+ certificate.setContentType(tlv::ContentType_Key);
+ certificate.setFreshnessPeriod(1_h);
+
+ // set content
+ certificate.setContent(requestedKey.getPublicKey().data(), requestedKey.getPublicKey().size());
+
+ // set signature-info
+ SignatureInfo info;
+ info.setValidityPeriod(security::ValidityPeriod(time::system_clock::now() - 10_days,
+ time::system_clock::now() + 10_days));
+
+ m_keyChain.sign(certificate, signingByKey(parentKey).setSignatureInfo(info));
+ face.receive(certificate);
+ };
+
+ Data data("/Security/V2/ValidatorFixture/Sub1/Sub2/Data");
+ m_keyChain.sign(data, signingByIdentity(subIdentity));
+
+ validator.setMaxDepth(40);
+ BOOST_CHECK_EQUAL(validator.getMaxDepth(), 40);
+ VALIDATE_FAILURE(data, "Should fail, as certificate should be looped");
+ BOOST_CHECK_EQUAL(face.sentInterests.size(), 40);
+ face.sentInterests.clear();
+
+ advanceClocks(1_h, 5); // expire caches
+
+ validator.setMaxDepth(30);
+ BOOST_CHECK_EQUAL(validator.getMaxDepth(), 30);
+ VALIDATE_FAILURE(data, "Should fail, as certificate chain is infinite");
+ BOOST_CHECK_EQUAL(face.sentInterests.size(), 30);
+}
+
+BOOST_AUTO_TEST_CASE(LoopedCertChain)
+{
+ auto s1 = addIdentity("/loop");
+ auto k1 = m_keyChain.createKey(s1, RsaKeyParams(name::Component("key1")));
+ auto k2 = m_keyChain.createKey(s1, RsaKeyParams(name::Component("key2")));
+ auto k3 = m_keyChain.createKey(s1, RsaKeyParams(name::Component("key3")));
+
+ auto makeCert = [this] (Key& key, const Key& signer) {
+ v2::Certificate request = key.getDefaultCertificate();
+ request.setName(Name(key.getName()).append("looper").appendVersion());
+
+ SignatureInfo info;
+ info.setValidityPeriod({time::system_clock::now() - 100_days,
+ time::system_clock::now() + 100_days});
+ m_keyChain.sign(request, signingByKey(signer).setSignatureInfo(info));
+ m_keyChain.addCertificate(key, request);
+
+ cache.insert(request);
+ };
+
+ makeCert(k1, k2);
+ makeCert(k2, k3);
+ makeCert(k3, k1);
+
+ Data data("/loop/Data");
+ m_keyChain.sign(data, signingByKey(k1));
+ VALIDATE_FAILURE(data, "Should fail, as certificate chain loops");
+ BOOST_CHECK_EQUAL(face.sentInterests.size(), 3);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestValidator
+BOOST_AUTO_TEST_SUITE_END() // V2
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace v2
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/validator-config.t.cpp b/tests/unit/security/validator-config.t.cpp
new file mode 100644
index 0000000..3e49d24
--- /dev/null
+++ b/tests/unit/security/validator-config.t.cpp
@@ -0,0 +1,159 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/validator-config.hpp"
+#include "security/command-interest-signer.hpp"
+#include "security/v2/certificate-fetcher-offline.hpp"
+#include "util/dummy-client-face.hpp"
+
+#include "boost-test.hpp"
+#include "identity-management-fixture.hpp"
+#include "v2/validator-config/common.hpp"
+
+namespace ndn {
+namespace security {
+namespace tests {
+
+using namespace ndn::tests;
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_FIXTURE_TEST_SUITE(TestValidatorConfig, IdentityManagementFixture)
+
+// This test only for API, actual tests are in ValidationPolicyConfig and corresponding CertificateFetchers
+
+BOOST_AUTO_TEST_CASE(Construct)
+{
+ util::DummyClientFace face;
+
+ ValidatorConfig v1(face);
+ BOOST_CHECK_EQUAL(v1.m_policyConfig.m_isConfigured, false);
+
+ ValidatorConfig v2(make_unique<v2::CertificateFetcherOffline>());
+ BOOST_CHECK_EQUAL(v2.m_policyConfig.m_isConfigured, false);
+}
+
+class ValidatorConfigFixture : public IdentityManagementFixture
+{
+public:
+ ValidatorConfigFixture()
+ : path(boost::filesystem::path(UNIT_TEST_CONFIG_PATH) / "security" / "validator-config")
+ , validator(make_unique<v2::CertificateFetcherOffline>())
+ {
+ boost::filesystem::create_directories(path);
+ config = R"CONF(
+ trust-anchor
+ {
+ type any
+ }
+ )CONF";
+ configFile = (this->path / "config.conf").string();
+ std::ofstream f(configFile.c_str());
+ f << config;
+ }
+
+ ~ValidatorConfigFixture()
+ {
+ boost::filesystem::remove_all(path);
+ }
+
+public:
+ const boost::filesystem::path path;
+ std::string config;
+ std::string configFile;
+ ValidatorConfig validator;
+};
+
+BOOST_FIXTURE_TEST_SUITE(Loads, ValidatorConfigFixture)
+
+BOOST_AUTO_TEST_CASE(FromFile)
+{
+ validator.load(configFile);
+ BOOST_CHECK_EQUAL(validator.m_policyConfig.m_isConfigured, true);
+
+ // should reload policy
+ validator.load(configFile);
+ BOOST_CHECK_EQUAL(validator.m_policyConfig.m_isConfigured, true);
+}
+
+BOOST_AUTO_TEST_CASE(FromString)
+{
+ validator.load(config, "config-file-from-string");
+ BOOST_CHECK_EQUAL(validator.m_policyConfig.m_isConfigured, true);
+
+ // should reload policy
+ validator.load(config, "config-file-from-string");
+ BOOST_CHECK_EQUAL(validator.m_policyConfig.m_isConfigured, true);
+}
+
+BOOST_AUTO_TEST_CASE(FromIstream)
+{
+ std::istringstream is(config);
+ validator.load(is, "config-file-from-istream");
+ BOOST_CHECK_EQUAL(validator.m_policyConfig.m_isConfigured, true);
+
+ // should reload policy
+ std::istringstream is2(config);
+ validator.load(is2, "config-file-from-istream");
+ BOOST_CHECK_EQUAL(validator.m_policyConfig.m_isConfigured, true);
+}
+
+BOOST_AUTO_TEST_CASE(FromSection)
+{
+ validator.load(v2::validator_config::tests::makeSection(config), "config-file-from-section");
+ BOOST_CHECK_EQUAL(validator.m_policyConfig.m_isConfigured, true);
+
+ // should reload policy
+ validator.load(v2::validator_config::tests::makeSection(config), "config-file-from-section");
+ BOOST_CHECK_EQUAL(validator.m_policyConfig.m_isConfigured, true);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // Loads
+
+
+BOOST_FIXTURE_TEST_CASE(ValidateCommandInterestWithDigestSha256, ValidatorConfigFixture) // Bug 4635
+{
+ validator.load(configFile);
+
+ CommandInterestSigner signer(m_keyChain);
+ auto i = signer.makeCommandInterest("/hello/world/CMD", signingWithSha256());
+ size_t nValidated = 0, nFailed = 0;
+
+ validator.validate(i, [&] (auto&&...) { ++nValidated; }, [&] (auto&&...) { ++nFailed; });
+ BOOST_CHECK_EQUAL(nValidated, 1);
+ BOOST_CHECK_EQUAL(nFailed, 0);
+
+ validator.validate(i, [&] (auto&&...) { ++nValidated; }, [&] (auto&&...) { ++nFailed; });
+ BOOST_CHECK_EQUAL(nValidated, 1);
+ BOOST_CHECK_EQUAL(nFailed, 1);
+
+ i = signer.makeCommandInterest("/hello/world/CMD", signingWithSha256());
+ validator.validate(i, [&] (auto&&...) { ++nValidated; }, [&] (auto&&...) { ++nFailed; });
+ BOOST_CHECK_EQUAL(nValidated, 2);
+ BOOST_CHECK_EQUAL(nFailed, 1);
+}
+
+
+BOOST_AUTO_TEST_SUITE_END() // TestValidatorConfig
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/validator-null.t.cpp b/tests/unit/security/validator-null.t.cpp
new file mode 100644
index 0000000..69cef48
--- /dev/null
+++ b/tests/unit/security/validator-null.t.cpp
@@ -0,0 +1,66 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/validator-null.hpp"
+
+#include "boost-test.hpp"
+#include "identity-management-fixture.hpp"
+#include "make-interest-data.hpp"
+
+namespace ndn {
+namespace security {
+namespace tests {
+
+using namespace ndn::tests;
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_FIXTURE_TEST_SUITE(TestValidatorNull, IdentityManagementFixture)
+
+BOOST_AUTO_TEST_CASE(ValidateData)
+{
+ auto identity = addIdentity("/TestValidator/Null");
+ Data data("/Some/Other/Data/Name");
+ m_keyChain.sign(data, signingByIdentity(identity));
+
+ ValidatorNull validator;
+ validator.validate(data,
+ bind([] { BOOST_CHECK_MESSAGE(true, "Validation should succeed"); }),
+ bind([] { BOOST_CHECK_MESSAGE(false, "Validation should not have failed"); }));
+}
+
+BOOST_AUTO_TEST_CASE(ValidateInterest)
+{
+ auto identity = addIdentity("/TestValidator/Null");
+ Interest interest("/Some/Other/Interest/Name");
+ m_keyChain.sign(interest, signingByIdentity(identity));
+
+ ValidatorNull validator;
+ validator.validate(interest,
+ bind([] { BOOST_CHECK_MESSAGE(true, "Validation should succeed"); }),
+ bind([] { BOOST_CHECK_MESSAGE(false, "Validation should not have failed"); }));
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestValidatorNull
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/validity-period.t.cpp b/tests/unit/security/validity-period.t.cpp
new file mode 100644
index 0000000..14d2a0f
--- /dev/null
+++ b/tests/unit/security/validity-period.t.cpp
@@ -0,0 +1,200 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/validity-period.hpp"
+
+#include "boost-test.hpp"
+#include "../unit-test-time-fixture.hpp"
+
+#include <boost/lexical_cast.hpp>
+
+namespace ndn {
+namespace security {
+namespace tests {
+
+using namespace ndn::tests;
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(TestValidityPeriod)
+
+BOOST_FIXTURE_TEST_CASE(ConstructorSetter, UnitTestTimeFixture)
+{
+ time::system_clock::TimePoint now = this->systemClock->getNow();
+
+ time::system_clock::TimePoint notBefore = now - 1_day;
+ time::system_clock::TimePoint notAfter = notBefore + 2_days;
+
+ ValidityPeriod validity1 = ValidityPeriod(notBefore, notAfter);
+
+ auto period = validity1.getPeriod();
+ BOOST_CHECK_GE(period.first, notBefore); // fractional seconds will be removed
+ BOOST_CHECK_LT(period.first, notBefore + 1_s);
+
+ BOOST_CHECK_LE(period.second, notAfter); // fractional seconds will be removed
+ BOOST_CHECK_GT(period.second, notAfter - 1_s);
+ BOOST_CHECK_EQUAL(validity1.isValid(), true);
+
+ BOOST_CHECK_EQUAL(ValidityPeriod(now - 2_days, now - 1_day).isValid(), false);
+
+ BOOST_CHECK_NO_THROW((ValidityPeriod()));
+ ValidityPeriod validity2;
+ BOOST_CHECK_EQUAL(validity2.isValid(), false);
+
+ validity2.setPeriod(notBefore, notAfter);
+ BOOST_CHECK(validity2.getPeriod() != std::make_pair(time::getUnixEpoch(), time::getUnixEpoch()));
+ BOOST_CHECK_EQUAL(validity2, validity1);
+
+ validity1.setPeriod(time::getUnixEpoch(), time::getUnixEpoch() + 10 * 365_days);
+ BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(validity1),
+ "(19700101T000000, 19791230T000000)");
+
+ validity1.setPeriod(time::getUnixEpoch() + 1_ns,
+ time::getUnixEpoch() + (10 * 365_days) + 1_ns);
+ BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(validity1),
+ "(19700101T000001, 19791230T000000)");
+
+ BOOST_CHECK_EQUAL(ValidityPeriod(now, now).isValid(), true);
+ BOOST_CHECK_EQUAL(ValidityPeriod(now + 1_s, now).isValid(), false);
+}
+
+const uint8_t VP1[] = {
+ 0xfd, 0x00, 0xfd, 0x26, // ValidityPeriod
+ 0xfd, 0x00, 0xfe, 0x0f, // NotBefore
+ 0x31, 0x39, 0x37, 0x30, 0x30, 0x31, 0x30, 0x31, // 19700101T000000
+ 0x54, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0xfd, 0x00, 0xff, 0x0f, // NotAfter
+ 0x31, 0x39, 0x37, 0x30, 0x30, 0x31, 0x30, 0x32, // 19700102T000000
+ 0x54, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30
+};
+
+BOOST_AUTO_TEST_CASE(EncodingDecoding)
+{
+ time::system_clock::TimePoint notBefore = time::getUnixEpoch();
+ time::system_clock::TimePoint notAfter = notBefore + 1_day;
+
+ ValidityPeriod v1(notBefore, notAfter);
+
+ BOOST_CHECK_EQUAL_COLLECTIONS(v1.wireEncode().begin(), v1.wireEncode().end(),
+ VP1, VP1 + sizeof(VP1));
+
+ BOOST_REQUIRE_NO_THROW(ValidityPeriod(Block(VP1, sizeof(VP1))));
+ Block block(VP1, sizeof(VP1));
+ ValidityPeriod v2(block);
+ BOOST_CHECK(v1.getPeriod() == v2.getPeriod());
+}
+
+const uint8_t VP_E1[] = {
+ 0xfd, 0x00, 0xff, 0x26, // ValidityPeriod (error)
+ 0xfd, 0x00, 0xfe, 0x0f, // NotBefore
+ 0x31, 0x39, 0x37, 0x30, 0x30, 0x31, 0x30, 0x31, // 19700101T000000
+ 0x54, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0xfd, 0x00, 0xff, 0x0f, // NotAfter
+ 0x31, 0x39, 0x37, 0x30, 0x30, 0x31, 0x30, 0x32, // 19700102T000000
+ 0x54, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30
+};
+
+const uint8_t VP_E2[] = {
+ 0xfd, 0x00, 0xfd, 0x26, // ValidityPeriod
+ 0xfd, 0x00, 0xff, 0x0f, // NotBefore (error)
+ 0x31, 0x39, 0x37, 0x30, 0x30, 0x31, 0x30, 0x31, // 19700101T000000
+ 0x54, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0xfd, 0x00, 0xff, 0x0f, // NotAfter
+ 0x31, 0x39, 0x37, 0x30, 0x30, 0x31, 0x30, 0x32, // 19700102T000000
+ 0x54, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30
+};
+
+const uint8_t VP_E3[] = {
+ 0xfd, 0x00, 0xfd, 0x26, // ValidityPeriod
+ 0xfd, 0x00, 0xfe, 0x0f, // NotBefore
+ 0x31, 0x39, 0x37, 0x30, 0x30, 0x31, 0x30, 0x31, // 19700101T000000
+ 0x54, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0xfd, 0x00, 0xfe, 0x0f, // NotAfter (error)
+ 0x31, 0x39, 0x37, 0x30, 0x30, 0x31, 0x30, 0x32, // 19700102T000000
+ 0x54, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30
+};
+
+const uint8_t VP_E4[] = {
+ 0xfd, 0x00, 0xfd, 0x39, // ValidityPeriod
+ 0xfd, 0x00, 0xfe, 0x0f, // NotBefore
+ 0x31, 0x39, 0x37, 0x30, 0x30, 0x31, 0x30, 0x31, // 19700101T000000
+ 0x54, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0xfd, 0x00, 0xff, 0x0f, // NotAfter
+ 0x31, 0x39, 0x37, 0x30, 0x30, 0x31, 0x30, 0x32, // 19700102T000000
+ 0x54, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0xfd, 0x00, 0xff, 0x0f, // NotAfter (error)
+ 0x31, 0x39, 0x37, 0x30, 0x30, 0x31, 0x30, 0x32, // 19700102T000000
+ 0x54, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30
+};
+
+const uint8_t VP_E5[] = {
+ 0xfd, 0x00, 0xfd, 0x13, // ValidityPeriod
+ 0xfd, 0x00, 0xfe, 0x0f, // NotBefore
+ 0x31, 0x39, 0x37, 0x30, 0x30, 0x31, 0x30, 0x31, // 19700101T000000
+ 0x54, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30
+};
+
+const uint8_t VP_E6[] = {
+ 0xfd, 0x00, 0xfd, 0x26, // ValidityPeriod
+ 0xfd, 0x00, 0xfe, 0x0f, // NotBefore
+ 0x31, 0x39, 0x37, 0x30, 0x30, 0x31, 0x30, 0x31, // 19700101T00000\xFF
+ 0x54, 0x30, 0x30, 0x30, 0x30, 0x30, 0xFF,
+ 0xfd, 0x00, 0xff, 0x0f, // NotAfter
+ 0x31, 0x39, 0x37, 0x30, 0x30, 0x31, 0x30, 0x32, // 19700102T000000
+ 0x54, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30
+};
+
+
+BOOST_AUTO_TEST_CASE(DecodingError)
+{
+ BOOST_CHECK_THROW(ValidityPeriod(Block(VP_E1, sizeof(VP_E1))), ValidityPeriod::Error);
+
+ BOOST_CHECK_THROW(ValidityPeriod(Block(VP_E2, sizeof(VP_E2))), ValidityPeriod::Error);
+ BOOST_CHECK_THROW(ValidityPeriod(Block(VP_E3, sizeof(VP_E3))), ValidityPeriod::Error);
+
+ BOOST_CHECK_THROW(ValidityPeriod(Block(VP_E4, sizeof(VP_E4))), ValidityPeriod::Error);
+ BOOST_CHECK_THROW(ValidityPeriod(Block(VP_E5, sizeof(VP_E5))), ValidityPeriod::Error);
+
+ Block emptyBlock;
+ BOOST_CHECK_THROW((ValidityPeriod(emptyBlock)), ValidityPeriod::Error);
+
+ BOOST_CHECK_THROW(ValidityPeriod(Block(VP_E6, sizeof(VP_E6))), ValidityPeriod::Error);
+}
+
+BOOST_AUTO_TEST_CASE(Comparison)
+{
+ time::system_clock::TimePoint notBefore = time::getUnixEpoch();
+ time::system_clock::TimePoint notAfter = notBefore + 1_day;
+ time::system_clock::TimePoint notAfter2 = notBefore + 2_days;
+
+ ValidityPeriod validity1(notBefore, notAfter);
+ ValidityPeriod validity2(notBefore, notAfter);
+ BOOST_CHECK(validity1 == validity2);
+
+ ValidityPeriod validity3(notBefore, notAfter2);
+ BOOST_CHECK(validity1 != validity3);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestValidityPeriod
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/verification-helpers.t.cpp b/tests/unit/security/verification-helpers.t.cpp
new file mode 100644
index 0000000..d06580a
--- /dev/null
+++ b/tests/unit/security/verification-helpers.t.cpp
@@ -0,0 +1,504 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/verification-helpers.hpp"
+#include "security/transform/public-key.hpp"
+// #include "util/string-helper.hpp"
+
+#include "boost-test.hpp"
+#include "identity-management-fixture.hpp"
+#include "make-interest-data.hpp"
+
+#include <boost/mpl/list.hpp>
+
+namespace ndn {
+namespace security {
+namespace tests {
+
+using namespace ndn::tests;
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(TestVerificationHelpers)
+
+// // Using this test case to generate dataset if signature format changes
+// BOOST_FIXTURE_TEST_CASE(Generator, IdentityManagementV2Fixture)
+// {
+// Identity wrongIdentity = addIdentity("/Security/TestVerificationHelpers/Wrong");
+// std::map<std::string, SigningInfo> identities = {
+// {"Ecdsa", signingByIdentity(addIdentity("/Security/TestVerificationHelpers/EC", EcKeyParams()))},
+// {"Rsa", signingByIdentity(addIdentity("/Security/TestVerificationHelpers/RSA", RsaKeyParams()))},
+// {"Sha256", signingWithSha256()}
+// };
+
+// auto print = [] (const std::string& name, const uint8_t* buf, size_t size) {
+// std::cout << " std::vector<uint8_t> " + name + " = {\n ";
+
+// std::string hex = toHex(buf, size);
+
+// for (size_t i = 0; i < hex.size(); i++) {
+// if (i > 0 && i % 32 == 0)
+// std::cout << "\n ";
+
+// std::cout << "0x" << hex[i];
+// std::cout << hex[++i];
+
+// if ((i + 1) != hex.size())
+// std::cout << ", ";
+// }
+// std::cout << "\n };";
+// };
+
+// for (const auto& i : identities) {
+// const std::string& type = i.first;
+// const SigningInfo& signingInfo = i.second;
+
+// std::cout << "struct " + type + "Dataset\n{\n";
+// std::cout << " const std::string name = \"" << type << "\";\n";
+
+// if (signingInfo.getSignerType() == SigningInfo::SIGNER_TYPE_ID) {
+// print("cert", signingInfo.getPibIdentity().getDefaultKey().getDefaultCertificate().wireEncode().wire(),
+// signingInfo.getPibIdentity().getDefaultKey().getDefaultCertificate().wireEncode().size());
+// }
+// else {
+// print("cert", nullptr, 0);
+// }
+// std::cout << "\n";
+
+// // Create data that can be verified by cert
+// Data data(Name("/test/data").append(type));
+// m_keyChain.sign(data, signingInfo);
+// print("goodData", data.wireEncode().wire(), data.wireEncode().size());
+// std::cout << "\n";
+
+// // Create data that cannot be verified by cert
+// m_keyChain.sign(data, signingByIdentity(wrongIdentity));
+// print("badSigData", data.wireEncode().wire(), data.wireEncode().size());
+// std::cout << "\n";
+
+// // Create interest that can be verified by cert
+// Interest interest(Name("/test/interest/").append(type));
+// m_keyChain.sign(interest, signingInfo);
+// print("goodInterest", interest.wireEncode().wire(), interest.wireEncode().size());
+// std::cout << "\n";
+
+// // Create interest that cannot be verified by cert
+// m_keyChain.sign(interest, signingByIdentity(wrongIdentity));
+// print("badSigInterest", interest.wireEncode().wire(), interest.wireEncode().size());
+// std::cout << "\n};\n\n";
+// }
+// }
+
+struct EcdsaDataset
+{
+ const std::string name = "Ecdsa";
+ std::vector<uint8_t> cert = {
+ 0x06, 0xFD, 0x02, 0x59, 0x07, 0x47, 0x08, 0x08, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79,
+ 0x08, 0x17, 0x54, 0x65, 0x73, 0x74, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69,
+ 0x6F, 0x6E, 0x48, 0x65, 0x6C, 0x70, 0x65, 0x72, 0x73, 0x08, 0x02, 0x45, 0x43, 0x08, 0x03, 0x4B,
+ 0x45, 0x59, 0x08, 0x08, 0xDC, 0x9E, 0x3B, 0x11, 0x2A, 0x81, 0x7E, 0x92, 0x08, 0x04, 0x73, 0x65,
+ 0x6C, 0x66, 0x08, 0x09, 0xFD, 0x00, 0x00, 0x01, 0x59, 0x90, 0x5F, 0x6F, 0x4F, 0x14, 0x09, 0x18,
+ 0x01, 0x02, 0x19, 0x04, 0x00, 0x36, 0xEE, 0x80, 0x15, 0xFD, 0x01, 0x4F, 0x30, 0x82, 0x01, 0x4B,
+ 0x30, 0x82, 0x01, 0x03, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x30, 0x81, 0xF7,
+ 0x02, 0x01, 0x01, 0x30, 0x2C, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x01, 0x01, 0x02, 0x21,
+ 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0x30, 0x5B, 0x04, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x04, 0x20, 0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A, 0x93, 0xE7, 0xB3,
+ 0xEB, 0xBD, 0x55, 0x76, 0x98, 0x86, 0xBC, 0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53, 0xB0, 0xF6, 0x3B,
+ 0xCE, 0x3C, 0x3E, 0x27, 0xD2, 0x60, 0x4B, 0x03, 0x15, 0x00, 0xC4, 0x9D, 0x36, 0x08, 0x86, 0xE7,
+ 0x04, 0x93, 0x6A, 0x66, 0x78, 0xE1, 0x13, 0x9D, 0x26, 0xB7, 0x81, 0x9F, 0x7E, 0x90, 0x04, 0x41,
+ 0x04, 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, 0xBC, 0xE6, 0xE5, 0x63, 0xA4, 0x40,
+ 0xF2, 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0, 0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2,
+ 0x96, 0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, 0x9B, 0x8E, 0xE7, 0xEB, 0x4A, 0x7C, 0x0F, 0x9E,
+ 0x16, 0x2B, 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE, 0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51,
+ 0xF5, 0x02, 0x21, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84, 0xF3, 0xB9, 0xCA, 0xC2,
+ 0xFC, 0x63, 0x25, 0x51, 0x02, 0x01, 0x01, 0x03, 0x42, 0x00, 0x04, 0x78, 0xF2, 0x68, 0x89, 0x92,
+ 0x8D, 0x84, 0x17, 0xF1, 0x2B, 0x50, 0x4C, 0x9B, 0xFA, 0x6C, 0x4D, 0x8D, 0x29, 0x7D, 0x85, 0xDC,
+ 0x03, 0x09, 0x72, 0xFA, 0x06, 0xD4, 0x5C, 0xCB, 0xA6, 0x62, 0x0A, 0x7E, 0x2D, 0x50, 0xF0, 0x07,
+ 0xDE, 0xE0, 0x34, 0xF6, 0xC2, 0xAE, 0xA9, 0x32, 0x9B, 0x2C, 0xBD, 0x25, 0xAF, 0xB7, 0xE1, 0x7C,
+ 0xCD, 0x85, 0xF4, 0x6D, 0x31, 0xD6, 0xC0, 0x01, 0xC3, 0xEF, 0xB3, 0x16, 0x67, 0x1B, 0x01, 0x03,
+ 0x1C, 0x38, 0x07, 0x36, 0x08, 0x08, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x08, 0x17,
+ 0x54, 0x65, 0x73, 0x74, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E,
+ 0x48, 0x65, 0x6C, 0x70, 0x65, 0x72, 0x73, 0x08, 0x02, 0x45, 0x43, 0x08, 0x03, 0x4B, 0x45, 0x59,
+ 0x08, 0x08, 0xDC, 0x9E, 0x3B, 0x11, 0x2A, 0x81, 0x7E, 0x92, 0xFD, 0x00, 0xFD, 0x26, 0xFD, 0x00,
+ 0xFE, 0x0F, 0x31, 0x39, 0x37, 0x30, 0x30, 0x31, 0x30, 0x31, 0x54, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0xFD, 0x00, 0xFF, 0x0F, 0x32, 0x30, 0x33, 0x37, 0x30, 0x31, 0x30, 0x37, 0x54, 0x30, 0x31,
+ 0x35, 0x31, 0x33, 0x30, 0x17, 0x47, 0x30, 0x45, 0x02, 0x21, 0x00, 0xC3, 0xB4, 0x2A, 0x00, 0x58,
+ 0x97, 0x42, 0xDA, 0x54, 0x4C, 0xA6, 0xEF, 0x0C, 0x40, 0x51, 0x88, 0x5C, 0x86, 0x99, 0xF2, 0xBC,
+ 0x15, 0xEA, 0x06, 0x64, 0xA5, 0xD5, 0xFF, 0x2B, 0xFA, 0xD1, 0xD3, 0x02, 0x20, 0x35, 0x4C, 0xC0,
+ 0x0D, 0x0F, 0x8E, 0x43, 0x56, 0x12, 0x60, 0x8C, 0x98, 0xF1, 0x5F, 0xC4, 0xD5, 0xF2, 0x25, 0x21,
+ 0xD4, 0x9C, 0x94, 0x55, 0x0D, 0x4F, 0xDE, 0x14, 0x51, 0x82, 0xB3, 0x8E, 0xA1
+ };
+ std::vector<uint8_t> goodData = {
+ 0x06, 0x9E, 0x07, 0x10, 0x08, 0x04, 0x74, 0x65, 0x73, 0x74, 0x08, 0x04, 0x64, 0x61, 0x74, 0x61,
+ 0x08, 0x02, 0x45, 0x63, 0x14, 0x00, 0x15, 0x00, 0x16, 0x3D, 0x1B, 0x01, 0x03, 0x1C, 0x38, 0x07,
+ 0x36, 0x08, 0x08, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x08, 0x17, 0x54, 0x65, 0x73,
+ 0x74, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x48, 0x65, 0x6C,
+ 0x70, 0x65, 0x72, 0x73, 0x08, 0x02, 0x45, 0x43, 0x08, 0x03, 0x4B, 0x45, 0x59, 0x08, 0x08, 0xDC,
+ 0x9E, 0x3B, 0x11, 0x2A, 0x81, 0x7E, 0x92, 0x17, 0x47, 0x30, 0x45, 0x02, 0x20, 0x29, 0x8B, 0xE5,
+ 0x0B, 0xD4, 0x24, 0x92, 0xA7, 0x5A, 0x36, 0x73, 0x5A, 0xC2, 0xBE, 0x17, 0x0D, 0xCA, 0x6C, 0xBB,
+ 0xF9, 0x15, 0x60, 0xBD, 0x08, 0x8E, 0xA9, 0x5B, 0x31, 0x94, 0xF2, 0xB7, 0x97, 0x02, 0x21, 0x00,
+ 0xA9, 0x02, 0xEF, 0x0F, 0x45, 0xCB, 0xC8, 0x5C, 0xF5, 0xD6, 0xCB, 0x90, 0x8E, 0x42, 0x07, 0xA0,
+ 0xA0, 0x34, 0x6A, 0x61, 0xAD, 0x24, 0x9E, 0xB7, 0x73, 0x98, 0xA4, 0x6C, 0x2D, 0xD6, 0x12, 0xE2
+ };
+ std::vector<uint8_t> badSigData = {
+ 0x06, 0xA2, 0x07, 0x10, 0x08, 0x04, 0x74, 0x65, 0x73, 0x74, 0x08, 0x04, 0x64, 0x61, 0x74, 0x61,
+ 0x08, 0x02, 0x45, 0x63, 0x14, 0x00, 0x15, 0x00, 0x16, 0x40, 0x1B, 0x01, 0x03, 0x1C, 0x3B, 0x07,
+ 0x39, 0x08, 0x08, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x08, 0x17, 0x54, 0x65, 0x73,
+ 0x74, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x48, 0x65, 0x6C,
+ 0x70, 0x65, 0x72, 0x73, 0x08, 0x05, 0x57, 0x72, 0x6F, 0x6E, 0x67, 0x08, 0x03, 0x4B, 0x45, 0x59,
+ 0x08, 0x08, 0x57, 0x76, 0xDC, 0x93, 0x8D, 0x34, 0x59, 0x9C, 0x17, 0x48, 0x30, 0x46, 0x02, 0x21,
+ 0x00, 0xB9, 0x4B, 0x40, 0x62, 0xAD, 0xAD, 0xFA, 0x75, 0x69, 0xDE, 0x48, 0x90, 0xC4, 0x11, 0x6B,
+ 0xC7, 0x9E, 0x6C, 0x3E, 0x04, 0x78, 0x53, 0xAB, 0xF2, 0x18, 0x16, 0x9F, 0x8D, 0x1A, 0x14, 0x68,
+ 0x57, 0x02, 0x21, 0x00, 0xC1, 0xA4, 0xC8, 0x00, 0x0B, 0x61, 0xA0, 0x2C, 0x88, 0x33, 0x7C, 0xE1,
+ 0x84, 0xE7, 0xF8, 0xAC, 0x8B, 0x46, 0x19, 0x9C, 0x03, 0xE4, 0xF1, 0xBE, 0x83, 0x09, 0x97, 0xD5,
+ 0xA8, 0x98, 0x1A, 0x47
+ };
+ std::vector<uint8_t> goodInterest = {
+ 0x05, 0xA9, 0x07, 0xA1, 0x08, 0x04, 0x74, 0x65, 0x73, 0x74, 0x08, 0x08, 0x69, 0x6E, 0x74, 0x65,
+ 0x72, 0x65, 0x73, 0x74, 0x08, 0x02, 0x45, 0x63, 0x08, 0x3F, 0x16, 0x3D, 0x1B, 0x01, 0x03, 0x1C,
+ 0x38, 0x07, 0x36, 0x08, 0x08, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x08, 0x17, 0x54,
+ 0x65, 0x73, 0x74, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x48,
+ 0x65, 0x6C, 0x70, 0x65, 0x72, 0x73, 0x08, 0x02, 0x45, 0x43, 0x08, 0x03, 0x4B, 0x45, 0x59, 0x08,
+ 0x08, 0xDC, 0x9E, 0x3B, 0x11, 0x2A, 0x81, 0x7E, 0x92, 0x08, 0x4A, 0x17, 0x48, 0x30, 0x46, 0x02,
+ 0x21, 0x00, 0xE9, 0x35, 0xF0, 0x7B, 0x51, 0xB5, 0x2E, 0xB7, 0xE8, 0x6B, 0xE8, 0xAC, 0xC7, 0xC1,
+ 0x90, 0x35, 0x64, 0x21, 0x53, 0x0F, 0x6D, 0x03, 0xB5, 0x1A, 0x58, 0xEA, 0xC4, 0x8A, 0xCA, 0xAF,
+ 0xDB, 0x4B, 0x02, 0x21, 0x00, 0x95, 0xF3, 0xEB, 0xF9, 0xF9, 0x66, 0x51, 0x87, 0x97, 0xB0, 0xBF,
+ 0xF8, 0x07, 0x5F, 0xF0, 0x70, 0x90, 0x36, 0xD8, 0x57, 0x65, 0xEA, 0xDB, 0x91, 0x79, 0x0E, 0x7E,
+ 0x0E, 0xD0, 0x20, 0x96, 0x19, 0x0A, 0x04, 0xF7, 0x2C, 0x8A, 0x4B
+ };
+ std::vector<uint8_t> badSigInterest = {
+ 0x05, 0xFD, 0x01, 0x3A, 0x07, 0xFD, 0x01, 0x30, 0x08, 0x04, 0x74, 0x65, 0x73, 0x74, 0x08, 0x08,
+ 0x69, 0x6E, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x08, 0x02, 0x45, 0x63, 0x08, 0x3F, 0x16, 0x3D,
+ 0x1B, 0x01, 0x03, 0x1C, 0x38, 0x07, 0x36, 0x08, 0x08, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74,
+ 0x79, 0x08, 0x17, 0x54, 0x65, 0x73, 0x74, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74,
+ 0x69, 0x6F, 0x6E, 0x48, 0x65, 0x6C, 0x70, 0x65, 0x72, 0x73, 0x08, 0x02, 0x45, 0x43, 0x08, 0x03,
+ 0x4B, 0x45, 0x59, 0x08, 0x08, 0xDC, 0x9E, 0x3B, 0x11, 0x2A, 0x81, 0x7E, 0x92, 0x08, 0x4A, 0x17,
+ 0x48, 0x30, 0x46, 0x02, 0x21, 0x00, 0xE9, 0x35, 0xF0, 0x7B, 0x51, 0xB5, 0x2E, 0xB7, 0xE8, 0x6B,
+ 0xE8, 0xAC, 0xC7, 0xC1, 0x90, 0x35, 0x64, 0x21, 0x53, 0x0F, 0x6D, 0x03, 0xB5, 0x1A, 0x58, 0xEA,
+ 0xC4, 0x8A, 0xCA, 0xAF, 0xDB, 0x4B, 0x02, 0x21, 0x00, 0x95, 0xF3, 0xEB, 0xF9, 0xF9, 0x66, 0x51,
+ 0x87, 0x97, 0xB0, 0xBF, 0xF8, 0x07, 0x5F, 0xF0, 0x70, 0x90, 0x36, 0xD8, 0x57, 0x65, 0xEA, 0xDB,
+ 0x91, 0x79, 0x0E, 0x7E, 0x0E, 0xD0, 0x20, 0x96, 0x19, 0x08, 0x42, 0x16, 0x40, 0x1B, 0x01, 0x03,
+ 0x1C, 0x3B, 0x07, 0x39, 0x08, 0x08, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x08, 0x17,
+ 0x54, 0x65, 0x73, 0x74, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E,
+ 0x48, 0x65, 0x6C, 0x70, 0x65, 0x72, 0x73, 0x08, 0x05, 0x57, 0x72, 0x6F, 0x6E, 0x67, 0x08, 0x03,
+ 0x4B, 0x45, 0x59, 0x08, 0x08, 0x57, 0x76, 0xDC, 0x93, 0x8D, 0x34, 0x59, 0x9C, 0x08, 0x49, 0x17,
+ 0x47, 0x30, 0x45, 0x02, 0x20, 0x30, 0x34, 0xB8, 0x9C, 0x33, 0x4C, 0x54, 0x56, 0xF0, 0x34, 0x7A,
+ 0x95, 0x72, 0x20, 0xEC, 0xF5, 0x0F, 0xBB, 0x90, 0x3D, 0xC4, 0x21, 0x90, 0xB8, 0x3D, 0xA1, 0x10,
+ 0x5A, 0x56, 0x71, 0xC3, 0x3F, 0x02, 0x21, 0x00, 0xAE, 0xE0, 0x60, 0xCF, 0x2C, 0xF7, 0x54, 0xC2,
+ 0x1C, 0xC5, 0x54, 0x88, 0xDA, 0x31, 0xD2, 0xDE, 0x53, 0x56, 0xEC, 0xE2, 0xC6, 0x4F, 0xDD, 0xF2,
+ 0x78, 0x5D, 0xB3, 0xD4, 0x8E, 0x45, 0x36, 0x23, 0x0A, 0x04, 0xF7, 0x2C, 0x8A, 0x4B
+ };
+};
+
+struct RsaDataset
+{
+ const std::string name = "Rsa";
+ std::vector<uint8_t> cert = {
+ 0x06, 0xFD, 0x02, 0xED, 0x07, 0x48, 0x08, 0x08, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79,
+ 0x08, 0x17, 0x54, 0x65, 0x73, 0x74, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69,
+ 0x6F, 0x6E, 0x48, 0x65, 0x6C, 0x70, 0x65, 0x72, 0x73, 0x08, 0x03, 0x52, 0x53, 0x41, 0x08, 0x03,
+ 0x4B, 0x45, 0x59, 0x08, 0x08, 0xE1, 0x7A, 0x42, 0xD0, 0x60, 0x6F, 0x0F, 0xDF, 0x08, 0x04, 0x73,
+ 0x65, 0x6C, 0x66, 0x08, 0x09, 0xFD, 0x00, 0x00, 0x01, 0x59, 0x90, 0x5F, 0x6F, 0x9F, 0x14, 0x09,
+ 0x18, 0x01, 0x02, 0x19, 0x04, 0x00, 0x36, 0xEE, 0x80, 0x15, 0xFD, 0x01, 0x26, 0x30, 0x82, 0x01,
+ 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00,
+ 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xE7, 0x7B,
+ 0x1F, 0x75, 0x3C, 0xCD, 0xB4, 0x62, 0x80, 0xC3, 0xA4, 0x5E, 0xA9, 0x8A, 0x7B, 0xC6, 0x4C, 0x43,
+ 0x27, 0x0D, 0xA4, 0x54, 0xEB, 0x67, 0x4F, 0xB4, 0x6E, 0xEF, 0x6D, 0x54, 0x9B, 0x85, 0x44, 0xE9,
+ 0x6B, 0x4D, 0x09, 0x31, 0xC0, 0xDC, 0xC5, 0x06, 0x5E, 0x88, 0x6B, 0xFC, 0x0B, 0x08, 0xDE, 0x14,
+ 0x0F, 0xAB, 0xE8, 0xA7, 0xED, 0x93, 0x5D, 0x17, 0x19, 0x4B, 0x2D, 0x7D, 0x29, 0xE7, 0x43, 0x42,
+ 0x19, 0xE0, 0x3C, 0xBA, 0x8D, 0xAB, 0xE9, 0x4A, 0xBF, 0x21, 0x1E, 0x13, 0xD5, 0x0D, 0x9A, 0xC5,
+ 0xD8, 0x67, 0x4A, 0x7F, 0x2D, 0xA6, 0xA9, 0xCE, 0x31, 0x82, 0x62, 0x6B, 0x89, 0xB1, 0x78, 0xE0,
+ 0x6E, 0x19, 0x8B, 0xE6, 0x5C, 0x1A, 0x10, 0x8B, 0xC2, 0x9D, 0xF4, 0xB6, 0x66, 0xE9, 0x73, 0xD0,
+ 0x93, 0xE9, 0x0A, 0xA8, 0xDA, 0x68, 0xC1, 0x23, 0xBC, 0xBE, 0x17, 0xA0, 0x8E, 0x88, 0xC6, 0x71,
+ 0xFF, 0x25, 0x83, 0x75, 0x2C, 0x0E, 0x49, 0x76, 0x27, 0xA0, 0x9E, 0x08, 0x55, 0xA2, 0xE1, 0x60,
+ 0xAC, 0x5E, 0x03, 0xC3, 0x9E, 0xF3, 0x2B, 0x56, 0x80, 0xE0, 0x30, 0xD8, 0x0A, 0x5A, 0xAB, 0x92,
+ 0xA4, 0x32, 0xF2, 0xEC, 0xE8, 0xFB, 0x6D, 0xE2, 0xE6, 0x2F, 0x87, 0x94, 0xEA, 0xA3, 0x39, 0x47,
+ 0x70, 0x71, 0x08, 0xBC, 0x11, 0x0B, 0xC5, 0x9A, 0xCF, 0x13, 0xCA, 0x68, 0x7C, 0x22, 0xF8, 0x33,
+ 0xCA, 0x5F, 0xEB, 0x98, 0xF3, 0x29, 0x12, 0xF0, 0x33, 0xDE, 0x30, 0xC4, 0x56, 0xB5, 0x3B, 0x0B,
+ 0x0C, 0x23, 0xF2, 0x0F, 0x93, 0x3D, 0x60, 0xC9, 0xD2, 0xAA, 0x5A, 0x94, 0x3E, 0xAB, 0xFB, 0xD5,
+ 0x9B, 0xF0, 0xC9, 0x79, 0x11, 0xAD, 0x78, 0x4E, 0xE9, 0x91, 0x1E, 0x62, 0x8D, 0x81, 0x71, 0xC9,
+ 0xE4, 0x5D, 0x41, 0xDD, 0x19, 0xC6, 0x77, 0x81, 0xF6, 0xA7, 0x38, 0xD4, 0xE1, 0xB3, 0x02, 0x03,
+ 0x01, 0x00, 0x01, 0x16, 0x68, 0x1B, 0x01, 0x01, 0x1C, 0x39, 0x07, 0x37, 0x08, 0x08, 0x53, 0x65,
+ 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x08, 0x17, 0x54, 0x65, 0x73, 0x74, 0x56, 0x65, 0x72, 0x69,
+ 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x48, 0x65, 0x6C, 0x70, 0x65, 0x72, 0x73, 0x08,
+ 0x03, 0x52, 0x53, 0x41, 0x08, 0x03, 0x4B, 0x45, 0x59, 0x08, 0x08, 0xE1, 0x7A, 0x42, 0xD0, 0x60,
+ 0x6F, 0x0F, 0xDF, 0xFD, 0x00, 0xFD, 0x26, 0xFD, 0x00, 0xFE, 0x0F, 0x31, 0x39, 0x37, 0x30, 0x30,
+ 0x31, 0x30, 0x31, 0x54, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xFD, 0x00, 0xFF, 0x0F, 0x32, 0x30,
+ 0x33, 0x37, 0x30, 0x31, 0x30, 0x37, 0x54, 0x30, 0x31, 0x35, 0x31, 0x33, 0x30, 0x17, 0xFD, 0x01,
+ 0x00, 0xD1, 0xEB, 0xB4, 0x09, 0x2B, 0x9D, 0xFA, 0x82, 0x88, 0x1A, 0xB6, 0x71, 0x99, 0xD0, 0x14,
+ 0x2B, 0xB5, 0xD8, 0xB8, 0x36, 0xA5, 0x70, 0xC0, 0xDD, 0x7E, 0xD1, 0xAD, 0x93, 0xEC, 0xCE, 0x9F,
+ 0x3E, 0x75, 0x1F, 0x7F, 0x95, 0x0A, 0x34, 0xCC, 0x8C, 0x5A, 0x45, 0x37, 0xE2, 0x65, 0xE4, 0x1D,
+ 0xEC, 0xE2, 0xC2, 0x39, 0x7F, 0xD7, 0xB7, 0x9B, 0x78, 0xDF, 0x0B, 0x39, 0x2B, 0xC6, 0x5E, 0x49,
+ 0x6F, 0xDB, 0xB0, 0x44, 0xFD, 0xC7, 0x5B, 0x00, 0xB4, 0xDD, 0x23, 0xBC, 0xA8, 0xC8, 0x9C, 0xCB,
+ 0xAD, 0x63, 0x3C, 0x40, 0x57, 0x07, 0x09, 0xC7, 0x26, 0x84, 0xBF, 0x49, 0x8B, 0xD0, 0x5A, 0xFD,
+ 0xBA, 0xA0, 0x0C, 0x06, 0xE5, 0x84, 0xA3, 0x9B, 0x36, 0x5E, 0x95, 0xBF, 0x34, 0xF5, 0x5A, 0x70,
+ 0x31, 0x3B, 0x70, 0x3E, 0x99, 0x84, 0xBA, 0x03, 0xE7, 0x5A, 0x9D, 0x6F, 0x46, 0x33, 0xA3, 0x95,
+ 0xAD, 0xB5, 0xC9, 0x20, 0x28, 0xA8, 0x6E, 0x52, 0x02, 0x97, 0x49, 0xDA, 0x89, 0x55, 0x6B, 0x5D,
+ 0xCB, 0x84, 0x75, 0x5F, 0x1F, 0x51, 0x0C, 0x59, 0x49, 0xC8, 0xCE, 0x2D, 0xC3, 0xA2, 0x2F, 0x7F,
+ 0x42, 0x71, 0x26, 0x4F, 0xF4, 0x1F, 0xBB, 0x09, 0x7D, 0xF8, 0x7E, 0x6D, 0x44, 0x74, 0xB1, 0x7F,
+ 0x76, 0xAE, 0x7B, 0x1C, 0x56, 0x75, 0x9B, 0xE7, 0x23, 0xF4, 0xF3, 0xA0, 0x3C, 0x47, 0xF0, 0x98,
+ 0x2B, 0xC1, 0x54, 0xDA, 0x75, 0x1B, 0x2E, 0x94, 0xFB, 0xB5, 0xDD, 0x44, 0xE9, 0x16, 0x27, 0xE5,
+ 0xE9, 0xB5, 0xA5, 0x70, 0x5E, 0xBC, 0x48, 0xB1, 0x02, 0x92, 0x64, 0x73, 0x08, 0x8A, 0x5C, 0xD8,
+ 0xF7, 0x58, 0x07, 0x66, 0xEF, 0x4A, 0x9E, 0xB5, 0x77, 0xDF, 0xDE, 0x54, 0xF1, 0x0A, 0xDF, 0xE1,
+ 0xE1, 0xF1, 0x76, 0x91, 0xEB, 0x78, 0xB6, 0x9A, 0x40, 0x57, 0x97, 0x9C, 0x2C, 0x8C, 0x00, 0x05,
+ 0x01
+ };
+ std::vector<uint8_t> goodData = {
+ 0x06, 0xFD, 0x01, 0x5B, 0x07, 0x11, 0x08, 0x04, 0x74, 0x65, 0x73, 0x74, 0x08, 0x04, 0x64, 0x61,
+ 0x74, 0x61, 0x08, 0x03, 0x52, 0x73, 0x61, 0x14, 0x00, 0x15, 0x00, 0x16, 0x3E, 0x1B, 0x01, 0x01,
+ 0x1C, 0x39, 0x07, 0x37, 0x08, 0x08, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x08, 0x17,
+ 0x54, 0x65, 0x73, 0x74, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E,
+ 0x48, 0x65, 0x6C, 0x70, 0x65, 0x72, 0x73, 0x08, 0x03, 0x52, 0x53, 0x41, 0x08, 0x03, 0x4B, 0x45,
+ 0x59, 0x08, 0x08, 0xE1, 0x7A, 0x42, 0xD0, 0x60, 0x6F, 0x0F, 0xDF, 0x17, 0xFD, 0x01, 0x00, 0x88,
+ 0xEA, 0x30, 0x2E, 0xF2, 0x40, 0xA4, 0x2F, 0xF6, 0x95, 0x83, 0x1B, 0xD7, 0x89, 0xB2, 0xDB, 0x73,
+ 0xB8, 0x88, 0x97, 0x48, 0xDC, 0xC4, 0x8F, 0xBD, 0x83, 0x49, 0x5E, 0x39, 0x14, 0xE5, 0x15, 0xE2,
+ 0x94, 0xB3, 0x7A, 0x4A, 0x46, 0x1F, 0xEE, 0x50, 0xF5, 0x1F, 0x46, 0xE9, 0xAB, 0x31, 0x94, 0x9C,
+ 0x41, 0xF1, 0xA7, 0x1E, 0xA7, 0x2F, 0x2C, 0x26, 0x5E, 0x97, 0x7D, 0x06, 0x86, 0x77, 0x63, 0x4B,
+ 0xD0, 0x38, 0x91, 0x0F, 0xB6, 0x2B, 0xFD, 0xF0, 0x77, 0xB1, 0xA8, 0x73, 0xBB, 0xF9, 0x8A, 0xED,
+ 0x8D, 0xDD, 0x32, 0x8E, 0x8A, 0xC2, 0xEE, 0x83, 0xA6, 0x72, 0xFF, 0xDB, 0x91, 0xA8, 0x83, 0x1D,
+ 0xDC, 0x37, 0x1F, 0x58, 0xF6, 0x16, 0x5D, 0x89, 0x50, 0xDD, 0x1D, 0x42, 0x96, 0x81, 0x75, 0x94,
+ 0xA7, 0x8D, 0x2E, 0x8C, 0xB2, 0x75, 0x36, 0x99, 0x7A, 0x65, 0x34, 0x07, 0xC8, 0x28, 0x98, 0xA2,
+ 0x46, 0x9D, 0x6F, 0x30, 0x8E, 0x32, 0x49, 0x20, 0xE6, 0xFC, 0x1A, 0x05, 0x4F, 0x6F, 0xE8, 0x5D,
+ 0x34, 0x1D, 0x8D, 0x7F, 0x09, 0xA8, 0xDD, 0xA7, 0x48, 0xB1, 0x14, 0xDC, 0x5A, 0xAF, 0xAA, 0x12,
+ 0xEA, 0x57, 0xDE, 0x47, 0x6C, 0xC6, 0x07, 0xBC, 0x6B, 0x76, 0xB1, 0x40, 0x56, 0x3B, 0x12, 0x47,
+ 0x1D, 0x89, 0x66, 0x12, 0x81, 0xE8, 0x8B, 0xBA, 0x70, 0x8A, 0x3E, 0x78, 0x64, 0x00, 0x3E, 0x56,
+ 0x3B, 0xCF, 0x26, 0xF0, 0x3D, 0x09, 0x1D, 0xB9, 0x22, 0x9E, 0xED, 0x67, 0xB8, 0x86, 0x1F, 0x44,
+ 0x92, 0x0A, 0x08, 0xE1, 0x8F, 0x4C, 0x6D, 0x9C, 0x11, 0x5F, 0x26, 0xEA, 0x3E, 0x95, 0x32, 0x13,
+ 0x20, 0x51, 0x95, 0x24, 0x37, 0x18, 0x13, 0x92, 0xBD, 0x22, 0xF0, 0x0E, 0xAF, 0x34, 0x37, 0x9B,
+ 0xDC, 0x61, 0x03, 0x29, 0x09, 0x9A, 0x45, 0x92, 0x1B, 0xA0, 0x29, 0x9E, 0xD8, 0x98, 0x54
+ };
+ std::vector<uint8_t> badSigData = {
+ 0x06, 0xA1, 0x07, 0x11, 0x08, 0x04, 0x74, 0x65, 0x73, 0x74, 0x08, 0x04, 0x64, 0x61, 0x74, 0x61,
+ 0x08, 0x03, 0x52, 0x73, 0x61, 0x14, 0x00, 0x15, 0x00, 0x16, 0x40, 0x1B, 0x01, 0x03, 0x1C, 0x3B,
+ 0x07, 0x39, 0x08, 0x08, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x08, 0x17, 0x54, 0x65,
+ 0x73, 0x74, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x48, 0x65,
+ 0x6C, 0x70, 0x65, 0x72, 0x73, 0x08, 0x05, 0x57, 0x72, 0x6F, 0x6E, 0x67, 0x08, 0x03, 0x4B, 0x45,
+ 0x59, 0x08, 0x08, 0x57, 0x76, 0xDC, 0x93, 0x8D, 0x34, 0x59, 0x9C, 0x17, 0x46, 0x30, 0x44, 0x02,
+ 0x20, 0x5E, 0xF9, 0x02, 0xF4, 0x78, 0xE7, 0x5E, 0x1B, 0xB9, 0x3B, 0x23, 0xDE, 0x9D, 0xB7, 0x87,
+ 0xC6, 0x30, 0x7F, 0x4A, 0xE2, 0xBE, 0x11, 0xFE, 0x29, 0xC7, 0x6F, 0x70, 0x97, 0xAF, 0x45, 0xE1,
+ 0x0B, 0x02, 0x20, 0x67, 0x45, 0x47, 0x52, 0xBE, 0x13, 0x59, 0x76, 0x16, 0x28, 0x70, 0xF6, 0x50,
+ 0x13, 0xB2, 0xC0, 0xFA, 0x8F, 0xF3, 0x05, 0xFF, 0xBC, 0x92, 0xAC, 0xF7, 0xD0, 0x12, 0x3A, 0x6E,
+ 0x31, 0x76, 0x02
+ };
+ std::vector<uint8_t> goodInterest = {
+ 0x05, 0xFD, 0x01, 0x69, 0x07, 0xFD, 0x01, 0x5F, 0x08, 0x04, 0x74, 0x65, 0x73, 0x74, 0x08, 0x08,
+ 0x69, 0x6E, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x08, 0x03, 0x52, 0x73, 0x61, 0x08, 0x40, 0x16,
+ 0x3E, 0x1B, 0x01, 0x01, 0x1C, 0x39, 0x07, 0x37, 0x08, 0x08, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69,
+ 0x74, 0x79, 0x08, 0x17, 0x54, 0x65, 0x73, 0x74, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61,
+ 0x74, 0x69, 0x6F, 0x6E, 0x48, 0x65, 0x6C, 0x70, 0x65, 0x72, 0x73, 0x08, 0x03, 0x52, 0x53, 0x41,
+ 0x08, 0x03, 0x4B, 0x45, 0x59, 0x08, 0x08, 0xE1, 0x7A, 0x42, 0xD0, 0x60, 0x6F, 0x0F, 0xDF, 0x08,
+ 0xFD, 0x01, 0x04, 0x17, 0xFD, 0x01, 0x00, 0x9C, 0x44, 0x23, 0xF4, 0x3A, 0x9F, 0xDD, 0x62, 0xD2,
+ 0x47, 0xE4, 0x73, 0x9E, 0x58, 0x54, 0xF5, 0xE7, 0x72, 0x8D, 0x2E, 0x1B, 0x26, 0xE7, 0xA2, 0xA1,
+ 0x56, 0x23, 0xBD, 0xB8, 0x75, 0x17, 0x78, 0x01, 0x67, 0xF9, 0x4D, 0xA9, 0xCC, 0xB8, 0x00, 0xF6,
+ 0xCD, 0xC4, 0xB9, 0xF6, 0x50, 0xC7, 0xAB, 0x57, 0xD8, 0xA7, 0x8B, 0xA8, 0x5C, 0xED, 0xD0, 0xCC,
+ 0x29, 0xC3, 0x5D, 0x80, 0x2B, 0xFA, 0xAF, 0x0D, 0xCB, 0x29, 0x1E, 0x74, 0xA8, 0x41, 0x80, 0xDE,
+ 0x52, 0x94, 0xDD, 0xE8, 0xAA, 0xA9, 0x61, 0x83, 0xC1, 0x5F, 0xA3, 0x11, 0x48, 0x0B, 0xB6, 0x53,
+ 0xB8, 0xE3, 0x77, 0x6A, 0xED, 0xF0, 0xFA, 0xED, 0x79, 0x43, 0x10, 0x10, 0x79, 0x98, 0x5D, 0xFD,
+ 0x66, 0xBF, 0x2F, 0x14, 0x9F, 0x7D, 0xA4, 0x3C, 0xBA, 0x67, 0x5F, 0xDB, 0xE3, 0x67, 0x13, 0x96,
+ 0x60, 0xC6, 0x69, 0x78, 0x5A, 0x8D, 0x52, 0xB7, 0xB7, 0x6B, 0x7F, 0xEE, 0xF4, 0x22, 0x3A, 0x64,
+ 0xE4, 0xB4, 0xA1, 0x8B, 0xDD, 0x3F, 0x80, 0xCD, 0xF4, 0x9E, 0x92, 0x06, 0x98, 0x23, 0x47, 0x58,
+ 0x70, 0xF0, 0xAC, 0x79, 0x76, 0x91, 0x7A, 0x78, 0xDF, 0xAD, 0xDD, 0x81, 0x30, 0x01, 0x5D, 0xCE,
+ 0x37, 0xEC, 0x7E, 0xDA, 0xDA, 0x36, 0x75, 0x50, 0x52, 0x57, 0x95, 0xBF, 0xCF, 0x3A, 0xC4, 0x9F,
+ 0x52, 0x97, 0x17, 0x15, 0x99, 0xA5, 0x2F, 0x68, 0x35, 0x91, 0x70, 0xDE, 0x98, 0x8A, 0xB0, 0x5F,
+ 0xF4, 0x63, 0x14, 0xB9, 0xCC, 0x76, 0x81, 0x87, 0xAE, 0x10, 0x8E, 0x9F, 0xEC, 0xCB, 0xF2, 0x33,
+ 0x1D, 0x50, 0xD4, 0xAB, 0x5B, 0xBB, 0xB9, 0x7F, 0x8C, 0xAD, 0xEC, 0xE3, 0xF8, 0xE1, 0x63, 0xDA,
+ 0x4E, 0x0D, 0x17, 0x28, 0xCD, 0x8D, 0x16, 0x00, 0x22, 0x4A, 0x51, 0x5C, 0xB2, 0x8C, 0xE7, 0x4B,
+ 0x3B, 0x00, 0x16, 0x92, 0xAD, 0x3A, 0xAB, 0x0A, 0x04, 0x10, 0x04, 0xFB, 0x38
+ };
+ std::vector<uint8_t> badSigInterest = {
+ 0x05, 0xFD, 0x01, 0xF7, 0x07, 0xFD, 0x01, 0xED, 0x08, 0x04, 0x74, 0x65, 0x73, 0x74, 0x08, 0x08,
+ 0x69, 0x6E, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x08, 0x03, 0x52, 0x73, 0x61, 0x08, 0x40, 0x16,
+ 0x3E, 0x1B, 0x01, 0x01, 0x1C, 0x39, 0x07, 0x37, 0x08, 0x08, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69,
+ 0x74, 0x79, 0x08, 0x17, 0x54, 0x65, 0x73, 0x74, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61,
+ 0x74, 0x69, 0x6F, 0x6E, 0x48, 0x65, 0x6C, 0x70, 0x65, 0x72, 0x73, 0x08, 0x03, 0x52, 0x53, 0x41,
+ 0x08, 0x03, 0x4B, 0x45, 0x59, 0x08, 0x08, 0xE1, 0x7A, 0x42, 0xD0, 0x60, 0x6F, 0x0F, 0xDF, 0x08,
+ 0xFD, 0x01, 0x04, 0x17, 0xFD, 0x01, 0x00, 0x9C, 0x44, 0x23, 0xF4, 0x3A, 0x9F, 0xDD, 0x62, 0xD2,
+ 0x47, 0xE4, 0x73, 0x9E, 0x58, 0x54, 0xF5, 0xE7, 0x72, 0x8D, 0x2E, 0x1B, 0x26, 0xE7, 0xA2, 0xA1,
+ 0x56, 0x23, 0xBD, 0xB8, 0x75, 0x17, 0x78, 0x01, 0x67, 0xF9, 0x4D, 0xA9, 0xCC, 0xB8, 0x00, 0xF6,
+ 0xCD, 0xC4, 0xB9, 0xF6, 0x50, 0xC7, 0xAB, 0x57, 0xD8, 0xA7, 0x8B, 0xA8, 0x5C, 0xED, 0xD0, 0xCC,
+ 0x29, 0xC3, 0x5D, 0x80, 0x2B, 0xFA, 0xAF, 0x0D, 0xCB, 0x29, 0x1E, 0x74, 0xA8, 0x41, 0x80, 0xDE,
+ 0x52, 0x94, 0xDD, 0xE8, 0xAA, 0xA9, 0x61, 0x83, 0xC1, 0x5F, 0xA3, 0x11, 0x48, 0x0B, 0xB6, 0x53,
+ 0xB8, 0xE3, 0x77, 0x6A, 0xED, 0xF0, 0xFA, 0xED, 0x79, 0x43, 0x10, 0x10, 0x79, 0x98, 0x5D, 0xFD,
+ 0x66, 0xBF, 0x2F, 0x14, 0x9F, 0x7D, 0xA4, 0x3C, 0xBA, 0x67, 0x5F, 0xDB, 0xE3, 0x67, 0x13, 0x96,
+ 0x60, 0xC6, 0x69, 0x78, 0x5A, 0x8D, 0x52, 0xB7, 0xB7, 0x6B, 0x7F, 0xEE, 0xF4, 0x22, 0x3A, 0x64,
+ 0xE4, 0xB4, 0xA1, 0x8B, 0xDD, 0x3F, 0x80, 0xCD, 0xF4, 0x9E, 0x92, 0x06, 0x98, 0x23, 0x47, 0x58,
+ 0x70, 0xF0, 0xAC, 0x79, 0x76, 0x91, 0x7A, 0x78, 0xDF, 0xAD, 0xDD, 0x81, 0x30, 0x01, 0x5D, 0xCE,
+ 0x37, 0xEC, 0x7E, 0xDA, 0xDA, 0x36, 0x75, 0x50, 0x52, 0x57, 0x95, 0xBF, 0xCF, 0x3A, 0xC4, 0x9F,
+ 0x52, 0x97, 0x17, 0x15, 0x99, 0xA5, 0x2F, 0x68, 0x35, 0x91, 0x70, 0xDE, 0x98, 0x8A, 0xB0, 0x5F,
+ 0xF4, 0x63, 0x14, 0xB9, 0xCC, 0x76, 0x81, 0x87, 0xAE, 0x10, 0x8E, 0x9F, 0xEC, 0xCB, 0xF2, 0x33,
+ 0x1D, 0x50, 0xD4, 0xAB, 0x5B, 0xBB, 0xB9, 0x7F, 0x8C, 0xAD, 0xEC, 0xE3, 0xF8, 0xE1, 0x63, 0xDA,
+ 0x4E, 0x0D, 0x17, 0x28, 0xCD, 0x8D, 0x16, 0x00, 0x22, 0x4A, 0x51, 0x5C, 0xB2, 0x8C, 0xE7, 0x4B,
+ 0x3B, 0x00, 0x16, 0x92, 0xAD, 0x3A, 0xAB, 0x08, 0x42, 0x16, 0x40, 0x1B, 0x01, 0x03, 0x1C, 0x3B,
+ 0x07, 0x39, 0x08, 0x08, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x08, 0x17, 0x54, 0x65,
+ 0x73, 0x74, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x48, 0x65,
+ 0x6C, 0x70, 0x65, 0x72, 0x73, 0x08, 0x05, 0x57, 0x72, 0x6F, 0x6E, 0x67, 0x08, 0x03, 0x4B, 0x45,
+ 0x59, 0x08, 0x08, 0x57, 0x76, 0xDC, 0x93, 0x8D, 0x34, 0x59, 0x9C, 0x08, 0x48, 0x17, 0x46, 0x30,
+ 0x44, 0x02, 0x20, 0x48, 0x87, 0xFE, 0x7D, 0x43, 0x35, 0x3C, 0x55, 0xCB, 0x4A, 0x4B, 0x83, 0x50,
+ 0xC2, 0x10, 0xAD, 0x01, 0x4A, 0x99, 0xED, 0x6C, 0x29, 0x38, 0xEF, 0xE4, 0x9E, 0x10, 0x23, 0x4D,
+ 0x57, 0xC3, 0xE4, 0x02, 0x20, 0x7B, 0x35, 0xDC, 0xF2, 0x98, 0xD8, 0xFE, 0x13, 0x4D, 0x3B, 0x5D,
+ 0xE7, 0xCE, 0xFF, 0x02, 0xBD, 0x6B, 0x50, 0x30, 0x8B, 0x93, 0x91, 0x7A, 0xC9, 0xE0, 0x95, 0x21,
+ 0x5F, 0x91, 0xB6, 0xEE, 0x4E, 0x0A, 0x04, 0x10, 0x04, 0xFB, 0x38
+ };
+};
+
+struct Sha256Dataset
+{
+ const std::string name = "Sha256";
+ std::vector<uint8_t> cert = {
+
+ };
+ std::vector<uint8_t> goodData = {
+ 0x06, 0x41, 0x07, 0x14, 0x08, 0x04, 0x74, 0x65, 0x73, 0x74, 0x08, 0x04, 0x64, 0x61, 0x74, 0x61,
+ 0x08, 0x06, 0x53, 0x68, 0x61, 0x32, 0x35, 0x36, 0x14, 0x00, 0x15, 0x00, 0x16, 0x03, 0x1B, 0x01,
+ 0x00, 0x17, 0x20, 0xE2, 0xE2, 0x2F, 0x02, 0x70, 0xA7, 0xF7, 0x48, 0x70, 0x45, 0x29, 0x46, 0xBD,
+ 0xD2, 0x62, 0x24, 0xA6, 0x1E, 0x1D, 0x75, 0x2A, 0x26, 0x98, 0x04, 0xAD, 0x9C, 0x47, 0x63, 0xF8,
+ 0x98, 0x5A, 0x49
+ };
+ std::vector<uint8_t> badSigData = {
+ 0x06, 0xA5, 0x07, 0x14, 0x08, 0x04, 0x74, 0x65, 0x73, 0x74, 0x08, 0x04, 0x64, 0x61, 0x74, 0x61,
+ 0x08, 0x06, 0x53, 0x68, 0x61, 0x32, 0x35, 0x36, 0x14, 0x00, 0x15, 0x00, 0x16, 0x40, 0x1B, 0x01,
+ 0x03, 0x1C, 0x3B, 0x07, 0x39, 0x08, 0x08, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x08,
+ 0x17, 0x54, 0x65, 0x73, 0x74, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F,
+ 0x6E, 0x48, 0x65, 0x6C, 0x70, 0x65, 0x72, 0x73, 0x08, 0x05, 0x57, 0x72, 0x6F, 0x6E, 0x67, 0x08,
+ 0x03, 0x4B, 0x45, 0x59, 0x08, 0x08, 0x57, 0x76, 0xDC, 0x93, 0x8D, 0x34, 0x59, 0x9C, 0x17, 0x47,
+ 0x30, 0x45, 0x02, 0x20, 0x5F, 0x5E, 0x1E, 0xC0, 0xB5, 0xAC, 0x13, 0xF9, 0x51, 0x2F, 0x22, 0x33,
+ 0xFB, 0xDE, 0x57, 0xF6, 0xC8, 0xBF, 0xAE, 0x55, 0x3A, 0xDC, 0x30, 0x8A, 0x12, 0x61, 0xB3, 0x5D,
+ 0xB9, 0x31, 0x95, 0xD3, 0x02, 0x21, 0x00, 0xFA, 0xEC, 0x54, 0xEB, 0x35, 0x4D, 0xBF, 0x87, 0x4C,
+ 0xD8, 0x20, 0x3A, 0xE5, 0x05, 0x2C, 0xA1, 0x70, 0x74, 0x2E, 0xF9, 0x1E, 0xE1, 0xEF, 0xB9, 0x47,
+ 0xC4, 0x53, 0x57, 0xED, 0xB5, 0xB7, 0x60
+ };
+ std::vector<uint8_t> goodInterest = {
+ 0x05, 0x4B, 0x07, 0x43, 0x08, 0x04, 0x74, 0x65, 0x73, 0x74, 0x08, 0x08, 0x69, 0x6E, 0x74, 0x65,
+ 0x72, 0x65, 0x73, 0x74, 0x08, 0x06, 0x53, 0x68, 0x61, 0x32, 0x35, 0x36, 0x08, 0x05, 0x16, 0x03,
+ 0x1B, 0x01, 0x00, 0x08, 0x22, 0x17, 0x20, 0x38, 0x65, 0xB5, 0x37, 0x8A, 0xF4, 0xEB, 0xB9, 0xCD,
+ 0xEF, 0x18, 0x49, 0xF5, 0x79, 0x85, 0xE5, 0x76, 0x6F, 0x3C, 0x72, 0x63, 0x0E, 0x4F, 0x5D, 0xC7,
+ 0x42, 0x6B, 0xDF, 0xB0, 0xE1, 0x75, 0x2C, 0x0A, 0x04, 0xEE, 0x0A, 0x69, 0x16
+ };
+ std::vector<uint8_t> badSigInterest = {
+ 0x05, 0xD9, 0x07, 0xD1, 0x08, 0x04, 0x74, 0x65, 0x73, 0x74, 0x08, 0x08, 0x69, 0x6E, 0x74, 0x65,
+ 0x72, 0x65, 0x73, 0x74, 0x08, 0x06, 0x53, 0x68, 0x61, 0x32, 0x35, 0x36, 0x08, 0x05, 0x16, 0x03,
+ 0x1B, 0x01, 0x00, 0x08, 0x22, 0x17, 0x20, 0x38, 0x65, 0xB5, 0x37, 0x8A, 0xF4, 0xEB, 0xB9, 0xCD,
+ 0xEF, 0x18, 0x49, 0xF5, 0x79, 0x85, 0xE5, 0x76, 0x6F, 0x3C, 0x72, 0x63, 0x0E, 0x4F, 0x5D, 0xC7,
+ 0x42, 0x6B, 0xDF, 0xB0, 0xE1, 0x75, 0x2C, 0x08, 0x42, 0x16, 0x40, 0x1B, 0x01, 0x03, 0x1C, 0x3B,
+ 0x07, 0x39, 0x08, 0x08, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x08, 0x17, 0x54, 0x65,
+ 0x73, 0x74, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x48, 0x65,
+ 0x6C, 0x70, 0x65, 0x72, 0x73, 0x08, 0x05, 0x57, 0x72, 0x6F, 0x6E, 0x67, 0x08, 0x03, 0x4B, 0x45,
+ 0x59, 0x08, 0x08, 0x57, 0x76, 0xDC, 0x93, 0x8D, 0x34, 0x59, 0x9C, 0x08, 0x48, 0x17, 0x46, 0x30,
+ 0x44, 0x02, 0x20, 0x73, 0xB7, 0x0E, 0x17, 0x6C, 0x98, 0xB5, 0x6B, 0x25, 0x99, 0x2C, 0x6E, 0x41,
+ 0x26, 0xE6, 0x08, 0xCF, 0x81, 0xB9, 0x51, 0x53, 0x6A, 0x6B, 0x21, 0xF3, 0x2D, 0x4D, 0x62, 0x53,
+ 0x86, 0x85, 0xEE, 0x02, 0x20, 0x7D, 0x9D, 0xFF, 0xE3, 0x18, 0xF7, 0xBD, 0x7F, 0x9B, 0xC6, 0x4D,
+ 0x76, 0x09, 0x58, 0x74, 0x69, 0x67, 0x9B, 0x51, 0xBC, 0x14, 0xF0, 0x1C, 0x46, 0xA7, 0xA3, 0xA7,
+ 0xCC, 0x9A, 0xBB, 0x33, 0x07, 0x0A, 0x04, 0xEE, 0x0A, 0x69, 0x16
+ };
+};
+
+// Note about the datasets:
+// - .cert a valid certificate
+// - .goodData is a data packet that can be verified by .cert
+// - .badSigData a valid and signed data packet that cannot be verified by cert (signed by a
+// different private key)
+// - .goodInterest is an interest packet that can be verified by .cert
+// - .badSigInterest a valid and signed interest packet that cannot be verified by cert
+// (signed by a different private key)
+
+typedef boost::mpl::list<EcdsaDataset, RsaDataset> SignatureDatasets;
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(VerifySignature, Dataset, SignatureDatasets)
+{
+ Dataset dataset;
+ v2::Certificate cert(Block(dataset.cert.data(), dataset.cert.size()));
+ Buffer keyRaw = cert.getPublicKey();
+ v2::PublicKey key;
+ key.loadPkcs8(keyRaw.data(), keyRaw.size());
+ Data data(Block(dataset.goodData.data(), dataset.goodData.size()));
+ Data badSigData(Block(dataset.badSigData.data(), dataset.badSigData.size()));
+ Interest interest(Block(dataset.goodInterest.data(), dataset.goodInterest.size()));
+ Interest badSigInterest(Block(dataset.badSigInterest.data(), dataset.badSigInterest.size()));
+
+ BOOST_CHECK(verifySignature(data, key));
+ BOOST_CHECK(verifySignature(data, keyRaw.data(), keyRaw.size()));
+ BOOST_CHECK(verifySignature(data, cert));
+ BOOST_CHECK(verifySignature(interest, key));
+ BOOST_CHECK(verifySignature(interest, keyRaw.data(), keyRaw.size()));
+ BOOST_CHECK(verifySignature(interest, cert));
+
+ BOOST_CHECK(!verifySignature(badSigData, key));
+ BOOST_CHECK(!verifySignature(badSigData, keyRaw.data(), keyRaw.size()));
+ BOOST_CHECK(!verifySignature(badSigData, cert));
+ BOOST_CHECK(!verifySignature(badSigInterest, key));
+ BOOST_CHECK(!verifySignature(badSigInterest, keyRaw.data(), keyRaw.size()));
+ BOOST_CHECK(!verifySignature(badSigInterest, cert));
+
+ Data unsignedData("/some/data");
+ Interest unsignedInterest1("/some/interest/with/several/name/components");
+ Interest unsignedInterest2("/interest-with-one-name-component");
+
+ BOOST_CHECK(!verifySignature(unsignedData, cert));
+ BOOST_CHECK(!verifySignature(unsignedData, key));
+ BOOST_CHECK(!verifySignature(unsignedInterest1, cert));
+ BOOST_CHECK(!verifySignature(unsignedInterest1, key));
+ BOOST_CHECK(!verifySignature(unsignedInterest2, cert));
+ BOOST_CHECK(!verifySignature(unsignedInterest2, key));
+
+ uint8_t invalidKey[] = {0x00, 0x00};
+ BOOST_CHECK(!verifySignature(unsignedData, invalidKey, sizeof(invalidKey)));
+ BOOST_CHECK(!verifySignature(unsignedInterest1, invalidKey, sizeof(invalidKey)));
+
+ // - base version of verifySignature is tested transitively
+ // - pib::Key version is tested as part of v2/key-chain.t.cpp (Security/V2/TestKeyChain)
+}
+
+typedef boost::mpl::list<Sha256Dataset> DigestDatasets;
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(VerifyDigest, Dataset, DigestDatasets)
+{
+ Dataset dataset;
+ Data data(Block(dataset.goodData.data(), dataset.goodData.size()));
+ Data badSigData(Block(dataset.badSigData.data(), dataset.badSigData.size()));
+ Interest interest(Block(dataset.goodInterest.data(), dataset.goodInterest.size()));
+ Interest badSigInterest(Block(dataset.badSigInterest.data(), dataset.badSigInterest.size()));
+
+ BOOST_CHECK(verifyDigest(data, DigestAlgorithm::SHA256));
+ BOOST_CHECK(verifyDigest(interest, DigestAlgorithm::SHA256));
+
+ BOOST_CHECK(!verifyDigest(badSigData, DigestAlgorithm::SHA256));
+ BOOST_CHECK(!verifyDigest(badSigInterest, DigestAlgorithm::SHA256));
+
+ Data unsignedData("/some/data");
+ Interest unsignedInterest1("/some/interest/with/several/name/components");
+ Interest unsignedInterest2("/interest-with-one-name-component");
+
+ BOOST_CHECK(!verifyDigest(unsignedData, DigestAlgorithm::SHA256));
+ BOOST_CHECK(!verifyDigest(unsignedInterest1, DigestAlgorithm::SHA256));
+ BOOST_CHECK(!verifyDigest(unsignedInterest2, DigestAlgorithm::SHA256));
+
+ // - base version of verifyDigest is tested transitively
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestVerificationHelpers
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace security
+} // namespace ndn