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