| /* -*- 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 "key-chain.hpp" |
| |
| #include "../../util/config-file.hpp" |
| #include "../../util/logger.hpp" |
| #include "../../util/sha256.hpp" |
| |
| #include "../pib/pib-sqlite3.hpp" |
| #include "../pib/pib-memory.hpp" |
| |
| #ifdef NDN_CXX_HAVE_OSX_FRAMEWORKS |
| #include "../tpm/back-end-osx.hpp" |
| #endif // NDN_CXX_HAVE_OSX_FRAMEWORKS |
| |
| #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/public-key.hpp" |
| #include "../transform/verifier-filter.hpp" |
| #include "../../encoding/buffer-stream.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 |
| |
| namespace pib { |
| NDN_CXX_V2_KEYCHAIN_REGISTER_PIB_BACKEND(PibSqlite3); |
| NDN_CXX_V2_KEYCHAIN_REGISTER_PIB_BACKEND(PibMemory); |
| } // namespace pib |
| |
| namespace tpm { |
| #if defined(NDN_CXX_HAVE_OSX_FRAMEWORKS) && defined(NDN_CXX_WITH_OSX_KEYCHAIN) |
| NDN_CXX_V2_KEYCHAIN_REGISTER_TPM_BACKEND(BackEndOsx); |
| #endif // defined(NDN_CXX_HAVE_OSX_FRAMEWORKS) && 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 { |
| |
| NDN_LOG_INIT(ndn.security.v2.KeyChain); |
| |
| 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_FRAMEWORKS) && defined(NDN_CXX_WITH_OSX_KEYCHAIN) |
| return tpm::BackEndOsx::getScheme(); |
| #else |
| return tpm::BackEndFile::getScheme(); |
| #endif // defined(NDN_CXX_HAVE_OSX_FRAMEWORKS) && 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() + ":"); |
| } |
| |
| std::string pibScheme, pibLocation; |
| std::tie(pibScheme, pibLocation) = parseAndCheckPibLocator(s_defaultPibLocator); |
| s_defaultPibLocator = pibScheme + ":" + pibLocation; |
| |
| 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() + ":"); |
| } |
| |
| std::string tpmScheme, tpmLocation; |
| std::tie(tpmScheme, tpmLocation) = parseAndCheckTpmLocator(s_defaultTpmLocator); |
| s_defaultTpmLocator = tpmScheme + ":" + tpmLocation; |
| |
| return s_defaultTpmLocator; |
| } |
| |
| |
| // Other defaults |
| |
| const SigningInfo& |
| KeyChain::getDefaultSigningInfo() |
| { |
| static SigningInfo signingInfo; |
| return signingInfo; |
| } |
| |
| const KeyParams& |
| KeyChain::getDefaultKeyParams() |
| { |
| static EcKeyParams 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&) { |
| NDN_LOG_DEBUG("No default cert for " << key.getName() << ", requesting self-signing"); |
| 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->data(), pubKey->size(), keyName); |
| |
| NDN_LOG_DEBUG("Requesting self-signing for newly created key " << key.getName()); |
| 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 not 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 not 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 not 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)); |
| |
| 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& e) { |
| BOOST_THROW_EXCEPTION(Error("Failed to export private key `" + keyName.toUri() + "`: " + e.what())); |
| } |
| |
| 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().data(), safeBag.getEncryptedKeyBag().size(), |
| pw, pwLen); |
| } |
| catch (const tpm::BackEnd::Error& e) { |
| BOOST_THROW_EXCEPTION(Error("Failed to import private key `" + keyName.toUri() + "`: " + e.what())); |
| } |
| |
| // 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.data(), publicKeyBits.size()); |
| bufferSource(content, sizeof(content)) >> verifierFilter(DigestAlgorithm::SHA256, publicKey, |
| sigBits->data(), 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().data(), 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(1_h); |
| |
| // set content |
| certificate.setContent(key.getPublicKey().data(), key.getPublicKey().size()); |
| |
| // set signature-info |
| SignatureInfo signatureInfo; |
| // Note time::system_clock::max() or other NotAfter date results in incorrect encoded value |
| // because of overflow during conversion to boost::posix_time::ptime (bug #3915). |
| signatureInfo.setValidityPeriod(ValidityPeriod(time::system_clock::TimePoint(), |
| time::system_clock::now() + 20 * 365_days)); |
| |
| sign(certificate, SigningInfo(key).setSignatureInfo(signatureInfo)); |
| |
| 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: { |
| identity = params.getPibIdentity(); |
| if (!identity) { |
| 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: { |
| key = params.getPibKey(); |
| if (!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 a default certificate")); |
| } |
| } |
| |
| BOOST_ASSERT(key); |
| |
| sigInfo.setSignatureType(getSignatureType(key.getKeyType(), params.getDigestAlgorithm())); |
| sigInfo.setKeyLocator(KeyLocator(key.getName())); |
| |
| NDN_LOG_TRACE("Prepared signature info: " << sigInfo); |
| 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, util::Sha256::computeDigest(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 |