blob: 7a3ff42848141c9b3b01d52d3f7e1c9265460a8f [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 Yu2abd73f2014-01-08 23:34:11 -080042
43 /**
44 * Create an identity by creating a pair of Key-Signing-Key (KSK) for this identity and a self-signed certificate of the KSK.
45 * @param identityName The name of the identity.
Yingdi Yu28fd32f2014-01-28 19:03:03 -080046 * @return The name of the default certificate of the identity.
Yingdi Yu2abd73f2014-01-08 23:34:11 -080047 */
48 Name
Yingdi Yu31b4af22014-01-14 14:13:00 -080049 createIdentity(const Name& identityName)
50 {
Yingdi Yu28fd32f2014-01-28 19:03:03 -080051 if (!Info::doesIdentityExist(identityName))
Yingdi Yu31b4af22014-01-14 14:13:00 -080052 Info::addIdentity(identityName);
Yingdi Yu28fd32f2014-01-28 19:03:03 -080053
54 Name keyName = Info::getDefaultKeyNameForIdentity(identityName);
55
56 if(keyName.empty())
57 keyName = generateRSAKeyPairAsDefault(identityName, true);
Yingdi Yu31b4af22014-01-14 14:13:00 -080058
Yingdi Yu28fd32f2014-01-28 19:03:03 -080059 Name certName = Info::getDefaultCertificateNameForKey(keyName);
Yingdi Yu31b4af22014-01-14 14:13:00 -080060
Yingdi Yu28fd32f2014-01-28 19:03:03 -080061 if(certName.empty())
62 {
Yingdi Yu8dceb1d2014-02-18 12:45:10 -080063 shared_ptr<IdentityCertificate> selfCert = selfSign(keyName);
Yingdi Yu28fd32f2014-01-28 19:03:03 -080064 Info::addCertificateAsIdentityDefault(*selfCert);
65 certName = selfCert->getName();
66 }
67
68 return certName;
Yingdi Yu31b4af22014-01-14 14:13:00 -080069 }
Yingdi Yu2abd73f2014-01-08 23:34:11 -080070
71 /**
Yingdi Yu2abd73f2014-01-08 23:34:11 -080072 * Generate a pair of RSA keys for the specified identity.
73 * @param identityName The name of the identity.
74 * @param isKsk true for generating a Key-Signing-Key (KSK), false for a Data-Signing-Key (KSK).
75 * @param keySize The size of the key.
76 * @return The generated key name.
77 */
78 Name
Yingdi Yu31b4af22014-01-14 14:13:00 -080079 generateRSAKeyPair(const Name& identityName, bool isKsk = false, int keySize = 2048)
Yingdi Yu2abd73f2014-01-08 23:34:11 -080080 {
Yingdi Yu31b4af22014-01-14 14:13:00 -080081 return generateKeyPair(identityName, isKsk, KEY_TYPE_RSA, keySize);
Yingdi Yu2abd73f2014-01-08 23:34:11 -080082 }
Alexander Afanasyev64a3d812014-01-05 23:35:05 -080083
Yingdi Yu2abd73f2014-01-08 23:34:11 -080084 /**
85 * Generate a pair of RSA keys for the specified identity and set it as default key for the identity.
86 * @param identityName The name of the identity.
87 * @param isKsk true for generating a Key-Signing-Key (KSK), false for a Data-Signing-Key (KSK).
88 * @param keySize The size of the key.
89 * @return The generated key name.
90 */
91 Name
Yingdi Yu31b4af22014-01-14 14:13:00 -080092 generateRSAKeyPairAsDefault(const Name& identityName, bool isKsk = false, int keySize = 2048)
93 {
94 Name keyName = generateKeyPair(identityName, isKsk, KEY_TYPE_RSA, keySize);
95
96 Info::setDefaultKeyNameForIdentity(keyName);
Yingdi Yu31b4af22014-01-14 14:13:00 -080097
98 return keyName;
99 }
Jeff Thompson79a2d5d2013-09-27 14:32:23 -0700100
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800101 /**
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800102 * Create an identity certificate for a public key managed by this IdentityManager.
103 * @param certificatePrefix The name of public key to be signed.
104 * @param signerCertificateName The name of signing certificate.
105 * @param notBefore The notBefore value in the validity field of the generated certificate.
106 * @param notAfter The notAfter vallue in validity field of the generated certificate.
107 * @return The name of generated identity certificate.
108 */
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800109 shared_ptr<IdentityCertificate>
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800110 createIdentityCertificate
111 (const Name& certificatePrefix,
112 const Name& signerCertificateName,
113 const MillisecondsSince1970& notBefore,
Yingdi Yu31b4af22014-01-14 14:13:00 -0800114 const MillisecondsSince1970& notAfter)
115 {
116 Name keyName = getKeyNameFromCertificatePrefix(certificatePrefix);
117
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800118 shared_ptr<PublicKey> pubKey = Info::getPublicKey(keyName);
Yingdi Yu31b4af22014-01-14 14:13:00 -0800119 if (!pubKey)
Yingdi Yu4270f202014-01-28 14:19:16 -0800120 throw InfoError("Requested public key [" + keyName.toUri() + "] doesn't exist");
Yingdi Yu31b4af22014-01-14 14:13:00 -0800121
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800122 shared_ptr<IdentityCertificate> certificate =
Yingdi Yu31b4af22014-01-14 14:13:00 -0800123 createIdentityCertificate(certificatePrefix,
124 *pubKey,
125 signerCertificateName,
126 notBefore, notAfter);
127
128 Info::addCertificate(*certificate);
129
130 return certificate;
131 }
132
Jeff Thompson79a2d5d2013-09-27 14:32:23 -0700133
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800134 /**
135 * Create an identity certificate for a public key supplied by the caller.
136 * @param certificatePrefix The name of public key to be signed.
137 * @param publickey The public key to be signed.
138 * @param signerCertificateName The name of signing certificate.
139 * @param notBefore The notBefore value in the validity field of the generated certificate.
140 * @param notAfter The notAfter vallue in validity field of the generated certificate.
141 * @return The generated identity certificate.
142 */
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800143 shared_ptr<IdentityCertificate>
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800144 createIdentityCertificate
145 (const Name& certificatePrefix,
Yingdi Yu31b4af22014-01-14 14:13:00 -0800146 const PublicKey& publicKey,
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800147 const Name& signerCertificateName,
148 const MillisecondsSince1970& notBefore,
Yingdi Yu31b4af22014-01-14 14:13:00 -0800149 const MillisecondsSince1970& notAfter)
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800150 {
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800151 shared_ptr<IdentityCertificate> certificate (new IdentityCertificate());
Yingdi Yu31b4af22014-01-14 14:13:00 -0800152 Name keyName = getKeyNameFromCertificatePrefix(certificatePrefix);
153
154 Name certificateName = certificatePrefix;
155 certificateName.append("ID-CERT").appendVersion();
156
157 certificate->setName(certificateName);
158 certificate->setNotBefore(notBefore);
159 certificate->setNotAfter(notAfter);
160 certificate->setPublicKeyInfo(publicKey);
161 certificate->addSubjectDescription(CertificateSubjectDescription("2.5.4.41", keyName.toUri()));
162 certificate->encode();
163
164 sign(*certificate, signerCertificateName);
165
166 return certificate;
Alexander Afanasyevbf1a67a2014-01-05 23:36:13 -0800167 }
168
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800169 void
Yingdi Yu31b4af22014-01-14 14:13:00 -0800170 sign(Data &data)
171 {
172 if (!Info::defaultCertificate())
173 {
174 Info::refreshDefaultCertificate();
175
176 if(!Info::defaultCertificate())
Yingdi Yu4270f202014-01-28 14:19:16 -0800177 throw InfoError("Default IdentityCertificate cannot be determined");
Yingdi Yu31b4af22014-01-14 14:13:00 -0800178 }
179
180 sign(data, *Info::defaultCertificate());
181 }
Yingdi Yu4270f202014-01-28 14:19:16 -0800182
183 void
184 sign(Interest &interest)
185 {
186 if (!Info::defaultCertificate())
187 {
188 Info::refreshDefaultCertificate();
189
190 if(!Info::defaultCertificate())
191 throw InfoError("Default IdentityCertificate cannot be determined");
192 }
193
194 sign(interest, *Info::defaultCertificate());
195 }
Alexander Afanasyeve64788e2014-01-05 22:38:21 -0800196
Jeff Thompson47c93cf2013-08-09 00:38:48 -0700197 /**
Jeff Thompson2ce8f492013-09-17 18:01:25 -0700198 * Wire encode the Data object, sign it and set its signature.
Jeff Thompson2ce8f492013-09-17 18:01:25 -0700199 * @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 -0700200 * @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 -0700201 */
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800202 void
Yingdi Yu31b4af22014-01-14 14:13:00 -0800203 sign(Data& data, const Name& certificateName)
204 {
Yingdi Yu17bc3012014-02-10 17:37:12 -0800205 shared_ptr<IdentityCertificate> cert = Info::getCertificate(certificateName);
Yingdi Yu31b4af22014-01-14 14:13:00 -0800206 if (!cert)
Yingdi Yu4270f202014-01-28 14:19:16 -0800207 throw InfoError("Requested certificate [" + certificateName.toUri() + "] doesn't exist");
Yingdi Yu31b4af22014-01-14 14:13:00 -0800208
209 SignatureSha256WithRsa signature;
210 signature.setKeyLocator(certificateName.getPrefix(-1)); // implicit conversion should take care
211 data.setSignature(signature);
212
213 // For temporary usage, we support RSA + SHA256 only, but will support more.
Yingdi Yu8726f652014-01-23 10:35:12 -0800214 signDataInTpm(data, cert->getPublicKeyName(), DIGEST_ALGORITHM_SHA256);
Yingdi Yu31b4af22014-01-14 14:13:00 -0800215 }
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800216
217 void
Yingdi Yu4270f202014-01-28 14:19:16 -0800218 sign(Interest &interest, const Name &certificateName)
219 {
Yingdi Yu17bc3012014-02-10 17:37:12 -0800220 shared_ptr<IdentityCertificate> cert = Info::getCertificate(certificateName);
Yingdi Yu4270f202014-01-28 14:19:16 -0800221 if(!static_cast<bool>(cert))
222 throw InfoError("Requested certificate [" + certificateName.toUri() + "] doesn't exist");
223
224 SignatureSha256WithRsa signature;
225 signature.setKeyLocator(certificateName.getPrefix(-1)); // implicit conversion should take care
226
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800227 Name signedName = Name(interest.getName()).append(signature.getInfo());
Yingdi Yu4270f202014-01-28 14:19:16 -0800228
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800229 signature.setValue(Tpm::signInTpm(signedName.wireEncode().value(),
230 signedName.wireEncode().value_size(),
Yingdi Yu4270f202014-01-28 14:19:16 -0800231 cert->getPublicKeyName(),
232 DIGEST_ALGORITHM_SHA256));
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800233 signedName.append(signature.getValue());
234 interest.setName(signedName);
Yingdi Yu4270f202014-01-28 14:19:16 -0800235 }
Jeff Thompson79a2d5d2013-09-27 14:32:23 -0700236
Jeff Thompson29ce3102013-09-27 11:47:48 -0700237 /**
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700238 * Sign the byte array using a certificate name and return a Signature object.
239 * @param buffer The byte array to be signed.
240 * @param bufferLength the length of buffer.
241 * @param certificateName The certificate name used to get the signing key and which will be put into KeyLocator.
242 * @return The Signature.
243 */
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800244 Signature
Yingdi Yu31b4af22014-01-14 14:13:00 -0800245 sign(const uint8_t* buffer, size_t bufferLength, const Name& certificateName)
246 {
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800247 shared_ptr<IdentityCertificate> cert = Info::getCertificate(certificateName);
Yingdi Yu4270f202014-01-28 14:19:16 -0800248 if (!static_cast<bool>(cert))
249 throw InfoError("Requested certificate [" + certificateName.toUri() + "] doesn't exist");
Yingdi Yu31b4af22014-01-14 14:13:00 -0800250
251 SignatureSha256WithRsa signature;
252 signature.setKeyLocator(certificateName.getPrefix(-1)); // implicit conversion should take care
253
254 // For temporary usage, we support RSA + SHA256 only, but will support more.
Yingdi Yub4bb85a2014-01-16 10:11:04 -0800255 signature.setValue(Tpm::signInTpm(buffer, bufferLength, cert->getPublicKeyName(), DIGEST_ALGORITHM_SHA256));
Yingdi Yu31b4af22014-01-14 14:13:00 -0800256 return signature;
257 }
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700258
259 /**
Jeff Thompson29ce3102013-09-27 11:47:48 -0700260 * Wire encode the Data object, sign it and set its signature.
Jeff Thompson29ce3102013-09-27 11:47:48 -0700261 * @param data The Data object to be signed. This updates its signature and key locator field and wireEncoding.
262 * @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 -0700263 */
264 void
Yingdi Yu4270f202014-01-28 14:19:16 -0800265 signByIdentity(Data& data, const Name& identityName)
Yingdi Yu31b4af22014-01-14 14:13:00 -0800266 {
267 Name signingCertificateName = Info::getDefaultCertificateNameForIdentity(identityName);
268
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800269 if (signingCertificateName.empty())
270 signingCertificateName = createIdentity(identityName);
Yingdi Yu31b4af22014-01-14 14:13:00 -0800271
272 sign(data, signingCertificateName);
273 }
Jeff Thompson3c73da42013-08-12 11:19:05 -0700274
Yingdi Yu4270f202014-01-28 14:19:16 -0800275 void
276 signByIdentity(Interest& interest, const Name& identityName)
277 {
278 Name signingCertificateName = Info::getDefaultCertificateNameForIdentity(identityName);
279
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800280 if (signingCertificateName.empty())
281 signingCertificateName = createIdentity(identityName);
Yingdi Yu4270f202014-01-28 14:19:16 -0800282
283 sign(interest, signingCertificateName);
284 }
285
286
Jeff Thompson3c73da42013-08-12 11:19:05 -0700287 /**
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700288 * Sign the byte array using an identity name and return a Signature object.
289 * @param buffer The byte array to be signed.
290 * @param bufferLength the length of buffer.
291 * @param identityName The identity name.
292 * @return The Signature.
293 */
Alexander Afanasyev64a3d812014-01-05 23:35:05 -0800294 Signature
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800295 signByIdentity(const uint8_t* buffer, size_t bufferLength, const Name& identityName)
Yingdi Yu31b4af22014-01-14 14:13:00 -0800296 {
297 Name signingCertificateName = Info::getDefaultCertificateNameForIdentity(identityName);
298
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800299 if (signingCertificateName.empty())
300 signingCertificateName = createIdentity(identityName);
Yingdi Yu31b4af22014-01-14 14:13:00 -0800301
302 return sign(buffer, bufferLength, signingCertificateName);
303 }
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700304
305 /**
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800306 * Generate a self-signed certificate for a public key.
307 * @param keyName The name of the public key.
308 * @return The generated certificate.
309 */
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800310 shared_ptr<IdentityCertificate>
Yingdi Yu31b4af22014-01-14 14:13:00 -0800311 selfSign(const Name& keyName)
312 {
Yingdi Yu7ea69502014-01-15 17:21:29 -0800313 if(keyName.empty())
Yingdi Yu4270f202014-01-28 14:19:16 -0800314 throw InfoError("Incorrect key name: " + keyName.toUri());
Yingdi Yu7ea69502014-01-15 17:21:29 -0800315
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800316 shared_ptr<IdentityCertificate> certificate = make_shared<IdentityCertificate>();
Yingdi Yu31b4af22014-01-14 14:13:00 -0800317
318 Name certificateName = keyName.getPrefix(-1);
319 certificateName.append("KEY").append(keyName.get(-1)).append("ID-CERT").appendVersion();
320
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800321 shared_ptr<PublicKey> pubKey = Info::getPublicKey(keyName);
Yingdi Yu31b4af22014-01-14 14:13:00 -0800322 if (!pubKey)
Yingdi Yu4270f202014-01-28 14:19:16 -0800323 throw InfoError("Requested public key [" + keyName.toUri() + "] doesn't exist");
Yingdi Yu31b4af22014-01-14 14:13:00 -0800324
325 certificate->setName(certificateName);
326 certificate->setNotBefore(getNow());
327 certificate->setNotAfter(getNow() + 630720000 /* 20 years*/);
328 certificate->setPublicKeyInfo(*pubKey);
329 certificate->addSubjectDescription(CertificateSubjectDescription("2.5.4.41", keyName.toUri()));
330 certificate->encode();
331
332 selfSign(*certificate);
333 return certificate;
334 }
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800335
336 /**
337 * @brief Self-sign the supplied identity certificate
Jeff Thompson8efe5ad2013-08-20 17:36:38 -0700338 */
Jeff Thompson2ce8f492013-09-17 18:01:25 -0700339 void
Yingdi Yu31b4af22014-01-14 14:13:00 -0800340 selfSign (IdentityCertificate& cert)
341 {
342 SignatureSha256WithRsa signature;
343 signature.setKeyLocator(cert.getName().getPrefix(-1)); // implicit conversion should take care
344 cert.setSignature(signature);
345
346 // For temporary usage, we support RSA + SHA256 only, but will support more.
Yingdi Yu8726f652014-01-23 10:35:12 -0800347 signDataInTpm(cert, cert.getPublicKeyName(), DIGEST_ALGORITHM_SHA256);
Yingdi Yu31b4af22014-01-14 14:13:00 -0800348 }
349
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800350 void
351 deleteCertificate (const Name &certificateName)
352 {
353 if(Info::getDefaultIdentity() == IdentityCertificate::certificateNameToPublicKeyName(certificateName).getPrefix(-1))
354 return;
355
356 Info::deleteCertificateInfo(certificateName);
357 }
358
359 void
360 deleteKey (const Name &keyName)
361 {
362 if(Info::getDefaultIdentity() == keyName.getPrefix(-1))
363 return;
364
365 Info::deletePublicKeyInfo(keyName);
366 Tpm::deleteKeyPairInTpm(keyName);
367 }
368
369 void
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800370 deleteIdentity (const Name& identity)
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800371 {
372 if(Info::getDefaultIdentity() == identity)
373 return;
374
375 std::vector<Name> nameList;
376 Info::getAllKeyNamesOfIdentity(identity, nameList, true);
377 Info::getAllKeyNamesOfIdentity(identity, nameList, false);
378
379 Info::deleteIdentityInfo(identity);
380
381 std::vector<Name>::const_iterator it = nameList.begin();
382 for(; it != nameList.end(); it++)
383 Tpm::deleteKeyPairInTpm(*it);
384 }
385
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800386 Block
387 exportIdentity(const Name& identity, bool inTerminal = true, std::string passwordStr = "")
388 {
389 if (!Info::doesIdentityExist(identity))
390 throw InfoError("Identity does not exist!");
391
392 Name keyName = Info::getDefaultKeyNameForIdentity(identity);
393
394 if(keyName.empty())
395 throw InfoError("Default key does not exist!");
396
397 ConstBufferPtr pkcs8 = Tpm::exportPrivateKeyPkcs8FromTpm(keyName, inTerminal, passwordStr);
398 Block wireKey(tlv::security::KeyPackage, pkcs8);
399
400 Name certName = Info::getDefaultCertificateNameForKey(keyName);
401
402 if(certName.empty())
403 {
404 shared_ptr<IdentityCertificate> selfCert = selfSign(keyName);
405 Info::addCertificateAsIdentityDefault(*selfCert);
406 certName = selfCert->getName();
407 }
408
409 shared_ptr<IdentityCertificate> cert = Info::getCertificate(certName);
410 Block wireCert(tlv::security::CertificatePackage, cert->wireEncode());
411
412 Block wire(tlv::security::IdentityPackage);
413 wire.push_back(wireCert);
414 wire.push_back(wireKey);
415
416 return wire;
417 }
418
419 void
420 importIdentity(const Block& block, bool inTerminal = true, std::string passwordStr = "")
421 {
422 block.parse();
423
424 Data data;
425 data.wireDecode(block.get(tlv::security::CertificatePackage).blockFromValue());
426 shared_ptr<IdentityCertificate> cert = make_shared<IdentityCertificate>(data);
427
428 Name keyName = IdentityCertificate::certificateNameToPublicKeyName(cert->getName());
429 Name identity = keyName.getPrefix(-1);
430
431 // Add identity
432 if (Info::doesIdentityExist(identity))
433 deleteIdentity(identity);
434 Info::addIdentity(identity);
435
436 // Add key
437 Block wireKey = block.get(tlv::security::KeyPackage);
438 if (Tpm::doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE))
439 deleteKey(keyName);
440 Tpm::importPrivateKeyPkcs8IntoTpm(keyName, wireKey.value(), wireKey.value_size(), inTerminal, passwordStr);
441 shared_ptr<PublicKey> pubKey = Tpm::getPublicKeyFromTpm(keyName.toUri());
442 Info::addPublicKey(keyName, KEY_TYPE_RSA, *pubKey); // HACK! We should set key type according to the pkcs8 info.
443 Info::setDefaultKeyNameForIdentity(keyName);
444
445 // Add cert
446 if (Info::doesCertificateExist(cert->getName()))
447 deleteCertificate(cert->getName());
448 Info::addCertificateAsIdentityDefault(*cert);
449 }
450
Jeff Thompson8efe5ad2013-08-20 17:36:38 -0700451
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800452private:
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800453
454 void
455 sign(Data &data, const IdentityCertificate& certificate)
456 {
457 SignatureSha256WithRsa signature;
458 signature.setKeyLocator(certificate.getName().getPrefix(-1));
459 data.setSignature(signature);
460
461 // For temporary usage, we support RSA + SHA256 only, but will support more.
462 signDataInTpm(data, certificate.getPublicKeyName(), DIGEST_ALGORITHM_SHA256);
463 }
464
465 void
466 sign(Interest &interest, const IdentityCertificate& certificate)
467 {
468 SignatureSha256WithRsa signature;
469 signature.setKeyLocator(certificate.getName().getPrefix(-1)); // implicit conversion should take care
470
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800471 Name signedName = Name(interest.getName()).append(signature.getInfo());
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800472
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800473 signature.setValue(Tpm::signInTpm(signedName.wireEncode().value(),
474 signedName.wireEncode().value_size(),
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800475 certificate.getPublicKeyName(),
476 DIGEST_ALGORITHM_SHA256));
477
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800478 signedName.append(signature.getValue());
479 interest.setName(signedName);
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800480 }
481
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800482 /**
483 * Generate a key pair for the specified identity.
484 * @param identityName The name of the specified identity.
485 * @param isKsk true for generating a Key-Signing-Key (KSK), false for a Data-Signing-Key (KSK).
486 * @param keyType The type of the key pair, e.g. KEY_TYPE_RSA.
487 * @param keySize The size of the key pair.
488 * @return The name of the generated key.
489 */
490 Name
Yingdi Yu31b4af22014-01-14 14:13:00 -0800491 generateKeyPair(const Name& identityName, bool isKsk = false, KeyType keyType = KEY_TYPE_RSA, int keySize = 2048)
492 {
493 Name keyName = Info::getNewKeyName(identityName, isKsk);
494
495 Tpm::generateKeyPairInTpm(keyName.toUri(), keyType, keySize);
496
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800497 shared_ptr<PublicKey> pubKey = Tpm::getPublicKeyFromTpm(keyName.toUri());
Yingdi Yuef26ee32014-01-15 16:41:14 -0800498 Info::addPublicKey(keyName, keyType, *pubKey);
Yingdi Yu31b4af22014-01-14 14:13:00 -0800499
500 return keyName;
501 }
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800502
503 static Name
Yingdi Yu31b4af22014-01-14 14:13:00 -0800504 getKeyNameFromCertificatePrefix(const Name& certificatePrefix)
505 {
506 Name result;
Alexander Afanasyevbf1a67a2014-01-05 23:36:13 -0800507
Yingdi Yu31b4af22014-01-14 14:13:00 -0800508 std::string keyString("KEY");
509 int i = 0;
510 for(; i < certificatePrefix.size(); i++) {
511 if (certificatePrefix.get(i).toEscapedString() == keyString)
512 break;
513 }
Alexander Afanasyevbf1a67a2014-01-05 23:36:13 -0800514
Yingdi Yu31b4af22014-01-14 14:13:00 -0800515 if (i >= certificatePrefix.size())
Yingdi Yu4270f202014-01-28 14:19:16 -0800516 throw InfoError("Identity Certificate Prefix does not have a KEY component");
Alexander Afanasyevbd5ba402014-01-05 22:41:09 -0800517
Yingdi Yu31b4af22014-01-14 14:13:00 -0800518 result.append(certificatePrefix.getSubName(0, i));
519 result.append(certificatePrefix.getSubName(i + 1, certificatePrefix.size()-i-1));
520
521 return result;
522 }
523
Yingdi Yu8726f652014-01-23 10:35:12 -0800524 /**
525 * Fetch the private key for keyName and sign the data, and set the signature block of the data packet.
526 * @param data Reference to the input data packet.
527 * @param keyName The name of the signing key.
528 * @param digestAlgorithm the digest algorithm.
529 * @throws Tpm::Error
530 */
531 void
532 signDataInTpm(Data &data, const Name& keyName, DigestAlgorithm digestAlgorithm)
533 {
534 data.setSignatureValue
535 (Tpm::signInTpm(data.wireEncode().value(),
536 data.wireEncode().value_size() - data.getSignature().getValue().size(),
537 keyName, digestAlgorithm));
538 }
539
Jeff Thompson47c93cf2013-08-09 00:38:48 -0700540};
541
Yingdi Yufc40d872014-02-18 12:56:04 -0800542} // namespace ndn
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800543
Yingdi Yu04020922014-01-22 12:46:53 -0800544
545
Alexander Afanasyev3e08d5d2014-02-12 19:24:28 -0800546#if defined(NDN_CPP_HAVE_OSX_SECURITY) and defined(NDN_CPP_WITH_OSX_KEYCHAIN)
Yingdi Yu31b4af22014-01-14 14:13:00 -0800547
548namespace ndn
Alexander Afanasyeve64788e2014-01-05 22:38:21 -0800549{
Yingdi Yu31b4af22014-01-14 14:13:00 -0800550typedef KeyChainImpl<SecPublicInfoSqlite3, SecTpmOsx> KeyChain;
551};
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800552
Yingdi Yu31b4af22014-01-14 14:13:00 -0800553#else
Alexander Afanasyeve64788e2014-01-05 22:38:21 -0800554
Yingdi Yu31b4af22014-01-14 14:13:00 -0800555namespace ndn
Alexander Afanasyeve64788e2014-01-05 22:38:21 -0800556{
Yingdi Yu04020922014-01-22 12:46:53 -0800557typedef KeyChainImpl<SecPublicInfoSqlite3, SecTpmFile> KeyChain;
Yingdi Yu31b4af22014-01-14 14:13:00 -0800558};
Alexander Afanasyeve64788e2014-01-05 22:38:21 -0800559
Yingdi Yu31b4af22014-01-14 14:13:00 -0800560#endif //NDN_CPP_HAVE_OSX_SECURITY
Jeff Thompson47c93cf2013-08-09 00:38:48 -0700561
Yingdi Yufc40d872014-02-18 12:56:04 -0800562#endif //NDN_SECURITY_KEY_CHAIN_HPP