blob: 758c2f56274503f460fba7aa083837d85cb6b4ac [file] [log] [blame]
Alexander Afanasyevc169a812014-05-20 20:37:29 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Yingdi Yuf56c68f2014-04-24 21:50:13 -07002/**
Alexander Afanasyevc169a812014-05-20 20:37:29 -04003 * Copyright (c) 2013-2014 Regents of the University of California.
Yingdi Yuf56c68f2014-04-24 21:50:13 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
Yingdi Yuf56c68f2014-04-24 21:50:13 -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.
Yingdi Yuf56c68f2014-04-24 21:50:13 -070020 *
21 * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
22 */
23
24#include "key-chain.hpp"
25
26#include "sec-public-info-sqlite3.hpp"
27#include "sec-tpm-file.hpp"
28
29#ifdef NDN_CXX_HAVE_OSX_SECURITY
30#include "sec-tpm-osx.hpp"
31#endif
32
33#include "../util/random.hpp"
34#include "../util/config-file.hpp"
35
36namespace ndn {
37
Yingdi Yu0eb5d722014-06-10 15:06:25 -070038// Use a GUID as a magic number of KeyChain::DEFAULT_PREFIX identifier
39const Name KeyChain::DEFAULT_PREFIX("/723821fd-f534-44b3-80d9-44bf5f58bbbb");
40
Yingdi Yu7036ce22014-06-19 18:53:37 -070041const RsaKeyParams KeyChain::DEFAULT_KEY_PARAMS;
42
Yingdi Yuf56c68f2014-04-24 21:50:13 -070043KeyChain::KeyChain()
Yingdi Yu41546342014-11-30 23:37:53 -080044 : m_pib(nullptr)
45 , m_tpm(nullptr)
Yingdi Yu0f5fb692014-06-10 12:07:28 -070046 , m_lastTimestamp(time::toUnixTimestamp(time::system_clock::now()))
Yingdi Yuf56c68f2014-04-24 21:50:13 -070047{
Yingdi Yu41546342014-11-30 23:37:53 -080048 initialize("", "", false);
49}
Yingdi Yuf56c68f2014-04-24 21:50:13 -070050
Yingdi Yu41546342014-11-30 23:37:53 -080051template<class T>
52inline
53KeyChain::KeyChain(T traits)
54 : m_pib(new typename T::Pib)
55 , m_tpm(nullptr)
56 , m_lastTimestamp(time::toUnixTimestamp(time::system_clock::now()))
57{
58 initialize(T::Pib::SCHEME, T::Tpm::SCHEME, false);
Yingdi Yuf56c68f2014-04-24 21:50:13 -070059}
60
61KeyChain::KeyChain(const std::string& pibName,
Yingdi Yu41546342014-11-30 23:37:53 -080062 const std::string& tpmName,
63 bool allowReset)
64 : m_pib(nullptr)
65 , m_tpm(nullptr)
Yingdi Yu0f5fb692014-06-10 12:07:28 -070066 , m_lastTimestamp(time::toUnixTimestamp(time::system_clock::now()))
Yingdi Yuf56c68f2014-04-24 21:50:13 -070067{
Yingdi Yu41546342014-11-30 23:37:53 -080068 std::string pibLocator;
69 std::string tpmLocator;
Yingdi Yuf56c68f2014-04-24 21:50:13 -070070
71 if (tpmName == "file")
Yingdi Yu41546342014-11-30 23:37:53 -080072 tpmLocator = SecTpmFile::SCHEME;
Yingdi Yuf56c68f2014-04-24 21:50:13 -070073#if defined(NDN_CXX_HAVE_OSX_SECURITY)
74 else if (tpmName == "osx-keychain")
Yingdi Yu41546342014-11-30 23:37:53 -080075 tpmLocator = SecTpmOsx::SCHEME;
Yingdi Yuf56c68f2014-04-24 21:50:13 -070076#endif //NDN_CXX_HAVE_OSX_SECURITY
77 else
Yingdi Yu41546342014-11-30 23:37:53 -080078 tpmLocator = tpmName;
79
80 if (pibName == "sqlite3")
81 pibLocator = SecPublicInfoSqlite3::SCHEME;
82 else
83 pibLocator = pibName;
84
85 initialize(pibLocator, tpmLocator, allowReset);
Yingdi Yuf56c68f2014-04-24 21:50:13 -070086}
87
Yingdi Yu5ec0ee32014-06-24 16:26:09 -070088KeyChain::~KeyChain()
89{
Yingdi Yu41546342014-11-30 23:37:53 -080090 if (m_pib != nullptr)
Yingdi Yu5ec0ee32014-06-24 16:26:09 -070091 delete m_pib;
92
Yingdi Yu41546342014-11-30 23:37:53 -080093 if (m_tpm != nullptr)
Yingdi Yu5ec0ee32014-06-24 16:26:09 -070094 delete m_tpm;
95}
96
Yingdi Yu41546342014-11-30 23:37:53 -080097void
98KeyChain::initialize(const std::string& pib,
99 const std::string& tpm,
100 bool allowReset)
101{
102 ConfigFile config;
103 const ConfigFile::Parsed& parsed = config.getParsedConfiguration();
104
105 std::string defaultTpmLocator;
106 try {
107 defaultTpmLocator = parsed.get<std::string>("tpm");
108 }
109 catch (boost::property_tree::ptree_bad_path&) {
110 // tpm is not specified, take the default
111 }
112 catch (boost::property_tree::ptree_bad_data& error) {
113 throw ConfigFile::Error(error.what());
114 }
115
116 if (defaultTpmLocator.empty())
117#if defined(NDN_CXX_HAVE_OSX_SECURITY) and defined(NDN_CXX_WITH_OSX_KEYCHAIN)
118 defaultTpmLocator = SecTpmOsx::SCHEME;
119#else
120 defaultTpmLocator = SecTpmFile::SCHEME;
121#endif // defined(NDN_CXX_HAVE_OSX_SECURITY) and defined(NDN_CXX_WITH_OSX_KEYCHAIN)
122 else if (defaultTpmLocator == "osx-keychain")
123#if defined(NDN_CXX_HAVE_OSX_SECURITY)
124 defaultTpmLocator = SecTpmOsx::SCHEME;
125#else
126 throw Error("TPM Locator '" + defaultTpmLocator + "' is not supported on this platform");
127#endif // NDN_CXX_HAVE_OSX_SECURITY
128 else if (defaultTpmLocator == "file")
129 defaultTpmLocator = SecTpmFile::SCHEME;
130
131 std::string defaultPibLocator;
132 try {
133 defaultPibLocator = parsed.get<std::string>("pib");
134 }
135 catch (boost::property_tree::ptree_bad_path&) {
136 // pib is not specified, take the default
137 }
138 catch (boost::property_tree::ptree_bad_data& error) {
139 throw ConfigFile::Error(error.what());
140 }
141
142 if (defaultPibLocator.empty() || defaultPibLocator == "sqlite3")
143 defaultPibLocator = SecPublicInfoSqlite3::SCHEME;
144
145 std::string pibLocator = pib;
146 std::string tpmLocator = tpm;
147
148 if (pibLocator == "")
149 pibLocator = defaultPibLocator;
150
151 if (defaultPibLocator == pibLocator)
152 tpmLocator = defaultTpmLocator;
153
154 initializePib(pibLocator);
155
156 std::string currentTpmLocator;
157 try {
158 currentTpmLocator = m_pib->getTpmLocator();
159
160 if (currentTpmLocator != tpmLocator) {
161 if (!allowReset) {
162 // Tpm mismatch, but we do not want to reset PIB
163 throw MismatchError("TPM locator supplied and TPM locator in PIB mismatch: " +
164 currentTpmLocator + " != " + tpmLocator);
165 }
166 else {
167 // reset is explicitly required
168 tpmLocator = currentTpmLocator;
169 }
170 }
171 }
172 catch (SecPublicInfo::Error&) {
173 // TPM locator is not set in PIB yet.
174 }
175
176 initializeTpm(tpmLocator); // note that key mismatch may still happen
177 // if the TPM locator is initially set to a wrong one
178 // or if the PIB was shared by more than one TPMs before.
179 // This is due to the old PIB does not have TPM info,
180 // new pib should not have this problem.
181
182 m_pib->setTpmLocator(tpmLocator);
183}
184
185void
186KeyChain::initializeTpm(const std::string& locator)
187{
188 size_t pos = locator.find(':');
189 std::string type = locator.substr(0, pos + 1);
190 std::string location = locator.substr(pos + 1);
191
192 if (type == SecTpmFile::SCHEME)
193 m_tpm = new SecTpmFile(location);
194#if defined(NDN_CXX_HAVE_OSX_SECURITY) and defined(NDN_CXX_WITH_OSX_KEYCHAIN)
195 else if (type == SecTpmOsx::SCHEME)
196 m_tpm = new SecTpmOsx(location);
197#endif
198 else
199 throw Error("Tpm locator error: Unsupported Tpm type: " + type);
200}
201
202void
203KeyChain::initializePib(const std::string& locator)
204{
205 size_t pos = locator.find(':');
206 std::string type = locator.substr(0, pos + 1);
207 std::string location = locator.substr(pos + 1);
208
209 if (type == SecPublicInfoSqlite3::SCHEME)
210 m_pib = new SecPublicInfoSqlite3(location);
211 else
212 throw Error("Pib locator error: Unsupported Pib type: " + type);
213}
214
Yingdi Yu7036ce22014-06-19 18:53:37 -0700215Name
216KeyChain::createIdentity(const Name& identityName, const KeyParams& params)
217{
218 m_pib->addIdentity(identityName);
219
220 Name keyName;
221 try
222 {
223 keyName = m_pib->getDefaultKeyNameForIdentity(identityName);
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700224
225 shared_ptr<PublicKey> key = m_pib->getPublicKey(keyName);
226
227 if (key->getKeyType() != params.getKeyType())
228 {
229 keyName = generateKeyPair(identityName, true, params);
230 m_pib->setDefaultKeyNameForIdentity(keyName);
231 }
Yingdi Yu7036ce22014-06-19 18:53:37 -0700232 }
233 catch (SecPublicInfo::Error& e)
234 {
235 keyName = generateKeyPair(identityName, true, params);
236 m_pib->setDefaultKeyNameForIdentity(keyName);
237 }
238
239 Name certName;
240 try
241 {
242 certName = m_pib->getDefaultCertificateNameForKey(keyName);
243 }
244 catch (SecPublicInfo::Error& e)
245 {
246 shared_ptr<IdentityCertificate> selfCert = selfSign(keyName);
247 m_pib->addCertificateAsIdentityDefault(*selfCert);
248 certName = selfCert->getName();
249 }
250
251 return certName;
252}
253
254Name
Yingdi Yu41546342014-11-30 23:37:53 -0800255KeyChain::generateRsaKeyPair(const Name& identityName, bool isKsk, uint32_t keySize)
256{
257 RsaKeyParams params(keySize);
258 return generateKeyPair(identityName, isKsk, params);
259}
260
261Name
262KeyChain::generateEcdsaKeyPair(const Name& identityName, bool isKsk, uint32_t keySize)
263{
264 EcdsaKeyParams params(keySize);
265 return generateKeyPair(identityName, isKsk, params);
266}
267
268Name
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700269KeyChain::generateRsaKeyPairAsDefault(const Name& identityName, bool isKsk, uint32_t keySize)
Yingdi Yu7036ce22014-06-19 18:53:37 -0700270{
271 RsaKeyParams params(keySize);
272
273 Name keyName = generateKeyPair(identityName, isKsk, params);
274
275 m_pib->setDefaultKeyNameForIdentity(keyName);
276
277 return keyName;
278}
279
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700280Name
281KeyChain::generateEcdsaKeyPairAsDefault(const Name& identityName, bool isKsk, uint32_t keySize)
282{
283 EcdsaKeyParams params(keySize);
284
285 Name keyName = generateKeyPair(identityName, isKsk, params);
286
287 m_pib->setDefaultKeyNameForIdentity(keyName);
288
289 return keyName;
290}
291
292
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700293shared_ptr<IdentityCertificate>
294KeyChain::prepareUnsignedIdentityCertificate(const Name& keyName,
295 const Name& signingIdentity,
296 const time::system_clock::TimePoint& notBefore,
297 const time::system_clock::TimePoint& notAfter,
Yingdi Yu0eb5d722014-06-10 15:06:25 -0700298 const std::vector<CertificateSubjectDescription>& subjectDescription,
299 const Name& certPrefix)
300{
301 shared_ptr<PublicKey> publicKey;
302 try
303 {
304 publicKey = m_pib->getPublicKey(keyName);
305 }
306 catch (SecPublicInfo::Error& e)
307 {
308 return shared_ptr<IdentityCertificate>();
309 }
310
311 return prepareUnsignedIdentityCertificate(keyName, *publicKey, signingIdentity,
312 notBefore, notAfter,
313 subjectDescription, certPrefix);
314}
315
316shared_ptr<IdentityCertificate>
317KeyChain::prepareUnsignedIdentityCertificate(const Name& keyName,
318 const PublicKey& publicKey,
319 const Name& signingIdentity,
320 const time::system_clock::TimePoint& notBefore,
321 const time::system_clock::TimePoint& notAfter,
322 const std::vector<CertificateSubjectDescription>& subjectDescription,
323 const Name& certPrefix)
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700324{
325 if (keyName.size() < 1)
326 return shared_ptr<IdentityCertificate>();
327
Alexander Afanasyev9c578182014-05-14 17:28:28 -0700328 std::string keyIdPrefix = keyName.get(-1).toUri().substr(0, 4);
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700329 if (keyIdPrefix != "ksk-" && keyIdPrefix != "dsk-")
330 return shared_ptr<IdentityCertificate>();
331
332 shared_ptr<IdentityCertificate> certificate = make_shared<IdentityCertificate>();
333 Name certName;
334
Yingdi Yu0eb5d722014-06-10 15:06:25 -0700335 if (certPrefix == KeyChain::DEFAULT_PREFIX)
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700336 {
Yingdi Yu0eb5d722014-06-10 15:06:25 -0700337 // No certificate prefix hint, infer the prefix
338 if (signingIdentity.isPrefixOf(keyName))
339 certName.append(signingIdentity)
340 .append("KEY")
341 .append(keyName.getSubName(signingIdentity.size()))
342 .append("ID-CERT")
343 .appendVersion();
344 else
345 certName.append(keyName.getPrefix(-1))
346 .append("KEY")
347 .append(keyName.get(-1))
348 .append("ID-CERT")
349 .appendVersion();
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700350 }
351 else
352 {
Yingdi Yu0eb5d722014-06-10 15:06:25 -0700353 // cert prefix hint is supplied, determine the cert name.
354 if (certPrefix.isPrefixOf(keyName) && certPrefix != keyName)
355 certName.append(certPrefix)
356 .append("KEY")
357 .append(keyName.getSubName(certPrefix.size()))
358 .append("ID-CERT")
359 .appendVersion();
360 else
361 return shared_ptr<IdentityCertificate>();
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700362 }
363
Yingdi Yu0eb5d722014-06-10 15:06:25 -0700364
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700365 certificate->setName(certName);
366 certificate->setNotBefore(notBefore);
367 certificate->setNotAfter(notAfter);
Yingdi Yu0eb5d722014-06-10 15:06:25 -0700368 certificate->setPublicKeyInfo(publicKey);
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700369
370 if (subjectDescription.empty())
371 {
Yingdi Yu9d9d5992014-06-25 12:25:16 -0700372 CertificateSubjectDescription subjectName(oid::ATTRIBUTE_NAME, keyName.getPrefix(-1).toUri());
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700373 certificate->addSubjectDescription(subjectName);
374 }
375 else
376 {
377 std::vector<CertificateSubjectDescription>::const_iterator sdIt =
378 subjectDescription.begin();
379 std::vector<CertificateSubjectDescription>::const_iterator sdEnd =
380 subjectDescription.end();
381 for(; sdIt != sdEnd; sdIt++)
382 certificate->addSubjectDescription(*sdIt);
383 }
384
385 certificate->encode();
386
387 return certificate;
388}
389
390Signature
391KeyChain::sign(const uint8_t* buffer, size_t bufferLength, const Name& certificateName)
392{
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700393 shared_ptr<IdentityCertificate> certificate = m_pib->getCertificate(certificateName);
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700394
Yingdi Yu4a557052014-07-09 16:40:37 -0700395 KeyLocator keyLocator(certificate->getName().getPrefix(-1));
396 shared_ptr<Signature> sig =
397 determineSignatureWithPublicKey(keyLocator, certificate->getPublicKeyInfo().getKeyType());
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700398
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700399 if (!static_cast<bool>(sig))
400 throw SecTpm::Error("unknown key type");
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700401
Yingdi Yu4a557052014-07-09 16:40:37 -0700402
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700403 // For temporary usage, we support SHA256 only, but will support more.
404 sig->setValue(m_tpm->signInTpm(buffer, bufferLength,
405 certificate->getPublicKeyName(),
406 DIGEST_ALGORITHM_SHA256));
407
408 return *sig;
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700409}
410
411shared_ptr<IdentityCertificate>
412KeyChain::selfSign(const Name& keyName)
413{
414 shared_ptr<PublicKey> pubKey;
415 try
416 {
417 pubKey = m_pib->getPublicKey(keyName); // may throw an exception.
418 }
419 catch (SecPublicInfo::Error& e)
420 {
421 return shared_ptr<IdentityCertificate>();
422 }
423
424 shared_ptr<IdentityCertificate> certificate = make_shared<IdentityCertificate>();
425
426 Name certificateName = keyName.getPrefix(-1);
427 certificateName.append("KEY").append(keyName.get(-1)).append("ID-CERT").appendVersion();
428
429 certificate->setName(certificateName);
430 certificate->setNotBefore(time::system_clock::now());
Yingdi Yu9d9d5992014-06-25 12:25:16 -0700431 certificate->setNotAfter(time::system_clock::now() + time::days(7300)); // ~20 years
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700432 certificate->setPublicKeyInfo(*pubKey);
Yingdi Yu9d9d5992014-06-25 12:25:16 -0700433 certificate->addSubjectDescription(CertificateSubjectDescription(oid::ATTRIBUTE_NAME,
434 keyName.toUri()));
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700435 certificate->encode();
436
437 selfSign(*certificate);
438 return certificate;
439}
440
441void
442KeyChain::selfSign(IdentityCertificate& cert)
443{
444 Name keyName = IdentityCertificate::certificateNameToPublicKeyName(cert.getName());
445 if (!m_tpm->doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE))
Yingdi Yu7036ce22014-06-19 18:53:37 -0700446 throw SecTpm::Error("Private key does not exist");
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700447
Yingdi Yu4a557052014-07-09 16:40:37 -0700448
449 KeyLocator keyLocator(cert.getName().getPrefix(-1));
450 shared_ptr<Signature> sig =
451 determineSignatureWithPublicKey(keyLocator, cert.getPublicKeyInfo().getKeyType());
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700452
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700453 if (!static_cast<bool>(sig))
454 throw SecTpm::Error("unknown key type");
455
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700456 signPacketWrapper(cert, *sig, keyName, DIGEST_ALGORITHM_SHA256);
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700457}
458
459shared_ptr<SecuredBag>
460KeyChain::exportIdentity(const Name& identity, const std::string& passwordStr)
461{
462 if (!m_pib->doesIdentityExist(identity))
Yingdi Yu7036ce22014-06-19 18:53:37 -0700463 throw SecPublicInfo::Error("Identity does not exist");
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700464
465 Name keyName = m_pib->getDefaultKeyNameForIdentity(identity);
466
467 ConstBufferPtr pkcs5;
468 try
469 {
470 pkcs5 = m_tpm->exportPrivateKeyPkcs5FromTpm(keyName, passwordStr);
471 }
472 catch (SecTpm::Error& e)
473 {
474 throw SecPublicInfo::Error("Fail to export PKCS5 of private key");
475 }
476
477 shared_ptr<IdentityCertificate> cert;
478 try
479 {
480 cert = m_pib->getCertificate(m_pib->getDefaultCertificateNameForKey(keyName));
481 }
482 catch (SecPublicInfo::Error& e)
483 {
484 cert = selfSign(keyName);
485 m_pib->addCertificateAsIdentityDefault(*cert);
486 }
487
Alexander Afanasyevb67090a2014-04-29 22:31:01 -0700488 // make_shared on OSX 10.9 has some strange problem here
489 shared_ptr<SecuredBag> secureBag(new SecuredBag(*cert, pkcs5));
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700490
491 return secureBag;
492}
493
494void
495KeyChain::importIdentity(const SecuredBag& securedBag, const std::string& passwordStr)
496{
497 Name certificateName = securedBag.getCertificate().getName();
498 Name keyName = IdentityCertificate::certificateNameToPublicKeyName(certificateName);
499 Name identity = keyName.getPrefix(-1);
500
501 // Add identity
502 m_pib->addIdentity(identity);
503
504 // Add key
505 m_tpm->importPrivateKeyPkcs5IntoTpm(keyName,
506 securedBag.getKey()->buf(),
507 securedBag.getKey()->size(),
508 passwordStr);
509
510 shared_ptr<PublicKey> pubKey = m_tpm->getPublicKeyFromTpm(keyName.toUri());
511 // HACK! We should set key type according to the pkcs8 info.
Yingdi Yu41546342014-11-30 23:37:53 -0800512 m_pib->addKey(keyName, *pubKey);
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700513 m_pib->setDefaultKeyNameForIdentity(keyName);
514
515 // Add cert
516 m_pib->addCertificateAsIdentityDefault(securedBag.getCertificate());
517}
518
Yingdi Yu4a557052014-07-09 16:40:37 -0700519shared_ptr<Signature>
520KeyChain::determineSignatureWithPublicKey(const KeyLocator& keyLocator,
521 KeyType keyType, DigestAlgorithm digestAlgorithm)
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700522{
523 switch (keyType)
524 {
525 case KEY_TYPE_RSA:
526 {
527 // For temporary usage, we support SHA256 only, but will support more.
528 if (digestAlgorithm != DIGEST_ALGORITHM_SHA256)
Yingdi Yu4a557052014-07-09 16:40:37 -0700529 return shared_ptr<Signature>();
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700530
Yingdi Yu4a557052014-07-09 16:40:37 -0700531 return make_shared<SignatureSha256WithRsa>(keyLocator);
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700532 }
533 case KEY_TYPE_ECDSA:
534 {
535 // For temporary usage, we support SHA256 only, but will support more.
536 if (digestAlgorithm != DIGEST_ALGORITHM_SHA256)
Yingdi Yu4a557052014-07-09 16:40:37 -0700537 return shared_ptr<Signature>();
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700538
Yingdi Yu4a557052014-07-09 16:40:37 -0700539 return make_shared<SignatureSha256WithEcdsa>(keyLocator);
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700540 }
541 default:
Yingdi Yu4a557052014-07-09 16:40:37 -0700542 return shared_ptr<Signature>();
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700543 }
544}
545
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700546void
547KeyChain::setDefaultCertificateInternal()
548{
549 m_pib->refreshDefaultCertificate();
550
Alexander Afanasyevaab79662014-07-07 17:35:34 -0700551 if (!static_cast<bool>(m_pib->getDefaultCertificate()))
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700552 {
553 Name defaultIdentity;
554 try
555 {
556 defaultIdentity = m_pib->getDefaultIdentity();
557 }
558 catch (SecPublicInfo::Error& e)
559 {
560 uint32_t random = random::generateWord32();
561 defaultIdentity.append("tmp-identity")
562 .append(reinterpret_cast<uint8_t*>(&random), 4);
563 }
564 createIdentity(defaultIdentity);
565 m_pib->setDefaultIdentity(defaultIdentity);
566 m_pib->refreshDefaultCertificate();
567 }
568}
569
Yingdi Yu7036ce22014-06-19 18:53:37 -0700570Name
571KeyChain::generateKeyPair(const Name& identityName, bool isKsk, const KeyParams& params)
572{
573 Name keyName = m_pib->getNewKeyName(identityName, isKsk);
574
575 m_tpm->generateKeyPairInTpm(keyName.toUri(), params);
576
577 shared_ptr<PublicKey> pubKey = m_tpm->getPublicKeyFromTpm(keyName.toUri());
578 m_pib->addKey(keyName, *pubKey);
579
580 return keyName;
581}
582
583void
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700584KeyChain::signPacketWrapper(Data& data, const Signature& signature,
Yingdi Yu7036ce22014-06-19 18:53:37 -0700585 const Name& keyName, DigestAlgorithm digestAlgorithm)
586{
587 data.setSignature(signature);
588
589 EncodingBuffer encoder;
590 data.wireEncode(encoder, true);
591
592 Block signatureValue = m_tpm->signInTpm(encoder.buf(), encoder.size(),
593 keyName, digestAlgorithm);
594 data.wireEncode(encoder, signatureValue);
595}
596
597void
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700598KeyChain::signPacketWrapper(Interest& interest, const Signature& signature,
Yingdi Yu7036ce22014-06-19 18:53:37 -0700599 const Name& keyName, DigestAlgorithm digestAlgorithm)
600{
601 time::milliseconds timestamp = time::toUnixTimestamp(time::system_clock::now());
602 if (timestamp <= m_lastTimestamp)
603 {
604 timestamp = m_lastTimestamp + time::milliseconds(1);
605 }
606
607 Name signedName = interest.getName();
608 signedName
609 .append(name::Component::fromNumber(timestamp.count())) // timestamp
610 .append(name::Component::fromNumber(random::generateWord64())) // nonce
611 .append(signature.getInfo()); // signatureInfo
612
613 Block sigValue = m_tpm->signInTpm(signedName.wireEncode().value(),
614 signedName.wireEncode().value_size(),
615 keyName,
616 digestAlgorithm);
617 sigValue.encode();
618 signedName.append(sigValue); // signatureValue
619 interest.setName(signedName);
620}
621
622Signature
623KeyChain::signByIdentity(const uint8_t* buffer, size_t bufferLength, const Name& identityName)
624{
625 Name signingCertificateName;
626 try
627 {
628 signingCertificateName = m_pib->getDefaultCertificateNameForIdentity(identityName);
629 }
630 catch (SecPublicInfo::Error& e)
631 {
632 signingCertificateName = createIdentity(identityName);
633 // Ideally, no exception will be thrown out, unless something goes wrong in the TPM, which
634 // is a fatal error.
635 }
636
637 // We either get or create the signing certificate, sign data! (no exception unless fatal error
638 // in TPM)
639 return sign(buffer, bufferLength, signingCertificateName);
640}
641
642void
643KeyChain::signWithSha256(Data& data)
644{
645 DigestSha256 sig;
646 data.setSignature(sig);
647
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600648 Block sigValue(tlv::SignatureValue,
Yingdi Yu7036ce22014-06-19 18:53:37 -0700649 crypto::sha256(data.wireEncode().value(),
650 data.wireEncode().value_size() -
651 data.getSignature().getValue().size()));
652 data.setSignatureValue(sigValue);
653}
654
655void
Yingdi Yu6ab67812014-11-27 15:00:34 -0800656KeyChain::signWithSha256(Interest& interest)
657{
658 DigestSha256 sig;
659
660 time::milliseconds timestamp = time::toUnixTimestamp(time::system_clock::now());
661 if (timestamp <= m_lastTimestamp)
662 timestamp = m_lastTimestamp + time::milliseconds(1);
663
664 Name signedName = interest.getName();
665 signedName
666 .append(name::Component::fromNumber(timestamp.count())) // timestamp
667 .append(name::Component::fromNumber(random::generateWord64())) // nonce
668 .append(sig.getInfo()); // signatureInfo
669
670 Block sigValue(tlv::SignatureValue,
671 crypto::sha256(signedName.wireEncode().value(),
672 signedName.wireEncode().value_size()));
673
674 sigValue.encode();
675 signedName.append(sigValue); // signatureValue
676 interest.setName(signedName);
677}
678
679void
Yingdi Yu7036ce22014-06-19 18:53:37 -0700680KeyChain::deleteCertificate(const Name& certificateName)
681{
Yingdi Yu7036ce22014-06-19 18:53:37 -0700682 m_pib->deleteCertificateInfo(certificateName);
683}
684
685void
686KeyChain::deleteKey(const Name& keyName)
687{
Yingdi Yu7036ce22014-06-19 18:53:37 -0700688 m_pib->deletePublicKeyInfo(keyName);
689 m_tpm->deleteKeyPairInTpm(keyName);
690}
691
692void
693KeyChain::deleteIdentity(const Name& identity)
694{
Yingdi Yu6147ef42014-12-08 17:48:32 -0800695 std::vector<Name> keyNames;
696 m_pib->getAllKeyNamesOfIdentity(identity, keyNames, true);
697 m_pib->getAllKeyNamesOfIdentity(identity, keyNames, false);
Yingdi Yu7036ce22014-06-19 18:53:37 -0700698
699 m_pib->deleteIdentityInfo(identity);
700
Yingdi Yu6147ef42014-12-08 17:48:32 -0800701 for (const auto& keyName : keyNames)
702 m_tpm->deleteKeyPairInTpm(keyName);
Yingdi Yu7036ce22014-06-19 18:53:37 -0700703}
704
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700705}