26 #include "ndn-cxx/security/pib/impl/pib-memory.hpp"
27 #include "ndn-cxx/security/pib/impl/pib-sqlite3.hpp"
29 #include "ndn-cxx/security/tpm/impl/back-end-file.hpp"
30 #include "ndn-cxx/security/tpm/impl/back-end-mem.hpp"
31 #ifdef NDN_CXX_HAVE_OSX_FRAMEWORKS
32 #include "ndn-cxx/security/tpm/impl/back-end-osx.hpp"
46 #include <boost/lexical_cast.hpp>
62 #ifdef NDN_CXX_HAVE_OSX_FRAMEWORKS
75 KeyChain::PibFactories&
76 KeyChain::getPibFactories()
78 static PibFactories pibFactories;
82 KeyChain::TpmFactories&
83 KeyChain::getTpmFactories()
85 static TpmFactories tpmFactories;
92 return pib::PibSqlite3::getScheme();
98 #if defined(NDN_CXX_HAVE_OSX_FRAMEWORKS) && defined(NDN_CXX_WITH_OSX_KEYCHAIN)
99 return tpm::BackEndOsx::getScheme();
101 return tpm::BackEndFile::getScheme();
114 class KeyChain::Locator
120 return scheme.empty();
126 return scheme +
':' + location;
130 operator==(
const Locator& lhs,
const Locator& rhs)
132 return lhs.scheme == rhs.scheme && lhs.location == rhs.location;
137 std::string location;
140 KeyChain::Locator KeyChain::s_defaultPibLocator;
141 KeyChain::Locator KeyChain::s_defaultTpmLocator;
146 :
KeyChain(getDefaultPibLocator(), getDefaultTpmLocator(), true)
151 :
KeyChain(parseAndCheckPibLocator(pibLocator),
152 parseAndCheckTpmLocator(tpmLocator),
160 auto pibFactory = getPibFactories().find(pibLocator.scheme);
161 BOOST_ASSERT(pibFactory != getPibFactories().end());
162 m_pib.reset(
new Pib(pibLocator.canonical(), pibFactory->second(pibLocator.location)));
165 std::string oldTpmLocator = m_pib->getTpmLocator();
166 if (pibLocator == getDefaultPibLocator()) {
168 if (!oldTpmLocator.empty() && oldTpmLocator != getDefaultTpmLocator().canonical()) {
170 tpmLocator = getDefaultTpmLocator();
175 if (!oldTpmLocator.empty() && oldTpmLocator != tpmLocator.canonical()) {
179 NDN_THROW(LocatorMismatchError(
"Supplied TPM locator (" + tpmLocator.canonical() +
180 ") does not match TPM locator in PIB (" + oldTpmLocator +
")"));
188 auto tpmFactory = getTpmFactories().find(tpmLocator.scheme);
189 BOOST_ASSERT(tpmFactory != getTpmFactories().end());
190 m_tpm.reset(
new Tpm(tpmLocator.canonical(), tpmFactory->second(tpmLocator.location)));
193 m_pib->setTpmLocator(tpmLocator.canonical());
203 NDN_LOG_DEBUG(
"Requesting creation of identity " << identityName);
204 Identity id = m_pib->addIdentity(identityName);
208 key =
id.getDefaultKey();
218 NDN_LOG_DEBUG(
"No default certificate for " << key <<
", requesting self-signing");
233 NDN_LOG_DEBUG(
"Requesting deletion of identity " << identityName);
235 for (
const auto& key : identity.
getKeys()) {
236 m_tpm->deleteKey(key.getName());
239 m_pib->removeIdentity(identityName);
245 BOOST_ASSERT(identity);
247 m_pib->setDefaultIdentity(identity.
getName());
253 BOOST_ASSERT(identity);
256 Name keyName = m_tpm->createKey(identity.
getName(), params);
259 Key key = identity.addKey(*m_tpm->getPublicKey(keyName), keyName);
261 NDN_LOG_DEBUG(
"Requesting self-signing for newly created key " << key);
270 return m_tpm->createKey(prefix, params);
276 BOOST_ASSERT(identity);
282 identity.removeKey(keyName);
283 m_tpm->deleteKey(keyName);
289 BOOST_ASSERT(identity);
292 identity.setDefaultKey(key.
getName());
300 key.addCertificate(certificate);
308 key.removeCertificate(certName);
316 key.setDefaultCertificate(cert);
326 encryptedKey = m_tpm->exportPrivateKey(keyName, pw, pwLen);
332 return make_shared<SafeBag>(certificate, *encryptedKey);
343 if (m_tpm->hasKey(keyName)) {
349 m_pib->getIdentity(identity).getKey(keyName);
357 m_tpm->importPrivateKey(keyName, safeBag.
getEncryptedKey(), pw, pwLen);
365 const auto msg = make_span(
reinterpret_cast<const uint8_t*
>(&r),
sizeof(r));
370 catch (
const std::runtime_error&) {
371 m_tpm->deleteKey(keyName);
375 m_tpm->deleteKey(keyName);
377 "and private key `" + keyName.
toUri() +
"` do not match"));
380 Identity id = m_pib->addIdentity(identity);
382 key.addCertificate(cert);
388 if (m_tpm->hasKey(keyName)) {
393 m_tpm->importPrivateKey(keyName, std::move(key));
407 std::tie(keyName, sigInfo) = prepareSignatureInfo(params);
423 std::tie(keyName, sigInfo) = prepareSignatureInfo(params);
437 signedName.
append(sigInfoBlock);
442 signedName.
append(sigValue);
465 NDN_THROW_NESTED(std::invalid_argument(
"Certificate request contains invalid public key"));
473 static std::tuple<std::string, std::string>
474 parseLocatorUri(
const std::string& uri)
476 auto pos = uri.find(
':');
477 if (pos != std::string::npos) {
478 return {uri.substr(0, pos), uri.substr(pos + 1)};
486 KeyChain::parseAndCheckPibLocator(
const std::string& pibLocator)
488 std::string pibScheme, pibLocation;
489 std::tie(pibScheme, pibLocation) = parseLocatorUri(pibLocator);
491 if (pibScheme.empty()) {
492 pibScheme = getDefaultPibScheme();
495 auto pibFactory = getPibFactories().find(pibScheme);
496 if (pibFactory == getPibFactories().end()) {
497 NDN_THROW(Error(
"PIB scheme `" + pibScheme +
"` is not supported"));
500 return {pibScheme, pibLocation};
504 KeyChain::parseAndCheckTpmLocator(
const std::string& tpmLocator)
506 std::string tpmScheme, tpmLocation;
507 std::tie(tpmScheme, tpmLocation) = parseLocatorUri(tpmLocator);
509 if (tpmScheme.empty()) {
510 tpmScheme = getDefaultTpmScheme();
513 auto tpmFactory = getTpmFactories().find(tpmScheme);
514 if (tpmFactory == getTpmFactories().end()) {
515 NDN_THROW(Error(
"TPM scheme `" + tpmScheme +
"` is not supported"));
518 return {tpmScheme, tpmLocation};
521 const KeyChain::Locator&
522 KeyChain::getDefaultPibLocator()
524 if (!s_defaultPibLocator.empty())
525 return s_defaultPibLocator;
528 const char* pibEnv = std::getenv(
"NDN_CLIENT_PIB");
529 if (pibEnv !=
nullptr) {
534 input = config.getParsedConfiguration().get<std::string>(
"pib", getDefaultPibScheme());
537 s_defaultPibLocator = parseAndCheckPibLocator(input);
538 BOOST_ASSERT(!s_defaultPibLocator.empty());
539 return s_defaultPibLocator;
542 const KeyChain::Locator&
543 KeyChain::getDefaultTpmLocator()
545 if (!s_defaultTpmLocator.empty())
546 return s_defaultTpmLocator;
549 const char* tpmEnv = std::getenv(
"NDN_CLIENT_TPM");
550 if (tpmEnv !=
nullptr) {
555 input = config.getParsedConfiguration().get<std::string>(
"tpm", getDefaultTpmScheme());
558 s_defaultTpmLocator = parseAndCheckTpmLocator(input);
559 BOOST_ASSERT(!s_defaultTpmLocator.empty());
560 return s_defaultTpmLocator;
563 #ifdef NDN_CXX_HAVE_TESTS
565 KeyChain::resetDefaultLocators()
567 s_defaultPibLocator = {};
568 s_defaultTpmLocator = {};
576 SigningInfo params,
const MakeCertificateOptions& opts)
578 if (opts.freshnessPeriod <= 0_ms) {
581 NDN_THROW(std::invalid_argument(
"FreshnessPeriod is not positive"));
585 name.append(opts.issuerId);
586 name.appendVersion(opts.version);
591 data.setFreshnessPeriod(opts.freshnessPeriod);
592 data.setContent(publicKey);
594 auto sigInfo = params.getSignatureInfo();
599 params.setSignatureInfo(sigInfo);
603 return Certificate(std::move(data));
607 KeyChain::selfSign(Key& key)
609 MakeCertificateOptions opts;
610 opts.issuerId =
SELF;
616 key.addCertificate(cert);
620 std::tuple<Name, SignatureInfo>
621 KeyChain::prepareSignatureInfo(
const SigningInfo& params)
623 switch (params.getSignerType()) {
625 pib::Identity identity;
627 identity = m_pib->getDefaultIdentity();
629 catch (
const Pib::Error&) {
630 return prepareSignatureInfoSha256(params);
632 return prepareSignatureInfoWithIdentity(params, identity);
635 auto identity = params.getPibIdentity();
637 auto identityName = params.getSignerName();
639 identity = m_pib->getIdentity(identityName);
641 catch (
const Pib::Error&) {
643 identityName.toUri() +
"` does not exist"));
647 NDN_THROW(InvalidSigningInfoError(
"Cannot determine signing parameters"));
649 return prepareSignatureInfoWithIdentity(params, identity);
652 auto key = params.getPibKey();
654 auto keyName = params.getSignerName();
657 key = m_pib->getIdentity(identityName).getKey(keyName);
659 catch (
const Pib::Error&) {
661 keyName.toUri() +
"` does not exist"));
665 NDN_THROW(InvalidSigningInfoError(
"Cannot determine signing parameters"));
667 return prepareSignatureInfoWithKey(params, key);
670 auto certName = params.getSignerName();
675 key = m_pib->getIdentity(identityName).getKey(keyName);
677 catch (
const Pib::Error&) {
679 certName.toUri() +
"` does not exist"));
681 return prepareSignatureInfoWithKey(params, key, certName);
684 return prepareSignatureInfoSha256(params);
687 return prepareSignatureInfoHmac(params, *m_tpm);
690 NDN_THROW(InvalidSigningInfoError(
"Unrecognized signer type " +
694 std::tuple<Name, SignatureInfo>
695 KeyChain::prepareSignatureInfoSha256(
const SigningInfo& params)
697 auto sigInfo = params.getSignatureInfo();
704 std::tuple<Name, SignatureInfo>
705 KeyChain::prepareSignatureInfoHmac(
const SigningInfo& params, Tpm& tpm)
707 const Name& keyName = params.getSignerName();
708 if (!tpm.hasKey(keyName)) {
709 tpm.importPrivateKey(keyName, params.getHmacKey());
712 auto sigInfo = params.getSignatureInfo();
713 sigInfo.setSignatureType(getSignatureType(
KeyType::HMAC, params.getDigestAlgorithm()));
714 sigInfo.setKeyLocator(keyName);
717 return {keyName, sigInfo};
720 std::tuple<Name, SignatureInfo>
721 KeyChain::prepareSignatureInfoWithIdentity(
const SigningInfo& params,
const pib::Identity& identity)
725 key = identity.getDefaultKey();
727 catch (
const Pib::Error&) {
728 NDN_THROW_NESTED(InvalidSigningInfoError(
"Signing identity `" + identity.getName().toUri() +
729 "` does not have a default key"));
731 return prepareSignatureInfoWithKey(params, key);
734 std::tuple<Name, SignatureInfo>
735 KeyChain::prepareSignatureInfoWithKey(
const SigningInfo& params,
const pib::Key& key,
736 const optional<Name>& certName)
738 auto sigInfo = params.getSignatureInfo();
739 sigInfo.setSignatureType(getSignatureType(key.getKeyType(), params.getDigestAlgorithm()));
740 if (!sigInfo.hasKeyLocator()) {
742 sigInfo.setKeyLocator(certName);
745 Name klName = key.getName();
747 klName = key.getDefaultCertificate().getName();
749 catch (
const Pib::Error&) {
751 sigInfo.setKeyLocator(klName);
756 return {key.getName(), sigInfo};
762 using namespace transform;
770 auto signature = m_tpm->sign(
bufs, keyName, digestAlgorithm);
772 NDN_THROW(InvalidSigningInfoError(
"TPM signing failed for key `" + keyName.toUri() +
"` "
773 "(e.g., PIB contains info about the key, but TPM is missing "
774 "the corresponding private key)"));
791 NDN_THROW(Error(
"Unsupported key type " + boost::lexical_cast<std::string>(keyType)));
#define NDN_CXX_NODISCARD
Represents a TLV element of the NDN packet format.
void encode()
Encode sub-elements into TLV-VALUE.
Represents a Data packet.
size_t wireEncode(EncodingImpl< TAG > &encoder, bool wantUnsignedPortionOnly=false) const
Prepend wire encoding to encoder.
const Name & getName() const noexcept
Get the data name.
Data & setSignatureInfo(const SignatureInfo &info)
Set the SignatureInfo element.
Represents an Interest packet.
const Name & getName() const noexcept
Interest & setSignatureValue(span< const uint8_t > value)
Set InterestSignatureValue by copying from a contiguous sequence of bytes.
InputBuffers extractSignedRanges() const
Extract ranges of Interest covered by the signature in Packet Specification v0.3.
Interest & setName(const Name &name)
Set the Interest's name.
Interest & setSignatureInfo(const SignatureInfo &info)
Set the InterestSignatureInfo element.
Base class for key parameters.
Represents an absolute name.
Name & append(const Component &component)
Append a name component.
size_t wireEncode(EncodingImpl< TAG > &encoder) const
Fast encoding or block size estimation.
void toUri(std::ostream &os, name::UriFormat format=name::UriFormat::DEFAULT) const
Write URI representation of the name to the output stream.
Represents a SignatureInfo or InterestSignatureInfo TLV element.
size_t wireEncode(EncodingImpl< TAG > &encoder, Type type=Type::Data) const
Fast encoding or block size estimation.
SimplePublicKeyParams is a template for public keys with only one parameter: size.
SimpleSymmetricKeyParams is a template for symmetric keys with only one parameter: size.
Represents a name component.
A secured container for sensitive information (certificate, private key)
span< const uint8_t > getEncryptedKey() const
Get the private key in PKCS #8 format from safe bag.
const Data & getCertificate() const
Get the certificate data packet from safe bag.
Signing parameters passed to KeyChain.
static const Name & getDigestSha256Identity()
A localhost identity to indicate that the signature is generated using SHA-256.
@ SIGNER_TYPE_CERT
Signer is a certificate, use it directly.
@ SIGNER_TYPE_SHA256
Use a SHA-256 digest only, no signer needs to be specified.
@ SIGNER_TYPE_HMAC
Signer is a HMAC key.
@ SIGNER_TYPE_NULL
No signer is specified, use default setting or follow the trust schema.
@ SIGNER_TYPE_ID
Signer is an identity, use its default key and default certificate.
@ SIGNER_TYPE_KEY
Signer is a key, use its default certificate.
SignedInterestFormat getSignedInterestFormat() const
Get the signed Interest format.
DigestAlgorithm getDigestAlgorithm() const
Get the digest algorithm for signing operations.
static ValidityPeriod makeRelative(time::seconds validFrom, time::seconds validUntil, const time::system_clock::TimePoint &now=time::system_clock::now())
Construct ValidityPeriod relative to a timepoint.
Frontend handle for an identity in the PIB.
const KeyContainer & getKeys() const
Return all the keys of this identity.
const Name & getName() const
Return the name of the identity.
Frontend handle for a key in the PIB.
const Certificate & getDefaultCertificate() const
Return the default certificate for this key.
span< const uint8_t > getPublicKey() const
Return the raw public key bits.
const Name & getName() const
Return the name of the key.
Represents a semantic error.
Frontend to the Public Information Base.
Represents an NDN certificate.
Name getKeyName() const
Get key name.
Name getIdentity() const
Get identity name.
span< const uint8_t > getPublicKey() const noexcept
Return the public key as a DER-encoded SubjectPublicKeyInfo structure, i.e., exactly as it appears in...
The main interface for signing key management.
void setDefaultIdentity(const Identity &identity)
Set identity as the default identity.
void deleteKey(const Identity &identity, const Key &key)
Delete key from identity.
void deleteCertificate(const Key &key, const Name &certName)
Delete a certificate with name certName from key.
Identity createIdentity(const Name &identityName, const KeyParams ¶ms=getDefaultKeyParams())
Create an identity identityName.
Key createKey(const Identity &identity, const KeyParams ¶ms=getDefaultKeyParams())
Create a new key for identity.
void setDefaultCertificate(const Key &key, const Certificate &cert)
Set cert as the default certificate of key.
void deleteIdentity(const Identity &identity)
Delete identity from this KeyChain.
static const KeyParams & getDefaultKeyParams()
void sign(Data &data, const SigningInfo ¶ms=SigningInfo())
Sign a Data packet according to the supplied signing information.
void setDefaultKey(const Identity &identity, const Key &key)
Set key as the default key of identity.
void importSafeBag(const SafeBag &safeBag, const char *pw, size_t pwLen)
Import a certificate and its corresponding private key from a SafeBag.
Name createHmacKey(const Name &prefix=SigningInfo::getHmacIdentity(), const HmacKeyParams ¶ms=HmacKeyParams())
Create a new HMAC key.
Certificate makeCertificate(const pib::Key &publicKey, const SigningInfo ¶ms=SigningInfo(), const MakeCertificateOptions &opts={})
Create and sign a certificate packet.
void importPrivateKey(const Name &keyName, shared_ptr< transform::PrivateKey > key)
Import a private key into the TPM.
void addCertificate(const Key &key, const Certificate &cert)
Add a certificate cert for key.
KeyChain()
Constructor to create KeyChain with default PIB and TPM.
shared_ptr< SafeBag > exportSafeBag(const Certificate &certificate, const char *pw, size_t pwLen)
Export a certificate and its corresponding private key.
#define NDN_THROW_NESTED(e)
#define NDN_CXX_KEYCHAIN_REGISTER_PIB_BACKEND(PibType)
Register Pib backend class in KeyChain.
#define NDN_CXX_KEYCHAIN_REGISTER_TPM_BACKEND(TpmType)
Register Tpm backend class in KeyChain.
#define NDN_LOG_DEBUG(expression)
Log at DEBUG level.
#define NDN_LOG_TRACE(expression)
Log at TRACE level.
#define NDN_LOG_INIT(name)
Define a non-member log module.
EncodingImpl< EncoderTag > EncodingBuffer
std::string to_string(const errinfo_stacktrace &x)
uint64_t generateWord64()
Generate a non-cryptographically-secure random integer in the range [0, 2^64)
Name extractIdentityFromKeyName(const Name &keyName)
Extract identity namespace from the key name keyName.
const name::Component SELF("self")
Name extractKeyNameFromCertName(const Name &certName)
Extract key name from the certificate name certName.
Name extractIdentityFromCertName(const Name &certName)
Extract identity namespace from the certificate name certName.
SigningInfo signingByKey(const Name &keyName)
Return a SigningInfo for signing with a key.
bool verifySignature(const InputBuffers &blobs, span< const uint8_t > sig, const transform::PublicKey &key)
Verify blobs using key against sig.
@ V03
Sign Interest using Packet Specification v0.3 semantics.
@ ContentType_Key
public key, certificate
SignatureTypeValue
SignatureType values.
@ SignatureHmacWithSha256
@ SignatureSha256WithEcdsa
shared_ptr< const Buffer > ConstBufferPtr
bool operator==(const Data &lhs, const Data &rhs)
KeyType
The type of a cryptographic key.
@ EC
Elliptic Curve key (e.g. for ECDSA), supports sign/verify operations.
@ RSA
RSA key, supports sign/verify and encrypt/decrypt operations.
@ HMAC
HMAC key, supports sign/verify operations.
Options to KeyChain::makeCertificate() .