28 #include "ndn-cxx/security/pib/impl/pib-memory.hpp"
29 #include "ndn-cxx/security/pib/impl/pib-sqlite3.hpp"
31 #include "ndn-cxx/security/tpm/impl/back-end-file.hpp"
32 #include "ndn-cxx/security/tpm/impl/back-end-mem.hpp"
33 #ifdef NDN_CXX_HAVE_OSX_FRAMEWORKS
34 #include "ndn-cxx/security/tpm/impl/back-end-osx.hpp"
45 #include <boost/lexical_cast.hpp>
60 #if defined(NDN_CXX_HAVE_OSX_FRAMEWORKS) && defined(NDN_CXX_WITH_OSX_KEYCHAIN)
71 std::string KeyChain::s_defaultPibLocator;
72 std::string KeyChain::s_defaultTpmLocator;
74 KeyChain::PibFactories&
75 KeyChain::getPibFactories()
77 static PibFactories pibFactories;
81 KeyChain::TpmFactories&
82 KeyChain::getTpmFactories()
84 static TpmFactories tpmFactories;
89 KeyChain::getDefaultPibScheme()
91 return pib::PibSqlite3::getScheme();
95 KeyChain::getDefaultTpmScheme()
97 #if defined(NDN_CXX_HAVE_OSX_FRAMEWORKS) && defined(NDN_CXX_WITH_OSX_KEYCHAIN)
98 return tpm::BackEndOsx::getScheme();
100 return tpm::BackEndFile::getScheme();
105 KeyChain::getDefaultPibLocator()
107 if (!s_defaultPibLocator.empty())
108 return s_defaultPibLocator;
110 if (getenv(
"NDN_CLIENT_PIB") !=
nullptr) {
111 s_defaultPibLocator = getenv(
"NDN_CLIENT_PIB");
115 s_defaultPibLocator = config.getParsedConfiguration().get<std::string>(
"pib", getDefaultPibScheme() +
":");
118 std::string pibScheme, pibLocation;
119 std::tie(pibScheme, pibLocation) = parseAndCheckPibLocator(s_defaultPibLocator);
120 s_defaultPibLocator = pibScheme +
":" + pibLocation;
122 return s_defaultPibLocator;
126 KeyChain::getDefaultTpmLocator()
128 if (!s_defaultTpmLocator.empty())
129 return s_defaultTpmLocator;
131 if (getenv(
"NDN_CLIENT_TPM") !=
nullptr) {
132 s_defaultTpmLocator = getenv(
"NDN_CLIENT_TPM");
136 s_defaultTpmLocator = config.getParsedConfiguration().get<std::string>(
"tpm", getDefaultTpmScheme() +
":");
139 std::string tpmScheme, tpmLocation;
140 std::tie(tpmScheme, tpmLocation) = parseAndCheckTpmLocator(s_defaultTpmLocator);
141 s_defaultTpmLocator = tpmScheme +
":" + tpmLocation;
143 return s_defaultTpmLocator;
156 :
KeyChain(getDefaultPibLocator(), getDefaultTpmLocator(), true)
163 std::string pibScheme, pibLocation;
164 std::tie(pibScheme, pibLocation) = parseAndCheckPibLocator(pibLocator);
165 std::string canonicalPibLocator = pibScheme +
":" + pibLocation;
168 m_pib = createPib(canonicalPibLocator);
169 std::string oldTpmLocator;
171 oldTpmLocator = m_pib->getTpmLocator();
178 std::string tpmScheme, tpmLocation;
179 std::tie(tpmScheme, tpmLocation) = parseAndCheckTpmLocator(tpmLocator);
180 std::string canonicalTpmLocator = tpmScheme +
":" + tpmLocation;
182 if (canonicalPibLocator == getDefaultPibLocator()) {
184 if (!oldTpmLocator.empty() && oldTpmLocator != getDefaultTpmLocator()) {
186 canonicalTpmLocator = getDefaultTpmLocator();
191 if (!oldTpmLocator.empty() && oldTpmLocator != canonicalTpmLocator) {
196 oldTpmLocator +
" != " + canonicalTpmLocator));
203 m_tpm = createTpm(canonicalTpmLocator);
204 m_pib->setTpmLocator(canonicalTpmLocator);
214 Identity id = m_pib->addIdentity(identityName);
218 key =
id.getDefaultKey();
238 BOOST_ASSERT(
static_cast<bool>(identity));
242 for (
const auto& key : identity.
getKeys()) {
243 m_tpm->deleteKey(key.getName());
246 m_pib->removeIdentity(identityName);
252 BOOST_ASSERT(
static_cast<bool>(identity));
254 m_pib->setDefaultIdentity(identity.
getName());
260 BOOST_ASSERT(
static_cast<bool>(identity));
263 Name keyName = m_tpm->createKey(identity.
getName(), params);
266 Key key = identity.addKey(*m_tpm->getPublicKey(keyName), keyName);
277 return m_tpm->createKey(prefix, params);
283 BOOST_ASSERT(
static_cast<bool>(identity));
284 BOOST_ASSERT(
static_cast<bool>(key));
289 "does not match key `" + keyName.
toUri() +
"`"));
292 identity.removeKey(keyName);
293 m_tpm->deleteKey(keyName);
299 BOOST_ASSERT(
static_cast<bool>(identity));
300 BOOST_ASSERT(
static_cast<bool>(key));
306 identity.setDefaultKey(key.
getName());
312 BOOST_ASSERT(
static_cast<bool>(key));
314 const auto& certContent = certificate.
getContent();
315 if (certContent.value_size() == 0) {
320 !std::equal(certContent.value_begin(), certContent.value_end(), key.
getPublicKey().begin())) {
322 "does not match certificate `" + certificate.
getName().
toUri() +
"`"));
325 key.addCertificate(certificate);
331 BOOST_ASSERT(
static_cast<bool>(key));
334 NDN_THROW(std::invalid_argument(
"Wrong certificate name `" + certificateName.
toUri() +
"`"));
337 key.removeCertificate(certificateName);
343 BOOST_ASSERT(
static_cast<bool>(key));
346 key.setDefaultCertificate(cert.
getName());
357 encryptedKey = m_tpm->exportPrivateKey(keyName, pw, pwLen);
363 return make_shared<SafeBag>(certificate, *encryptedKey);
375 if (m_tpm->hasKey(keyName)) {
380 Identity existingId = m_pib->getIdentity(identity);
381 existingId.
getKey(keyName);
389 m_tpm->importPrivateKey(keyName, safeBag.
getEncryptedKey(), pw, pwLen);
396 const uint8_t content[] = {0x01, 0x02, 0x03, 0x04};
401 catch (
const std::runtime_error&) {
402 m_tpm->deleteKey(keyName);
405 bool isVerified =
false;
407 using namespace transform;
409 publicKey.loadPkcs8(publicKeyBits);
414 m_tpm->deleteKey(keyName);
416 "and private key `" + keyName.
toUri() +
"` do not match"));
419 Identity id = m_pib->addIdentity(identity);
421 key.addCertificate(cert);
427 if (m_tpm->hasKey(keyName)) {
432 m_tpm->importPrivateKey(keyName, std::move(key));
446 std::tie(keyName, sigInfo) = prepareSignatureInfo(params);
462 std::tie(keyName, sigInfo) = prepareSignatureInfo(params);
476 signedName.
append(sigInfoBlock.begin(), sigInfoBlock.end());
490 static inline std::tuple<std::string, std::string>
491 parseLocatorUri(
const std::string& uri)
493 size_t pos = uri.find(
':');
494 if (pos != std::string::npos) {
495 return std::make_tuple(uri.substr(0, pos), uri.substr(pos + 1));
498 return std::make_tuple(uri,
"");
502 std::tuple<std::string, std::string>
503 KeyChain::parseAndCheckPibLocator(
const std::string& pibLocator)
505 std::string pibScheme, pibLocation;
506 std::tie(pibScheme, pibLocation) = parseLocatorUri(pibLocator);
508 if (pibScheme.empty()) {
509 pibScheme = getDefaultPibScheme();
512 auto pibFactory = getPibFactories().find(pibScheme);
513 if (pibFactory == getPibFactories().end()) {
514 NDN_THROW(Error(
"PIB scheme `" + pibScheme +
"` is not supported"));
517 return std::make_tuple(pibScheme, pibLocation);
521 KeyChain::createPib(
const std::string& pibLocator)
523 std::string pibScheme, pibLocation;
524 std::tie(pibScheme, pibLocation) = parseAndCheckPibLocator(pibLocator);
525 auto pibFactory = getPibFactories().find(pibScheme);
526 BOOST_ASSERT(pibFactory != getPibFactories().end());
527 return unique_ptr<Pib>(
new Pib(pibScheme, pibLocation, pibFactory->second(pibLocation)));
530 std::tuple<std::string, std::string>
531 KeyChain::parseAndCheckTpmLocator(
const std::string& tpmLocator)
533 std::string tpmScheme, tpmLocation;
534 std::tie(tpmScheme, tpmLocation) = parseLocatorUri(tpmLocator);
536 if (tpmScheme.empty()) {
537 tpmScheme = getDefaultTpmScheme();
540 auto tpmFactory = getTpmFactories().find(tpmScheme);
541 if (tpmFactory == getTpmFactories().end()) {
542 NDN_THROW(Error(
"TPM scheme `" + tpmScheme +
"` is not supported"));
545 return std::make_tuple(tpmScheme, tpmLocation);
549 KeyChain::createTpm(
const std::string& tpmLocator)
551 std::string tpmScheme, tpmLocation;
552 std::tie(tpmScheme, tpmLocation) = parseAndCheckTpmLocator(tpmLocator);
553 auto tpmFactory = getTpmFactories().find(tpmScheme);
554 BOOST_ASSERT(tpmFactory != getTpmFactories().end());
555 return unique_ptr<Tpm>(
new Tpm(tpmScheme, tpmLocation, tpmFactory->second(tpmLocation)));
561 KeyChain::selfSign(Key& key)
563 Certificate certificate;
566 Name certificateName = key.getName();
570 certificate.setName(certificateName);
574 certificate.setFreshnessPeriod(1_h);
577 certificate.setContent(key.getPublicKey());
586 sign(certificate, SigningInfo(key).setSignatureInfo(signatureInfo));
588 key.addCertificate(certificate);
592 std::tuple<Name, SignatureInfo>
593 KeyChain::prepareSignatureInfo(
const SigningInfo& params)
596 pib::Identity identity;
599 switch (params.getSignerType()) {
602 identity = m_pib->getDefaultIdentity();
604 catch (
const Pib::Error&) {
612 identity = params.getPibIdentity();
615 identity = m_pib->getIdentity(params.getSignerName());
617 catch (
const Pib::Error&) {
619 params.getSignerName().toUri() +
"` does not exist"));
625 key = params.getPibKey();
629 key = m_pib->getIdentity(identityName).getKey(params.getSignerName());
631 catch (
const Pib::Error&) {
633 params.getSignerName().toUri() +
"` does not exist"));
642 identity = m_pib->getIdentity(identityName);
643 key = identity.getKey(keyName);
645 catch (
const Pib::Error&) {
647 params.getSignerName().toUri() +
"` does not exist"));
657 const Name& keyName = params.getSignerName();
658 if (!m_tpm->hasKey(keyName)) {
659 m_tpm->importPrivateKey(keyName, params.getHmacKey());
661 sigInfo.setSignatureType(getSignatureType(
KeyType::HMAC, params.getDigestAlgorithm()));
662 sigInfo.setKeyLocator(keyName);
664 return std::make_tuple(keyName, sigInfo);
667 NDN_THROW(InvalidSigningInfoError(
"Unrecognized signer type " +
668 boost::lexical_cast<std::string>(params.getSignerType())));
674 NDN_THROW(InvalidSigningInfoError(
"Cannot determine signing parameters"));
677 key = identity.getDefaultKey();
679 catch (
const Pib::Error&) {
680 NDN_THROW_NESTED(InvalidSigningInfoError(
"Signing identity `" + identity.getName().toUri() +
681 "` does not have a default certificate"));
687 sigInfo.setSignatureType(getSignatureType(key.getKeyType(), params.getDigestAlgorithm()));
688 sigInfo.setKeyLocator(key.getName());
691 return std::make_tuple(key.getName(), sigInfo);
697 using namespace transform;
705 auto signature = m_tpm->sign(
bufs, keyName, digestAlgorithm);
707 NDN_THROW(InvalidSigningInfoError(
"TPM signing failed for key `" + keyName.toUri() +
"` "
708 "(e.g., PIB contains info about the key, but TPM is missing "
709 "the corresponding private key)"));
726 NDN_THROW(Error(
"Unsupported key type " + boost::lexical_cast<std::string>(keyType)));
Represents a TLV element of the NDN packet format.
Buffer::const_iterator begin() const
Get begin iterator of encoded wire.
Buffer::const_iterator end() const
Get end iterator of encoded wire.
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 name.
Data & setSignatureInfo(const SignatureInfo &info)
Set SignatureInfo.
const Block & getContent() const noexcept
Get the Content element.
Represents an Interest packet.
const Name & getName() const noexcept
Interest & setSignatureValue(ConstBufferPtr value)
Set the InterestSignatureValue.
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.
Base class for key parameters.
Represents an absolute name.
Name & append(const Component &component)
Append a 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.
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
DigestAlgorithm getDigestAlgorithm() const
A frontend handle of an Identity.
const KeyContainer & getKeys() const
Get all keys for this identity.
const Name & getName() const
Get the name of the identity.
Key getKey(const Name &keyName) const
Get a key with id keyName.
A frontend handle of a key instance.
const Certificate & getDefaultCertificate() const
Get the default certificate for this Key.
const Name & getIdentity() const
Get the name of the belonging identity.
span< const uint8_t > getPublicKey() const
Get public key bits.
const Name & getName() const
Get key name.
represents a semantic error
Represents an NDN certificate following the version 2.0 format.
Buffer getPublicKey() const
Get public key bits (in PKCS#8 format)
Name getKeyName() const
Get key name.
Name getIdentity() const
Get identity name.
static bool isValidName(const Name &certName)
Check if the specified name follows the naming convention for the certificate.
Error indicating that the supplied TPM locator does not match the locator stored in PIB.
The interface of signing key management.
void setDefaultIdentity(const Identity &identity)
Set identity as the default identity.
void deleteKey(const Identity &identity, const Key &key)
Delete a key key of identity.
void setDefaultCertificate(const Key &key, const Certificate &certificate)
Set cert as the default certificate of 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 deleteIdentity(const Identity &identity)
delete identity.
static const KeyParams & getDefaultKeyParams()
void sign(Data &data, const SigningInfo ¶ms=SigningInfo())
Sign a Data packet according to the supplied signing information.
void deleteCertificate(const Key &key, const Name &certificateName)
delete a certificate with name certificateName of key.
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.
void importPrivateKey(const Name &keyName, shared_ptr< transform::PrivateKey > key)
Import a private key into the TPM.
void addCertificate(const Key &key, const Certificate &certificate)
Add a certificate certificate 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.
static time_point now() noexcept
#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
Name extractIdentityFromKeyName(const Name &keyName)
Extract identity namespace from the key name keyName.
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.
@ V03
Sign Interest using Packet Specification v0.3 semantics.
@ ContentType_Key
public key, certificate
SignatureTypeValue
SignatureType values.
@ SignatureHmacWithSha256
@ SignatureSha256WithEcdsa
shared_ptr< const Buffer > ConstBufferPtr
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.