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