security: Move KeyChain to security::v1 namespace and deprecated it
Change-Id: Ic4b6915ca15998a83b410f3f8fac027f797ee7ca
Refs: #3098
diff --git a/src/security/v1/key-chain.cpp b/src/security/v1/key-chain.cpp
new file mode 100644
index 0000000..f70bf05
--- /dev/null
+++ b/src/security/v1/key-chain.cpp
@@ -0,0 +1,846 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2017 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 Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
+ */
+
+#include "key-chain.hpp"
+#include "../signing-helpers.hpp"
+
+#include "../../util/random.hpp"
+#include "../../util/config-file.hpp"
+
+#include "sec-public-info-sqlite3.hpp"
+
+#ifdef NDN_CXX_HAVE_OSX_SECURITY
+#include "sec-tpm-osx.hpp"
+#endif // NDN_CXX_HAVE_OSX_SECURITY
+
+#include "sec-tpm-file.hpp"
+
+namespace ndn {
+namespace security {
+namespace v1 {
+
+// Use a GUID as a magic number of KeyChain::DEFAULT_PREFIX identifier
+const Name KeyChain::DEFAULT_PREFIX("/723821fd-f534-44b3-80d9-44bf5f58bbbb");
+
+// Note: cannot use default constructor, as it depends on static variables which may or may not be
+// initialized at this point
+const SigningInfo KeyChain::DEFAULT_SIGNING_INFO(SigningInfo::SIGNER_TYPE_NULL, Name(), SignatureInfo());
+
+const RsaKeyParams KeyChain::DEFAULT_KEY_PARAMS;
+
+const std::string DEFAULT_PIB_SCHEME = "pib-sqlite3";
+
+#if defined(NDN_CXX_HAVE_OSX_SECURITY) and defined(NDN_CXX_WITH_OSX_KEYCHAIN)
+const std::string DEFAULT_TPM_SCHEME = "tpm-osxkeychain";
+#else
+const std::string DEFAULT_TPM_SCHEME = "tpm-file";
+#endif // defined(NDN_CXX_HAVE_OSX_SECURITY) and defined(NDN_CXX_WITH_OSX_KEYCHAIN)
+
+// When static library is used, not everything is compiled into the resulting binary.
+// Therefore, the following standard PIB and TPMs need to be registered here.
+// http://stackoverflow.com/q/9459980/2150331
+//
+// Also, cannot use Type::SCHEME, as its value may be uninitialized
+NDN_CXX_V1_KEYCHAIN_REGISTER_PIB(SecPublicInfoSqlite3, "pib-sqlite3", "sqlite3");
+
+#ifdef NDN_CXX_HAVE_OSX_SECURITY
+NDN_CXX_V1_KEYCHAIN_REGISTER_TPM(SecTpmOsx, "tpm-osxkeychain", "osx-keychain");
+#endif // NDN_CXX_HAVE_OSX_SECURITY
+
+NDN_CXX_V1_KEYCHAIN_REGISTER_TPM(SecTpmFile, "tpm-file", "file");
+
+template<class T>
+struct Factory
+{
+ Factory(const std::string& canonicalName, const T& create)
+ : canonicalName(canonicalName)
+ , create(create)
+ {
+ }
+
+ std::string canonicalName;
+ T create;
+};
+typedef Factory<KeyChain::PibCreateFunc> PibFactory;
+typedef Factory<KeyChain::TpmCreateFunc> TpmFactory;
+
+static std::map<std::string, PibFactory>&
+getPibFactories()
+{
+ static std::map<std::string, PibFactory> pibFactories;
+ return pibFactories;
+}
+
+static std::map<std::string, TpmFactory>&
+getTpmFactories()
+{
+ static std::map<std::string, TpmFactory> tpmFactories;
+ return tpmFactories;
+}
+
+void
+KeyChain::registerPibImpl(const std::string& canonicalName,
+ std::initializer_list<std::string> aliases,
+ KeyChain::PibCreateFunc createFunc)
+{
+ for (const std::string& alias : aliases) {
+ getPibFactories().insert(make_pair(alias, PibFactory(canonicalName, createFunc)));
+ }
+}
+
+void
+KeyChain::registerTpmImpl(const std::string& canonicalName,
+ std::initializer_list<std::string> aliases,
+ KeyChain::TpmCreateFunc createFunc)
+{
+ for (const std::string& alias : aliases) {
+ getTpmFactories().insert(make_pair(alias, TpmFactory(canonicalName, createFunc)));
+ }
+}
+
+KeyChain::KeyChain()
+ : m_pib(nullptr)
+ , m_tpm(nullptr)
+ , m_lastTimestamp(time::toUnixTimestamp(time::system_clock::now()))
+{
+ std::string pibLocator;
+ std::string tpmLocator;
+
+ if (getenv("NDN_CLIENT_PIB") != nullptr) {
+ pibLocator = getenv("NDN_CLIENT_PIB");
+ }
+
+ if (getenv("NDN_CLIENT_TPM") != nullptr) {
+ tpmLocator = getenv("NDN_CLIENT_TPM");
+ }
+
+ if (pibLocator.empty() || tpmLocator.empty()) {
+ ConfigFile config;
+ const ConfigFile::Parsed& parsed = config.getParsedConfiguration();
+
+ if (pibLocator.empty()) {
+ pibLocator = parsed.get<std::string>("pib", "");
+ }
+
+ if (tpmLocator.empty()) {
+ tpmLocator = parsed.get<std::string>("tpm", "");
+ }
+ }
+
+ initialize(pibLocator, tpmLocator, false);
+}
+
+KeyChain::KeyChain(const std::string& pibName,
+ const std::string& tpmName,
+ bool allowReset)
+ : m_pib(nullptr)
+ , m_tpm(nullptr)
+ , m_lastTimestamp(time::toUnixTimestamp(time::system_clock::now()))
+{
+ initialize(pibName, tpmName, allowReset);
+}
+
+KeyChain::~KeyChain()
+{
+}
+
+static inline std::tuple<std::string/*type*/, std::string/*location*/>
+parseUri(const std::string& uri)
+{
+ size_t pos = uri.find(':');
+ if (pos != std::string::npos) {
+ return std::make_tuple(uri.substr(0, pos),
+ uri.substr(pos + 1));
+ }
+ else {
+ return std::make_tuple(uri, "");
+ }
+}
+
+std::string
+KeyChain::getDefaultPibLocator()
+{
+ std::string defaultPibLocator = DEFAULT_PIB_SCHEME + ":";
+ return defaultPibLocator;
+}
+
+static inline std::tuple<std::string/*type*/, std::string/*location*/>
+getCanonicalPibLocator(const std::string& pibLocator)
+{
+ std::string pibScheme, pibLocation;
+ std::tie(pibScheme, pibLocation) = parseUri(pibLocator);
+
+ if (pibScheme.empty()) {
+ pibScheme = DEFAULT_PIB_SCHEME;
+ }
+
+ auto pibFactory = getPibFactories().find(pibScheme);
+ if (pibFactory == getPibFactories().end()) {
+ BOOST_THROW_EXCEPTION(KeyChain::Error("PIB scheme '" + pibScheme + "' is not supported"));
+ }
+ pibScheme = pibFactory->second.canonicalName;
+
+ return std::make_tuple(pibScheme, pibLocation);
+}
+
+unique_ptr<SecPublicInfo>
+KeyChain::createPib(const std::string& pibLocator)
+{
+ BOOST_ASSERT(!getPibFactories().empty());
+
+ std::string pibScheme, pibLocation;
+ std::tie(pibScheme, pibLocation) = getCanonicalPibLocator(pibLocator);
+ auto pibFactory = getPibFactories().find(pibScheme);
+ BOOST_ASSERT(pibFactory != getPibFactories().end());
+ return pibFactory->second.create(pibLocation);
+}
+
+std::string
+KeyChain::getDefaultTpmLocator()
+{
+ std::string defaultTpmLocator = DEFAULT_TPM_SCHEME + ":";
+ return defaultTpmLocator;
+}
+
+static inline std::tuple<std::string/*type*/, std::string/*location*/>
+getCanonicalTpmLocator(const std::string& tpmLocator)
+{
+ std::string tpmScheme, tpmLocation;
+ std::tie(tpmScheme, tpmLocation) = parseUri(tpmLocator);
+
+ if (tpmScheme.empty()) {
+ tpmScheme = DEFAULT_TPM_SCHEME;
+ }
+ auto tpmFactory = getTpmFactories().find(tpmScheme);
+ if (tpmFactory == getTpmFactories().end()) {
+ BOOST_THROW_EXCEPTION(KeyChain::Error("TPM scheme '" + tpmScheme + "' is not supported"));
+ }
+ tpmScheme = tpmFactory->second.canonicalName;
+
+ return std::make_tuple(tpmScheme, tpmLocation);
+}
+
+unique_ptr<SecTpm>
+KeyChain::createTpm(const std::string& tpmLocator)
+{
+ BOOST_ASSERT(!getTpmFactories().empty());
+
+ std::string tpmScheme, tpmLocation;
+ std::tie(tpmScheme, tpmLocation) = getCanonicalTpmLocator(tpmLocator);
+ auto tpmFactory = getTpmFactories().find(tpmScheme);
+ BOOST_ASSERT(tpmFactory != getTpmFactories().end());
+ return tpmFactory->second.create(tpmLocation);
+}
+
+void
+KeyChain::initialize(const std::string& pibLocator,
+ const std::string& tpmLocator,
+ bool allowReset)
+{
+ // PIB Locator
+ std::string pibScheme, pibLocation;
+ std::tie(pibScheme, pibLocation) = getCanonicalPibLocator(pibLocator);
+ std::string canonicalPibLocator = pibScheme + ":" + pibLocation;
+
+ // Create PIB
+ m_pib = createPib(canonicalPibLocator);
+
+ // TPM Locator
+ std::string tpmScheme, tpmLocation;
+ std::tie(tpmScheme, tpmLocation) = getCanonicalTpmLocator(tpmLocator);
+ std::string canonicalTpmLocator = tpmScheme + ":" + tpmLocation;
+
+ // Create TPM, checking that it matches to the previously associated one
+ try {
+ if (!allowReset &&
+ !m_pib->getTpmLocator().empty() && m_pib->getTpmLocator() != canonicalTpmLocator)
+ // Tpm mismatch, but we do not want to reset PIB
+ BOOST_THROW_EXCEPTION(MismatchError("TPM locator supplied does not match TPM locator in PIB: "
+ + m_pib->getTpmLocator() + " != " + canonicalTpmLocator));
+ }
+ catch (const SecPublicInfo::Error&) {
+ // TPM locator is not set in PIB yet.
+ }
+
+ // note that key mismatch may still happen if the TPM locator is initially set to a
+ // wrong one or if the PIB was shared by more than one TPMs before. This is due to the
+ // old PIB does not have TPM info, new pib should not have this problem.
+ m_tpm = createTpm(canonicalTpmLocator);
+ m_pib->setTpmLocator(canonicalTpmLocator);
+}
+
+Name
+KeyChain::createIdentity(const Name& identityName, const KeyParams& params)
+{
+ m_pib->addIdentity(identityName);
+
+ Name keyName;
+ try {
+ keyName = m_pib->getDefaultKeyNameForIdentity(identityName);
+
+ shared_ptr<PublicKey> key = m_pib->getPublicKey(keyName);
+
+ if (key->getKeyType() != params.getKeyType()) {
+ keyName = generateKeyPair(identityName, true, params);
+ m_pib->setDefaultKeyNameForIdentity(keyName);
+ }
+ }
+ catch (const SecPublicInfo::Error& e) {
+ keyName = generateKeyPair(identityName, true, params);
+ m_pib->setDefaultKeyNameForIdentity(keyName);
+ }
+
+ Name certName;
+ try {
+ certName = m_pib->getDefaultCertificateNameForKey(keyName);
+ }
+ catch (const SecPublicInfo::Error& e) {
+ shared_ptr<IdentityCertificate> selfCert = selfSign(keyName);
+ m_pib->addCertificateAsIdentityDefault(*selfCert);
+ certName = selfCert->getName();
+ }
+
+ return certName;
+}
+
+Name
+KeyChain::generateRsaKeyPair(const Name& identityName, bool isKsk, uint32_t keySize)
+{
+ RsaKeyParams params(keySize);
+ return generateKeyPair(identityName, isKsk, params);
+}
+
+Name
+KeyChain::generateEcdsaKeyPair(const Name& identityName, bool isKsk, uint32_t keySize)
+{
+ EcdsaKeyParams params(keySize);
+ return generateKeyPair(identityName, isKsk, params);
+}
+
+Name
+KeyChain::generateRsaKeyPairAsDefault(const Name& identityName, bool isKsk, uint32_t keySize)
+{
+ RsaKeyParams params(keySize);
+
+ Name keyName = generateKeyPair(identityName, isKsk, params);
+
+ m_pib->setDefaultKeyNameForIdentity(keyName);
+
+ return keyName;
+}
+
+Name
+KeyChain::generateEcdsaKeyPairAsDefault(const Name& identityName, bool isKsk, uint32_t keySize)
+{
+ EcdsaKeyParams params(keySize);
+
+ Name keyName = generateKeyPair(identityName, isKsk, params);
+
+ m_pib->setDefaultKeyNameForIdentity(keyName);
+
+ return keyName;
+}
+
+
+shared_ptr<IdentityCertificate>
+KeyChain::prepareUnsignedIdentityCertificate(const Name& keyName,
+ const Name& signingIdentity,
+ const time::system_clock::TimePoint& notBefore,
+ const time::system_clock::TimePoint& notAfter,
+ const std::vector<CertificateSubjectDescription>& subjectDescription,
+ const Name& certPrefix)
+{
+ shared_ptr<PublicKey> publicKey;
+ try {
+ publicKey = m_pib->getPublicKey(keyName);
+ }
+ catch (const SecPublicInfo::Error& e) {
+ return nullptr;
+ }
+
+ return prepareUnsignedIdentityCertificate(keyName, *publicKey, signingIdentity,
+ notBefore, notAfter,
+ subjectDescription, certPrefix);
+}
+
+shared_ptr<IdentityCertificate>
+KeyChain::prepareUnsignedIdentityCertificate(const Name& keyName,
+ const PublicKey& publicKey,
+ const Name& signingIdentity,
+ const time::system_clock::TimePoint& notBefore,
+ const time::system_clock::TimePoint& notAfter,
+ const std::vector<CertificateSubjectDescription>& subjectDescription,
+ const Name& certPrefix)
+{
+ if (keyName.size() < 1)
+ return nullptr;
+
+ std::string keyIdPrefix = keyName.get(-1).toUri().substr(0, 4);
+ if (keyIdPrefix != "ksk-" && keyIdPrefix != "dsk-")
+ return nullptr;
+
+ Name certName;
+
+ if (certPrefix == KeyChain::DEFAULT_PREFIX) {
+ // No certificate prefix hint, infer the prefix
+ if (signingIdentity.isPrefixOf(keyName))
+ certName.append(signingIdentity)
+ .append("KEY")
+ .append(keyName.getSubName(signingIdentity.size()))
+ .append("ID-CERT")
+ .appendVersion();
+ else
+ certName.append(keyName.getPrefix(-1))
+ .append("KEY")
+ .append(keyName.get(-1))
+ .append("ID-CERT")
+ .appendVersion();
+ }
+ else {
+ // cert prefix hint is supplied, determine the cert name.
+ if (certPrefix.isPrefixOf(keyName) && certPrefix != keyName)
+ certName.append(certPrefix)
+ .append("KEY")
+ .append(keyName.getSubName(certPrefix.size()))
+ .append("ID-CERT")
+ .appendVersion();
+ else
+ return nullptr;
+ }
+
+ auto certificate = make_shared<IdentityCertificate>();
+ certificate->setName(certName);
+ certificate->setNotBefore(notBefore);
+ certificate->setNotAfter(notAfter);
+ certificate->setPublicKeyInfo(publicKey);
+
+ if (subjectDescription.empty()) {
+ CertificateSubjectDescription subjectName(oid::ATTRIBUTE_NAME, keyName.getPrefix(-1).toUri());
+ certificate->addSubjectDescription(subjectName);
+ }
+ else {
+ std::vector<CertificateSubjectDescription>::const_iterator sdIt = subjectDescription.begin();
+ std::vector<CertificateSubjectDescription>::const_iterator sdEnd = subjectDescription.end();
+ for(; sdIt != sdEnd; sdIt++)
+ certificate->addSubjectDescription(*sdIt);
+ }
+
+ certificate->encode();
+
+ return certificate;
+}
+
+std::tuple<Name, SignatureInfo>
+KeyChain::prepareSignatureInfo(const SigningInfo& params)
+{
+ SignatureInfo sigInfo = params.getSignatureInfo();
+
+ shared_ptr<IdentityCertificate> signingCert;
+
+ switch (params.getSignerType()) {
+ case SigningInfo::SIGNER_TYPE_NULL: {
+ if (m_pib->getDefaultCertificate() == nullptr)
+ setDefaultCertificateInternal();
+
+ signingCert = m_pib->getDefaultCertificate();
+ break;
+ }
+ case SigningInfo::SIGNER_TYPE_ID: {
+ Name signingCertName;
+ try {
+ signingCertName = m_pib->getDefaultCertificateNameForIdentity(params.getSignerName());
+ }
+ catch (const SecPublicInfo::Error&) {
+ signingCertName = createIdentity(params.getSignerName(), getDefaultKeyParamsForIdentity(params.getSignerName()));
+ }
+
+ signingCert = m_pib->getCertificate(signingCertName);
+
+ break;
+ }
+ case SigningInfo::SIGNER_TYPE_KEY: {
+ Name signingCertName;
+ try {
+ signingCertName = m_pib->getDefaultCertificateNameForKey(params.getSignerName());
+ }
+ catch (const SecPublicInfo::Error&) {
+ BOOST_THROW_EXCEPTION(Error("signing certificate does not exist"));
+ }
+
+ signingCert = m_pib->getCertificate(signingCertName);
+
+ break;
+ }
+ case SigningInfo::SIGNER_TYPE_CERT: {
+ signingCert = m_pib->getCertificate(params.getSignerName());
+ if (signingCert == nullptr)
+ BOOST_THROW_EXCEPTION(Error("signing certificate does not exist"));
+
+ break;
+ }
+ case SigningInfo::SIGNER_TYPE_SHA256: {
+ sigInfo.setSignatureType(tlv::DigestSha256);
+ return std::make_tuple(SigningInfo::getDigestSha256Identity(), sigInfo);
+ }
+ default:
+ BOOST_THROW_EXCEPTION(Error("Unrecognized signer type"));
+ }
+
+ sigInfo.setSignatureType(getSignatureType(signingCert->getPublicKeyInfo().getKeyType(),
+ params.getDigestAlgorithm()));
+ sigInfo.setKeyLocator(KeyLocator(signingCert->getName().getPrefix(-1)));
+
+ return std::make_tuple(signingCert->getPublicKeyName(), sigInfo);
+}
+
+void
+KeyChain::sign(Data& data, const SigningInfo& params)
+{
+ signImpl(data, params);
+}
+
+void
+KeyChain::sign(Interest& interest, const SigningInfo& params)
+{
+ signImpl(interest, params);
+}
+
+Block
+KeyChain::sign(const uint8_t* buffer, size_t bufferLength, const SigningInfo& params)
+{
+ Name keyName;
+ SignatureInfo sigInfo;
+ std::tie(keyName, sigInfo) = prepareSignatureInfo(params);
+ return pureSign(buffer, bufferLength, keyName, DigestAlgorithm::SHA256);
+}
+
+Signature
+KeyChain::sign(const uint8_t* buffer, size_t bufferLength, const Name& certificateName)
+{
+ shared_ptr<IdentityCertificate> certificate = m_pib->getCertificate(certificateName);
+
+ if (certificate == nullptr) {
+ BOOST_THROW_EXCEPTION(SecPublicInfo::Error("certificate does not exist"));
+ }
+
+ Signature sig;
+
+ // For temporary usage, we support SHA256 only, but will support more.
+ sig.setValue(m_tpm->signInTpm(buffer, bufferLength,
+ certificate->getPublicKeyName(),
+ DigestAlgorithm::SHA256));
+
+ return sig;
+}
+
+shared_ptr<IdentityCertificate>
+KeyChain::selfSign(const Name& keyName)
+{
+ shared_ptr<PublicKey> pubKey;
+ try {
+ pubKey = m_pib->getPublicKey(keyName); // may throw an exception.
+ }
+ catch (const SecPublicInfo::Error&) {
+ return nullptr;
+ }
+
+ auto certificate = make_shared<IdentityCertificate>();
+
+ Name certificateName = keyName.getPrefix(-1);
+ certificateName.append("KEY").append(keyName.get(-1)).append("ID-CERT").appendVersion();
+
+ certificate->setName(certificateName);
+ certificate->setNotBefore(time::system_clock::now());
+ certificate->setNotAfter(time::system_clock::now() + time::days(7300)); // ~20 years
+ certificate->setPublicKeyInfo(*pubKey);
+ certificate->addSubjectDescription(CertificateSubjectDescription(oid::ATTRIBUTE_NAME,
+ keyName.toUri()));
+ certificate->encode();
+
+ certificate->setSignature(Signature(SignatureInfo()));
+
+ selfSign(*certificate);
+ return certificate;
+}
+
+void
+KeyChain::selfSign(IdentityCertificate& cert)
+{
+ Name keyName = cert.getPublicKeyName();
+
+ if (!m_tpm->doesKeyExistInTpm(keyName, KeyClass::PRIVATE))
+ BOOST_THROW_EXCEPTION(SecTpm::Error("Private key does not exist"));
+
+ SignatureInfo sigInfo(cert.getSignature().getInfo());
+ sigInfo.setKeyLocator(KeyLocator(cert.getName().getPrefix(-1)));
+ sigInfo.setSignatureType(getSignatureType(cert.getPublicKeyInfo().getKeyType(),
+ DigestAlgorithm::SHA256));
+
+ signPacketWrapper(cert, Signature(sigInfo), keyName, DigestAlgorithm::SHA256);
+}
+
+shared_ptr<SecuredBag>
+KeyChain::exportIdentity(const Name& identity, const std::string& passwordStr)
+{
+ if (!m_pib->doesIdentityExist(identity))
+ BOOST_THROW_EXCEPTION(SecPublicInfo::Error("Identity does not exist"));
+
+ Name keyName = m_pib->getDefaultKeyNameForIdentity(identity);
+
+ ConstBufferPtr pkcs5;
+ try {
+ pkcs5 = m_tpm->exportPrivateKeyPkcs5FromTpm(keyName, passwordStr);
+ }
+ catch (const SecTpm::Error& e) {
+ BOOST_THROW_EXCEPTION(SecPublicInfo::Error("Fail to export PKCS5 of private key"));
+ }
+
+ shared_ptr<IdentityCertificate> cert;
+ try {
+ cert = m_pib->getCertificate(m_pib->getDefaultCertificateNameForKey(keyName));
+ }
+ catch (const SecPublicInfo::Error& e) {
+ cert = selfSign(keyName);
+ m_pib->addCertificateAsIdentityDefault(*cert);
+ }
+
+ // make_shared on OSX 10.9 has some strange problem here
+ return shared_ptr<SecuredBag>(new SecuredBag(*cert, pkcs5));
+}
+
+void
+KeyChain::importIdentity(const SecuredBag& securedBag, const std::string& passwordStr)
+{
+ Name certificateName = securedBag.getCertificate().getName();
+ Name keyName = IdentityCertificate::certificateNameToPublicKeyName(certificateName);
+ Name identity = keyName.getPrefix(-1);
+
+ // Add identity
+ m_pib->addIdentity(identity);
+
+ // Add key
+ m_tpm->importPrivateKeyPkcs5IntoTpm(keyName,
+ securedBag.getKey()->buf(),
+ securedBag.getKey()->size(),
+ passwordStr);
+
+ shared_ptr<PublicKey> pubKey = m_tpm->getPublicKeyFromTpm(keyName.toUri());
+ // HACK! We should set key type according to the pkcs8 info.
+ m_pib->addKey(keyName, *pubKey);
+ m_pib->setDefaultKeyNameForIdentity(keyName);
+
+ // Add cert
+ m_pib->addCertificateAsIdentityDefault(securedBag.getCertificate());
+}
+
+const KeyParams&
+KeyChain::getDefaultKeyParamsForIdentity(const Name &identityName) const
+{
+ KeyType keyType = KeyType::NONE;
+ try {
+ keyType = m_pib->getPublicKeyType(m_pib->getDefaultKeyNameForIdentity(identityName));
+ }
+ catch (const SecPublicInfo::Error& e) { // @TODO Switch to Pib::Error
+ return DEFAULT_KEY_PARAMS;
+ }
+
+ switch (keyType) {
+ case KeyType::RSA: {
+ static RsaKeyParams defaultRsaParams;
+ return defaultRsaParams;
+ }
+ case KeyType::EC: {
+ static EcdsaKeyParams defaultEcdsaParams;
+ return defaultEcdsaParams;
+ }
+ case KeyType::NONE: {
+ return DEFAULT_KEY_PARAMS;
+ }
+ default:
+ BOOST_THROW_EXCEPTION(Error("Unsupported key type"));
+ }
+}
+
+void
+KeyChain::setDefaultCertificateInternal()
+{
+ m_pib->refreshDefaultCertificate();
+
+ if (m_pib->getDefaultCertificate() == nullptr) {
+ Name defaultIdentity;
+ try {
+ defaultIdentity = m_pib->getDefaultIdentity();
+ }
+ catch (const SecPublicInfo::Error& e) {
+ uint32_t random = random::generateWord32();
+ defaultIdentity.append("tmp-identity")
+ .append(reinterpret_cast<uint8_t*>(&random), 4);
+ }
+ createIdentity(defaultIdentity);
+ m_pib->setDefaultIdentity(defaultIdentity);
+ m_pib->refreshDefaultCertificate();
+ }
+}
+
+Name
+KeyChain::generateKeyPair(const Name& identityName, bool isKsk, const KeyParams& params)
+{
+ Name keyName = m_pib->getNewKeyName(identityName, isKsk);
+
+ m_tpm->generateKeyPairInTpm(keyName.toUri(), params);
+
+ shared_ptr<PublicKey> pubKey = m_tpm->getPublicKeyFromTpm(keyName.toUri());
+ m_pib->addKey(keyName, *pubKey);
+
+ return keyName;
+}
+
+void
+KeyChain::signPacketWrapper(Data& data, const Signature& signature,
+ const Name& keyName, DigestAlgorithm digestAlgorithm)
+{
+ data.setSignature(signature);
+
+ EncodingBuffer encoder;
+ data.wireEncode(encoder, true);
+
+ Block sigValue = pureSign(encoder.buf(), encoder.size(), keyName, digestAlgorithm);
+
+ data.wireEncode(encoder, sigValue);
+}
+
+void
+KeyChain::signPacketWrapper(Interest& interest, const Signature& signature,
+ const Name& keyName, DigestAlgorithm digestAlgorithm)
+{
+ time::milliseconds timestamp = time::toUnixTimestamp(time::system_clock::now());
+ if (timestamp <= m_lastTimestamp) {
+ timestamp = m_lastTimestamp + time::milliseconds(1);
+ }
+
+ Name signedName = interest.getName();
+ signedName
+ .append(name::Component::fromNumber(timestamp.count())) // timestamp
+ .append(name::Component::fromNumber(random::generateWord64())) // nonce
+ .append(signature.getInfo()); // signatureInfo
+
+ Block sigValue = pureSign(signedName.wireEncode().value(),
+ signedName.wireEncode().value_size(),
+ keyName,
+ digestAlgorithm);
+
+ sigValue.encode();
+ signedName.append(sigValue); // signatureValue
+ interest.setName(signedName);
+}
+
+Block
+KeyChain::pureSign(const uint8_t* buf, size_t size,
+ const Name& keyName, DigestAlgorithm digestAlgorithm) const
+{
+ if (keyName == SigningInfo::getDigestSha256Identity())
+ return Block(tlv::SignatureValue, crypto::computeSha256Digest(buf, size));
+
+ return m_tpm->signInTpm(buf, size, keyName, digestAlgorithm);
+}
+
+Signature
+KeyChain::signByIdentity(const uint8_t* buffer, size_t bufferLength, const Name& identityName)
+{
+ Signature sig;
+ sig.setValue(sign(buffer, bufferLength, signingByIdentity(identityName)));
+ return sig;
+}
+
+void
+KeyChain::signWithSha256(Data& data)
+{
+ return sign(data, signingWithSha256());
+}
+
+void
+KeyChain::signWithSha256(Interest& interest)
+{
+ DigestSha256 sig;
+
+ time::milliseconds timestamp = time::toUnixTimestamp(time::system_clock::now());
+ if (timestamp <= m_lastTimestamp)
+ timestamp = m_lastTimestamp + time::milliseconds(1);
+
+ Name signedName = interest.getName();
+ signedName
+ .append(name::Component::fromNumber(timestamp.count())) // timestamp
+ .append(name::Component::fromNumber(random::generateWord64())) // nonce
+ .append(sig.getInfo()); // signatureInfo
+
+ Block sigValue(tlv::SignatureValue,
+ crypto::computeSha256Digest(signedName.wireEncode().value(),
+ signedName.wireEncode().value_size()));
+
+ sigValue.encode();
+ signedName.append(sigValue); // signatureValue
+ interest.setName(signedName);
+}
+
+void
+KeyChain::deleteCertificate(const Name& certificateName)
+{
+ m_pib->deleteCertificateInfo(certificateName);
+}
+
+void
+KeyChain::deleteKey(const Name& keyName)
+{
+ m_pib->deletePublicKeyInfo(keyName);
+ m_tpm->deleteKeyPairInTpm(keyName);
+}
+
+void
+KeyChain::deleteIdentity(const Name& identity)
+{
+ std::vector<Name> keyNames;
+ m_pib->getAllKeyNamesOfIdentity(identity, keyNames, true);
+ m_pib->getAllKeyNamesOfIdentity(identity, keyNames, false);
+
+ m_pib->deleteIdentityInfo(identity);
+
+ for (const auto& keyName : keyNames)
+ m_tpm->deleteKeyPairInTpm(keyName);
+}
+
+tlv::SignatureTypeValue
+KeyChain::getSignatureType(KeyType keyType, DigestAlgorithm digestAlgorithm)
+{
+ switch (keyType) {
+ case KeyType::RSA:
+ return tlv::SignatureSha256WithRsa;
+ case KeyType::EC:
+ return tlv::SignatureSha256WithEcdsa;
+ default:
+ BOOST_THROW_EXCEPTION(Error("Unsupported key types"));
+ }
+}
+
+} // namespace v1
+} // namespace security
+} // namespace ndn