NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.0: 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; -*- */
24 #include "key-chain.hpp"
25 
26 #include "../util/random.hpp"
27 #include "../util/config-file.hpp"
28 
30 
31 #ifdef NDN_CXX_HAVE_OSX_SECURITY
32 #include "sec-tpm-osx.hpp"
33 #endif // NDN_CXX_HAVE_OSX_SECURITY
34 
35 #include "sec-tpm-file.hpp"
36 
37 namespace ndn {
38 namespace security {
39 
40 // Use a GUID as a magic number of KeyChain::DEFAULT_PREFIX identifier
41 const Name KeyChain::DEFAULT_PREFIX("/723821fd-f534-44b3-80d9-44bf5f58bbbb");
42 const Name KeyChain::DIGEST_SHA256_IDENTITY("/localhost/identity/digest-sha256");
43 
44 // Note: cannot use default constructor, as it depends on static variables which may or may not be
45 // initialized at this point
47 
49 
50 const std::string DEFAULT_PIB_SCHEME = "pib-sqlite3";
51 
52 #if defined(NDN_CXX_HAVE_OSX_SECURITY) and defined(NDN_CXX_WITH_OSX_KEYCHAIN)
53 const std::string DEFAULT_TPM_SCHEME = "tpm-osxkeychain";
54 #else
55 const std::string DEFAULT_TPM_SCHEME = "tpm-file";
56 #endif // defined(NDN_CXX_HAVE_OSX_SECURITY) and defined(NDN_CXX_WITH_OSX_KEYCHAIN)
57 
58 // When static library is used, not everything is compiled into the resulting binary.
59 // Therefore, the following standard PIB and TPMs need to be registered here.
60 // http://stackoverflow.com/q/9459980/2150331
61 //
62 // Also, cannot use Type::SCHEME, as its value may be uninitialized
64 
65 #ifdef NDN_CXX_HAVE_OSX_SECURITY
66 NDN_CXX_KEYCHAIN_REGISTER_TPM(SecTpmOsx, "tpm-osxkeychain", "osx-keychain");
67 #endif // NDN_CXX_HAVE_OSX_SECURITY
68 
70 
71 template<class T>
72 struct Factory
73 {
74  Factory(const std::string& canonicalName, const T& create)
75  : canonicalName(canonicalName)
76  , create(create)
77  {
78  }
79 
80  std::string canonicalName;
81  T create;
82 };
85 
86 static std::map<std::string, PibFactory>&
88 {
89  static std::map<std::string, PibFactory> pibFactories;
90  return pibFactories;
91 }
92 
93 static std::map<std::string, TpmFactory>&
95 {
96  static std::map<std::string, TpmFactory> tpmFactories;
97  return tpmFactories;
98 }
99 
100 void
101 KeyChain::registerPibImpl(const std::string& canonicalName,
102  std::initializer_list<std::string> aliases,
103  KeyChain::PibCreateFunc createFunc)
104 {
105  for (const std::string& alias : aliases) {
106  getPibFactories().insert(make_pair(alias, PibFactory(canonicalName, createFunc)));
107  }
108 }
109 
110 void
111 KeyChain::registerTpmImpl(const std::string& canonicalName,
112  std::initializer_list<std::string> aliases,
113  KeyChain::TpmCreateFunc createFunc)
114 {
115  for (const std::string& alias : aliases) {
116  getTpmFactories().insert(make_pair(alias, TpmFactory(canonicalName, createFunc)));
117  }
118 }
119 
121  : m_pib(nullptr)
122  , m_tpm(nullptr)
123  , m_lastTimestamp(time::toUnixTimestamp(time::system_clock::now()))
124 {
125  ConfigFile config;
126  const ConfigFile::Parsed& parsed = config.getParsedConfiguration();
127 
128  std::string pibLocator = parsed.get<std::string>("pib", "");
129  std::string tpmLocator = parsed.get<std::string>("tpm", "");
130 
131  initialize(pibLocator, tpmLocator, false);
132 }
133 
134 KeyChain::KeyChain(const std::string& pibName,
135  const std::string& tpmName,
136  bool allowReset)
137  : m_pib(nullptr)
138  , m_tpm(nullptr)
139  , m_lastTimestamp(time::toUnixTimestamp(time::system_clock::now()))
140 {
141  initialize(pibName, tpmName, allowReset);
142 }
143 
145 {
146 }
147 
148 static inline std::tuple<std::string/*type*/, std::string/*location*/>
149 parseUri(const std::string& uri)
150 {
151  size_t pos = uri.find(':');
152  if (pos != std::string::npos) {
153  return std::make_tuple(uri.substr(0, pos),
154  uri.substr(pos + 1));
155  }
156  else {
157  return std::make_tuple(uri, "");
158  }
159 }
160 
161 std::string
163 {
164  std::string defaultPibLocator = DEFAULT_PIB_SCHEME + ":";
165  return defaultPibLocator;
166 }
167 
168 static inline std::tuple<std::string/*type*/, std::string/*location*/>
169 getCanonicalPibLocator(const std::string& pibLocator)
170 {
171  std::string pibScheme, pibLocation;
172  std::tie(pibScheme, pibLocation) = parseUri(pibLocator);
173 
174  if (pibScheme.empty()) {
175  pibScheme = DEFAULT_PIB_SCHEME;
176  }
177 
178  auto pibFactory = getPibFactories().find(pibScheme);
179  if (pibFactory == getPibFactories().end()) {
180  BOOST_THROW_EXCEPTION(KeyChain::Error("PIB scheme '" + pibScheme + "' is not supported"));
181  }
182  pibScheme = pibFactory->second.canonicalName;
183 
184  return std::make_tuple(pibScheme, pibLocation);
185 }
186 
187 unique_ptr<SecPublicInfo>
188 KeyChain::createPib(const std::string& pibLocator)
189 {
190  BOOST_ASSERT(!getPibFactories().empty());
191 
192  std::string pibScheme, pibLocation;
193  std::tie(pibScheme, pibLocation) = getCanonicalPibLocator(pibLocator);
194  auto pibFactory = getPibFactories().find(pibScheme);
195  BOOST_ASSERT(pibFactory != getPibFactories().end());
196  return pibFactory->second.create(pibLocation);
197 }
198 
199 std::string
201 {
202  std::string defaultTpmLocator = DEFAULT_TPM_SCHEME + ":";
203  return defaultTpmLocator;
204 }
205 
206 static inline std::tuple<std::string/*type*/, std::string/*location*/>
207 getCanonicalTpmLocator(const std::string& tpmLocator)
208 {
209  std::string tpmScheme, tpmLocation;
210  std::tie(tpmScheme, tpmLocation) = parseUri(tpmLocator);
211 
212  if (tpmScheme.empty()) {
213  tpmScheme = DEFAULT_TPM_SCHEME;
214  }
215  auto tpmFactory = getTpmFactories().find(tpmScheme);
216  if (tpmFactory == getTpmFactories().end()) {
217  BOOST_THROW_EXCEPTION(KeyChain::Error("TPM scheme '" + tpmScheme + "' is not supported"));
218  }
219  tpmScheme = tpmFactory->second.canonicalName;
220 
221  return std::make_tuple(tpmScheme, tpmLocation);
222 }
223 
224 unique_ptr<SecTpm>
225 KeyChain::createTpm(const std::string& tpmLocator)
226 {
227  BOOST_ASSERT(!getTpmFactories().empty());
228 
229  std::string tpmScheme, tpmLocation;
230  std::tie(tpmScheme, tpmLocation) = getCanonicalTpmLocator(tpmLocator);
231  auto tpmFactory = getTpmFactories().find(tpmScheme);
232  BOOST_ASSERT(tpmFactory != getTpmFactories().end());
233  return tpmFactory->second.create(tpmLocation);
234 }
235 
236 void
237 KeyChain::initialize(const std::string& pibLocator,
238  const std::string& tpmLocator,
239  bool allowReset)
240 {
241  // PIB Locator
242  std::string pibScheme, pibLocation;
243  std::tie(pibScheme, pibLocation) = getCanonicalPibLocator(pibLocator);
244  std::string canonicalPibLocator = pibScheme + ":" + pibLocation;
245 
246  // Create PIB
247  m_pib = createPib(canonicalPibLocator);
248 
249  // TPM Locator
250  std::string tpmScheme, tpmLocation;
251  std::tie(tpmScheme, tpmLocation) = getCanonicalTpmLocator(tpmLocator);
252  std::string canonicalTpmLocator = tpmScheme + ":" + tpmLocation;
253 
254  // Create TPM, checking that it matches to the previously associated one
255  try {
256  if (!allowReset &&
257  !m_pib->getTpmLocator().empty() && m_pib->getTpmLocator() != canonicalTpmLocator)
258  // Tpm mismatch, but we do not want to reset PIB
259  BOOST_THROW_EXCEPTION(MismatchError("TPM locator supplied does not match TPM locator in PIB: "
260  + m_pib->getTpmLocator() + " != " + canonicalTpmLocator));
261  }
262  catch (SecPublicInfo::Error&) {
263  // TPM locator is not set in PIB yet.
264  }
265 
266  // note that key mismatch may still happen if the TPM locator is initially set to a
267  // wrong one or if the PIB was shared by more than one TPMs before. This is due to the
268  // old PIB does not have TPM info, new pib should not have this problem.
269  m_tpm = createTpm(canonicalTpmLocator);
270  m_pib->setTpmLocator(canonicalTpmLocator);
271 }
272 
273 Name
274 KeyChain::createIdentity(const Name& identityName, const KeyParams& params)
275 {
276  m_pib->addIdentity(identityName);
277 
278  Name keyName;
279  try
280  {
281  keyName = m_pib->getDefaultKeyNameForIdentity(identityName);
282 
283  shared_ptr<PublicKey> key = m_pib->getPublicKey(keyName);
284 
285  if (key->getKeyType() != params.getKeyType())
286  {
287  keyName = generateKeyPair(identityName, true, params);
288  m_pib->setDefaultKeyNameForIdentity(keyName);
289  }
290  }
291  catch (SecPublicInfo::Error& e)
292  {
293  keyName = generateKeyPair(identityName, true, params);
294  m_pib->setDefaultKeyNameForIdentity(keyName);
295  }
296 
297  Name certName;
298  try
299  {
300  certName = m_pib->getDefaultCertificateNameForKey(keyName);
301  }
302  catch (SecPublicInfo::Error& e)
303  {
304  shared_ptr<IdentityCertificate> selfCert = selfSign(keyName);
305  m_pib->addCertificateAsIdentityDefault(*selfCert);
306  certName = selfCert->getName();
307  }
308 
309  return certName;
310 }
311 
312 Name
313 KeyChain::generateRsaKeyPair(const Name& identityName, bool isKsk, uint32_t keySize)
314 {
315  RsaKeyParams params(keySize);
316  return generateKeyPair(identityName, isKsk, params);
317 }
318 
319 Name
320 KeyChain::generateEcdsaKeyPair(const Name& identityName, bool isKsk, uint32_t keySize)
321 {
322  EcdsaKeyParams params(keySize);
323  return generateKeyPair(identityName, isKsk, params);
324 }
325 
326 Name
327 KeyChain::generateRsaKeyPairAsDefault(const Name& identityName, bool isKsk, uint32_t keySize)
328 {
329  RsaKeyParams params(keySize);
330 
331  Name keyName = generateKeyPair(identityName, isKsk, params);
332 
333  m_pib->setDefaultKeyNameForIdentity(keyName);
334 
335  return keyName;
336 }
337 
338 Name
339 KeyChain::generateEcdsaKeyPairAsDefault(const Name& identityName, bool isKsk, uint32_t keySize)
340 {
341  EcdsaKeyParams params(keySize);
342 
343  Name keyName = generateKeyPair(identityName, isKsk, params);
344 
345  m_pib->setDefaultKeyNameForIdentity(keyName);
346 
347  return keyName;
348 }
349 
350 
351 shared_ptr<IdentityCertificate>
353  const Name& signingIdentity,
354  const time::system_clock::TimePoint& notBefore,
355  const time::system_clock::TimePoint& notAfter,
356  const std::vector<CertificateSubjectDescription>& subjectDescription,
357  const Name& certPrefix)
358 {
359  shared_ptr<PublicKey> publicKey;
360  try
361  {
362  publicKey = m_pib->getPublicKey(keyName);
363  }
364  catch (SecPublicInfo::Error& e)
365  {
366  return shared_ptr<IdentityCertificate>();
367  }
368 
369  return prepareUnsignedIdentityCertificate(keyName, *publicKey, signingIdentity,
370  notBefore, notAfter,
371  subjectDescription, certPrefix);
372 }
373 
374 shared_ptr<IdentityCertificate>
376  const PublicKey& publicKey,
377  const Name& signingIdentity,
378  const time::system_clock::TimePoint& notBefore,
379  const time::system_clock::TimePoint& notAfter,
380  const std::vector<CertificateSubjectDescription>& subjectDescription,
381  const Name& certPrefix)
382 {
383  if (keyName.size() < 1)
384  return shared_ptr<IdentityCertificate>();
385 
386  std::string keyIdPrefix = keyName.get(-1).toUri().substr(0, 4);
387  if (keyIdPrefix != "ksk-" && keyIdPrefix != "dsk-")
388  return shared_ptr<IdentityCertificate>();
389 
390  shared_ptr<IdentityCertificate> certificate = make_shared<IdentityCertificate>();
391  Name certName;
392 
393  if (certPrefix == KeyChain::DEFAULT_PREFIX)
394  {
395  // No certificate prefix hint, infer the prefix
396  if (signingIdentity.isPrefixOf(keyName))
397  certName.append(signingIdentity)
398  .append("KEY")
399  .append(keyName.getSubName(signingIdentity.size()))
400  .append("ID-CERT")
401  .appendVersion();
402  else
403  certName.append(keyName.getPrefix(-1))
404  .append("KEY")
405  .append(keyName.get(-1))
406  .append("ID-CERT")
407  .appendVersion();
408  }
409  else
410  {
411  // cert prefix hint is supplied, determine the cert name.
412  if (certPrefix.isPrefixOf(keyName) && certPrefix != keyName)
413  certName.append(certPrefix)
414  .append("KEY")
415  .append(keyName.getSubName(certPrefix.size()))
416  .append("ID-CERT")
417  .appendVersion();
418  else
419  return shared_ptr<IdentityCertificate>();
420  }
421 
422 
423  certificate->setName(certName);
424  certificate->setNotBefore(notBefore);
425  certificate->setNotAfter(notAfter);
426  certificate->setPublicKeyInfo(publicKey);
427 
428  if (subjectDescription.empty())
429  {
431  certificate->addSubjectDescription(subjectName);
432  }
433  else
434  {
435  std::vector<CertificateSubjectDescription>::const_iterator sdIt =
436  subjectDescription.begin();
437  std::vector<CertificateSubjectDescription>::const_iterator sdEnd =
438  subjectDescription.end();
439  for(; sdIt != sdEnd; sdIt++)
440  certificate->addSubjectDescription(*sdIt);
441  }
442 
443  certificate->encode();
444 
445  return certificate;
446 }
447 
448 std::tuple<Name, SignatureInfo>
449 KeyChain::prepareSignatureInfo(const SigningInfo& params)
450 {
451  SignatureInfo sigInfo = params.getSignatureInfo();
452 
453  shared_ptr<IdentityCertificate> signingCert;
454 
455  switch (params.getSignerType()) {
457  {
458  if (m_pib->getDefaultCertificate() == nullptr)
459  setDefaultCertificateInternal();
460 
461  signingCert = m_pib->getDefaultCertificate();
462  break;
463  }
465  {
466  Name signingCertName;
467  try {
468  signingCertName = m_pib->getDefaultCertificateNameForIdentity(params.getSignerName());
469  }
470  catch (SecPublicInfo::Error&) {
471  signingCertName = createIdentity(params.getSignerName());
472  }
473 
474  signingCert = m_pib->getCertificate(signingCertName);
475 
476  break;
477  }
479  {
480  Name signingCertName;
481  try {
482  signingCertName = m_pib->getDefaultCertificateNameForKey(params.getSignerName());
483  }
484  catch (SecPublicInfo::Error&) {
485  BOOST_THROW_EXCEPTION(Error("signing certificate does not exist"));
486  }
487 
488  signingCert = m_pib->getCertificate(signingCertName);
489 
490  break;
491  }
493  {
494  signingCert = m_pib->getCertificate(params.getSignerName());
495  if (signingCert == nullptr)
496  BOOST_THROW_EXCEPTION(Error("signing certificate does not exist"));
497 
498  break;
499  }
501  {
503  return std::make_tuple(DIGEST_SHA256_IDENTITY, sigInfo);
504  }
505  default:
506  BOOST_THROW_EXCEPTION(Error("Unrecognized signer type"));
507  }
508 
509  sigInfo.setSignatureType(getSignatureType(signingCert->getPublicKeyInfo().getKeyType(),
510  params.getDigestAlgorithm()));
511  sigInfo.setKeyLocator(KeyLocator(signingCert->getName().getPrefix(-1)));
512 
513  return std::make_tuple(signingCert->getPublicKeyName(), sigInfo);
514 }
515 
516 void
517 KeyChain::sign(Data& data, const SigningInfo& params)
518 {
519  signImpl(data, params);
520 }
521 
522 void
523 KeyChain::sign(Interest& interest, const SigningInfo& params)
524 {
525  signImpl(interest, params);
526 }
527 
528 Block
529 KeyChain::sign(const uint8_t* buffer, size_t bufferLength, const SigningInfo& params)
530 {
531  Name keyName;
532  SignatureInfo sigInfo;
533  std::tie(keyName, sigInfo) = prepareSignatureInfo(params);
534  return pureSign(buffer, bufferLength, keyName, DIGEST_ALGORITHM_SHA256);
535 }
536 
537 Signature
538 KeyChain::sign(const uint8_t* buffer, size_t bufferLength, const Name& certificateName)
539 {
540  shared_ptr<IdentityCertificate> certificate = m_pib->getCertificate(certificateName);
541 
542  if (certificate == nullptr)
543  BOOST_THROW_EXCEPTION(SecPublicInfo::Error("certificate does not exist"));
544 
545  Signature sig;
546 
547  // For temporary usage, we support SHA256 only, but will support more.
548  sig.setValue(m_tpm->signInTpm(buffer, bufferLength,
549  certificate->getPublicKeyName(),
551 
552  return sig;
553 }
554 
555 shared_ptr<IdentityCertificate>
556 KeyChain::selfSign(const Name& keyName)
557 {
558  shared_ptr<PublicKey> pubKey;
559  try {
560  pubKey = m_pib->getPublicKey(keyName); // may throw an exception.
561  }
562  catch (SecPublicInfo::Error&) {
563  return shared_ptr<IdentityCertificate>();
564  }
565 
566  auto certificate = make_shared<IdentityCertificate>();
567 
568  Name certificateName = keyName.getPrefix(-1);
569  certificateName.append("KEY").append(keyName.get(-1)).append("ID-CERT").appendVersion();
570 
571  certificate->setName(certificateName);
572  certificate->setNotBefore(time::system_clock::now());
573  certificate->setNotAfter(time::system_clock::now() + time::days(7300)); // ~20 years
574  certificate->setPublicKeyInfo(*pubKey);
575  certificate->addSubjectDescription(CertificateSubjectDescription(oid::ATTRIBUTE_NAME,
576  keyName.toUri()));
577  certificate->encode();
578 
579  certificate->setSignature(Signature(SignatureInfo()));
580 
581  selfSign(*certificate);
582  return certificate;
583 }
584 
585 void
587 {
588  Name keyName = cert.getPublicKeyName();
589  if (!m_tpm->doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE))
590  BOOST_THROW_EXCEPTION(SecTpm::Error("Private key does not exist"));
591 
592  SignatureInfo sigInfo(cert.getSignature().getInfo());
593  sigInfo.setKeyLocator(KeyLocator(cert.getName().getPrefix(-1)));
594  sigInfo.setSignatureType(getSignatureType(cert.getPublicKeyInfo().getKeyType(),
596 
597  signPacketWrapper(cert, Signature(sigInfo), keyName, DIGEST_ALGORITHM_SHA256);
598 }
599 
600 shared_ptr<SecuredBag>
601 KeyChain::exportIdentity(const Name& identity, const std::string& passwordStr)
602 {
603  if (!m_pib->doesIdentityExist(identity))
604  BOOST_THROW_EXCEPTION(SecPublicInfo::Error("Identity does not exist"));
605 
606  Name keyName = m_pib->getDefaultKeyNameForIdentity(identity);
607 
608  ConstBufferPtr pkcs5;
609  try
610  {
611  pkcs5 = m_tpm->exportPrivateKeyPkcs5FromTpm(keyName, passwordStr);
612  }
613  catch (SecTpm::Error& e)
614  {
615  BOOST_THROW_EXCEPTION(SecPublicInfo::Error("Fail to export PKCS5 of private key"));
616  }
617 
618  shared_ptr<IdentityCertificate> cert;
619  try
620  {
621  cert = m_pib->getCertificate(m_pib->getDefaultCertificateNameForKey(keyName));
622  }
623  catch (SecPublicInfo::Error& e)
624  {
625  cert = selfSign(keyName);
626  m_pib->addCertificateAsIdentityDefault(*cert);
627  }
628 
629  // make_shared on OSX 10.9 has some strange problem here
630  shared_ptr<SecuredBag> secureBag(new SecuredBag(*cert, pkcs5));
631 
632  return secureBag;
633 }
634 
635 void
636 KeyChain::importIdentity(const SecuredBag& securedBag, const std::string& passwordStr)
637 {
638  Name certificateName = securedBag.getCertificate().getName();
640  Name identity = keyName.getPrefix(-1);
641 
642  // Add identity
643  m_pib->addIdentity(identity);
644 
645  // Add key
646  m_tpm->importPrivateKeyPkcs5IntoTpm(keyName,
647  securedBag.getKey()->buf(),
648  securedBag.getKey()->size(),
649  passwordStr);
650 
651  shared_ptr<PublicKey> pubKey = m_tpm->getPublicKeyFromTpm(keyName.toUri());
652  // HACK! We should set key type according to the pkcs8 info.
653  m_pib->addKey(keyName, *pubKey);
654  m_pib->setDefaultKeyNameForIdentity(keyName);
655 
656  // Add cert
657  m_pib->addCertificateAsIdentityDefault(securedBag.getCertificate());
658 }
659 
660 void
661 KeyChain::setDefaultCertificateInternal()
662 {
663  m_pib->refreshDefaultCertificate();
664 
665  if (!static_cast<bool>(m_pib->getDefaultCertificate()))
666  {
667  Name defaultIdentity;
668  try
669  {
670  defaultIdentity = m_pib->getDefaultIdentity();
671  }
672  catch (SecPublicInfo::Error& e)
673  {
674  uint32_t random = random::generateWord32();
675  defaultIdentity.append("tmp-identity")
676  .append(reinterpret_cast<uint8_t*>(&random), 4);
677  }
678  createIdentity(defaultIdentity);
679  m_pib->setDefaultIdentity(defaultIdentity);
680  m_pib->refreshDefaultCertificate();
681  }
682 }
683 
684 Name
685 KeyChain::generateKeyPair(const Name& identityName, bool isKsk, const KeyParams& params)
686 {
687  Name keyName = m_pib->getNewKeyName(identityName, isKsk);
688 
689  m_tpm->generateKeyPairInTpm(keyName.toUri(), params);
690 
691  shared_ptr<PublicKey> pubKey = m_tpm->getPublicKeyFromTpm(keyName.toUri());
692  m_pib->addKey(keyName, *pubKey);
693 
694  return keyName;
695 }
696 
697 void
698 KeyChain::signPacketWrapper(Data& data, const Signature& signature,
699  const Name& keyName, DigestAlgorithm digestAlgorithm)
700 {
701  data.setSignature(signature);
702 
703  EncodingBuffer encoder;
704  data.wireEncode(encoder, true);
705 
706  Block sigValue = pureSign(encoder.buf(), encoder.size(), keyName, digestAlgorithm);
707 
708  data.wireEncode(encoder, sigValue);
709 }
710 
711 void
712 KeyChain::signPacketWrapper(Interest& interest, const Signature& signature,
713  const Name& keyName, DigestAlgorithm digestAlgorithm)
714 {
715  time::milliseconds timestamp = time::toUnixTimestamp(time::system_clock::now());
716  if (timestamp <= m_lastTimestamp)
717  {
718  timestamp = m_lastTimestamp + time::milliseconds(1);
719  }
720 
721  Name signedName = interest.getName();
722  signedName
723  .append(name::Component::fromNumber(timestamp.count())) // timestamp
725  .append(signature.getInfo()); // signatureInfo
726 
727  Block sigValue = pureSign(signedName.wireEncode().value(),
728  signedName.wireEncode().value_size(),
729  keyName,
730  digestAlgorithm);
731 
732  sigValue.encode();
733  signedName.append(sigValue); // signatureValue
734  interest.setName(signedName);
735 }
736 
737 Block
738 KeyChain::pureSign(const uint8_t* buf, size_t size,
739  const Name& keyName, DigestAlgorithm digestAlgorithm) const
740 {
741  if (keyName == DIGEST_SHA256_IDENTITY)
742  return Block(tlv::SignatureValue, crypto::sha256(buf, size));
743 
744  return m_tpm->signInTpm(buf, size, keyName, digestAlgorithm);
745 }
746 
747 Signature
748 KeyChain::signByIdentity(const uint8_t* buffer, size_t bufferLength, const Name& identityName)
749 {
750  Name signingCertificateName;
751  try
752  {
753  signingCertificateName = m_pib->getDefaultCertificateNameForIdentity(identityName);
754  }
755  catch (SecPublicInfo::Error& e)
756  {
757  signingCertificateName = createIdentity(identityName);
758  // Ideally, no exception will be thrown out, unless something goes wrong in the TPM, which
759  // is a fatal error.
760  }
761 
762  // We either get or create the signing certificate, sign data! (no exception unless fatal error
763  // in TPM)
764  Signature sig;
765 
766  // For temporary usage, we support SHA256 only, but will support more.
767  sig.setValue(sign(buffer, bufferLength, SigningInfo(SigningInfo::SIGNER_TYPE_CERT,
768  signingCertificateName)));
769 
770  return sig;
771 }
772 
773 void
775 {
776  DigestSha256 sig;
777  data.setSignature(sig);
778 
779  Block sigValue(tlv::SignatureValue,
780  crypto::sha256(data.wireEncode().value(),
781  data.wireEncode().value_size() -
782  data.getSignature().getValue().size()));
783  data.setSignatureValue(sigValue);
784 }
785 
786 void
788 {
789  DigestSha256 sig;
790 
791  time::milliseconds timestamp = time::toUnixTimestamp(time::system_clock::now());
792  if (timestamp <= m_lastTimestamp)
793  timestamp = m_lastTimestamp + time::milliseconds(1);
794 
795  Name signedName = interest.getName();
796  signedName
797  .append(name::Component::fromNumber(timestamp.count())) // timestamp
799  .append(sig.getInfo()); // signatureInfo
800 
801  Block sigValue(tlv::SignatureValue,
802  crypto::sha256(signedName.wireEncode().value(),
803  signedName.wireEncode().value_size()));
804 
805  sigValue.encode();
806  signedName.append(sigValue); // signatureValue
807  interest.setName(signedName);
808 }
809 
810 void
811 KeyChain::deleteCertificate(const Name& certificateName)
812 {
813  m_pib->deleteCertificateInfo(certificateName);
814 }
815 
816 void
817 KeyChain::deleteKey(const Name& keyName)
818 {
819  m_pib->deletePublicKeyInfo(keyName);
820  m_tpm->deleteKeyPairInTpm(keyName);
821 }
822 
823 void
825 {
826  std::vector<Name> keyNames;
827  m_pib->getAllKeyNamesOfIdentity(identity, keyNames, true);
828  m_pib->getAllKeyNamesOfIdentity(identity, keyNames, false);
829 
830  m_pib->deleteIdentityInfo(identity);
831 
832  for (const auto& keyName : keyNames)
833  m_tpm->deleteKeyPairInTpm(keyName);
834 }
835 
838 {
839  switch (keyType) {
840  case KEY_TYPE_RSA:
842  case KEY_TYPE_ECDSA:
844  default:
845  BOOST_THROW_EXCEPTION(Error("Unsupported key types"));
846  }
847 
848 }
849 
850 } // namespace security
851 } // namespace ndn
Factory< KeyChain::PibCreateFunc > PibFactory
Definition: key-chain.cpp:83
static const RsaKeyParams DEFAULT_KEY_PARAMS
Definition: key-chain.hpp:874
static std::tuple< std::string, std::string > getCanonicalTpmLocator(const std::string &tpmLocator)
Definition: key-chain.cpp:207
static Component fromNumber(uint64_t number)
Create a component encoded as nonNegativeInteger.
shared_ptr< IdentityCertificate > prepareUnsignedIdentityCertificate(const Name &keyName, const Name &signingIdentity, const time::system_clock::TimePoint &notBefore, const time::system_clock::TimePoint &notAfter, const std::vector< CertificateSubjectDescription > &subjectDescription, const Name &certPrefix=DEFAULT_PREFIX)
prepare an unsigned identity certificate
Definition: key-chain.cpp:352
const Name & getName() const
Definition: interest.hpp:216
static std::map< std::string, PibFactory > & getPibFactories()
Definition: key-chain.cpp:87
Copyright (c) 2011-2015 Regents of the University of California.
void setSignatureType(tlv::SignatureTypeValue type)
Set SignatureType.
function< unique_ptr< SecPublicInfo >const std::string &)> PibCreateFunc
Definition: key-chain.hpp:75
SimplePublicKeyParams< RsaKeyParamsInfo > RsaKeyParams
RsaKeyParams carries parameters for RSA key.
Definition: key-params.hpp:158
Data & setSignature(const Signature &signature)
Set the signature to a copy of the given signature.
Definition: data.cpp:275
A CertificateSubjectDescription represents the SubjectDescription entry in a Certificate.
KeyType getKeyType() const
Definition: key-params.hpp:54
void importIdentity(const SecuredBag &securedBag, const std::string &passwordStr)
import an identity.
Definition: key-chain.cpp:636
const std::string DEFAULT_TPM_SCHEME
Definition: key-chain.cpp:55
static unique_ptr< SecPublicInfo > createPib(const std::string &pibLocator)
Create a PIB according to pibLocator.
Definition: key-chain.cpp:188
const Name & getSignerName() const
ConstBufferPtr getKey() const
Definition: secured-bag.hpp:67
Represent a SHA256 digest.
void signByIdentity(T &packet, const Name &identityName)
Sign packet using the default certificate of a particular identity.
Definition: key-chain.hpp:905
const Parsed & getParsedConfiguration() const
static Name certificateNameToPublicKeyName(const Name &certificateName)
Get the public key name from the full certificate name.
Error thrown when the supplied TPM locator to KeyChain constructor does not match the locator stored ...
Definition: key-chain.hpp:65
size_t wireEncode(EncodingImpl< TAG > &encoder) const
Fast encoding or block size estimation.
Definition: name.cpp:69
Class representing a wire element of NDN-TLV packet format.
Definition: block.hpp:43
represents an Interest packet
Definition: interest.hpp:45
const Block & getValue() const
Get SignatureValue in the wire format.
Definition: signature.hpp:96
use sha256 digest, no signer needs to be specified
void sign(Data &data, const SigningInfo &params=DEFAULT_SIGNING_INFO)
Sign data according to the supplied signing information.
Definition: key-chain.cpp:517
static time_point now() noexcept
Definition: time.cpp:45
Signing parameters passed to KeyChain.
shared_ptr< SecuredBag > exportIdentity(const Name &identity, const std::string &passwordStr)
export an identity.
Definition: key-chain.cpp:601
PublicKey & getPublicKeyInfo()
const OID ATTRIBUTE_NAME("2.5.4.41")
Definition: oid.hpp:105
Factory< KeyChain::TpmCreateFunc > TpmFactory
Definition: key-chain.cpp:84
const Name & getName() const
Get name of the Data packet.
Definition: data.hpp:343
size_t size() const
Definition: block.cpp:504
void setKeyLocator(const KeyLocator &keyLocator)
Set KeyLocator.
std::string toUri() const
Encode this name as a URI.
Definition: name.cpp:183
uint32_t generateWord32()
Generate a cryptographically non-secure random integer from the range [0, 2^32)
Definition: random.cpp:73
size_t wireEncode(EncodingImpl< TAG > &encoder, bool wantUnsignedPortionOnly=false) const
Fast encoding or block size estimation.
Definition: data.cpp:52
Data & setSignatureValue(const Block &value)
Definition: data.cpp:284
static std::tuple< std::string, std::string > getCanonicalPibLocator(const std::string &pibLocator)
Definition: key-chain.cpp:169
static const SigningInfo DEFAULT_SIGNING_INFO
Definition: key-chain.hpp:865
EncodingImpl< EncoderTag > EncodingBuffer
void setValue(const Block &value)
Get SignatureValue from a block.
Definition: signature.cpp:50
Interest & setName(const Name &name)
Definition: interest.hpp:222
boost::property_tree::ptree Parsed
Definition: config-file.hpp:48
no signer is specified, use default setting or follow the trust schema
Name createIdentity(const Name &identityName, const KeyParams &params=DEFAULT_KEY_PARAMS)
Create an identity by creating a pair of Key-Signing-Key (KSK) for this identity and a self-signed ce...
Definition: key-chain.cpp:274
void toUri(std::ostream &os) const
Write *this to the output stream, escaping characters according to the NDN URI Scheme.
function< unique_ptr< SecTpm >const std::string &)> TpmCreateFunc
Definition: key-chain.hpp:76
const SignatureInfo & getSignatureInfo() const
static std::string getDefaultTpmLocator()
Get default TPM locator.
Definition: key-chain.cpp:200
KeyType getKeyType() const
Definition: public-key.hpp:83
size_t size() const
Get the number of components.
Definition: name.hpp:408
Name abstraction to represent an absolute name.
Definition: name.hpp:46
signer is a certificate, use it directly
const Name & getPublicKeyName() const
Factory(const std::string &canonicalName, const T &create)
Definition: key-chain.cpp:74
void deleteIdentity(const Name &identity)
delete an identity.
Definition: key-chain.cpp:824
signer is a key, use its default certificate
time_point TimePoint
Definition: time.hpp:78
const Signature & getSignature() const
Definition: data.hpp:373
Name generateRsaKeyPair(const Name &identityName, bool isKsk=false, uint32_t keySize=2048)
Generate a pair of RSA keys for the specified identity.
Definition: key-chain.cpp:313
static tlv::SignatureTypeValue getSignatureType(KeyType keyType, DigestAlgorithm digestAlgorithm)
Definition: key-chain.cpp:837
KeyChain()
Constructor to create KeyChain with default PIB and TPM.
Definition: key-chain.cpp:120
uint64_t generateWord64()
Generate a cryptographically non-secure random integer from range [0, 2^64)
Definition: random.cpp:80
static unique_ptr< SecTpm > createTpm(const std::string &tpmLocator)
Create a TPM according to tpmLocator.
Definition: key-chain.cpp:225
static std::string getDefaultPibLocator()
Get default PIB locator.
Definition: key-chain.cpp:162
const std::string DEFAULT_PIB_SCHEME
Definition: key-chain.cpp:50
const Block & getInfo() const
Get SignatureInfo in the wire format.
Definition: signature.hpp:70
void encode()
Encode subblocks into wire buffer.
Definition: block.cpp:355
milliseconds toUnixTimestamp(const system_clock::TimePoint &point)
Convert system_clock::TimePoint to UNIX timestamp.
Definition: time.cpp:118
const IdentityCertificate & getCertificate() const
Definition: secured-bag.hpp:61
static std::tuple< std::string, std::string > parseUri(const std::string &uri)
Definition: key-chain.cpp:149
SignatureTypeValue
Definition: tlv.hpp:95
Name & append(const uint8_t *value, size_t valueLength)
Append a new component, copying from value of length valueLength.
Definition: name.hpp:148
shared_ptr< IdentityCertificate > selfSign(const Name &keyName)
Generate a self-signed certificate for a public key.
Definition: key-chain.cpp:556
Base class of key parameters.
Definition: key-params.hpp:35
bool isPrefixOf(const Name &name) const
Check if the N components of this name are the same as the first N components of the given name...
Definition: name.cpp:320
signer is an identity, use its default key and default certificate
PartialName getSubName(ssize_t iStartComponent, size_t nComponents=npos) const
Extract a sub-name (PartialName) of nComponents components starting from iStartComponent.
Definition: name.cpp:274
Name generateEcdsaKeyPair(const Name &identityName, bool isKsk=false, uint32_t keySize=256)
Generate a pair of ECDSA keys for the specified identity.
Definition: key-chain.cpp:320
PartialName getPrefix(ssize_t nComponents) const
Extract a prefix (PartialName) of the name, containing first nComponents components.
Definition: name.hpp:249
#define NDN_CXX_KEYCHAIN_REGISTER_TPM(TpmType,...)
Register SecTpm class in ndn-cxx KeyChain.
Definition: key-chain.hpp:950
static const Name DEFAULT_PREFIX
Definition: key-chain.hpp:864
void signWithSha256(Data &data)
Set Sha256 weak signature for data.
Definition: key-chain.cpp:774
shared_ptr< const Buffer > ConstBufferPtr
Definition: buffer.hpp:33
ConstBufferPtr sha256(const uint8_t *data, size_t dataLength)
Compute the sha-256 digest of data.
Definition: crypto.cpp:51
Name generateEcdsaKeyPairAsDefault(const Name &identityName, bool isKsk, uint32_t keySize=256)
Generate a pair of ECDSA keys for the specified identity and set it as default key for the identity...
Definition: key-chain.cpp:339
represents a Data packet
Definition: data.hpp:39
SimplePublicKeyParams is a template for public keys with only one parameter: size.
Definition: key-params.hpp:110
DigestAlgorithm getDigestAlgorithm() const
Name generateRsaKeyPairAsDefault(const Name &identityName, bool isKsk=false, uint32_t keySize=2048)
Generate a pair of RSA keys for the specified identity and set it as default key for the identity...
Definition: key-chain.cpp:327
static const Name DIGEST_SHA256_IDENTITY
A localhost identity which indicates that signature is generated using SHA-256.
Definition: key-chain.hpp:871
#define NDN_CXX_KEYCHAIN_REGISTER_PIB(PibType,...)
Register SecPib class in ndn-cxx KeyChain.
Definition: key-chain.hpp:934
void deleteKey(const Name &keyName)
delete a key.
Definition: key-chain.cpp:817
const Component & get(ssize_t i) const
Get the component at the given index.
Definition: name.hpp:419
SignerType getSignerType() const
void deleteCertificate(const Name &certificateName)
delete a certificate.
Definition: key-chain.cpp:811
duration< boost::int_least32_t, boost::ratio< 86400 > > days
Definition: time.hpp:35
Name & appendVersion(uint64_t version)
Append version using NDN naming conventions.
Definition: name.cpp:218
static std::map< std::string, TpmFactory > & getTpmFactories()
Definition: key-chain.cpp:94
std::string canonicalName
Definition: key-chain.cpp:80
A Signature is storage for the signature-related information (info and value) in a Data packet...
Definition: signature.hpp:33