blob: bdf3514866c36e03efda6e56d3d54c88bd21ac11 [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
91 /**
92 * @brief Constructor to create KeyChain with default PIB and TPM
93 *
94 * Default PIB and TPM are platform-dependent and can be overriden system-wide or on
95 * per-use basis.
96 *
97 * @todo Add detailed description about config file behavior here
98 */
99 KeyChain();
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700100
Yingdi Yu41546342014-11-30 23:37:53 -0800101 /**
102 * @brief KeyChain constructor
103 *
104 * @sa http://redmine.named-data.net/issues/2260
105 *
106 * @param pibLocator
107 * @param tpmLocator
108 * @param allowReset if true, the PIB will be reset when the supplied tpmLocator
109 * mismatches the one in PIB
110 */
111 KeyChain(const std::string& pibLocator,
112 const std::string& tpmLocator,
113 bool allowReset = false);
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700114
115 virtual
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700116 ~KeyChain();
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700117
Yingdi Yube4150e2014-02-18 13:02:46 -0800118 /**
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700119 * @brief Create an identity by creating a pair of Key-Signing-Key (KSK) for this identity and a
120 * self-signed certificate of the KSK.
Yingdi Yube4150e2014-02-18 13:02:46 -0800121 *
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800122 * @param identityName The name of the identity.
Yingdi Yu7036ce22014-06-19 18:53:37 -0700123 * @param params The key parameter if a key needs to be generated for the identity.
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800124 * @return The name of the default certificate of the identity.
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800125 */
Yingdi Yu7036ce22014-06-19 18:53:37 -0700126 Name
127 createIdentity(const Name& identityName, const KeyParams& params = DEFAULT_KEY_PARAMS);
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700128
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800129 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800130 * @brief Generate a pair of RSA keys for the specified identity.
131 *
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800132 * @param identityName The name of the identity.
133 * @param isKsk true for generating a Key-Signing-Key (KSK), false for a Data-Signing-Key (KSK).
134 * @param keySize The size of the key.
135 * @return The generated key name.
136 */
Yingdi Yu41546342014-11-30 23:37:53 -0800137 Name
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700138 generateRsaKeyPair(const Name& identityName, bool isKsk = false, uint32_t keySize = 2048);
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700139
Yingdi Yu41546342014-11-30 23:37:53 -0800140 Name
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700141 generateEcdsaKeyPair(const Name& identityName, bool isKsk = false, uint32_t keySize = 256);
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800142 /**
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700143 * @brief Generate a pair of RSA keys for the specified identity and set it as default key for
144 * the identity.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800145 *
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800146 * @param identityName The name of the identity.
147 * @param isKsk true for generating a Key-Signing-Key (KSK), false for a Data-Signing-Key (KSK).
148 * @param keySize The size of the key.
149 * @return The generated key name.
150 */
Yingdi Yu7036ce22014-06-19 18:53:37 -0700151 Name
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700152 generateRsaKeyPairAsDefault(const Name& identityName, bool isKsk = false,
153 uint32_t keySize = 2048);
154
155 Name
156 generateEcdsaKeyPairAsDefault(const Name& identityName, bool isKsk, uint32_t keySize = 256);
Jeff Thompson79a2d5d2013-09-27 14:32:23 -0700157
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800158 /**
Yingdi Yuc55680b2014-02-26 12:31:35 -0800159 * @brief prepare an unsigned identity certificate
160 *
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700161 * @param keyName Key name, e.g., `/<identity_name>/ksk-123456`.
Yingdi Yuc55680b2014-02-26 12:31:35 -0800162 * @param signingIdentity The signing identity.
163 * @param notBefore Refer to IdentityCertificate.
164 * @param notAfter Refer to IdentityCertificate.
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700165 * @param subjectDescription Refer to IdentityCertificate.
Yingdi Yu0eb5d722014-06-10 15:06:25 -0700166 * @param certPrefix Prefix before `KEY` component. By default, KeyChain will infer the
167 * certificate name according to the relation between the signingIdentity and
168 * the subject identity. If signingIdentity is a prefix of the subject identity,
169 * `KEY` will be inserted after the signingIdentity, otherwise `KEY` is inserted
170 * after subject identity (i.e., before `ksk-....`).
Yingdi Yuc55680b2014-02-26 12:31:35 -0800171 * @return IdentityCertificate.
172 */
173 shared_ptr<IdentityCertificate>
174 prepareUnsignedIdentityCertificate(const Name& keyName,
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700175 const Name& signingIdentity,
176 const time::system_clock::TimePoint& notBefore,
177 const time::system_clock::TimePoint& notAfter,
Yingdi Yu0eb5d722014-06-10 15:06:25 -0700178 const std::vector<CertificateSubjectDescription>& subjectDescription,
179 const Name& certPrefix = DEFAULT_PREFIX);
180
181 /**
182 * @brief prepare an unsigned identity certificate
183 *
184 * @param keyName Key name, e.g., `/<identity_name>/ksk-123456`.
185 * @param publicKey Public key to sign.
186 * @param signingIdentity The signing identity.
187 * @param notBefore Refer to IdentityCertificate.
188 * @param notAfter Refer to IdentityCertificate.
189 * @param subjectDescription Refer to IdentityCertificate.
190 * @param certPrefix Prefix before `KEY` component. By default, KeyChain will infer the
191 * certificate name according to the relation between the signingIdentity and
192 * the subject identity. If signingIdentity is a prefix of the subject identity,
193 * `KEY` will be inserted after the signingIdentity, otherwise `KEY` is inserted
194 * after subject identity (i.e., before `ksk-....`).
195 * @return IdentityCertificate.
196 */
197 shared_ptr<IdentityCertificate>
198 prepareUnsignedIdentityCertificate(const Name& keyName,
199 const PublicKey& publicKey,
200 const Name& signingIdentity,
201 const time::system_clock::TimePoint& notBefore,
202 const time::system_clock::TimePoint& notAfter,
203 const std::vector<CertificateSubjectDescription>& subjectDescription,
204 const Name& certPrefix = DEFAULT_PREFIX);
Yingdi Yuc55680b2014-02-26 12:31:35 -0800205
206 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800207 * @brief Sign packet with default identity
208 *
Yingdi Yu60bd7082014-03-25 18:18:54 -0700209 * On return, signatureInfo and signatureValue in the packet are set.
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700210 * If default identity does not exist,
Yingdi Yu60bd7082014-03-25 18:18:54 -0700211 * a temporary identity will be created and set as default.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800212 *
213 * @param packet The packet to be signed
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800214 */
Yingdi Yu2e57a582014-02-20 23:34:43 -0800215 template<typename T>
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800216 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700217 sign(T& packet);
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700218
Jeff Thompson47c93cf2013-08-09 00:38:48 -0700219 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800220 * @brief Sign packet with a particular certificate.
221 *
222 * @param packet The packet to be signed.
223 * @param certificateName The certificate name of the key to use for signing.
224 * @throws SecPublicInfo::Error if certificate does not exist.
Jeff Thompson3c73da42013-08-12 11:19:05 -0700225 */
Yingdi Yu2e57a582014-02-20 23:34:43 -0800226 template<typename T>
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700227 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700228 sign(T& packet, const Name& certificateName);
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700229
Jeff Thompson29ce3102013-09-27 11:47:48 -0700230 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800231 * @brief Sign the byte array using a particular certificate.
232 *
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700233 * @param buffer The byte array to be signed.
234 * @param bufferLength the length of buffer.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800235 * @param certificateName The certificate name of the signing key.
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700236 * @return The Signature.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800237 * @throws SecPublicInfo::Error if certificate does not exist.
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700238 */
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800239 Signature
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700240 sign(const uint8_t* buffer, size_t bufferLength, const Name& certificateName);
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700241
242 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800243 * @brief Sign packet using the default certificate of a particular identity.
244 *
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700245 * If there is no default certificate of that identity, this method will create a self-signed
246 * certificate.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800247 *
248 * @param packet The packet to be signed.
249 * @param identityName The signing identity name.
Jeff Thompson29ce3102013-09-27 11:47:48 -0700250 */
Yingdi Yu2e57a582014-02-20 23:34:43 -0800251 template<typename T>
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700252 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700253 signByIdentity(T& packet, const Name& identityName);
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700254
Jeff Thompson3c73da42013-08-12 11:19:05 -0700255 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800256 * @brief Sign the byte array using the default certificate of a particular identity.
257 *
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700258 * @param buffer The byte array to be signed.
259 * @param bufferLength the length of buffer.
260 * @param identityName The identity name.
261 * @return The Signature.
262 */
Yingdi Yu7036ce22014-06-19 18:53:37 -0700263 Signature
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700264 signByIdentity(const uint8_t* buffer, size_t bufferLength, const Name& identityName);
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700265
266 /**
Yingdi Yu6ab67812014-11-27 15:00:34 -0800267 * @brief Set Sha256 weak signature for @p data
Yingdi Yu21157162014-02-28 13:02:34 -0800268 */
Yingdi Yu7036ce22014-06-19 18:53:37 -0700269 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700270 signWithSha256(Data& data);
Yingdi Yu21157162014-02-28 13:02:34 -0800271
272 /**
Yingdi Yu6ab67812014-11-27 15:00:34 -0800273 * @brief Set Sha256 weak signature for @p interest
274 */
275 void
276 signWithSha256(Interest& interest);
277
278 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800279 * @brief Generate a self-signed certificate for a public key.
280 *
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700281 * @param keyName The name of the public key
282 * @return The generated certificate, shared_ptr<IdentityCertificate>() if selfSign fails
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800283 */
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800284 shared_ptr<IdentityCertificate>
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700285 selfSign(const Name& keyName);
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800286
287 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800288 * @brief Self-sign the supplied identity certificate.
289 *
290 * @param cert The supplied cert.
291 * @throws SecTpm::Error if the private key does not exist.
Jeff Thompson8efe5ad2013-08-20 17:36:38 -0700292 */
Jeff Thompson2ce8f492013-09-17 18:01:25 -0700293 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700294 selfSign(IdentityCertificate& cert);
Yingdi Yu31b4af22014-01-14 14:13:00 -0800295
Yingdi Yu2e57a582014-02-20 23:34:43 -0800296 /**
297 * @brief delete a certificate.
298 *
Yingdi Yu2e57a582014-02-20 23:34:43 -0800299 * @param certificateName The certificate to be deleted.
Yingdi Yu6147ef42014-12-08 17:48:32 -0800300 * @throws KeyChain::Error if certificate cannot be deleted.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800301 */
Yingdi Yu7036ce22014-06-19 18:53:37 -0700302 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700303 deleteCertificate(const Name& certificateName);
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800304
Yingdi Yu2e57a582014-02-20 23:34:43 -0800305 /**
306 * @brief delete a key.
307 *
Yingdi Yu2e57a582014-02-20 23:34:43 -0800308 * @param keyName The key to be deleted.
Yingdi Yu6147ef42014-12-08 17:48:32 -0800309 * @throws KeyChain::Error if key cannot be deleted.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800310 */
Yingdi Yu7036ce22014-06-19 18:53:37 -0700311 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700312 deleteKey(const Name& keyName);
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800313
Yingdi Yu2e57a582014-02-20 23:34:43 -0800314 /**
315 * @brief delete an identity.
316 *
Yingdi Yu2e57a582014-02-20 23:34:43 -0800317 * @param identity The identity to be deleted.
Yingdi Yu6147ef42014-12-08 17:48:32 -0800318 * @throws KeyChain::Error if identity cannot be deleted.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800319 */
Yingdi Yu7036ce22014-06-19 18:53:37 -0700320 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700321 deleteIdentity(const Name& identity);
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800322
Yingdi Yu2e57a582014-02-20 23:34:43 -0800323 /**
324 * @brief export an identity.
325 *
326 * @param identity The identity to export.
327 * @param passwordStr The password to secure the private key.
Yingdi Yu64c3fb42014-02-26 17:30:04 -0800328 * @return The encoded export data.
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700329 * @throws SecPublicInfo::Error if anything goes wrong in exporting.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800330 */
Yingdi Yu64c3fb42014-02-26 17:30:04 -0800331 shared_ptr<SecuredBag>
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700332 exportIdentity(const Name& identity, const std::string& passwordStr);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800333
Yingdi Yu2e57a582014-02-20 23:34:43 -0800334 /**
335 * @brief import an identity.
336 *
Yingdi Yu64c3fb42014-02-26 17:30:04 -0800337 * @param securedBag The encoded import data.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800338 * @param passwordStr The password to secure the private key.
339 */
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800340 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700341 importIdentity(const SecuredBag& securedBag, const std::string& passwordStr);
342
343 SecPublicInfo&
344 getPib()
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800345 {
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700346 return *m_pib;
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800347 }
348
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700349 const SecPublicInfo&
350 getPib() const
351 {
352 return *m_pib;
353 }
354
355 SecTpm&
356 getTpm()
357 {
358 return *m_tpm;
359 }
360
361 const SecTpm&
362 getTpm() const
363 {
364 return *m_tpm;
365 }
366
367 /*******************************
368 * Wrapper of SecPublicInfo *
369 *******************************/
370 bool
371 doesIdentityExist(const Name& identityName) const
372 {
373 return m_pib->doesIdentityExist(identityName);
374 }
375
376 void
377 addIdentity(const Name& identityName)
378 {
379 return m_pib->addIdentity(identityName);
380 }
381
382 bool
383 doesPublicKeyExist(const Name& keyName) const
384 {
385 return m_pib->doesPublicKeyExist(keyName);
386 }
387
388 void
389 addPublicKey(const Name& keyName, KeyType keyType, const PublicKey& publicKeyDer)
390 {
Yingdi Yu41546342014-11-30 23:37:53 -0800391 return m_pib->addKey(keyName, publicKeyDer);
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700392 }
393
Yingdi Yu7036ce22014-06-19 18:53:37 -0700394 void
395 addKey(const Name& keyName, const PublicKey& publicKeyDer)
396 {
397 return m_pib->addKey(keyName, publicKeyDer);
398 }
399
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700400 shared_ptr<PublicKey>
401 getPublicKey(const Name& keyName) const
402 {
403 return m_pib->getPublicKey(keyName);
404 }
405
406 bool
407 doesCertificateExist(const Name& certificateName) const
408 {
409 return m_pib->doesCertificateExist(certificateName);
410 }
411
412 void
413 addCertificate(const IdentityCertificate& certificate)
414 {
415 return m_pib->addCertificate(certificate);
416 }
417
418 shared_ptr<IdentityCertificate>
419 getCertificate(const Name& certificateName) const
420 {
421 return m_pib->getCertificate(certificateName);
422 }
423
424 Name
425 getDefaultIdentity() const
426 {
427 return m_pib->getDefaultIdentity();
428 }
429
430 Name
431 getDefaultKeyNameForIdentity(const Name& identityName) const
432 {
433 return m_pib->getDefaultKeyNameForIdentity(identityName);
434 }
435
436 Name
437 getDefaultCertificateNameForKey(const Name& keyName) const
438 {
439 return m_pib->getDefaultCertificateNameForKey(keyName);
440 }
441
442 void
443 getAllIdentities(std::vector<Name>& nameList, bool isDefault) const
444 {
445 return m_pib->getAllIdentities(nameList, isDefault);
446 }
447
448 void
449 getAllKeyNames(std::vector<Name>& nameList, bool isDefault) const
450 {
451 return m_pib->getAllKeyNames(nameList, isDefault);
452 }
453
454 void
455 getAllKeyNamesOfIdentity(const Name& identity, std::vector<Name>& nameList, bool isDefault) const
456 {
457 return m_pib->getAllKeyNamesOfIdentity(identity, nameList, isDefault);
458 }
459
460 void
461 getAllCertificateNames(std::vector<Name>& nameList, bool isDefault) const
462 {
463 return m_pib->getAllCertificateNames(nameList, isDefault);
464 }
465
466 void
467 getAllCertificateNamesOfKey(const Name& keyName,
468 std::vector<Name>& nameList,
469 bool isDefault) const
470 {
471 return m_pib->getAllCertificateNamesOfKey(keyName, nameList, isDefault);
472 }
473
474 void
475 deleteCertificateInfo(const Name& certificateName)
476 {
477 return m_pib->deleteCertificateInfo(certificateName);
478 }
479
480 void
481 deletePublicKeyInfo(const Name& keyName)
482 {
483 return m_pib->deletePublicKeyInfo(keyName);
484 }
485
486 void
487 deleteIdentityInfo(const Name& identity)
488 {
489 return m_pib->deleteIdentityInfo(identity);
490 }
491
492 void
493 setDefaultIdentity(const Name& identityName)
494 {
495 return m_pib->setDefaultIdentity(identityName);
496 }
497
498 void
499 setDefaultKeyNameForIdentity(const Name& keyName)
500 {
501 return m_pib->setDefaultKeyNameForIdentity(keyName);
502 }
503
504 void
505 setDefaultCertificateNameForKey(const Name& certificateName)
506 {
507 return m_pib->setDefaultCertificateNameForKey(certificateName);
508 }
509
510 Name
511 getNewKeyName(const Name& identityName, bool useKsk)
512 {
513 return m_pib->getNewKeyName(identityName, useKsk);
514 }
515
516 Name
517 getDefaultCertificateNameForIdentity(const Name& identityName) const
518 {
519 return m_pib->getDefaultCertificateNameForIdentity(identityName);
520 }
521
522 Name
523 getDefaultCertificateName() const
524 {
525 return m_pib->getDefaultCertificateName();
526 }
527
528 void
529 addCertificateAsKeyDefault(const IdentityCertificate& certificate)
530 {
531 return m_pib->addCertificateAsKeyDefault(certificate);
532 }
533
534 void
535 addCertificateAsIdentityDefault(const IdentityCertificate& certificate)
536 {
537 return m_pib->addCertificateAsIdentityDefault(certificate);
538 }
539
540 void
541 addCertificateAsSystemDefault(const IdentityCertificate& certificate)
542 {
543 return m_pib->addCertificateAsSystemDefault(certificate);
544 }
545
546 shared_ptr<IdentityCertificate>
547 getDefaultCertificate() const
548 {
Alexander Afanasyevaab79662014-07-07 17:35:34 -0700549 if (!static_cast<bool>(m_pib->getDefaultCertificate()))
550 const_cast<KeyChain*>(this)->setDefaultCertificateInternal();
551
552 return m_pib->getDefaultCertificate();
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700553 }
554
555 void
556 refreshDefaultCertificate()
557 {
558 return m_pib->refreshDefaultCertificate();
559 }
560
561 /*******************************
562 * Wrapper of SecTpm *
563 *******************************/
564
565 void
566 setTpmPassword(const uint8_t* password, size_t passwordLength)
567 {
568 return m_tpm->setTpmPassword(password, passwordLength);
569 }
570
571 void
572 resetTpmPassword()
573 {
574 return m_tpm->resetTpmPassword();
575 }
576
577 void
578 setInTerminal(bool inTerminal)
579 {
580 return m_tpm->setInTerminal(inTerminal);
581 }
582
583 bool
584 getInTerminal() const
585 {
586 return m_tpm->getInTerminal();
587 }
588
589 bool
590 isLocked() const
591 {
592 return m_tpm->isLocked();
593 }
594
595 bool
596 unlockTpm(const char* password, size_t passwordLength, bool usePassword)
597 {
598 return m_tpm->unlockTpm(password, passwordLength, usePassword);
599 }
600
601 void
Yingdi Yu7036ce22014-06-19 18:53:37 -0700602 generateKeyPairInTpm(const Name& keyName, const KeyParams& params)
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700603 {
Yingdi Yu7036ce22014-06-19 18:53:37 -0700604 return m_tpm->generateKeyPairInTpm(keyName, params);
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700605 }
606
607 void
608 deleteKeyPairInTpm(const Name& keyName)
609 {
610 return m_tpm->deleteKeyPairInTpm(keyName);
611 }
612
613 shared_ptr<PublicKey>
614 getPublicKeyFromTpm(const Name& keyName) const
615 {
616 return m_tpm->getPublicKeyFromTpm(keyName);
617 }
618
619 Block
620 signInTpm(const uint8_t* data, size_t dataLength,
621 const Name& keyName,
622 DigestAlgorithm digestAlgorithm)
623 {
624 return m_tpm->signInTpm(data, dataLength, keyName, digestAlgorithm);
625 }
626
627 ConstBufferPtr
628 decryptInTpm(const uint8_t* data, size_t dataLength, const Name& keyName, bool isSymmetric)
629 {
630 return m_tpm->decryptInTpm(data, dataLength, keyName, isSymmetric);
631 }
632
633 ConstBufferPtr
634 encryptInTpm(const uint8_t* data, size_t dataLength, const Name& keyName, bool isSymmetric)
635 {
636 return m_tpm->encryptInTpm(data, dataLength, keyName, isSymmetric);
637 }
638
639 void
Yingdi Yu7036ce22014-06-19 18:53:37 -0700640 generateSymmetricKeyInTpm(const Name& keyName, const KeyParams& params)
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700641 {
Yingdi Yu7036ce22014-06-19 18:53:37 -0700642 return m_tpm->generateSymmetricKeyInTpm(keyName, params);
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700643 }
644
645 bool
646 doesKeyExistInTpm(const Name& keyName, KeyClass keyClass) const
647 {
648 return m_tpm->doesKeyExistInTpm(keyName, keyClass);
649 }
650
651 bool
652 generateRandomBlock(uint8_t* res, size_t size) const
653 {
654 return m_tpm->generateRandomBlock(res, size);
655 }
656
657 void
658 addAppToAcl(const Name& keyName, KeyClass keyClass, const std::string& appPath, AclType acl)
659 {
660 return m_tpm->addAppToAcl(keyName, keyClass, appPath, acl);
661 }
662
663 ConstBufferPtr
664 exportPrivateKeyPkcs5FromTpm(const Name& keyName, const std::string& password)
665 {
666 return m_tpm->exportPrivateKeyPkcs5FromTpm(keyName, password);
667 }
668
669 bool
670 importPrivateKeyPkcs5IntoTpm(const Name& keyName,
671 const uint8_t* buf, size_t size,
672 const std::string& password)
673 {
674 return m_tpm->importPrivateKeyPkcs5IntoTpm(keyName, buf, size, password);
675 }
Jeff Thompson8efe5ad2013-08-20 17:36:38 -0700676
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800677private:
Yingdi Yu41546342014-11-30 23:37:53 -0800678 void
Alexander Afanasyev07113802015-01-15 19:14:36 -0800679 initialize(const std::string& pibLocatorUri,
680 const std::string& tpmLocatorUri,
Yingdi Yu41546342014-11-30 23:37:53 -0800681 bool needReset);
682
Yingdi Yu2e57a582014-02-20 23:34:43 -0800683 /**
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700684 * @brief Determine signature type
685 *
686 * An empty pointer will be returned if there is no valid signature.
687 */
Yingdi Yu4a557052014-07-09 16:40:37 -0700688 shared_ptr<Signature>
689 determineSignatureWithPublicKey(const KeyLocator& keyLocator,
690 KeyType keyType,
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700691 DigestAlgorithm digestAlgorithm = DIGEST_ALGORITHM_SHA256);
692
693 /**
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700694 * @brief Set default certificate if it is not initialized
695 */
696 void
697 setDefaultCertificateInternal();
698
699 /**
700 * @brief Sign a packet using a pariticular certificate.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800701 *
702 * @param packet The packet to be signed.
703 * @param certificate The signing certificate.
704 */
705 template<typename T>
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800706 void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700707 sign(T& packet, const IdentityCertificate& certificate);
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800708
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800709 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800710 * @brief Generate a key pair for the specified identity.
711 *
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800712 * @param identityName The name of the specified identity.
713 * @param isKsk true for generating a Key-Signing-Key (KSK), false for a Data-Signing-Key (KSK).
Yingdi Yu7036ce22014-06-19 18:53:37 -0700714 * @param params The parameter of the key.
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800715 * @return The name of the generated key.
716 */
Yingdi Yu7036ce22014-06-19 18:53:37 -0700717 Name
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700718 generateKeyPair(const Name& identityName, bool isKsk = false,
Yingdi Yu7036ce22014-06-19 18:53:37 -0700719 const KeyParams& params = DEFAULT_KEY_PARAMS);
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800720
Yingdi Yu8726f652014-01-23 10:35:12 -0800721 /**
Yingdi Yu2e57a582014-02-20 23:34:43 -0800722 * @brief Sign the data using a particular key.
723 *
724 * @param data Reference to the data packet.
725 * @param signature Signature to be added.
Yingdi Yu8726f652014-01-23 10:35:12 -0800726 * @param keyName The name of the signing key.
727 * @param digestAlgorithm the digest algorithm.
728 * @throws Tpm::Error
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700729 */
Yingdi Yu7036ce22014-06-19 18:53:37 -0700730 void
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700731 signPacketWrapper(Data& data, const Signature& signature,
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700732 const Name& keyName, DigestAlgorithm digestAlgorithm);
Yingdi Yu8726f652014-01-23 10:35:12 -0800733
Yingdi Yu2e57a582014-02-20 23:34:43 -0800734 /**
735 * @brief Sign the interest using a particular key.
736 *
737 * @param interest Reference to the interest packet.
738 * @param signature Signature to be added.
739 * @param keyName The name of the signing key.
740 * @param digestAlgorithm the digest algorithm.
741 * @throws Tpm::Error
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -0700742 */
Yingdi Yu7036ce22014-06-19 18:53:37 -0700743 void
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700744 signPacketWrapper(Interest& interest, const Signature& signature,
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700745 const Name& keyName, DigestAlgorithm digestAlgorithm);
Yingdi Yu2e57a582014-02-20 23:34:43 -0800746
Alexander Afanasyev07113802015-01-15 19:14:36 -0800747 static void
Alexander Afanasyev34a37632015-01-16 17:37:36 -0800748 registerPibImpl(const std::string& canonicalName,
749 std::initializer_list<std::string> aliases, PibCreateFunc createFunc);
Alexander Afanasyev07113802015-01-15 19:14:36 -0800750
751 static void
Alexander Afanasyev34a37632015-01-16 17:37:36 -0800752 registerTpmImpl(const std::string& canonicalName,
753 std::initializer_list<std::string> aliases, TpmCreateFunc createFunc);
Alexander Afanasyev07113802015-01-15 19:14:36 -0800754
Yingdi Yu41546342014-11-30 23:37:53 -0800755public:
756 static const Name DEFAULT_PREFIX;
757 // RsaKeyParams is set to be default for backward compatibility.
758 static const RsaKeyParams DEFAULT_KEY_PARAMS;
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700759
760private:
Alexander Afanasyev07113802015-01-15 19:14:36 -0800761 std::unique_ptr<SecPublicInfo> m_pib;
762 std::unique_ptr<SecTpm> m_tpm;
Yingdi Yu0f5fb692014-06-10 12:07:28 -0700763 time::milliseconds m_lastTimestamp;
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700764};
765
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700766template<typename T>
767void
768KeyChain::sign(T& packet)
769{
Alexander Afanasyevaab79662014-07-07 17:35:34 -0700770 if (!static_cast<bool>(m_pib->getDefaultCertificate()))
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700771 setDefaultCertificateInternal();
772
Alexander Afanasyevaab79662014-07-07 17:35:34 -0700773 sign(packet, *m_pib->getDefaultCertificate());
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700774}
775
776template<typename T>
777void
778KeyChain::sign(T& packet, const Name& certificateName)
779{
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700780 shared_ptr<IdentityCertificate> certificate = m_pib->getCertificate(certificateName);
781 sign(packet, *certificate);
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700782}
783
784template<typename T>
785void
786KeyChain::signByIdentity(T& packet, const Name& identityName)
787{
788 Name signingCertificateName;
789 try
790 {
791 signingCertificateName = m_pib->getDefaultCertificateNameForIdentity(identityName);
792 }
793 catch (SecPublicInfo::Error& e)
794 {
795 signingCertificateName = createIdentity(identityName);
796 // Ideally, no exception will be thrown out, unless something goes wrong in the TPM, which
797 // is a fatal error.
798 }
799
800 // We either get or create the signing certificate, sign packet! (no exception unless fatal
801 // error in TPM)
802 sign(packet, signingCertificateName);
803}
804
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700805template<typename T>
806void
807KeyChain::sign(T& packet, const IdentityCertificate& certificate)
808{
Yingdi Yu4a557052014-07-09 16:40:37 -0700809 KeyLocator keyLocator(certificate.getName().getPrefix(-1));
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700810
Yingdi Yu4a557052014-07-09 16:40:37 -0700811 shared_ptr<Signature> signature =
812 determineSignatureWithPublicKey(keyLocator, certificate.getPublicKeyInfo().getKeyType());
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700813
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700814 if (!static_cast<bool>(signature))
815 throw SecPublicInfo::Error("unknown key type!");
816
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700817 signPacketWrapper(packet, *signature,
818 certificate.getPublicKeyName(),
819 DIGEST_ALGORITHM_SHA256);
820
821 return;
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700822}
823
Alexander Afanasyev07113802015-01-15 19:14:36 -0800824template<class PibType>
825inline void
Alexander Afanasyev34a37632015-01-16 17:37:36 -0800826KeyChain::registerPib(std::initializer_list<std::string> aliases)
Alexander Afanasyev07113802015-01-15 19:14:36 -0800827{
Alexander Afanasyev34a37632015-01-16 17:37:36 -0800828 registerPibImpl(*aliases.begin(), aliases, [] (const std::string& locator) {
Alexander Afanasyev07113802015-01-15 19:14:36 -0800829 return unique_ptr<SecPublicInfo>(new PibType(locator));
830 });
831}
832
833template<class TpmType>
834inline void
Alexander Afanasyev34a37632015-01-16 17:37:36 -0800835KeyChain::registerTpm(std::initializer_list<std::string> aliases)
Alexander Afanasyev07113802015-01-15 19:14:36 -0800836{
Alexander Afanasyev34a37632015-01-16 17:37:36 -0800837 registerTpmImpl(*aliases.begin(), aliases, [] (const std::string& locator) {
Alexander Afanasyev07113802015-01-15 19:14:36 -0800838 return unique_ptr<SecTpm>(new TpmType(locator));
839 });
840}
841
842/**
843 * \brief Register SecPib class in ndn-cxx KeyChain
844 *
845 * This macro should be placed once in the implementation file of the
846 * SecPib type within the namespace where the type is declared.
847 */
Alexander Afanasyev34a37632015-01-16 17:37:36 -0800848#define NDN_CXX_KEYCHAIN_REGISTER_PIB(PibType, ...) \
Alexander Afanasyev07113802015-01-15 19:14:36 -0800849static class NdnCxxAuto ## PibType ## PibRegistrationClass \
850{ \
851public: \
852 NdnCxxAuto ## PibType ## PibRegistrationClass() \
853 { \
854 ::ndn::KeyChain::registerPib<PibType>({__VA_ARGS__}); \
855 } \
856} ndnCxxAuto ## PibType ## PibRegistrationVariable
857
858/**
859 * \brief Register SecTpm class in ndn-cxx KeyChain
860 *
861 * This macro should be placed once in the implementation file of the
862 * SecTpm type within the namespace where the type is declared.
863 */
Alexander Afanasyev34a37632015-01-16 17:37:36 -0800864#define NDN_CXX_KEYCHAIN_REGISTER_TPM(TpmType, ...) \
Alexander Afanasyev07113802015-01-15 19:14:36 -0800865static class NdnCxxAuto ## TpmType ## TpmRegistrationClass \
866{ \
867public: \
868 NdnCxxAuto ## TpmType ## TpmRegistrationClass() \
869 { \
870 ::ndn::KeyChain::registerTpm<TpmType>({__VA_ARGS__}); \
871 } \
872} ndnCxxAuto ## TpmType ## TpmRegistrationVariable
873
Yingdi Yu6ab67812014-11-27 15:00:34 -0800874} // namespace ndn
Jeff Thompson47c93cf2013-08-09 00:38:48 -0700875
Alexander Afanasyev766cea72014-04-24 19:16:42 -0700876#endif // NDN_SECURITY_KEY_CHAIN_HPP