blob: 6ac16686eb8153da03673267051c299fb28e0f41 [file] [log] [blame]
Jeff Thompson25b4e612013-10-10 16:03:24 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
Jeff Thompson47c93cf2013-08-09 00:38:48 -07002/**
Jeff Thompson7687dc02013-09-13 11:54:07 -07003 * Copyright (C) 2013 Regents of the University of California.
Jeff Thompsonba16b8f2013-12-16 13:11:47 -08004 * @author: Yingdi Yu <yingdi@cs.ucla.edu>
Jeff Thompson7687dc02013-09-13 11:54:07 -07005 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
Jeff Thompson47c93cf2013-08-09 00:38:48 -07006 * See COPYING for copyright and distribution information.
7 */
8
Yingdi Yufc40d872014-02-18 12:56:04 -08009#ifndef NDN_SECURITY_KEY_CHAIN_HPP
10#define NDN_SECURITY_KEY_CHAIN_HPP
Jeff Thompson47c93cf2013-08-09 00:38:48 -070011
Yingdi Yu4f324632014-01-15 18:10:03 -080012#include "identity-certificate.hpp"
13#include "public-key.hpp"
14#include "signature-sha256-with-rsa.hpp"
Yingdi Yu4270f202014-01-28 14:19:16 -080015#include "../interest.hpp"
Yingdi Yu8dceb1d2014-02-18 12:45:10 -080016#include "../encoding/tlv-security.hpp"
Yingdi Yu2e57a582014-02-20 23:34:43 -080017#include "../util/random.hpp"
Yingdi Yu31b4af22014-01-14 14:13:00 -080018
Yingdi Yu04020922014-01-22 12:46:53 -080019//PublicInfo
Yingdi Yu4f324632014-01-15 18:10:03 -080020#include "sec-public-info-sqlite3.hpp"
21#include "sec-public-info-memory.hpp"
Yingdi Yu04020922014-01-22 12:46:53 -080022//TPM
23#include "sec-tpm-file.hpp"
Yingdi Yu4f324632014-01-15 18:10:03 -080024#include "sec-tpm-memory.hpp"
Yingdi Yu2abd73f2014-01-08 23:34:11 -080025
Yingdi Yu04020922014-01-22 12:46:53 -080026#ifdef NDN_CPP_HAVE_OSX_SECURITY
27#include "sec-tpm-osx.hpp"
28#endif
29
Jeff Thompson47c93cf2013-08-09 00:38:48 -070030
31namespace ndn {
32
Jeff Thompson2ce8f492013-09-17 18:01:25 -070033/**
Yingdi Yu2e57a582014-02-20 23:34:43 -080034 * @brief KeyChain is one of the main classes of the security library.
Jeff Thompsonffa36f92013-09-20 08:42:41 -070035 *
Yingdi Yu2abd73f2014-01-08 23:34:11 -080036 * The KeyChain class provides a set of interfaces of identity management and private key related operations.
Jeff Thompsonffa36f92013-09-20 08:42:41 -070037 */
Yingdi Yu31b4af22014-01-14 14:13:00 -080038template<class Info, class Tpm>
39class KeyChainImpl : public Info, public Tpm
40{
Yingdi Yu4270f202014-01-28 14:19:16 -080041 typedef typename Info::Error InfoError;
Yingdi Yu2e57a582014-02-20 23:34:43 -080042 typedef typename Tpm::Error TpmError;
Jeff Thompson47c93cf2013-08-09 00:38:48 -070043public:
Yingdi Yube4150e2014-02-18 13:02:46 -080044 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -080045 * @brief Create an identity by creating a pair of Key-Signing-Key (KSK) for this identity and a self-signed certificate of the KSK.
Yingdi Yube4150e2014-02-18 13:02:46 -080046 *
Yingdi Yu2abd73f2014-01-08 23:34:11 -080047 * @param identityName The name of the identity.
Yingdi Yu28fd32f2014-01-28 19:03:03 -080048 * @return The name of the default certificate of the identity.
Yingdi Yu2abd73f2014-01-08 23:34:11 -080049 */
50 Name
Yingdi Yu31b4af22014-01-14 14:13:00 -080051 createIdentity(const Name& identityName)
52 {
Yingdi Yu2e57a582014-02-20 23:34:43 -080053 Info::addIdentity(identityName);
Yingdi Yu28fd32f2014-01-28 19:03:03 -080054
Yingdi Yu2e57a582014-02-20 23:34:43 -080055 Name keyName;
56 try
57 {
58 keyName = Info::getDefaultKeyNameForIdentity(identityName);
59 }
60 catch(InfoError& e)
61 {
62 keyName = generateRSAKeyPairAsDefault(identityName, true);
63 }
Yingdi Yu31b4af22014-01-14 14:13:00 -080064
Yingdi Yu2e57a582014-02-20 23:34:43 -080065 Name certName;
66 try
67 {
68 certName = Info::getDefaultCertificateNameForKey(keyName);
69 }
70 catch(InfoError& e)
Yingdi Yu28fd32f2014-01-28 19:03:03 -080071 {
Yingdi Yu8dceb1d2014-02-18 12:45:10 -080072 shared_ptr<IdentityCertificate> selfCert = selfSign(keyName);
Yingdi Yu28fd32f2014-01-28 19:03:03 -080073 Info::addCertificateAsIdentityDefault(*selfCert);
74 certName = selfCert->getName();
75 }
76
77 return certName;
Yingdi Yu31b4af22014-01-14 14:13:00 -080078 }
Yingdi Yu2abd73f2014-01-08 23:34:11 -080079
80 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -080081 * @brief Generate a pair of RSA keys for the specified identity.
82 *
Yingdi Yu2abd73f2014-01-08 23:34:11 -080083 * @param identityName The name of the identity.
84 * @param isKsk true for generating a Key-Signing-Key (KSK), false for a Data-Signing-Key (KSK).
85 * @param keySize The size of the key.
86 * @return The generated key name.
87 */
88 Name
Yingdi Yu31b4af22014-01-14 14:13:00 -080089 generateRSAKeyPair(const Name& identityName, bool isKsk = false, int keySize = 2048)
Yingdi Yu2abd73f2014-01-08 23:34:11 -080090 {
Yingdi Yu31b4af22014-01-14 14:13:00 -080091 return generateKeyPair(identityName, isKsk, KEY_TYPE_RSA, keySize);
Yingdi Yu2abd73f2014-01-08 23:34:11 -080092 }
Alexander Afanasyev64a3d812014-01-05 23:35:05 -080093
Yingdi Yu2abd73f2014-01-08 23:34:11 -080094 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -080095 * @brief Generate a pair of RSA keys for the specified identity and set it as default key for the identity.
96 *
Yingdi Yu2abd73f2014-01-08 23:34:11 -080097 * @param identityName The name of the identity.
98 * @param isKsk true for generating a Key-Signing-Key (KSK), false for a Data-Signing-Key (KSK).
99 * @param keySize The size of the key.
100 * @return The generated key name.
101 */
102 Name
Yingdi Yu31b4af22014-01-14 14:13:00 -0800103 generateRSAKeyPairAsDefault(const Name& identityName, bool isKsk = false, int keySize = 2048)
104 {
105 Name keyName = generateKeyPair(identityName, isKsk, KEY_TYPE_RSA, keySize);
106
107 Info::setDefaultKeyNameForIdentity(keyName);
Yingdi Yu31b4af22014-01-14 14:13:00 -0800108
109 return keyName;
110 }
Jeff Thompson79a2d5d2013-09-27 14:32:23 -0700111
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800112 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800113 * @brief Sign packet with default identity
114 *
115 * on return signatureInfo and signatureValue in the packet are set.
116 *
117 * @param packet The packet to be signed
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800118 */
Yingdi Yu2e57a582014-02-20 23:34:43 -0800119 template<typename T>
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800120 void
Yingdi Yu2e57a582014-02-20 23:34:43 -0800121 sign(T& packet)
Yingdi Yu31b4af22014-01-14 14:13:00 -0800122 {
123 if (!Info::defaultCertificate())
124 {
125 Info::refreshDefaultCertificate();
126
127 if(!Info::defaultCertificate())
Yingdi Yu2e57a582014-02-20 23:34:43 -0800128 {
129 Name defaultIdentity;
130 try
131 {
132 defaultIdentity = Info::getDefaultIdentity();
133 }
134 catch(InfoError& e)
135 {
136 uint32_t random = random::generateWord32();
137 defaultIdentity.append("tmp-identity").append(reinterpret_cast<uint8_t*>(&random), 4);
138 }
139 createIdentity(defaultIdentity);
140 Info::refreshDefaultCertificate();
141 }
Yingdi Yu31b4af22014-01-14 14:13:00 -0800142 }
143
Yingdi Yu2e57a582014-02-20 23:34:43 -0800144 sign(packet, *Info::defaultCertificate());
Yingdi Yu4270f202014-01-28 14:19:16 -0800145 }
Alexander Afanasyeve64788e2014-01-05 22:38:21 -0800146
Jeff Thompson47c93cf2013-08-09 00:38:48 -0700147 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800148 * @brief Sign packet with a particular certificate.
149 *
150 * @param packet The packet to be signed.
151 * @param certificateName The certificate name of the key to use for signing.
152 * @throws SecPublicInfo::Error if certificate does not exist.
Jeff Thompson3c73da42013-08-12 11:19:05 -0700153 */
Yingdi Yu2e57a582014-02-20 23:34:43 -0800154 template<typename T>
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800155 void
Yingdi Yu2e57a582014-02-20 23:34:43 -0800156 sign(T& packet, const Name& certificateName)
Yingdi Yu31b4af22014-01-14 14:13:00 -0800157 {
Yingdi Yu2e57a582014-02-20 23:34:43 -0800158 if (!Info::doesCertificateExist(certificateName))
Yingdi Yu4270f202014-01-28 14:19:16 -0800159 throw InfoError("Requested certificate [" + certificateName.toUri() + "] doesn't exist");
Yingdi Yu31b4af22014-01-14 14:13:00 -0800160
161 SignatureSha256WithRsa signature;
162 signature.setKeyLocator(certificateName.getPrefix(-1)); // implicit conversion should take care
Yingdi Yu31b4af22014-01-14 14:13:00 -0800163
164 // For temporary usage, we support RSA + SHA256 only, but will support more.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800165 signPacketWrapper(packet, signature,
166 IdentityCertificate::certificateNameToPublicKeyName(certificateName),
167 DIGEST_ALGORITHM_SHA256);
Yingdi Yu4270f202014-01-28 14:19:16 -0800168 }
Jeff Thompson79a2d5d2013-09-27 14:32:23 -0700169
Jeff Thompson29ce3102013-09-27 11:47:48 -0700170 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800171 * @brief Sign the byte array using a particular certificate.
172 *
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700173 * @param buffer The byte array to be signed.
174 * @param bufferLength the length of buffer.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800175 * @param certificateName The certificate name of the signing key.
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700176 * @return The Signature.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800177 * @throws SecPublicInfo::Error if certificate does not exist.
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700178 */
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800179 Signature
Yingdi Yu31b4af22014-01-14 14:13:00 -0800180 sign(const uint8_t* buffer, size_t bufferLength, const Name& certificateName)
181 {
Yingdi Yu2e57a582014-02-20 23:34:43 -0800182 if (!Info::doesCertificateExist(certificateName))
Yingdi Yu4270f202014-01-28 14:19:16 -0800183 throw InfoError("Requested certificate [" + certificateName.toUri() + "] doesn't exist");
Yingdi Yu31b4af22014-01-14 14:13:00 -0800184
185 SignatureSha256WithRsa signature;
186 signature.setKeyLocator(certificateName.getPrefix(-1)); // implicit conversion should take care
187
188 // For temporary usage, we support RSA + SHA256 only, but will support more.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800189 signature.setValue(Tpm::signInTpm(buffer, bufferLength,
190 IdentityCertificate::certificateNameToPublicKeyName(certificateName),
191 DIGEST_ALGORITHM_SHA256));
Yingdi Yu31b4af22014-01-14 14:13:00 -0800192 return signature;
193 }
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700194
195 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800196 * @brief Sign packet using the default certificate of a particular identity.
197 *
198 * If there is no default certificate of that identity, this method will create a self-signed certificate.
199 *
200 * @param packet The packet to be signed.
201 * @param identityName The signing identity name.
Jeff Thompson29ce3102013-09-27 11:47:48 -0700202 */
Yingdi Yu2e57a582014-02-20 23:34:43 -0800203 template<typename T>
Jeff Thompson29ce3102013-09-27 11:47:48 -0700204 void
Yingdi Yu2e57a582014-02-20 23:34:43 -0800205 signByIdentity(T& packet, const Name& identityName)
Yingdi Yu31b4af22014-01-14 14:13:00 -0800206 {
Yingdi Yu2e57a582014-02-20 23:34:43 -0800207 Name signingCertificateName;
208 try
209 {
210 signingCertificateName = Info::getDefaultCertificateNameForIdentity(identityName);
211 }
212 catch(InfoError& e)
213 {
214 signingCertificateName = createIdentity(identityName);
215 // Ideally, no exception will be thrown out, unless something goes wrong in the TPM, which is a fatal error.
216 }
Yingdi Yu31b4af22014-01-14 14:13:00 -0800217
Yingdi Yu2e57a582014-02-20 23:34:43 -0800218 // We either get or create the signing certificate, sign packet! (no exception unless fatal error in TPM)
219 sign(packet, signingCertificateName);
Yingdi Yu31b4af22014-01-14 14:13:00 -0800220 }
Jeff Thompson3c73da42013-08-12 11:19:05 -0700221
222 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800223 * @brief Sign the byte array using the default certificate of a particular identity.
224 *
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700225 * @param buffer The byte array to be signed.
226 * @param bufferLength the length of buffer.
227 * @param identityName The identity name.
228 * @return The Signature.
229 */
Alexander Afanasyev64a3d812014-01-05 23:35:05 -0800230 Signature
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800231 signByIdentity(const uint8_t* buffer, size_t bufferLength, const Name& identityName)
Yingdi Yu31b4af22014-01-14 14:13:00 -0800232 {
Yingdi Yu2e57a582014-02-20 23:34:43 -0800233 Name signingCertificateName;
234 try
235 {
236 signingCertificateName = Info::getDefaultCertificateNameForIdentity(identityName);
237 }
238 catch(InfoError& e)
239 {
240 signingCertificateName = createIdentity(identityName);
241 // Ideally, no exception will be thrown out, unless something goes wrong in the TPM, which is a fatal error.
242 }
Yingdi Yu31b4af22014-01-14 14:13:00 -0800243
Yingdi Yu2e57a582014-02-20 23:34:43 -0800244 // We either get or create the signing certificate, sign data! (no exception unless fatal error in TPM)
Yingdi Yu31b4af22014-01-14 14:13:00 -0800245 return sign(buffer, bufferLength, signingCertificateName);
246 }
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700247
248 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800249 * @brief Generate a self-signed certificate for a public key.
250 *
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800251 * @param keyName The name of the public key.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800252 * @return The generated certificate, NULL if selfSign fails.
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800253 */
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800254 shared_ptr<IdentityCertificate>
Yingdi Yu31b4af22014-01-14 14:13:00 -0800255 selfSign(const Name& keyName)
256 {
Yingdi Yu2e57a582014-02-20 23:34:43 -0800257 shared_ptr<PublicKey> pubKey;
258 try
259 {
260 pubKey = Info::getPublicKey(keyName); // may throw an exception.
261 }
262 catch(InfoError& e)
263 {
264 return shared_ptr<IdentityCertificate>();
265 }
Yingdi Yu7ea69502014-01-15 17:21:29 -0800266
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800267 shared_ptr<IdentityCertificate> certificate = make_shared<IdentityCertificate>();
Yingdi Yu31b4af22014-01-14 14:13:00 -0800268
269 Name certificateName = keyName.getPrefix(-1);
270 certificateName.append("KEY").append(keyName.get(-1)).append("ID-CERT").appendVersion();
Yingdi Yu2e57a582014-02-20 23:34:43 -0800271
Yingdi Yu31b4af22014-01-14 14:13:00 -0800272 certificate->setName(certificateName);
273 certificate->setNotBefore(getNow());
274 certificate->setNotAfter(getNow() + 630720000 /* 20 years*/);
275 certificate->setPublicKeyInfo(*pubKey);
276 certificate->addSubjectDescription(CertificateSubjectDescription("2.5.4.41", keyName.toUri()));
277 certificate->encode();
278
279 selfSign(*certificate);
280 return certificate;
281 }
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800282
283 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800284 * @brief Self-sign the supplied identity certificate.
285 *
286 * @param cert The supplied cert.
287 * @throws SecTpm::Error if the private key does not exist.
Jeff Thompson8efe5ad2013-08-20 17:36:38 -0700288 */
Jeff Thompson2ce8f492013-09-17 18:01:25 -0700289 void
Yingdi Yu31b4af22014-01-14 14:13:00 -0800290 selfSign (IdentityCertificate& cert)
291 {
Yingdi Yu2e57a582014-02-20 23:34:43 -0800292 Name keyName = IdentityCertificate::certificateNameToPublicKeyName(cert.getName());
293 if(!Tpm::doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE))
294 throw TpmError("private key does not exist!");
295
Yingdi Yu31b4af22014-01-14 14:13:00 -0800296 SignatureSha256WithRsa signature;
297 signature.setKeyLocator(cert.getName().getPrefix(-1)); // implicit conversion should take care
Yingdi Yu31b4af22014-01-14 14:13:00 -0800298
299 // For temporary usage, we support RSA + SHA256 only, but will support more.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800300 signPacketWrapper(cert, signature, keyName, DIGEST_ALGORITHM_SHA256);
Yingdi Yu31b4af22014-01-14 14:13:00 -0800301 }
302
Yingdi Yu2e57a582014-02-20 23:34:43 -0800303 /**
304 * @brief delete a certificate.
305 *
306 * If the certificate to be deleted is current default system default,
307 * the method will not delete the certificate and return immediately.
308 *
309 * @param certificateName The certificate to be deleted.
310 */
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800311 void
Yingdi Yu2e57a582014-02-20 23:34:43 -0800312 deleteCertificate (const Name& certificateName)
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800313 {
Yingdi Yu2e57a582014-02-20 23:34:43 -0800314 try
315 {
316 if(Info::getDefaultCertificateName() == certificateName)
317 return;
318 }
319 catch(InfoError& e)
320 {
321 // Not a real error, just try to delete the certificate
322 }
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800323
324 Info::deleteCertificateInfo(certificateName);
325 }
326
Yingdi Yu2e57a582014-02-20 23:34:43 -0800327 /**
328 * @brief delete a key.
329 *
330 * If the key to be deleted is current default system default,
331 * the method will not delete the key and return immediately.
332 *
333 * @param keyName The key to be deleted.
334 */
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800335 void
Yingdi Yu2e57a582014-02-20 23:34:43 -0800336 deleteKey (const Name& keyName)
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800337 {
Yingdi Yu2e57a582014-02-20 23:34:43 -0800338 try
339 {
340 if(Info::getDefaultKeyNameForIdentity(Info::getDefaultIdentity()) == keyName)
341 return;
342 }
343 catch(InfoError& e)
344 {
345 // Not a real error, just try to delete the key
346 }
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800347
348 Info::deletePublicKeyInfo(keyName);
349 Tpm::deleteKeyPairInTpm(keyName);
350 }
351
Yingdi Yu2e57a582014-02-20 23:34:43 -0800352 /**
353 * @brief delete an identity.
354 *
355 * If the identity to be deleted is current default system default,
356 * the method will not delete the identity and return immediately.
357 *
358 * @param identity The identity to be deleted.
359 */
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800360 void
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800361 deleteIdentity (const Name& identity)
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800362 {
Yingdi Yu2e57a582014-02-20 23:34:43 -0800363 try
364 {
365 if(Info::getDefaultIdentity() == identity)
366 return;
367 }
368 catch(InfoError& e)
369 {
370 // Not a real error, just try to delete the identity
371 }
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800372
373 std::vector<Name> nameList;
374 Info::getAllKeyNamesOfIdentity(identity, nameList, true);
375 Info::getAllKeyNamesOfIdentity(identity, nameList, false);
376
377 Info::deleteIdentityInfo(identity);
378
379 std::vector<Name>::const_iterator it = nameList.begin();
380 for(; it != nameList.end(); it++)
381 Tpm::deleteKeyPairInTpm(*it);
382 }
383
Yingdi Yu2e57a582014-02-20 23:34:43 -0800384 /**
385 * @brief export an identity.
386 *
387 * @param identity The identity to export.
388 * @param passwordStr The password to secure the private key.
389 * @param The encoded export data.
390 * @throws InfoError if anything goes wrong in exporting.
391 */
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800392 Block
Yingdi Yube4150e2014-02-18 13:02:46 -0800393 exportIdentity(const Name& identity, const std::string& passwordStr)
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800394 {
395 if (!Info::doesIdentityExist(identity))
396 throw InfoError("Identity does not exist!");
397
398 Name keyName = Info::getDefaultKeyNameForIdentity(identity);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800399
Yingdi Yu2e57a582014-02-20 23:34:43 -0800400 ConstBufferPtr pkcs8;
401 try
402 {
403 pkcs8 = Tpm::exportPrivateKeyPkcs8FromTpm(keyName, passwordStr);
404 }
405 catch(TpmError& e)
406 {
407 throw InfoError("Fail to export PKCS8 of private key");
408 }
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800409 Block wireKey(tlv::security::KeyPackage, pkcs8);
410
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800411
Yingdi Yu2e57a582014-02-20 23:34:43 -0800412 shared_ptr<IdentityCertificate> cert;
413 try
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800414 {
Yingdi Yu2e57a582014-02-20 23:34:43 -0800415 cert = Info::getCertificate(Info::getDefaultCertificateNameForKey(keyName));
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800416 }
Yingdi Yu2e57a582014-02-20 23:34:43 -0800417 catch(InfoError& e)
418 {
419 cert = selfSign(keyName);
420 Info::addCertificateAsIdentityDefault(*cert);
421 }
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800422 Block wireCert(tlv::security::CertificatePackage, cert->wireEncode());
423
424 Block wire(tlv::security::IdentityPackage);
425 wire.push_back(wireCert);
426 wire.push_back(wireKey);
427
428 return wire;
429 }
430
Yingdi Yu2e57a582014-02-20 23:34:43 -0800431 /**
432 * @brief import an identity.
433 *
434 * @param The encoded import data.
435 * @param passwordStr The password to secure the private key.
436 */
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800437 void
Yingdi Yube4150e2014-02-18 13:02:46 -0800438 importIdentity(const Block& block, const std::string& passwordStr)
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800439 {
Yingdi Yu2e57a582014-02-20 23:34:43 -0800440 try
441 {
442 block.parse();
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800443
Yingdi Yu2e57a582014-02-20 23:34:43 -0800444 Data data;
445 data.wireDecode(block.get(tlv::security::CertificatePackage).blockFromValue());
446 shared_ptr<IdentityCertificate> cert = make_shared<IdentityCertificate>(data);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800447
Yingdi Yu2e57a582014-02-20 23:34:43 -0800448 Name keyName = IdentityCertificate::certificateNameToPublicKeyName(cert->getName());
449 Name identity = keyName.getPrefix(-1);
450
451 // Add identity
452 Info::addIdentity(identity);
453
454 // Add key
455 Block wireKey = block.get(tlv::security::KeyPackage);
456 Tpm::importPrivateKeyPkcs8IntoTpm(keyName, wireKey.value(), wireKey.value_size(), passwordStr);
457 shared_ptr<PublicKey> pubKey = Tpm::getPublicKeyFromTpm(keyName.toUri());
458 Info::addPublicKey(keyName, KEY_TYPE_RSA, *pubKey); // HACK! We should set key type according to the pkcs8 info.
459 Info::setDefaultKeyNameForIdentity(keyName);
460
461 // Add cert
462 Info::addCertificateAsIdentityDefault(*cert);
463 }
464 catch(Block::Error& e)
465 {
466 return;
467 }
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800468 }
469
Jeff Thompson8efe5ad2013-08-20 17:36:38 -0700470
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800471private:
Yingdi Yu2e57a582014-02-20 23:34:43 -0800472 /**
473 * @brief sign a packet using a pariticular certificate.
474 *
475 * @param packet The packet to be signed.
476 * @param certificate The signing certificate.
477 */
478 template<typename T>
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800479 void
Yingdi Yu2e57a582014-02-20 23:34:43 -0800480 sign(T& packet, const IdentityCertificate& certificate)
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800481 {
482 SignatureSha256WithRsa signature;
483 signature.setKeyLocator(certificate.getName().getPrefix(-1));
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800484
485 // For temporary usage, we support RSA + SHA256 only, but will support more.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800486 signPacketWrapper(packet, signature, certificate.getPublicKeyName(), DIGEST_ALGORITHM_SHA256);
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800487 }
488
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800489 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800490 * @brief Generate a key pair for the specified identity.
491 *
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800492 * @param identityName The name of the specified identity.
493 * @param isKsk true for generating a Key-Signing-Key (KSK), false for a Data-Signing-Key (KSK).
494 * @param keyType The type of the key pair, e.g. KEY_TYPE_RSA.
495 * @param keySize The size of the key pair.
496 * @return The name of the generated key.
497 */
498 Name
Yingdi Yu31b4af22014-01-14 14:13:00 -0800499 generateKeyPair(const Name& identityName, bool isKsk = false, KeyType keyType = KEY_TYPE_RSA, int keySize = 2048)
500 {
501 Name keyName = Info::getNewKeyName(identityName, isKsk);
502
503 Tpm::generateKeyPairInTpm(keyName.toUri(), keyType, keySize);
504
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800505 shared_ptr<PublicKey> pubKey = Tpm::getPublicKeyFromTpm(keyName.toUri());
Yingdi Yuef26ee32014-01-15 16:41:14 -0800506 Info::addPublicKey(keyName, keyType, *pubKey);
Yingdi Yu31b4af22014-01-14 14:13:00 -0800507
508 return keyName;
509 }
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800510
Yingdi Yu8726f652014-01-23 10:35:12 -0800511 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800512 * @brief Sign the data using a particular key.
513 *
514 * @param data Reference to the data packet.
515 * @param signature Signature to be added.
Yingdi Yu8726f652014-01-23 10:35:12 -0800516 * @param keyName The name of the signing key.
517 * @param digestAlgorithm the digest algorithm.
518 * @throws Tpm::Error
519 */
520 void
Yingdi Yu2e57a582014-02-20 23:34:43 -0800521 signPacketWrapper(Data& data, const SignatureSha256WithRsa& signature, const Name& keyName, DigestAlgorithm digestAlgorithm)
Yingdi Yu8726f652014-01-23 10:35:12 -0800522 {
Yingdi Yu2e57a582014-02-20 23:34:43 -0800523 data.setSignature(signature);
Yingdi Yu8726f652014-01-23 10:35:12 -0800524 data.setSignatureValue
525 (Tpm::signInTpm(data.wireEncode().value(),
526 data.wireEncode().value_size() - data.getSignature().getValue().size(),
527 keyName, digestAlgorithm));
528 }
529
Yingdi Yu2e57a582014-02-20 23:34:43 -0800530 /**
531 * @brief Sign the interest using a particular key.
532 *
533 * @param interest Reference to the interest packet.
534 * @param signature Signature to be added.
535 * @param keyName The name of the signing key.
536 * @param digestAlgorithm the digest algorithm.
537 * @throws Tpm::Error
538 */
539 void
540 signPacketWrapper(Interest& interest, const SignatureSha256WithRsa& signature, const Name& keyName, DigestAlgorithm digestAlgorithm)
541 {
542 Name signedName = Name(interest.getName()).append(signature.getInfo());
543
544 Block sigValue = Tpm::signInTpm(signedName.wireEncode().value(),
545 signedName.wireEncode().value_size(),
546 keyName,
547 DIGEST_ALGORITHM_SHA256);
548 sigValue.encode();
549 signedName.append(sigValue);
550 interest.setName(signedName);
551 }
552
553
Jeff Thompson47c93cf2013-08-09 00:38:48 -0700554};
555
Yingdi Yufc40d872014-02-18 12:56:04 -0800556} // namespace ndn
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800557
Yingdi Yu04020922014-01-22 12:46:53 -0800558
559
Alexander Afanasyev3e08d5d2014-02-12 19:24:28 -0800560#if defined(NDN_CPP_HAVE_OSX_SECURITY) and defined(NDN_CPP_WITH_OSX_KEYCHAIN)
Yingdi Yu31b4af22014-01-14 14:13:00 -0800561
562namespace ndn
Alexander Afanasyeve64788e2014-01-05 22:38:21 -0800563{
Yingdi Yu31b4af22014-01-14 14:13:00 -0800564typedef KeyChainImpl<SecPublicInfoSqlite3, SecTpmOsx> KeyChain;
565};
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800566
Yingdi Yu31b4af22014-01-14 14:13:00 -0800567#else
Alexander Afanasyeve64788e2014-01-05 22:38:21 -0800568
Yingdi Yu31b4af22014-01-14 14:13:00 -0800569namespace ndn
Alexander Afanasyeve64788e2014-01-05 22:38:21 -0800570{
Yingdi Yu04020922014-01-22 12:46:53 -0800571typedef KeyChainImpl<SecPublicInfoSqlite3, SecTpmFile> KeyChain;
Yingdi Yu31b4af22014-01-14 14:13:00 -0800572};
Alexander Afanasyeve64788e2014-01-05 22:38:21 -0800573
Yingdi Yu31b4af22014-01-14 14:13:00 -0800574#endif //NDN_CPP_HAVE_OSX_SECURITY
Jeff Thompson47c93cf2013-08-09 00:38:48 -0700575
Yingdi Yufc40d872014-02-18 12:56:04 -0800576#endif //NDN_SECURITY_KEY_CHAIN_HPP