blob: 2b6da41c3c7788c55f5da97b6af336191a5f2a62 [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 Yubf6a2812014-06-17 15:32:11 -070031#include "digest-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 Yu0f5fb692014-06-10 12:07:28 -070035#include "../util/random.hpp"
Yingdi Yu31b4af22014-01-14 14:13:00 -080036
Jeff Thompson47c93cf2013-08-09 00:38:48 -070037
38namespace ndn {
39
Yingdi Yuf56c68f2014-04-24 21:50:13 -070040template<class TypePib, class TypeTpm>
41class KeyChainTraits
Yingdi Yu31b4af22014-01-14 14:13:00 -080042{
Jeff Thompson47c93cf2013-08-09 00:38:48 -070043public:
Yingdi Yuf56c68f2014-04-24 21:50:13 -070044 typedef TypePib Pib;
45 typedef TypeTpm Tpm;
46};
47
Alexander Afanasyev45a37132014-04-28 16:54:57 -070048class KeyChain : noncopyable
Yingdi Yuf56c68f2014-04-24 21:50:13 -070049{
50public:
51 class Error : public std::runtime_error
52 {
53 public:
54 explicit
55 Error(const std::string& what)
56 : std::runtime_error(what)
57 {
58 }
59 };
60
Yingdi Yu0eb5d722014-06-10 15:06:25 -070061 static const Name DEFAULT_PREFIX;
62
Yingdi Yuf56c68f2014-04-24 21:50:13 -070063 KeyChain();
64
65 template<class KeyChainTraits>
Alexander Afanasyeva4297a62014-06-19 13:29:34 -070066 explicit
Yingdi Yuf56c68f2014-04-24 21:50:13 -070067 KeyChain(KeyChainTraits traits);
68
69 KeyChain(const std::string& pibName,
70 const std::string& tpmName);
71
72 virtual
73 ~KeyChain()
74 {
75 if (m_pib != 0)
76 delete m_pib;
77
78 if (m_tpm != 0)
79 delete m_tpm;
80 }
81
Yingdi Yube4150e2014-02-18 13:02:46 -080082 /**
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070083 * @brief Create an identity by creating a pair of Key-Signing-Key (KSK) for this identity and a
84 * self-signed certificate of the KSK.
Yingdi Yube4150e2014-02-18 13:02:46 -080085 *
Yingdi Yu2abd73f2014-01-08 23:34:11 -080086 * @param identityName The name of the identity.
Yingdi Yu28fd32f2014-01-28 19:03:03 -080087 * @return The name of the default certificate of the identity.
Yingdi Yu2abd73f2014-01-08 23:34:11 -080088 */
Yingdi Yuf56c68f2014-04-24 21:50:13 -070089 inline Name
90 createIdentity(const Name& identityName);
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -070091
Yingdi Yu2abd73f2014-01-08 23:34:11 -080092 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -080093 * @brief Generate a pair of RSA keys for the specified identity.
94 *
Yingdi Yu2abd73f2014-01-08 23:34:11 -080095 * @param identityName The name of the identity.
96 * @param isKsk true for generating a Key-Signing-Key (KSK), false for a Data-Signing-Key (KSK).
97 * @param keySize The size of the key.
98 * @return The generated key name.
99 */
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700100 inline Name
101 generateRsaKeyPair(const Name& identityName, bool isKsk = false, int keySize = 2048);
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700102
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800103 /**
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700104 * @brief Generate a pair of RSA keys for the specified identity and set it as default key for
105 * the identity.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800106 *
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800107 * @param identityName The name of the identity.
108 * @param isKsk true for generating a Key-Signing-Key (KSK), false for a Data-Signing-Key (KSK).
109 * @param keySize The size of the key.
110 * @return The generated key name.
111 */
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700112 inline Name
113 generateRsaKeyPairAsDefault(const Name& identityName, bool isKsk = false, int keySize = 2048);
Jeff Thompson79a2d5d2013-09-27 14:32:23 -0700114
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800115 /**
Yingdi Yuc55680b2014-02-26 12:31:35 -0800116 * @brief prepare an unsigned identity certificate
117 *
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700118 * @param keyName Key name, e.g., `/<identity_name>/ksk-123456`.
Yingdi Yuc55680b2014-02-26 12:31:35 -0800119 * @param signingIdentity The signing identity.
120 * @param notBefore Refer to IdentityCertificate.
121 * @param notAfter Refer to IdentityCertificate.
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700122 * @param subjectDescription Refer to IdentityCertificate.
Yingdi Yu0eb5d722014-06-10 15:06:25 -0700123 * @param certPrefix Prefix before `KEY` component. By default, KeyChain will infer the
124 * certificate name according to the relation between the signingIdentity and
125 * the subject identity. If signingIdentity is a prefix of the subject identity,
126 * `KEY` will be inserted after the signingIdentity, otherwise `KEY` is inserted
127 * after subject identity (i.e., before `ksk-....`).
Yingdi Yuc55680b2014-02-26 12:31:35 -0800128 * @return IdentityCertificate.
129 */
130 shared_ptr<IdentityCertificate>
131 prepareUnsignedIdentityCertificate(const Name& keyName,
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700132 const Name& signingIdentity,
133 const time::system_clock::TimePoint& notBefore,
134 const time::system_clock::TimePoint& notAfter,
Yingdi Yu0eb5d722014-06-10 15:06:25 -0700135 const std::vector<CertificateSubjectDescription>& subjectDescription,
136 const Name& certPrefix = DEFAULT_PREFIX);
137
138 /**
139 * @brief prepare an unsigned identity certificate
140 *
141 * @param keyName Key name, e.g., `/<identity_name>/ksk-123456`.
142 * @param publicKey Public key to sign.
143 * @param signingIdentity The signing identity.
144 * @param notBefore Refer to IdentityCertificate.
145 * @param notAfter Refer to IdentityCertificate.
146 * @param subjectDescription Refer to IdentityCertificate.
147 * @param certPrefix Prefix before `KEY` component. By default, KeyChain will infer the
148 * certificate name according to the relation between the signingIdentity and
149 * the subject identity. If signingIdentity is a prefix of the subject identity,
150 * `KEY` will be inserted after the signingIdentity, otherwise `KEY` is inserted
151 * after subject identity (i.e., before `ksk-....`).
152 * @return IdentityCertificate.
153 */
154 shared_ptr<IdentityCertificate>
155 prepareUnsignedIdentityCertificate(const Name& keyName,
156 const PublicKey& publicKey,
157 const Name& signingIdentity,
158 const time::system_clock::TimePoint& notBefore,
159 const time::system_clock::TimePoint& notAfter,
160 const std::vector<CertificateSubjectDescription>& subjectDescription,
161 const Name& certPrefix = DEFAULT_PREFIX);
Yingdi Yuc55680b2014-02-26 12:31:35 -0800162
163 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800164 * @brief Sign packet with default identity
165 *
Yingdi Yu60bd7082014-03-25 18:18:54 -0700166 * On return, signatureInfo and signatureValue in the packet are set.
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700167 * If default identity does not exist,
Yingdi Yu60bd7082014-03-25 18:18:54 -0700168 * a temporary identity will be created and set as default.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800169 *
170 * @param packet The packet to be signed
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800171 */
Yingdi Yu2e57a582014-02-20 23:34:43 -0800172 template<typename T>
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800173 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700174 sign(T& packet);
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700175
Jeff Thompson47c93cf2013-08-09 00:38:48 -0700176 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800177 * @brief Sign packet with a particular certificate.
178 *
179 * @param packet The packet to be signed.
180 * @param certificateName The certificate name of the key to use for signing.
181 * @throws SecPublicInfo::Error if certificate does not exist.
Jeff Thompson3c73da42013-08-12 11:19:05 -0700182 */
Yingdi Yu2e57a582014-02-20 23:34:43 -0800183 template<typename T>
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700184 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700185 sign(T& packet, const Name& certificateName);
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700186
Jeff Thompson29ce3102013-09-27 11:47:48 -0700187 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800188 * @brief Sign the byte array using a particular certificate.
189 *
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700190 * @param buffer The byte array to be signed.
191 * @param bufferLength the length of buffer.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800192 * @param certificateName The certificate name of the signing key.
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700193 * @return The Signature.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800194 * @throws SecPublicInfo::Error if certificate does not exist.
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700195 */
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800196 Signature
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700197 sign(const uint8_t* buffer, size_t bufferLength, const Name& certificateName);
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700198
199 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800200 * @brief Sign packet using the default certificate of a particular identity.
201 *
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700202 * If there is no default certificate of that identity, this method will create a self-signed
203 * certificate.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800204 *
205 * @param packet The packet to be signed.
206 * @param identityName The signing identity name.
Jeff Thompson29ce3102013-09-27 11:47:48 -0700207 */
Yingdi Yu2e57a582014-02-20 23:34:43 -0800208 template<typename T>
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700209 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700210 signByIdentity(T& packet, const Name& identityName);
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700211
Jeff Thompson3c73da42013-08-12 11:19:05 -0700212 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800213 * @brief Sign the byte array using the default certificate of a particular identity.
214 *
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700215 * @param buffer The byte array to be signed.
216 * @param bufferLength the length of buffer.
217 * @param identityName The identity name.
218 * @return The Signature.
219 */
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700220 inline Signature
221 signByIdentity(const uint8_t* buffer, size_t bufferLength, const Name& identityName);
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700222
223 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700224 * @brief Set Sha256 weak signature for @param data
Yingdi Yu21157162014-02-28 13:02:34 -0800225 */
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700226 inline void
227 signWithSha256(Data& data);
Yingdi Yu21157162014-02-28 13:02:34 -0800228
229 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800230 * @brief Generate a self-signed certificate for a public key.
231 *
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700232 * @param keyName The name of the public key
233 * @return The generated certificate, shared_ptr<IdentityCertificate>() if selfSign fails
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800234 */
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800235 shared_ptr<IdentityCertificate>
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700236 selfSign(const Name& keyName);
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800237
238 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800239 * @brief Self-sign the supplied identity certificate.
240 *
241 * @param cert The supplied cert.
242 * @throws SecTpm::Error if the private key does not exist.
Jeff Thompson8efe5ad2013-08-20 17:36:38 -0700243 */
Jeff Thompson2ce8f492013-09-17 18:01:25 -0700244 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700245 selfSign(IdentityCertificate& cert);
Yingdi Yu31b4af22014-01-14 14:13:00 -0800246
Yingdi Yu2e57a582014-02-20 23:34:43 -0800247 /**
248 * @brief delete a certificate.
249 *
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700250 * If the certificate to be deleted is current default system default,
Yingdi Yu2e57a582014-02-20 23:34:43 -0800251 * the method will not delete the certificate and return immediately.
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700252 *
Yingdi Yu2e57a582014-02-20 23:34:43 -0800253 * @param certificateName The certificate to be deleted.
254 */
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700255 inline void
256 deleteCertificate(const Name& certificateName);
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800257
Yingdi Yu2e57a582014-02-20 23:34:43 -0800258 /**
259 * @brief delete a key.
260 *
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700261 * If the key to be deleted is current default system default,
Yingdi Yu2e57a582014-02-20 23:34:43 -0800262 * the method will not delete the key and return immediately.
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700263 *
Yingdi Yu2e57a582014-02-20 23:34:43 -0800264 * @param keyName The key to be deleted.
265 */
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700266 inline void
267 deleteKey(const Name& keyName);
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800268
Yingdi Yu2e57a582014-02-20 23:34:43 -0800269 /**
270 * @brief delete an identity.
271 *
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700272 * If the identity to be deleted is current default system default,
Yingdi Yu2e57a582014-02-20 23:34:43 -0800273 * the method will not delete the identity and return immediately.
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700274 *
Yingdi Yu2e57a582014-02-20 23:34:43 -0800275 * @param identity The identity to be deleted.
276 */
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700277 inline void
278 deleteIdentity(const Name& identity);
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800279
Yingdi Yu2e57a582014-02-20 23:34:43 -0800280 /**
281 * @brief export an identity.
282 *
283 * @param identity The identity to export.
284 * @param passwordStr The password to secure the private key.
Yingdi Yu64c3fb42014-02-26 17:30:04 -0800285 * @return The encoded export data.
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700286 * @throws SecPublicInfo::Error if anything goes wrong in exporting.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800287 */
Yingdi Yu64c3fb42014-02-26 17:30:04 -0800288 shared_ptr<SecuredBag>
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700289 exportIdentity(const Name& identity, const std::string& passwordStr);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800290
Yingdi Yu2e57a582014-02-20 23:34:43 -0800291 /**
292 * @brief import an identity.
293 *
Yingdi Yu64c3fb42014-02-26 17:30:04 -0800294 * @param securedBag The encoded import data.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800295 * @param passwordStr The password to secure the private key.
296 */
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800297 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700298 importIdentity(const SecuredBag& securedBag, const std::string& passwordStr);
299
300 SecPublicInfo&
301 getPib()
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800302 {
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700303 return *m_pib;
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800304 }
305
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700306 const SecPublicInfo&
307 getPib() const
308 {
309 return *m_pib;
310 }
311
312 SecTpm&
313 getTpm()
314 {
315 return *m_tpm;
316 }
317
318 const SecTpm&
319 getTpm() const
320 {
321 return *m_tpm;
322 }
323
324 /*******************************
325 * Wrapper of SecPublicInfo *
326 *******************************/
327 bool
328 doesIdentityExist(const Name& identityName) const
329 {
330 return m_pib->doesIdentityExist(identityName);
331 }
332
333 void
334 addIdentity(const Name& identityName)
335 {
336 return m_pib->addIdentity(identityName);
337 }
338
339 bool
340 doesPublicKeyExist(const Name& keyName) const
341 {
342 return m_pib->doesPublicKeyExist(keyName);
343 }
344
345 void
346 addPublicKey(const Name& keyName, KeyType keyType, const PublicKey& publicKeyDer)
347 {
348 return m_pib->addPublicKey(keyName, keyType, publicKeyDer);
349 }
350
351 shared_ptr<PublicKey>
352 getPublicKey(const Name& keyName) const
353 {
354 return m_pib->getPublicKey(keyName);
355 }
356
357 bool
358 doesCertificateExist(const Name& certificateName) const
359 {
360 return m_pib->doesCertificateExist(certificateName);
361 }
362
363 void
364 addCertificate(const IdentityCertificate& certificate)
365 {
366 return m_pib->addCertificate(certificate);
367 }
368
369 shared_ptr<IdentityCertificate>
370 getCertificate(const Name& certificateName) const
371 {
372 return m_pib->getCertificate(certificateName);
373 }
374
375 Name
376 getDefaultIdentity() const
377 {
378 return m_pib->getDefaultIdentity();
379 }
380
381 Name
382 getDefaultKeyNameForIdentity(const Name& identityName) const
383 {
384 return m_pib->getDefaultKeyNameForIdentity(identityName);
385 }
386
387 Name
388 getDefaultCertificateNameForKey(const Name& keyName) const
389 {
390 return m_pib->getDefaultCertificateNameForKey(keyName);
391 }
392
393 void
394 getAllIdentities(std::vector<Name>& nameList, bool isDefault) const
395 {
396 return m_pib->getAllIdentities(nameList, isDefault);
397 }
398
399 void
400 getAllKeyNames(std::vector<Name>& nameList, bool isDefault) const
401 {
402 return m_pib->getAllKeyNames(nameList, isDefault);
403 }
404
405 void
406 getAllKeyNamesOfIdentity(const Name& identity, std::vector<Name>& nameList, bool isDefault) const
407 {
408 return m_pib->getAllKeyNamesOfIdentity(identity, nameList, isDefault);
409 }
410
411 void
412 getAllCertificateNames(std::vector<Name>& nameList, bool isDefault) const
413 {
414 return m_pib->getAllCertificateNames(nameList, isDefault);
415 }
416
417 void
418 getAllCertificateNamesOfKey(const Name& keyName,
419 std::vector<Name>& nameList,
420 bool isDefault) const
421 {
422 return m_pib->getAllCertificateNamesOfKey(keyName, nameList, isDefault);
423 }
424
425 void
426 deleteCertificateInfo(const Name& certificateName)
427 {
428 return m_pib->deleteCertificateInfo(certificateName);
429 }
430
431 void
432 deletePublicKeyInfo(const Name& keyName)
433 {
434 return m_pib->deletePublicKeyInfo(keyName);
435 }
436
437 void
438 deleteIdentityInfo(const Name& identity)
439 {
440 return m_pib->deleteIdentityInfo(identity);
441 }
442
443 void
444 setDefaultIdentity(const Name& identityName)
445 {
446 return m_pib->setDefaultIdentity(identityName);
447 }
448
449 void
450 setDefaultKeyNameForIdentity(const Name& keyName)
451 {
452 return m_pib->setDefaultKeyNameForIdentity(keyName);
453 }
454
455 void
456 setDefaultCertificateNameForKey(const Name& certificateName)
457 {
458 return m_pib->setDefaultCertificateNameForKey(certificateName);
459 }
460
461 Name
462 getNewKeyName(const Name& identityName, bool useKsk)
463 {
464 return m_pib->getNewKeyName(identityName, useKsk);
465 }
466
467 Name
468 getDefaultCertificateNameForIdentity(const Name& identityName) const
469 {
470 return m_pib->getDefaultCertificateNameForIdentity(identityName);
471 }
472
473 Name
474 getDefaultCertificateName() const
475 {
476 return m_pib->getDefaultCertificateName();
477 }
478
479 void
480 addCertificateAsKeyDefault(const IdentityCertificate& certificate)
481 {
482 return m_pib->addCertificateAsKeyDefault(certificate);
483 }
484
485 void
486 addCertificateAsIdentityDefault(const IdentityCertificate& certificate)
487 {
488 return m_pib->addCertificateAsIdentityDefault(certificate);
489 }
490
491 void
492 addCertificateAsSystemDefault(const IdentityCertificate& certificate)
493 {
494 return m_pib->addCertificateAsSystemDefault(certificate);
495 }
496
497 shared_ptr<IdentityCertificate>
498 getDefaultCertificate() const
499 {
500 return m_pib->defaultCertificate();
501 }
502
503 void
504 refreshDefaultCertificate()
505 {
506 return m_pib->refreshDefaultCertificate();
507 }
508
509 /*******************************
510 * Wrapper of SecTpm *
511 *******************************/
512
513 void
514 setTpmPassword(const uint8_t* password, size_t passwordLength)
515 {
516 return m_tpm->setTpmPassword(password, passwordLength);
517 }
518
519 void
520 resetTpmPassword()
521 {
522 return m_tpm->resetTpmPassword();
523 }
524
525 void
526 setInTerminal(bool inTerminal)
527 {
528 return m_tpm->setInTerminal(inTerminal);
529 }
530
531 bool
532 getInTerminal() const
533 {
534 return m_tpm->getInTerminal();
535 }
536
537 bool
538 isLocked() const
539 {
540 return m_tpm->isLocked();
541 }
542
543 bool
544 unlockTpm(const char* password, size_t passwordLength, bool usePassword)
545 {
546 return m_tpm->unlockTpm(password, passwordLength, usePassword);
547 }
548
549 void
550 generateKeyPairInTpm(const Name& keyName, KeyType keyType, int keySize)
551 {
552 return m_tpm->generateKeyPairInTpm(keyName, keyType, keySize);
553 }
554
555 void
556 deleteKeyPairInTpm(const Name& keyName)
557 {
558 return m_tpm->deleteKeyPairInTpm(keyName);
559 }
560
561 shared_ptr<PublicKey>
562 getPublicKeyFromTpm(const Name& keyName) const
563 {
564 return m_tpm->getPublicKeyFromTpm(keyName);
565 }
566
567 Block
568 signInTpm(const uint8_t* data, size_t dataLength,
569 const Name& keyName,
570 DigestAlgorithm digestAlgorithm)
571 {
572 return m_tpm->signInTpm(data, dataLength, keyName, digestAlgorithm);
573 }
574
575 ConstBufferPtr
576 decryptInTpm(const uint8_t* data, size_t dataLength, const Name& keyName, bool isSymmetric)
577 {
578 return m_tpm->decryptInTpm(data, dataLength, keyName, isSymmetric);
579 }
580
581 ConstBufferPtr
582 encryptInTpm(const uint8_t* data, size_t dataLength, const Name& keyName, bool isSymmetric)
583 {
584 return m_tpm->encryptInTpm(data, dataLength, keyName, isSymmetric);
585 }
586
587 void
588 generateSymmetricKeyInTpm(const Name& keyName, KeyType keyType, int keySize)
589 {
590 return m_tpm->generateSymmetricKeyInTpm(keyName, keyType, keySize);
591 }
592
593 bool
594 doesKeyExistInTpm(const Name& keyName, KeyClass keyClass) const
595 {
596 return m_tpm->doesKeyExistInTpm(keyName, keyClass);
597 }
598
599 bool
600 generateRandomBlock(uint8_t* res, size_t size) const
601 {
602 return m_tpm->generateRandomBlock(res, size);
603 }
604
605 void
606 addAppToAcl(const Name& keyName, KeyClass keyClass, const std::string& appPath, AclType acl)
607 {
608 return m_tpm->addAppToAcl(keyName, keyClass, appPath, acl);
609 }
610
611 ConstBufferPtr
612 exportPrivateKeyPkcs5FromTpm(const Name& keyName, const std::string& password)
613 {
614 return m_tpm->exportPrivateKeyPkcs5FromTpm(keyName, password);
615 }
616
617 bool
618 importPrivateKeyPkcs5IntoTpm(const Name& keyName,
619 const uint8_t* buf, size_t size,
620 const std::string& password)
621 {
622 return m_tpm->importPrivateKeyPkcs5IntoTpm(keyName, buf, size, password);
623 }
Jeff Thompson8efe5ad2013-08-20 17:36:38 -0700624
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800625private:
Yingdi Yu2e57a582014-02-20 23:34:43 -0800626 /**
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700627 * @brief Set default certificate if it is not initialized
628 */
629 void
630 setDefaultCertificateInternal();
631
632 /**
633 * @brief Sign a packet using a pariticular certificate.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800634 *
635 * @param packet The packet to be signed.
636 * @param certificate The signing certificate.
637 */
638 template<typename T>
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800639 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700640 sign(T& packet, const IdentityCertificate& certificate);
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800641
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800642 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800643 * @brief Generate a key pair for the specified identity.
644 *
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800645 * @param identityName The name of the specified identity.
646 * @param isKsk true for generating a Key-Signing-Key (KSK), false for a Data-Signing-Key (KSK).
647 * @param keyType The type of the key pair, e.g. KEY_TYPE_RSA.
648 * @param keySize The size of the key pair.
649 * @return The name of the generated key.
650 */
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700651 inline Name
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700652 generateKeyPair(const Name& identityName, bool isKsk = false,
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700653 KeyType keyType = KEY_TYPE_RSA, int keySize = 2048);
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800654
Yingdi Yu8726f652014-01-23 10:35:12 -0800655 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800656 * @brief Sign the data using a particular key.
657 *
658 * @param data Reference to the data packet.
659 * @param signature Signature to be added.
Yingdi Yu8726f652014-01-23 10:35:12 -0800660 * @param keyName The name of the signing key.
661 * @param digestAlgorithm the digest algorithm.
662 * @throws Tpm::Error
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700663 */
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700664 inline void
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700665 signPacketWrapper(Data& data, const SignatureSha256WithRsa& signature,
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700666 const Name& keyName, DigestAlgorithm digestAlgorithm);
Yingdi Yu8726f652014-01-23 10:35:12 -0800667
Yingdi Yu2e57a582014-02-20 23:34:43 -0800668 /**
669 * @brief Sign the interest using a particular key.
670 *
671 * @param interest Reference to the interest packet.
672 * @param signature Signature to be added.
673 * @param keyName The name of the signing key.
674 * @param digestAlgorithm the digest algorithm.
675 * @throws Tpm::Error
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700676 */
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700677 inline void
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700678 signPacketWrapper(Interest& interest, const SignatureSha256WithRsa& signature,
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700679 const Name& keyName, DigestAlgorithm digestAlgorithm);
Yingdi Yu2e57a582014-02-20 23:34:43 -0800680
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700681
682private:
683 SecPublicInfo* m_pib;
684 SecTpm* m_tpm;
Yingdi Yu0f5fb692014-06-10 12:07:28 -0700685 time::milliseconds m_lastTimestamp;
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700686};
687
688template<class T>
689inline
690KeyChain::KeyChain(T)
691 : m_pib(new typename T::Pib)
692 , m_tpm(new typename T::Tpm)
Yingdi Yu0f5fb692014-06-10 12:07:28 -0700693 , m_lastTimestamp(time::toUnixTimestamp(time::system_clock::now()))
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700694{
695}
696
697inline Name
698KeyChain::createIdentity(const Name& identityName)
699{
700 m_pib->addIdentity(identityName);
701
702 Name keyName;
703 try
704 {
705 keyName = m_pib->getDefaultKeyNameForIdentity(identityName);
706 }
707 catch (SecPublicInfo::Error& e)
708 {
709 keyName = generateRsaKeyPairAsDefault(identityName, true);
710 }
711
712 Name certName;
713 try
714 {
715 certName = m_pib->getDefaultCertificateNameForKey(keyName);
716 }
717 catch (SecPublicInfo::Error& e)
718 {
719 shared_ptr<IdentityCertificate> selfCert = selfSign(keyName);
720 m_pib->addCertificateAsIdentityDefault(*selfCert);
721 certName = selfCert->getName();
722 }
723
724 return certName;
725}
726
727inline Name
728KeyChain::generateRsaKeyPair(const Name& identityName, bool isKsk, int keySize)
729{
730 return generateKeyPair(identityName, isKsk, KEY_TYPE_RSA, keySize);
731}
732
733inline Name
734KeyChain::generateRsaKeyPairAsDefault(const Name& identityName, bool isKsk, int keySize)
735{
736 Name keyName = generateKeyPair(identityName, isKsk, KEY_TYPE_RSA, keySize);
737
738 m_pib->setDefaultKeyNameForIdentity(keyName);
739
740 return keyName;
741}
742
743template<typename T>
744void
745KeyChain::sign(T& packet)
746{
747 if (!static_cast<bool>(m_pib->defaultCertificate()))
748 setDefaultCertificateInternal();
749
750 sign(packet, *m_pib->defaultCertificate());
751}
752
753template<typename T>
754void
755KeyChain::sign(T& packet, const Name& certificateName)
756{
757 if (!m_pib->doesCertificateExist(certificateName))
758 throw SecPublicInfo::Error("Requested certificate [" +
759 certificateName.toUri() + "] doesn't exist");
760
761 SignatureSha256WithRsa signature;
762 // implicit conversion should take care
763 signature.setKeyLocator(certificateName.getPrefix(-1));
764
765 // For temporary usage, we support RSA + SHA256 only, but will support more.
766 signPacketWrapper(packet, signature,
767 IdentityCertificate::certificateNameToPublicKeyName(certificateName),
768 DIGEST_ALGORITHM_SHA256);
769}
770
771template<typename T>
772void
773KeyChain::signByIdentity(T& packet, const Name& identityName)
774{
775 Name signingCertificateName;
776 try
777 {
778 signingCertificateName = m_pib->getDefaultCertificateNameForIdentity(identityName);
779 }
780 catch (SecPublicInfo::Error& e)
781 {
782 signingCertificateName = createIdentity(identityName);
783 // Ideally, no exception will be thrown out, unless something goes wrong in the TPM, which
784 // is a fatal error.
785 }
786
787 // We either get or create the signing certificate, sign packet! (no exception unless fatal
788 // error in TPM)
789 sign(packet, signingCertificateName);
790}
791
792inline Signature
793KeyChain::signByIdentity(const uint8_t* buffer, size_t bufferLength, const Name& identityName)
794{
795 Name signingCertificateName;
796 try
797 {
798 signingCertificateName = m_pib->getDefaultCertificateNameForIdentity(identityName);
799 }
800 catch (SecPublicInfo::Error& e)
801 {
802 signingCertificateName = createIdentity(identityName);
803 // Ideally, no exception will be thrown out, unless something goes wrong in the TPM, which
804 // is a fatal error.
805 }
806
807 // We either get or create the signing certificate, sign data! (no exception unless fatal error
808 // in TPM)
809 return sign(buffer, bufferLength, signingCertificateName);
810}
811
812inline void
813KeyChain::signWithSha256(Data& data)
814{
Yingdi Yubf6a2812014-06-17 15:32:11 -0700815 DigestSha256 sig;
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700816 data.setSignature(sig);
817
818 Block sigValue(Tlv::SignatureValue,
819 crypto::sha256(data.wireEncode().value(),
820 data.wireEncode().value_size() -
821 data.getSignature().getValue().size()));
822 data.setSignatureValue(sigValue);
823}
824
825inline void
826KeyChain::deleteCertificate(const Name& certificateName)
827{
828 try
829 {
830 if (m_pib->getDefaultCertificateName() == certificateName)
831 return;
832 }
833 catch (SecPublicInfo::Error& e)
834 {
835 // Not a real error, just try to delete the certificate
836 }
837
838 m_pib->deleteCertificateInfo(certificateName);
839}
840
841inline void
842KeyChain::deleteKey(const Name& keyName)
843{
844 try
845 {
846 if (m_pib->getDefaultKeyNameForIdentity(m_pib->getDefaultIdentity()) == keyName)
847 return;
848 }
849 catch (SecPublicInfo::Error& e)
850 {
851 // Not a real error, just try to delete the key
852 }
853
854 m_pib->deletePublicKeyInfo(keyName);
855 m_tpm->deleteKeyPairInTpm(keyName);
856}
857
858inline void
859KeyChain::deleteIdentity(const Name& identity)
860{
861 try
862 {
863 if (m_pib->getDefaultIdentity() == identity)
864 return;
865 }
866 catch (SecPublicInfo::Error& e)
867 {
868 // Not a real error, just try to delete the identity
869 }
870
871 std::vector<Name> nameList;
872 m_pib->getAllKeyNamesOfIdentity(identity, nameList, true);
873 m_pib->getAllKeyNamesOfIdentity(identity, nameList, false);
874
875 m_pib->deleteIdentityInfo(identity);
876
877 std::vector<Name>::const_iterator it = nameList.begin();
878 for(; it != nameList.end(); it++)
879 m_tpm->deleteKeyPairInTpm(*it);
880}
881
882template<typename T>
883void
884KeyChain::sign(T& packet, const IdentityCertificate& certificate)
885{
886 SignatureSha256WithRsa signature;
887 signature.setKeyLocator(certificate.getName().getPrefix(-1));
888
889 // For temporary usage, we support RSA + SHA256 only, but will support more.
890 signPacketWrapper(packet, signature, certificate.getPublicKeyName(), DIGEST_ALGORITHM_SHA256);
891}
892
893inline Name
894KeyChain::generateKeyPair(const Name& identityName, bool isKsk, KeyType keyType, int keySize)
895{
896 Name keyName = m_pib->getNewKeyName(identityName, isKsk);
897
898 m_tpm->generateKeyPairInTpm(keyName.toUri(), keyType, keySize);
899
900 shared_ptr<PublicKey> pubKey = m_tpm->getPublicKeyFromTpm(keyName.toUri());
901 m_pib->addPublicKey(keyName, keyType, *pubKey);
902
903 return keyName;
904}
905
906inline void
907KeyChain::signPacketWrapper(Data& data, const SignatureSha256WithRsa& signature,
908 const Name& keyName, DigestAlgorithm digestAlgorithm)
909{
910 data.setSignature(signature);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700911
912 EncodingBuffer encoder;
913 data.wireEncode(encoder, true);
914
915 Block signatureValue = m_tpm->signInTpm(encoder.buf(), encoder.size(),
916 keyName, digestAlgorithm);
917 data.wireEncode(encoder, signatureValue);
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700918}
919
920inline void
921KeyChain::signPacketWrapper(Interest& interest, const SignatureSha256WithRsa& signature,
922 const Name& keyName, DigestAlgorithm digestAlgorithm)
923{
Yingdi Yu0f5fb692014-06-10 12:07:28 -0700924 time::milliseconds timestamp = time::toUnixTimestamp(time::system_clock::now());
925 if (timestamp <= m_lastTimestamp)
926 {
927 timestamp = m_lastTimestamp + time::milliseconds(1);
928 }
929
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700930 Name signedName = interest.getName();
Yingdi Yu0f5fb692014-06-10 12:07:28 -0700931 signedName
932 .append(name::Component::fromNumber(timestamp.count())) // timestamp
933 .append(name::Component::fromNumber(random::generateWord64())) // nonce
934 .append(signature.getInfo()); // signatureInfo
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700935
936 Block sigValue = m_tpm->signInTpm(signedName.wireEncode().value(),
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700937 signedName.wireEncode().value_size(),
Yingdi Yu2e57a582014-02-20 23:34:43 -0800938 keyName,
Alexander Afanasyev24b75c82014-05-31 15:59:31 +0300939 digestAlgorithm);
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700940 sigValue.encode();
Yingdi Yu0f5fb692014-06-10 12:07:28 -0700941 signedName.append(sigValue); // signatureValue
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700942 interest.setName(signedName);
943}
Yingdi Yu2e57a582014-02-20 23:34:43 -0800944
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700945}
Jeff Thompson47c93cf2013-08-09 00:38:48 -0700946
Alexander Afanasyev766cea72014-04-24 19:16:42 -0700947#endif // NDN_SECURITY_KEY_CHAIN_HPP