key-chain.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2013-2024 Regents of the University of California.
4  *
5  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6  *
7  * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8  * terms of the GNU Lesser General Public License as published by the Free Software
9  * Foundation, either version 3 of the License, or (at your option) any later version.
10  *
11  * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13  * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14  *
15  * You should have received copies of the GNU General Public License and GNU Lesser
16  * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17  * <http://www.gnu.org/licenses/>.
18  *
19  * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
20  */
21 
25 
26 #include "ndn-cxx/security/pib/impl/pib-memory.hpp"
27 #include "ndn-cxx/security/pib/impl/pib-sqlite3.hpp"
28 
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"
33 #endif // NDN_CXX_HAVE_OSX_FRAMEWORKS
34 
40 
43 #include "ndn-cxx/util/logger.hpp"
44 #include "ndn-cxx/util/random.hpp"
45 
46 #include <boost/lexical_cast.hpp>
47 #include <cstdlib> // for std::getenv()
48 
49 namespace ndn::security {
50 
52 
53 // When static library is used, not everything is compiled into the resulting binary.
54 // Therefore, the following standard PIB and TPMs need to be registered here.
55 // http://stackoverflow.com/q/9459980/2150331
56 
57 namespace pib {
60 } // namespace pib
61 
62 namespace tpm {
63 #ifdef NDN_CXX_HAVE_OSX_FRAMEWORKS
65 #endif // NDN_CXX_HAVE_OSX_FRAMEWORKS
68 } // namespace tpm
69 
70 const name::Component SELF{"self"};
71 
72 KeyChain::PibFactories&
73 KeyChain::getPibFactories()
74 {
75  static PibFactories pibFactories;
76  return pibFactories;
77 }
78 
79 KeyChain::TpmFactories&
80 KeyChain::getTpmFactories()
81 {
82  static TpmFactories tpmFactories;
83  return tpmFactories;
84 }
85 
86 static const auto&
87 getDefaultPibScheme()
88 {
89  return pib::PibSqlite3::getScheme();
90 }
91 
92 static const auto&
93 getDefaultTpmScheme()
94 {
95 #ifdef NDN_CXX_WITH_OSX_KEYCHAIN
96  return tpm::BackEndOsx::getScheme();
97 #else
98  return tpm::BackEndFile::getScheme();
99 #endif // NDN_CXX_WITH_OSX_KEYCHAIN
100 }
101 
102 const KeyParams&
104 {
105  static EcKeyParams keyParams;
106  return keyParams;
107 }
108 
109 //
110 
111 class KeyChain::Locator
112 {
113 public:
114  [[nodiscard]] bool
115  empty() const noexcept
116  {
117  return scheme.empty();
118  }
119 
120  [[nodiscard]] std::string
121  canonical() const
122  {
123  return scheme + ':' + location;
124  }
125 
126  friend bool
127  operator==(const Locator& lhs, const Locator& rhs) noexcept
128  {
129  return lhs.scheme == rhs.scheme && lhs.location == rhs.location;
130  }
131 
132 public:
133  std::string scheme;
134  std::string location;
135 };
136 
137 KeyChain::Locator KeyChain::s_defaultPibLocator;
138 KeyChain::Locator KeyChain::s_defaultTpmLocator;
139 
140 //
141 
143  : KeyChain(getDefaultPibLocator(), getDefaultTpmLocator(), true)
144 {
145 }
146 
147 KeyChain::KeyChain(const std::string& pibLocator, const std::string& tpmLocator, bool allowReset)
148  : KeyChain(parseAndCheckPibLocator(pibLocator),
149  parseAndCheckTpmLocator(tpmLocator),
150  allowReset)
151 {
152 }
153 
154 KeyChain::KeyChain(Locator pibLocator, Locator tpmLocator, bool allowReset)
155 {
156  // Create PIB
157  auto pibFactory = getPibFactories().find(pibLocator.scheme);
158  BOOST_ASSERT(pibFactory != getPibFactories().end());
159  m_pib.reset(new Pib(pibLocator.canonical(), pibFactory->second(pibLocator.location)));
160 
161  // Figure out the TPM Locator
162  std::string oldTpmLocator = m_pib->getTpmLocator();
163  if (pibLocator == getDefaultPibLocator()) {
164  // Default PIB must use default TPM
165  if (!oldTpmLocator.empty() && oldTpmLocator != getDefaultTpmLocator().canonical()) {
166  m_pib->reset();
167  tpmLocator = getDefaultTpmLocator();
168  }
169  }
170  else {
171  // non-default PIB check consistency
172  if (!oldTpmLocator.empty() && oldTpmLocator != tpmLocator.canonical()) {
173  if (allowReset)
174  m_pib->reset();
175  else
176  NDN_THROW(LocatorMismatchError("Supplied TPM locator (" + tpmLocator.canonical() +
177  ") does not match TPM locator in PIB (" + oldTpmLocator + ")"));
178  }
179  }
180  // Note that key mismatch may still happen if the TPM locator is initially set to a
181  // wrong one or if the PIB was shared by more than one TPMs before. This is due to the
182  // old PIB not having TPM info, the new PIB should not have this problem.
183 
184  // Create TPM
185  auto tpmFactory = getTpmFactories().find(tpmLocator.scheme);
186  BOOST_ASSERT(tpmFactory != getTpmFactories().end());
187  m_tpm.reset(new Tpm(tpmLocator.canonical(), tpmFactory->second(tpmLocator.location)));
188 
189  // Link PIB with TPM
190  m_pib->setTpmLocator(tpmLocator.canonical());
191 }
192 
193 KeyChain::~KeyChain() = default;
194 
195 // public: management
196 
197 Identity
198 KeyChain::createIdentity(const Name& identityName, const KeyParams& params)
199 {
200  NDN_LOG_DEBUG("Requesting creation of identity " << identityName);
201  Identity id = m_pib->addIdentity(identityName);
202 
203  Key key;
204  try {
205  key = id.getDefaultKey();
206  }
207  catch (const Pib::Error&) {
208  key = createKey(id, params);
209  }
210 
211  try {
212  key.getDefaultCertificate();
213  }
214  catch (const Pib::Error&) {
215  NDN_LOG_DEBUG("No default certificate for " << key << ", requesting self-signing");
216  selfSign(key);
217  }
218 
219  return id;
220 }
221 
222 void
224 {
225  if (!identity) {
226  return;
227  }
228 
229  Name identityName = identity.getName();
230  NDN_LOG_DEBUG("Requesting deletion of identity " << identityName);
231 
232  for (const auto& key : identity.getKeys()) {
233  m_tpm->deleteKey(key.getName());
234  }
235 
236  m_pib->removeIdentity(identityName);
237 }
238 
239 void
241 {
242  BOOST_ASSERT(identity);
243 
244  m_pib->setDefaultIdentity(identity.getName());
245 }
246 
247 Key
248 KeyChain::createKey(const Identity& identity, const KeyParams& params)
249 {
250  BOOST_ASSERT(identity);
251 
252  // create key in TPM
253  Name keyName = m_tpm->createKey(identity.getName(), params);
254 
255  // set up key info in PIB
256  Key key = identity.addKey(*m_tpm->getPublicKey(keyName), keyName);
257 
258  NDN_LOG_DEBUG("Requesting self-signing for newly created key " << key);
259  selfSign(key);
260 
261  return key;
262 }
263 
264 Name
265 KeyChain::createHmacKey(const Name& prefix, const HmacKeyParams& params)
266 {
267  return m_tpm->createKey(prefix, params);
268 }
269 
270 void
271 KeyChain::deleteKey(const Identity& identity, const Key& key)
272 {
273  BOOST_ASSERT(identity);
274  if (!key) {
275  return;
276  }
277 
278  Name keyName = key.getName();
279  identity.removeKey(keyName);
280  m_tpm->deleteKey(keyName);
281 }
282 
283 void
284 KeyChain::setDefaultKey(const Identity& identity, const Key& key)
285 {
286  BOOST_ASSERT(identity);
287  BOOST_ASSERT(key);
288 
289  identity.setDefaultKey(key.getName());
290 }
291 
292 void
293 KeyChain::addCertificate(const Key& key, const Certificate& certificate)
294 {
295  BOOST_ASSERT(key);
296 
297  key.addCertificate(certificate);
298 }
299 
300 void
301 KeyChain::deleteCertificate(const Key& key, const Name& certName)
302 {
303  BOOST_ASSERT(key);
304 
305  key.removeCertificate(certName);
306 }
307 
308 void
310 {
311  BOOST_ASSERT(key);
312 
313  key.setDefaultCertificate(cert);
314 }
315 
316 shared_ptr<SafeBag>
317 KeyChain::exportSafeBag(const Certificate& certificate, const char* pw, size_t pwLen)
318 {
319  Name keyName = certificate.getKeyName();
320 
321  ConstBufferPtr encryptedKey;
322  try {
323  encryptedKey = m_tpm->exportPrivateKey(keyName, pw, pwLen);
324  }
325  catch (const Tpm::Error&) {
326  NDN_THROW_NESTED(Error("Failed to export private key `" + keyName.toUri() + "`"));
327  }
328 
329  return make_shared<SafeBag>(certificate, *encryptedKey);
330 }
331 
332 void
333 KeyChain::importSafeBag(const SafeBag& safeBag, const char* pw, size_t pwLen)
334 {
335  Certificate cert(safeBag.getCertificate());
336  Name identity = cert.getIdentity();
337  Name keyName = cert.getKeyName();
338 
339  // check if private key already exists
340  if (m_tpm->hasKey(keyName)) {
341  NDN_THROW(Error("Private key `" + keyName.toUri() + "` already exists"));
342  }
343 
344  // check if public key already exists
345  try {
346  m_pib->getIdentity(identity).getKey(keyName);
347  NDN_THROW(Error("Public key `" + keyName.toUri() + "` already exists"));
348  }
349  catch (const Pib::Error&) {
350  // Either identity or key doesn't exist. OK to import.
351  }
352 
353  try {
354  m_tpm->importPrivateKey(keyName, safeBag.getEncryptedKey(), pw, pwLen);
355  }
356  catch (const Tpm::Error&) {
357  NDN_THROW_NESTED(Error("Failed to import private key `" + keyName.toUri() + "`"));
358  }
359 
360  // check the consistency of private key and certificate (sign/verify a random message)
361  const auto r = random::generateWord64();
362  const auto msg = make_span(reinterpret_cast<const uint8_t*>(&r), sizeof(r));
363  ConstBufferPtr sigBits;
364  try {
365  sigBits = m_tpm->sign({msg}, keyName, DigestAlgorithm::SHA256);
366  }
367  catch (const std::runtime_error&) {
368  m_tpm->deleteKey(keyName);
369  NDN_THROW(Error("Invalid private key `" + keyName.toUri() + "`"));
370  }
371  if (!verifySignature({msg}, *sigBits, cert.getPublicKey())) {
372  m_tpm->deleteKey(keyName);
373  NDN_THROW(Error("Certificate `" + cert.getName().toUri() + "` "
374  "and private key `" + keyName.toUri() + "` do not match"));
375  }
376 
377  Identity id = m_pib->addIdentity(identity);
378  Key key = id.addKey(cert.getPublicKey(), keyName);
379  key.addCertificate(cert);
380 }
381 
382 void
383 KeyChain::importPrivateKey(const Name& keyName, shared_ptr<transform::PrivateKey> key)
384 {
385  if (m_tpm->hasKey(keyName)) {
386  NDN_THROW(Error("Private key `" + keyName.toUri() + "` already exists"));
387  }
388 
389  try {
390  m_tpm->importPrivateKey(keyName, std::move(key));
391  }
392  catch (const Tpm::Error&) {
393  NDN_THROW_NESTED(Error("Failed to import private key `" + keyName.toUri() + "`"));
394  }
395 }
396 
397 // public: signing
398 
399 void
400 KeyChain::sign(Data& data, const SigningInfo& params)
401 {
402  auto [keyName, sigInfo] = prepareSignatureInfo(params);
403 
404  data.setSignatureInfo(sigInfo);
405  EncodingBuffer encoder;
406  data.wireEncode(encoder, true);
407 
408  auto sigValue = sign({encoder}, keyName, params.getDigestAlgorithm());
409  data.wireEncode(encoder, *sigValue);
410 }
411 
412 void
413 KeyChain::sign(Interest& interest, const SigningInfo& params)
414 {
415  auto [keyName, sigInfo] = prepareSignatureInfo(params);
416 
418  interest.setSignatureInfo(sigInfo);
419 
420  // Extract function will throw if not all necessary elements are present in Interest
421  auto sigValue = sign(interest.extractSignedRanges(), keyName, params.getDigestAlgorithm());
422  interest.setSignatureValue(std::move(sigValue));
423  }
424  else {
425  Name signedName = interest.getName();
426 
427  // We encode in Data format because this is the format used prior to Packet Specification v0.3
428  const auto& sigInfoBlock = sigInfo.wireEncode(SignatureInfo::Type::Data);
429  signedName.append(sigInfoBlock); // SignatureInfo
430 
431  Block sigValue(tlv::SignatureValue,
432  sign({signedName.wireEncode().value_bytes()}, keyName, params.getDigestAlgorithm()));
433  sigValue.encode();
434  signedName.append(sigValue); // SignatureValue
435 
436  interest.setName(signedName);
437  }
438 }
439 
441 KeyChain::makeCertificate(const pib::Key& publicKey, const SigningInfo& params,
442  const MakeCertificateOptions& opts)
443 {
444  return makeCertificate(publicKey.getName(), publicKey.getPublicKey(), params, opts);
445 }
446 
448 KeyChain::makeCertificate(const Certificate& certRequest, const SigningInfo& params,
449  const MakeCertificateOptions& opts)
450 {
451  auto pkcs8 = certRequest.getPublicKey();
452  try {
454  pub.loadPkcs8(pkcs8);
455  }
456  catch (const transform::PublicKey::Error&) {
457  NDN_THROW_NESTED(std::invalid_argument("Certificate request contains invalid public key"));
458  }
459 
460  return makeCertificate(extractKeyNameFromCertName(certRequest.getName()), pkcs8, params, opts);
461 }
462 
463 // private: PIB/TPM locator helpers
464 
465 static std::tuple<std::string/*scheme*/, std::string/*location*/>
466 parseLocatorUri(const std::string& uri)
467 {
468  if (auto pos = uri.find(':'); pos != std::string::npos) {
469  return {uri.substr(0, pos), uri.substr(pos + 1)};
470  }
471  else {
472  return {uri, ""};
473  }
474 }
475 
476 KeyChain::Locator
477 KeyChain::parseAndCheckPibLocator(const std::string& pibLocator)
478 {
479  auto [pibScheme, pibLocation] = parseLocatorUri(pibLocator);
480  if (pibScheme.empty()) {
481  pibScheme = getDefaultPibScheme();
482  }
483 
484  auto pibFactory = getPibFactories().find(pibScheme);
485  if (pibFactory == getPibFactories().end()) {
486  NDN_THROW(Error("PIB scheme `" + pibScheme + "` is not supported"));
487  }
488 
489  return {pibScheme, pibLocation};
490 }
491 
492 KeyChain::Locator
493 KeyChain::parseAndCheckTpmLocator(const std::string& tpmLocator)
494 {
495  auto [tpmScheme, tpmLocation] = parseLocatorUri(tpmLocator);
496  if (tpmScheme.empty()) {
497  tpmScheme = getDefaultTpmScheme();
498  }
499 
500  auto tpmFactory = getTpmFactories().find(tpmScheme);
501  if (tpmFactory == getTpmFactories().end()) {
502  NDN_THROW(Error("TPM scheme `" + tpmScheme + "` is not supported"));
503  }
504 
505  return {tpmScheme, tpmLocation};
506 }
507 
508 const KeyChain::Locator&
509 KeyChain::getDefaultPibLocator()
510 {
511  if (!s_defaultPibLocator.empty())
512  return s_defaultPibLocator;
513 
514  std::string input;
515  const char* pibEnv = std::getenv("NDN_CLIENT_PIB");
516  if (pibEnv != nullptr) {
517  input = pibEnv;
518  }
519  else {
520  ConfigFile config;
521  input = config.getParsedConfiguration().get<std::string>("pib", getDefaultPibScheme());
522  }
523 
524  s_defaultPibLocator = parseAndCheckPibLocator(input);
525  BOOST_ASSERT(!s_defaultPibLocator.empty());
526  return s_defaultPibLocator;
527 }
528 
529 const KeyChain::Locator&
530 KeyChain::getDefaultTpmLocator()
531 {
532  if (!s_defaultTpmLocator.empty())
533  return s_defaultTpmLocator;
534 
535  std::string input;
536  const char* tpmEnv = std::getenv("NDN_CLIENT_TPM");
537  if (tpmEnv != nullptr) {
538  input = tpmEnv;
539  }
540  else {
541  ConfigFile config;
542  input = config.getParsedConfiguration().get<std::string>("tpm", getDefaultTpmScheme());
543  }
544 
545  s_defaultTpmLocator = parseAndCheckTpmLocator(input);
546  BOOST_ASSERT(!s_defaultTpmLocator.empty());
547  return s_defaultTpmLocator;
548 }
549 
550 #ifdef NDN_CXX_WITH_TESTS
551 void
552 KeyChain::resetDefaultLocators()
553 {
554  s_defaultPibLocator = {};
555  s_defaultTpmLocator = {};
556 }
557 #endif
558 
559 // private: signing
560 
561 Certificate
562 KeyChain::makeCertificate(const Name& keyName, span<const uint8_t> publicKey,
563  SigningInfo params, const MakeCertificateOptions& opts)
564 {
565  if (opts.freshnessPeriod <= 0_ms) {
566  // We cannot rely on Certificate constructor to check this, because
567  // it throws Certificate::Error, not std::invalid_argument
568  NDN_THROW(std::invalid_argument("FreshnessPeriod is not positive"));
569  }
570 
571  Name name(keyName);
572  name.append(opts.issuerId);
573  name.appendVersion(opts.version);
574 
575  Data data;
576  data.setName(name);
577  data.setContentType(tlv::ContentType_Key);
578  data.setFreshnessPeriod(opts.freshnessPeriod);
579  data.setContent(publicKey);
580 
581  auto sigInfo = params.getSignatureInfo();
582  // Call ValidityPeriod::makeRelative here instead of in MakeCertificateOptions struct
583  // because the caller may prepare MakeCertificateOptions first and call makeCertificate
584  // at a later time.
585  sigInfo.setValidityPeriod(opts.validity.value_or(ValidityPeriod::makeRelative(-1_s, 365_days)));
586  params.setSignatureInfo(sigInfo);
587 
588  sign(data, params);
589  // let Certificate constructor double-check correctness of this function
590  return Certificate(std::move(data));
591 }
592 
593 Certificate
594 KeyChain::selfSign(Key& key)
595 {
596  MakeCertificateOptions opts;
597  opts.issuerId = SELF;
598  // Note time::system_clock::max() or other NotAfter date results in incorrect encoded value
599  // because of overflow during conversion to boost::posix_time::ptime (bug #3915, bug #5176).
600  opts.validity = ValidityPeriod::makeRelative(-1_s, 20 * 365_days);
601  auto cert = makeCertificate(key, signingByKey(key), opts);
602 
603  key.addCertificate(cert);
604  return cert;
605 }
606 
607 std::tuple<Name, SignatureInfo>
608 KeyChain::prepareSignatureInfo(const SigningInfo& params)
609 {
610  switch (params.getSignerType()) {
612  pib::Identity identity;
613  try {
614  identity = m_pib->getDefaultIdentity();
615  }
616  catch (const Pib::Error&) { // no default identity, use sha256 for signing.
617  return prepareSignatureInfoSha256(params);
618  }
619  return prepareSignatureInfoWithIdentity(params, identity);
620  }
622  auto identity = params.getPibIdentity();
623  if (!identity) {
624  auto identityName = params.getSignerName();
625  try {
626  identity = m_pib->getIdentity(identityName);
627  }
628  catch (const Pib::Error&) {
629  NDN_THROW_NESTED(InvalidSigningInfoError("Signing identity `" +
630  identityName.toUri() + "` does not exist"));
631  }
632  }
633  if (!identity) {
634  NDN_THROW(InvalidSigningInfoError("Cannot determine signing parameters"));
635  }
636  return prepareSignatureInfoWithIdentity(params, identity);
637  }
639  auto key = params.getPibKey();
640  if (!key) {
641  auto keyName = params.getSignerName();
642  auto identityName = extractIdentityFromKeyName(keyName);
643  try {
644  key = m_pib->getIdentity(identityName).getKey(keyName);
645  }
646  catch (const Pib::Error&) {
647  NDN_THROW_NESTED(InvalidSigningInfoError("Signing key `" +
648  keyName.toUri() + "` does not exist"));
649  }
650  }
651  if (!key) {
652  NDN_THROW(InvalidSigningInfoError("Cannot determine signing parameters"));
653  }
654  return prepareSignatureInfoWithKey(params, key);
655  }
657  auto certName = params.getSignerName();
658  auto keyName = extractKeyNameFromCertName(certName);
659  auto identityName = extractIdentityFromCertName(certName);
660  pib::Key key;
661  try {
662  key = m_pib->getIdentity(identityName).getKey(keyName);
663  }
664  catch (const Pib::Error&) {
665  NDN_THROW_NESTED(InvalidSigningInfoError("Signing certificate `" +
666  certName.toUri() + "` does not exist"));
667  }
668  return prepareSignatureInfoWithKey(params, key, certName);
669  }
671  return prepareSignatureInfoSha256(params);
672  }
674  return prepareSignatureInfoHmac(params, *m_tpm);
675  }
676  }
677  NDN_THROW(InvalidSigningInfoError("Unrecognized signer type " +
678  to_string(params.getSignerType())));
679 }
680 
681 std::tuple<Name, SignatureInfo>
682 KeyChain::prepareSignatureInfoSha256(const SigningInfo& params)
683 {
684  auto sigInfo = params.getSignatureInfo();
685  sigInfo.setSignatureType(tlv::DigestSha256);
686 
687  NDN_LOG_TRACE("Prepared signature info: " << sigInfo);
688  return {SigningInfo::getDigestSha256Identity(), sigInfo};
689 }
690 
691 std::tuple<Name, SignatureInfo>
692 KeyChain::prepareSignatureInfoHmac(const SigningInfo& params, Tpm& tpm)
693 {
694  const Name& keyName = params.getSignerName();
695  if (!tpm.hasKey(keyName)) {
696  tpm.importPrivateKey(keyName, params.getHmacKey());
697  }
698 
699  auto sigInfo = params.getSignatureInfo();
700  sigInfo.setSignatureType(getSignatureType(KeyType::HMAC, params.getDigestAlgorithm()));
701  sigInfo.setKeyLocator(keyName);
702 
703  NDN_LOG_TRACE("Prepared signature info: " << sigInfo);
704  return {keyName, sigInfo};
705 }
706 
707 std::tuple<Name, SignatureInfo>
708 KeyChain::prepareSignatureInfoWithIdentity(const SigningInfo& params, const pib::Identity& identity)
709 {
710  pib::Key key;
711  try {
712  key = identity.getDefaultKey();
713  }
714  catch (const Pib::Error&) {
715  NDN_THROW_NESTED(InvalidSigningInfoError("Signing identity `" + identity.getName().toUri() +
716  "` does not have a default key"));
717  }
718  return prepareSignatureInfoWithKey(params, key);
719 }
720 
721 std::tuple<Name, SignatureInfo>
722 KeyChain::prepareSignatureInfoWithKey(const SigningInfo& params, const pib::Key& key,
723  const std::optional<Name>& certName)
724 {
725  auto sigInfo = params.getSignatureInfo();
726  sigInfo.setSignatureType(getSignatureType(key.getKeyType(), params.getDigestAlgorithm()));
727  if (!sigInfo.hasKeyLocator()) {
728  if (certName) {
729  sigInfo.setKeyLocator(certName);
730  }
731  else {
732  Name klName = key.getName();
733  try {
734  klName = key.getDefaultCertificate().getName();
735  }
736  catch (const Pib::Error&) {
737  }
738  sigInfo.setKeyLocator(klName);
739  }
740  }
741 
742  NDN_LOG_TRACE("Prepared signature info: " << sigInfo);
743  return {key.getName(), sigInfo};
744 }
745 
747 KeyChain::sign(const InputBuffers& bufs, const Name& keyName, DigestAlgorithm digestAlgorithm) const
748 {
749  using namespace transform;
750 
751  if (keyName == SigningInfo::getDigestSha256Identity()) {
752  OBufferStream os;
754  return os.buf();
755  }
756 
757  auto signature = m_tpm->sign(bufs, keyName, digestAlgorithm);
758  if (!signature) {
759  NDN_THROW(InvalidSigningInfoError("TPM signing failed for key `" + keyName.toUri() + "` "
760  "(e.g., PIB contains info about the key, but TPM is missing "
761  "the corresponding private key)"));
762  }
763 
764  return signature;
765 }
766 
768 KeyChain::getSignatureType(KeyType keyType, DigestAlgorithm)
769 {
770  switch (keyType) {
771  case KeyType::RSA:
773  case KeyType::EC:
775  case KeyType::HMAC:
777  default:
778  NDN_THROW(Error("Unsupported key type " + boost::lexical_cast<std::string>(keyType)));
779  }
780 }
781 
782 } // namespace ndn::security
Represents a TLV element of the NDN packet format.
Definition: block.hpp:45
void encode()
Encode sub-elements into TLV-VALUE.
Definition: block.cpp:353
Represents a Data packet.
Definition: data.hpp:39
size_t wireEncode(EncodingImpl< TAG > &encoder, bool wantUnsignedPortionOnly=false) const
Prepend wire encoding to encoder.
Definition: data.cpp:39
const Name & getName() const noexcept
Get the Data name.
Definition: data.hpp:137
Data & setSignatureInfo(const SignatureInfo &info)
Set the SignatureInfo element.
Definition: data.cpp:295
Represents an Interest packet.
Definition: interest.hpp:50
const Name & getName() const noexcept
Get the Interest name.
Definition: interest.hpp:179
Interest & setSignatureValue(span< const uint8_t > value)
Set InterestSignatureValue by copying from a contiguous sequence of bytes.
Definition: interest.cpp:641
InputBuffers extractSignedRanges() const
Extract ranges of Interest covered by the signature.
Definition: interest.cpp:657
Interest & setName(const Name &name)
Set the Interest name.
Definition: interest.cpp:354
Interest & setSignatureInfo(const SignatureInfo &info)
Set the InterestSignatureInfo element.
Definition: interest.cpp:562
Base class for key parameters.
Definition: key-params.hpp:36
Represents an absolute name.
Definition: name.hpp:45
Name & append(const Component &component)
Append a name component.
Definition: name.hpp:308
size_t wireEncode(EncodingImpl< TAG > &encoder) const
Prepend wire encoding to encoder.
Definition: name.cpp:92
void toUri(std::ostream &os, name::UriFormat format=name::UriFormat::DEFAULT) const
Write URI representation of the name to the output stream.
Definition: name.cpp:324
SimplePublicKeyParams is a template for public keys with only one parameter: size.
Definition: key-params.hpp:150
SimpleSymmetricKeyParams is a template for symmetric keys with only one parameter: size.
Definition: key-params.hpp:257
Represents a name component.
Represents an NDN certificate.
Definition: certificate.hpp:58
span< const uint8_t > getPublicKey() const noexcept
Return the public key as a DER-encoded SubjectPublicKeyInfo structure, i.e., exactly as it appears in...
Name getKeyName() const
Get key name.
Definition: certificate.cpp:72
Name getIdentity() const
Get identity name.
Definition: certificate.cpp:66
The main interface for signing key management.
Definition: key-chain.hpp:87
void sign(Data &data, const SigningInfo &params=SigningInfo())
Sign a Data packet according to the supplied signing information.
Definition: key-chain.cpp:400
void setDefaultCertificate(const Key &key, const Certificate &cert)
Set cert as the default certificate of key.
Definition: key-chain.cpp:309
void addCertificate(const Key &key, const Certificate &cert)
Add a certificate cert for key.
Definition: key-chain.cpp:293
void importPrivateKey(const Name &keyName, shared_ptr< transform::PrivateKey > key)
Import a private key into the TPM.
Definition: key-chain.cpp:383
void importSafeBag(const SafeBag &safeBag, const char *pw, size_t pwLen)
Import a certificate and its corresponding private key from a SafeBag.
Definition: key-chain.cpp:333
static const KeyParams & getDefaultKeyParams()
Definition: key-chain.cpp:103
shared_ptr< SafeBag > exportSafeBag(const Certificate &certificate, const char *pw, size_t pwLen)
Export a certificate and its corresponding private key.
Definition: key-chain.cpp:317
void deleteIdentity(const Identity &identity)
Delete identity from this KeyChain.
Definition: key-chain.cpp:223
Key createKey(const Identity &identity, const KeyParams &params=getDefaultKeyParams())
Create a new key for identity.
Definition: key-chain.cpp:248
void setDefaultIdentity(const Identity &identity)
Set identity as the default identity.
Definition: key-chain.cpp:240
void setDefaultKey(const Identity &identity, const Key &key)
Set key as the default key of identity.
Definition: key-chain.cpp:284
Name createHmacKey(const Name &prefix=SigningInfo::getHmacIdentity(), const HmacKeyParams &params=HmacKeyParams())
Create a new HMAC key.
Definition: key-chain.cpp:265
KeyChain()
Constructor to create KeyChain with default PIB and TPM.
Definition: key-chain.cpp:142
Certificate makeCertificate(const pib::Key &publicKey, const SigningInfo &params=SigningInfo(), const MakeCertificateOptions &opts={})
Create and sign a certificate packet.
Definition: key-chain.cpp:441
Identity createIdentity(const Name &identityName, const KeyParams &params=getDefaultKeyParams())
Create an identity identityName.
Definition: key-chain.cpp:198
void deleteKey(const Identity &identity, const Key &key)
Delete key from identity.
Definition: key-chain.cpp:271
void deleteCertificate(const Key &key, const Name &certName)
Delete a certificate with name certName from key.
Definition: key-chain.cpp:301
A secured container for sensitive information (certificate, private key)
Definition: safe-bag.hpp:38
span< const uint8_t > getEncryptedKey() const
Get the private key in PKCS #8 format from safe bag.
Definition: safe-bag.hpp:92
const Data & getCertificate() const
Get the certificate data packet from safe bag.
Definition: safe-bag.hpp:83
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::time_point &now=time::system_clock::now())
Construct ValidityPeriod relative to a timepoint.
Frontend handle for an identity in the PIB.
Definition: identity.hpp:44
const KeyContainer & getKeys() const
Return all the keys of this identity.
Definition: identity.cpp:59
const Name & getName() const
Return the name of the identity.
Definition: identity.cpp:35
Frontend handle for a key in the PIB.
Definition: key.hpp:45
const Certificate & getDefaultCertificate() const
Return the default certificate for this key.
Definition: key.cpp:96
span< const uint8_t > getPublicKey() const
Return the raw public key bits.
Definition: key.cpp:54
const Name & getName() const
Return the name of the key.
Definition: key.cpp:36
Represents a semantic error.
Definition: pib.hpp:56
Frontend to the Public Information Base.
Definition: pib.hpp:52
Abstraction of a public key in crypto transformations.
Definition: public-key.hpp:35
void loadPkcs8(span< const uint8_t > buf)
Load the public key in PKCS#8 format from a buffer buf.
Definition: public-key.cpp:101
#define NDN_THROW_NESTED(e)
Definition: exception.hpp:65
#define NDN_THROW(e)
Definition: exception.hpp:56
#define NDN_CXX_KEYCHAIN_REGISTER_PIB_BACKEND(PibType)
Register Pib backend class in KeyChain.
Definition: key-chain.hpp:530
#define NDN_CXX_KEYCHAIN_REGISTER_TPM_BACKEND(TpmType)
Register Tpm backend class in KeyChain.
Definition: key-chain.hpp:546
#define NDN_LOG_DEBUG(expression)
Log at DEBUG level.
Definition: logger.hpp:260
#define NDN_LOG_TRACE(expression)
Log at TRACE level.
Definition: logger.hpp:255
#define NDN_LOG_INIT(name)
Define a non-member log module.
Definition: logger.hpp:169
EncodingImpl< EncoderTag > EncodingBuffer
std::string to_string(const errinfo_stacktrace &x)
Definition: exception.cpp:30
uint64_t generateWord64()
Generate a non-cryptographically-secure random integer in the range [0, 2^64).
Definition: random.cpp:75
unique_ptr< Transform > digestFilter(DigestAlgorithm algo)
unique_ptr< Sink > streamSink(std::ostream &os)
Definition: stream-sink.cpp:51
Contains the ndn-cxx security framework.
Name extractIdentityFromKeyName(const Name &keyName)
Extract identity namespace from the key name keyName.
Definition: key.cpp:141
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.
const name::Component SELF
Definition: key-chain.cpp:70
Name extractIdentityFromCertName(const Name &certName)
Extract identity namespace from the certificate name certName.
@ V03
Sign Interest using Packet Specification v0.3 semantics.
Name extractKeyNameFromCertName(const Name &certName)
Extract key name from the certificate name certName.
@ Name
Definition: tlv.hpp:71
@ Data
Definition: tlv.hpp:69
@ SignatureValue
Definition: tlv.hpp:95
@ ContentType_Key
public key, certificate
Definition: tlv.hpp:147
SignatureTypeValue
SignatureType values.
Definition: tlv.hpp:127
@ SignatureSha256WithRsa
Definition: tlv.hpp:129
@ DigestSha256
Definition: tlv.hpp:128
@ SignatureHmacWithSha256
Definition: tlv.hpp:131
@ SignatureSha256WithEcdsa
Definition: tlv.hpp:130
Definition: data.cpp:25
bool operator==(const Data &lhs, const Data &rhs)
Definition: data.cpp:367
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.
std::shared_ptr< const Buffer > ConstBufferPtr
Definition: buffer.hpp:140
Options to KeyChain::makeCertificate().
Definition: key-chain.hpp:42
InputBuffers bufs