blob: 00a2e6b8be9d87208921e3b583c875c9ee0bfeed [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
Yingdi Yu0eb5d722014-06-10 15:06:25 -070060 static const Name DEFAULT_PREFIX;
61
Yingdi Yuf56c68f2014-04-24 21:50:13 -070062 KeyChain();
63
64 template<class KeyChainTraits>
65 KeyChain(KeyChainTraits traits);
66
67 KeyChain(const std::string& pibName,
68 const std::string& tpmName);
69
70 virtual
71 ~KeyChain()
72 {
73 if (m_pib != 0)
74 delete m_pib;
75
76 if (m_tpm != 0)
77 delete m_tpm;
78 }
79
Yingdi Yube4150e2014-02-18 13:02:46 -080080 /**
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070081 * @brief Create an identity by creating a pair of Key-Signing-Key (KSK) for this identity and a
82 * self-signed certificate of the KSK.
Yingdi Yube4150e2014-02-18 13:02:46 -080083 *
Yingdi Yu2abd73f2014-01-08 23:34:11 -080084 * @param identityName The name of the identity.
Yingdi Yu28fd32f2014-01-28 19:03:03 -080085 * @return The name of the default certificate of the identity.
Yingdi Yu2abd73f2014-01-08 23:34:11 -080086 */
Yingdi Yuf56c68f2014-04-24 21:50:13 -070087 inline Name
88 createIdentity(const Name& identityName);
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -070089
Yingdi Yu2abd73f2014-01-08 23:34:11 -080090 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -080091 * @brief Generate a pair of RSA keys for the specified identity.
92 *
Yingdi Yu2abd73f2014-01-08 23:34:11 -080093 * @param identityName The name of the identity.
94 * @param isKsk true for generating a Key-Signing-Key (KSK), false for a Data-Signing-Key (KSK).
95 * @param keySize The size of the key.
96 * @return The generated key name.
97 */
Yingdi Yuf56c68f2014-04-24 21:50:13 -070098 inline Name
99 generateRsaKeyPair(const Name& identityName, bool isKsk = false, int keySize = 2048);
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700100
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800101 /**
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700102 * @brief Generate a pair of RSA keys for the specified identity and set it as default key for
103 * the identity.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800104 *
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800105 * @param identityName The name of the identity.
106 * @param isKsk true for generating a Key-Signing-Key (KSK), false for a Data-Signing-Key (KSK).
107 * @param keySize The size of the key.
108 * @return The generated key name.
109 */
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700110 inline Name
111 generateRsaKeyPairAsDefault(const Name& identityName, bool isKsk = false, int keySize = 2048);
Jeff Thompson79a2d5d2013-09-27 14:32:23 -0700112
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800113 /**
Yingdi Yuc55680b2014-02-26 12:31:35 -0800114 * @brief prepare an unsigned identity certificate
115 *
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700116 * @param keyName Key name, e.g., `/<identity_name>/ksk-123456`.
Yingdi Yuc55680b2014-02-26 12:31:35 -0800117 * @param signingIdentity The signing identity.
118 * @param notBefore Refer to IdentityCertificate.
119 * @param notAfter Refer to IdentityCertificate.
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700120 * @param subjectDescription Refer to IdentityCertificate.
Yingdi Yu0eb5d722014-06-10 15:06:25 -0700121 * @param certPrefix Prefix before `KEY` component. By default, KeyChain will infer the
122 * certificate name according to the relation between the signingIdentity and
123 * the subject identity. If signingIdentity is a prefix of the subject identity,
124 * `KEY` will be inserted after the signingIdentity, otherwise `KEY` is inserted
125 * after subject identity (i.e., before `ksk-....`).
Yingdi Yuc55680b2014-02-26 12:31:35 -0800126 * @return IdentityCertificate.
127 */
128 shared_ptr<IdentityCertificate>
129 prepareUnsignedIdentityCertificate(const Name& keyName,
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700130 const Name& signingIdentity,
131 const time::system_clock::TimePoint& notBefore,
132 const time::system_clock::TimePoint& notAfter,
Yingdi Yu0eb5d722014-06-10 15:06:25 -0700133 const std::vector<CertificateSubjectDescription>& subjectDescription,
134 const Name& certPrefix = DEFAULT_PREFIX);
135
136 /**
137 * @brief prepare an unsigned identity certificate
138 *
139 * @param keyName Key name, e.g., `/<identity_name>/ksk-123456`.
140 * @param publicKey Public key to sign.
141 * @param signingIdentity The signing identity.
142 * @param notBefore Refer to IdentityCertificate.
143 * @param notAfter Refer to IdentityCertificate.
144 * @param subjectDescription Refer to IdentityCertificate.
145 * @param certPrefix Prefix before `KEY` component. By default, KeyChain will infer the
146 * certificate name according to the relation between the signingIdentity and
147 * the subject identity. If signingIdentity is a prefix of the subject identity,
148 * `KEY` will be inserted after the signingIdentity, otherwise `KEY` is inserted
149 * after subject identity (i.e., before `ksk-....`).
150 * @return IdentityCertificate.
151 */
152 shared_ptr<IdentityCertificate>
153 prepareUnsignedIdentityCertificate(const Name& keyName,
154 const PublicKey& publicKey,
155 const Name& signingIdentity,
156 const time::system_clock::TimePoint& notBefore,
157 const time::system_clock::TimePoint& notAfter,
158 const std::vector<CertificateSubjectDescription>& subjectDescription,
159 const Name& certPrefix = DEFAULT_PREFIX);
Yingdi Yuc55680b2014-02-26 12:31:35 -0800160
161 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800162 * @brief Sign packet with default identity
163 *
Yingdi Yu60bd7082014-03-25 18:18:54 -0700164 * On return, signatureInfo and signatureValue in the packet are set.
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700165 * If default identity does not exist,
Yingdi Yu60bd7082014-03-25 18:18:54 -0700166 * a temporary identity will be created and set as default.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800167 *
168 * @param packet The packet to be signed
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800169 */
Yingdi Yu2e57a582014-02-20 23:34:43 -0800170 template<typename T>
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800171 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700172 sign(T& packet);
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700173
Jeff Thompson47c93cf2013-08-09 00:38:48 -0700174 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800175 * @brief Sign packet with a particular certificate.
176 *
177 * @param packet The packet to be signed.
178 * @param certificateName The certificate name of the key to use for signing.
179 * @throws SecPublicInfo::Error if certificate does not exist.
Jeff Thompson3c73da42013-08-12 11:19:05 -0700180 */
Yingdi Yu2e57a582014-02-20 23:34:43 -0800181 template<typename T>
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700182 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700183 sign(T& packet, const Name& certificateName);
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700184
Jeff Thompson29ce3102013-09-27 11:47:48 -0700185 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800186 * @brief Sign the byte array using a particular certificate.
187 *
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700188 * @param buffer The byte array to be signed.
189 * @param bufferLength the length of buffer.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800190 * @param certificateName The certificate name of the signing key.
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700191 * @return The Signature.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800192 * @throws SecPublicInfo::Error if certificate does not exist.
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700193 */
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800194 Signature
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700195 sign(const uint8_t* buffer, size_t bufferLength, const Name& certificateName);
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700196
197 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800198 * @brief Sign packet using the default certificate of a particular identity.
199 *
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700200 * If there is no default certificate of that identity, this method will create a self-signed
201 * certificate.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800202 *
203 * @param packet The packet to be signed.
204 * @param identityName The signing identity name.
Jeff Thompson29ce3102013-09-27 11:47:48 -0700205 */
Yingdi Yu2e57a582014-02-20 23:34:43 -0800206 template<typename T>
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700207 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700208 signByIdentity(T& packet, const Name& identityName);
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700209
Jeff Thompson3c73da42013-08-12 11:19:05 -0700210 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800211 * @brief Sign the byte array using the default certificate of a particular identity.
212 *
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700213 * @param buffer The byte array to be signed.
214 * @param bufferLength the length of buffer.
215 * @param identityName The identity name.
216 * @return The Signature.
217 */
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700218 inline Signature
219 signByIdentity(const uint8_t* buffer, size_t bufferLength, const Name& identityName);
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700220
221 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700222 * @brief Set Sha256 weak signature for @param data
Yingdi Yu21157162014-02-28 13:02:34 -0800223 */
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700224 inline void
225 signWithSha256(Data& data);
Yingdi Yu21157162014-02-28 13:02:34 -0800226
227 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800228 * @brief Generate a self-signed certificate for a public key.
229 *
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700230 * @param keyName The name of the public key
231 * @return The generated certificate, shared_ptr<IdentityCertificate>() if selfSign fails
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800232 */
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800233 shared_ptr<IdentityCertificate>
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700234 selfSign(const Name& keyName);
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800235
236 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800237 * @brief Self-sign the supplied identity certificate.
238 *
239 * @param cert The supplied cert.
240 * @throws SecTpm::Error if the private key does not exist.
Jeff Thompson8efe5ad2013-08-20 17:36:38 -0700241 */
Jeff Thompson2ce8f492013-09-17 18:01:25 -0700242 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700243 selfSign(IdentityCertificate& cert);
Yingdi Yu31b4af22014-01-14 14:13:00 -0800244
Yingdi Yu2e57a582014-02-20 23:34:43 -0800245 /**
246 * @brief delete a certificate.
247 *
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700248 * If the certificate to be deleted is current default system default,
Yingdi Yu2e57a582014-02-20 23:34:43 -0800249 * the method will not delete the certificate and return immediately.
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700250 *
Yingdi Yu2e57a582014-02-20 23:34:43 -0800251 * @param certificateName The certificate to be deleted.
252 */
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700253 inline void
254 deleteCertificate(const Name& certificateName);
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800255
Yingdi Yu2e57a582014-02-20 23:34:43 -0800256 /**
257 * @brief delete a key.
258 *
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700259 * If the key to be deleted is current default system default,
Yingdi Yu2e57a582014-02-20 23:34:43 -0800260 * the method will not delete the key and return immediately.
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700261 *
Yingdi Yu2e57a582014-02-20 23:34:43 -0800262 * @param keyName The key to be deleted.
263 */
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700264 inline void
265 deleteKey(const Name& keyName);
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800266
Yingdi Yu2e57a582014-02-20 23:34:43 -0800267 /**
268 * @brief delete an identity.
269 *
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700270 * If the identity to be deleted is current default system default,
Yingdi Yu2e57a582014-02-20 23:34:43 -0800271 * the method will not delete the identity and return immediately.
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700272 *
Yingdi Yu2e57a582014-02-20 23:34:43 -0800273 * @param identity The identity to be deleted.
274 */
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700275 inline void
276 deleteIdentity(const Name& identity);
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800277
Yingdi Yu2e57a582014-02-20 23:34:43 -0800278 /**
279 * @brief export an identity.
280 *
281 * @param identity The identity to export.
282 * @param passwordStr The password to secure the private key.
Yingdi Yu64c3fb42014-02-26 17:30:04 -0800283 * @return The encoded export data.
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700284 * @throws SecPublicInfo::Error if anything goes wrong in exporting.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800285 */
Yingdi Yu64c3fb42014-02-26 17:30:04 -0800286 shared_ptr<SecuredBag>
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700287 exportIdentity(const Name& identity, const std::string& passwordStr);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800288
Yingdi Yu2e57a582014-02-20 23:34:43 -0800289 /**
290 * @brief import an identity.
291 *
Yingdi Yu64c3fb42014-02-26 17:30:04 -0800292 * @param securedBag The encoded import data.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800293 * @param passwordStr The password to secure the private key.
294 */
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800295 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700296 importIdentity(const SecuredBag& securedBag, const std::string& passwordStr);
297
298 SecPublicInfo&
299 getPib()
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800300 {
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700301 return *m_pib;
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800302 }
303
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700304 const SecPublicInfo&
305 getPib() const
306 {
307 return *m_pib;
308 }
309
310 SecTpm&
311 getTpm()
312 {
313 return *m_tpm;
314 }
315
316 const SecTpm&
317 getTpm() const
318 {
319 return *m_tpm;
320 }
321
322 /*******************************
323 * Wrapper of SecPublicInfo *
324 *******************************/
325 bool
326 doesIdentityExist(const Name& identityName) const
327 {
328 return m_pib->doesIdentityExist(identityName);
329 }
330
331 void
332 addIdentity(const Name& identityName)
333 {
334 return m_pib->addIdentity(identityName);
335 }
336
337 bool
338 doesPublicKeyExist(const Name& keyName) const
339 {
340 return m_pib->doesPublicKeyExist(keyName);
341 }
342
343 void
344 addPublicKey(const Name& keyName, KeyType keyType, const PublicKey& publicKeyDer)
345 {
346 return m_pib->addPublicKey(keyName, keyType, publicKeyDer);
347 }
348
349 shared_ptr<PublicKey>
350 getPublicKey(const Name& keyName) const
351 {
352 return m_pib->getPublicKey(keyName);
353 }
354
355 bool
356 doesCertificateExist(const Name& certificateName) const
357 {
358 return m_pib->doesCertificateExist(certificateName);
359 }
360
361 void
362 addCertificate(const IdentityCertificate& certificate)
363 {
364 return m_pib->addCertificate(certificate);
365 }
366
367 shared_ptr<IdentityCertificate>
368 getCertificate(const Name& certificateName) const
369 {
370 return m_pib->getCertificate(certificateName);
371 }
372
373 Name
374 getDefaultIdentity() const
375 {
376 return m_pib->getDefaultIdentity();
377 }
378
379 Name
380 getDefaultKeyNameForIdentity(const Name& identityName) const
381 {
382 return m_pib->getDefaultKeyNameForIdentity(identityName);
383 }
384
385 Name
386 getDefaultCertificateNameForKey(const Name& keyName) const
387 {
388 return m_pib->getDefaultCertificateNameForKey(keyName);
389 }
390
391 void
392 getAllIdentities(std::vector<Name>& nameList, bool isDefault) const
393 {
394 return m_pib->getAllIdentities(nameList, isDefault);
395 }
396
397 void
398 getAllKeyNames(std::vector<Name>& nameList, bool isDefault) const
399 {
400 return m_pib->getAllKeyNames(nameList, isDefault);
401 }
402
403 void
404 getAllKeyNamesOfIdentity(const Name& identity, std::vector<Name>& nameList, bool isDefault) const
405 {
406 return m_pib->getAllKeyNamesOfIdentity(identity, nameList, isDefault);
407 }
408
409 void
410 getAllCertificateNames(std::vector<Name>& nameList, bool isDefault) const
411 {
412 return m_pib->getAllCertificateNames(nameList, isDefault);
413 }
414
415 void
416 getAllCertificateNamesOfKey(const Name& keyName,
417 std::vector<Name>& nameList,
418 bool isDefault) const
419 {
420 return m_pib->getAllCertificateNamesOfKey(keyName, nameList, isDefault);
421 }
422
423 void
424 deleteCertificateInfo(const Name& certificateName)
425 {
426 return m_pib->deleteCertificateInfo(certificateName);
427 }
428
429 void
430 deletePublicKeyInfo(const Name& keyName)
431 {
432 return m_pib->deletePublicKeyInfo(keyName);
433 }
434
435 void
436 deleteIdentityInfo(const Name& identity)
437 {
438 return m_pib->deleteIdentityInfo(identity);
439 }
440
441 void
442 setDefaultIdentity(const Name& identityName)
443 {
444 return m_pib->setDefaultIdentity(identityName);
445 }
446
447 void
448 setDefaultKeyNameForIdentity(const Name& keyName)
449 {
450 return m_pib->setDefaultKeyNameForIdentity(keyName);
451 }
452
453 void
454 setDefaultCertificateNameForKey(const Name& certificateName)
455 {
456 return m_pib->setDefaultCertificateNameForKey(certificateName);
457 }
458
459 Name
460 getNewKeyName(const Name& identityName, bool useKsk)
461 {
462 return m_pib->getNewKeyName(identityName, useKsk);
463 }
464
465 Name
466 getDefaultCertificateNameForIdentity(const Name& identityName) const
467 {
468 return m_pib->getDefaultCertificateNameForIdentity(identityName);
469 }
470
471 Name
472 getDefaultCertificateName() const
473 {
474 return m_pib->getDefaultCertificateName();
475 }
476
477 void
478 addCertificateAsKeyDefault(const IdentityCertificate& certificate)
479 {
480 return m_pib->addCertificateAsKeyDefault(certificate);
481 }
482
483 void
484 addCertificateAsIdentityDefault(const IdentityCertificate& certificate)
485 {
486 return m_pib->addCertificateAsIdentityDefault(certificate);
487 }
488
489 void
490 addCertificateAsSystemDefault(const IdentityCertificate& certificate)
491 {
492 return m_pib->addCertificateAsSystemDefault(certificate);
493 }
494
495 shared_ptr<IdentityCertificate>
496 getDefaultCertificate() const
497 {
498 return m_pib->defaultCertificate();
499 }
500
501 void
502 refreshDefaultCertificate()
503 {
504 return m_pib->refreshDefaultCertificate();
505 }
506
507 /*******************************
508 * Wrapper of SecTpm *
509 *******************************/
510
511 void
512 setTpmPassword(const uint8_t* password, size_t passwordLength)
513 {
514 return m_tpm->setTpmPassword(password, passwordLength);
515 }
516
517 void
518 resetTpmPassword()
519 {
520 return m_tpm->resetTpmPassword();
521 }
522
523 void
524 setInTerminal(bool inTerminal)
525 {
526 return m_tpm->setInTerminal(inTerminal);
527 }
528
529 bool
530 getInTerminal() const
531 {
532 return m_tpm->getInTerminal();
533 }
534
535 bool
536 isLocked() const
537 {
538 return m_tpm->isLocked();
539 }
540
541 bool
542 unlockTpm(const char* password, size_t passwordLength, bool usePassword)
543 {
544 return m_tpm->unlockTpm(password, passwordLength, usePassword);
545 }
546
547 void
548 generateKeyPairInTpm(const Name& keyName, KeyType keyType, int keySize)
549 {
550 return m_tpm->generateKeyPairInTpm(keyName, keyType, keySize);
551 }
552
553 void
554 deleteKeyPairInTpm(const Name& keyName)
555 {
556 return m_tpm->deleteKeyPairInTpm(keyName);
557 }
558
559 shared_ptr<PublicKey>
560 getPublicKeyFromTpm(const Name& keyName) const
561 {
562 return m_tpm->getPublicKeyFromTpm(keyName);
563 }
564
565 Block
566 signInTpm(const uint8_t* data, size_t dataLength,
567 const Name& keyName,
568 DigestAlgorithm digestAlgorithm)
569 {
570 return m_tpm->signInTpm(data, dataLength, keyName, digestAlgorithm);
571 }
572
573 ConstBufferPtr
574 decryptInTpm(const uint8_t* data, size_t dataLength, const Name& keyName, bool isSymmetric)
575 {
576 return m_tpm->decryptInTpm(data, dataLength, keyName, isSymmetric);
577 }
578
579 ConstBufferPtr
580 encryptInTpm(const uint8_t* data, size_t dataLength, const Name& keyName, bool isSymmetric)
581 {
582 return m_tpm->encryptInTpm(data, dataLength, keyName, isSymmetric);
583 }
584
585 void
586 generateSymmetricKeyInTpm(const Name& keyName, KeyType keyType, int keySize)
587 {
588 return m_tpm->generateSymmetricKeyInTpm(keyName, keyType, keySize);
589 }
590
591 bool
592 doesKeyExistInTpm(const Name& keyName, KeyClass keyClass) const
593 {
594 return m_tpm->doesKeyExistInTpm(keyName, keyClass);
595 }
596
597 bool
598 generateRandomBlock(uint8_t* res, size_t size) const
599 {
600 return m_tpm->generateRandomBlock(res, size);
601 }
602
603 void
604 addAppToAcl(const Name& keyName, KeyClass keyClass, const std::string& appPath, AclType acl)
605 {
606 return m_tpm->addAppToAcl(keyName, keyClass, appPath, acl);
607 }
608
609 ConstBufferPtr
610 exportPrivateKeyPkcs5FromTpm(const Name& keyName, const std::string& password)
611 {
612 return m_tpm->exportPrivateKeyPkcs5FromTpm(keyName, password);
613 }
614
615 bool
616 importPrivateKeyPkcs5IntoTpm(const Name& keyName,
617 const uint8_t* buf, size_t size,
618 const std::string& password)
619 {
620 return m_tpm->importPrivateKeyPkcs5IntoTpm(keyName, buf, size, password);
621 }
Jeff Thompson8efe5ad2013-08-20 17:36:38 -0700622
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800623private:
Yingdi Yu2e57a582014-02-20 23:34:43 -0800624 /**
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700625 * @brief Set default certificate if it is not initialized
626 */
627 void
628 setDefaultCertificateInternal();
629
630 /**
631 * @brief Sign a packet using a pariticular certificate.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800632 *
633 * @param packet The packet to be signed.
634 * @param certificate The signing certificate.
635 */
636 template<typename T>
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800637 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700638 sign(T& packet, const IdentityCertificate& certificate);
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800639
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800640 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800641 * @brief Generate a key pair for the specified identity.
642 *
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800643 * @param identityName The name of the specified identity.
644 * @param isKsk true for generating a Key-Signing-Key (KSK), false for a Data-Signing-Key (KSK).
645 * @param keyType The type of the key pair, e.g. KEY_TYPE_RSA.
646 * @param keySize The size of the key pair.
647 * @return The name of the generated key.
648 */
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700649 inline Name
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700650 generateKeyPair(const Name& identityName, bool isKsk = false,
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700651 KeyType keyType = KEY_TYPE_RSA, int keySize = 2048);
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800652
Yingdi Yu8726f652014-01-23 10:35:12 -0800653 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800654 * @brief Sign the data using a particular key.
655 *
656 * @param data Reference to the data packet.
657 * @param signature Signature to be added.
Yingdi Yu8726f652014-01-23 10:35:12 -0800658 * @param keyName The name of the signing key.
659 * @param digestAlgorithm the digest algorithm.
660 * @throws Tpm::Error
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700661 */
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700662 inline void
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700663 signPacketWrapper(Data& data, const SignatureSha256WithRsa& signature,
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700664 const Name& keyName, DigestAlgorithm digestAlgorithm);
Yingdi Yu8726f652014-01-23 10:35:12 -0800665
Yingdi Yu2e57a582014-02-20 23:34:43 -0800666 /**
667 * @brief Sign the interest using a particular key.
668 *
669 * @param interest Reference to the interest packet.
670 * @param signature Signature to be added.
671 * @param keyName The name of the signing key.
672 * @param digestAlgorithm the digest algorithm.
673 * @throws Tpm::Error
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700674 */
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700675 inline void
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700676 signPacketWrapper(Interest& interest, const SignatureSha256WithRsa& signature,
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700677 const Name& keyName, DigestAlgorithm digestAlgorithm);
Yingdi Yu2e57a582014-02-20 23:34:43 -0800678
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700679
680private:
681 SecPublicInfo* m_pib;
682 SecTpm* m_tpm;
683};
684
685template<class T>
686inline
687KeyChain::KeyChain(T)
688 : m_pib(new typename T::Pib)
689 , m_tpm(new typename T::Tpm)
690{
691}
692
693inline Name
694KeyChain::createIdentity(const Name& identityName)
695{
696 m_pib->addIdentity(identityName);
697
698 Name keyName;
699 try
700 {
701 keyName = m_pib->getDefaultKeyNameForIdentity(identityName);
702 }
703 catch (SecPublicInfo::Error& e)
704 {
705 keyName = generateRsaKeyPairAsDefault(identityName, true);
706 }
707
708 Name certName;
709 try
710 {
711 certName = m_pib->getDefaultCertificateNameForKey(keyName);
712 }
713 catch (SecPublicInfo::Error& e)
714 {
715 shared_ptr<IdentityCertificate> selfCert = selfSign(keyName);
716 m_pib->addCertificateAsIdentityDefault(*selfCert);
717 certName = selfCert->getName();
718 }
719
720 return certName;
721}
722
723inline Name
724KeyChain::generateRsaKeyPair(const Name& identityName, bool isKsk, int keySize)
725{
726 return generateKeyPair(identityName, isKsk, KEY_TYPE_RSA, keySize);
727}
728
729inline Name
730KeyChain::generateRsaKeyPairAsDefault(const Name& identityName, bool isKsk, int keySize)
731{
732 Name keyName = generateKeyPair(identityName, isKsk, KEY_TYPE_RSA, keySize);
733
734 m_pib->setDefaultKeyNameForIdentity(keyName);
735
736 return keyName;
737}
738
739template<typename T>
740void
741KeyChain::sign(T& packet)
742{
743 if (!static_cast<bool>(m_pib->defaultCertificate()))
744 setDefaultCertificateInternal();
745
746 sign(packet, *m_pib->defaultCertificate());
747}
748
749template<typename T>
750void
751KeyChain::sign(T& packet, const Name& certificateName)
752{
753 if (!m_pib->doesCertificateExist(certificateName))
754 throw SecPublicInfo::Error("Requested certificate [" +
755 certificateName.toUri() + "] doesn't exist");
756
757 SignatureSha256WithRsa signature;
758 // implicit conversion should take care
759 signature.setKeyLocator(certificateName.getPrefix(-1));
760
761 // For temporary usage, we support RSA + SHA256 only, but will support more.
762 signPacketWrapper(packet, signature,
763 IdentityCertificate::certificateNameToPublicKeyName(certificateName),
764 DIGEST_ALGORITHM_SHA256);
765}
766
767template<typename T>
768void
769KeyChain::signByIdentity(T& packet, const Name& identityName)
770{
771 Name signingCertificateName;
772 try
773 {
774 signingCertificateName = m_pib->getDefaultCertificateNameForIdentity(identityName);
775 }
776 catch (SecPublicInfo::Error& e)
777 {
778 signingCertificateName = createIdentity(identityName);
779 // Ideally, no exception will be thrown out, unless something goes wrong in the TPM, which
780 // is a fatal error.
781 }
782
783 // We either get or create the signing certificate, sign packet! (no exception unless fatal
784 // error in TPM)
785 sign(packet, signingCertificateName);
786}
787
788inline Signature
789KeyChain::signByIdentity(const uint8_t* buffer, size_t bufferLength, const Name& identityName)
790{
791 Name signingCertificateName;
792 try
793 {
794 signingCertificateName = m_pib->getDefaultCertificateNameForIdentity(identityName);
795 }
796 catch (SecPublicInfo::Error& e)
797 {
798 signingCertificateName = createIdentity(identityName);
799 // Ideally, no exception will be thrown out, unless something goes wrong in the TPM, which
800 // is a fatal error.
801 }
802
803 // We either get or create the signing certificate, sign data! (no exception unless fatal error
804 // in TPM)
805 return sign(buffer, bufferLength, signingCertificateName);
806}
807
808inline void
809KeyChain::signWithSha256(Data& data)
810{
811 SignatureSha256 sig;
812 data.setSignature(sig);
813
814 Block sigValue(Tlv::SignatureValue,
815 crypto::sha256(data.wireEncode().value(),
816 data.wireEncode().value_size() -
817 data.getSignature().getValue().size()));
818 data.setSignatureValue(sigValue);
819}
820
821inline void
822KeyChain::deleteCertificate(const Name& certificateName)
823{
824 try
825 {
826 if (m_pib->getDefaultCertificateName() == certificateName)
827 return;
828 }
829 catch (SecPublicInfo::Error& e)
830 {
831 // Not a real error, just try to delete the certificate
832 }
833
834 m_pib->deleteCertificateInfo(certificateName);
835}
836
837inline void
838KeyChain::deleteKey(const Name& keyName)
839{
840 try
841 {
842 if (m_pib->getDefaultKeyNameForIdentity(m_pib->getDefaultIdentity()) == keyName)
843 return;
844 }
845 catch (SecPublicInfo::Error& e)
846 {
847 // Not a real error, just try to delete the key
848 }
849
850 m_pib->deletePublicKeyInfo(keyName);
851 m_tpm->deleteKeyPairInTpm(keyName);
852}
853
854inline void
855KeyChain::deleteIdentity(const Name& identity)
856{
857 try
858 {
859 if (m_pib->getDefaultIdentity() == identity)
860 return;
861 }
862 catch (SecPublicInfo::Error& e)
863 {
864 // Not a real error, just try to delete the identity
865 }
866
867 std::vector<Name> nameList;
868 m_pib->getAllKeyNamesOfIdentity(identity, nameList, true);
869 m_pib->getAllKeyNamesOfIdentity(identity, nameList, false);
870
871 m_pib->deleteIdentityInfo(identity);
872
873 std::vector<Name>::const_iterator it = nameList.begin();
874 for(; it != nameList.end(); it++)
875 m_tpm->deleteKeyPairInTpm(*it);
876}
877
878template<typename T>
879void
880KeyChain::sign(T& packet, const IdentityCertificate& certificate)
881{
882 SignatureSha256WithRsa signature;
883 signature.setKeyLocator(certificate.getName().getPrefix(-1));
884
885 // For temporary usage, we support RSA + SHA256 only, but will support more.
886 signPacketWrapper(packet, signature, certificate.getPublicKeyName(), DIGEST_ALGORITHM_SHA256);
887}
888
889inline Name
890KeyChain::generateKeyPair(const Name& identityName, bool isKsk, KeyType keyType, int keySize)
891{
892 Name keyName = m_pib->getNewKeyName(identityName, isKsk);
893
894 m_tpm->generateKeyPairInTpm(keyName.toUri(), keyType, keySize);
895
896 shared_ptr<PublicKey> pubKey = m_tpm->getPublicKeyFromTpm(keyName.toUri());
897 m_pib->addPublicKey(keyName, keyType, *pubKey);
898
899 return keyName;
900}
901
902inline void
903KeyChain::signPacketWrapper(Data& data, const SignatureSha256WithRsa& signature,
904 const Name& keyName, DigestAlgorithm digestAlgorithm)
905{
906 data.setSignature(signature);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700907
908 EncodingBuffer encoder;
909 data.wireEncode(encoder, true);
910
911 Block signatureValue = m_tpm->signInTpm(encoder.buf(), encoder.size(),
912 keyName, digestAlgorithm);
913 data.wireEncode(encoder, signatureValue);
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700914}
915
916inline void
917KeyChain::signPacketWrapper(Interest& interest, const SignatureSha256WithRsa& signature,
918 const Name& keyName, DigestAlgorithm digestAlgorithm)
919{
920 Name signedName = interest.getName();
921 signedName.append(signature.getInfo());
922
923 Block sigValue = m_tpm->signInTpm(signedName.wireEncode().value(),
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700924 signedName.wireEncode().value_size(),
Yingdi Yu2e57a582014-02-20 23:34:43 -0800925 keyName,
Alexander Afanasyev24b75c82014-05-31 15:59:31 +0300926 digestAlgorithm);
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700927 sigValue.encode();
928 signedName.append(sigValue);
929 interest.setName(signedName);
930}
Yingdi Yu2e57a582014-02-20 23:34:43 -0800931
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700932}
Jeff Thompson47c93cf2013-08-09 00:38:48 -0700933
Alexander Afanasyev766cea72014-04-24 19:16:42 -0700934#endif // NDN_SECURITY_KEY_CHAIN_HPP