blob: 7c95e14938a09ac1d1d6e4ef7fc15af9860b06d4 [file] [log] [blame]
Alexander Afanasyevc169a812014-05-20 20:37:29 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Jeff Thompson47c93cf2013-08-09 00:38:48 -07002/**
Alexander Afanasyevc169a812014-05-20 20:37:29 -04003 * Copyright (c) 2013-2014 Regents of the University of California.
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07006 *
Alexander Afanasyevc169a812014-05-20 20:37:29 -04007 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -070020 *
21 * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
Jeff Thompson47c93cf2013-08-09 00:38:48 -070022 */
23
Yingdi Yufc40d872014-02-18 12:56:04 -080024#ifndef NDN_SECURITY_KEY_CHAIN_HPP
25#define NDN_SECURITY_KEY_CHAIN_HPP
Jeff Thompson47c93cf2013-08-09 00:38:48 -070026
Yingdi Yuf56c68f2014-04-24 21:50:13 -070027#include "sec-public-info.hpp"
28#include "sec-tpm.hpp"
29#include "secured-bag.hpp"
Yingdi Yu4f324632014-01-15 18:10:03 -080030#include "signature-sha256-with-rsa.hpp"
Yingdi Yu21157162014-02-28 13:02:34 -080031#include "signature-sha256.hpp"
Yingdi Yuf56c68f2014-04-24 21:50:13 -070032
Yingdi Yu4270f202014-01-28 14:19:16 -080033#include "../interest.hpp"
Yingdi Yu21157162014-02-28 13:02:34 -080034#include "../util/crypto.hpp"
Yingdi Yu31b4af22014-01-14 14:13:00 -080035
Jeff Thompson47c93cf2013-08-09 00:38:48 -070036
37namespace ndn {
38
Yingdi Yuf56c68f2014-04-24 21:50:13 -070039template<class TypePib, class TypeTpm>
40class KeyChainTraits
Yingdi Yu31b4af22014-01-14 14:13:00 -080041{
Jeff Thompson47c93cf2013-08-09 00:38:48 -070042public:
Yingdi Yuf56c68f2014-04-24 21:50:13 -070043 typedef TypePib Pib;
44 typedef TypeTpm Tpm;
45};
46
Alexander Afanasyev45a37132014-04-28 16:54:57 -070047class KeyChain : noncopyable
Yingdi Yuf56c68f2014-04-24 21:50:13 -070048{
49public:
50 class Error : public std::runtime_error
51 {
52 public:
53 explicit
54 Error(const std::string& what)
55 : std::runtime_error(what)
56 {
57 }
58 };
59
60 KeyChain();
61
62 template<class KeyChainTraits>
63 KeyChain(KeyChainTraits traits);
64
65 KeyChain(const std::string& pibName,
66 const std::string& tpmName);
67
68 virtual
69 ~KeyChain()
70 {
71 if (m_pib != 0)
72 delete m_pib;
73
74 if (m_tpm != 0)
75 delete m_tpm;
76 }
77
Yingdi Yube4150e2014-02-18 13:02:46 -080078 /**
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070079 * @brief Create an identity by creating a pair of Key-Signing-Key (KSK) for this identity and a
80 * self-signed certificate of the KSK.
Yingdi Yube4150e2014-02-18 13:02:46 -080081 *
Yingdi Yu2abd73f2014-01-08 23:34:11 -080082 * @param identityName The name of the identity.
Yingdi Yu28fd32f2014-01-28 19:03:03 -080083 * @return The name of the default certificate of the identity.
Yingdi Yu2abd73f2014-01-08 23:34:11 -080084 */
Yingdi Yuf56c68f2014-04-24 21:50:13 -070085 inline Name
86 createIdentity(const Name& identityName);
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -070087
Yingdi Yu2abd73f2014-01-08 23:34:11 -080088 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -080089 * @brief Generate a pair of RSA keys for the specified identity.
90 *
Yingdi Yu2abd73f2014-01-08 23:34:11 -080091 * @param identityName The name of the identity.
92 * @param isKsk true for generating a Key-Signing-Key (KSK), false for a Data-Signing-Key (KSK).
93 * @param keySize The size of the key.
94 * @return The generated key name.
95 */
Yingdi Yuf56c68f2014-04-24 21:50:13 -070096 inline Name
97 generateRsaKeyPair(const Name& identityName, bool isKsk = false, int keySize = 2048);
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -070098
Yingdi Yu2abd73f2014-01-08 23:34:11 -080099 /**
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700100 * @brief Generate a pair of RSA keys for the specified identity and set it as default key for
101 * the identity.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800102 *
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800103 * @param identityName The name of the identity.
104 * @param isKsk true for generating a Key-Signing-Key (KSK), false for a Data-Signing-Key (KSK).
105 * @param keySize The size of the key.
106 * @return The generated key name.
107 */
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700108 inline Name
109 generateRsaKeyPairAsDefault(const Name& identityName, bool isKsk = false, int keySize = 2048);
Jeff Thompson79a2d5d2013-09-27 14:32:23 -0700110
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800111 /**
Yingdi Yuc55680b2014-02-26 12:31:35 -0800112 * @brief prepare an unsigned identity certificate
113 *
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700114 * @param keyName Key name, e.g., `/<identity_name>/ksk-123456`.
Yingdi Yuc55680b2014-02-26 12:31:35 -0800115 * @param signingIdentity The signing identity.
116 * @param notBefore Refer to IdentityCertificate.
117 * @param notAfter Refer to IdentityCertificate.
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700118 * @param subjectDescription Refer to IdentityCertificate.
Yingdi Yuc55680b2014-02-26 12:31:35 -0800119 * @return IdentityCertificate.
120 */
121 shared_ptr<IdentityCertificate>
122 prepareUnsignedIdentityCertificate(const Name& keyName,
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700123 const Name& signingIdentity,
124 const time::system_clock::TimePoint& notBefore,
125 const time::system_clock::TimePoint& notAfter,
126 const std::vector<CertificateSubjectDescription>& subjectDescription);
Yingdi Yuc55680b2014-02-26 12:31:35 -0800127
128 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800129 * @brief Sign packet with default identity
130 *
Yingdi Yu60bd7082014-03-25 18:18:54 -0700131 * On return, signatureInfo and signatureValue in the packet are set.
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700132 * If default identity does not exist,
Yingdi Yu60bd7082014-03-25 18:18:54 -0700133 * a temporary identity will be created and set as default.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800134 *
135 * @param packet The packet to be signed
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800136 */
Yingdi Yu2e57a582014-02-20 23:34:43 -0800137 template<typename T>
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800138 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700139 sign(T& packet);
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700140
Jeff Thompson47c93cf2013-08-09 00:38:48 -0700141 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800142 * @brief Sign packet with a particular certificate.
143 *
144 * @param packet The packet to be signed.
145 * @param certificateName The certificate name of the key to use for signing.
146 * @throws SecPublicInfo::Error if certificate does not exist.
Jeff Thompson3c73da42013-08-12 11:19:05 -0700147 */
Yingdi Yu2e57a582014-02-20 23:34:43 -0800148 template<typename T>
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700149 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700150 sign(T& packet, const Name& certificateName);
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700151
Jeff Thompson29ce3102013-09-27 11:47:48 -0700152 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800153 * @brief Sign the byte array using a particular certificate.
154 *
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700155 * @param buffer The byte array to be signed.
156 * @param bufferLength the length of buffer.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800157 * @param certificateName The certificate name of the signing key.
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700158 * @return The Signature.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800159 * @throws SecPublicInfo::Error if certificate does not exist.
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700160 */
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800161 Signature
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700162 sign(const uint8_t* buffer, size_t bufferLength, const Name& certificateName);
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700163
164 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800165 * @brief Sign packet using the default certificate of a particular identity.
166 *
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700167 * If there is no default certificate of that identity, this method will create a self-signed
168 * certificate.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800169 *
170 * @param packet The packet to be signed.
171 * @param identityName The signing identity name.
Jeff Thompson29ce3102013-09-27 11:47:48 -0700172 */
Yingdi Yu2e57a582014-02-20 23:34:43 -0800173 template<typename T>
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700174 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700175 signByIdentity(T& packet, const Name& identityName);
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700176
Jeff Thompson3c73da42013-08-12 11:19:05 -0700177 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800178 * @brief Sign the byte array using the default certificate of a particular identity.
179 *
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700180 * @param buffer The byte array to be signed.
181 * @param bufferLength the length of buffer.
182 * @param identityName The identity name.
183 * @return The Signature.
184 */
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700185 inline Signature
186 signByIdentity(const uint8_t* buffer, size_t bufferLength, const Name& identityName);
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700187
188 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700189 * @brief Set Sha256 weak signature for @param data
Yingdi Yu21157162014-02-28 13:02:34 -0800190 */
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700191 inline void
192 signWithSha256(Data& data);
Yingdi Yu21157162014-02-28 13:02:34 -0800193
194 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800195 * @brief Generate a self-signed certificate for a public key.
196 *
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700197 * @param keyName The name of the public key
198 * @return The generated certificate, shared_ptr<IdentityCertificate>() if selfSign fails
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800199 */
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800200 shared_ptr<IdentityCertificate>
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700201 selfSign(const Name& keyName);
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800202
203 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800204 * @brief Self-sign the supplied identity certificate.
205 *
206 * @param cert The supplied cert.
207 * @throws SecTpm::Error if the private key does not exist.
Jeff Thompson8efe5ad2013-08-20 17:36:38 -0700208 */
Jeff Thompson2ce8f492013-09-17 18:01:25 -0700209 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700210 selfSign(IdentityCertificate& cert);
Yingdi Yu31b4af22014-01-14 14:13:00 -0800211
Yingdi Yu2e57a582014-02-20 23:34:43 -0800212 /**
213 * @brief delete a certificate.
214 *
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700215 * If the certificate to be deleted is current default system default,
Yingdi Yu2e57a582014-02-20 23:34:43 -0800216 * the method will not delete the certificate and return immediately.
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700217 *
Yingdi Yu2e57a582014-02-20 23:34:43 -0800218 * @param certificateName The certificate to be deleted.
219 */
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700220 inline void
221 deleteCertificate(const Name& certificateName);
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800222
Yingdi Yu2e57a582014-02-20 23:34:43 -0800223 /**
224 * @brief delete a key.
225 *
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700226 * If the key to be deleted is current default system default,
Yingdi Yu2e57a582014-02-20 23:34:43 -0800227 * the method will not delete the key and return immediately.
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700228 *
Yingdi Yu2e57a582014-02-20 23:34:43 -0800229 * @param keyName The key to be deleted.
230 */
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700231 inline void
232 deleteKey(const Name& keyName);
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800233
Yingdi Yu2e57a582014-02-20 23:34:43 -0800234 /**
235 * @brief delete an identity.
236 *
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700237 * If the identity to be deleted is current default system default,
Yingdi Yu2e57a582014-02-20 23:34:43 -0800238 * the method will not delete the identity and return immediately.
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700239 *
Yingdi Yu2e57a582014-02-20 23:34:43 -0800240 * @param identity The identity to be deleted.
241 */
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700242 inline void
243 deleteIdentity(const Name& identity);
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800244
Yingdi Yu2e57a582014-02-20 23:34:43 -0800245 /**
246 * @brief export an identity.
247 *
248 * @param identity The identity to export.
249 * @param passwordStr The password to secure the private key.
Yingdi Yu64c3fb42014-02-26 17:30:04 -0800250 * @return The encoded export data.
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700251 * @throws SecPublicInfo::Error if anything goes wrong in exporting.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800252 */
Yingdi Yu64c3fb42014-02-26 17:30:04 -0800253 shared_ptr<SecuredBag>
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700254 exportIdentity(const Name& identity, const std::string& passwordStr);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800255
Yingdi Yu2e57a582014-02-20 23:34:43 -0800256 /**
257 * @brief import an identity.
258 *
Yingdi Yu64c3fb42014-02-26 17:30:04 -0800259 * @param securedBag The encoded import data.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800260 * @param passwordStr The password to secure the private key.
261 */
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800262 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700263 importIdentity(const SecuredBag& securedBag, const std::string& passwordStr);
264
265 SecPublicInfo&
266 getPib()
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800267 {
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700268 return *m_pib;
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800269 }
270
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700271 const SecPublicInfo&
272 getPib() const
273 {
274 return *m_pib;
275 }
276
277 SecTpm&
278 getTpm()
279 {
280 return *m_tpm;
281 }
282
283 const SecTpm&
284 getTpm() const
285 {
286 return *m_tpm;
287 }
288
289 /*******************************
290 * Wrapper of SecPublicInfo *
291 *******************************/
292 bool
293 doesIdentityExist(const Name& identityName) const
294 {
295 return m_pib->doesIdentityExist(identityName);
296 }
297
298 void
299 addIdentity(const Name& identityName)
300 {
301 return m_pib->addIdentity(identityName);
302 }
303
304 bool
305 doesPublicKeyExist(const Name& keyName) const
306 {
307 return m_pib->doesPublicKeyExist(keyName);
308 }
309
310 void
311 addPublicKey(const Name& keyName, KeyType keyType, const PublicKey& publicKeyDer)
312 {
313 return m_pib->addPublicKey(keyName, keyType, publicKeyDer);
314 }
315
316 shared_ptr<PublicKey>
317 getPublicKey(const Name& keyName) const
318 {
319 return m_pib->getPublicKey(keyName);
320 }
321
322 bool
323 doesCertificateExist(const Name& certificateName) const
324 {
325 return m_pib->doesCertificateExist(certificateName);
326 }
327
328 void
329 addCertificate(const IdentityCertificate& certificate)
330 {
331 return m_pib->addCertificate(certificate);
332 }
333
334 shared_ptr<IdentityCertificate>
335 getCertificate(const Name& certificateName) const
336 {
337 return m_pib->getCertificate(certificateName);
338 }
339
340 Name
341 getDefaultIdentity() const
342 {
343 return m_pib->getDefaultIdentity();
344 }
345
346 Name
347 getDefaultKeyNameForIdentity(const Name& identityName) const
348 {
349 return m_pib->getDefaultKeyNameForIdentity(identityName);
350 }
351
352 Name
353 getDefaultCertificateNameForKey(const Name& keyName) const
354 {
355 return m_pib->getDefaultCertificateNameForKey(keyName);
356 }
357
358 void
359 getAllIdentities(std::vector<Name>& nameList, bool isDefault) const
360 {
361 return m_pib->getAllIdentities(nameList, isDefault);
362 }
363
364 void
365 getAllKeyNames(std::vector<Name>& nameList, bool isDefault) const
366 {
367 return m_pib->getAllKeyNames(nameList, isDefault);
368 }
369
370 void
371 getAllKeyNamesOfIdentity(const Name& identity, std::vector<Name>& nameList, bool isDefault) const
372 {
373 return m_pib->getAllKeyNamesOfIdentity(identity, nameList, isDefault);
374 }
375
376 void
377 getAllCertificateNames(std::vector<Name>& nameList, bool isDefault) const
378 {
379 return m_pib->getAllCertificateNames(nameList, isDefault);
380 }
381
382 void
383 getAllCertificateNamesOfKey(const Name& keyName,
384 std::vector<Name>& nameList,
385 bool isDefault) const
386 {
387 return m_pib->getAllCertificateNamesOfKey(keyName, nameList, isDefault);
388 }
389
390 void
391 deleteCertificateInfo(const Name& certificateName)
392 {
393 return m_pib->deleteCertificateInfo(certificateName);
394 }
395
396 void
397 deletePublicKeyInfo(const Name& keyName)
398 {
399 return m_pib->deletePublicKeyInfo(keyName);
400 }
401
402 void
403 deleteIdentityInfo(const Name& identity)
404 {
405 return m_pib->deleteIdentityInfo(identity);
406 }
407
408 void
409 setDefaultIdentity(const Name& identityName)
410 {
411 return m_pib->setDefaultIdentity(identityName);
412 }
413
414 void
415 setDefaultKeyNameForIdentity(const Name& keyName)
416 {
417 return m_pib->setDefaultKeyNameForIdentity(keyName);
418 }
419
420 void
421 setDefaultCertificateNameForKey(const Name& certificateName)
422 {
423 return m_pib->setDefaultCertificateNameForKey(certificateName);
424 }
425
426 Name
427 getNewKeyName(const Name& identityName, bool useKsk)
428 {
429 return m_pib->getNewKeyName(identityName, useKsk);
430 }
431
432 Name
433 getDefaultCertificateNameForIdentity(const Name& identityName) const
434 {
435 return m_pib->getDefaultCertificateNameForIdentity(identityName);
436 }
437
438 Name
439 getDefaultCertificateName() const
440 {
441 return m_pib->getDefaultCertificateName();
442 }
443
444 void
445 addCertificateAsKeyDefault(const IdentityCertificate& certificate)
446 {
447 return m_pib->addCertificateAsKeyDefault(certificate);
448 }
449
450 void
451 addCertificateAsIdentityDefault(const IdentityCertificate& certificate)
452 {
453 return m_pib->addCertificateAsIdentityDefault(certificate);
454 }
455
456 void
457 addCertificateAsSystemDefault(const IdentityCertificate& certificate)
458 {
459 return m_pib->addCertificateAsSystemDefault(certificate);
460 }
461
462 shared_ptr<IdentityCertificate>
463 getDefaultCertificate() const
464 {
465 return m_pib->defaultCertificate();
466 }
467
468 void
469 refreshDefaultCertificate()
470 {
471 return m_pib->refreshDefaultCertificate();
472 }
473
474 /*******************************
475 * Wrapper of SecTpm *
476 *******************************/
477
478 void
479 setTpmPassword(const uint8_t* password, size_t passwordLength)
480 {
481 return m_tpm->setTpmPassword(password, passwordLength);
482 }
483
484 void
485 resetTpmPassword()
486 {
487 return m_tpm->resetTpmPassword();
488 }
489
490 void
491 setInTerminal(bool inTerminal)
492 {
493 return m_tpm->setInTerminal(inTerminal);
494 }
495
496 bool
497 getInTerminal() const
498 {
499 return m_tpm->getInTerminal();
500 }
501
502 bool
503 isLocked() const
504 {
505 return m_tpm->isLocked();
506 }
507
508 bool
509 unlockTpm(const char* password, size_t passwordLength, bool usePassword)
510 {
511 return m_tpm->unlockTpm(password, passwordLength, usePassword);
512 }
513
514 void
515 generateKeyPairInTpm(const Name& keyName, KeyType keyType, int keySize)
516 {
517 return m_tpm->generateKeyPairInTpm(keyName, keyType, keySize);
518 }
519
520 void
521 deleteKeyPairInTpm(const Name& keyName)
522 {
523 return m_tpm->deleteKeyPairInTpm(keyName);
524 }
525
526 shared_ptr<PublicKey>
527 getPublicKeyFromTpm(const Name& keyName) const
528 {
529 return m_tpm->getPublicKeyFromTpm(keyName);
530 }
531
532 Block
533 signInTpm(const uint8_t* data, size_t dataLength,
534 const Name& keyName,
535 DigestAlgorithm digestAlgorithm)
536 {
537 return m_tpm->signInTpm(data, dataLength, keyName, digestAlgorithm);
538 }
539
540 ConstBufferPtr
541 decryptInTpm(const uint8_t* data, size_t dataLength, const Name& keyName, bool isSymmetric)
542 {
543 return m_tpm->decryptInTpm(data, dataLength, keyName, isSymmetric);
544 }
545
546 ConstBufferPtr
547 encryptInTpm(const uint8_t* data, size_t dataLength, const Name& keyName, bool isSymmetric)
548 {
549 return m_tpm->encryptInTpm(data, dataLength, keyName, isSymmetric);
550 }
551
552 void
553 generateSymmetricKeyInTpm(const Name& keyName, KeyType keyType, int keySize)
554 {
555 return m_tpm->generateSymmetricKeyInTpm(keyName, keyType, keySize);
556 }
557
558 bool
559 doesKeyExistInTpm(const Name& keyName, KeyClass keyClass) const
560 {
561 return m_tpm->doesKeyExistInTpm(keyName, keyClass);
562 }
563
564 bool
565 generateRandomBlock(uint8_t* res, size_t size) const
566 {
567 return m_tpm->generateRandomBlock(res, size);
568 }
569
570 void
571 addAppToAcl(const Name& keyName, KeyClass keyClass, const std::string& appPath, AclType acl)
572 {
573 return m_tpm->addAppToAcl(keyName, keyClass, appPath, acl);
574 }
575
576 ConstBufferPtr
577 exportPrivateKeyPkcs5FromTpm(const Name& keyName, const std::string& password)
578 {
579 return m_tpm->exportPrivateKeyPkcs5FromTpm(keyName, password);
580 }
581
582 bool
583 importPrivateKeyPkcs5IntoTpm(const Name& keyName,
584 const uint8_t* buf, size_t size,
585 const std::string& password)
586 {
587 return m_tpm->importPrivateKeyPkcs5IntoTpm(keyName, buf, size, password);
588 }
Jeff Thompson8efe5ad2013-08-20 17:36:38 -0700589
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800590private:
Yingdi Yu2e57a582014-02-20 23:34:43 -0800591 /**
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700592 * @brief Set default certificate if it is not initialized
593 */
594 void
595 setDefaultCertificateInternal();
596
597 /**
598 * @brief Sign a packet using a pariticular certificate.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800599 *
600 * @param packet The packet to be signed.
601 * @param certificate The signing certificate.
602 */
603 template<typename T>
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800604 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700605 sign(T& packet, const IdentityCertificate& certificate);
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800606
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800607 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800608 * @brief Generate a key pair for the specified identity.
609 *
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800610 * @param identityName The name of the specified identity.
611 * @param isKsk true for generating a Key-Signing-Key (KSK), false for a Data-Signing-Key (KSK).
612 * @param keyType The type of the key pair, e.g. KEY_TYPE_RSA.
613 * @param keySize The size of the key pair.
614 * @return The name of the generated key.
615 */
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700616 inline Name
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700617 generateKeyPair(const Name& identityName, bool isKsk = false,
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700618 KeyType keyType = KEY_TYPE_RSA, int keySize = 2048);
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800619
Yingdi Yu8726f652014-01-23 10:35:12 -0800620 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800621 * @brief Sign the data using a particular key.
622 *
623 * @param data Reference to the data packet.
624 * @param signature Signature to be added.
Yingdi Yu8726f652014-01-23 10:35:12 -0800625 * @param keyName The name of the signing key.
626 * @param digestAlgorithm the digest algorithm.
627 * @throws Tpm::Error
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700628 */
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700629 inline void
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700630 signPacketWrapper(Data& data, const SignatureSha256WithRsa& signature,
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700631 const Name& keyName, DigestAlgorithm digestAlgorithm);
Yingdi Yu8726f652014-01-23 10:35:12 -0800632
Yingdi Yu2e57a582014-02-20 23:34:43 -0800633 /**
634 * @brief Sign the interest using a particular key.
635 *
636 * @param interest Reference to the interest packet.
637 * @param signature Signature to be added.
638 * @param keyName The name of the signing key.
639 * @param digestAlgorithm the digest algorithm.
640 * @throws Tpm::Error
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700641 */
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700642 inline void
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700643 signPacketWrapper(Interest& interest, const SignatureSha256WithRsa& signature,
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700644 const Name& keyName, DigestAlgorithm digestAlgorithm);
Yingdi Yu2e57a582014-02-20 23:34:43 -0800645
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700646
647private:
648 SecPublicInfo* m_pib;
649 SecTpm* m_tpm;
650};
651
652template<class T>
653inline
654KeyChain::KeyChain(T)
655 : m_pib(new typename T::Pib)
656 , m_tpm(new typename T::Tpm)
657{
658}
659
660inline Name
661KeyChain::createIdentity(const Name& identityName)
662{
663 m_pib->addIdentity(identityName);
664
665 Name keyName;
666 try
667 {
668 keyName = m_pib->getDefaultKeyNameForIdentity(identityName);
669 }
670 catch (SecPublicInfo::Error& e)
671 {
672 keyName = generateRsaKeyPairAsDefault(identityName, true);
673 }
674
675 Name certName;
676 try
677 {
678 certName = m_pib->getDefaultCertificateNameForKey(keyName);
679 }
680 catch (SecPublicInfo::Error& e)
681 {
682 shared_ptr<IdentityCertificate> selfCert = selfSign(keyName);
683 m_pib->addCertificateAsIdentityDefault(*selfCert);
684 certName = selfCert->getName();
685 }
686
687 return certName;
688}
689
690inline Name
691KeyChain::generateRsaKeyPair(const Name& identityName, bool isKsk, int keySize)
692{
693 return generateKeyPair(identityName, isKsk, KEY_TYPE_RSA, keySize);
694}
695
696inline Name
697KeyChain::generateRsaKeyPairAsDefault(const Name& identityName, bool isKsk, int keySize)
698{
699 Name keyName = generateKeyPair(identityName, isKsk, KEY_TYPE_RSA, keySize);
700
701 m_pib->setDefaultKeyNameForIdentity(keyName);
702
703 return keyName;
704}
705
706template<typename T>
707void
708KeyChain::sign(T& packet)
709{
710 if (!static_cast<bool>(m_pib->defaultCertificate()))
711 setDefaultCertificateInternal();
712
713 sign(packet, *m_pib->defaultCertificate());
714}
715
716template<typename T>
717void
718KeyChain::sign(T& packet, const Name& certificateName)
719{
720 if (!m_pib->doesCertificateExist(certificateName))
721 throw SecPublicInfo::Error("Requested certificate [" +
722 certificateName.toUri() + "] doesn't exist");
723
724 SignatureSha256WithRsa signature;
725 // implicit conversion should take care
726 signature.setKeyLocator(certificateName.getPrefix(-1));
727
728 // For temporary usage, we support RSA + SHA256 only, but will support more.
729 signPacketWrapper(packet, signature,
730 IdentityCertificate::certificateNameToPublicKeyName(certificateName),
731 DIGEST_ALGORITHM_SHA256);
732}
733
734template<typename T>
735void
736KeyChain::signByIdentity(T& packet, const Name& identityName)
737{
738 Name signingCertificateName;
739 try
740 {
741 signingCertificateName = m_pib->getDefaultCertificateNameForIdentity(identityName);
742 }
743 catch (SecPublicInfo::Error& e)
744 {
745 signingCertificateName = createIdentity(identityName);
746 // Ideally, no exception will be thrown out, unless something goes wrong in the TPM, which
747 // is a fatal error.
748 }
749
750 // We either get or create the signing certificate, sign packet! (no exception unless fatal
751 // error in TPM)
752 sign(packet, signingCertificateName);
753}
754
755inline Signature
756KeyChain::signByIdentity(const uint8_t* buffer, size_t bufferLength, const Name& identityName)
757{
758 Name signingCertificateName;
759 try
760 {
761 signingCertificateName = m_pib->getDefaultCertificateNameForIdentity(identityName);
762 }
763 catch (SecPublicInfo::Error& e)
764 {
765 signingCertificateName = createIdentity(identityName);
766 // Ideally, no exception will be thrown out, unless something goes wrong in the TPM, which
767 // is a fatal error.
768 }
769
770 // We either get or create the signing certificate, sign data! (no exception unless fatal error
771 // in TPM)
772 return sign(buffer, bufferLength, signingCertificateName);
773}
774
775inline void
776KeyChain::signWithSha256(Data& data)
777{
778 SignatureSha256 sig;
779 data.setSignature(sig);
780
781 Block sigValue(Tlv::SignatureValue,
782 crypto::sha256(data.wireEncode().value(),
783 data.wireEncode().value_size() -
784 data.getSignature().getValue().size()));
785 data.setSignatureValue(sigValue);
786}
787
788inline void
789KeyChain::deleteCertificate(const Name& certificateName)
790{
791 try
792 {
793 if (m_pib->getDefaultCertificateName() == certificateName)
794 return;
795 }
796 catch (SecPublicInfo::Error& e)
797 {
798 // Not a real error, just try to delete the certificate
799 }
800
801 m_pib->deleteCertificateInfo(certificateName);
802}
803
804inline void
805KeyChain::deleteKey(const Name& keyName)
806{
807 try
808 {
809 if (m_pib->getDefaultKeyNameForIdentity(m_pib->getDefaultIdentity()) == keyName)
810 return;
811 }
812 catch (SecPublicInfo::Error& e)
813 {
814 // Not a real error, just try to delete the key
815 }
816
817 m_pib->deletePublicKeyInfo(keyName);
818 m_tpm->deleteKeyPairInTpm(keyName);
819}
820
821inline void
822KeyChain::deleteIdentity(const Name& identity)
823{
824 try
825 {
826 if (m_pib->getDefaultIdentity() == identity)
827 return;
828 }
829 catch (SecPublicInfo::Error& e)
830 {
831 // Not a real error, just try to delete the identity
832 }
833
834 std::vector<Name> nameList;
835 m_pib->getAllKeyNamesOfIdentity(identity, nameList, true);
836 m_pib->getAllKeyNamesOfIdentity(identity, nameList, false);
837
838 m_pib->deleteIdentityInfo(identity);
839
840 std::vector<Name>::const_iterator it = nameList.begin();
841 for(; it != nameList.end(); it++)
842 m_tpm->deleteKeyPairInTpm(*it);
843}
844
845template<typename T>
846void
847KeyChain::sign(T& packet, const IdentityCertificate& certificate)
848{
849 SignatureSha256WithRsa signature;
850 signature.setKeyLocator(certificate.getName().getPrefix(-1));
851
852 // For temporary usage, we support RSA + SHA256 only, but will support more.
853 signPacketWrapper(packet, signature, certificate.getPublicKeyName(), DIGEST_ALGORITHM_SHA256);
854}
855
856inline Name
857KeyChain::generateKeyPair(const Name& identityName, bool isKsk, KeyType keyType, int keySize)
858{
859 Name keyName = m_pib->getNewKeyName(identityName, isKsk);
860
861 m_tpm->generateKeyPairInTpm(keyName.toUri(), keyType, keySize);
862
863 shared_ptr<PublicKey> pubKey = m_tpm->getPublicKeyFromTpm(keyName.toUri());
864 m_pib->addPublicKey(keyName, keyType, *pubKey);
865
866 return keyName;
867}
868
869inline void
870KeyChain::signPacketWrapper(Data& data, const SignatureSha256WithRsa& signature,
871 const Name& keyName, DigestAlgorithm digestAlgorithm)
872{
873 data.setSignature(signature);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700874
875 EncodingBuffer encoder;
876 data.wireEncode(encoder, true);
877
878 Block signatureValue = m_tpm->signInTpm(encoder.buf(), encoder.size(),
879 keyName, digestAlgorithm);
880 data.wireEncode(encoder, signatureValue);
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700881}
882
883inline void
884KeyChain::signPacketWrapper(Interest& interest, const SignatureSha256WithRsa& signature,
885 const Name& keyName, DigestAlgorithm digestAlgorithm)
886{
887 Name signedName = interest.getName();
888 signedName.append(signature.getInfo());
889
890 Block sigValue = m_tpm->signInTpm(signedName.wireEncode().value(),
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700891 signedName.wireEncode().value_size(),
Yingdi Yu2e57a582014-02-20 23:34:43 -0800892 keyName,
Alexander Afanasyev24b75c82014-05-31 15:59:31 +0300893 digestAlgorithm);
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700894 sigValue.encode();
895 signedName.append(sigValue);
896 interest.setName(signedName);
897}
Yingdi Yu2e57a582014-02-20 23:34:43 -0800898
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700899}
Jeff Thompson47c93cf2013-08-09 00:38:48 -0700900
Alexander Afanasyev766cea72014-04-24 19:16:42 -0700901#endif // NDN_SECURITY_KEY_CHAIN_HPP