blob: a0832593c936ec9d9bcb47d72fa5938e99ca3507 [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 Yuf8fc8de2014-02-25 15:45:39 -080041 typedef SecPublicInfo::Error InfoError;
42 typedef SecTpm::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 Yuc55680b2014-02-26 12:31:35 -0800113 * @brief prepare an unsigned identity certificate
114 *
115 * @param keyName Key name, e.g., /<identity_name>/ksk-123456.
116 * @param signingIdentity The signing identity.
117 * @param notBefore Refer to IdentityCertificate.
118 * @param notAfter Refer to IdentityCertificate.
119 * @param subjectDescription Refer to IdentityCertificate.
120 * @return IdentityCertificate.
121 */
122 shared_ptr<IdentityCertificate>
123 prepareUnsignedIdentityCertificate(const Name& keyName,
124 const Name& signingIdentity,
125 const MillisecondsSince1970& notBefore,
126 const MillisecondsSince1970& notAfter,
127 const std::vector<CertificateSubjectDescription>& subjectDescription)
128
129 {
130 if(keyName.size() < 1)
131 return shared_ptr<IdentityCertificate>();
132
133 std::string keyIdPrefix = keyName.get(-1).toEscapedString().substr(0, 4);
134 if(keyIdPrefix != "ksk-" && keyIdPrefix != "dsk-")
135 return shared_ptr<IdentityCertificate>();
136
137 shared_ptr<IdentityCertificate> certificate = make_shared<IdentityCertificate>();
138 Name certName;
139
140 if(signingIdentity.isPrefixOf(keyName))
141 {
142 certName.append(signingIdentity).append("KEY").append(keyName.getSubName(signingIdentity.size())).append("ID-CERT").appendVersion();
143 }
144 else
145 {
146 certName.append(keyName.getPrefix(-1)).append("KEY").append(keyName.get(-1)).append("ID-CERT").appendVersion();
147 }
148
149 certificate->setName(certName);
150 certificate->setNotBefore(notBefore);
151 certificate->setNotAfter(notAfter);
152
153 shared_ptr<PublicKey> publicKey;
154 try
155 {
156 publicKey = Info::getPublicKey(keyName);
157 }
158 catch(InfoError& e)
159 {
160 return shared_ptr<IdentityCertificate>();
161 }
162 certificate->setPublicKeyInfo(*publicKey);
163
164 if(subjectDescription.empty())
165 {
166 CertificateSubjectDescription subDescryptName("2.5.4.41", keyName.getPrefix(-1).toUri());
167 certificate->addSubjectDescription(subDescryptName);
168 }
169 else
170 {
171 std::vector<CertificateSubjectDescription>::const_iterator sdIt = subjectDescription.begin();
172 std::vector<CertificateSubjectDescription>::const_iterator sdEnd = subjectDescription.end();
173 for(; sdIt != sdEnd; sdIt++)
174 certificate->addSubjectDescription(*sdIt);
175 }
176
177 certificate->encode();
178
179 return certificate;
180 }
181
182 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800183 * @brief Sign packet with default identity
184 *
185 * on return signatureInfo and signatureValue in the packet are set.
186 *
187 * @param packet The packet to be signed
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800188 */
Yingdi Yu2e57a582014-02-20 23:34:43 -0800189 template<typename T>
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800190 void
Yingdi Yu2e57a582014-02-20 23:34:43 -0800191 sign(T& packet)
Yingdi Yu31b4af22014-01-14 14:13:00 -0800192 {
193 if (!Info::defaultCertificate())
194 {
195 Info::refreshDefaultCertificate();
196
197 if(!Info::defaultCertificate())
Yingdi Yu2e57a582014-02-20 23:34:43 -0800198 {
199 Name defaultIdentity;
200 try
201 {
202 defaultIdentity = Info::getDefaultIdentity();
203 }
204 catch(InfoError& e)
205 {
206 uint32_t random = random::generateWord32();
207 defaultIdentity.append("tmp-identity").append(reinterpret_cast<uint8_t*>(&random), 4);
208 }
209 createIdentity(defaultIdentity);
210 Info::refreshDefaultCertificate();
211 }
Yingdi Yu31b4af22014-01-14 14:13:00 -0800212 }
213
Yingdi Yu2e57a582014-02-20 23:34:43 -0800214 sign(packet, *Info::defaultCertificate());
Yingdi Yu4270f202014-01-28 14:19:16 -0800215 }
Alexander Afanasyeve64788e2014-01-05 22:38:21 -0800216
Jeff Thompson47c93cf2013-08-09 00:38:48 -0700217 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800218 * @brief Sign packet with a particular certificate.
219 *
220 * @param packet The packet to be signed.
221 * @param certificateName The certificate name of the key to use for signing.
222 * @throws SecPublicInfo::Error if certificate does not exist.
Jeff Thompson3c73da42013-08-12 11:19:05 -0700223 */
Yingdi Yu2e57a582014-02-20 23:34:43 -0800224 template<typename T>
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800225 void
Yingdi Yu2e57a582014-02-20 23:34:43 -0800226 sign(T& packet, const Name& certificateName)
Yingdi Yu31b4af22014-01-14 14:13:00 -0800227 {
Yingdi Yu2e57a582014-02-20 23:34:43 -0800228 if (!Info::doesCertificateExist(certificateName))
Yingdi Yu4270f202014-01-28 14:19:16 -0800229 throw InfoError("Requested certificate [" + certificateName.toUri() + "] doesn't exist");
Yingdi Yu31b4af22014-01-14 14:13:00 -0800230
231 SignatureSha256WithRsa signature;
232 signature.setKeyLocator(certificateName.getPrefix(-1)); // implicit conversion should take care
Yingdi Yu31b4af22014-01-14 14:13:00 -0800233
234 // For temporary usage, we support RSA + SHA256 only, but will support more.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800235 signPacketWrapper(packet, signature,
236 IdentityCertificate::certificateNameToPublicKeyName(certificateName),
237 DIGEST_ALGORITHM_SHA256);
Yingdi Yu4270f202014-01-28 14:19:16 -0800238 }
Jeff Thompson79a2d5d2013-09-27 14:32:23 -0700239
Jeff Thompson29ce3102013-09-27 11:47:48 -0700240 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800241 * @brief Sign the byte array using a particular certificate.
242 *
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700243 * @param buffer The byte array to be signed.
244 * @param bufferLength the length of buffer.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800245 * @param certificateName The certificate name of the signing key.
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700246 * @return The Signature.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800247 * @throws SecPublicInfo::Error if certificate does not exist.
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700248 */
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800249 Signature
Yingdi Yu31b4af22014-01-14 14:13:00 -0800250 sign(const uint8_t* buffer, size_t bufferLength, const Name& certificateName)
251 {
Yingdi Yu2e57a582014-02-20 23:34:43 -0800252 if (!Info::doesCertificateExist(certificateName))
Yingdi Yu4270f202014-01-28 14:19:16 -0800253 throw InfoError("Requested certificate [" + certificateName.toUri() + "] doesn't exist");
Yingdi Yu31b4af22014-01-14 14:13:00 -0800254
255 SignatureSha256WithRsa signature;
256 signature.setKeyLocator(certificateName.getPrefix(-1)); // implicit conversion should take care
257
258 // For temporary usage, we support RSA + SHA256 only, but will support more.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800259 signature.setValue(Tpm::signInTpm(buffer, bufferLength,
260 IdentityCertificate::certificateNameToPublicKeyName(certificateName),
261 DIGEST_ALGORITHM_SHA256));
Yingdi Yu31b4af22014-01-14 14:13:00 -0800262 return signature;
263 }
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700264
265 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800266 * @brief Sign packet using the default certificate of a particular identity.
267 *
268 * If there is no default certificate of that identity, this method will create a self-signed certificate.
269 *
270 * @param packet The packet to be signed.
271 * @param identityName The signing identity name.
Jeff Thompson29ce3102013-09-27 11:47:48 -0700272 */
Yingdi Yu2e57a582014-02-20 23:34:43 -0800273 template<typename T>
Jeff Thompson29ce3102013-09-27 11:47:48 -0700274 void
Yingdi Yu2e57a582014-02-20 23:34:43 -0800275 signByIdentity(T& packet, const Name& identityName)
Yingdi Yu31b4af22014-01-14 14:13:00 -0800276 {
Yingdi Yu2e57a582014-02-20 23:34:43 -0800277 Name signingCertificateName;
278 try
279 {
280 signingCertificateName = Info::getDefaultCertificateNameForIdentity(identityName);
281 }
282 catch(InfoError& e)
283 {
284 signingCertificateName = createIdentity(identityName);
285 // Ideally, no exception will be thrown out, unless something goes wrong in the TPM, which is a fatal error.
286 }
Yingdi Yu31b4af22014-01-14 14:13:00 -0800287
Yingdi Yu2e57a582014-02-20 23:34:43 -0800288 // We either get or create the signing certificate, sign packet! (no exception unless fatal error in TPM)
289 sign(packet, signingCertificateName);
Yingdi Yu31b4af22014-01-14 14:13:00 -0800290 }
Jeff Thompson3c73da42013-08-12 11:19:05 -0700291
292 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800293 * @brief Sign the byte array using the default certificate of a particular identity.
294 *
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700295 * @param buffer The byte array to be signed.
296 * @param bufferLength the length of buffer.
297 * @param identityName The identity name.
298 * @return The Signature.
299 */
Alexander Afanasyev64a3d812014-01-05 23:35:05 -0800300 Signature
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800301 signByIdentity(const uint8_t* buffer, size_t bufferLength, const Name& identityName)
Yingdi Yu31b4af22014-01-14 14:13:00 -0800302 {
Yingdi Yu2e57a582014-02-20 23:34:43 -0800303 Name signingCertificateName;
304 try
305 {
306 signingCertificateName = Info::getDefaultCertificateNameForIdentity(identityName);
307 }
308 catch(InfoError& e)
309 {
310 signingCertificateName = createIdentity(identityName);
311 // Ideally, no exception will be thrown out, unless something goes wrong in the TPM, which is a fatal error.
312 }
Yingdi Yu31b4af22014-01-14 14:13:00 -0800313
Yingdi Yu2e57a582014-02-20 23:34:43 -0800314 // We either get or create the signing certificate, sign data! (no exception unless fatal error in TPM)
Yingdi Yu31b4af22014-01-14 14:13:00 -0800315 return sign(buffer, bufferLength, signingCertificateName);
316 }
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700317
318 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800319 * @brief Generate a self-signed certificate for a public key.
320 *
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800321 * @param keyName The name of the public key.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800322 * @return The generated certificate, NULL if selfSign fails.
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800323 */
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800324 shared_ptr<IdentityCertificate>
Yingdi Yu31b4af22014-01-14 14:13:00 -0800325 selfSign(const Name& keyName)
326 {
Yingdi Yu2e57a582014-02-20 23:34:43 -0800327 shared_ptr<PublicKey> pubKey;
328 try
329 {
330 pubKey = Info::getPublicKey(keyName); // may throw an exception.
331 }
332 catch(InfoError& e)
333 {
334 return shared_ptr<IdentityCertificate>();
335 }
Yingdi Yu7ea69502014-01-15 17:21:29 -0800336
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800337 shared_ptr<IdentityCertificate> certificate = make_shared<IdentityCertificate>();
Yingdi Yu31b4af22014-01-14 14:13:00 -0800338
339 Name certificateName = keyName.getPrefix(-1);
340 certificateName.append("KEY").append(keyName.get(-1)).append("ID-CERT").appendVersion();
Yingdi Yu2e57a582014-02-20 23:34:43 -0800341
Yingdi Yu31b4af22014-01-14 14:13:00 -0800342 certificate->setName(certificateName);
343 certificate->setNotBefore(getNow());
344 certificate->setNotAfter(getNow() + 630720000 /* 20 years*/);
345 certificate->setPublicKeyInfo(*pubKey);
346 certificate->addSubjectDescription(CertificateSubjectDescription("2.5.4.41", keyName.toUri()));
347 certificate->encode();
348
349 selfSign(*certificate);
350 return certificate;
351 }
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800352
353 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800354 * @brief Self-sign the supplied identity certificate.
355 *
356 * @param cert The supplied cert.
357 * @throws SecTpm::Error if the private key does not exist.
Jeff Thompson8efe5ad2013-08-20 17:36:38 -0700358 */
Jeff Thompson2ce8f492013-09-17 18:01:25 -0700359 void
Yingdi Yu31b4af22014-01-14 14:13:00 -0800360 selfSign (IdentityCertificate& cert)
361 {
Yingdi Yu2e57a582014-02-20 23:34:43 -0800362 Name keyName = IdentityCertificate::certificateNameToPublicKeyName(cert.getName());
363 if(!Tpm::doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE))
364 throw TpmError("private key does not exist!");
365
Yingdi Yu31b4af22014-01-14 14:13:00 -0800366 SignatureSha256WithRsa signature;
367 signature.setKeyLocator(cert.getName().getPrefix(-1)); // implicit conversion should take care
Yingdi Yu31b4af22014-01-14 14:13:00 -0800368
369 // For temporary usage, we support RSA + SHA256 only, but will support more.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800370 signPacketWrapper(cert, signature, keyName, DIGEST_ALGORITHM_SHA256);
Yingdi Yu31b4af22014-01-14 14:13:00 -0800371 }
372
Yingdi Yu2e57a582014-02-20 23:34:43 -0800373 /**
374 * @brief delete a certificate.
375 *
376 * If the certificate to be deleted is current default system default,
377 * the method will not delete the certificate and return immediately.
378 *
379 * @param certificateName The certificate to be deleted.
380 */
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800381 void
Yingdi Yu2e57a582014-02-20 23:34:43 -0800382 deleteCertificate (const Name& certificateName)
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800383 {
Yingdi Yu2e57a582014-02-20 23:34:43 -0800384 try
385 {
386 if(Info::getDefaultCertificateName() == certificateName)
387 return;
388 }
389 catch(InfoError& e)
390 {
391 // Not a real error, just try to delete the certificate
392 }
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800393
394 Info::deleteCertificateInfo(certificateName);
395 }
396
Yingdi Yu2e57a582014-02-20 23:34:43 -0800397 /**
398 * @brief delete a key.
399 *
400 * If the key to be deleted is current default system default,
401 * the method will not delete the key and return immediately.
402 *
403 * @param keyName The key to be deleted.
404 */
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800405 void
Yingdi Yu2e57a582014-02-20 23:34:43 -0800406 deleteKey (const Name& keyName)
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800407 {
Yingdi Yu2e57a582014-02-20 23:34:43 -0800408 try
409 {
410 if(Info::getDefaultKeyNameForIdentity(Info::getDefaultIdentity()) == keyName)
411 return;
412 }
413 catch(InfoError& e)
414 {
415 // Not a real error, just try to delete the key
416 }
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800417
418 Info::deletePublicKeyInfo(keyName);
419 Tpm::deleteKeyPairInTpm(keyName);
420 }
421
Yingdi Yu2e57a582014-02-20 23:34:43 -0800422 /**
423 * @brief delete an identity.
424 *
425 * If the identity to be deleted is current default system default,
426 * the method will not delete the identity and return immediately.
427 *
428 * @param identity The identity to be deleted.
429 */
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800430 void
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800431 deleteIdentity (const Name& identity)
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800432 {
Yingdi Yu2e57a582014-02-20 23:34:43 -0800433 try
434 {
435 if(Info::getDefaultIdentity() == identity)
436 return;
437 }
438 catch(InfoError& e)
439 {
440 // Not a real error, just try to delete the identity
441 }
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800442
443 std::vector<Name> nameList;
444 Info::getAllKeyNamesOfIdentity(identity, nameList, true);
445 Info::getAllKeyNamesOfIdentity(identity, nameList, false);
446
447 Info::deleteIdentityInfo(identity);
448
449 std::vector<Name>::const_iterator it = nameList.begin();
450 for(; it != nameList.end(); it++)
451 Tpm::deleteKeyPairInTpm(*it);
452 }
453
Yingdi Yu2e57a582014-02-20 23:34:43 -0800454 /**
455 * @brief export an identity.
456 *
457 * @param identity The identity to export.
458 * @param passwordStr The password to secure the private key.
459 * @param The encoded export data.
460 * @throws InfoError if anything goes wrong in exporting.
461 */
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800462 Block
Yingdi Yube4150e2014-02-18 13:02:46 -0800463 exportIdentity(const Name& identity, const std::string& passwordStr)
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800464 {
465 if (!Info::doesIdentityExist(identity))
466 throw InfoError("Identity does not exist!");
467
468 Name keyName = Info::getDefaultKeyNameForIdentity(identity);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800469
Yingdi Yu2e57a582014-02-20 23:34:43 -0800470 ConstBufferPtr pkcs8;
471 try
472 {
473 pkcs8 = Tpm::exportPrivateKeyPkcs8FromTpm(keyName, passwordStr);
474 }
475 catch(TpmError& e)
476 {
477 throw InfoError("Fail to export PKCS8 of private key");
478 }
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800479 Block wireKey(tlv::security::KeyPackage, pkcs8);
480
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800481
Yingdi Yu2e57a582014-02-20 23:34:43 -0800482 shared_ptr<IdentityCertificate> cert;
483 try
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800484 {
Yingdi Yu2e57a582014-02-20 23:34:43 -0800485 cert = Info::getCertificate(Info::getDefaultCertificateNameForKey(keyName));
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800486 }
Yingdi Yu2e57a582014-02-20 23:34:43 -0800487 catch(InfoError& e)
488 {
489 cert = selfSign(keyName);
490 Info::addCertificateAsIdentityDefault(*cert);
491 }
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800492 Block wireCert(tlv::security::CertificatePackage, cert->wireEncode());
493
494 Block wire(tlv::security::IdentityPackage);
495 wire.push_back(wireCert);
496 wire.push_back(wireKey);
497
498 return wire;
499 }
500
Yingdi Yu2e57a582014-02-20 23:34:43 -0800501 /**
502 * @brief import an identity.
503 *
504 * @param The encoded import data.
505 * @param passwordStr The password to secure the private key.
506 */
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800507 void
Yingdi Yube4150e2014-02-18 13:02:46 -0800508 importIdentity(const Block& block, const std::string& passwordStr)
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800509 {
Yingdi Yu2e57a582014-02-20 23:34:43 -0800510 try
511 {
512 block.parse();
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800513
Yingdi Yu2e57a582014-02-20 23:34:43 -0800514 Data data;
515 data.wireDecode(block.get(tlv::security::CertificatePackage).blockFromValue());
516 shared_ptr<IdentityCertificate> cert = make_shared<IdentityCertificate>(data);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800517
Yingdi Yu2e57a582014-02-20 23:34:43 -0800518 Name keyName = IdentityCertificate::certificateNameToPublicKeyName(cert->getName());
519 Name identity = keyName.getPrefix(-1);
520
521 // Add identity
522 Info::addIdentity(identity);
523
524 // Add key
525 Block wireKey = block.get(tlv::security::KeyPackage);
526 Tpm::importPrivateKeyPkcs8IntoTpm(keyName, wireKey.value(), wireKey.value_size(), passwordStr);
527 shared_ptr<PublicKey> pubKey = Tpm::getPublicKeyFromTpm(keyName.toUri());
528 Info::addPublicKey(keyName, KEY_TYPE_RSA, *pubKey); // HACK! We should set key type according to the pkcs8 info.
529 Info::setDefaultKeyNameForIdentity(keyName);
530
531 // Add cert
532 Info::addCertificateAsIdentityDefault(*cert);
533 }
534 catch(Block::Error& e)
535 {
536 return;
537 }
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800538 }
539
Jeff Thompson8efe5ad2013-08-20 17:36:38 -0700540
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800541private:
Yingdi Yu2e57a582014-02-20 23:34:43 -0800542 /**
543 * @brief sign a packet using a pariticular certificate.
544 *
545 * @param packet The packet to be signed.
546 * @param certificate The signing certificate.
547 */
548 template<typename T>
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800549 void
Yingdi Yu2e57a582014-02-20 23:34:43 -0800550 sign(T& packet, const IdentityCertificate& certificate)
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800551 {
552 SignatureSha256WithRsa signature;
553 signature.setKeyLocator(certificate.getName().getPrefix(-1));
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800554
555 // For temporary usage, we support RSA + SHA256 only, but will support more.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800556 signPacketWrapper(packet, signature, certificate.getPublicKeyName(), DIGEST_ALGORITHM_SHA256);
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800557 }
558
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800559 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800560 * @brief Generate a key pair for the specified identity.
561 *
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800562 * @param identityName The name of the specified identity.
563 * @param isKsk true for generating a Key-Signing-Key (KSK), false for a Data-Signing-Key (KSK).
564 * @param keyType The type of the key pair, e.g. KEY_TYPE_RSA.
565 * @param keySize The size of the key pair.
566 * @return The name of the generated key.
567 */
568 Name
Yingdi Yu31b4af22014-01-14 14:13:00 -0800569 generateKeyPair(const Name& identityName, bool isKsk = false, KeyType keyType = KEY_TYPE_RSA, int keySize = 2048)
570 {
571 Name keyName = Info::getNewKeyName(identityName, isKsk);
572
573 Tpm::generateKeyPairInTpm(keyName.toUri(), keyType, keySize);
574
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800575 shared_ptr<PublicKey> pubKey = Tpm::getPublicKeyFromTpm(keyName.toUri());
Yingdi Yuef26ee32014-01-15 16:41:14 -0800576 Info::addPublicKey(keyName, keyType, *pubKey);
Yingdi Yu31b4af22014-01-14 14:13:00 -0800577
578 return keyName;
579 }
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800580
Yingdi Yu8726f652014-01-23 10:35:12 -0800581 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800582 * @brief Sign the data using a particular key.
583 *
584 * @param data Reference to the data packet.
585 * @param signature Signature to be added.
Yingdi Yu8726f652014-01-23 10:35:12 -0800586 * @param keyName The name of the signing key.
587 * @param digestAlgorithm the digest algorithm.
588 * @throws Tpm::Error
589 */
590 void
Yingdi Yu2e57a582014-02-20 23:34:43 -0800591 signPacketWrapper(Data& data, const SignatureSha256WithRsa& signature, const Name& keyName, DigestAlgorithm digestAlgorithm)
Yingdi Yu8726f652014-01-23 10:35:12 -0800592 {
Yingdi Yu2e57a582014-02-20 23:34:43 -0800593 data.setSignature(signature);
Yingdi Yu8726f652014-01-23 10:35:12 -0800594 data.setSignatureValue
595 (Tpm::signInTpm(data.wireEncode().value(),
596 data.wireEncode().value_size() - data.getSignature().getValue().size(),
597 keyName, digestAlgorithm));
598 }
599
Yingdi Yu2e57a582014-02-20 23:34:43 -0800600 /**
601 * @brief Sign the interest using a particular key.
602 *
603 * @param interest Reference to the interest packet.
604 * @param signature Signature to be added.
605 * @param keyName The name of the signing key.
606 * @param digestAlgorithm the digest algorithm.
607 * @throws Tpm::Error
608 */
609 void
610 signPacketWrapper(Interest& interest, const SignatureSha256WithRsa& signature, const Name& keyName, DigestAlgorithm digestAlgorithm)
611 {
612 Name signedName = Name(interest.getName()).append(signature.getInfo());
613
614 Block sigValue = Tpm::signInTpm(signedName.wireEncode().value(),
615 signedName.wireEncode().value_size(),
616 keyName,
617 DIGEST_ALGORITHM_SHA256);
618 sigValue.encode();
619 signedName.append(sigValue);
620 interest.setName(signedName);
621 }
622
623
Jeff Thompson47c93cf2013-08-09 00:38:48 -0700624};
625
Yingdi Yufc40d872014-02-18 12:56:04 -0800626} // namespace ndn
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800627
Yingdi Yu04020922014-01-22 12:46:53 -0800628
629
Alexander Afanasyev3e08d5d2014-02-12 19:24:28 -0800630#if defined(NDN_CPP_HAVE_OSX_SECURITY) and defined(NDN_CPP_WITH_OSX_KEYCHAIN)
Yingdi Yu31b4af22014-01-14 14:13:00 -0800631
632namespace ndn
Alexander Afanasyeve64788e2014-01-05 22:38:21 -0800633{
Yingdi Yu31b4af22014-01-14 14:13:00 -0800634typedef KeyChainImpl<SecPublicInfoSqlite3, SecTpmOsx> KeyChain;
635};
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800636
Yingdi Yu31b4af22014-01-14 14:13:00 -0800637#else
Alexander Afanasyeve64788e2014-01-05 22:38:21 -0800638
Yingdi Yu31b4af22014-01-14 14:13:00 -0800639namespace ndn
Alexander Afanasyeve64788e2014-01-05 22:38:21 -0800640{
Yingdi Yu04020922014-01-22 12:46:53 -0800641typedef KeyChainImpl<SecPublicInfoSqlite3, SecTpmFile> KeyChain;
Yingdi Yu31b4af22014-01-14 14:13:00 -0800642};
Alexander Afanasyeve64788e2014-01-05 22:38:21 -0800643
Yingdi Yu31b4af22014-01-14 14:13:00 -0800644#endif //NDN_CPP_HAVE_OSX_SECURITY
Jeff Thompson47c93cf2013-08-09 00:38:48 -0700645
Yingdi Yufc40d872014-02-18 12:56:04 -0800646#endif //NDN_SECURITY_KEY_CHAIN_HPP