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 
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 
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 const KeyParams&
148 {
149  static EcKeyParams keyParams;
150  return keyParams;
151 }
152 
153 //
154 
156  : KeyChain(getDefaultPibLocator(), getDefaultTpmLocator(), true)
157 {
158 }
159 
160 KeyChain::KeyChain(const std::string& pibLocator, const std::string& tpmLocator, bool allowReset)
161 {
162  // PIB Locator
163  std::string pibScheme, pibLocation;
164  std::tie(pibScheme, pibLocation) = parseAndCheckPibLocator(pibLocator);
165  std::string canonicalPibLocator = pibScheme + ":" + pibLocation;
166 
167  // Create PIB
168  m_pib = createPib(canonicalPibLocator);
169  std::string oldTpmLocator;
170  try {
171  oldTpmLocator = m_pib->getTpmLocator();
172  }
173  catch (const Pib::Error&) {
174  // TPM locator is not set in PIB yet.
175  }
176 
177  // TPM Locator
178  std::string tpmScheme, tpmLocation;
179  std::tie(tpmScheme, tpmLocation) = parseAndCheckTpmLocator(tpmLocator);
180  std::string canonicalTpmLocator = tpmScheme + ":" + tpmLocation;
181 
182  if (canonicalPibLocator == getDefaultPibLocator()) {
183  // Default PIB must use default TPM
184  if (!oldTpmLocator.empty() && oldTpmLocator != getDefaultTpmLocator()) {
185  m_pib->reset();
186  canonicalTpmLocator = getDefaultTpmLocator();
187  }
188  }
189  else {
190  // non-default PIB check consistency
191  if (!oldTpmLocator.empty() && oldTpmLocator != canonicalTpmLocator) {
192  if (allowReset)
193  m_pib->reset();
194  else
195  NDN_THROW(LocatorMismatchError("TPM locator supplied does not match TPM locator in PIB: " +
196  oldTpmLocator + " != " + canonicalTpmLocator));
197  }
198  }
199 
200  // note that key mismatch may still happen if the TPM locator is initially set to a
201  // wrong one or if the PIB was shared by more than one TPMs before. This is due to the
202  // old PIB does not have TPM info, new pib should not have this problem.
203  m_tpm = createTpm(canonicalTpmLocator);
204  m_pib->setTpmLocator(canonicalTpmLocator);
205 }
206 
207 KeyChain::~KeyChain() = default;
208 
209 // public: management
210 
211 Identity
212 KeyChain::createIdentity(const Name& identityName, const KeyParams& params)
213 {
214  Identity id = m_pib->addIdentity(identityName);
215 
216  Key key;
217  try {
218  key = id.getDefaultKey();
219  }
220  catch (const Pib::Error&) {
221  key = createKey(id, params);
222  }
223 
224  try {
225  key.getDefaultCertificate();
226  }
227  catch (const Pib::Error&) {
228  NDN_LOG_DEBUG("No default cert for " << key.getName() << ", requesting self-signing");
229  selfSign(key);
230  }
231 
232  return id;
233 }
234 
235 void
237 {
238  BOOST_ASSERT(static_cast<bool>(identity));
239 
240  Name identityName = identity.getName();
241 
242  for (const auto& key : identity.getKeys()) {
243  m_tpm->deleteKey(key.getName());
244  }
245 
246  m_pib->removeIdentity(identityName);
247 }
248 
249 void
251 {
252  BOOST_ASSERT(static_cast<bool>(identity));
253 
254  m_pib->setDefaultIdentity(identity.getName());
255 }
256 
257 Key
258 KeyChain::createKey(const Identity& identity, const KeyParams& params)
259 {
260  BOOST_ASSERT(static_cast<bool>(identity));
261 
262  // create key in TPM
263  Name keyName = m_tpm->createKey(identity.getName(), params);
264 
265  // set up key info in PIB
266  Key key = identity.addKey(*m_tpm->getPublicKey(keyName), keyName);
267 
268  NDN_LOG_DEBUG("Requesting self-signing for newly created key " << key.getName());
269  selfSign(key);
270 
271  return key;
272 }
273 
274 Name
275 KeyChain::createHmacKey(const Name& prefix, const HmacKeyParams& params)
276 {
277  return m_tpm->createKey(prefix, params);
278 }
279 
280 void
281 KeyChain::deleteKey(const Identity& identity, const Key& key)
282 {
283  BOOST_ASSERT(static_cast<bool>(identity));
284  BOOST_ASSERT(static_cast<bool>(key));
285 
286  Name keyName = key.getName();
287  if (identity.getName() != key.getIdentity()) {
288  NDN_THROW(std::invalid_argument("Identity `" + identity.getName().toUri() + "` "
289  "does not match key `" + keyName.toUri() + "`"));
290  }
291 
292  identity.removeKey(keyName);
293  m_tpm->deleteKey(keyName);
294 }
295 
296 void
297 KeyChain::setDefaultKey(const Identity& identity, const Key& key)
298 {
299  BOOST_ASSERT(static_cast<bool>(identity));
300  BOOST_ASSERT(static_cast<bool>(key));
301 
302  if (identity.getName() != key.getIdentity())
303  NDN_THROW(std::invalid_argument("Identity `" + identity.getName().toUri() + "` "
304  "does not match key `" + key.getName().toUri() + "`"));
305 
306  identity.setDefaultKey(key.getName());
307 }
308 
309 void
310 KeyChain::addCertificate(const Key& key, const Certificate& certificate)
311 {
312  BOOST_ASSERT(static_cast<bool>(key));
313 
314  const auto& certContent = certificate.getContent();
315  if (certContent.value_size() == 0) {
316  NDN_THROW(std::invalid_argument("Certificate `" + certificate.getName().toUri() + "` is empty"));
317  }
318 
319  if (key.getName() != certificate.getKeyName() ||
320  !std::equal(certContent.value_begin(), certContent.value_end(), key.getPublicKey().begin())) {
321  NDN_THROW(std::invalid_argument("Key `" + key.getName().toUri() + "` "
322  "does not match certificate `" + certificate.getName().toUri() + "`"));
323  }
324 
325  key.addCertificate(certificate);
326 }
327 
328 void
329 KeyChain::deleteCertificate(const Key& key, const Name& certificateName)
330 {
331  BOOST_ASSERT(static_cast<bool>(key));
332 
333  if (!Certificate::isValidName(certificateName)) {
334  NDN_THROW(std::invalid_argument("Wrong certificate name `" + certificateName.toUri() + "`"));
335  }
336 
337  key.removeCertificate(certificateName);
338 }
339 
340 void
342 {
343  BOOST_ASSERT(static_cast<bool>(key));
344 
345  addCertificate(key, cert);
346  key.setDefaultCertificate(cert.getName());
347 }
348 
349 shared_ptr<SafeBag>
350 KeyChain::exportSafeBag(const Certificate& certificate, const char* pw, size_t pwLen)
351 {
352  Name identity = certificate.getIdentity();
353  Name keyName = certificate.getKeyName();
354 
355  ConstBufferPtr encryptedKey;
356  try {
357  encryptedKey = m_tpm->exportPrivateKey(keyName, pw, pwLen);
358  }
359  catch (const Tpm::Error&) {
360  NDN_THROW_NESTED(Error("Failed to export private key `" + keyName.toUri() + "`"));
361  }
362 
363  return make_shared<SafeBag>(certificate, *encryptedKey);
364 }
365 
366 void
367 KeyChain::importSafeBag(const SafeBag& safeBag, const char* pw, size_t pwLen)
368 {
369  Data certData = safeBag.getCertificate();
370  Certificate cert(std::move(certData));
371  Name identity = cert.getIdentity();
372  Name keyName = cert.getKeyName();
373  const auto publicKeyBits = cert.getPublicKey();
374 
375  if (m_tpm->hasKey(keyName)) {
376  NDN_THROW(Error("Private key `" + keyName.toUri() + "` already exists"));
377  }
378 
379  try {
380  Identity existingId = m_pib->getIdentity(identity);
381  existingId.getKey(keyName);
382  NDN_THROW(Error("Public key `" + keyName.toUri() + "` already exists"));
383  }
384  catch (const Pib::Error&) {
385  // Either identity or key doesn't exist. OK to import.
386  }
387 
388  try {
389  m_tpm->importPrivateKey(keyName, safeBag.getEncryptedKey(), pw, pwLen);
390  }
391  catch (const Tpm::Error&) {
392  NDN_THROW_NESTED(Error("Failed to import private key `" + keyName.toUri() + "`"));
393  }
394 
395  // check the consistency of private key and certificate
396  const uint8_t content[] = {0x01, 0x02, 0x03, 0x04};
397  ConstBufferPtr sigBits;
398  try {
399  sigBits = m_tpm->sign({content}, keyName, DigestAlgorithm::SHA256);
400  }
401  catch (const std::runtime_error&) {
402  m_tpm->deleteKey(keyName);
403  NDN_THROW(Error("Invalid private key `" + keyName.toUri() + "`"));
404  }
405  bool isVerified = false;
406  {
407  using namespace transform;
408  PublicKey publicKey;
409  publicKey.loadPkcs8(publicKeyBits);
410  bufferSource(content) >> verifierFilter(DigestAlgorithm::SHA256, publicKey, *sigBits)
411  >> boolSink(isVerified);
412  }
413  if (!isVerified) {
414  m_tpm->deleteKey(keyName);
415  NDN_THROW(Error("Certificate `" + cert.getName().toUri() + "` "
416  "and private key `" + keyName.toUri() + "` do not match"));
417  }
418 
419  Identity id = m_pib->addIdentity(identity);
420  Key key = id.addKey(cert.getPublicKey(), keyName);
421  key.addCertificate(cert);
422 }
423 
424 void
425 KeyChain::importPrivateKey(const Name& keyName, shared_ptr<transform::PrivateKey> key)
426 {
427  if (m_tpm->hasKey(keyName)) {
428  NDN_THROW(Error("Private key `" + keyName.toUri() + "` already exists"));
429  }
430 
431  try {
432  m_tpm->importPrivateKey(keyName, std::move(key));
433  }
434  catch (const Tpm::Error&) {
435  NDN_THROW_NESTED(Error("Failed to import private key `" + keyName.toUri() + "`"));
436  }
437 }
438 
439 // public: signing
440 
441 void
442 KeyChain::sign(Data& data, const SigningInfo& params)
443 {
444  Name keyName;
445  SignatureInfo sigInfo;
446  std::tie(keyName, sigInfo) = prepareSignatureInfo(params);
447 
448  data.setSignatureInfo(sigInfo);
449 
450  EncodingBuffer encoder;
451  data.wireEncode(encoder, true);
452 
453  auto sigValue = sign({encoder}, keyName, params.getDigestAlgorithm());
454  data.wireEncode(encoder, *sigValue);
455 }
456 
457 void
458 KeyChain::sign(Interest& interest, const SigningInfo& params)
459 {
460  Name keyName;
461  SignatureInfo sigInfo;
462  std::tie(keyName, sigInfo) = prepareSignatureInfo(params);
463 
465  interest.setSignatureInfo(sigInfo);
466 
467  // Extract function will throw if not all necessary elements are present in Interest
468  auto sigValue = sign(interest.extractSignedRanges(), keyName, params.getDigestAlgorithm());
469  interest.setSignatureValue(std::move(sigValue));
470  }
471  else {
472  Name signedName = interest.getName();
473 
474  // We encode in Data format because this is the format used prior to Packet Specification v0.3
475  const auto& sigInfoBlock = sigInfo.wireEncode(SignatureInfo::Type::Data);
476  signedName.append(sigInfoBlock.begin(), sigInfoBlock.end()); // SignatureInfo
477 
478  Block sigValue(tlv::SignatureValue,
479  sign({{signedName.wireEncode().value(), signedName.wireEncode().value_size()}},
480  keyName, params.getDigestAlgorithm()));
481  sigValue.encode();
482  signedName.append(sigValue.begin(), sigValue.end()); // SignatureValue
483 
484  interest.setName(signedName);
485  }
486 }
487 
488 // public: PIB/TPM creation helpers
489 
490 static inline std::tuple<std::string/*type*/, std::string/*location*/>
491 parseLocatorUri(const std::string& uri)
492 {
493  size_t pos = uri.find(':');
494  if (pos != std::string::npos) {
495  return std::make_tuple(uri.substr(0, pos), uri.substr(pos + 1));
496  }
497  else {
498  return std::make_tuple(uri, "");
499  }
500 }
501 
502 std::tuple<std::string/*type*/, std::string/*location*/>
503 KeyChain::parseAndCheckPibLocator(const std::string& pibLocator)
504 {
505  std::string pibScheme, pibLocation;
506  std::tie(pibScheme, pibLocation) = parseLocatorUri(pibLocator);
507 
508  if (pibScheme.empty()) {
509  pibScheme = getDefaultPibScheme();
510  }
511 
512  auto pibFactory = getPibFactories().find(pibScheme);
513  if (pibFactory == getPibFactories().end()) {
514  NDN_THROW(Error("PIB scheme `" + pibScheme + "` is not supported"));
515  }
516 
517  return std::make_tuple(pibScheme, pibLocation);
518 }
519 
520 unique_ptr<Pib>
521 KeyChain::createPib(const std::string& pibLocator)
522 {
523  std::string pibScheme, pibLocation;
524  std::tie(pibScheme, pibLocation) = parseAndCheckPibLocator(pibLocator);
525  auto pibFactory = getPibFactories().find(pibScheme);
526  BOOST_ASSERT(pibFactory != getPibFactories().end());
527  return unique_ptr<Pib>(new Pib(pibScheme, pibLocation, pibFactory->second(pibLocation)));
528 }
529 
530 std::tuple<std::string/*type*/, std::string/*location*/>
531 KeyChain::parseAndCheckTpmLocator(const std::string& tpmLocator)
532 {
533  std::string tpmScheme, tpmLocation;
534  std::tie(tpmScheme, tpmLocation) = parseLocatorUri(tpmLocator);
535 
536  if (tpmScheme.empty()) {
537  tpmScheme = getDefaultTpmScheme();
538  }
539 
540  auto tpmFactory = getTpmFactories().find(tpmScheme);
541  if (tpmFactory == getTpmFactories().end()) {
542  NDN_THROW(Error("TPM scheme `" + tpmScheme + "` is not supported"));
543  }
544 
545  return std::make_tuple(tpmScheme, tpmLocation);
546 }
547 
548 unique_ptr<Tpm>
549 KeyChain::createTpm(const std::string& tpmLocator)
550 {
551  std::string tpmScheme, tpmLocation;
552  std::tie(tpmScheme, tpmLocation) = parseAndCheckTpmLocator(tpmLocator);
553  auto tpmFactory = getTpmFactories().find(tpmScheme);
554  BOOST_ASSERT(tpmFactory != getTpmFactories().end());
555  return unique_ptr<Tpm>(new Tpm(tpmScheme, tpmLocation, tpmFactory->second(tpmLocation)));
556 }
557 
558 // private: signing
559 
560 Certificate
561 KeyChain::selfSign(Key& key)
562 {
563  Certificate certificate;
564 
565  // set name
566  Name certificateName = key.getName();
567  certificateName
568  .append("self")
569  .appendVersion();
570  certificate.setName(certificateName);
571 
572  // set metainfo
573  certificate.setContentType(tlv::ContentType_Key);
574  certificate.setFreshnessPeriod(1_h);
575 
576  // set content
577  certificate.setContent(key.getPublicKey());
578 
579  // set signature-info
580  SignatureInfo signatureInfo;
581  // Note time::system_clock::max() or other NotAfter date results in incorrect encoded value
582  // because of overflow during conversion to boost::posix_time::ptime (bug #3915).
583  signatureInfo.setValidityPeriod(ValidityPeriod(time::system_clock::TimePoint(),
584  time::system_clock::now() + 20 * 365_days));
585 
586  sign(certificate, SigningInfo(key).setSignatureInfo(signatureInfo));
587 
588  key.addCertificate(certificate);
589  return certificate;
590 }
591 
592 std::tuple<Name, SignatureInfo>
593 KeyChain::prepareSignatureInfo(const SigningInfo& params)
594 {
595  SignatureInfo sigInfo = params.getSignatureInfo();
596  pib::Identity identity;
597  pib::Key key;
598 
599  switch (params.getSignerType()) {
601  try {
602  identity = m_pib->getDefaultIdentity();
603  }
604  catch (const Pib::Error&) { // no default identity, use sha256 for signing.
605  sigInfo.setSignatureType(tlv::DigestSha256);
606  NDN_LOG_TRACE("Prepared signature info: " << sigInfo);
607  return std::make_tuple(SigningInfo::getDigestSha256Identity(), sigInfo);
608  }
609  break;
610  }
612  identity = params.getPibIdentity();
613  if (!identity) {
614  try {
615  identity = m_pib->getIdentity(params.getSignerName());
616  }
617  catch (const Pib::Error&) {
618  NDN_THROW_NESTED(InvalidSigningInfoError("Signing identity `" +
619  params.getSignerName().toUri() + "` does not exist"));
620  }
621  }
622  break;
623  }
625  key = params.getPibKey();
626  if (!key) {
627  Name identityName = extractIdentityFromKeyName(params.getSignerName());
628  try {
629  key = m_pib->getIdentity(identityName).getKey(params.getSignerName());
630  }
631  catch (const Pib::Error&) {
632  NDN_THROW_NESTED(InvalidSigningInfoError("Signing key `" +
633  params.getSignerName().toUri() + "` does not exist"));
634  }
635  }
636  break;
637  }
639  Name identityName = extractIdentityFromCertName(params.getSignerName());
640  Name keyName = extractKeyNameFromCertName(params.getSignerName());
641  try {
642  identity = m_pib->getIdentity(identityName);
643  key = identity.getKey(keyName);
644  }
645  catch (const Pib::Error&) {
646  NDN_THROW_NESTED(InvalidSigningInfoError("Signing certificate `" +
647  params.getSignerName().toUri() + "` does not exist"));
648  }
649  break;
650  }
652  sigInfo.setSignatureType(tlv::DigestSha256);
653  NDN_LOG_TRACE("Prepared signature info: " << sigInfo);
654  return std::make_tuple(SigningInfo::getDigestSha256Identity(), sigInfo);
655  }
657  const Name& keyName = params.getSignerName();
658  if (!m_tpm->hasKey(keyName)) {
659  m_tpm->importPrivateKey(keyName, params.getHmacKey());
660  }
661  sigInfo.setSignatureType(getSignatureType(KeyType::HMAC, params.getDigestAlgorithm()));
662  sigInfo.setKeyLocator(keyName);
663  NDN_LOG_TRACE("Prepared signature info: " << sigInfo);
664  return std::make_tuple(keyName, sigInfo);
665  }
666  default: {
667  NDN_THROW(InvalidSigningInfoError("Unrecognized signer type " +
668  boost::lexical_cast<std::string>(params.getSignerType())));
669  }
670  }
671 
672  if (!key) {
673  if (!identity) {
674  NDN_THROW(InvalidSigningInfoError("Cannot determine signing parameters"));
675  }
676  try {
677  key = identity.getDefaultKey();
678  }
679  catch (const Pib::Error&) {
680  NDN_THROW_NESTED(InvalidSigningInfoError("Signing identity `" + identity.getName().toUri() +
681  "` does not have a default certificate"));
682  }
683  }
684 
685  BOOST_ASSERT(key);
686 
687  sigInfo.setSignatureType(getSignatureType(key.getKeyType(), params.getDigestAlgorithm()));
688  sigInfo.setKeyLocator(key.getName());
689 
690  NDN_LOG_TRACE("Prepared signature info: " << sigInfo);
691  return std::make_tuple(key.getName(), sigInfo);
692 }
693 
695 KeyChain::sign(const InputBuffers& bufs, const Name& keyName, DigestAlgorithm digestAlgorithm) const
696 {
697  using namespace transform;
698 
699  if (keyName == SigningInfo::getDigestSha256Identity()) {
700  OBufferStream os;
702  return os.buf();
703  }
704 
705  auto signature = m_tpm->sign(bufs, keyName, digestAlgorithm);
706  if (!signature) {
707  NDN_THROW(InvalidSigningInfoError("TPM signing failed for key `" + keyName.toUri() + "` "
708  "(e.g., PIB contains info about the key, but TPM is missing "
709  "the corresponding private key)"));
710  }
711 
712  return signature;
713 }
714 
716 KeyChain::getSignatureType(KeyType keyType, DigestAlgorithm)
717 {
718  switch (keyType) {
719  case KeyType::RSA:
721  case KeyType::EC:
723  case KeyType::HMAC:
725  default:
726  NDN_THROW(Error("Unsupported key type " + boost::lexical_cast<std::string>(keyType)));
727  }
728 }
729 
730 } // inline namespace v2
731 } // namespace security
732 } // namespace ndn
Represents a TLV element of the NDN packet format.
Definition: block.hpp:45
Buffer::const_iterator begin() const
Get begin iterator of encoded wire.
Definition: block.cpp:278
Buffer::const_iterator end() const
Get end iterator of encoded wire.
Definition: block.cpp:287
void encode()
Encode sub-elements into TLV-VALUE.
Definition: block.cpp:368
Represents a Data packet.
Definition: data.hpp:38
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 name.
Definition: data.hpp:127
Data & setSignatureInfo(const SignatureInfo &info)
Set SignatureInfo.
Definition: data.cpp:302
const Block & getContent() const noexcept
Get the Content element.
Definition: data.hpp:173
Represents an Interest packet.
Definition: interest.hpp:50
const Name & getName() const noexcept
Definition: interest.hpp:173
Interest & setSignatureValue(ConstBufferPtr value)
Set the InterestSignatureValue.
Definition: interest.cpp:603
InputBuffers extractSignedRanges() const
Extract ranges of Interest covered by the signature in Packet Specification v0.3.
Definition: interest.cpp:643
Interest & setName(const Name &name)
Set the Interest's name.
Definition: interest.cpp:372
Interest & setSignatureInfo(const SignatureInfo &info)
Set the InterestSignatureInfo.
Definition: interest.cpp:559
Base class for key parameters.
Definition: key-params.hpp:36
Represents an absolute name.
Definition: name.hpp:46
Name & append(const Component &component)
Append a component.
Definition: name.hpp:279
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:348
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
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:107
const Data & getCertificate() const
Get the certificate data packet from safe bag.
Definition: safe-bag.hpp:98
Signing parameters passed to KeyChain.
static const Name & getDigestSha256Identity()
A localhost identity to indicate that the signature is generated using SHA-256.
@ SIGNER_TYPE_CERT
Signer is a certificate, use it directly.
@ SIGNER_TYPE_SHA256
Use a SHA-256 digest only, no signer needs to be specified.
@ SIGNER_TYPE_HMAC
Signer is a HMAC key.
@ SIGNER_TYPE_NULL
No signer is specified, use default setting or follow the trust schema.
@ SIGNER_TYPE_ID
Signer is an identity, use its default key and default certificate.
@ SIGNER_TYPE_KEY
Signer is a key, use its default certificate.
SignedInterestFormat getSignedInterestFormat() const
DigestAlgorithm getDigestAlgorithm() const
A frontend handle of an Identity.
Definition: identity.hpp:48
const KeyContainer & getKeys() const
Get all keys for this identity.
Definition: identity.cpp:61
const Name & getName() const
Get the name of the identity.
Definition: identity.cpp:37
Key getKey(const Name &keyName) const
Get a key with id keyName.
Definition: identity.cpp:55
A frontend handle of a key instance.
Definition: key.hpp:50
const Certificate & getDefaultCertificate() const
Get the default certificate for this Key.
Definition: key.cpp:98
const Name & getIdentity() const
Get the name of the belonging identity.
Definition: key.cpp:44
span< const uint8_t > getPublicKey() const
Get public key bits.
Definition: key.cpp:56
const Name & getName() const
Get key name.
Definition: key.cpp:38
represents a semantic error
Definition: pib.hpp:57
Represents an NDN certificate following the version 2.0 format.
Definition: certificate.hpp:61
Buffer getPublicKey() const
Get public key bits (in PKCS#8 format)
Name getKeyName() const
Get key name.
Definition: certificate.cpp:81
Name getIdentity() const
Get identity name.
Definition: certificate.cpp:87
static bool isValidName(const Name &certName)
Check if the specified name follows the naming convention for the certificate.
Error indicating that the supplied TPM locator does not match the locator stored in PIB.
Definition: key-chain.hpp:58
The interface of signing key management.
Definition: key-chain.hpp:46
void setDefaultIdentity(const Identity &identity)
Set identity as the default identity.
Definition: key-chain.cpp:250
void deleteKey(const Identity &identity, const Key &key)
Delete a key key of identity.
Definition: key-chain.cpp:281
void setDefaultCertificate(const Key &key, const Certificate &certificate)
Set cert as the default certificate of key.
Definition: key-chain.cpp:341
Identity createIdentity(const Name &identityName, const KeyParams &params=getDefaultKeyParams())
Create an identity identityName.
Definition: key-chain.cpp:212
Key createKey(const Identity &identity, const KeyParams &params=getDefaultKeyParams())
Create a new key for identity.
Definition: key-chain.cpp:258
void deleteIdentity(const Identity &identity)
delete identity.
Definition: key-chain.cpp:236
static const KeyParams & getDefaultKeyParams()
Definition: key-chain.cpp:147
void sign(Data &data, const SigningInfo &params=SigningInfo())
Sign a Data packet according to the supplied signing information.
Definition: key-chain.cpp:442
void deleteCertificate(const Key &key, const Name &certificateName)
delete a certificate with name certificateName of key.
Definition: key-chain.cpp:329
void setDefaultKey(const Identity &identity, const Key &key)
Set key as the default key of identity.
Definition: key-chain.cpp:297
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:367
Name createHmacKey(const Name &prefix=SigningInfo::getHmacIdentity(), const HmacKeyParams &params=HmacKeyParams())
Create a new HMAC key.
Definition: key-chain.cpp:275
void importPrivateKey(const Name &keyName, shared_ptr< transform::PrivateKey > key)
Import a private key into the TPM.
Definition: key-chain.cpp:425
void addCertificate(const Key &key, const Certificate &certificate)
Add a certificate certificate for key.
Definition: key-chain.cpp:310
KeyChain()
Constructor to create KeyChain with default PIB and TPM.
Definition: key-chain.cpp:155
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:350
static time_point now() noexcept
Definition: time.cpp:46
time_point TimePoint
Definition: time.hpp:203
#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:450
#define NDN_CXX_KEYCHAIN_REGISTER_TPM_BACKEND(TpmType)
Register Tpm backend class in KeyChain.
Definition: key-chain.hpp:468
#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
unique_ptr< Transform > digestFilter(DigestAlgorithm algo)
unique_ptr< Sink > streamSink(std::ostream &os)
Definition: stream-sink.cpp:53
unique_ptr< Sink > boolSink(bool &value)
Definition: bool-sink.cpp:51
unique_ptr< Transform > verifierFilter(DigestAlgorithm algo, const PublicKey &key, span< const uint8_t > sig)
Name extractIdentityFromKeyName(const Name &keyName)
Extract identity namespace from the key name keyName.
Definition: key.cpp:160
Name extractKeyNameFromCertName(const Name &certName)
Extract key name from the certificate name certName.
Name extractIdentityFromCertName(const Name &certName)
Extract identity namespace from the certificate name certName.
@ V03
Sign Interest using Packet Specification v0.3 semantics.
@ ValidityPeriod
Definition: tlv.hpp:147
@ Name
Definition: tlv.hpp:67
@ SignatureInfo
Definition: tlv.hpp:82
@ SignatureValue
Definition: tlv.hpp:83
@ ContentType_Key
public key, certificate
Definition: tlv.hpp:163
SignatureTypeValue
SignatureType values.
Definition: tlv.hpp:132
@ SignatureSha256WithRsa
Definition: tlv.hpp:134
@ DigestSha256
Definition: tlv.hpp:133
@ SignatureHmacWithSha256
Definition: tlv.hpp:136
@ SignatureSha256WithEcdsa
Definition: tlv.hpp:135
Definition: data.cpp:25
shared_ptr< const Buffer > ConstBufferPtr
Definition: buffer.hpp:139
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.
InputBuffers bufs