blob: 955733d3d861bddce91cb015d194eae4f1616cdb [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 Afanasyev34a37632015-01-16 17:37:36 -08003 * Copyright (c) 2013-2015 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
Alexander Afanasyev34a37632015-01-16 17:37:36 -080075 * @param aliases List of schemes with which this PIB will be associated.
76 * The first alias in the list is considered a canonical name of the PIB instance.
Alexander Afanasyev07113802015-01-15 19:14:36 -080077 */
78 template<class PibType>
79 static void
Alexander Afanasyev34a37632015-01-16 17:37:36 -080080 registerPib(std::initializer_list<std::string> aliases);
Alexander Afanasyev07113802015-01-15 19:14:36 -080081
82 /**
83 * @brief Register a new TPM
Alexander Afanasyev34a37632015-01-16 17:37:36 -080084 * @param aliases List of schemes with which this TPM will be associated
85 * The first alias in the list is considered a canonical name of the TPM instance.
Alexander Afanasyev07113802015-01-15 19:14:36 -080086 */
87 template<class TpmType>
88 static void
Alexander Afanasyev34a37632015-01-16 17:37:36 -080089 registerTpm(std::initializer_list<std::string> aliases);
Alexander Afanasyev07113802015-01-15 19:14:36 -080090
Yingdi Yu281689a2015-06-13 14:32:32 -070091 /// @brief Get default PIB locator
92 static std::string
93 getDefaultPibLocator();
94
95 /// @brief Create a PIB according to @p pibLocator
96 static unique_ptr<SecPublicInfo>
97 createPib(const std::string& pibLocator);
98
99 /// @brief Get default TPM locator
100 static std::string
101 getDefaultTpmLocator();
102
103 /// @brief Create a TPM according to @p tpmLocator
104 static unique_ptr<SecTpm>
105 createTpm(const std::string& tpmLocator);
106
Alexander Afanasyev07113802015-01-15 19:14:36 -0800107 /**
108 * @brief Constructor to create KeyChain with default PIB and TPM
109 *
110 * Default PIB and TPM are platform-dependent and can be overriden system-wide or on
111 * per-use basis.
112 *
113 * @todo Add detailed description about config file behavior here
114 */
115 KeyChain();
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700116
Yingdi Yu41546342014-11-30 23:37:53 -0800117 /**
118 * @brief KeyChain constructor
119 *
120 * @sa http://redmine.named-data.net/issues/2260
121 *
122 * @param pibLocator
123 * @param tpmLocator
124 * @param allowReset if true, the PIB will be reset when the supplied tpmLocator
125 * mismatches the one in PIB
126 */
127 KeyChain(const std::string& pibLocator,
128 const std::string& tpmLocator,
129 bool allowReset = false);
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700130
131 virtual
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700132 ~KeyChain();
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700133
Yingdi Yube4150e2014-02-18 13:02:46 -0800134 /**
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700135 * @brief Create an identity by creating a pair of Key-Signing-Key (KSK) for this identity and a
136 * self-signed certificate of the KSK.
Yingdi Yube4150e2014-02-18 13:02:46 -0800137 *
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800138 * @param identityName The name of the identity.
Yingdi Yu7036ce22014-06-19 18:53:37 -0700139 * @param params The key parameter if a key needs to be generated for the identity.
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800140 * @return The name of the default certificate of the identity.
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800141 */
Yingdi Yu7036ce22014-06-19 18:53:37 -0700142 Name
143 createIdentity(const Name& identityName, const KeyParams& params = DEFAULT_KEY_PARAMS);
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700144
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800145 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800146 * @brief Generate a pair of RSA keys for the specified identity.
147 *
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800148 * @param identityName The name of the identity.
149 * @param isKsk true for generating a Key-Signing-Key (KSK), false for a Data-Signing-Key (KSK).
150 * @param keySize The size of the key.
151 * @return The generated key name.
152 */
Yingdi Yu41546342014-11-30 23:37:53 -0800153 Name
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700154 generateRsaKeyPair(const Name& identityName, bool isKsk = false, uint32_t keySize = 2048);
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700155
Yingdi Yu41546342014-11-30 23:37:53 -0800156 Name
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700157 generateEcdsaKeyPair(const Name& identityName, bool isKsk = false, uint32_t keySize = 256);
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800158 /**
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700159 * @brief Generate a pair of RSA keys for the specified identity and set it as default key for
160 * the identity.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800161 *
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800162 * @param identityName The name of the identity.
163 * @param isKsk true for generating a Key-Signing-Key (KSK), false for a Data-Signing-Key (KSK).
164 * @param keySize The size of the key.
165 * @return The generated key name.
166 */
Yingdi Yu7036ce22014-06-19 18:53:37 -0700167 Name
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700168 generateRsaKeyPairAsDefault(const Name& identityName, bool isKsk = false,
169 uint32_t keySize = 2048);
170
171 Name
172 generateEcdsaKeyPairAsDefault(const Name& identityName, bool isKsk, uint32_t keySize = 256);
Jeff Thompson79a2d5d2013-09-27 14:32:23 -0700173
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800174 /**
Yingdi Yuc55680b2014-02-26 12:31:35 -0800175 * @brief prepare an unsigned identity certificate
176 *
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700177 * @param keyName Key name, e.g., `/<identity_name>/ksk-123456`.
Yingdi Yuc55680b2014-02-26 12:31:35 -0800178 * @param signingIdentity The signing identity.
179 * @param notBefore Refer to IdentityCertificate.
180 * @param notAfter Refer to IdentityCertificate.
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700181 * @param subjectDescription Refer to IdentityCertificate.
Yingdi Yu0eb5d722014-06-10 15:06:25 -0700182 * @param certPrefix Prefix before `KEY` component. By default, KeyChain will infer the
183 * certificate name according to the relation between the signingIdentity and
184 * the subject identity. If signingIdentity is a prefix of the subject identity,
185 * `KEY` will be inserted after the signingIdentity, otherwise `KEY` is inserted
186 * after subject identity (i.e., before `ksk-....`).
Yingdi Yuc55680b2014-02-26 12:31:35 -0800187 * @return IdentityCertificate.
188 */
189 shared_ptr<IdentityCertificate>
190 prepareUnsignedIdentityCertificate(const Name& keyName,
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700191 const Name& signingIdentity,
192 const time::system_clock::TimePoint& notBefore,
193 const time::system_clock::TimePoint& notAfter,
Yingdi Yu0eb5d722014-06-10 15:06:25 -0700194 const std::vector<CertificateSubjectDescription>& subjectDescription,
195 const Name& certPrefix = DEFAULT_PREFIX);
196
197 /**
198 * @brief prepare an unsigned identity certificate
199 *
200 * @param keyName Key name, e.g., `/<identity_name>/ksk-123456`.
201 * @param publicKey Public key to sign.
202 * @param signingIdentity The signing identity.
203 * @param notBefore Refer to IdentityCertificate.
204 * @param notAfter Refer to IdentityCertificate.
205 * @param subjectDescription Refer to IdentityCertificate.
206 * @param certPrefix Prefix before `KEY` component. By default, KeyChain will infer the
207 * certificate name according to the relation between the signingIdentity and
208 * the subject identity. If signingIdentity is a prefix of the subject identity,
209 * `KEY` will be inserted after the signingIdentity, otherwise `KEY` is inserted
210 * after subject identity (i.e., before `ksk-....`).
211 * @return IdentityCertificate.
212 */
213 shared_ptr<IdentityCertificate>
214 prepareUnsignedIdentityCertificate(const Name& keyName,
215 const PublicKey& publicKey,
216 const Name& signingIdentity,
217 const time::system_clock::TimePoint& notBefore,
218 const time::system_clock::TimePoint& notAfter,
219 const std::vector<CertificateSubjectDescription>& subjectDescription,
220 const Name& certPrefix = DEFAULT_PREFIX);
Yingdi Yuc55680b2014-02-26 12:31:35 -0800221
222 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800223 * @brief Sign packet with default identity
224 *
Yingdi Yu60bd7082014-03-25 18:18:54 -0700225 * On return, signatureInfo and signatureValue in the packet are set.
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700226 * If default identity does not exist,
Yingdi Yu60bd7082014-03-25 18:18:54 -0700227 * a temporary identity will be created and set as default.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800228 *
229 * @param packet The packet to be signed
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800230 */
Yingdi Yu2e57a582014-02-20 23:34:43 -0800231 template<typename T>
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800232 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700233 sign(T& packet);
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700234
Jeff Thompson47c93cf2013-08-09 00:38:48 -0700235 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800236 * @brief Sign packet with a particular certificate.
237 *
238 * @param packet The packet to be signed.
239 * @param certificateName The certificate name of the key to use for signing.
240 * @throws SecPublicInfo::Error if certificate does not exist.
Jeff Thompson3c73da42013-08-12 11:19:05 -0700241 */
Yingdi Yu2e57a582014-02-20 23:34:43 -0800242 template<typename T>
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700243 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700244 sign(T& packet, const Name& certificateName);
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700245
Jeff Thompson29ce3102013-09-27 11:47:48 -0700246 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800247 * @brief Sign the byte array using a particular certificate.
248 *
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700249 * @param buffer The byte array to be signed.
250 * @param bufferLength the length of buffer.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800251 * @param certificateName The certificate name of the signing key.
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700252 * @return The Signature.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800253 * @throws SecPublicInfo::Error if certificate does not exist.
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700254 */
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800255 Signature
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700256 sign(const uint8_t* buffer, size_t bufferLength, const Name& certificateName);
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700257
258 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800259 * @brief Sign packet using the default certificate of a particular identity.
260 *
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700261 * If there is no default certificate of that identity, this method will create a self-signed
262 * certificate.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800263 *
264 * @param packet The packet to be signed.
265 * @param identityName The signing identity name.
Jeff Thompson29ce3102013-09-27 11:47:48 -0700266 */
Yingdi Yu2e57a582014-02-20 23:34:43 -0800267 template<typename T>
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700268 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700269 signByIdentity(T& packet, const Name& identityName);
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700270
Jeff Thompson3c73da42013-08-12 11:19:05 -0700271 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800272 * @brief Sign the byte array using the default certificate of a particular identity.
273 *
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700274 * @param buffer The byte array to be signed.
275 * @param bufferLength the length of buffer.
276 * @param identityName The identity name.
277 * @return The Signature.
278 */
Yingdi Yu7036ce22014-06-19 18:53:37 -0700279 Signature
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700280 signByIdentity(const uint8_t* buffer, size_t bufferLength, const Name& identityName);
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700281
282 /**
Yingdi Yu6ab67812014-11-27 15:00:34 -0800283 * @brief Set Sha256 weak signature for @p data
Yingdi Yu21157162014-02-28 13:02:34 -0800284 */
Yingdi Yu7036ce22014-06-19 18:53:37 -0700285 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700286 signWithSha256(Data& data);
Yingdi Yu21157162014-02-28 13:02:34 -0800287
288 /**
Yingdi Yu6ab67812014-11-27 15:00:34 -0800289 * @brief Set Sha256 weak signature for @p interest
290 */
291 void
292 signWithSha256(Interest& interest);
293
294 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800295 * @brief Generate a self-signed certificate for a public key.
296 *
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700297 * @param keyName The name of the public key
298 * @return The generated certificate, shared_ptr<IdentityCertificate>() if selfSign fails
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800299 */
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800300 shared_ptr<IdentityCertificate>
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700301 selfSign(const Name& keyName);
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800302
303 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800304 * @brief Self-sign the supplied identity certificate.
305 *
306 * @param cert The supplied cert.
307 * @throws SecTpm::Error if the private key does not exist.
Jeff Thompson8efe5ad2013-08-20 17:36:38 -0700308 */
Jeff Thompson2ce8f492013-09-17 18:01:25 -0700309 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700310 selfSign(IdentityCertificate& cert);
Yingdi Yu31b4af22014-01-14 14:13:00 -0800311
Yingdi Yu2e57a582014-02-20 23:34:43 -0800312 /**
313 * @brief delete a certificate.
314 *
Yingdi Yu2e57a582014-02-20 23:34:43 -0800315 * @param certificateName The certificate to be deleted.
Yingdi Yu6147ef42014-12-08 17:48:32 -0800316 * @throws KeyChain::Error if certificate 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 deleteCertificate(const Name& certificateName);
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800320
Yingdi Yu2e57a582014-02-20 23:34:43 -0800321 /**
322 * @brief delete a key.
323 *
Yingdi Yu2e57a582014-02-20 23:34:43 -0800324 * @param keyName The key to be deleted.
Yingdi Yu6147ef42014-12-08 17:48:32 -0800325 * @throws KeyChain::Error if key cannot be deleted.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800326 */
Yingdi Yu7036ce22014-06-19 18:53:37 -0700327 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700328 deleteKey(const Name& keyName);
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800329
Yingdi Yu2e57a582014-02-20 23:34:43 -0800330 /**
331 * @brief delete an identity.
332 *
Yingdi Yu2e57a582014-02-20 23:34:43 -0800333 * @param identity The identity to be deleted.
Yingdi Yu6147ef42014-12-08 17:48:32 -0800334 * @throws KeyChain::Error if identity cannot be deleted.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800335 */
Yingdi Yu7036ce22014-06-19 18:53:37 -0700336 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700337 deleteIdentity(const Name& identity);
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800338
Yingdi Yu2e57a582014-02-20 23:34:43 -0800339 /**
340 * @brief export an identity.
341 *
342 * @param identity The identity to export.
343 * @param passwordStr The password to secure the private key.
Yingdi Yu64c3fb42014-02-26 17:30:04 -0800344 * @return The encoded export data.
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700345 * @throws SecPublicInfo::Error if anything goes wrong in exporting.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800346 */
Yingdi Yu64c3fb42014-02-26 17:30:04 -0800347 shared_ptr<SecuredBag>
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700348 exportIdentity(const Name& identity, const std::string& passwordStr);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800349
Yingdi Yu2e57a582014-02-20 23:34:43 -0800350 /**
351 * @brief import an identity.
352 *
Yingdi Yu64c3fb42014-02-26 17:30:04 -0800353 * @param securedBag The encoded import data.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800354 * @param passwordStr The password to secure the private key.
355 */
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800356 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700357 importIdentity(const SecuredBag& securedBag, const std::string& passwordStr);
358
359 SecPublicInfo&
360 getPib()
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800361 {
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700362 return *m_pib;
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800363 }
364
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700365 const SecPublicInfo&
366 getPib() const
367 {
368 return *m_pib;
369 }
370
371 SecTpm&
372 getTpm()
373 {
374 return *m_tpm;
375 }
376
377 const SecTpm&
378 getTpm() const
379 {
380 return *m_tpm;
381 }
382
383 /*******************************
384 * Wrapper of SecPublicInfo *
385 *******************************/
386 bool
387 doesIdentityExist(const Name& identityName) const
388 {
389 return m_pib->doesIdentityExist(identityName);
390 }
391
392 void
393 addIdentity(const Name& identityName)
394 {
395 return m_pib->addIdentity(identityName);
396 }
397
398 bool
399 doesPublicKeyExist(const Name& keyName) const
400 {
401 return m_pib->doesPublicKeyExist(keyName);
402 }
403
404 void
405 addPublicKey(const Name& keyName, KeyType keyType, const PublicKey& publicKeyDer)
406 {
Yingdi Yu41546342014-11-30 23:37:53 -0800407 return m_pib->addKey(keyName, publicKeyDer);
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700408 }
409
Yingdi Yu7036ce22014-06-19 18:53:37 -0700410 void
411 addKey(const Name& keyName, const PublicKey& publicKeyDer)
412 {
413 return m_pib->addKey(keyName, publicKeyDer);
414 }
415
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700416 shared_ptr<PublicKey>
417 getPublicKey(const Name& keyName) const
418 {
419 return m_pib->getPublicKey(keyName);
420 }
421
422 bool
423 doesCertificateExist(const Name& certificateName) const
424 {
425 return m_pib->doesCertificateExist(certificateName);
426 }
427
428 void
429 addCertificate(const IdentityCertificate& certificate)
430 {
431 return m_pib->addCertificate(certificate);
432 }
433
434 shared_ptr<IdentityCertificate>
435 getCertificate(const Name& certificateName) const
436 {
437 return m_pib->getCertificate(certificateName);
438 }
439
440 Name
441 getDefaultIdentity() const
442 {
443 return m_pib->getDefaultIdentity();
444 }
445
446 Name
447 getDefaultKeyNameForIdentity(const Name& identityName) const
448 {
449 return m_pib->getDefaultKeyNameForIdentity(identityName);
450 }
451
452 Name
453 getDefaultCertificateNameForKey(const Name& keyName) const
454 {
455 return m_pib->getDefaultCertificateNameForKey(keyName);
456 }
457
458 void
459 getAllIdentities(std::vector<Name>& nameList, bool isDefault) const
460 {
461 return m_pib->getAllIdentities(nameList, isDefault);
462 }
463
464 void
465 getAllKeyNames(std::vector<Name>& nameList, bool isDefault) const
466 {
467 return m_pib->getAllKeyNames(nameList, isDefault);
468 }
469
470 void
471 getAllKeyNamesOfIdentity(const Name& identity, std::vector<Name>& nameList, bool isDefault) const
472 {
473 return m_pib->getAllKeyNamesOfIdentity(identity, nameList, isDefault);
474 }
475
476 void
477 getAllCertificateNames(std::vector<Name>& nameList, bool isDefault) const
478 {
479 return m_pib->getAllCertificateNames(nameList, isDefault);
480 }
481
482 void
483 getAllCertificateNamesOfKey(const Name& keyName,
484 std::vector<Name>& nameList,
485 bool isDefault) const
486 {
487 return m_pib->getAllCertificateNamesOfKey(keyName, nameList, isDefault);
488 }
489
490 void
491 deleteCertificateInfo(const Name& certificateName)
492 {
493 return m_pib->deleteCertificateInfo(certificateName);
494 }
495
496 void
497 deletePublicKeyInfo(const Name& keyName)
498 {
499 return m_pib->deletePublicKeyInfo(keyName);
500 }
501
502 void
503 deleteIdentityInfo(const Name& identity)
504 {
505 return m_pib->deleteIdentityInfo(identity);
506 }
507
508 void
509 setDefaultIdentity(const Name& identityName)
510 {
511 return m_pib->setDefaultIdentity(identityName);
512 }
513
514 void
515 setDefaultKeyNameForIdentity(const Name& keyName)
516 {
517 return m_pib->setDefaultKeyNameForIdentity(keyName);
518 }
519
520 void
521 setDefaultCertificateNameForKey(const Name& certificateName)
522 {
523 return m_pib->setDefaultCertificateNameForKey(certificateName);
524 }
525
526 Name
527 getNewKeyName(const Name& identityName, bool useKsk)
528 {
529 return m_pib->getNewKeyName(identityName, useKsk);
530 }
531
532 Name
533 getDefaultCertificateNameForIdentity(const Name& identityName) const
534 {
535 return m_pib->getDefaultCertificateNameForIdentity(identityName);
536 }
537
538 Name
539 getDefaultCertificateName() const
540 {
541 return m_pib->getDefaultCertificateName();
542 }
543
544 void
545 addCertificateAsKeyDefault(const IdentityCertificate& certificate)
546 {
547 return m_pib->addCertificateAsKeyDefault(certificate);
548 }
549
550 void
551 addCertificateAsIdentityDefault(const IdentityCertificate& certificate)
552 {
553 return m_pib->addCertificateAsIdentityDefault(certificate);
554 }
555
556 void
557 addCertificateAsSystemDefault(const IdentityCertificate& certificate)
558 {
559 return m_pib->addCertificateAsSystemDefault(certificate);
560 }
561
562 shared_ptr<IdentityCertificate>
563 getDefaultCertificate() const
564 {
Alexander Afanasyevaab79662014-07-07 17:35:34 -0700565 if (!static_cast<bool>(m_pib->getDefaultCertificate()))
566 const_cast<KeyChain*>(this)->setDefaultCertificateInternal();
567
568 return m_pib->getDefaultCertificate();
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700569 }
570
571 void
572 refreshDefaultCertificate()
573 {
574 return m_pib->refreshDefaultCertificate();
575 }
576
577 /*******************************
578 * Wrapper of SecTpm *
579 *******************************/
580
581 void
582 setTpmPassword(const uint8_t* password, size_t passwordLength)
583 {
584 return m_tpm->setTpmPassword(password, passwordLength);
585 }
586
587 void
588 resetTpmPassword()
589 {
590 return m_tpm->resetTpmPassword();
591 }
592
593 void
594 setInTerminal(bool inTerminal)
595 {
596 return m_tpm->setInTerminal(inTerminal);
597 }
598
599 bool
600 getInTerminal() const
601 {
602 return m_tpm->getInTerminal();
603 }
604
605 bool
606 isLocked() const
607 {
608 return m_tpm->isLocked();
609 }
610
611 bool
612 unlockTpm(const char* password, size_t passwordLength, bool usePassword)
613 {
614 return m_tpm->unlockTpm(password, passwordLength, usePassword);
615 }
616
617 void
Yingdi Yu7036ce22014-06-19 18:53:37 -0700618 generateKeyPairInTpm(const Name& keyName, const KeyParams& params)
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700619 {
Yingdi Yu7036ce22014-06-19 18:53:37 -0700620 return m_tpm->generateKeyPairInTpm(keyName, params);
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700621 }
622
623 void
624 deleteKeyPairInTpm(const Name& keyName)
625 {
626 return m_tpm->deleteKeyPairInTpm(keyName);
627 }
628
629 shared_ptr<PublicKey>
630 getPublicKeyFromTpm(const Name& keyName) const
631 {
632 return m_tpm->getPublicKeyFromTpm(keyName);
633 }
634
635 Block
636 signInTpm(const uint8_t* data, size_t dataLength,
637 const Name& keyName,
638 DigestAlgorithm digestAlgorithm)
639 {
640 return m_tpm->signInTpm(data, dataLength, keyName, digestAlgorithm);
641 }
642
643 ConstBufferPtr
644 decryptInTpm(const uint8_t* data, size_t dataLength, const Name& keyName, bool isSymmetric)
645 {
646 return m_tpm->decryptInTpm(data, dataLength, keyName, isSymmetric);
647 }
648
649 ConstBufferPtr
650 encryptInTpm(const uint8_t* data, size_t dataLength, const Name& keyName, bool isSymmetric)
651 {
652 return m_tpm->encryptInTpm(data, dataLength, keyName, isSymmetric);
653 }
654
655 void
Yingdi Yu7036ce22014-06-19 18:53:37 -0700656 generateSymmetricKeyInTpm(const Name& keyName, const KeyParams& params)
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700657 {
Yingdi Yu7036ce22014-06-19 18:53:37 -0700658 return m_tpm->generateSymmetricKeyInTpm(keyName, params);
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700659 }
660
661 bool
662 doesKeyExistInTpm(const Name& keyName, KeyClass keyClass) const
663 {
664 return m_tpm->doesKeyExistInTpm(keyName, keyClass);
665 }
666
667 bool
668 generateRandomBlock(uint8_t* res, size_t size) const
669 {
670 return m_tpm->generateRandomBlock(res, size);
671 }
672
673 void
674 addAppToAcl(const Name& keyName, KeyClass keyClass, const std::string& appPath, AclType acl)
675 {
676 return m_tpm->addAppToAcl(keyName, keyClass, appPath, acl);
677 }
678
679 ConstBufferPtr
680 exportPrivateKeyPkcs5FromTpm(const Name& keyName, const std::string& password)
681 {
682 return m_tpm->exportPrivateKeyPkcs5FromTpm(keyName, password);
683 }
684
685 bool
686 importPrivateKeyPkcs5IntoTpm(const Name& keyName,
687 const uint8_t* buf, size_t size,
688 const std::string& password)
689 {
690 return m_tpm->importPrivateKeyPkcs5IntoTpm(keyName, buf, size, password);
691 }
Jeff Thompson8efe5ad2013-08-20 17:36:38 -0700692
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800693private:
Yingdi Yu41546342014-11-30 23:37:53 -0800694 void
Alexander Afanasyev07113802015-01-15 19:14:36 -0800695 initialize(const std::string& pibLocatorUri,
696 const std::string& tpmLocatorUri,
Yingdi Yu41546342014-11-30 23:37:53 -0800697 bool needReset);
698
Yingdi Yu2e57a582014-02-20 23:34:43 -0800699 /**
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700700 * @brief Determine signature type
701 *
702 * An empty pointer will be returned if there is no valid signature.
703 */
Yingdi Yu4a557052014-07-09 16:40:37 -0700704 shared_ptr<Signature>
705 determineSignatureWithPublicKey(const KeyLocator& keyLocator,
706 KeyType keyType,
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700707 DigestAlgorithm digestAlgorithm = DIGEST_ALGORITHM_SHA256);
708
709 /**
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700710 * @brief Set default certificate if it is not initialized
711 */
712 void
713 setDefaultCertificateInternal();
714
715 /**
716 * @brief Sign a packet using a pariticular certificate.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800717 *
718 * @param packet The packet to be signed.
719 * @param certificate The signing certificate.
720 */
721 template<typename T>
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800722 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700723 sign(T& packet, const IdentityCertificate& certificate);
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800724
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800725 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800726 * @brief Generate a key pair for the specified identity.
727 *
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800728 * @param identityName The name of the specified identity.
729 * @param isKsk true for generating a Key-Signing-Key (KSK), false for a Data-Signing-Key (KSK).
Yingdi Yu7036ce22014-06-19 18:53:37 -0700730 * @param params The parameter of the key.
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800731 * @return The name of the generated key.
732 */
Yingdi Yu7036ce22014-06-19 18:53:37 -0700733 Name
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700734 generateKeyPair(const Name& identityName, bool isKsk = false,
Yingdi Yu7036ce22014-06-19 18:53:37 -0700735 const KeyParams& params = DEFAULT_KEY_PARAMS);
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800736
Yingdi Yu8726f652014-01-23 10:35:12 -0800737 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800738 * @brief Sign the data using a particular key.
739 *
740 * @param data Reference to the data packet.
741 * @param signature Signature to be added.
Yingdi Yu8726f652014-01-23 10:35:12 -0800742 * @param keyName The name of the signing key.
743 * @param digestAlgorithm the digest algorithm.
744 * @throws Tpm::Error
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700745 */
Yingdi Yu7036ce22014-06-19 18:53:37 -0700746 void
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700747 signPacketWrapper(Data& data, const Signature& signature,
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700748 const Name& keyName, DigestAlgorithm digestAlgorithm);
Yingdi Yu8726f652014-01-23 10:35:12 -0800749
Yingdi Yu2e57a582014-02-20 23:34:43 -0800750 /**
751 * @brief Sign the interest using a particular key.
752 *
753 * @param interest Reference to the interest packet.
754 * @param signature Signature to be added.
755 * @param keyName The name of the signing key.
756 * @param digestAlgorithm the digest algorithm.
757 * @throws Tpm::Error
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700758 */
Yingdi Yu7036ce22014-06-19 18:53:37 -0700759 void
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700760 signPacketWrapper(Interest& interest, const Signature& signature,
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700761 const Name& keyName, DigestAlgorithm digestAlgorithm);
Yingdi Yu2e57a582014-02-20 23:34:43 -0800762
Alexander Afanasyev07113802015-01-15 19:14:36 -0800763 static void
Alexander Afanasyev34a37632015-01-16 17:37:36 -0800764 registerPibImpl(const std::string& canonicalName,
765 std::initializer_list<std::string> aliases, PibCreateFunc createFunc);
Alexander Afanasyev07113802015-01-15 19:14:36 -0800766
767 static void
Alexander Afanasyev34a37632015-01-16 17:37:36 -0800768 registerTpmImpl(const std::string& canonicalName,
769 std::initializer_list<std::string> aliases, TpmCreateFunc createFunc);
Alexander Afanasyev07113802015-01-15 19:14:36 -0800770
Yingdi Yu41546342014-11-30 23:37:53 -0800771public:
772 static const Name DEFAULT_PREFIX;
773 // RsaKeyParams is set to be default for backward compatibility.
774 static const RsaKeyParams DEFAULT_KEY_PARAMS;
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700775
776private:
Alexander Afanasyev07113802015-01-15 19:14:36 -0800777 std::unique_ptr<SecPublicInfo> m_pib;
778 std::unique_ptr<SecTpm> m_tpm;
Yingdi Yu0f5fb692014-06-10 12:07:28 -0700779 time::milliseconds m_lastTimestamp;
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700780};
781
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700782template<typename T>
783void
784KeyChain::sign(T& packet)
785{
Alexander Afanasyevaab79662014-07-07 17:35:34 -0700786 if (!static_cast<bool>(m_pib->getDefaultCertificate()))
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700787 setDefaultCertificateInternal();
788
Alexander Afanasyevaab79662014-07-07 17:35:34 -0700789 sign(packet, *m_pib->getDefaultCertificate());
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700790}
791
792template<typename T>
793void
794KeyChain::sign(T& packet, const Name& certificateName)
795{
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700796 shared_ptr<IdentityCertificate> certificate = m_pib->getCertificate(certificateName);
797 sign(packet, *certificate);
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700798}
799
800template<typename T>
801void
802KeyChain::signByIdentity(T& packet, const Name& identityName)
803{
804 Name signingCertificateName;
805 try
806 {
807 signingCertificateName = m_pib->getDefaultCertificateNameForIdentity(identityName);
808 }
809 catch (SecPublicInfo::Error& e)
810 {
811 signingCertificateName = createIdentity(identityName);
812 // Ideally, no exception will be thrown out, unless something goes wrong in the TPM, which
813 // is a fatal error.
814 }
815
816 // We either get or create the signing certificate, sign packet! (no exception unless fatal
817 // error in TPM)
818 sign(packet, signingCertificateName);
819}
820
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700821template<typename T>
822void
823KeyChain::sign(T& packet, const IdentityCertificate& certificate)
824{
Yingdi Yu4a557052014-07-09 16:40:37 -0700825 KeyLocator keyLocator(certificate.getName().getPrefix(-1));
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700826
Yingdi Yu4a557052014-07-09 16:40:37 -0700827 shared_ptr<Signature> signature =
828 determineSignatureWithPublicKey(keyLocator, certificate.getPublicKeyInfo().getKeyType());
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700829
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700830 if (!static_cast<bool>(signature))
831 throw SecPublicInfo::Error("unknown key type!");
832
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700833 signPacketWrapper(packet, *signature,
834 certificate.getPublicKeyName(),
835 DIGEST_ALGORITHM_SHA256);
836
837 return;
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700838}
839
Alexander Afanasyev07113802015-01-15 19:14:36 -0800840template<class PibType>
841inline void
Alexander Afanasyev34a37632015-01-16 17:37:36 -0800842KeyChain::registerPib(std::initializer_list<std::string> aliases)
Alexander Afanasyev07113802015-01-15 19:14:36 -0800843{
Alexander Afanasyev34a37632015-01-16 17:37:36 -0800844 registerPibImpl(*aliases.begin(), aliases, [] (const std::string& locator) {
Alexander Afanasyev07113802015-01-15 19:14:36 -0800845 return unique_ptr<SecPublicInfo>(new PibType(locator));
846 });
847}
848
849template<class TpmType>
850inline void
Alexander Afanasyev34a37632015-01-16 17:37:36 -0800851KeyChain::registerTpm(std::initializer_list<std::string> aliases)
Alexander Afanasyev07113802015-01-15 19:14:36 -0800852{
Alexander Afanasyev34a37632015-01-16 17:37:36 -0800853 registerTpmImpl(*aliases.begin(), aliases, [] (const std::string& locator) {
Alexander Afanasyev07113802015-01-15 19:14:36 -0800854 return unique_ptr<SecTpm>(new TpmType(locator));
855 });
856}
857
858/**
859 * \brief Register SecPib class in ndn-cxx KeyChain
860 *
861 * This macro should be placed once in the implementation file of the
862 * SecPib type within the namespace where the type is declared.
863 */
Alexander Afanasyev34a37632015-01-16 17:37:36 -0800864#define NDN_CXX_KEYCHAIN_REGISTER_PIB(PibType, ...) \
Alexander Afanasyev07113802015-01-15 19:14:36 -0800865static class NdnCxxAuto ## PibType ## PibRegistrationClass \
866{ \
867public: \
868 NdnCxxAuto ## PibType ## PibRegistrationClass() \
869 { \
870 ::ndn::KeyChain::registerPib<PibType>({__VA_ARGS__}); \
871 } \
872} ndnCxxAuto ## PibType ## PibRegistrationVariable
873
874/**
875 * \brief Register SecTpm class in ndn-cxx KeyChain
876 *
877 * This macro should be placed once in the implementation file of the
878 * SecTpm type within the namespace where the type is declared.
879 */
Alexander Afanasyev34a37632015-01-16 17:37:36 -0800880#define NDN_CXX_KEYCHAIN_REGISTER_TPM(TpmType, ...) \
Alexander Afanasyev07113802015-01-15 19:14:36 -0800881static class NdnCxxAuto ## TpmType ## TpmRegistrationClass \
882{ \
883public: \
884 NdnCxxAuto ## TpmType ## TpmRegistrationClass() \
885 { \
886 ::ndn::KeyChain::registerTpm<TpmType>({__VA_ARGS__}); \
887 } \
888} ndnCxxAuto ## TpmType ## TpmRegistrationVariable
889
Yingdi Yu6ab67812014-11-27 15:00:34 -0800890} // namespace ndn
Jeff Thompson47c93cf2013-08-09 00:38:48 -0700891
Alexander Afanasyev766cea72014-04-24 19:16:42 -0700892#endif // NDN_SECURITY_KEY_CHAIN_HPP