24 #include "../../util/config-file.hpp"
25 #include "../../util/logger.hpp"
27 #include "../pib/pib-sqlite3.hpp"
28 #include "../pib/pib-memory.hpp"
30 #ifdef NDN_CXX_HAVE_OSX_SECURITY
31 #include "../tpm/back-end-osx.hpp"
32 #endif // NDN_CXX_HAVE_OSX_SECURITY
34 #include "../tpm/back-end-file.hpp"
35 #include "../tpm/back-end-mem.hpp"
37 #include "../transform/bool-sink.hpp"
38 #include "../transform/buffer-source.hpp"
39 #include "../transform/private-key.hpp"
40 #include "../transform/verifier-filter.hpp"
41 #include "../../encoding/buffer-stream.hpp"
42 #include "../../util/crypto.hpp"
44 #include <boost/lexical_cast.hpp>
65 #if defined(NDN_CXX_HAVE_OSX_SECURITY) && defined(NDN_CXX_WITH_OSX_KEYCHAIN)
67 #endif // defined(NDN_CXX_HAVE_OSX_SECURITY) && defined(NDN_CXX_WITH_OSX_KEYCHAIN)
77 std::string KeyChain::s_defaultPibLocator;
78 std::string KeyChain::s_defaultTpmLocator;
80 KeyChain::PibFactories&
81 KeyChain::getPibFactories()
83 static PibFactories pibFactories;
87 KeyChain::TpmFactories&
88 KeyChain::getTpmFactories()
90 static TpmFactories tpmFactories;
95 KeyChain::getDefaultPibScheme()
101 KeyChain::getDefaultTpmScheme()
103 #if defined(NDN_CXX_HAVE_OSX_SECURITY) && defined(NDN_CXX_WITH_OSX_KEYCHAIN)
107 #endif // defined(NDN_CXX_HAVE_OSX_SECURITY) && defined(NDN_CXX_WITH_OSX_KEYCHAIN)
111 KeyChain::getDefaultPibLocator()
113 if (!s_defaultPibLocator.empty())
114 return s_defaultPibLocator;
116 if (getenv(
"NDN_CLIENT_PIB") !=
nullptr) {
117 s_defaultPibLocator = getenv(
"NDN_CLIENT_PIB");
121 s_defaultPibLocator = config.getParsedConfiguration().get<std::string>(
"pib", getDefaultPibScheme() +
":");
124 return s_defaultPibLocator;
128 KeyChain::getDefaultTpmLocator()
130 if (!s_defaultTpmLocator.empty())
131 return s_defaultTpmLocator;
133 if (getenv(
"NDN_CLIENT_TPM") !=
nullptr) {
134 s_defaultTpmLocator = getenv(
"NDN_CLIENT_TPM");
138 s_defaultTpmLocator = config.getParsedConfiguration().get<std::string>(
"tpm", getDefaultTpmScheme() +
":");
141 return s_defaultTpmLocator;
164 :
KeyChain(getDefaultPibLocator(), getDefaultTpmLocator(), true)
171 std::string pibScheme, pibLocation;
172 std::tie(pibScheme, pibLocation) = parseAndCheckPibLocator(pibLocator);
173 std::string canonicalPibLocator = pibScheme +
":" + pibLocation;
176 m_pib = createPib(canonicalPibLocator);
177 std::string oldTpmLocator;
179 oldTpmLocator = m_pib->getTpmLocator();
181 catch (
const Pib::Error&) {
186 std::string tpmScheme, tpmLocation;
187 std::tie(tpmScheme, tpmLocation) = parseAndCheckTpmLocator(tpmLocator);
188 std::string canonicalTpmLocator = tpmScheme +
":" + tpmLocation;
190 if (canonicalPibLocator == getDefaultPibLocator()) {
192 if (!oldTpmLocator.empty() && oldTpmLocator != getDefaultTpmLocator()) {
194 canonicalTpmLocator = getDefaultTpmLocator();
199 if (!oldTpmLocator.empty() && oldTpmLocator != canonicalTpmLocator) {
203 BOOST_THROW_EXCEPTION(
LocatorMismatchError(
"TPM locator supplied does not match TPM locator in PIB: " +
204 oldTpmLocator +
" != " + canonicalTpmLocator));
211 m_tpm = createTpm(canonicalTpmLocator);
212 m_pib->setTpmLocator(canonicalTpmLocator);
222 Identity
id = m_pib->addIdentity(identityName);
226 key =
id.getDefaultKey();
228 catch (
const Pib::Error&) {
233 key.getDefaultCertificate();
235 catch (
const Pib::Error&) {
236 NDN_LOG_DEBUG(
"No default cert for " << key.getName() <<
", requesting self-signing");
246 BOOST_ASSERT(static_cast<bool>(identity));
248 Name identityName = identity.getName();
250 for (
const auto& key : identity.getKeys()) {
251 m_tpm->deleteKey(key.getName());
254 m_pib->removeIdentity(identityName);
260 BOOST_ASSERT(static_cast<bool>(identity));
262 m_pib->setDefaultIdentity(identity.getName());
268 BOOST_ASSERT(static_cast<bool>(identity));
271 Name keyName = m_tpm->createKey(identity.getName(), params);
275 Key key = identity.addKey(pubKey->buf(), pubKey->size(), keyName);
277 NDN_LOG_DEBUG(
"Requesting self-signing for newly created key " << key.getName());
286 BOOST_ASSERT(static_cast<bool>(identity));
287 BOOST_ASSERT(static_cast<bool>(key));
289 Name keyName = key.getName();
290 if (identity.getName() != key.getIdentity()) {
291 BOOST_THROW_EXCEPTION(std::invalid_argument(
"Identity `" + identity.getName().toUri() +
"` "
292 "does match key `" + keyName.
toUri() +
"`"));
295 identity.removeKey(keyName);
296 m_tpm->deleteKey(keyName);
302 BOOST_ASSERT(static_cast<bool>(identity));
303 BOOST_ASSERT(static_cast<bool>(key));
305 if (identity.getName() != key.getIdentity())
306 BOOST_THROW_EXCEPTION(std::invalid_argument(
"Identity `" + identity.getName().toUri() +
"` "
307 "does match key `" + key.getName().toUri() +
"`"));
309 identity.setDefaultKey(key.getName());
315 BOOST_ASSERT(static_cast<bool>(key));
317 if (key.getName() != certificate.
getKeyName() ||
319 key.getPublicKey().begin()))
320 BOOST_THROW_EXCEPTION(std::invalid_argument(
"Key `" + key.getName().toUri() +
"` "
321 "does match certificate `" + certificate.
getName().
toUri() +
"`"));
323 key.addCertificate(certificate);
329 BOOST_ASSERT(static_cast<bool>(key));
332 BOOST_THROW_EXCEPTION(std::invalid_argument(
"Wrong certificate name `" + certificateName.
toUri() +
"`"));
335 key.removeCertificate(certificateName);
341 BOOST_ASSERT(static_cast<bool>(key));
346 catch (
const Pib::Error&) {
347 key.removeCertificate(cert.
getName());
350 key.setDefaultCertificate(cert.
getName());
361 encryptedKey = m_tpm->exportPrivateKey(keyName, pw, pwLen);
364 BOOST_THROW_EXCEPTION(
Error(
"Private `" + keyName.
toUri() +
"` key does not exist"));
367 return make_shared<SafeBag>(certificate, *encryptedKey);
379 if (m_tpm->hasKey(keyName)) {
380 BOOST_THROW_EXCEPTION(
Error(
"Private key `" + keyName.
toUri() +
"` already exists"));
384 Identity existingId = m_pib->getIdentity(identity);
385 existingId.getKey(keyName);
386 BOOST_THROW_EXCEPTION(
Error(
"Public key `" + keyName.
toUri() +
"` already exists"));
388 catch (
const Pib::Error&) {
393 m_tpm->importPrivateKey(keyName,
397 catch (
const std::runtime_error&) {
398 BOOST_THROW_EXCEPTION(
Error(
"Fail to import private key `" + keyName.
toUri() +
"`"));
402 const uint8_t content[] = {0x01, 0x02, 0x03, 0x04};
407 catch (
const std::runtime_error&) {
408 m_tpm->deleteKey(keyName);
409 BOOST_THROW_EXCEPTION(
Error(
"Invalid private key `" + keyName.
toUri() +
"`"));
411 bool isVerified =
false;
415 publicKey.loadPkcs8(publicKeyBits.
buf(), publicKeyBits.size());
417 sigBits->buf(), sigBits->size())
421 m_tpm->deleteKey(keyName);
423 "and private key `" + keyName.
toUri() +
"` do not match"));
426 Identity
id = m_pib->addIdentity(identity);
428 key.addCertificate(cert);
439 std::tie(keyName, sigInfo) = prepareSignatureInfo(params);
456 std::tie(keyName, sigInfo) = prepareSignatureInfo(params);
465 signedName.
append(sigValue);
474 std::tie(keyName, sigInfo) = prepareSignatureInfo(params);
481 static inline std::tuple<std::string, std::string>
484 size_t pos = uri.find(
':');
485 if (pos != std::string::npos) {
486 return std::make_tuple(uri.substr(0, pos), uri.substr(pos + 1));
489 return std::make_tuple(uri,
"");
493 std::tuple<std::string, std::string>
494 KeyChain::parseAndCheckPibLocator(
const std::string& pibLocator)
496 std::string pibScheme, pibLocation;
499 if (pibScheme.empty()) {
500 pibScheme = getDefaultPibScheme();
503 auto pibFactory = getPibFactories().find(pibScheme);
504 if (pibFactory == getPibFactories().end()) {
505 BOOST_THROW_EXCEPTION(KeyChain::Error(
"PIB scheme `" + pibScheme +
"` is not supported"));
508 return std::make_tuple(pibScheme, pibLocation);
512 KeyChain::createPib(
const std::string& pibLocator)
514 std::string pibScheme, pibLocation;
515 std::tie(pibScheme, pibLocation) = parseAndCheckPibLocator(pibLocator);
516 auto pibFactory = getPibFactories().find(pibScheme);
517 BOOST_ASSERT(pibFactory != getPibFactories().end());
518 return unique_ptr<Pib>(
new Pib(pibScheme, pibLocation, pibFactory->second(pibLocation)));
521 std::tuple<std::string, std::string>
522 KeyChain::parseAndCheckTpmLocator(
const std::string& tpmLocator)
524 std::string tpmScheme, tpmLocation;
527 if (tpmScheme.empty()) {
528 tpmScheme = getDefaultTpmScheme();
530 auto tpmFactory = getTpmFactories().find(tpmScheme);
531 if (tpmFactory == getTpmFactories().end()) {
532 BOOST_THROW_EXCEPTION(KeyChain::Error(
"TPM scheme `" + tpmScheme +
"` is not supported"));
535 return std::make_tuple(tpmScheme, tpmLocation);
539 KeyChain::createTpm(
const std::string& tpmLocator)
541 std::string tpmScheme, tpmLocation;
542 std::tie(tpmScheme, tpmLocation) = parseAndCheckTpmLocator(tpmLocator);
543 auto tpmFactory = getTpmFactories().find(tpmScheme);
544 BOOST_ASSERT(tpmFactory != getTpmFactories().end());
545 return unique_ptr<Tpm>(
new Tpm(tpmScheme, tpmLocation, tpmFactory->second(tpmLocation)));
551 KeyChain::selfSign(Key& key)
553 Certificate certificate;
556 Name certificateName = key.getName();
560 certificate.setName(certificateName);
564 certificate.setFreshnessPeriod(time::hours(1));
567 certificate.setContent(key.getPublicKey().buf(), key.getPublicKey().size());
576 sign(certificate, SigningInfo(key).setSignatureInfo(signatureInfo));
578 key.addCertificate(certificate);
582 std::tuple<Name, SignatureInfo>
583 KeyChain::prepareSignatureInfo(
const SigningInfo& params)
588 name::Component keyId;
589 Name certificateName;
591 pib::Identity identity;
594 switch (params.getSignerType()) {
597 identity = m_pib->getDefaultIdentity();
599 catch (
const Pib::Error&) {
607 identity = m_pib->getIdentity(params.getSignerName());
609 catch (
const Pib::Error&) {
610 BOOST_THROW_EXCEPTION(InvalidSigningInfoError(
"Signing identity `" +
611 params.getSignerName().toUri() +
"` does not exist"));
619 identity = m_pib->getIdentity(identityName);
620 key = identity.getKey(params.getSignerName());
621 identity = Identity();
623 catch (
const Pib::Error&) {
624 BOOST_THROW_EXCEPTION(InvalidSigningInfoError(
"Signing key `" +
625 params.getSignerName().toUri() +
"` does not exist"));
634 identity = m_pib->getIdentity(identityName);
635 key = identity.getKey(keyName);
637 catch (
const Pib::Error&) {
638 BOOST_THROW_EXCEPTION(InvalidSigningInfoError(
"Signing certificate `" +
639 params.getSignerName().toUri() +
"` does not exist"));
649 identity = params.getPibIdentity();
651 BOOST_THROW_EXCEPTION(InvalidSigningInfoError(
"PIB identity is invalid"));
655 key = params.getPibKey();
657 BOOST_THROW_EXCEPTION(InvalidSigningInfoError(
"PIB key is invalid"));
661 BOOST_THROW_EXCEPTION(InvalidSigningInfoError(
"Unrecognized signer type " +
662 boost::lexical_cast<std::string>(params.getSignerType())));
666 if (!identity && !key) {
667 BOOST_THROW_EXCEPTION(InvalidSigningInfoError(
"Cannot determine signing parameters"));
670 if (identity && !key) {
672 key = identity.getDefaultKey();
674 catch (
const Pib::Error&) {
675 BOOST_THROW_EXCEPTION(InvalidSigningInfoError(
"Signing identity `" + identity.getName().toUri() +
676 "` does not have default certificate"));
682 sigInfo.setSignatureType(getSignatureType(key.getKeyType(), params.getDigestAlgorithm()));
683 sigInfo.setKeyLocator(
KeyLocator(key.getName()));
686 return std::make_tuple(key.getName(), sigInfo);
708 BOOST_THROW_EXCEPTION(Error(
"Unsupported key types"));
void deleteKey(const Identity &identity, const Key &key)
Delete a key key of identity.
const Name & getName() const
Copyright (c) 2013-2016 Regents of the University of California.
The certificate following the certificate format naming convention.
Name getKeyName() const
Get key name.
The interface of signing key management.
void addCertificate(const Key &key, const Certificate &certificate)
Add a certificate certificate for key.
#define NDN_CXX_V2_KEYCHAIN_REGISTER_PIB_BACKEND(PibType)
Register Pib backend class in KeyChain.
Key createKey(const Identity &identity, const KeyParams ¶ms=getDefaultKeyParams())
Create a key for identity according to params.
#define NDN_CXX_V2_KEYCHAIN_REGISTER_TPM_BACKEND(TpmType)
Register Tpm backend class in KeyChain.
Data & setSignature(const Signature &signature)
Set the signature to a copy of the given signature.
The back-end implementation of file-based TPM.
given PIB identity handle, use its default key and default certificate
Name extractKeyNameFromCertName(const Name &certName)
Extract key name from the certificate name certName.
static std::tuple< std::string, std::string > parseLocatorUri(const std::string &uri)
KeyChain()
Constructor to create KeyChain with default PIB and TPM.
size_t wireEncode(EncodingImpl< TAG > &encoder) const
Fast encoding or block size estimation.
Class representing a wire element of NDN-TLV packet format.
Error indicating that the supplied TPM locator does not match the locator stored in PIB...
represents an Interest packet
#define NDN_LOG_DEBUG(expression)
log at DEBUG level
use sha256 digest, no signer needs to be specified
#define NDN_LOG_INIT(name)
declare a log module
static time_point now() noexcept
Buffer::const_iterator value_begin() const
Buffer::const_iterator value_end() const
Signing parameters passed to KeyChain.
void deleteCertificate(const Key &key, const Name &certificateName)
delete a certificate with name certificateName of key.
const Name & getName() const
Get name of the Data packet.
Identity createIdentity(const Name &identityName, const KeyParams ¶ms=getDefaultKeyParams())
Create an identity identityName.
void importSafeBag(const SafeBag &safeBag, const char *pw, size_t pwLen)
Import a pair of certificate and its corresponding private key encapsulated in a SafeBag.
static const std::string & getScheme()
std::string toUri() const
Encode this name as a URI.
Pib backend implementation based on SQLite3 database.
size_t wireEncode(EncodingImpl< TAG > &encoder, bool wantUnsignedPortionOnly=false) const
Fast encoding or block size estimation.
shared_ptr< SafeBag > exportSafeBag(const Certificate &certificate, const char *pw, size_t pwLen)
export a certificate of name certificateName and its corresponding private key.
EncodingImpl< EncoderTag > EncodingBuffer
static const std::string & getScheme()
Interest & setName(const Name &name)
no signer is specified, use default setting or follow the trust schema
static const std::string & getScheme()
void setDefaultIdentity(const Identity &identity)
Set identity as the default identity.
static const SigningInfo & getDefaultSigningInfo()
static const Name & getDigestSha256Identity()
A localhost identity to indicate that the signature is generated using SHA-256.
Use the SHA256 hash of the public key as the key id.
Name getIdentity() const
Get identity name.
The back-end implementation of in-memory TPM.
Name abstraction to represent an absolute name.
signer is a certificate, use it directly
Buffer getPublicKey() const
Get public key bits (in PKCS#8 format)
signer is a key, use its default certificate
An in-memory implementation of Pib.
const Buffer & getEncryptedKeyBag() const
Get the private key in PKCS#8 from safe bag.
void sign(Data &data, const SigningInfo ¶ms=getDefaultSigningInfo())
Sign data according to the supplied signing information.
given PIB key handle, use its default certificate
size_t wireEncode(EncodingImpl< TAG > &encoder) const
Encode to a wire format or estimate wire format.
void deleteIdentity(const Identity &identity)
delete identity.
static bool isValidName(const Name &certName)
Check if the specified name follows the naming convention for the certificate.
static const KeyParams & getDefaultKeyParams()
a secured container for sensitive information(certificate, private key)
void setDefaultKey(const Identity &identity, const Key &key)
Set key as the default key of identity.
void encode()
Encode subblocks into wire buffer.
const Block & getContent() const
Get content Block.
void setDefaultCertificate(const Key &key, const Certificate &cert)
Set cert as the default certificate of key.
Name & append(const uint8_t *value, size_t valueLength)
Append a new component, copying from value of length valueLength.
const Data & getCertificate() const
Get the certificate data packet from safe bag.
indicates content is a public key
Base class of key parameters.
signer is an identity, use its default key and default certificate
#define NDN_LOG_TRACE(expression)
log at TRACE level
shared_ptr< const Buffer > ConstBufferPtr
ConstBufferPtr sha256(const uint8_t *data, size_t dataLength)
Compute the sha-256 digest of data.
SimplePublicKeyParams is a template for public keys with only one parameter: size.
DigestAlgorithm getDigestAlgorithm() const
Name extractIdentityFromKeyName(const Name &keyName)
Extract identity namespace from the key name keyName.
Class representing a general-use automatically managed/resized buffer.
duration< boost::int_least32_t, boost::ratio< 86400 > > days
A Signature is storage for the signature-related information (info and value) in a Data packet...
Name extractIdentityFromCertName(const Name &certName)
Extract identity namespace from the certificate name certName.