blob: 043f43788321c6aa81c4c2763f88eb033dc42452 [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>
66 KeyChain(KeyChainTraits traits);
67
68 KeyChain(const std::string& pibName,
69 const std::string& tpmName);
70
71 virtual
72 ~KeyChain()
73 {
74 if (m_pib != 0)
75 delete m_pib;
76
77 if (m_tpm != 0)
78 delete m_tpm;
79 }
80
Yingdi Yube4150e2014-02-18 13:02:46 -080081 /**
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070082 * @brief Create an identity by creating a pair of Key-Signing-Key (KSK) for this identity and a
83 * self-signed certificate of the KSK.
Yingdi Yube4150e2014-02-18 13:02:46 -080084 *
Yingdi Yu2abd73f2014-01-08 23:34:11 -080085 * @param identityName The name of the identity.
Yingdi Yu28fd32f2014-01-28 19:03:03 -080086 * @return The name of the default certificate of the identity.
Yingdi Yu2abd73f2014-01-08 23:34:11 -080087 */
Yingdi Yuf56c68f2014-04-24 21:50:13 -070088 inline Name
89 createIdentity(const Name& identityName);
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -070090
Yingdi Yu2abd73f2014-01-08 23:34:11 -080091 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -080092 * @brief Generate a pair of RSA keys for the specified identity.
93 *
Yingdi Yu2abd73f2014-01-08 23:34:11 -080094 * @param identityName The name of the identity.
95 * @param isKsk true for generating a Key-Signing-Key (KSK), false for a Data-Signing-Key (KSK).
96 * @param keySize The size of the key.
97 * @return The generated key name.
98 */
Yingdi Yuf56c68f2014-04-24 21:50:13 -070099 inline Name
100 generateRsaKeyPair(const Name& identityName, bool isKsk = false, int keySize = 2048);
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700101
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800102 /**
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700103 * @brief Generate a pair of RSA keys for the specified identity and set it as default key for
104 * the identity.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800105 *
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800106 * @param identityName The name of the identity.
107 * @param isKsk true for generating a Key-Signing-Key (KSK), false for a Data-Signing-Key (KSK).
108 * @param keySize The size of the key.
109 * @return The generated key name.
110 */
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700111 inline Name
112 generateRsaKeyPairAsDefault(const Name& identityName, bool isKsk = false, int keySize = 2048);
Jeff Thompson79a2d5d2013-09-27 14:32:23 -0700113
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800114 /**
Yingdi Yuc55680b2014-02-26 12:31:35 -0800115 * @brief prepare an unsigned identity certificate
116 *
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700117 * @param keyName Key name, e.g., `/<identity_name>/ksk-123456`.
Yingdi Yuc55680b2014-02-26 12:31:35 -0800118 * @param signingIdentity The signing identity.
119 * @param notBefore Refer to IdentityCertificate.
120 * @param notAfter Refer to IdentityCertificate.
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700121 * @param subjectDescription Refer to IdentityCertificate.
Yingdi Yu0eb5d722014-06-10 15:06:25 -0700122 * @param certPrefix Prefix before `KEY` component. By default, KeyChain will infer the
123 * certificate name according to the relation between the signingIdentity and
124 * the subject identity. If signingIdentity is a prefix of the subject identity,
125 * `KEY` will be inserted after the signingIdentity, otherwise `KEY` is inserted
126 * after subject identity (i.e., before `ksk-....`).
Yingdi Yuc55680b2014-02-26 12:31:35 -0800127 * @return IdentityCertificate.
128 */
129 shared_ptr<IdentityCertificate>
130 prepareUnsignedIdentityCertificate(const Name& keyName,
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700131 const Name& signingIdentity,
132 const time::system_clock::TimePoint& notBefore,
133 const time::system_clock::TimePoint& notAfter,
Yingdi Yu0eb5d722014-06-10 15:06:25 -0700134 const std::vector<CertificateSubjectDescription>& subjectDescription,
135 const Name& certPrefix = DEFAULT_PREFIX);
136
137 /**
138 * @brief prepare an unsigned identity certificate
139 *
140 * @param keyName Key name, e.g., `/<identity_name>/ksk-123456`.
141 * @param publicKey Public key to sign.
142 * @param signingIdentity The signing identity.
143 * @param notBefore Refer to IdentityCertificate.
144 * @param notAfter Refer to IdentityCertificate.
145 * @param subjectDescription Refer to IdentityCertificate.
146 * @param certPrefix Prefix before `KEY` component. By default, KeyChain will infer the
147 * certificate name according to the relation between the signingIdentity and
148 * the subject identity. If signingIdentity is a prefix of the subject identity,
149 * `KEY` will be inserted after the signingIdentity, otherwise `KEY` is inserted
150 * after subject identity (i.e., before `ksk-....`).
151 * @return IdentityCertificate.
152 */
153 shared_ptr<IdentityCertificate>
154 prepareUnsignedIdentityCertificate(const Name& keyName,
155 const PublicKey& publicKey,
156 const Name& signingIdentity,
157 const time::system_clock::TimePoint& notBefore,
158 const time::system_clock::TimePoint& notAfter,
159 const std::vector<CertificateSubjectDescription>& subjectDescription,
160 const Name& certPrefix = DEFAULT_PREFIX);
Yingdi Yuc55680b2014-02-26 12:31:35 -0800161
162 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800163 * @brief Sign packet with default identity
164 *
Yingdi Yu60bd7082014-03-25 18:18:54 -0700165 * On return, signatureInfo and signatureValue in the packet are set.
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700166 * If default identity does not exist,
Yingdi Yu60bd7082014-03-25 18:18:54 -0700167 * a temporary identity will be created and set as default.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800168 *
169 * @param packet The packet to be signed
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800170 */
Yingdi Yu2e57a582014-02-20 23:34:43 -0800171 template<typename T>
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800172 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700173 sign(T& packet);
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700174
Jeff Thompson47c93cf2013-08-09 00:38:48 -0700175 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800176 * @brief Sign packet with a particular certificate.
177 *
178 * @param packet The packet to be signed.
179 * @param certificateName The certificate name of the key to use for signing.
180 * @throws SecPublicInfo::Error if certificate does not exist.
Jeff Thompson3c73da42013-08-12 11:19:05 -0700181 */
Yingdi Yu2e57a582014-02-20 23:34:43 -0800182 template<typename T>
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700183 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700184 sign(T& packet, const Name& certificateName);
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700185
Jeff Thompson29ce3102013-09-27 11:47:48 -0700186 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800187 * @brief Sign the byte array using a particular certificate.
188 *
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700189 * @param buffer The byte array to be signed.
190 * @param bufferLength the length of buffer.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800191 * @param certificateName The certificate name of the signing key.
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700192 * @return The Signature.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800193 * @throws SecPublicInfo::Error if certificate does not exist.
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700194 */
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800195 Signature
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700196 sign(const uint8_t* buffer, size_t bufferLength, const Name& certificateName);
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700197
198 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800199 * @brief Sign packet using the default certificate of a particular identity.
200 *
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700201 * If there is no default certificate of that identity, this method will create a self-signed
202 * certificate.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800203 *
204 * @param packet The packet to be signed.
205 * @param identityName The signing identity name.
Jeff Thompson29ce3102013-09-27 11:47:48 -0700206 */
Yingdi Yu2e57a582014-02-20 23:34:43 -0800207 template<typename T>
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700208 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700209 signByIdentity(T& packet, const Name& identityName);
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700210
Jeff Thompson3c73da42013-08-12 11:19:05 -0700211 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800212 * @brief Sign the byte array using the default certificate of a particular identity.
213 *
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700214 * @param buffer The byte array to be signed.
215 * @param bufferLength the length of buffer.
216 * @param identityName The identity name.
217 * @return The Signature.
218 */
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700219 inline Signature
220 signByIdentity(const uint8_t* buffer, size_t bufferLength, const Name& identityName);
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700221
222 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700223 * @brief Set Sha256 weak signature for @param data
Yingdi Yu21157162014-02-28 13:02:34 -0800224 */
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700225 inline void
226 signWithSha256(Data& data);
Yingdi Yu21157162014-02-28 13:02:34 -0800227
228 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800229 * @brief Generate a self-signed certificate for a public key.
230 *
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700231 * @param keyName The name of the public key
232 * @return The generated certificate, shared_ptr<IdentityCertificate>() if selfSign fails
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800233 */
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800234 shared_ptr<IdentityCertificate>
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700235 selfSign(const Name& keyName);
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800236
237 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800238 * @brief Self-sign the supplied identity certificate.
239 *
240 * @param cert The supplied cert.
241 * @throws SecTpm::Error if the private key does not exist.
Jeff Thompson8efe5ad2013-08-20 17:36:38 -0700242 */
Jeff Thompson2ce8f492013-09-17 18:01:25 -0700243 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700244 selfSign(IdentityCertificate& cert);
Yingdi Yu31b4af22014-01-14 14:13:00 -0800245
Yingdi Yu2e57a582014-02-20 23:34:43 -0800246 /**
247 * @brief delete a certificate.
248 *
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700249 * If the certificate to be deleted is current default system default,
Yingdi Yu2e57a582014-02-20 23:34:43 -0800250 * the method will not delete the certificate and return immediately.
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700251 *
Yingdi Yu2e57a582014-02-20 23:34:43 -0800252 * @param certificateName The certificate to be deleted.
253 */
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700254 inline void
255 deleteCertificate(const Name& certificateName);
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800256
Yingdi Yu2e57a582014-02-20 23:34:43 -0800257 /**
258 * @brief delete a key.
259 *
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700260 * If the key to be deleted is current default system default,
Yingdi Yu2e57a582014-02-20 23:34:43 -0800261 * the method will not delete the key and return immediately.
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700262 *
Yingdi Yu2e57a582014-02-20 23:34:43 -0800263 * @param keyName The key to be deleted.
264 */
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700265 inline void
266 deleteKey(const Name& keyName);
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800267
Yingdi Yu2e57a582014-02-20 23:34:43 -0800268 /**
269 * @brief delete an identity.
270 *
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700271 * If the identity to be deleted is current default system default,
Yingdi Yu2e57a582014-02-20 23:34:43 -0800272 * the method will not delete the identity and return immediately.
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700273 *
Yingdi Yu2e57a582014-02-20 23:34:43 -0800274 * @param identity The identity to be deleted.
275 */
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700276 inline void
277 deleteIdentity(const Name& identity);
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800278
Yingdi Yu2e57a582014-02-20 23:34:43 -0800279 /**
280 * @brief export an identity.
281 *
282 * @param identity The identity to export.
283 * @param passwordStr The password to secure the private key.
Yingdi Yu64c3fb42014-02-26 17:30:04 -0800284 * @return The encoded export data.
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700285 * @throws SecPublicInfo::Error if anything goes wrong in exporting.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800286 */
Yingdi Yu64c3fb42014-02-26 17:30:04 -0800287 shared_ptr<SecuredBag>
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700288 exportIdentity(const Name& identity, const std::string& passwordStr);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800289
Yingdi Yu2e57a582014-02-20 23:34:43 -0800290 /**
291 * @brief import an identity.
292 *
Yingdi Yu64c3fb42014-02-26 17:30:04 -0800293 * @param securedBag The encoded import data.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800294 * @param passwordStr The password to secure the private key.
295 */
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800296 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700297 importIdentity(const SecuredBag& securedBag, const std::string& passwordStr);
298
299 SecPublicInfo&
300 getPib()
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800301 {
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700302 return *m_pib;
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800303 }
304
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700305 const SecPublicInfo&
306 getPib() const
307 {
308 return *m_pib;
309 }
310
311 SecTpm&
312 getTpm()
313 {
314 return *m_tpm;
315 }
316
317 const SecTpm&
318 getTpm() const
319 {
320 return *m_tpm;
321 }
322
323 /*******************************
324 * Wrapper of SecPublicInfo *
325 *******************************/
326 bool
327 doesIdentityExist(const Name& identityName) const
328 {
329 return m_pib->doesIdentityExist(identityName);
330 }
331
332 void
333 addIdentity(const Name& identityName)
334 {
335 return m_pib->addIdentity(identityName);
336 }
337
338 bool
339 doesPublicKeyExist(const Name& keyName) const
340 {
341 return m_pib->doesPublicKeyExist(keyName);
342 }
343
344 void
345 addPublicKey(const Name& keyName, KeyType keyType, const PublicKey& publicKeyDer)
346 {
347 return m_pib->addPublicKey(keyName, keyType, publicKeyDer);
348 }
349
350 shared_ptr<PublicKey>
351 getPublicKey(const Name& keyName) const
352 {
353 return m_pib->getPublicKey(keyName);
354 }
355
356 bool
357 doesCertificateExist(const Name& certificateName) const
358 {
359 return m_pib->doesCertificateExist(certificateName);
360 }
361
362 void
363 addCertificate(const IdentityCertificate& certificate)
364 {
365 return m_pib->addCertificate(certificate);
366 }
367
368 shared_ptr<IdentityCertificate>
369 getCertificate(const Name& certificateName) const
370 {
371 return m_pib->getCertificate(certificateName);
372 }
373
374 Name
375 getDefaultIdentity() const
376 {
377 return m_pib->getDefaultIdentity();
378 }
379
380 Name
381 getDefaultKeyNameForIdentity(const Name& identityName) const
382 {
383 return m_pib->getDefaultKeyNameForIdentity(identityName);
384 }
385
386 Name
387 getDefaultCertificateNameForKey(const Name& keyName) const
388 {
389 return m_pib->getDefaultCertificateNameForKey(keyName);
390 }
391
392 void
393 getAllIdentities(std::vector<Name>& nameList, bool isDefault) const
394 {
395 return m_pib->getAllIdentities(nameList, isDefault);
396 }
397
398 void
399 getAllKeyNames(std::vector<Name>& nameList, bool isDefault) const
400 {
401 return m_pib->getAllKeyNames(nameList, isDefault);
402 }
403
404 void
405 getAllKeyNamesOfIdentity(const Name& identity, std::vector<Name>& nameList, bool isDefault) const
406 {
407 return m_pib->getAllKeyNamesOfIdentity(identity, nameList, isDefault);
408 }
409
410 void
411 getAllCertificateNames(std::vector<Name>& nameList, bool isDefault) const
412 {
413 return m_pib->getAllCertificateNames(nameList, isDefault);
414 }
415
416 void
417 getAllCertificateNamesOfKey(const Name& keyName,
418 std::vector<Name>& nameList,
419 bool isDefault) const
420 {
421 return m_pib->getAllCertificateNamesOfKey(keyName, nameList, isDefault);
422 }
423
424 void
425 deleteCertificateInfo(const Name& certificateName)
426 {
427 return m_pib->deleteCertificateInfo(certificateName);
428 }
429
430 void
431 deletePublicKeyInfo(const Name& keyName)
432 {
433 return m_pib->deletePublicKeyInfo(keyName);
434 }
435
436 void
437 deleteIdentityInfo(const Name& identity)
438 {
439 return m_pib->deleteIdentityInfo(identity);
440 }
441
442 void
443 setDefaultIdentity(const Name& identityName)
444 {
445 return m_pib->setDefaultIdentity(identityName);
446 }
447
448 void
449 setDefaultKeyNameForIdentity(const Name& keyName)
450 {
451 return m_pib->setDefaultKeyNameForIdentity(keyName);
452 }
453
454 void
455 setDefaultCertificateNameForKey(const Name& certificateName)
456 {
457 return m_pib->setDefaultCertificateNameForKey(certificateName);
458 }
459
460 Name
461 getNewKeyName(const Name& identityName, bool useKsk)
462 {
463 return m_pib->getNewKeyName(identityName, useKsk);
464 }
465
466 Name
467 getDefaultCertificateNameForIdentity(const Name& identityName) const
468 {
469 return m_pib->getDefaultCertificateNameForIdentity(identityName);
470 }
471
472 Name
473 getDefaultCertificateName() const
474 {
475 return m_pib->getDefaultCertificateName();
476 }
477
478 void
479 addCertificateAsKeyDefault(const IdentityCertificate& certificate)
480 {
481 return m_pib->addCertificateAsKeyDefault(certificate);
482 }
483
484 void
485 addCertificateAsIdentityDefault(const IdentityCertificate& certificate)
486 {
487 return m_pib->addCertificateAsIdentityDefault(certificate);
488 }
489
490 void
491 addCertificateAsSystemDefault(const IdentityCertificate& certificate)
492 {
493 return m_pib->addCertificateAsSystemDefault(certificate);
494 }
495
496 shared_ptr<IdentityCertificate>
497 getDefaultCertificate() const
498 {
499 return m_pib->defaultCertificate();
500 }
501
502 void
503 refreshDefaultCertificate()
504 {
505 return m_pib->refreshDefaultCertificate();
506 }
507
508 /*******************************
509 * Wrapper of SecTpm *
510 *******************************/
511
512 void
513 setTpmPassword(const uint8_t* password, size_t passwordLength)
514 {
515 return m_tpm->setTpmPassword(password, passwordLength);
516 }
517
518 void
519 resetTpmPassword()
520 {
521 return m_tpm->resetTpmPassword();
522 }
523
524 void
525 setInTerminal(bool inTerminal)
526 {
527 return m_tpm->setInTerminal(inTerminal);
528 }
529
530 bool
531 getInTerminal() const
532 {
533 return m_tpm->getInTerminal();
534 }
535
536 bool
537 isLocked() const
538 {
539 return m_tpm->isLocked();
540 }
541
542 bool
543 unlockTpm(const char* password, size_t passwordLength, bool usePassword)
544 {
545 return m_tpm->unlockTpm(password, passwordLength, usePassword);
546 }
547
548 void
549 generateKeyPairInTpm(const Name& keyName, KeyType keyType, int keySize)
550 {
551 return m_tpm->generateKeyPairInTpm(keyName, keyType, keySize);
552 }
553
554 void
555 deleteKeyPairInTpm(const Name& keyName)
556 {
557 return m_tpm->deleteKeyPairInTpm(keyName);
558 }
559
560 shared_ptr<PublicKey>
561 getPublicKeyFromTpm(const Name& keyName) const
562 {
563 return m_tpm->getPublicKeyFromTpm(keyName);
564 }
565
566 Block
567 signInTpm(const uint8_t* data, size_t dataLength,
568 const Name& keyName,
569 DigestAlgorithm digestAlgorithm)
570 {
571 return m_tpm->signInTpm(data, dataLength, keyName, digestAlgorithm);
572 }
573
574 ConstBufferPtr
575 decryptInTpm(const uint8_t* data, size_t dataLength, const Name& keyName, bool isSymmetric)
576 {
577 return m_tpm->decryptInTpm(data, dataLength, keyName, isSymmetric);
578 }
579
580 ConstBufferPtr
581 encryptInTpm(const uint8_t* data, size_t dataLength, const Name& keyName, bool isSymmetric)
582 {
583 return m_tpm->encryptInTpm(data, dataLength, keyName, isSymmetric);
584 }
585
586 void
587 generateSymmetricKeyInTpm(const Name& keyName, KeyType keyType, int keySize)
588 {
589 return m_tpm->generateSymmetricKeyInTpm(keyName, keyType, keySize);
590 }
591
592 bool
593 doesKeyExistInTpm(const Name& keyName, KeyClass keyClass) const
594 {
595 return m_tpm->doesKeyExistInTpm(keyName, keyClass);
596 }
597
598 bool
599 generateRandomBlock(uint8_t* res, size_t size) const
600 {
601 return m_tpm->generateRandomBlock(res, size);
602 }
603
604 void
605 addAppToAcl(const Name& keyName, KeyClass keyClass, const std::string& appPath, AclType acl)
606 {
607 return m_tpm->addAppToAcl(keyName, keyClass, appPath, acl);
608 }
609
610 ConstBufferPtr
611 exportPrivateKeyPkcs5FromTpm(const Name& keyName, const std::string& password)
612 {
613 return m_tpm->exportPrivateKeyPkcs5FromTpm(keyName, password);
614 }
615
616 bool
617 importPrivateKeyPkcs5IntoTpm(const Name& keyName,
618 const uint8_t* buf, size_t size,
619 const std::string& password)
620 {
621 return m_tpm->importPrivateKeyPkcs5IntoTpm(keyName, buf, size, password);
622 }
Jeff Thompson8efe5ad2013-08-20 17:36:38 -0700623
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800624private:
Yingdi Yu2e57a582014-02-20 23:34:43 -0800625 /**
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700626 * @brief Set default certificate if it is not initialized
627 */
628 void
629 setDefaultCertificateInternal();
630
631 /**
632 * @brief Sign a packet using a pariticular certificate.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800633 *
634 * @param packet The packet to be signed.
635 * @param certificate The signing certificate.
636 */
637 template<typename T>
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800638 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700639 sign(T& packet, const IdentityCertificate& certificate);
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800640
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800641 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800642 * @brief Generate a key pair for the specified identity.
643 *
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800644 * @param identityName The name of the specified identity.
645 * @param isKsk true for generating a Key-Signing-Key (KSK), false for a Data-Signing-Key (KSK).
646 * @param keyType The type of the key pair, e.g. KEY_TYPE_RSA.
647 * @param keySize The size of the key pair.
648 * @return The name of the generated key.
649 */
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700650 inline Name
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700651 generateKeyPair(const Name& identityName, bool isKsk = false,
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700652 KeyType keyType = KEY_TYPE_RSA, int keySize = 2048);
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800653
Yingdi Yu8726f652014-01-23 10:35:12 -0800654 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800655 * @brief Sign the data using a particular key.
656 *
657 * @param data Reference to the data packet.
658 * @param signature Signature to be added.
Yingdi Yu8726f652014-01-23 10:35:12 -0800659 * @param keyName The name of the signing key.
660 * @param digestAlgorithm the digest algorithm.
661 * @throws Tpm::Error
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700662 */
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700663 inline void
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700664 signPacketWrapper(Data& data, const SignatureSha256WithRsa& signature,
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700665 const Name& keyName, DigestAlgorithm digestAlgorithm);
Yingdi Yu8726f652014-01-23 10:35:12 -0800666
Yingdi Yu2e57a582014-02-20 23:34:43 -0800667 /**
668 * @brief Sign the interest using a particular key.
669 *
670 * @param interest Reference to the interest packet.
671 * @param signature Signature to be added.
672 * @param keyName The name of the signing key.
673 * @param digestAlgorithm the digest algorithm.
674 * @throws Tpm::Error
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700675 */
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700676 inline void
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700677 signPacketWrapper(Interest& interest, const SignatureSha256WithRsa& signature,
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700678 const Name& keyName, DigestAlgorithm digestAlgorithm);
Yingdi Yu2e57a582014-02-20 23:34:43 -0800679
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700680
681private:
682 SecPublicInfo* m_pib;
683 SecTpm* m_tpm;
Yingdi Yu0f5fb692014-06-10 12:07:28 -0700684 time::milliseconds m_lastTimestamp;
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700685};
686
687template<class T>
688inline
689KeyChain::KeyChain(T)
690 : m_pib(new typename T::Pib)
691 , m_tpm(new typename T::Tpm)
Yingdi Yu0f5fb692014-06-10 12:07:28 -0700692 , m_lastTimestamp(time::toUnixTimestamp(time::system_clock::now()))
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700693{
694}
695
696inline Name
697KeyChain::createIdentity(const Name& identityName)
698{
699 m_pib->addIdentity(identityName);
700
701 Name keyName;
702 try
703 {
704 keyName = m_pib->getDefaultKeyNameForIdentity(identityName);
705 }
706 catch (SecPublicInfo::Error& e)
707 {
708 keyName = generateRsaKeyPairAsDefault(identityName, true);
709 }
710
711 Name certName;
712 try
713 {
714 certName = m_pib->getDefaultCertificateNameForKey(keyName);
715 }
716 catch (SecPublicInfo::Error& e)
717 {
718 shared_ptr<IdentityCertificate> selfCert = selfSign(keyName);
719 m_pib->addCertificateAsIdentityDefault(*selfCert);
720 certName = selfCert->getName();
721 }
722
723 return certName;
724}
725
726inline Name
727KeyChain::generateRsaKeyPair(const Name& identityName, bool isKsk, int keySize)
728{
729 return generateKeyPair(identityName, isKsk, KEY_TYPE_RSA, keySize);
730}
731
732inline Name
733KeyChain::generateRsaKeyPairAsDefault(const Name& identityName, bool isKsk, int keySize)
734{
735 Name keyName = generateKeyPair(identityName, isKsk, KEY_TYPE_RSA, keySize);
736
737 m_pib->setDefaultKeyNameForIdentity(keyName);
738
739 return keyName;
740}
741
742template<typename T>
743void
744KeyChain::sign(T& packet)
745{
746 if (!static_cast<bool>(m_pib->defaultCertificate()))
747 setDefaultCertificateInternal();
748
749 sign(packet, *m_pib->defaultCertificate());
750}
751
752template<typename T>
753void
754KeyChain::sign(T& packet, const Name& certificateName)
755{
756 if (!m_pib->doesCertificateExist(certificateName))
757 throw SecPublicInfo::Error("Requested certificate [" +
758 certificateName.toUri() + "] doesn't exist");
759
760 SignatureSha256WithRsa signature;
761 // implicit conversion should take care
762 signature.setKeyLocator(certificateName.getPrefix(-1));
763
764 // For temporary usage, we support RSA + SHA256 only, but will support more.
765 signPacketWrapper(packet, signature,
766 IdentityCertificate::certificateNameToPublicKeyName(certificateName),
767 DIGEST_ALGORITHM_SHA256);
768}
769
770template<typename T>
771void
772KeyChain::signByIdentity(T& packet, const Name& identityName)
773{
774 Name signingCertificateName;
775 try
776 {
777 signingCertificateName = m_pib->getDefaultCertificateNameForIdentity(identityName);
778 }
779 catch (SecPublicInfo::Error& e)
780 {
781 signingCertificateName = createIdentity(identityName);
782 // Ideally, no exception will be thrown out, unless something goes wrong in the TPM, which
783 // is a fatal error.
784 }
785
786 // We either get or create the signing certificate, sign packet! (no exception unless fatal
787 // error in TPM)
788 sign(packet, signingCertificateName);
789}
790
791inline Signature
792KeyChain::signByIdentity(const uint8_t* buffer, size_t bufferLength, const Name& identityName)
793{
794 Name signingCertificateName;
795 try
796 {
797 signingCertificateName = m_pib->getDefaultCertificateNameForIdentity(identityName);
798 }
799 catch (SecPublicInfo::Error& e)
800 {
801 signingCertificateName = createIdentity(identityName);
802 // Ideally, no exception will be thrown out, unless something goes wrong in the TPM, which
803 // is a fatal error.
804 }
805
806 // We either get or create the signing certificate, sign data! (no exception unless fatal error
807 // in TPM)
808 return sign(buffer, bufferLength, signingCertificateName);
809}
810
811inline void
812KeyChain::signWithSha256(Data& data)
813{
Yingdi Yubf6a2812014-06-17 15:32:11 -0700814 DigestSha256 sig;
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700815 data.setSignature(sig);
816
817 Block sigValue(Tlv::SignatureValue,
818 crypto::sha256(data.wireEncode().value(),
819 data.wireEncode().value_size() -
820 data.getSignature().getValue().size()));
821 data.setSignatureValue(sigValue);
822}
823
824inline void
825KeyChain::deleteCertificate(const Name& certificateName)
826{
827 try
828 {
829 if (m_pib->getDefaultCertificateName() == certificateName)
830 return;
831 }
832 catch (SecPublicInfo::Error& e)
833 {
834 // Not a real error, just try to delete the certificate
835 }
836
837 m_pib->deleteCertificateInfo(certificateName);
838}
839
840inline void
841KeyChain::deleteKey(const Name& keyName)
842{
843 try
844 {
845 if (m_pib->getDefaultKeyNameForIdentity(m_pib->getDefaultIdentity()) == keyName)
846 return;
847 }
848 catch (SecPublicInfo::Error& e)
849 {
850 // Not a real error, just try to delete the key
851 }
852
853 m_pib->deletePublicKeyInfo(keyName);
854 m_tpm->deleteKeyPairInTpm(keyName);
855}
856
857inline void
858KeyChain::deleteIdentity(const Name& identity)
859{
860 try
861 {
862 if (m_pib->getDefaultIdentity() == identity)
863 return;
864 }
865 catch (SecPublicInfo::Error& e)
866 {
867 // Not a real error, just try to delete the identity
868 }
869
870 std::vector<Name> nameList;
871 m_pib->getAllKeyNamesOfIdentity(identity, nameList, true);
872 m_pib->getAllKeyNamesOfIdentity(identity, nameList, false);
873
874 m_pib->deleteIdentityInfo(identity);
875
876 std::vector<Name>::const_iterator it = nameList.begin();
877 for(; it != nameList.end(); it++)
878 m_tpm->deleteKeyPairInTpm(*it);
879}
880
881template<typename T>
882void
883KeyChain::sign(T& packet, const IdentityCertificate& certificate)
884{
885 SignatureSha256WithRsa signature;
886 signature.setKeyLocator(certificate.getName().getPrefix(-1));
887
888 // For temporary usage, we support RSA + SHA256 only, but will support more.
889 signPacketWrapper(packet, signature, certificate.getPublicKeyName(), DIGEST_ALGORITHM_SHA256);
890}
891
892inline Name
893KeyChain::generateKeyPair(const Name& identityName, bool isKsk, KeyType keyType, int keySize)
894{
895 Name keyName = m_pib->getNewKeyName(identityName, isKsk);
896
897 m_tpm->generateKeyPairInTpm(keyName.toUri(), keyType, keySize);
898
899 shared_ptr<PublicKey> pubKey = m_tpm->getPublicKeyFromTpm(keyName.toUri());
900 m_pib->addPublicKey(keyName, keyType, *pubKey);
901
902 return keyName;
903}
904
905inline void
906KeyChain::signPacketWrapper(Data& data, const SignatureSha256WithRsa& signature,
907 const Name& keyName, DigestAlgorithm digestAlgorithm)
908{
909 data.setSignature(signature);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700910
911 EncodingBuffer encoder;
912 data.wireEncode(encoder, true);
913
914 Block signatureValue = m_tpm->signInTpm(encoder.buf(), encoder.size(),
915 keyName, digestAlgorithm);
916 data.wireEncode(encoder, signatureValue);
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700917}
918
919inline void
920KeyChain::signPacketWrapper(Interest& interest, const SignatureSha256WithRsa& signature,
921 const Name& keyName, DigestAlgorithm digestAlgorithm)
922{
Yingdi Yu0f5fb692014-06-10 12:07:28 -0700923 time::milliseconds timestamp = time::toUnixTimestamp(time::system_clock::now());
924 if (timestamp <= m_lastTimestamp)
925 {
926 timestamp = m_lastTimestamp + time::milliseconds(1);
927 }
928
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700929 Name signedName = interest.getName();
Yingdi Yu0f5fb692014-06-10 12:07:28 -0700930 signedName
931 .append(name::Component::fromNumber(timestamp.count())) // timestamp
932 .append(name::Component::fromNumber(random::generateWord64())) // nonce
933 .append(signature.getInfo()); // signatureInfo
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700934
935 Block sigValue = m_tpm->signInTpm(signedName.wireEncode().value(),
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700936 signedName.wireEncode().value_size(),
Yingdi Yu2e57a582014-02-20 23:34:43 -0800937 keyName,
Alexander Afanasyev24b75c82014-05-31 15:59:31 +0300938 digestAlgorithm);
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700939 sigValue.encode();
Yingdi Yu0f5fb692014-06-10 12:07:28 -0700940 signedName.append(sigValue); // signatureValue
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700941 interest.setName(signedName);
942}
Yingdi Yu2e57a582014-02-20 23:34:43 -0800943
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700944}
Jeff Thompson47c93cf2013-08-09 00:38:48 -0700945
Alexander Afanasyev766cea72014-04-24 19:16:42 -0700946#endif // NDN_SECURITY_KEY_CHAIN_HPP