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-2020 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 
23 
26 #include "ndn-cxx/util/logger.hpp"
27 
28 #include "ndn-cxx/security/pib/impl/pib-memory.hpp"
29 #include "ndn-cxx/security/pib/impl/pib-sqlite3.hpp"
30 
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"
35 #endif // NDN_CXX_HAVE_OSX_FRAMEWORKS
36 
44 
45 #include <boost/lexical_cast.hpp>
46 
47 namespace ndn {
48 namespace security {
49 
50 // When static library is used, not everything is compiled into the resulting binary.
51 // Therefore, the following standard PIB and TPMs need to be registered here.
52 // http://stackoverflow.com/q/9459980/2150331
53 
54 namespace pib {
57 } // namespace pib
58 
59 namespace tpm {
60 #if defined(NDN_CXX_HAVE_OSX_FRAMEWORKS) && defined(NDN_CXX_WITH_OSX_KEYCHAIN)
62 #endif // defined(NDN_CXX_HAVE_OSX_FRAMEWORKS) && defined(NDN_CXX_WITH_OSX_KEYCHAIN)
65 } // namespace tpm
66 
67 inline namespace v2 {
68 
69 NDN_LOG_INIT(ndn.security.KeyChain);
70 
71 std::string KeyChain::s_defaultPibLocator;
72 std::string KeyChain::s_defaultTpmLocator;
73 
74 KeyChain::PibFactories&
75 KeyChain::getPibFactories()
76 {
77  static PibFactories pibFactories;
78  return pibFactories;
79 }
80 
81 KeyChain::TpmFactories&
82 KeyChain::getTpmFactories()
83 {
84  static TpmFactories tpmFactories;
85  return tpmFactories;
86 }
87 
88 const std::string&
89 KeyChain::getDefaultPibScheme()
90 {
91  return pib::PibSqlite3::getScheme();
92 }
93 
94 const std::string&
95 KeyChain::getDefaultTpmScheme()
96 {
97 #if defined(NDN_CXX_HAVE_OSX_FRAMEWORKS) && defined(NDN_CXX_WITH_OSX_KEYCHAIN)
98  return tpm::BackEndOsx::getScheme();
99 #else
100  return tpm::BackEndFile::getScheme();
101 #endif // defined(NDN_CXX_HAVE_OSX_FRAMEWORKS) && defined(NDN_CXX_WITH_OSX_KEYCHAIN)
102 }
103 
104 const std::string&
105 KeyChain::getDefaultPibLocator()
106 {
107  if (!s_defaultPibLocator.empty())
108  return s_defaultPibLocator;
109 
110  if (getenv("NDN_CLIENT_PIB") != nullptr) {
111  s_defaultPibLocator = getenv("NDN_CLIENT_PIB");
112  }
113  else {
114  ConfigFile config;
115  s_defaultPibLocator = config.getParsedConfiguration().get<std::string>("pib", getDefaultPibScheme() + ":");
116  }
117 
118  std::string pibScheme, pibLocation;
119  std::tie(pibScheme, pibLocation) = parseAndCheckPibLocator(s_defaultPibLocator);
120  s_defaultPibLocator = pibScheme + ":" + pibLocation;
121 
122  return s_defaultPibLocator;
123 }
124 
125 const std::string&
126 KeyChain::getDefaultTpmLocator()
127 {
128  if (!s_defaultTpmLocator.empty())
129  return s_defaultTpmLocator;
130 
131  if (getenv("NDN_CLIENT_TPM") != nullptr) {
132  s_defaultTpmLocator = getenv("NDN_CLIENT_TPM");
133  }
134  else {
135  ConfigFile config;
136  s_defaultTpmLocator = config.getParsedConfiguration().get<std::string>("tpm", getDefaultTpmScheme() + ":");
137  }
138 
139  std::string tpmScheme, tpmLocation;
140  std::tie(tpmScheme, tpmLocation) = parseAndCheckTpmLocator(s_defaultTpmLocator);
141  s_defaultTpmLocator = tpmScheme + ":" + tpmLocation;
142 
143  return s_defaultTpmLocator;
144 }
145 
146 
147 // Other defaults
148 
149 const SigningInfo&
151 {
152  static SigningInfo signingInfo;
153  return signingInfo;
154 }
155 
156 const KeyParams&
158 {
159  static EcKeyParams keyParams;
160  return keyParams;
161 }
162 
163 //
164 
166  : KeyChain(getDefaultPibLocator(), getDefaultTpmLocator(), true)
167 {
168 }
169 
170 KeyChain::KeyChain(const std::string& pibLocator, const std::string& tpmLocator, bool allowReset)
171 {
172  // PIB Locator
173  std::string pibScheme, pibLocation;
174  std::tie(pibScheme, pibLocation) = parseAndCheckPibLocator(pibLocator);
175  std::string canonicalPibLocator = pibScheme + ":" + pibLocation;
176 
177  // Create PIB
178  m_pib = createPib(canonicalPibLocator);
179  std::string oldTpmLocator;
180  try {
181  oldTpmLocator = m_pib->getTpmLocator();
182  }
183  catch (const Pib::Error&) {
184  // TPM locator is not set in PIB yet.
185  }
186 
187  // TPM Locator
188  std::string tpmScheme, tpmLocation;
189  std::tie(tpmScheme, tpmLocation) = parseAndCheckTpmLocator(tpmLocator);
190  std::string canonicalTpmLocator = tpmScheme + ":" + tpmLocation;
191 
192  if (canonicalPibLocator == getDefaultPibLocator()) {
193  // Default PIB must use default TPM
194  if (!oldTpmLocator.empty() && oldTpmLocator != getDefaultTpmLocator()) {
195  m_pib->reset();
196  canonicalTpmLocator = getDefaultTpmLocator();
197  }
198  }
199  else {
200  // non-default PIB check consistency
201  if (!oldTpmLocator.empty() && oldTpmLocator != canonicalTpmLocator) {
202  if (allowReset)
203  m_pib->reset();
204  else
205  NDN_THROW(LocatorMismatchError("TPM locator supplied does not match TPM locator in PIB: " +
206  oldTpmLocator + " != " + canonicalTpmLocator));
207  }
208  }
209 
210  // note that key mismatch may still happen if the TPM locator is initially set to a
211  // wrong one or if the PIB was shared by more than one TPMs before. This is due to the
212  // old PIB does not have TPM info, new pib should not have this problem.
213  m_tpm = createTpm(canonicalTpmLocator);
214  m_pib->setTpmLocator(canonicalTpmLocator);
215 }
216 
217 KeyChain::~KeyChain() = default;
218 
219 // public: management
220 
221 Identity
222 KeyChain::createIdentity(const Name& identityName, const KeyParams& params)
223 {
224  Identity id = m_pib->addIdentity(identityName);
225 
226  Key key;
227  try {
228  key = id.getDefaultKey();
229  }
230  catch (const Pib::Error&) {
231  key = createKey(id, params);
232  }
233 
234  try {
235  key.getDefaultCertificate();
236  }
237  catch (const Pib::Error&) {
238  NDN_LOG_DEBUG("No default cert for " << key.getName() << ", requesting self-signing");
239  selfSign(key);
240  }
241 
242  return id;
243 }
244 
245 void
247 {
248  BOOST_ASSERT(static_cast<bool>(identity));
249 
250  Name identityName = identity.getName();
251 
252  for (const auto& key : identity.getKeys()) {
253  m_tpm->deleteKey(key.getName());
254  }
255 
256  m_pib->removeIdentity(identityName);
257 }
258 
259 void
261 {
262  BOOST_ASSERT(static_cast<bool>(identity));
263 
264  m_pib->setDefaultIdentity(identity.getName());
265 }
266 
267 Key
268 KeyChain::createKey(const Identity& identity, const KeyParams& params)
269 {
270  BOOST_ASSERT(static_cast<bool>(identity));
271 
272  // create key in TPM
273  Name keyName = m_tpm->createKey(identity.getName(), params);
274 
275  // set up key info in PIB
276  ConstBufferPtr pubKey = m_tpm->getPublicKey(keyName);
277  Key key = identity.addKey(pubKey->data(), pubKey->size(), keyName);
278 
279  NDN_LOG_DEBUG("Requesting self-signing for newly created key " << key.getName());
280  selfSign(key);
281 
282  return key;
283 }
284 
285 Name
286 KeyChain::createHmacKey(const Name& prefix, const HmacKeyParams& params)
287 {
288  return m_tpm->createKey(prefix, params);
289 }
290 
291 void
292 KeyChain::deleteKey(const Identity& identity, const Key& key)
293 {
294  BOOST_ASSERT(static_cast<bool>(identity));
295  BOOST_ASSERT(static_cast<bool>(key));
296 
297  Name keyName = key.getName();
298  if (identity.getName() != key.getIdentity()) {
299  NDN_THROW(std::invalid_argument("Identity `" + identity.getName().toUri() + "` "
300  "does not match key `" + keyName.toUri() + "`"));
301  }
302 
303  identity.removeKey(keyName);
304  m_tpm->deleteKey(keyName);
305 }
306 
307 void
308 KeyChain::setDefaultKey(const Identity& identity, const Key& key)
309 {
310  BOOST_ASSERT(static_cast<bool>(identity));
311  BOOST_ASSERT(static_cast<bool>(key));
312 
313  if (identity.getName() != key.getIdentity())
314  NDN_THROW(std::invalid_argument("Identity `" + identity.getName().toUri() + "` "
315  "does not match key `" + key.getName().toUri() + "`"));
316 
317  identity.setDefaultKey(key.getName());
318 }
319 
320 void
321 KeyChain::addCertificate(const Key& key, const Certificate& certificate)
322 {
323  BOOST_ASSERT(static_cast<bool>(key));
324 
325  const auto& certContent = certificate.getContent();
326  if (certContent.value_size() == 0) {
327  NDN_THROW(std::invalid_argument("Certificate `" + certificate.getName().toUri() + "` is empty"));
328  }
329 
330  if (key.getName() != certificate.getKeyName() ||
331  !std::equal(certContent.value_begin(), certContent.value_end(), key.getPublicKey().begin())) {
332  NDN_THROW(std::invalid_argument("Key `" + key.getName().toUri() + "` "
333  "does not match certificate `" + certificate.getName().toUri() + "`"));
334  }
335 
336  key.addCertificate(certificate);
337 }
338 
339 void
340 KeyChain::deleteCertificate(const Key& key, const Name& certificateName)
341 {
342  BOOST_ASSERT(static_cast<bool>(key));
343 
344  if (!Certificate::isValidName(certificateName)) {
345  NDN_THROW(std::invalid_argument("Wrong certificate name `" + certificateName.toUri() + "`"));
346  }
347 
348  key.removeCertificate(certificateName);
349 }
350 
351 void
353 {
354  BOOST_ASSERT(static_cast<bool>(key));
355 
356  addCertificate(key, cert);
357  key.setDefaultCertificate(cert.getName());
358 }
359 
360 shared_ptr<SafeBag>
361 KeyChain::exportSafeBag(const Certificate& certificate, const char* pw, size_t pwLen)
362 {
363  Name identity = certificate.getIdentity();
364  Name keyName = certificate.getKeyName();
365 
366  ConstBufferPtr encryptedKey;
367  try {
368  encryptedKey = m_tpm->exportPrivateKey(keyName, pw, pwLen);
369  }
370  catch (const Tpm::Error&) {
371  NDN_THROW_NESTED(Error("Failed to export private key `" + keyName.toUri() + "`"));
372  }
373 
374  return make_shared<SafeBag>(certificate, *encryptedKey);
375 }
376 
377 void
378 KeyChain::importSafeBag(const SafeBag& safeBag, const char* pw, size_t pwLen)
379 {
380  Data certData = safeBag.getCertificate();
381  Certificate cert(std::move(certData));
382  Name identity = cert.getIdentity();
383  Name keyName = cert.getKeyName();
384  const Buffer publicKeyBits = cert.getPublicKey();
385 
386  if (m_tpm->hasKey(keyName)) {
387  NDN_THROW(Error("Private key `" + keyName.toUri() + "` already exists"));
388  }
389 
390  try {
391  Identity existingId = m_pib->getIdentity(identity);
392  existingId.getKey(keyName);
393  NDN_THROW(Error("Public key `" + keyName.toUri() + "` already exists"));
394  }
395  catch (const Pib::Error&) {
396  // Either identity or key doesn't exist. OK to import.
397  }
398 
399  try {
400  m_tpm->importPrivateKey(keyName,
401  safeBag.getEncryptedKeyBag().data(), safeBag.getEncryptedKeyBag().size(),
402  pw, pwLen);
403  }
404  catch (const Tpm::Error&) {
405  NDN_THROW_NESTED(Error("Failed to import private key `" + keyName.toUri() + "`"));
406  }
407 
408  // check the consistency of private key and certificate
409  const uint8_t content[] = {0x01, 0x02, 0x03, 0x04};
410  ConstBufferPtr sigBits;
411  try {
412  sigBits = m_tpm->sign(content, 4, keyName, DigestAlgorithm::SHA256);
413  }
414  catch (const std::runtime_error&) {
415  m_tpm->deleteKey(keyName);
416  NDN_THROW(Error("Invalid private key `" + keyName.toUri() + "`"));
417  }
418  bool isVerified = false;
419  {
420  using namespace transform;
421  PublicKey publicKey;
422  publicKey.loadPkcs8(publicKeyBits.data(), publicKeyBits.size());
423  bufferSource(content, sizeof(content)) >> verifierFilter(DigestAlgorithm::SHA256, publicKey,
424  sigBits->data(), sigBits->size())
425  >> boolSink(isVerified);
426  }
427  if (!isVerified) {
428  m_tpm->deleteKey(keyName);
429  NDN_THROW(Error("Certificate `" + cert.getName().toUri() + "` "
430  "and private key `" + keyName.toUri() + "` do not match"));
431  }
432 
433  Identity id = m_pib->addIdentity(identity);
434  Key key = id.addKey(cert.getPublicKey().data(), cert.getPublicKey().size(), keyName);
435  key.addCertificate(cert);
436 }
437 
438 void
439 KeyChain::importPrivateKey(const Name& keyName, shared_ptr<transform::PrivateKey> key)
440 {
441  if (m_tpm->hasKey(keyName)) {
442  NDN_THROW(Error("Private key `" + keyName.toUri() + "` already exists"));
443  }
444 
445  try {
446  m_tpm->importPrivateKey(keyName, std::move(key));
447  }
448  catch (const Tpm::Error&) {
449  NDN_THROW_NESTED(Error("Failed to import private key `" + keyName.toUri() + "`"));
450  }
451 }
452 
453 // public: signing
454 
455 void
456 KeyChain::sign(Data& data, const SigningInfo& params)
457 {
458  Name keyName;
459  SignatureInfo sigInfo;
460  std::tie(keyName, sigInfo) = prepareSignatureInfo(params);
461 
462  data.setSignatureInfo(sigInfo);
463 
464  EncodingBuffer encoder;
465  data.wireEncode(encoder, true);
466 
467  Block sigValue(tlv::SignatureValue,
468  sign({{encoder.buf(), encoder.size()}}, keyName, params.getDigestAlgorithm()));
469 
470  data.wireEncode(encoder, sigValue);
471 }
472 
473 void
474 KeyChain::sign(Interest& interest, const SigningInfo& params)
475 {
476  Name keyName;
477  SignatureInfo sigInfo;
478  std::tie(keyName, sigInfo) = prepareSignatureInfo(params);
479 
481  interest.setSignatureInfo(sigInfo);
482 
483  // Extract function will throw if not all necessary elements are present in Interest
484  auto sigValue = sign(interest.extractSignedRanges(), keyName, params.getDigestAlgorithm());
485  interest.setSignatureValue(std::move(sigValue));
486  }
487  else {
488  Name signedName = interest.getName();
489  // We encode in Data format because this is the format used prior to Packet Specification v0.3
490  signedName.append(sigInfo.wireEncode(SignatureInfo::Type::Data)); // SignatureInfo
491  Block sigValue(tlv::SignatureValue,
492  sign({{signedName.wireEncode().value(), signedName.wireEncode().value_size()}},
493  keyName, params.getDigestAlgorithm()));
494  sigValue.encode();
495  signedName.append(std::move(sigValue)); // SignatureValue
496  interest.setName(signedName);
497  }
498 }
499 
500 Block
501 KeyChain::sign(const uint8_t* buffer, size_t bufferLength, const SigningInfo& params)
502 {
503  Name keyName;
504  SignatureInfo sigInfo;
505  std::tie(keyName, sigInfo) = prepareSignatureInfo(params);
506 
507  return Block(tlv::SignatureValue,
508  sign({{buffer, bufferLength}}, keyName, params.getDigestAlgorithm()));
509 }
510 
511 // public: PIB/TPM creation helpers
512 
513 static inline std::tuple<std::string/*type*/, std::string/*location*/>
514 parseLocatorUri(const std::string& uri)
515 {
516  size_t pos = uri.find(':');
517  if (pos != std::string::npos) {
518  return std::make_tuple(uri.substr(0, pos), uri.substr(pos + 1));
519  }
520  else {
521  return std::make_tuple(uri, "");
522  }
523 }
524 
525 std::tuple<std::string/*type*/, std::string/*location*/>
526 KeyChain::parseAndCheckPibLocator(const std::string& pibLocator)
527 {
528  std::string pibScheme, pibLocation;
529  std::tie(pibScheme, pibLocation) = parseLocatorUri(pibLocator);
530 
531  if (pibScheme.empty()) {
532  pibScheme = getDefaultPibScheme();
533  }
534 
535  auto pibFactory = getPibFactories().find(pibScheme);
536  if (pibFactory == getPibFactories().end()) {
537  NDN_THROW(KeyChain::Error("PIB scheme `" + pibScheme + "` is not supported"));
538  }
539 
540  return std::make_tuple(pibScheme, pibLocation);
541 }
542 
543 unique_ptr<Pib>
544 KeyChain::createPib(const std::string& pibLocator)
545 {
546  std::string pibScheme, pibLocation;
547  std::tie(pibScheme, pibLocation) = parseAndCheckPibLocator(pibLocator);
548  auto pibFactory = getPibFactories().find(pibScheme);
549  BOOST_ASSERT(pibFactory != getPibFactories().end());
550  return unique_ptr<Pib>(new Pib(pibScheme, pibLocation, pibFactory->second(pibLocation)));
551 }
552 
553 std::tuple<std::string/*type*/, std::string/*location*/>
554 KeyChain::parseAndCheckTpmLocator(const std::string& tpmLocator)
555 {
556  std::string tpmScheme, tpmLocation;
557  std::tie(tpmScheme, tpmLocation) = parseLocatorUri(tpmLocator);
558 
559  if (tpmScheme.empty()) {
560  tpmScheme = getDefaultTpmScheme();
561  }
562  auto tpmFactory = getTpmFactories().find(tpmScheme);
563  if (tpmFactory == getTpmFactories().end()) {
564  NDN_THROW(KeyChain::Error("TPM scheme `" + tpmScheme + "` is not supported"));
565  }
566 
567  return std::make_tuple(tpmScheme, tpmLocation);
568 }
569 
570 unique_ptr<Tpm>
571 KeyChain::createTpm(const std::string& tpmLocator)
572 {
573  std::string tpmScheme, tpmLocation;
574  std::tie(tpmScheme, tpmLocation) = parseAndCheckTpmLocator(tpmLocator);
575  auto tpmFactory = getTpmFactories().find(tpmScheme);
576  BOOST_ASSERT(tpmFactory != getTpmFactories().end());
577  return unique_ptr<Tpm>(new Tpm(tpmScheme, tpmLocation, tpmFactory->second(tpmLocation)));
578 }
579 
580 // private: signing
581 
583 KeyChain::selfSign(Key& key)
584 {
585  Certificate certificate;
586 
587  // set name
588  Name certificateName = key.getName();
589  certificateName
590  .append("self")
591  .appendVersion();
592  certificate.setName(certificateName);
593 
594  // set metainfo
596  certificate.setFreshnessPeriod(1_h);
597 
598  // set content
599  certificate.setContent(key.getPublicKey().data(), key.getPublicKey().size());
600 
601  // set signature-info
602  SignatureInfo signatureInfo;
603  // Note time::system_clock::max() or other NotAfter date results in incorrect encoded value
604  // because of overflow during conversion to boost::posix_time::ptime (bug #3915).
606  time::system_clock::now() + 20 * 365_days));
607 
608  sign(certificate, SigningInfo(key).setSignatureInfo(signatureInfo));
609 
610  key.addCertificate(certificate);
611  return certificate;
612 }
613 
614 std::tuple<Name, SignatureInfo>
615 KeyChain::prepareSignatureInfo(const SigningInfo& params)
616 {
617  SignatureInfo sigInfo = params.getSignatureInfo();
618  pib::Identity identity;
619  pib::Key key;
620 
621  switch (params.getSignerType()) {
623  try {
624  identity = m_pib->getDefaultIdentity();
625  }
626  catch (const Pib::Error&) { // no default identity, use sha256 for signing.
628  NDN_LOG_TRACE("Prepared signature info: " << sigInfo);
629  return std::make_tuple(SigningInfo::getDigestSha256Identity(), sigInfo);
630  }
631  break;
632  }
634  identity = params.getPibIdentity();
635  if (!identity) {
636  try {
637  identity = m_pib->getIdentity(params.getSignerName());
638  }
639  catch (const Pib::Error&) {
640  NDN_THROW_NESTED(InvalidSigningInfoError("Signing identity `" +
641  params.getSignerName().toUri() + "` does not exist"));
642  }
643  }
644  break;
645  }
647  key = params.getPibKey();
648  if (!key) {
649  Name identityName = extractIdentityFromKeyName(params.getSignerName());
650  try {
651  key = m_pib->getIdentity(identityName).getKey(params.getSignerName());
652  }
653  catch (const Pib::Error&) {
654  NDN_THROW_NESTED(InvalidSigningInfoError("Signing key `" +
655  params.getSignerName().toUri() + "` does not exist"));
656  }
657  }
658  break;
659  }
661  Name identityName = extractIdentityFromCertName(params.getSignerName());
662  Name keyName = extractKeyNameFromCertName(params.getSignerName());
663  try {
664  identity = m_pib->getIdentity(identityName);
665  key = identity.getKey(keyName);
666  }
667  catch (const Pib::Error&) {
668  NDN_THROW_NESTED(InvalidSigningInfoError("Signing certificate `" +
669  params.getSignerName().toUri() + "` does not exist"));
670  }
671  break;
672  }
675  NDN_LOG_TRACE("Prepared signature info: " << sigInfo);
676  return std::make_tuple(SigningInfo::getDigestSha256Identity(), sigInfo);
677  }
679  const Name& keyName = params.getSignerName();
680  if (!m_tpm->hasKey(keyName)) {
681  m_tpm->importPrivateKey(keyName, params.getHmacKey());
682  }
683  sigInfo.setSignatureType(getSignatureType(KeyType::HMAC, params.getDigestAlgorithm()));
684  sigInfo.setKeyLocator(keyName);
685  NDN_LOG_TRACE("Prepared signature info: " << sigInfo);
686  return std::make_tuple(keyName, sigInfo);
687  }
688  default: {
689  NDN_THROW(InvalidSigningInfoError("Unrecognized signer type " +
690  boost::lexical_cast<std::string>(params.getSignerType())));
691  }
692  }
693 
694  if (!key) {
695  if (!identity) {
696  NDN_THROW(InvalidSigningInfoError("Cannot determine signing parameters"));
697  }
698  try {
699  key = identity.getDefaultKey();
700  }
701  catch (const Pib::Error&) {
702  NDN_THROW_NESTED(InvalidSigningInfoError("Signing identity `" + identity.getName().toUri() +
703  "` does not have a default certificate"));
704  }
705  }
706 
707  BOOST_ASSERT(key);
708 
709  sigInfo.setSignatureType(getSignatureType(key.getKeyType(), params.getDigestAlgorithm()));
710  sigInfo.setKeyLocator(key.getName());
711 
712  NDN_LOG_TRACE("Prepared signature info: " << sigInfo);
713  return std::make_tuple(key.getName(), sigInfo);
714 }
715 
717 KeyChain::sign(const InputBuffers& bufs, const Name& keyName, DigestAlgorithm digestAlgorithm) const
718 {
719  using namespace transform;
720 
721  if (keyName == SigningInfo::getDigestSha256Identity()) {
722  OBufferStream os;
724  return os.buf();
725  }
726 
727  auto signature = m_tpm->sign(bufs, keyName, digestAlgorithm);
728  if (!signature) {
729  NDN_THROW(InvalidSigningInfoError("TPM signing failed for key `" + keyName.toUri() + "` "
730  "(e.g., PIB contains info about the key, but TPM is missing "
731  "the corresponding private key)"));
732  }
733 
734  return signature;
735 }
736 
738 KeyChain::getSignatureType(KeyType keyType, DigestAlgorithm)
739 {
740  switch (keyType) {
741  case KeyType::RSA:
743  case KeyType::EC:
745  case KeyType::HMAC:
747  default:
748  NDN_THROW(Error("Unsupported key type " + boost::lexical_cast<std::string>(keyType)));
749  }
750 }
751 
752 } // inline namespace v2
753 } // namespace security
754 } // namespace ndn
#define NDN_THROW_NESTED(e)
Definition: exception.hpp:71
void deleteKey(const Identity &identity, const Key &key)
Delete a key key of identity.
Definition: key-chain.cpp:292
Sign Interest using Packet Specification v0.3 semantics.
Key getKey(const Name &keyName) const
Get a key with id keyName.
Definition: identity.cpp:55
Data & setContentType(uint32_t type)
Definition: data.cpp:343
Definition: data.cpp:26
The certificate following the certificate format naming convention.
Definition: certificate.hpp:81
represents a semantic error
Definition: pib.hpp:56
Buffer getPublicKey() const
Get public key bits (in PKCS#8 format)
Represents a SignatureInfo or InterestSignatureInfo TLV element.
The interface of signing key management.
Definition: key-chain.hpp:45
const SignatureInfo & getSignatureInfo() const
SimpleSymmetricKeyParams is a template for symmetric keys with only one parameter: size...
Definition: key-params.hpp:256
void addCertificate(const Key &key, const Certificate &certificate)
Add a certificate certificate for key.
Definition: key-chain.cpp:321
Key createKey(const Identity &identity, const KeyParams &params=getDefaultKeyParams())
Create a new key for identity.
Definition: key-chain.cpp:268
Name getIdentity() const
Get identity name.
Definition: certificate.cpp:87
Data & setName(const Name &name)
Set name.
Definition: data.cpp:227
public key, certificate
Definition: tlv.hpp:162
DigestAlgorithm getDigestAlgorithm() const
KeyType getKeyType() const
Get key type.
Definition: key.cpp:50
Name extractKeyNameFromCertName(const Name &certName)
Extract key name from the certificate name certName.
static std::tuple< std::string, std::string > parseLocatorUri(const std::string &uri)
Definition: key-chain.cpp:514
RSA key, supports sign/verify and encrypt/decrypt operations.
KeyChain()
Constructor to create KeyChain with default PIB and TPM.
Definition: key-chain.cpp:165
Data & setContent(const Block &block)
Set Content from a Block.
Definition: data.cpp:245
SignatureInfo & setValidityPeriod(optional< security::ValidityPeriod > validityPeriod)
Append or replace ValidityPeriod.
const Key & getPibKey() const
void sign(Data &data, const SigningInfo &params=SigningInfo())
Sign a Data packet according to the supplied signing information.
Definition: key-chain.cpp:456
InputBuffers extractSignedRanges() const
Extract ranges of Interest covered by the signature in Packet Specification v0.3. ...
Definition: interest.cpp:640
Represents a TLV element of the NDN packet format.
Definition: block.hpp:42
Error indicating that the supplied TPM locator does not match the locator stored in PIB...
Definition: key-chain.hpp:57
Represents an Interest packet.
Definition: interest.hpp:50
#define NDN_LOG_DEBUG(expression)
Log at DEBUG level.
Definition: logger.hpp:254
Use a SHA-256 digest only, no signer needs to be specified.
shared_ptr< transform::PrivateKey > getHmacKey() const
#define NDN_LOG_INIT(name)
Define a non-member log module.
Definition: logger.hpp:163
static time_point now() noexcept
Definition: time.cpp:46
Name & append(const Component &component)
Append a component.
Definition: name.hpp:278
Signing parameters passed to KeyChain.
void deleteCertificate(const Key &key, const Name &certificateName)
delete a certificate with name certificateName of key.
Definition: key-chain.cpp:340
TPM front-end class.
Definition: tpm.hpp:65
Name & appendVersion(optional< uint64_t > version=nullopt)
Append a version component.
Definition: name.cpp:230
const Buffer & getEncryptedKeyBag() const
Get the private key in PKCS#8 from safe bag.
Definition: safe-bag.hpp:105
#define NDN_THROW(e)
Definition: exception.hpp:61
HMAC key, supports sign/verify operations.
Identity createIdentity(const Name &identityName, const KeyParams &params=getDefaultKeyParams())
Create an identity identityName.
Definition: key-chain.cpp:222
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:378
const Name & getSignerName() const
KeyType
The type of a cryptographic key.
#define NDN_CXX_KEYCHAIN_REGISTER_TPM_BACKEND(TpmType)
Register Tpm backend class in KeyChain.
Definition: key-chain.hpp:505
Interest & setSignatureValue(ConstBufferPtr value)
Set the InterestSignatureValue.
Definition: interest.cpp:600
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:361
const Data & getCertificate() const
Get the certificate data packet from safe bag.
Definition: safe-bag.hpp:96
Data & setSignatureInfo(const SignatureInfo &info)
Set SignatureInfo.
Definition: data.cpp:310
#define NDN_CXX_KEYCHAIN_REGISTER_PIB_BACKEND(PibType)
Register Pib backend class in KeyChain.
Definition: key-chain.hpp:487
A frontend handle of a key instance.
Definition: key.hpp:49
No signer is specified, use default setting or follow the trust schema.
SignedInterestFormat getSignedInterestFormat() const
void setDefaultCertificate(const Key &key, const Certificate &certificate)
Set cert as the default certificate of key.
Definition: key-chain.cpp:352
unique_ptr< Sink > streamSink(std::ostream &os)
Definition: stream-sink.cpp:53
void setDefaultIdentity(const Identity &identity)
Set identity as the default identity.
Definition: key-chain.cpp:260
Name getKeyName() const
Get key name.
Definition: certificate.cpp:81
static const SigningInfo & getDefaultSigningInfo()
Definition: key-chain.cpp:150
Elliptic Curve key (e.g. for ECDSA), supports sign/verify operations.
const Name & getName() const noexcept
Get name.
Definition: data.hpp:126
static const Name & getDigestSha256Identity()
A localhost identity to indicate that the signature is generated using SHA-256.
unique_ptr< Transform > digestFilter(DigestAlgorithm algo)
Use the SHA-256 hash of the public key as key id.
Represents an absolute name.
Definition: name.hpp:44
const Name & getName() const
Get key name.
Definition: key.cpp:38
Signer is a certificate, use it directly.
unique_ptr< Transform > verifierFilter(DigestAlgorithm algo, const PublicKey &key, const uint8_t *sig, size_t sigLen)
Name createHmacKey(const Name &prefix=SigningInfo::getHmacIdentity(), const HmacKeyParams &params=HmacKeyParams())
Create a new HMAC key.
Definition: key-chain.cpp:286
void importPrivateKey(const Name &keyName, shared_ptr< transform::PrivateKey > key)
Import a private key into the TPM.
Definition: key-chain.cpp:439
SignatureTypeValue
SignatureType values.
Definition: tlv.hpp:131
SignatureInfo & setSignatureType(tlv::SignatureTypeValue type)
Set SignatureType.
Signer is a key, use its default certificate.
size_t wireEncode(EncodingImpl< TAG > &encoder, Type type=Type::Data) const
Fast encoding or block size estimation.
time_point TimePoint
Definition: time.hpp:195
Interest & setSignatureInfo(const SignatureInfo &info)
Set the InterestSignatureInfo.
Definition: interest.cpp:556
const Identity & getPibIdentity() const
const Key & getDefaultKey() const
Get the default key for this Identity.
Definition: identity.cpp:79
void deleteIdentity(const Identity &identity)
delete identity.
Definition: key-chain.cpp:246
static bool isValidName(const Name &certName)
Check if the specified name follows the naming convention for the certificate.
static const KeyParams & getDefaultKeyParams()
Definition: key-chain.cpp:157
a secured container for sensitive information(certificate, private key)
Definition: safe-bag.hpp:37
shared_ptr< Buffer > buf()
Flush written data to the stream and return shared pointer to the underlying buffer.
System configuration file for NDN platform.
Definition: config-file.hpp:48
Data & setFreshnessPeriod(time::milliseconds freshnessPeriod)
Definition: data.cpp:353
void setDefaultKey(const Identity &identity, const Key &key)
Set key as the default key of identity.
Definition: key-chain.cpp:308
void encode()
Encode sub-elements into TLV-VALUE.
Definition: block.cpp:353
const Block & getContent() const noexcept
Get the Content element.
Definition: data.hpp:172
SignatureInfo & setKeyLocator(optional< KeyLocator > keyLocator)
Set KeyLocator.
const Name & getName() const noexcept
Definition: interest.hpp:174
const Name & getName() const
Get the name of the identity.
Definition: identity.cpp:37
const v2::Certificate & getDefaultCertificate() const
Get the default certificate for this Key.
Definition: key.cpp:98
size_t wireEncode(EncodingImpl< TAG > &encoder, bool wantUnsignedPortionOnly=false) const
Prepend wire encoding to encoder.
Definition: data.cpp:47
Base class for key parameters.
Definition: key-params.hpp:35
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:348
Signer is an identity, use its default key and default certificate.
const Buffer & getPublicKey() const
Get public key bits.
Definition: key.cpp:56
A frontend handle of an Identity.
Definition: identity.hpp:42
size_t wireEncode(EncodingImpl< TAG > &encoder) const
Fast encoding or block size estimation.
Definition: name.cpp:117
const KeyContainer & getKeys() const
Get all keys for this identity.
Definition: identity.cpp:61
implements an output stream that constructs ndn::Buffer
#define NDN_LOG_TRACE(expression)
Log at TRACE level.
Definition: logger.hpp:249
InputBuffers bufs
Represents a Data packet.
Definition: data.hpp:39
SimplePublicKeyParams is a template for public keys with only one parameter: size.
Definition: key-params.hpp:149
Name extractIdentityFromKeyName(const Name &keyName)
Extract identity namespace from the key name keyName.
Definition: key.cpp:160
General-purpose automatically managed/resized buffer.
Definition: buffer.hpp:40
const Parsed & getParsedConfiguration() const
const Name & getIdentity() const
Get the name of the belonging identity.
Definition: key.cpp:44
unique_ptr< Sink > boolSink(bool &value)
Definition: bool-sink.cpp:51
EncodingImpl< EncoderTag > EncodingBuffer
represents the PIB
Definition: pib.hpp:52
SignerType getSignerType() const
shared_ptr< const Buffer > ConstBufferPtr
Definition: buffer.hpp:126
Interest & setName(const Name &name)
Set the Interest&#39;s name.
Definition: interest.cpp:375
Name extractIdentityFromCertName(const Name &certName)
Extract identity namespace from the certificate name certName.