blob: b9cb2d4f695efc3802d1a5193d698b429dad26e5 [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 Yu31b4af22014-01-14 14:13:00 -080017
Yingdi Yu04020922014-01-22 12:46:53 -080018//PublicInfo
Yingdi Yu4f324632014-01-15 18:10:03 -080019#include "sec-public-info-sqlite3.hpp"
20#include "sec-public-info-memory.hpp"
Yingdi Yu04020922014-01-22 12:46:53 -080021//TPM
22#include "sec-tpm-file.hpp"
Yingdi Yu4f324632014-01-15 18:10:03 -080023#include "sec-tpm-memory.hpp"
Yingdi Yu2abd73f2014-01-08 23:34:11 -080024
Yingdi Yu04020922014-01-22 12:46:53 -080025#ifdef NDN_CPP_HAVE_OSX_SECURITY
26#include "sec-tpm-osx.hpp"
27#endif
28
Jeff Thompson47c93cf2013-08-09 00:38:48 -070029
30namespace ndn {
31
Jeff Thompson2ce8f492013-09-17 18:01:25 -070032/**
Yingdi Yu2abd73f2014-01-08 23:34:11 -080033 * KeyChain is one of the main classes of the security library.
Jeff Thompsonffa36f92013-09-20 08:42:41 -070034 *
Yingdi Yu2abd73f2014-01-08 23:34:11 -080035 * The KeyChain class provides a set of interfaces of identity management and private key related operations.
Jeff Thompsonffa36f92013-09-20 08:42:41 -070036 */
Yingdi Yu31b4af22014-01-14 14:13:00 -080037template<class Info, class Tpm>
38class KeyChainImpl : public Info, public Tpm
39{
Yingdi Yu4270f202014-01-28 14:19:16 -080040 typedef typename Info::Error InfoError;
Jeff Thompson47c93cf2013-08-09 00:38:48 -070041public:
Yingdi Yube4150e2014-02-18 13:02:46 -080042
43 /**
44 * @brief Unlock key chain
45 *
46 * @param password The password.
47 * @param passwordLength The password size.
48 * @param usePassword True if password parameter is used.
49 */
50 void
51 unlock(const char* password, size_t passwordLength, bool usePassword)
52 {
53 return Tpm::unlockTpm(password, passwordLength, usePassword);
54 }
55
Yingdi Yu2abd73f2014-01-08 23:34:11 -080056
57 /**
58 * Create an identity by creating a pair of Key-Signing-Key (KSK) for this identity and a self-signed certificate of the KSK.
59 * @param identityName The name of the identity.
Yingdi Yu28fd32f2014-01-28 19:03:03 -080060 * @return The name of the default certificate of the identity.
Yingdi Yu2abd73f2014-01-08 23:34:11 -080061 */
62 Name
Yingdi Yu31b4af22014-01-14 14:13:00 -080063 createIdentity(const Name& identityName)
64 {
Yingdi Yu28fd32f2014-01-28 19:03:03 -080065 if (!Info::doesIdentityExist(identityName))
Yingdi Yu31b4af22014-01-14 14:13:00 -080066 Info::addIdentity(identityName);
Yingdi Yu28fd32f2014-01-28 19:03:03 -080067
68 Name keyName = Info::getDefaultKeyNameForIdentity(identityName);
69
70 if(keyName.empty())
71 keyName = generateRSAKeyPairAsDefault(identityName, true);
Yingdi Yu31b4af22014-01-14 14:13:00 -080072
Yingdi Yu28fd32f2014-01-28 19:03:03 -080073 Name certName = Info::getDefaultCertificateNameForKey(keyName);
Yingdi Yu31b4af22014-01-14 14:13:00 -080074
Yingdi Yu28fd32f2014-01-28 19:03:03 -080075 if(certName.empty())
76 {
Yingdi Yu8dceb1d2014-02-18 12:45:10 -080077 shared_ptr<IdentityCertificate> selfCert = selfSign(keyName);
Yingdi Yu28fd32f2014-01-28 19:03:03 -080078 Info::addCertificateAsIdentityDefault(*selfCert);
79 certName = selfCert->getName();
80 }
81
82 return certName;
Yingdi Yu31b4af22014-01-14 14:13:00 -080083 }
Yingdi Yu2abd73f2014-01-08 23:34:11 -080084
85 /**
Yingdi Yu2abd73f2014-01-08 23:34:11 -080086 * Generate a pair of RSA keys for the specified identity.
87 * @param identityName The name of the identity.
88 * @param isKsk true for generating a Key-Signing-Key (KSK), false for a Data-Signing-Key (KSK).
89 * @param keySize The size of the key.
90 * @return The generated key name.
91 */
92 Name
Yingdi Yu31b4af22014-01-14 14:13:00 -080093 generateRSAKeyPair(const Name& identityName, bool isKsk = false, int keySize = 2048)
Yingdi Yu2abd73f2014-01-08 23:34:11 -080094 {
Yingdi Yu31b4af22014-01-14 14:13:00 -080095 return generateKeyPair(identityName, isKsk, KEY_TYPE_RSA, keySize);
Yingdi Yu2abd73f2014-01-08 23:34:11 -080096 }
Alexander Afanasyev64a3d812014-01-05 23:35:05 -080097
Yingdi Yu2abd73f2014-01-08 23:34:11 -080098 /**
99 * Generate a pair of RSA keys for the specified identity and set it as default key for the identity.
100 * @param identityName The name of the identity.
101 * @param isKsk true for generating a Key-Signing-Key (KSK), false for a Data-Signing-Key (KSK).
102 * @param keySize The size of the key.
103 * @return The generated key name.
104 */
105 Name
Yingdi Yu31b4af22014-01-14 14:13:00 -0800106 generateRSAKeyPairAsDefault(const Name& identityName, bool isKsk = false, int keySize = 2048)
107 {
108 Name keyName = generateKeyPair(identityName, isKsk, KEY_TYPE_RSA, keySize);
109
110 Info::setDefaultKeyNameForIdentity(keyName);
Yingdi Yu31b4af22014-01-14 14:13:00 -0800111
112 return keyName;
113 }
Jeff Thompson79a2d5d2013-09-27 14:32:23 -0700114
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800115 /**
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800116 * Create an identity certificate for a public key managed by this IdentityManager.
117 * @param certificatePrefix The name of public key to be signed.
118 * @param signerCertificateName The name of signing certificate.
119 * @param notBefore The notBefore value in the validity field of the generated certificate.
120 * @param notAfter The notAfter vallue in validity field of the generated certificate.
121 * @return The name of generated identity certificate.
122 */
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800123 shared_ptr<IdentityCertificate>
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800124 createIdentityCertificate
125 (const Name& certificatePrefix,
126 const Name& signerCertificateName,
127 const MillisecondsSince1970& notBefore,
Yingdi Yu31b4af22014-01-14 14:13:00 -0800128 const MillisecondsSince1970& notAfter)
129 {
130 Name keyName = getKeyNameFromCertificatePrefix(certificatePrefix);
131
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800132 shared_ptr<PublicKey> pubKey = Info::getPublicKey(keyName);
Yingdi Yu31b4af22014-01-14 14:13:00 -0800133 if (!pubKey)
Yingdi Yu4270f202014-01-28 14:19:16 -0800134 throw InfoError("Requested public key [" + keyName.toUri() + "] doesn't exist");
Yingdi Yu31b4af22014-01-14 14:13:00 -0800135
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800136 shared_ptr<IdentityCertificate> certificate =
Yingdi Yu31b4af22014-01-14 14:13:00 -0800137 createIdentityCertificate(certificatePrefix,
138 *pubKey,
139 signerCertificateName,
140 notBefore, notAfter);
141
142 Info::addCertificate(*certificate);
143
144 return certificate;
145 }
146
Jeff Thompson79a2d5d2013-09-27 14:32:23 -0700147
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800148 /**
149 * Create an identity certificate for a public key supplied by the caller.
150 * @param certificatePrefix The name of public key to be signed.
151 * @param publickey The public key to be signed.
152 * @param signerCertificateName The name of signing certificate.
153 * @param notBefore The notBefore value in the validity field of the generated certificate.
154 * @param notAfter The notAfter vallue in validity field of the generated certificate.
155 * @return The generated identity certificate.
156 */
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800157 shared_ptr<IdentityCertificate>
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800158 createIdentityCertificate
159 (const Name& certificatePrefix,
Yingdi Yu31b4af22014-01-14 14:13:00 -0800160 const PublicKey& publicKey,
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800161 const Name& signerCertificateName,
162 const MillisecondsSince1970& notBefore,
Yingdi Yu31b4af22014-01-14 14:13:00 -0800163 const MillisecondsSince1970& notAfter)
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800164 {
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800165 shared_ptr<IdentityCertificate> certificate (new IdentityCertificate());
Yingdi Yu31b4af22014-01-14 14:13:00 -0800166 Name keyName = getKeyNameFromCertificatePrefix(certificatePrefix);
167
168 Name certificateName = certificatePrefix;
169 certificateName.append("ID-CERT").appendVersion();
170
171 certificate->setName(certificateName);
172 certificate->setNotBefore(notBefore);
173 certificate->setNotAfter(notAfter);
174 certificate->setPublicKeyInfo(publicKey);
175 certificate->addSubjectDescription(CertificateSubjectDescription("2.5.4.41", keyName.toUri()));
176 certificate->encode();
177
178 sign(*certificate, signerCertificateName);
179
180 return certificate;
Alexander Afanasyevbf1a67a2014-01-05 23:36:13 -0800181 }
182
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800183 void
Yingdi Yu31b4af22014-01-14 14:13:00 -0800184 sign(Data &data)
185 {
186 if (!Info::defaultCertificate())
187 {
188 Info::refreshDefaultCertificate();
189
190 if(!Info::defaultCertificate())
Yingdi Yu4270f202014-01-28 14:19:16 -0800191 throw InfoError("Default IdentityCertificate cannot be determined");
Yingdi Yu31b4af22014-01-14 14:13:00 -0800192 }
193
194 sign(data, *Info::defaultCertificate());
195 }
Yingdi Yu4270f202014-01-28 14:19:16 -0800196
197 void
198 sign(Interest &interest)
199 {
200 if (!Info::defaultCertificate())
201 {
202 Info::refreshDefaultCertificate();
203
204 if(!Info::defaultCertificate())
205 throw InfoError("Default IdentityCertificate cannot be determined");
206 }
207
208 sign(interest, *Info::defaultCertificate());
209 }
Alexander Afanasyeve64788e2014-01-05 22:38:21 -0800210
Jeff Thompson47c93cf2013-08-09 00:38:48 -0700211 /**
Jeff Thompson2ce8f492013-09-17 18:01:25 -0700212 * Wire encode the Data object, sign it and set its signature.
Jeff Thompson2ce8f492013-09-17 18:01:25 -0700213 * @param data The Data object to be signed. This updates its signature and key locator field and wireEncoding.
Jeff Thompson9296f0c2013-09-23 18:10:27 -0700214 * @param certificateName The certificate name of the key to use for signing. If omitted, infer the signing identity from the data packet name.
Jeff Thompson3c73da42013-08-12 11:19:05 -0700215 */
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800216 void
Yingdi Yu31b4af22014-01-14 14:13:00 -0800217 sign(Data& data, const Name& certificateName)
218 {
Yingdi Yu17bc3012014-02-10 17:37:12 -0800219 shared_ptr<IdentityCertificate> cert = Info::getCertificate(certificateName);
Yingdi Yu31b4af22014-01-14 14:13:00 -0800220 if (!cert)
Yingdi Yu4270f202014-01-28 14:19:16 -0800221 throw InfoError("Requested certificate [" + certificateName.toUri() + "] doesn't exist");
Yingdi Yu31b4af22014-01-14 14:13:00 -0800222
223 SignatureSha256WithRsa signature;
224 signature.setKeyLocator(certificateName.getPrefix(-1)); // implicit conversion should take care
225 data.setSignature(signature);
226
227 // For temporary usage, we support RSA + SHA256 only, but will support more.
Yingdi Yu8726f652014-01-23 10:35:12 -0800228 signDataInTpm(data, cert->getPublicKeyName(), DIGEST_ALGORITHM_SHA256);
Yingdi Yu31b4af22014-01-14 14:13:00 -0800229 }
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800230
231 void
Yingdi Yu4270f202014-01-28 14:19:16 -0800232 sign(Interest &interest, const Name &certificateName)
233 {
Yingdi Yu17bc3012014-02-10 17:37:12 -0800234 shared_ptr<IdentityCertificate> cert = Info::getCertificate(certificateName);
Yingdi Yu4270f202014-01-28 14:19:16 -0800235 if(!static_cast<bool>(cert))
236 throw InfoError("Requested certificate [" + certificateName.toUri() + "] doesn't exist");
237
238 SignatureSha256WithRsa signature;
239 signature.setKeyLocator(certificateName.getPrefix(-1)); // implicit conversion should take care
240
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800241 Name signedName = Name(interest.getName()).append(signature.getInfo());
Yingdi Yu4270f202014-01-28 14:19:16 -0800242
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800243 signature.setValue(Tpm::signInTpm(signedName.wireEncode().value(),
244 signedName.wireEncode().value_size(),
Yingdi Yu4270f202014-01-28 14:19:16 -0800245 cert->getPublicKeyName(),
246 DIGEST_ALGORITHM_SHA256));
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800247 signedName.append(signature.getValue());
248 interest.setName(signedName);
Yingdi Yu4270f202014-01-28 14:19:16 -0800249 }
Jeff Thompson79a2d5d2013-09-27 14:32:23 -0700250
Jeff Thompson29ce3102013-09-27 11:47:48 -0700251 /**
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700252 * Sign the byte array using a certificate name and return a Signature object.
253 * @param buffer The byte array to be signed.
254 * @param bufferLength the length of buffer.
255 * @param certificateName The certificate name used to get the signing key and which will be put into KeyLocator.
256 * @return The Signature.
257 */
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800258 Signature
Yingdi Yu31b4af22014-01-14 14:13:00 -0800259 sign(const uint8_t* buffer, size_t bufferLength, const Name& certificateName)
260 {
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800261 shared_ptr<IdentityCertificate> cert = Info::getCertificate(certificateName);
Yingdi Yu4270f202014-01-28 14:19:16 -0800262 if (!static_cast<bool>(cert))
263 throw InfoError("Requested certificate [" + certificateName.toUri() + "] doesn't exist");
Yingdi Yu31b4af22014-01-14 14:13:00 -0800264
265 SignatureSha256WithRsa signature;
266 signature.setKeyLocator(certificateName.getPrefix(-1)); // implicit conversion should take care
267
268 // For temporary usage, we support RSA + SHA256 only, but will support more.
Yingdi Yub4bb85a2014-01-16 10:11:04 -0800269 signature.setValue(Tpm::signInTpm(buffer, bufferLength, cert->getPublicKeyName(), DIGEST_ALGORITHM_SHA256));
Yingdi Yu31b4af22014-01-14 14:13:00 -0800270 return signature;
271 }
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700272
273 /**
Jeff Thompson29ce3102013-09-27 11:47:48 -0700274 * Wire encode the Data object, sign it and set its signature.
Jeff Thompson29ce3102013-09-27 11:47:48 -0700275 * @param data The Data object to be signed. This updates its signature and key locator field and wireEncoding.
276 * @param identityName The identity name for the key to use for signing. If omitted, infer the signing identity from the data packet name.
Jeff Thompson29ce3102013-09-27 11:47:48 -0700277 */
278 void
Yingdi Yu4270f202014-01-28 14:19:16 -0800279 signByIdentity(Data& data, const Name& identityName)
Yingdi Yu31b4af22014-01-14 14:13:00 -0800280 {
281 Name signingCertificateName = Info::getDefaultCertificateNameForIdentity(identityName);
282
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800283 if (signingCertificateName.empty())
284 signingCertificateName = createIdentity(identityName);
Yingdi Yu31b4af22014-01-14 14:13:00 -0800285
286 sign(data, signingCertificateName);
287 }
Jeff Thompson3c73da42013-08-12 11:19:05 -0700288
Yingdi Yu4270f202014-01-28 14:19:16 -0800289 void
290 signByIdentity(Interest& interest, const Name& identityName)
291 {
292 Name signingCertificateName = Info::getDefaultCertificateNameForIdentity(identityName);
293
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800294 if (signingCertificateName.empty())
295 signingCertificateName = createIdentity(identityName);
Yingdi Yu4270f202014-01-28 14:19:16 -0800296
297 sign(interest, signingCertificateName);
298 }
299
300
Jeff Thompson3c73da42013-08-12 11:19:05 -0700301 /**
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700302 * Sign the byte array using an identity name and return a Signature object.
303 * @param buffer The byte array to be signed.
304 * @param bufferLength the length of buffer.
305 * @param identityName The identity name.
306 * @return The Signature.
307 */
Alexander Afanasyev64a3d812014-01-05 23:35:05 -0800308 Signature
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800309 signByIdentity(const uint8_t* buffer, size_t bufferLength, const Name& identityName)
Yingdi Yu31b4af22014-01-14 14:13:00 -0800310 {
311 Name signingCertificateName = Info::getDefaultCertificateNameForIdentity(identityName);
312
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800313 if (signingCertificateName.empty())
314 signingCertificateName = createIdentity(identityName);
Yingdi Yu31b4af22014-01-14 14:13:00 -0800315
316 return sign(buffer, bufferLength, signingCertificateName);
317 }
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700318
319 /**
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800320 * Generate a self-signed certificate for a public key.
321 * @param keyName The name of the public key.
322 * @return The generated certificate.
323 */
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 Yu7ea69502014-01-15 17:21:29 -0800327 if(keyName.empty())
Yingdi Yu4270f202014-01-28 14:19:16 -0800328 throw InfoError("Incorrect key name: " + keyName.toUri());
Yingdi Yu7ea69502014-01-15 17:21:29 -0800329
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800330 shared_ptr<IdentityCertificate> certificate = make_shared<IdentityCertificate>();
Yingdi Yu31b4af22014-01-14 14:13:00 -0800331
332 Name certificateName = keyName.getPrefix(-1);
333 certificateName.append("KEY").append(keyName.get(-1)).append("ID-CERT").appendVersion();
334
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800335 shared_ptr<PublicKey> pubKey = Info::getPublicKey(keyName);
Yingdi Yu31b4af22014-01-14 14:13:00 -0800336 if (!pubKey)
Yingdi Yu4270f202014-01-28 14:19:16 -0800337 throw InfoError("Requested public key [" + keyName.toUri() + "] doesn't exist");
Yingdi Yu31b4af22014-01-14 14:13:00 -0800338
339 certificate->setName(certificateName);
340 certificate->setNotBefore(getNow());
341 certificate->setNotAfter(getNow() + 630720000 /* 20 years*/);
342 certificate->setPublicKeyInfo(*pubKey);
343 certificate->addSubjectDescription(CertificateSubjectDescription("2.5.4.41", keyName.toUri()));
344 certificate->encode();
345
346 selfSign(*certificate);
347 return certificate;
348 }
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800349
350 /**
351 * @brief Self-sign the supplied identity certificate
Jeff Thompson8efe5ad2013-08-20 17:36:38 -0700352 */
Jeff Thompson2ce8f492013-09-17 18:01:25 -0700353 void
Yingdi Yu31b4af22014-01-14 14:13:00 -0800354 selfSign (IdentityCertificate& cert)
355 {
356 SignatureSha256WithRsa signature;
357 signature.setKeyLocator(cert.getName().getPrefix(-1)); // implicit conversion should take care
358 cert.setSignature(signature);
359
360 // For temporary usage, we support RSA + SHA256 only, but will support more.
Yingdi Yu8726f652014-01-23 10:35:12 -0800361 signDataInTpm(cert, cert.getPublicKeyName(), DIGEST_ALGORITHM_SHA256);
Yingdi Yu31b4af22014-01-14 14:13:00 -0800362 }
363
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800364 void
365 deleteCertificate (const Name &certificateName)
366 {
367 if(Info::getDefaultIdentity() == IdentityCertificate::certificateNameToPublicKeyName(certificateName).getPrefix(-1))
368 return;
369
370 Info::deleteCertificateInfo(certificateName);
371 }
372
373 void
374 deleteKey (const Name &keyName)
375 {
376 if(Info::getDefaultIdentity() == keyName.getPrefix(-1))
377 return;
378
379 Info::deletePublicKeyInfo(keyName);
380 Tpm::deleteKeyPairInTpm(keyName);
381 }
382
383 void
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800384 deleteIdentity (const Name& identity)
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800385 {
386 if(Info::getDefaultIdentity() == identity)
387 return;
388
389 std::vector<Name> nameList;
390 Info::getAllKeyNamesOfIdentity(identity, nameList, true);
391 Info::getAllKeyNamesOfIdentity(identity, nameList, false);
392
393 Info::deleteIdentityInfo(identity);
394
395 std::vector<Name>::const_iterator it = nameList.begin();
396 for(; it != nameList.end(); it++)
397 Tpm::deleteKeyPairInTpm(*it);
398 }
399
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800400 Block
Yingdi Yube4150e2014-02-18 13:02:46 -0800401 exportIdentity(const Name& identity, const std::string& passwordStr)
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800402 {
403 if (!Info::doesIdentityExist(identity))
404 throw InfoError("Identity does not exist!");
405
406 Name keyName = Info::getDefaultKeyNameForIdentity(identity);
407
408 if(keyName.empty())
409 throw InfoError("Default key does not exist!");
410
Yingdi Yube4150e2014-02-18 13:02:46 -0800411 ConstBufferPtr pkcs8 = Tpm::exportPrivateKeyPkcs8FromTpm(keyName, passwordStr);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800412 Block wireKey(tlv::security::KeyPackage, pkcs8);
413
414 Name certName = Info::getDefaultCertificateNameForKey(keyName);
415
416 if(certName.empty())
417 {
418 shared_ptr<IdentityCertificate> selfCert = selfSign(keyName);
419 Info::addCertificateAsIdentityDefault(*selfCert);
420 certName = selfCert->getName();
421 }
422
423 shared_ptr<IdentityCertificate> cert = Info::getCertificate(certName);
424 Block wireCert(tlv::security::CertificatePackage, cert->wireEncode());
425
426 Block wire(tlv::security::IdentityPackage);
427 wire.push_back(wireCert);
428 wire.push_back(wireKey);
429
430 return wire;
431 }
432
433 void
Yingdi Yube4150e2014-02-18 13:02:46 -0800434 importIdentity(const Block& block, const std::string& passwordStr)
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800435 {
436 block.parse();
437
438 Data data;
439 data.wireDecode(block.get(tlv::security::CertificatePackage).blockFromValue());
440 shared_ptr<IdentityCertificate> cert = make_shared<IdentityCertificate>(data);
441
442 Name keyName = IdentityCertificate::certificateNameToPublicKeyName(cert->getName());
443 Name identity = keyName.getPrefix(-1);
444
445 // Add identity
446 if (Info::doesIdentityExist(identity))
447 deleteIdentity(identity);
448 Info::addIdentity(identity);
449
450 // Add key
451 Block wireKey = block.get(tlv::security::KeyPackage);
452 if (Tpm::doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE))
453 deleteKey(keyName);
Yingdi Yube4150e2014-02-18 13:02:46 -0800454 Tpm::importPrivateKeyPkcs8IntoTpm(keyName, wireKey.value(), wireKey.value_size(), passwordStr);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800455 shared_ptr<PublicKey> pubKey = Tpm::getPublicKeyFromTpm(keyName.toUri());
456 Info::addPublicKey(keyName, KEY_TYPE_RSA, *pubKey); // HACK! We should set key type according to the pkcs8 info.
457 Info::setDefaultKeyNameForIdentity(keyName);
458
459 // Add cert
460 if (Info::doesCertificateExist(cert->getName()))
461 deleteCertificate(cert->getName());
462 Info::addCertificateAsIdentityDefault(*cert);
463 }
464
Jeff Thompson8efe5ad2013-08-20 17:36:38 -0700465
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800466private:
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800467
468 void
469 sign(Data &data, const IdentityCertificate& certificate)
470 {
471 SignatureSha256WithRsa signature;
472 signature.setKeyLocator(certificate.getName().getPrefix(-1));
473 data.setSignature(signature);
474
475 // For temporary usage, we support RSA + SHA256 only, but will support more.
476 signDataInTpm(data, certificate.getPublicKeyName(), DIGEST_ALGORITHM_SHA256);
477 }
478
479 void
480 sign(Interest &interest, const IdentityCertificate& certificate)
481 {
482 SignatureSha256WithRsa signature;
483 signature.setKeyLocator(certificate.getName().getPrefix(-1)); // implicit conversion should take care
484
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800485 Name signedName = Name(interest.getName()).append(signature.getInfo());
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800486
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800487 signature.setValue(Tpm::signInTpm(signedName.wireEncode().value(),
488 signedName.wireEncode().value_size(),
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800489 certificate.getPublicKeyName(),
490 DIGEST_ALGORITHM_SHA256));
491
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800492 signedName.append(signature.getValue());
493 interest.setName(signedName);
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800494 }
495
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800496 /**
497 * Generate a key pair for the specified identity.
498 * @param identityName The name of the specified identity.
499 * @param isKsk true for generating a Key-Signing-Key (KSK), false for a Data-Signing-Key (KSK).
500 * @param keyType The type of the key pair, e.g. KEY_TYPE_RSA.
501 * @param keySize The size of the key pair.
502 * @return The name of the generated key.
503 */
504 Name
Yingdi Yu31b4af22014-01-14 14:13:00 -0800505 generateKeyPair(const Name& identityName, bool isKsk = false, KeyType keyType = KEY_TYPE_RSA, int keySize = 2048)
506 {
507 Name keyName = Info::getNewKeyName(identityName, isKsk);
508
509 Tpm::generateKeyPairInTpm(keyName.toUri(), keyType, keySize);
510
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800511 shared_ptr<PublicKey> pubKey = Tpm::getPublicKeyFromTpm(keyName.toUri());
Yingdi Yuef26ee32014-01-15 16:41:14 -0800512 Info::addPublicKey(keyName, keyType, *pubKey);
Yingdi Yu31b4af22014-01-14 14:13:00 -0800513
514 return keyName;
515 }
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800516
517 static Name
Yingdi Yu31b4af22014-01-14 14:13:00 -0800518 getKeyNameFromCertificatePrefix(const Name& certificatePrefix)
519 {
520 Name result;
Alexander Afanasyevbf1a67a2014-01-05 23:36:13 -0800521
Yingdi Yu31b4af22014-01-14 14:13:00 -0800522 std::string keyString("KEY");
523 int i = 0;
524 for(; i < certificatePrefix.size(); i++) {
525 if (certificatePrefix.get(i).toEscapedString() == keyString)
526 break;
527 }
Alexander Afanasyevbf1a67a2014-01-05 23:36:13 -0800528
Yingdi Yu31b4af22014-01-14 14:13:00 -0800529 if (i >= certificatePrefix.size())
Yingdi Yu4270f202014-01-28 14:19:16 -0800530 throw InfoError("Identity Certificate Prefix does not have a KEY component");
Alexander Afanasyevbd5ba402014-01-05 22:41:09 -0800531
Yingdi Yu31b4af22014-01-14 14:13:00 -0800532 result.append(certificatePrefix.getSubName(0, i));
533 result.append(certificatePrefix.getSubName(i + 1, certificatePrefix.size()-i-1));
534
535 return result;
536 }
537
Yingdi Yu8726f652014-01-23 10:35:12 -0800538 /**
539 * Fetch the private key for keyName and sign the data, and set the signature block of the data packet.
540 * @param data Reference to the input data packet.
541 * @param keyName The name of the signing key.
542 * @param digestAlgorithm the digest algorithm.
543 * @throws Tpm::Error
544 */
545 void
546 signDataInTpm(Data &data, const Name& keyName, DigestAlgorithm digestAlgorithm)
547 {
548 data.setSignatureValue
549 (Tpm::signInTpm(data.wireEncode().value(),
550 data.wireEncode().value_size() - data.getSignature().getValue().size(),
551 keyName, digestAlgorithm));
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