All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
key-chain.hpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
9 #ifndef NDN_SECURITY_KEY_CHAIN_HPP
10 #define NDN_SECURITY_KEY_CHAIN_HPP
11 
12 #include "identity-certificate.hpp"
13 #include "public-key.hpp"
15 #include "signature-sha256.hpp"
16 #include "secured-bag.hpp"
17 #include "../interest.hpp"
18 #include "../util/random.hpp"
19 #include "../util/crypto.hpp"
20 
21 //PublicInfo
24 //TPM
25 #include "sec-tpm-file.hpp"
26 #include "sec-tpm-memory.hpp"
27 
28 #ifdef NDN_CPP_HAVE_OSX_SECURITY
29 #include "sec-tpm-osx.hpp"
30 #endif
31 
32 
33 namespace ndn {
34 
41 template<class Info, class Tpm>
42 class KeyChainImpl : public Info, public Tpm
43 {
45  typedef SecTpm::Error TpmError;
46 public:
54  Name
55  createIdentity(const Name& identityName)
56  {
57  Info::addIdentity(identityName);
58 
59  Name keyName;
60  try
61  {
62  keyName = Info::getDefaultKeyNameForIdentity(identityName);
63  }
64  catch (InfoError& e)
65  {
66  keyName = generateRSAKeyPairAsDefault(identityName, true);
67  }
68 
69  Name certName;
70  try
71  {
72  certName = Info::getDefaultCertificateNameForKey(keyName);
73  }
74  catch (InfoError& e)
75  {
76  shared_ptr<IdentityCertificate> selfCert = selfSign(keyName);
77  Info::addCertificateAsIdentityDefault(*selfCert);
78  certName = selfCert->getName();
79  }
80 
81  return certName;
82  }
83 
92  Name
93  generateRSAKeyPair(const Name& identityName, bool isKsk = false, int keySize = 2048)
94  {
95  return generateKeyPair(identityName, isKsk, KEY_TYPE_RSA, keySize);
96  }
97 
107  Name
108  generateRSAKeyPairAsDefault(const Name& identityName, bool isKsk = false, int keySize = 2048)
109  {
110  Name keyName = generateKeyPair(identityName, isKsk, KEY_TYPE_RSA, keySize);
111 
112  Info::setDefaultKeyNameForIdentity(keyName);
113 
114  return keyName;
115  }
116 
127  shared_ptr<IdentityCertificate>
129  const Name& signingIdentity,
130  const time::system_clock::TimePoint& notBefore,
131  const time::system_clock::TimePoint& notAfter,
132  const std::vector<CertificateSubjectDescription>& subjectDescription)
133 
134  {
135  if (keyName.size() < 1)
136  return shared_ptr<IdentityCertificate>();
137 
138  std::string keyIdPrefix = keyName.get(-1).toEscapedString().substr(0, 4);
139  if (keyIdPrefix != "ksk-" && keyIdPrefix != "dsk-")
140  return shared_ptr<IdentityCertificate>();
141 
142  shared_ptr<IdentityCertificate> certificate = make_shared<IdentityCertificate>();
143  Name certName;
144 
145  if (signingIdentity.isPrefixOf(keyName))
146  {
147  certName.append(signingIdentity)
148  .append("KEY")
149  .append(keyName.getSubName(signingIdentity.size()))
150  .append("ID-CERT")
151  .appendVersion();
152  }
153  else
154  {
155  certName.append(keyName.getPrefix(-1))
156  .append("KEY")
157  .append(keyName.get(-1))
158  .append("ID-CERT")
159  .appendVersion();
160  }
161 
162  certificate->setName(certName);
163  certificate->setNotBefore(notBefore);
164  certificate->setNotAfter(notAfter);
165 
166  shared_ptr<PublicKey> publicKey;
167  try
168  {
169  publicKey = Info::getPublicKey(keyName);
170  }
171  catch (InfoError& e)
172  {
173  return shared_ptr<IdentityCertificate>();
174  }
175  certificate->setPublicKeyInfo(*publicKey);
176 
177  if (subjectDescription.empty())
178  {
179  CertificateSubjectDescription subDescryptName("2.5.4.41", keyName.getPrefix(-1).toUri());
180  certificate->addSubjectDescription(subDescryptName);
181  }
182  else
183  {
184  std::vector<CertificateSubjectDescription>::const_iterator sdIt =
185  subjectDescription.begin();
186  std::vector<CertificateSubjectDescription>::const_iterator sdEnd =
187  subjectDescription.end();
188  for(; sdIt != sdEnd; sdIt++)
189  certificate->addSubjectDescription(*sdIt);
190  }
191 
192  certificate->encode();
193 
194  return certificate;
195  }
196 
206  template<typename T>
207  void
208  sign(T& packet)
209  {
210  if (!static_cast<bool>(Info::defaultCertificate()))
211  {
212  Info::refreshDefaultCertificate();
213 
214  if (!static_cast<bool>(Info::defaultCertificate()))
215  {
216  Name defaultIdentity;
217  try
218  {
219  defaultIdentity = Info::getDefaultIdentity();
220  }
221  catch (InfoError& e)
222  {
223  uint32_t random = random::generateWord32();
224  defaultIdentity.append("tmp-identity")
225  .append(reinterpret_cast<uint8_t*>(&random), 4);
226  }
227  createIdentity(defaultIdentity);
228  Info::setDefaultIdentity(defaultIdentity);
229  Info::refreshDefaultCertificate();
230  }
231  }
232 
233  sign(packet, *Info::defaultCertificate());
234  }
235 
243  template<typename T>
244  void
245  sign(T& packet, const Name& certificateName)
246  {
247  if (!Info::doesCertificateExist(certificateName))
248  throw InfoError("Requested certificate [" + certificateName.toUri() + "] doesn't exist");
249 
250  SignatureSha256WithRsa signature;
251  // implicit conversion should take care
252  signature.setKeyLocator(certificateName.getPrefix(-1));
253 
254  // For temporary usage, we support RSA + SHA256 only, but will support more.
255  signPacketWrapper(packet, signature,
258  }
259 
269  Signature
270  sign(const uint8_t* buffer, size_t bufferLength, const Name& certificateName)
271  {
272  if (!Info::doesCertificateExist(certificateName))
273  throw InfoError("Requested certificate [" + certificateName.toUri() + "] doesn't exist");
274 
276 
277  SignatureSha256WithRsa signature;
278  // implicit conversion should take care
279  signature.setKeyLocator(certificateName.getPrefix(-1));
280 
281  // For temporary usage, we support RSA + SHA256 only, but will support more.
282  signature.setValue(Tpm::signInTpm(buffer, bufferLength, keyName, DIGEST_ALGORITHM_SHA256));
283  return signature;
284  }
285 
295  template<typename T>
296  void
297  signByIdentity(T& packet, const Name& identityName)
298  {
299  Name signingCertificateName;
300  try
301  {
302  signingCertificateName = Info::getDefaultCertificateNameForIdentity(identityName);
303  }
304  catch (InfoError& e)
305  {
306  signingCertificateName = createIdentity(identityName);
307  // Ideally, no exception will be thrown out, unless something goes wrong in the TPM, which
308  // is a fatal error.
309  }
310 
311  // We either get or create the signing certificate, sign packet! (no exception unless fatal
312  // error in TPM)
313  sign(packet, signingCertificateName);
314  }
315 
324  Signature
325  signByIdentity(const uint8_t* buffer, size_t bufferLength, const Name& identityName)
326  {
327  Name signingCertificateName;
328  try
329  {
330  signingCertificateName = Info::getDefaultCertificateNameForIdentity(identityName);
331  }
332  catch (InfoError& e)
333  {
334  signingCertificateName = createIdentity(identityName);
335  // Ideally, no exception will be thrown out, unless something goes wrong in the TPM, which
336  // is a fatal error.
337  }
338 
339  // We either get or create the signing certificate, sign data! (no exception unless fatal error
340  // in TPM)
341  return sign(buffer, bufferLength, signingCertificateName);
342  }
343 
349  void
351  {
352  SignatureSha256 sig;
353  data.setSignature(sig);
354 
355  Block sigValue(Tlv::SignatureValue,
356  crypto::sha256(data.wireEncode().value(),
357  data.wireEncode().value_size() -
358  data.getSignature().getValue().size()));
359  data.setSignatureValue(sigValue);
360  }
361 
368  shared_ptr<IdentityCertificate>
369  selfSign(const Name& keyName)
370  {
371  shared_ptr<PublicKey> pubKey;
372  try
373  {
374  pubKey = Info::getPublicKey(keyName); // may throw an exception.
375  }
376  catch (InfoError& e)
377  {
378  return shared_ptr<IdentityCertificate>();
379  }
380 
381  shared_ptr<IdentityCertificate> certificate = make_shared<IdentityCertificate>();
382 
383  Name certificateName = keyName.getPrefix(-1);
384  certificateName.append("KEY").append(keyName.get(-1)).append("ID-CERT").appendVersion();
385 
386  certificate->setName(certificateName);
387  certificate->setNotBefore(time::system_clock::now());
388  certificate->setNotAfter(time::system_clock::now() + time::days(7300)/* ~20 years*/);
389  certificate->setPublicKeyInfo(*pubKey);
390  certificate->addSubjectDescription(CertificateSubjectDescription("2.5.4.41", keyName.toUri()));
391  certificate->encode();
392 
393  selfSign(*certificate);
394  return certificate;
395  }
396 
403  void
405  {
407  if (!Tpm::doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE))
408  throw TpmError("private key does not exist!");
409 
410  SignatureSha256WithRsa signature;
411  signature.setKeyLocator(cert.getName().getPrefix(-1)); // implicit conversion should take care
412 
413  // For temporary usage, we support RSA + SHA256 only, but will support more.
414  signPacketWrapper(cert, signature, keyName, DIGEST_ALGORITHM_SHA256);
415  }
416 
425  void
426  deleteCertificate (const Name& certificateName)
427  {
428  try
429  {
430  if (Info::getDefaultCertificateName() == certificateName)
431  return;
432  }
433  catch (InfoError& e)
434  {
435  // Not a real error, just try to delete the certificate
436  }
437 
438  Info::deleteCertificateInfo(certificateName);
439  }
440 
449  void
450  deleteKey (const Name& keyName)
451  {
452  try
453  {
454  if (Info::getDefaultKeyNameForIdentity(Info::getDefaultIdentity()) == keyName)
455  return;
456  }
457  catch (InfoError& e)
458  {
459  // Not a real error, just try to delete the key
460  }
461 
462  Info::deletePublicKeyInfo(keyName);
463  Tpm::deleteKeyPairInTpm(keyName);
464  }
465 
474  void
475  deleteIdentity (const Name& identity)
476  {
477  try
478  {
479  if (Info::getDefaultIdentity() == identity)
480  return;
481  }
482  catch (InfoError& e)
483  {
484  // Not a real error, just try to delete the identity
485  }
486 
487  std::vector<Name> nameList;
488  Info::getAllKeyNamesOfIdentity(identity, nameList, true);
489  Info::getAllKeyNamesOfIdentity(identity, nameList, false);
490 
491  Info::deleteIdentityInfo(identity);
492 
493  std::vector<Name>::const_iterator it = nameList.begin();
494  for(; it != nameList.end(); it++)
495  Tpm::deleteKeyPairInTpm(*it);
496  }
497 
506  shared_ptr<SecuredBag>
507  exportIdentity(const Name& identity, const std::string& passwordStr)
508  {
509  if (!Info::doesIdentityExist(identity))
510  throw InfoError("Identity does not exist!");
511 
512  Name keyName = Info::getDefaultKeyNameForIdentity(identity);
513 
514  ConstBufferPtr pkcs5;
515  try
516  {
517  pkcs5 = Tpm::exportPrivateKeyPkcs5FromTpm(keyName, passwordStr);
518  }
519  catch (TpmError& e)
520  {
521  throw InfoError("Fail to export PKCS5 of private key");
522  }
523 
524  shared_ptr<IdentityCertificate> cert;
525  try
526  {
527  cert = Info::getCertificate(Info::getDefaultCertificateNameForKey(keyName));
528  }
529  catch (InfoError& e)
530  {
531  cert = selfSign(keyName);
532  Info::addCertificateAsIdentityDefault(*cert);
533  }
534 
535  shared_ptr<SecuredBag> secureBag = make_shared<SecuredBag>(boost::cref(*cert),
536  boost::cref(pkcs5));
537 
538  return secureBag;
539  }
540 
547  void
548  importIdentity(const SecuredBag& securedBag, const std::string& passwordStr)
549  {
550  Name certificateName = securedBag.getCertificate().getName();
552  Name identity = keyName.getPrefix(-1);
553 
554  // Add identity
555  Info::addIdentity(identity);
556 
557  // Add key
558  Tpm::importPrivateKeyPkcs5IntoTpm(keyName,
559  securedBag.getKey()->buf(),
560  securedBag.getKey()->size(),
561  passwordStr);
562 
563  shared_ptr<PublicKey> pubKey = Tpm::getPublicKeyFromTpm(keyName.toUri());
564  // HACK! We should set key type according to the pkcs8 info.
565  Info::addPublicKey(keyName, KEY_TYPE_RSA, *pubKey);
566  Info::setDefaultKeyNameForIdentity(keyName);
567 
568  // Add cert
569  Info::addCertificateAsIdentityDefault(securedBag.getCertificate());
570  }
571 
572 
573 private:
580  template<typename T>
581  void
582  sign(T& packet, const IdentityCertificate& certificate)
583  {
584  SignatureSha256WithRsa signature;
585  signature.setKeyLocator(certificate.getName().getPrefix(-1));
586 
587  // For temporary usage, we support RSA + SHA256 only, but will support more.
588  signPacketWrapper(packet, signature, certificate.getPublicKeyName(), DIGEST_ALGORITHM_SHA256);
589  }
590 
600  Name
601  generateKeyPair(const Name& identityName, bool isKsk = false,
602  KeyType keyType = KEY_TYPE_RSA, int keySize = 2048)
603  {
604  Name keyName = Info::getNewKeyName(identityName, isKsk);
605 
606  Tpm::generateKeyPairInTpm(keyName.toUri(), keyType, keySize);
607 
608  shared_ptr<PublicKey> pubKey = Tpm::getPublicKeyFromTpm(keyName.toUri());
609  Info::addPublicKey(keyName, keyType, *pubKey);
610 
611  return keyName;
612  }
613 
623  void
624  signPacketWrapper(Data& data, const SignatureSha256WithRsa& signature,
625  const Name& keyName, DigestAlgorithm digestAlgorithm)
626  {
627  data.setSignature(signature);
628  data.setSignatureValue(Tpm::signInTpm(data.wireEncode().value(),
629  data.wireEncode().value_size() -
630  data.getSignature().getValue().size(),
631  keyName, digestAlgorithm));
632  }
633 
643  void
644  signPacketWrapper(Interest& interest, const SignatureSha256WithRsa& signature,
645  const Name& keyName, DigestAlgorithm digestAlgorithm)
646  {
647  Name signedName = interest.getName();
648  signedName.append(signature.getInfo());
649 
650  Block sigValue = Tpm::signInTpm(signedName.wireEncode().value(),
651  signedName.wireEncode().value_size(),
652  keyName,
654  sigValue.encode();
655  signedName.append(sigValue);
656  interest.setName(signedName);
657  }
658 
659 };
660 
661 } // namespace ndn
662 
663 
664 
665 #if defined(NDN_CPP_HAVE_OSX_SECURITY) and defined(NDN_CPP_WITH_OSX_KEYCHAIN)
666 
667 namespace ndn {
668 
669 typedef KeyChainImpl<SecPublicInfoSqlite3, SecTpmOsx> KeyChain;
670 
671 } // namespace ndn
672 
673 #else
674 
675 namespace ndn {
676 
678 
679 } // namespace ndn
680 
681 #endif //NDN_CPP_HAVE_OSX_SECURITY
682 
683 #endif //NDN_SECURITY_KEY_CHAIN_HPP
Representing of SHA256-with-RSA signature in a data packet.
Name getSubName(size_t iStartComponent, size_t nComponents) const
Get a new name, constructed as a subset of components.
Definition: name.hpp:632
void toEscapedString(std::ostream &result) const
Write the value to result, escaping characters according to the NDN URI Scheme.
Name getPrefix(int nComponents) const
Return a new Name with the first nComponents components of this Name.
Definition: name.hpp:240
Name generateRSAKeyPair(const Name &identityName, bool isKsk=false, int keySize=2048)
Generate a pair of RSA keys for the specified identity.
Definition: key-chain.hpp:93
A CertificateSubjectDescription represents the SubjectDescription entry in a Certificate.
Representing of SHA256 signature in a data packet.
ConstBufferPtr getKey() const
Definition: secured-bag.hpp:78
void selfSign(IdentityCertificate &cert)
Self-sign the supplied identity certificate.
Definition: key-chain.hpp:404
Name generateRSAKeyPairAsDefault(const Name &identityName, bool isKsk=false, int keySize=2048)
Generate a pair of RSA keys for the specified identity and set it as default key for the identity...
Definition: key-chain.hpp:108
void signByIdentity(T &packet, const Name &identityName)
Sign packet using the default certificate of a particular identity.
Definition: key-chain.hpp:297
static Name certificateNameToPublicKeyName(const Name &certificateName)
Get the public key name from the full certificate name.
void importIdentity(const SecuredBag &securedBag, const std::string &passwordStr)
import an identity.
Definition: key-chain.hpp:548
Class representing wire element of the NDN packet.
Definition: block.hpp:26
const Block & getValue() const
Definition: signature.hpp:79
void sign(T &packet, const Name &certificateName)
Sign packet with a particular certificate.
Definition: key-chain.hpp:245
void deleteCertificate(const Name &certificateName)
delete a certificate.
Definition: key-chain.hpp:426
size_t wireEncode(EncodingImpl< T > &block, bool unsignedPortion=false) const
Fast encoding or block size estimation.
Definition: data.hpp:242
const Name & getName() const
Definition: data.hpp:346
size_t size() const
Definition: block.hpp:415
std::string toUri() const
Encode this name as a URI.
Definition: name.hpp:536
ptr_lib::shared_ptr< const Buffer > ConstBufferPtr
Definition: buffer.hpp:17
uint32_t generateWord32()
Definition: random.cpp:17
void sign(T &packet)
Sign packet with default identity.
Definition: key-chain.hpp:208
shared_ptr< IdentityCertificate > selfSign(const Name &keyName)
Generate a self-signed certificate for a public key.
Definition: key-chain.hpp:369
void signWithSha256(Data &data)
Set Sha256 weak signature.
Definition: key-chain.hpp:350
void deleteKey(const Name &keyName)
delete a key.
Definition: key-chain.hpp:450
void setValue(const Block &value)
Definition: signature.hpp:86
size_t size() const
Get the number of components.
Definition: name.hpp:329
A Name holds an array of Name::Component and represents an NDN name.
Definition: name.hpp:26
const Name & getPublicKeyName() const
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)
prepare an unsigned identity certificate
Definition: key-chain.hpp:128
time_point TimePoint
Definition: time.hpp:55
const Signature & getSignature() const
Definition: data.hpp:450
Signature signByIdentity(const uint8_t *buffer, size_t bufferLength, const Name &identityName)
Sign the byte array using the default certificate of a particular identity.
Definition: key-chain.hpp:325
KeyChainImpl< SecPublicInfoSqlite3, SecTpmFile > KeyChain
Definition: key-chain.hpp:677
Name createIdentity(const Name &identityName)
Create an identity by creating a pair of Key-Signing-Key (KSK) for this identity and a self-signed ce...
Definition: key-chain.hpp:55
void setKeyLocator(const KeyLocator &keyLocator)
shared_ptr< SecuredBag > exportIdentity(const Name &identity, const std::string &passwordStr)
export an identity.
Definition: key-chain.hpp:507
KeyChain is one of the main classes of the security library.
Definition: key-chain.hpp:42
void setSignatureValue(const Block &value)
Definition: data.hpp:463
const IdentityCertificate & getCertificate() const
Definition: secured-bag.hpp:72
Name & append(const uint8_t *value, size_t valueLength)
Append a new component, copying from value of length valueLength.
Definition: name.hpp:142
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.hpp:669
Signature sign(const uint8_t *buffer, size_t bufferLength, const Name &certificateName)
Sign the byte array using a particular certificate.
Definition: key-chain.hpp:270
Name & appendVersion(uint64_t number)
An alias for appendNumber(uint64_t)
Definition: name.hpp:274
ConstBufferPtr sha256(const uint8_t *data, size_t dataLength)
Compute the sha-256 digest of data.
Definition: crypto.cpp:33
void setSignature(const Signature &signature)
Set the signature to a copy of the given signature.
Definition: data.hpp:456
const Component & get(ssize_t i) const
Get the component at the given index.
Definition: name.hpp:340
void deleteIdentity(const Name &identity)
delete an identity.
Definition: key-chain.hpp:475
duration< boost::int_least32_t, boost::ratio< 86400 > > days
Definition: time.hpp:18
A Signature is storage for the signature-related information (info and value) in a Data packet...
Definition: signature.hpp:15