blob: cc45dc383bda34bc894603149bdceac4b4e63e8b [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"
Yingdi Yu7036ce22014-06-19 18:53:37 -070029#include "key-params.hpp"
Yingdi Yuf56c68f2014-04-24 21:50:13 -070030#include "secured-bag.hpp"
Yingdi Yu4f324632014-01-15 18:10:03 -080031#include "signature-sha256-with-rsa.hpp"
Yingdi Yuc8f883c2014-06-20 23:25:22 -070032#include "signature-sha256-with-ecdsa.hpp"
Yingdi Yubf6a2812014-06-17 15:32:11 -070033#include "digest-sha256.hpp"
Yingdi Yuf56c68f2014-04-24 21:50:13 -070034
Yingdi Yu4270f202014-01-28 14:19:16 -080035#include "../interest.hpp"
Yingdi Yu21157162014-02-28 13:02:34 -080036#include "../util/crypto.hpp"
Yingdi Yu0f5fb692014-06-10 12:07:28 -070037#include "../util/random.hpp"
Alexander Afanasyev07113802015-01-15 19:14:36 -080038#include <initializer_list>
Yingdi Yu31b4af22014-01-14 14:13:00 -080039
Jeff Thompson47c93cf2013-08-09 00:38:48 -070040
41namespace ndn {
42
Alexander Afanasyev45a37132014-04-28 16:54:57 -070043class KeyChain : noncopyable
Yingdi Yuf56c68f2014-04-24 21:50:13 -070044{
45public:
46 class Error : public std::runtime_error
47 {
48 public:
49 explicit
50 Error(const std::string& what)
51 : std::runtime_error(what)
52 {
53 }
54 };
55
Yingdi Yu41546342014-11-30 23:37:53 -080056 /**
57 * This error is thrown when the TPM locator retrieved from PIB is
58 * different from what is supplied to the KeyChain constructor.
59 */
60 class MismatchError : public Error
61 {
62 public:
63 explicit
64 MismatchError(const std::string& what)
65 : Error(what)
66 {
67 }
68 };
Yingdi Yu7036ce22014-06-19 18:53:37 -070069
Alexander Afanasyev07113802015-01-15 19:14:36 -080070 typedef function<unique_ptr<SecPublicInfo> (const std::string&)> PibCreateFunc;
71 typedef function<unique_ptr<SecTpm>(const std::string&)> TpmCreateFunc;
Yingdi Yuf56c68f2014-04-24 21:50:13 -070072
Alexander Afanasyev07113802015-01-15 19:14:36 -080073 /**
74 * @brief Register a new PIB
75 * @param schemes List of scheme with which this PIB will be associated
76 */
77 template<class PibType>
78 static void
79 registerPib(std::initializer_list<std::string> schemes);
80
81 /**
82 * @brief Register a new TPM
83 * @param schemes List of scheme with which this TPM will be associated
84 */
85 template<class TpmType>
86 static void
87 registerTpm(std::initializer_list<std::string> schemes);
88
89 /**
90 * @brief Constructor to create KeyChain with default PIB and TPM
91 *
92 * Default PIB and TPM are platform-dependent and can be overriden system-wide or on
93 * per-use basis.
94 *
95 * @todo Add detailed description about config file behavior here
96 */
97 KeyChain();
Yingdi Yuf56c68f2014-04-24 21:50:13 -070098
Yingdi Yu41546342014-11-30 23:37:53 -080099 /**
100 * @brief KeyChain constructor
101 *
102 * @sa http://redmine.named-data.net/issues/2260
103 *
104 * @param pibLocator
105 * @param tpmLocator
106 * @param allowReset if true, the PIB will be reset when the supplied tpmLocator
107 * mismatches the one in PIB
108 */
109 KeyChain(const std::string& pibLocator,
110 const std::string& tpmLocator,
111 bool allowReset = false);
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700112
113 virtual
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700114 ~KeyChain();
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700115
Yingdi Yube4150e2014-02-18 13:02:46 -0800116 /**
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700117 * @brief Create an identity by creating a pair of Key-Signing-Key (KSK) for this identity and a
118 * self-signed certificate of the KSK.
Yingdi Yube4150e2014-02-18 13:02:46 -0800119 *
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800120 * @param identityName The name of the identity.
Yingdi Yu7036ce22014-06-19 18:53:37 -0700121 * @param params The key parameter if a key needs to be generated for the identity.
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800122 * @return The name of the default certificate of the identity.
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800123 */
Yingdi Yu7036ce22014-06-19 18:53:37 -0700124 Name
125 createIdentity(const Name& identityName, const KeyParams& params = DEFAULT_KEY_PARAMS);
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700126
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800127 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800128 * @brief Generate a pair of RSA keys for the specified identity.
129 *
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800130 * @param identityName The name of the identity.
131 * @param isKsk true for generating a Key-Signing-Key (KSK), false for a Data-Signing-Key (KSK).
132 * @param keySize The size of the key.
133 * @return The generated key name.
134 */
Yingdi Yu41546342014-11-30 23:37:53 -0800135 Name
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700136 generateRsaKeyPair(const Name& identityName, bool isKsk = false, uint32_t keySize = 2048);
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700137
Yingdi Yu41546342014-11-30 23:37:53 -0800138 Name
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700139 generateEcdsaKeyPair(const Name& identityName, bool isKsk = false, uint32_t keySize = 256);
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800140 /**
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700141 * @brief Generate a pair of RSA keys for the specified identity and set it as default key for
142 * the identity.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800143 *
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800144 * @param identityName The name of the identity.
145 * @param isKsk true for generating a Key-Signing-Key (KSK), false for a Data-Signing-Key (KSK).
146 * @param keySize The size of the key.
147 * @return The generated key name.
148 */
Yingdi Yu7036ce22014-06-19 18:53:37 -0700149 Name
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700150 generateRsaKeyPairAsDefault(const Name& identityName, bool isKsk = false,
151 uint32_t keySize = 2048);
152
153 Name
154 generateEcdsaKeyPairAsDefault(const Name& identityName, bool isKsk, uint32_t keySize = 256);
Jeff Thompson79a2d5d2013-09-27 14:32:23 -0700155
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800156 /**
Yingdi Yuc55680b2014-02-26 12:31:35 -0800157 * @brief prepare an unsigned identity certificate
158 *
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700159 * @param keyName Key name, e.g., `/<identity_name>/ksk-123456`.
Yingdi Yuc55680b2014-02-26 12:31:35 -0800160 * @param signingIdentity The signing identity.
161 * @param notBefore Refer to IdentityCertificate.
162 * @param notAfter Refer to IdentityCertificate.
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700163 * @param subjectDescription Refer to IdentityCertificate.
Yingdi Yu0eb5d722014-06-10 15:06:25 -0700164 * @param certPrefix Prefix before `KEY` component. By default, KeyChain will infer the
165 * certificate name according to the relation between the signingIdentity and
166 * the subject identity. If signingIdentity is a prefix of the subject identity,
167 * `KEY` will be inserted after the signingIdentity, otherwise `KEY` is inserted
168 * after subject identity (i.e., before `ksk-....`).
Yingdi Yuc55680b2014-02-26 12:31:35 -0800169 * @return IdentityCertificate.
170 */
171 shared_ptr<IdentityCertificate>
172 prepareUnsignedIdentityCertificate(const Name& keyName,
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700173 const Name& signingIdentity,
174 const time::system_clock::TimePoint& notBefore,
175 const time::system_clock::TimePoint& notAfter,
Yingdi Yu0eb5d722014-06-10 15:06:25 -0700176 const std::vector<CertificateSubjectDescription>& subjectDescription,
177 const Name& certPrefix = DEFAULT_PREFIX);
178
179 /**
180 * @brief prepare an unsigned identity certificate
181 *
182 * @param keyName Key name, e.g., `/<identity_name>/ksk-123456`.
183 * @param publicKey Public key to sign.
184 * @param signingIdentity The signing identity.
185 * @param notBefore Refer to IdentityCertificate.
186 * @param notAfter Refer to IdentityCertificate.
187 * @param subjectDescription Refer to IdentityCertificate.
188 * @param certPrefix Prefix before `KEY` component. By default, KeyChain will infer the
189 * certificate name according to the relation between the signingIdentity and
190 * the subject identity. If signingIdentity is a prefix of the subject identity,
191 * `KEY` will be inserted after the signingIdentity, otherwise `KEY` is inserted
192 * after subject identity (i.e., before `ksk-....`).
193 * @return IdentityCertificate.
194 */
195 shared_ptr<IdentityCertificate>
196 prepareUnsignedIdentityCertificate(const Name& keyName,
197 const PublicKey& publicKey,
198 const Name& signingIdentity,
199 const time::system_clock::TimePoint& notBefore,
200 const time::system_clock::TimePoint& notAfter,
201 const std::vector<CertificateSubjectDescription>& subjectDescription,
202 const Name& certPrefix = DEFAULT_PREFIX);
Yingdi Yuc55680b2014-02-26 12:31:35 -0800203
204 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800205 * @brief Sign packet with default identity
206 *
Yingdi Yu60bd7082014-03-25 18:18:54 -0700207 * On return, signatureInfo and signatureValue in the packet are set.
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700208 * If default identity does not exist,
Yingdi Yu60bd7082014-03-25 18:18:54 -0700209 * a temporary identity will be created and set as default.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800210 *
211 * @param packet The packet to be signed
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800212 */
Yingdi Yu2e57a582014-02-20 23:34:43 -0800213 template<typename T>
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800214 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700215 sign(T& packet);
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700216
Jeff Thompson47c93cf2013-08-09 00:38:48 -0700217 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800218 * @brief Sign packet with a particular certificate.
219 *
220 * @param packet The packet to be signed.
221 * @param certificateName The certificate name of the key to use for signing.
222 * @throws SecPublicInfo::Error if certificate does not exist.
Jeff Thompson3c73da42013-08-12 11:19:05 -0700223 */
Yingdi Yu2e57a582014-02-20 23:34:43 -0800224 template<typename T>
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700225 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700226 sign(T& packet, const Name& certificateName);
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700227
Jeff Thompson29ce3102013-09-27 11:47:48 -0700228 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800229 * @brief Sign the byte array using a particular certificate.
230 *
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700231 * @param buffer The byte array to be signed.
232 * @param bufferLength the length of buffer.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800233 * @param certificateName The certificate name of the signing key.
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700234 * @return The Signature.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800235 * @throws SecPublicInfo::Error if certificate does not exist.
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700236 */
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800237 Signature
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700238 sign(const uint8_t* buffer, size_t bufferLength, const Name& certificateName);
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700239
240 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800241 * @brief Sign packet using the default certificate of a particular identity.
242 *
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700243 * If there is no default certificate of that identity, this method will create a self-signed
244 * certificate.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800245 *
246 * @param packet The packet to be signed.
247 * @param identityName The signing identity name.
Jeff Thompson29ce3102013-09-27 11:47:48 -0700248 */
Yingdi Yu2e57a582014-02-20 23:34:43 -0800249 template<typename T>
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700250 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700251 signByIdentity(T& packet, const Name& identityName);
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700252
Jeff Thompson3c73da42013-08-12 11:19:05 -0700253 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800254 * @brief Sign the byte array using the default certificate of a particular identity.
255 *
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700256 * @param buffer The byte array to be signed.
257 * @param bufferLength the length of buffer.
258 * @param identityName The identity name.
259 * @return The Signature.
260 */
Yingdi Yu7036ce22014-06-19 18:53:37 -0700261 Signature
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700262 signByIdentity(const uint8_t* buffer, size_t bufferLength, const Name& identityName);
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700263
264 /**
Yingdi Yu6ab67812014-11-27 15:00:34 -0800265 * @brief Set Sha256 weak signature for @p data
Yingdi Yu21157162014-02-28 13:02:34 -0800266 */
Yingdi Yu7036ce22014-06-19 18:53:37 -0700267 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700268 signWithSha256(Data& data);
Yingdi Yu21157162014-02-28 13:02:34 -0800269
270 /**
Yingdi Yu6ab67812014-11-27 15:00:34 -0800271 * @brief Set Sha256 weak signature for @p interest
272 */
273 void
274 signWithSha256(Interest& interest);
275
276 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800277 * @brief Generate a self-signed certificate for a public key.
278 *
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700279 * @param keyName The name of the public key
280 * @return The generated certificate, shared_ptr<IdentityCertificate>() if selfSign fails
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800281 */
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800282 shared_ptr<IdentityCertificate>
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700283 selfSign(const Name& keyName);
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800284
285 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800286 * @brief Self-sign the supplied identity certificate.
287 *
288 * @param cert The supplied cert.
289 * @throws SecTpm::Error if the private key does not exist.
Jeff Thompson8efe5ad2013-08-20 17:36:38 -0700290 */
Jeff Thompson2ce8f492013-09-17 18:01:25 -0700291 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700292 selfSign(IdentityCertificate& cert);
Yingdi Yu31b4af22014-01-14 14:13:00 -0800293
Yingdi Yu2e57a582014-02-20 23:34:43 -0800294 /**
295 * @brief delete a certificate.
296 *
Yingdi Yu2e57a582014-02-20 23:34:43 -0800297 * @param certificateName The certificate to be deleted.
Yingdi Yu6147ef42014-12-08 17:48:32 -0800298 * @throws KeyChain::Error if certificate cannot be deleted.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800299 */
Yingdi Yu7036ce22014-06-19 18:53:37 -0700300 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700301 deleteCertificate(const Name& certificateName);
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800302
Yingdi Yu2e57a582014-02-20 23:34:43 -0800303 /**
304 * @brief delete a key.
305 *
Yingdi Yu2e57a582014-02-20 23:34:43 -0800306 * @param keyName The key to be deleted.
Yingdi Yu6147ef42014-12-08 17:48:32 -0800307 * @throws KeyChain::Error if key cannot be deleted.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800308 */
Yingdi Yu7036ce22014-06-19 18:53:37 -0700309 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700310 deleteKey(const Name& keyName);
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800311
Yingdi Yu2e57a582014-02-20 23:34:43 -0800312 /**
313 * @brief delete an identity.
314 *
Yingdi Yu2e57a582014-02-20 23:34:43 -0800315 * @param identity The identity to be deleted.
Yingdi Yu6147ef42014-12-08 17:48:32 -0800316 * @throws KeyChain::Error if identity cannot be deleted.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800317 */
Yingdi Yu7036ce22014-06-19 18:53:37 -0700318 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700319 deleteIdentity(const Name& identity);
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800320
Yingdi Yu2e57a582014-02-20 23:34:43 -0800321 /**
322 * @brief export an identity.
323 *
324 * @param identity The identity to export.
325 * @param passwordStr The password to secure the private key.
Yingdi Yu64c3fb42014-02-26 17:30:04 -0800326 * @return The encoded export data.
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700327 * @throws SecPublicInfo::Error if anything goes wrong in exporting.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800328 */
Yingdi Yu64c3fb42014-02-26 17:30:04 -0800329 shared_ptr<SecuredBag>
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700330 exportIdentity(const Name& identity, const std::string& passwordStr);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800331
Yingdi Yu2e57a582014-02-20 23:34:43 -0800332 /**
333 * @brief import an identity.
334 *
Yingdi Yu64c3fb42014-02-26 17:30:04 -0800335 * @param securedBag The encoded import data.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800336 * @param passwordStr The password to secure the private key.
337 */
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800338 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700339 importIdentity(const SecuredBag& securedBag, const std::string& passwordStr);
340
341 SecPublicInfo&
342 getPib()
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800343 {
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700344 return *m_pib;
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800345 }
346
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700347 const SecPublicInfo&
348 getPib() const
349 {
350 return *m_pib;
351 }
352
353 SecTpm&
354 getTpm()
355 {
356 return *m_tpm;
357 }
358
359 const SecTpm&
360 getTpm() const
361 {
362 return *m_tpm;
363 }
364
365 /*******************************
366 * Wrapper of SecPublicInfo *
367 *******************************/
368 bool
369 doesIdentityExist(const Name& identityName) const
370 {
371 return m_pib->doesIdentityExist(identityName);
372 }
373
374 void
375 addIdentity(const Name& identityName)
376 {
377 return m_pib->addIdentity(identityName);
378 }
379
380 bool
381 doesPublicKeyExist(const Name& keyName) const
382 {
383 return m_pib->doesPublicKeyExist(keyName);
384 }
385
386 void
387 addPublicKey(const Name& keyName, KeyType keyType, const PublicKey& publicKeyDer)
388 {
Yingdi Yu41546342014-11-30 23:37:53 -0800389 return m_pib->addKey(keyName, publicKeyDer);
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700390 }
391
Yingdi Yu7036ce22014-06-19 18:53:37 -0700392 void
393 addKey(const Name& keyName, const PublicKey& publicKeyDer)
394 {
395 return m_pib->addKey(keyName, publicKeyDer);
396 }
397
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700398 shared_ptr<PublicKey>
399 getPublicKey(const Name& keyName) const
400 {
401 return m_pib->getPublicKey(keyName);
402 }
403
404 bool
405 doesCertificateExist(const Name& certificateName) const
406 {
407 return m_pib->doesCertificateExist(certificateName);
408 }
409
410 void
411 addCertificate(const IdentityCertificate& certificate)
412 {
413 return m_pib->addCertificate(certificate);
414 }
415
416 shared_ptr<IdentityCertificate>
417 getCertificate(const Name& certificateName) const
418 {
419 return m_pib->getCertificate(certificateName);
420 }
421
422 Name
423 getDefaultIdentity() const
424 {
425 return m_pib->getDefaultIdentity();
426 }
427
428 Name
429 getDefaultKeyNameForIdentity(const Name& identityName) const
430 {
431 return m_pib->getDefaultKeyNameForIdentity(identityName);
432 }
433
434 Name
435 getDefaultCertificateNameForKey(const Name& keyName) const
436 {
437 return m_pib->getDefaultCertificateNameForKey(keyName);
438 }
439
440 void
441 getAllIdentities(std::vector<Name>& nameList, bool isDefault) const
442 {
443 return m_pib->getAllIdentities(nameList, isDefault);
444 }
445
446 void
447 getAllKeyNames(std::vector<Name>& nameList, bool isDefault) const
448 {
449 return m_pib->getAllKeyNames(nameList, isDefault);
450 }
451
452 void
453 getAllKeyNamesOfIdentity(const Name& identity, std::vector<Name>& nameList, bool isDefault) const
454 {
455 return m_pib->getAllKeyNamesOfIdentity(identity, nameList, isDefault);
456 }
457
458 void
459 getAllCertificateNames(std::vector<Name>& nameList, bool isDefault) const
460 {
461 return m_pib->getAllCertificateNames(nameList, isDefault);
462 }
463
464 void
465 getAllCertificateNamesOfKey(const Name& keyName,
466 std::vector<Name>& nameList,
467 bool isDefault) const
468 {
469 return m_pib->getAllCertificateNamesOfKey(keyName, nameList, isDefault);
470 }
471
472 void
473 deleteCertificateInfo(const Name& certificateName)
474 {
475 return m_pib->deleteCertificateInfo(certificateName);
476 }
477
478 void
479 deletePublicKeyInfo(const Name& keyName)
480 {
481 return m_pib->deletePublicKeyInfo(keyName);
482 }
483
484 void
485 deleteIdentityInfo(const Name& identity)
486 {
487 return m_pib->deleteIdentityInfo(identity);
488 }
489
490 void
491 setDefaultIdentity(const Name& identityName)
492 {
493 return m_pib->setDefaultIdentity(identityName);
494 }
495
496 void
497 setDefaultKeyNameForIdentity(const Name& keyName)
498 {
499 return m_pib->setDefaultKeyNameForIdentity(keyName);
500 }
501
502 void
503 setDefaultCertificateNameForKey(const Name& certificateName)
504 {
505 return m_pib->setDefaultCertificateNameForKey(certificateName);
506 }
507
508 Name
509 getNewKeyName(const Name& identityName, bool useKsk)
510 {
511 return m_pib->getNewKeyName(identityName, useKsk);
512 }
513
514 Name
515 getDefaultCertificateNameForIdentity(const Name& identityName) const
516 {
517 return m_pib->getDefaultCertificateNameForIdentity(identityName);
518 }
519
520 Name
521 getDefaultCertificateName() const
522 {
523 return m_pib->getDefaultCertificateName();
524 }
525
526 void
527 addCertificateAsKeyDefault(const IdentityCertificate& certificate)
528 {
529 return m_pib->addCertificateAsKeyDefault(certificate);
530 }
531
532 void
533 addCertificateAsIdentityDefault(const IdentityCertificate& certificate)
534 {
535 return m_pib->addCertificateAsIdentityDefault(certificate);
536 }
537
538 void
539 addCertificateAsSystemDefault(const IdentityCertificate& certificate)
540 {
541 return m_pib->addCertificateAsSystemDefault(certificate);
542 }
543
544 shared_ptr<IdentityCertificate>
545 getDefaultCertificate() const
546 {
Alexander Afanasyevaab79662014-07-07 17:35:34 -0700547 if (!static_cast<bool>(m_pib->getDefaultCertificate()))
548 const_cast<KeyChain*>(this)->setDefaultCertificateInternal();
549
550 return m_pib->getDefaultCertificate();
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700551 }
552
553 void
554 refreshDefaultCertificate()
555 {
556 return m_pib->refreshDefaultCertificate();
557 }
558
559 /*******************************
560 * Wrapper of SecTpm *
561 *******************************/
562
563 void
564 setTpmPassword(const uint8_t* password, size_t passwordLength)
565 {
566 return m_tpm->setTpmPassword(password, passwordLength);
567 }
568
569 void
570 resetTpmPassword()
571 {
572 return m_tpm->resetTpmPassword();
573 }
574
575 void
576 setInTerminal(bool inTerminal)
577 {
578 return m_tpm->setInTerminal(inTerminal);
579 }
580
581 bool
582 getInTerminal() const
583 {
584 return m_tpm->getInTerminal();
585 }
586
587 bool
588 isLocked() const
589 {
590 return m_tpm->isLocked();
591 }
592
593 bool
594 unlockTpm(const char* password, size_t passwordLength, bool usePassword)
595 {
596 return m_tpm->unlockTpm(password, passwordLength, usePassword);
597 }
598
599 void
Yingdi Yu7036ce22014-06-19 18:53:37 -0700600 generateKeyPairInTpm(const Name& keyName, const KeyParams& params)
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700601 {
Yingdi Yu7036ce22014-06-19 18:53:37 -0700602 return m_tpm->generateKeyPairInTpm(keyName, params);
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700603 }
604
605 void
606 deleteKeyPairInTpm(const Name& keyName)
607 {
608 return m_tpm->deleteKeyPairInTpm(keyName);
609 }
610
611 shared_ptr<PublicKey>
612 getPublicKeyFromTpm(const Name& keyName) const
613 {
614 return m_tpm->getPublicKeyFromTpm(keyName);
615 }
616
617 Block
618 signInTpm(const uint8_t* data, size_t dataLength,
619 const Name& keyName,
620 DigestAlgorithm digestAlgorithm)
621 {
622 return m_tpm->signInTpm(data, dataLength, keyName, digestAlgorithm);
623 }
624
625 ConstBufferPtr
626 decryptInTpm(const uint8_t* data, size_t dataLength, const Name& keyName, bool isSymmetric)
627 {
628 return m_tpm->decryptInTpm(data, dataLength, keyName, isSymmetric);
629 }
630
631 ConstBufferPtr
632 encryptInTpm(const uint8_t* data, size_t dataLength, const Name& keyName, bool isSymmetric)
633 {
634 return m_tpm->encryptInTpm(data, dataLength, keyName, isSymmetric);
635 }
636
637 void
Yingdi Yu7036ce22014-06-19 18:53:37 -0700638 generateSymmetricKeyInTpm(const Name& keyName, const KeyParams& params)
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700639 {
Yingdi Yu7036ce22014-06-19 18:53:37 -0700640 return m_tpm->generateSymmetricKeyInTpm(keyName, params);
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700641 }
642
643 bool
644 doesKeyExistInTpm(const Name& keyName, KeyClass keyClass) const
645 {
646 return m_tpm->doesKeyExistInTpm(keyName, keyClass);
647 }
648
649 bool
650 generateRandomBlock(uint8_t* res, size_t size) const
651 {
652 return m_tpm->generateRandomBlock(res, size);
653 }
654
655 void
656 addAppToAcl(const Name& keyName, KeyClass keyClass, const std::string& appPath, AclType acl)
657 {
658 return m_tpm->addAppToAcl(keyName, keyClass, appPath, acl);
659 }
660
661 ConstBufferPtr
662 exportPrivateKeyPkcs5FromTpm(const Name& keyName, const std::string& password)
663 {
664 return m_tpm->exportPrivateKeyPkcs5FromTpm(keyName, password);
665 }
666
667 bool
668 importPrivateKeyPkcs5IntoTpm(const Name& keyName,
669 const uint8_t* buf, size_t size,
670 const std::string& password)
671 {
672 return m_tpm->importPrivateKeyPkcs5IntoTpm(keyName, buf, size, password);
673 }
Jeff Thompson8efe5ad2013-08-20 17:36:38 -0700674
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800675private:
Yingdi Yu41546342014-11-30 23:37:53 -0800676 void
Alexander Afanasyev07113802015-01-15 19:14:36 -0800677 initialize(const std::string& pibLocatorUri,
678 const std::string& tpmLocatorUri,
Yingdi Yu41546342014-11-30 23:37:53 -0800679 bool needReset);
680
Yingdi Yu2e57a582014-02-20 23:34:43 -0800681 /**
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700682 * @brief Determine signature type
683 *
684 * An empty pointer will be returned if there is no valid signature.
685 */
Yingdi Yu4a557052014-07-09 16:40:37 -0700686 shared_ptr<Signature>
687 determineSignatureWithPublicKey(const KeyLocator& keyLocator,
688 KeyType keyType,
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700689 DigestAlgorithm digestAlgorithm = DIGEST_ALGORITHM_SHA256);
690
691 /**
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700692 * @brief Set default certificate if it is not initialized
693 */
694 void
695 setDefaultCertificateInternal();
696
697 /**
698 * @brief Sign a packet using a pariticular certificate.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800699 *
700 * @param packet The packet to be signed.
701 * @param certificate The signing certificate.
702 */
703 template<typename T>
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800704 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700705 sign(T& packet, const IdentityCertificate& certificate);
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800706
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800707 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800708 * @brief Generate a key pair for the specified identity.
709 *
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800710 * @param identityName The name of the specified identity.
711 * @param isKsk true for generating a Key-Signing-Key (KSK), false for a Data-Signing-Key (KSK).
Yingdi Yu7036ce22014-06-19 18:53:37 -0700712 * @param params The parameter of the key.
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800713 * @return The name of the generated key.
714 */
Yingdi Yu7036ce22014-06-19 18:53:37 -0700715 Name
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700716 generateKeyPair(const Name& identityName, bool isKsk = false,
Yingdi Yu7036ce22014-06-19 18:53:37 -0700717 const KeyParams& params = DEFAULT_KEY_PARAMS);
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800718
Yingdi Yu8726f652014-01-23 10:35:12 -0800719 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800720 * @brief Sign the data using a particular key.
721 *
722 * @param data Reference to the data packet.
723 * @param signature Signature to be added.
Yingdi Yu8726f652014-01-23 10:35:12 -0800724 * @param keyName The name of the signing key.
725 * @param digestAlgorithm the digest algorithm.
726 * @throws Tpm::Error
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700727 */
Yingdi Yu7036ce22014-06-19 18:53:37 -0700728 void
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700729 signPacketWrapper(Data& data, const Signature& signature,
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700730 const Name& keyName, DigestAlgorithm digestAlgorithm);
Yingdi Yu8726f652014-01-23 10:35:12 -0800731
Yingdi Yu2e57a582014-02-20 23:34:43 -0800732 /**
733 * @brief Sign the interest using a particular key.
734 *
735 * @param interest Reference to the interest packet.
736 * @param signature Signature to be added.
737 * @param keyName The name of the signing key.
738 * @param digestAlgorithm the digest algorithm.
739 * @throws Tpm::Error
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700740 */
Yingdi Yu7036ce22014-06-19 18:53:37 -0700741 void
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700742 signPacketWrapper(Interest& interest, const Signature& signature,
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700743 const Name& keyName, DigestAlgorithm digestAlgorithm);
Yingdi Yu2e57a582014-02-20 23:34:43 -0800744
Alexander Afanasyev07113802015-01-15 19:14:36 -0800745 static void
746 registerPibImpl(std::initializer_list<std::string> schemes, PibCreateFunc createFunc);
747
748 static void
749 registerTpmImpl(std::initializer_list<std::string> schemes, TpmCreateFunc createFunc);
750
Yingdi Yu41546342014-11-30 23:37:53 -0800751public:
752 static const Name DEFAULT_PREFIX;
753 // RsaKeyParams is set to be default for backward compatibility.
754 static const RsaKeyParams DEFAULT_KEY_PARAMS;
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700755
756private:
Alexander Afanasyev07113802015-01-15 19:14:36 -0800757 std::unique_ptr<SecPublicInfo> m_pib;
758 std::unique_ptr<SecTpm> m_tpm;
Yingdi Yu0f5fb692014-06-10 12:07:28 -0700759 time::milliseconds m_lastTimestamp;
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700760};
761
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700762template<typename T>
763void
764KeyChain::sign(T& packet)
765{
Alexander Afanasyevaab79662014-07-07 17:35:34 -0700766 if (!static_cast<bool>(m_pib->getDefaultCertificate()))
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700767 setDefaultCertificateInternal();
768
Alexander Afanasyevaab79662014-07-07 17:35:34 -0700769 sign(packet, *m_pib->getDefaultCertificate());
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700770}
771
772template<typename T>
773void
774KeyChain::sign(T& packet, const Name& certificateName)
775{
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700776 shared_ptr<IdentityCertificate> certificate = m_pib->getCertificate(certificateName);
777 sign(packet, *certificate);
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700778}
779
780template<typename T>
781void
782KeyChain::signByIdentity(T& packet, const Name& identityName)
783{
784 Name signingCertificateName;
785 try
786 {
787 signingCertificateName = m_pib->getDefaultCertificateNameForIdentity(identityName);
788 }
789 catch (SecPublicInfo::Error& e)
790 {
791 signingCertificateName = createIdentity(identityName);
792 // Ideally, no exception will be thrown out, unless something goes wrong in the TPM, which
793 // is a fatal error.
794 }
795
796 // We either get or create the signing certificate, sign packet! (no exception unless fatal
797 // error in TPM)
798 sign(packet, signingCertificateName);
799}
800
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700801template<typename T>
802void
803KeyChain::sign(T& packet, const IdentityCertificate& certificate)
804{
Yingdi Yu4a557052014-07-09 16:40:37 -0700805 KeyLocator keyLocator(certificate.getName().getPrefix(-1));
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700806
Yingdi Yu4a557052014-07-09 16:40:37 -0700807 shared_ptr<Signature> signature =
808 determineSignatureWithPublicKey(keyLocator, certificate.getPublicKeyInfo().getKeyType());
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700809
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700810 if (!static_cast<bool>(signature))
811 throw SecPublicInfo::Error("unknown key type!");
812
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700813 signPacketWrapper(packet, *signature,
814 certificate.getPublicKeyName(),
815 DIGEST_ALGORITHM_SHA256);
816
817 return;
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700818}
819
Alexander Afanasyev07113802015-01-15 19:14:36 -0800820template<class PibType>
821inline void
822KeyChain::registerPib(std::initializer_list<std::string> schemes)
823{
824 registerPibImpl(schemes, [] (const std::string& locator) {
825 return unique_ptr<SecPublicInfo>(new PibType(locator));
826 });
827}
828
829template<class TpmType>
830inline void
831KeyChain::registerTpm(std::initializer_list<std::string> schemes)
832{
833 registerTpmImpl(schemes, [] (const std::string& locator) {
834 return unique_ptr<SecTpm>(new TpmType(locator));
835 });
836}
837
838/**
839 * \brief Register SecPib class in ndn-cxx KeyChain
840 *
841 * This macro should be placed once in the implementation file of the
842 * SecPib type within the namespace where the type is declared.
843 */
844#define NDN_CXX_KEYCHAIN_REGISTER_PIB(PibType, ...) \
845static class NdnCxxAuto ## PibType ## PibRegistrationClass \
846{ \
847public: \
848 NdnCxxAuto ## PibType ## PibRegistrationClass() \
849 { \
850 ::ndn::KeyChain::registerPib<PibType>({__VA_ARGS__}); \
851 } \
852} ndnCxxAuto ## PibType ## PibRegistrationVariable
853
854/**
855 * \brief Register SecTpm class in ndn-cxx KeyChain
856 *
857 * This macro should be placed once in the implementation file of the
858 * SecTpm type within the namespace where the type is declared.
859 */
860#define NDN_CXX_KEYCHAIN_REGISTER_TPM(TpmType, ...) \
861static class NdnCxxAuto ## TpmType ## TpmRegistrationClass \
862{ \
863public: \
864 NdnCxxAuto ## TpmType ## TpmRegistrationClass() \
865 { \
866 ::ndn::KeyChain::registerTpm<TpmType>({__VA_ARGS__}); \
867 } \
868} ndnCxxAuto ## TpmType ## TpmRegistrationVariable
869
Yingdi Yu6ab67812014-11-27 15:00:34 -0800870} // namespace ndn
Jeff Thompson47c93cf2013-08-09 00:38:48 -0700871
Alexander Afanasyev766cea72014-04-24 19:16:42 -0700872#endif // NDN_SECURITY_KEY_CHAIN_HPP