security: Add new v2::KeyChain
Change-Id: I5fdf51ecd96b50db2a7cbf730c6e8b1d9fbe09e9
Refs: #2926
diff --git a/src/security/v2/key-chain.cpp b/src/security/v2/key-chain.cpp
new file mode 100644
index 0000000..0f3909e
--- /dev/null
+++ b/src/security/v2/key-chain.cpp
@@ -0,0 +1,698 @@
+/* -*- 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.
+ */
+
+#include "key-chain.hpp"
+
+#include "../../util/config-file.hpp"
+
+#include "../pib/pib-sqlite3.hpp"
+#include "../pib/pib-memory.hpp"
+
+#ifdef NDN_CXX_HAVE_OSX_SECURITY
+#include "../tpm/back-end-osx.hpp"
+#endif // NDN_CXX_HAVE_OSX_SECURITY
+
+#include "../tpm/back-end-file.hpp"
+#include "../tpm/back-end-mem.hpp"
+
+#include "../transform/bool-sink.hpp"
+#include "../transform/buffer-source.hpp"
+#include "../transform/private-key.hpp"
+#include "../transform/verifier-filter.hpp"
+#include "../../encoding/buffer-stream.hpp"
+#include "../../util/crypto.hpp"
+
+#include <boost/lexical_cast.hpp>
+
+namespace ndn {
+namespace security {
+
+// 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
+
+/////////
+// PIB //
+/////////
+namespace pib {
+NDN_CXX_V2_KEYCHAIN_REGISTER_PIB_BACKEND(PibSqlite3);
+NDN_CXX_V2_KEYCHAIN_REGISTER_PIB_BACKEND(PibMemory);
+} // namespace pib
+
+/////////
+// TPM //
+/////////
+namespace tpm {
+#if defined(NDN_CXX_HAVE_OSX_SECURITY) && defined(NDN_CXX_WITH_OSX_KEYCHAIN)
+NDN_CXX_V2_KEYCHAIN_REGISTER_TPM_BACKEND(BackEndOsx);
+#endif // defined(NDN_CXX_HAVE_OSX_SECURITY) && defined(NDN_CXX_WITH_OSX_KEYCHAIN)
+
+NDN_CXX_V2_KEYCHAIN_REGISTER_TPM_BACKEND(BackEndFile);
+NDN_CXX_V2_KEYCHAIN_REGISTER_TPM_BACKEND(BackEndMem);
+} // namespace tpm
+
+namespace v2 {
+
+std::string KeyChain::s_defaultPibLocator;
+std::string KeyChain::s_defaultTpmLocator;
+
+KeyChain::PibFactories&
+KeyChain::getPibFactories()
+{
+ static PibFactories pibFactories;
+ return pibFactories;
+}
+
+KeyChain::TpmFactories&
+KeyChain::getTpmFactories()
+{
+ static TpmFactories tpmFactories;
+ return tpmFactories;
+}
+
+const std::string&
+KeyChain::getDefaultPibScheme()
+{
+ return pib::PibSqlite3::getScheme();;
+}
+
+const std::string&
+KeyChain::getDefaultTpmScheme()
+{
+#if defined(NDN_CXX_HAVE_OSX_SECURITY) && defined(NDN_CXX_WITH_OSX_KEYCHAIN)
+ return tpm::BackEndOsx::getScheme();;
+#else
+ return tpm::BackEndFile::getScheme();
+#endif // defined(NDN_CXX_HAVE_OSX_SECURITY) && defined(NDN_CXX_WITH_OSX_KEYCHAIN)
+}
+
+const std::string&
+KeyChain::getDefaultPibLocator()
+{
+ if (!s_defaultPibLocator.empty())
+ return s_defaultPibLocator;
+
+ if (getenv("NDN_CLIENT_PIB") != nullptr) {
+ s_defaultPibLocator = getenv("NDN_CLIENT_PIB");
+ }
+ else {
+ ConfigFile config;
+ s_defaultPibLocator = config.getParsedConfiguration().get<std::string>("pib", getDefaultPibScheme() + ":");
+ }
+
+ return s_defaultPibLocator;
+}
+
+const std::string&
+KeyChain::getDefaultTpmLocator()
+{
+ if (!s_defaultTpmLocator.empty())
+ return s_defaultTpmLocator;
+
+ if (getenv("NDN_CLIENT_TPM") != nullptr) {
+ s_defaultTpmLocator = getenv("NDN_CLIENT_TPM");
+ }
+ else {
+ ConfigFile config;
+ s_defaultTpmLocator = config.getParsedConfiguration().get<std::string>("tpm", getDefaultTpmScheme() + ":");
+ }
+
+ return s_defaultTpmLocator;
+}
+
+
+// Other defaults
+
+const SigningInfo&
+KeyChain::getDefaultSigningInfo()
+{
+ static SigningInfo signingInfo;
+ return signingInfo;
+}
+
+const KeyParams&
+KeyChain::getDefaultKeyParams()
+{
+ static EcdsaKeyParams keyParams;
+ return keyParams;
+}
+
+//
+
+KeyChain::KeyChain()
+ : KeyChain(getDefaultPibLocator(), getDefaultTpmLocator(), true)
+{
+}
+
+KeyChain::KeyChain(const std::string& pibLocator, const std::string& tpmLocator, bool allowReset)
+{
+ // PIB Locator
+ std::string pibScheme, pibLocation;
+ std::tie(pibScheme, pibLocation) = parseAndCheckPibLocator(pibLocator);
+ std::string canonicalPibLocator = pibScheme + ":" + pibLocation;
+
+ // Create PIB
+ m_pib = createPib(canonicalPibLocator);
+ std::string oldTpmLocator;
+ try {
+ oldTpmLocator = m_pib->getTpmLocator();
+ }
+ catch (const Pib::Error&) {
+ // TPM locator is not set in PIB yet.
+ }
+
+ // TPM Locator
+ std::string tpmScheme, tpmLocation;
+ std::tie(tpmScheme, tpmLocation) = parseAndCheckTpmLocator(tpmLocator);
+ std::string canonicalTpmLocator = tpmScheme + ":" + tpmLocation;
+
+ if (canonicalPibLocator == getDefaultPibLocator()) {
+ // Default PIB must use default TPM
+ if (!oldTpmLocator.empty() && oldTpmLocator != getDefaultTpmLocator()) {
+ m_pib->reset();
+ canonicalTpmLocator = getDefaultTpmLocator();
+ }
+ }
+ else {
+ // non-default PIB check consistency
+ if (!oldTpmLocator.empty() && oldTpmLocator != canonicalTpmLocator) {
+ if (allowReset)
+ m_pib->reset();
+ else
+ BOOST_THROW_EXCEPTION(LocatorMismatchError("TPM locator supplied does not match TPM locator in PIB: " +
+ oldTpmLocator + " != " + canonicalTpmLocator));
+ }
+ }
+
+ // 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);
+}
+
+KeyChain::~KeyChain() = default;
+
+// public: management
+
+Identity
+KeyChain::createIdentity(const Name& identityName, const KeyParams& params)
+{
+ Identity id = m_pib->addIdentity(identityName);
+
+ Key key;
+ try {
+ key = id.getDefaultKey();
+ }
+ catch (const Pib::Error&) {
+ key = createKey(id, params);
+ }
+
+ try {
+ key.getDefaultCertificate();
+ }
+ catch (const Pib::Error&) {
+ selfSign(key);
+ }
+
+ return id;
+}
+
+void
+KeyChain::deleteIdentity(const Identity& identity)
+{
+ BOOST_ASSERT(static_cast<bool>(identity));
+
+ Name identityName = identity.getName();
+
+ for (const auto& key : identity.getKeys()) {
+ m_tpm->deleteKey(key.getName());
+ }
+
+ m_pib->removeIdentity(identityName);
+}
+
+void
+KeyChain::setDefaultIdentity(const Identity& identity)
+{
+ BOOST_ASSERT(static_cast<bool>(identity));
+
+ m_pib->setDefaultIdentity(identity.getName());
+}
+
+Key
+KeyChain::createKey(const Identity& identity, const KeyParams& params)
+{
+ BOOST_ASSERT(static_cast<bool>(identity));
+
+ // create key in TPM
+ Name keyName = m_tpm->createKey(identity.getName(), params);
+
+ // set up key info in PIB
+ ConstBufferPtr pubKey = m_tpm->getPublicKey(keyName);
+ Key key = identity.addKey(pubKey->buf(), pubKey->size(), keyName);
+ selfSign(key);
+
+ return key;
+}
+
+void
+KeyChain::deleteKey(const Identity& identity, const Key& key)
+{
+ BOOST_ASSERT(static_cast<bool>(identity));
+ BOOST_ASSERT(static_cast<bool>(key));
+
+ Name keyName = key.getName();
+ if (identity.getName() != key.getIdentity()) {
+ BOOST_THROW_EXCEPTION(std::invalid_argument("Identity `" + identity.getName().toUri() + "` "
+ "does match key `" + keyName.toUri() + "`"));
+ }
+
+ identity.removeKey(keyName);
+ m_tpm->deleteKey(keyName);
+}
+
+void
+KeyChain::setDefaultKey(const Identity& identity, const Key& key)
+{
+ BOOST_ASSERT(static_cast<bool>(identity));
+ BOOST_ASSERT(static_cast<bool>(key));
+
+ if (identity.getName() != key.getIdentity())
+ BOOST_THROW_EXCEPTION(std::invalid_argument("Identity `" + identity.getName().toUri() + "` "
+ "does match key `" + key.getName().toUri() + "`"));
+
+ identity.setDefaultKey(key.getName());
+}
+
+void
+KeyChain::addCertificate(const Key& key, const Certificate& certificate)
+{
+ BOOST_ASSERT(static_cast<bool>(key));
+
+ if (key.getName() != certificate.getKeyName() ||
+ !std::equal(certificate.getContent().value_begin(), certificate.getContent().value_end(),
+ key.getPublicKey().begin()))
+ BOOST_THROW_EXCEPTION(std::invalid_argument("Key `" + key.getName().toUri() + "` "
+ "does match certificate `" + certificate.getName().toUri() + "`"));
+
+ key.addCertificate(certificate);
+}
+
+void
+KeyChain::deleteCertificate(const Key& key, const Name& certificateName)
+{
+ BOOST_ASSERT(static_cast<bool>(key));
+
+ if (!Certificate::isValidName(certificateName)) {
+ BOOST_THROW_EXCEPTION(std::invalid_argument("Wrong certificate name `" + certificateName.toUri() + "`"));
+ }
+
+ key.removeCertificate(certificateName);
+}
+
+void
+KeyChain::setDefaultCertificate(const Key& key, const Certificate& cert)
+{
+ BOOST_ASSERT(static_cast<bool>(key));
+
+ try {
+ addCertificate(key, cert);
+ }
+ catch (const Pib::Error&) { // force to overwrite the existing certificates
+ key.removeCertificate(cert.getName());
+ addCertificate(key, cert);
+ }
+ key.setDefaultCertificate(cert.getName());
+}
+
+shared_ptr<SafeBag>
+KeyChain::exportSafeBag(const Certificate& certificate, const char* pw, size_t pwLen)
+{
+ Name identity = certificate.getIdentity();
+ Name keyName = certificate.getKeyName();
+
+ ConstBufferPtr encryptedKey;
+ try {
+ encryptedKey = m_tpm->exportPrivateKey(keyName, pw, pwLen);
+ }
+ catch (const tpm::BackEnd::Error&) {
+ BOOST_THROW_EXCEPTION(Error("Private `" + keyName.toUri() + "` key does not exist"));
+ }
+
+ return make_shared<SafeBag>(certificate, *encryptedKey);
+}
+
+void
+KeyChain::importSafeBag(const SafeBag& safeBag, const char* pw, size_t pwLen)
+{
+ Data certData = safeBag.getCertificate();
+ Certificate cert(std::move(certData));
+ Name identity = cert.getIdentity();
+ Name keyName = cert.getKeyName();
+ const Buffer publicKeyBits = cert.getPublicKey();
+
+ if (m_tpm->hasKey(keyName)) {
+ BOOST_THROW_EXCEPTION(Error("Private key `" + keyName.toUri() + "` already exists"));
+ }
+
+ try {
+ Identity existingId = m_pib->getIdentity(identity);
+ existingId.getKey(keyName);
+ BOOST_THROW_EXCEPTION(Error("Public key `" + keyName.toUri() + "` already exists"));
+ }
+ catch (const Pib::Error&) {
+ // Either identity or key doesn't exist. OK to import.
+ }
+
+ try {
+ m_tpm->importPrivateKey(keyName,
+ safeBag.getEncryptedKeyBag().buf(), safeBag.getEncryptedKeyBag().size(),
+ pw, pwLen);
+ }
+ catch (const std::runtime_error&) {
+ BOOST_THROW_EXCEPTION(Error("Fail to import private key `" + keyName.toUri() + "`"));
+ }
+
+ // check the consistency of private key and certificate
+ const uint8_t content[] = {0x01, 0x02, 0x03, 0x04};
+ ConstBufferPtr sigBits;
+ try {
+ sigBits = m_tpm->sign(content, 4, keyName, DigestAlgorithm::SHA256);
+ }
+ catch (const std::runtime_error&) {
+ m_tpm->deleteKey(keyName);
+ BOOST_THROW_EXCEPTION(Error("Invalid private key `" + keyName.toUri() + "`"));
+ }
+ bool isVerified = false;
+ {
+ using namespace transform;
+ PublicKey publicKey;
+ publicKey.loadPkcs8(publicKeyBits.buf(), publicKeyBits.size());
+ bufferSource(content, sizeof(content)) >> verifierFilter(DigestAlgorithm::SHA256, publicKey,
+ sigBits->buf(), sigBits->size())
+ >> boolSink(isVerified);
+ }
+ if (!isVerified) {
+ m_tpm->deleteKey(keyName);
+ BOOST_THROW_EXCEPTION(Error("Certificate `" + cert.getName().toUri() + "` "
+ "and private key `" + keyName.toUri() + "` do not match"));
+ }
+
+ Identity id = m_pib->addIdentity(identity);
+ Key key = id.addKey(cert.getPublicKey().buf(), cert.getPublicKey().size(), keyName);
+ key.addCertificate(cert);
+}
+
+
+// public: signing
+
+void
+KeyChain::sign(Data& data, const SigningInfo& params)
+{
+ Name keyName;
+ SignatureInfo sigInfo;
+ std::tie(keyName, sigInfo) = prepareSignatureInfo(params);
+
+ data.setSignature(Signature(sigInfo));
+
+ EncodingBuffer encoder;
+ data.wireEncode(encoder, true);
+
+ Block sigValue = sign(encoder.buf(), encoder.size(), keyName, params.getDigestAlgorithm());
+
+ data.wireEncode(encoder, sigValue);
+}
+
+void
+KeyChain::sign(Interest& interest, const SigningInfo& params)
+{
+ Name keyName;
+ SignatureInfo sigInfo;
+ std::tie(keyName, sigInfo) = prepareSignatureInfo(params);
+
+ Name signedName = interest.getName();
+ signedName.append(sigInfo.wireEncode()); // signatureInfo
+
+ Block sigValue = sign(signedName.wireEncode().value(), signedName.wireEncode().value_size(),
+ keyName, params.getDigestAlgorithm());
+
+ sigValue.encode();
+ signedName.append(sigValue); // signatureValue
+ interest.setName(signedName);
+}
+
+Block
+KeyChain::sign(const uint8_t* buffer, size_t bufferLength, const SigningInfo& params)
+{
+ Name keyName;
+ SignatureInfo sigInfo;
+ std::tie(keyName, sigInfo) = prepareSignatureInfo(params);
+
+ return sign(buffer, bufferLength, keyName, params.getDigestAlgorithm());
+}
+
+// public: PIB/TPM creation helpers
+
+static inline std::tuple<std::string/*type*/, std::string/*location*/>
+parseLocatorUri(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::tuple<std::string/*type*/, std::string/*location*/>
+KeyChain::parseAndCheckPibLocator(const std::string& pibLocator)
+{
+ std::string pibScheme, pibLocation;
+ std::tie(pibScheme, pibLocation) = parseLocatorUri(pibLocator);
+
+ if (pibScheme.empty()) {
+ pibScheme = getDefaultPibScheme();
+ }
+
+ auto pibFactory = getPibFactories().find(pibScheme);
+ if (pibFactory == getPibFactories().end()) {
+ BOOST_THROW_EXCEPTION(KeyChain::Error("PIB scheme `" + pibScheme + "` is not supported"));
+ }
+
+ return std::make_tuple(pibScheme, pibLocation);
+}
+
+unique_ptr<Pib>
+KeyChain::createPib(const std::string& pibLocator)
+{
+ std::string pibScheme, pibLocation;
+ std::tie(pibScheme, pibLocation) = parseAndCheckPibLocator(pibLocator);
+ auto pibFactory = getPibFactories().find(pibScheme);
+ BOOST_ASSERT(pibFactory != getPibFactories().end());
+ return unique_ptr<Pib>(new Pib(pibScheme, pibLocation, pibFactory->second(pibLocation)));
+}
+
+std::tuple<std::string/*type*/, std::string/*location*/>
+KeyChain::parseAndCheckTpmLocator(const std::string& tpmLocator)
+{
+ std::string tpmScheme, tpmLocation;
+ std::tie(tpmScheme, tpmLocation) = parseLocatorUri(tpmLocator);
+
+ if (tpmScheme.empty()) {
+ tpmScheme = getDefaultTpmScheme();
+ }
+ auto tpmFactory = getTpmFactories().find(tpmScheme);
+ if (tpmFactory == getTpmFactories().end()) {
+ BOOST_THROW_EXCEPTION(KeyChain::Error("TPM scheme `" + tpmScheme + "` is not supported"));
+ }
+
+ return std::make_tuple(tpmScheme, tpmLocation);
+}
+
+unique_ptr<Tpm>
+KeyChain::createTpm(const std::string& tpmLocator)
+{
+ std::string tpmScheme, tpmLocation;
+ std::tie(tpmScheme, tpmLocation) = parseAndCheckTpmLocator(tpmLocator);
+ auto tpmFactory = getTpmFactories().find(tpmScheme);
+ BOOST_ASSERT(tpmFactory != getTpmFactories().end());
+ return unique_ptr<Tpm>(new Tpm(tpmScheme, tpmLocation, tpmFactory->second(tpmLocation)));
+}
+
+// private: signing
+
+Certificate
+KeyChain::selfSign(Key& key)
+{
+ Certificate certificate;
+
+ // set name
+ Name certificateName = key.getName();
+ certificateName
+ .append("self")
+ .appendVersion();
+ certificate.setName(certificateName);
+
+ // set metainfo
+ certificate.setContentType(tlv::ContentType_Key);
+ certificate.setFreshnessPeriod(time::hours(1));
+
+ // set content
+ certificate.setContent(key.getPublicKey().buf(), key.getPublicKey().size());
+
+ // set signature-info
+ SignatureInfo sigInfo;
+ sigInfo.setKeyLocator(key.getName());
+ sigInfo.setSignatureType(getSignatureType(key.getKeyType(), DigestAlgorithm::SHA256));
+ sigInfo.setValidityPeriod(ValidityPeriod(time::system_clock::now(),
+ time::system_clock::now() + time::days(1000 * 3365)));
+ certificate.setSignature(Signature(sigInfo));
+
+ EncodingBuffer encoder;
+ certificate.wireEncode(encoder, true);
+ Block sigValue = sign(encoder.buf(), encoder.size(), key.getName(), DigestAlgorithm::SHA256);
+ certificate.wireEncode(encoder, sigValue);
+
+ key.addCertificate(certificate);
+ return certificate;
+}
+
+std::tuple<Name, SignatureInfo>
+KeyChain::prepareSignatureInfo(const SigningInfo& params)
+{
+ SignatureInfo sigInfo = params.getSignatureInfo();
+
+ Name identityName;
+ name::Component keyId;
+ Name certificateName;
+
+ pib::Identity identity;
+ pib::Key key;
+
+ switch (params.getSignerType()) {
+ case SigningInfo::SIGNER_TYPE_NULL: {
+ try {
+ identity = m_pib->getDefaultIdentity();
+ }
+ catch (const Pib::Error&) { // no default identity, use sha256 for signing.
+ sigInfo.setSignatureType(tlv::DigestSha256);
+ return std::make_tuple(SigningInfo::getDigestSha256Identity(), sigInfo);
+ }
+ break;
+ }
+ case SigningInfo::SIGNER_TYPE_ID: {
+ try {
+ identity = m_pib->getIdentity(params.getSignerName());
+ }
+ catch (const Pib::Error&) {
+ BOOST_THROW_EXCEPTION(InvalidSigningInfoError("Signing identity `" +
+ params.getSignerName().toUri() + "` does not exist"));
+ }
+ break;
+ }
+ case SigningInfo::SIGNER_TYPE_KEY: {
+ Name identityName = extractIdentityFromKeyName(params.getSignerName());
+
+ try {
+ identity = m_pib->getIdentity(identityName);
+ key = identity.getKey(params.getSignerName());
+ identity = Identity(); // we will use the PIB key instance, so reset identity;
+ }
+ catch (const Pib::Error&) {
+ BOOST_THROW_EXCEPTION(InvalidSigningInfoError("Signing key `" +
+ params.getSignerName().toUri() + "` does not exist"));
+ }
+ break;
+ }
+ case SigningInfo::SIGNER_TYPE_CERT: {
+ Name identityName = extractIdentityFromCertName(params.getSignerName());
+ Name keyName = extractKeyNameFromCertName(params.getSignerName());
+
+ try {
+ identity = m_pib->getIdentity(identityName);
+ key = identity.getKey(keyName);
+ }
+ catch (const Pib::Error&) {
+ BOOST_THROW_EXCEPTION(InvalidSigningInfoError("Signing certificate `" +
+ params.getSignerName().toUri() + "` does not exist"));
+ }
+
+ break;
+ }
+ case SigningInfo::SIGNER_TYPE_SHA256: {
+ sigInfo.setSignatureType(tlv::DigestSha256);
+ return std::make_tuple(SigningInfo::getDigestSha256Identity(), sigInfo);
+ }
+ default: {
+ BOOST_THROW_EXCEPTION(InvalidSigningInfoError("Unrecognized signer type " +
+ boost::lexical_cast<std::string>(params.getSignerType())));
+ }
+ }
+
+ if (!identity && !key) {
+ BOOST_THROW_EXCEPTION(InvalidSigningInfoError("Cannot determine signing parameters"));
+ }
+
+ if (identity && !key) {
+ try {
+ key = identity.getDefaultKey();
+ }
+ catch (const Pib::Error&) {
+ BOOST_THROW_EXCEPTION(InvalidSigningInfoError("Signing identity `" + identity.getName().toUri() +
+ "` does not have default certificate"));
+ }
+ }
+
+ BOOST_ASSERT(key);
+
+ sigInfo.setSignatureType(getSignatureType(key.getKeyType(), params.getDigestAlgorithm()));
+ sigInfo.setKeyLocator(KeyLocator(key.getName()));
+ return std::make_tuple(key.getName(), sigInfo);
+}
+
+Block
+KeyChain::sign(const uint8_t* buf, size_t size,
+ const Name& keyName, DigestAlgorithm digestAlgorithm) const
+{
+ if (keyName == SigningInfo::getDigestSha256Identity())
+ return Block(tlv::SignatureValue, crypto::sha256(buf, size));
+
+ return Block(tlv::SignatureValue, m_tpm->sign(buf, size, keyName, digestAlgorithm));
+}
+
+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 v2
+} // namespace security
+} // namespace ndn