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