blob: 9f14402429945ef47b4a5ebd2f542d42b8febcfb [file] [log] [blame]
Yingdi Yufe4733a2015-10-22 14:24:12 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Davide Pesavento10b24be2017-07-12 23:23:46 -04002/*
Yingdi Yufe4733a2015-10-22 14:24:12 -07003 * Copyright (c) 2013-2017 Regents of the University of California.
4 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6 *
7 * 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.
20 */
21
22#include "key-chain.hpp"
23
24#include "../../util/config-file.hpp"
Alexander Afanasyev83eb1cc2017-01-04 17:34:34 -080025#include "../../util/logger.hpp"
Junxiao Shi6938e342017-07-25 21:56:58 +000026#include "../../util/sha256.hpp"
Yingdi Yufe4733a2015-10-22 14:24:12 -070027
28#include "../pib/pib-sqlite3.hpp"
29#include "../pib/pib-memory.hpp"
30
Alexander Afanasyev0cf887d2017-03-26 16:58:59 -050031#ifdef NDN_CXX_HAVE_OSX_FRAMEWORKS
Yingdi Yufe4733a2015-10-22 14:24:12 -070032#include "../tpm/back-end-osx.hpp"
Alexander Afanasyev0cf887d2017-03-26 16:58:59 -050033#endif // NDN_CXX_HAVE_OSX_FRAMEWORKS
Yingdi Yufe4733a2015-10-22 14:24:12 -070034
35#include "../tpm/back-end-file.hpp"
36#include "../tpm/back-end-mem.hpp"
37
38#include "../transform/bool-sink.hpp"
39#include "../transform/buffer-source.hpp"
40#include "../transform/private-key.hpp"
Davide Pesavento8aad3722017-09-16 20:57:28 -040041#include "../transform/public-key.hpp"
Yingdi Yufe4733a2015-10-22 14:24:12 -070042#include "../transform/verifier-filter.hpp"
43#include "../../encoding/buffer-stream.hpp"
Yingdi Yufe4733a2015-10-22 14:24:12 -070044
45#include <boost/lexical_cast.hpp>
46
47namespace ndn {
48namespace security {
49
50// When static library is used, not everything is compiled into the resulting binary.
51// Therefore, the following standard PIB and TPMs need to be registered here.
52// http://stackoverflow.com/q/9459980/2150331
53
54/////////
55// PIB //
56/////////
57namespace pib {
58NDN_CXX_V2_KEYCHAIN_REGISTER_PIB_BACKEND(PibSqlite3);
59NDN_CXX_V2_KEYCHAIN_REGISTER_PIB_BACKEND(PibMemory);
60} // namespace pib
61
62/////////
63// TPM //
64/////////
65namespace tpm {
Alexander Afanasyev0cf887d2017-03-26 16:58:59 -050066#if defined(NDN_CXX_HAVE_OSX_FRAMEWORKS) && defined(NDN_CXX_WITH_OSX_KEYCHAIN)
Yingdi Yufe4733a2015-10-22 14:24:12 -070067NDN_CXX_V2_KEYCHAIN_REGISTER_TPM_BACKEND(BackEndOsx);
Alexander Afanasyev0cf887d2017-03-26 16:58:59 -050068#endif // defined(NDN_CXX_HAVE_OSX_FRAMEWORKS) && defined(NDN_CXX_WITH_OSX_KEYCHAIN)
Yingdi Yufe4733a2015-10-22 14:24:12 -070069
70NDN_CXX_V2_KEYCHAIN_REGISTER_TPM_BACKEND(BackEndFile);
71NDN_CXX_V2_KEYCHAIN_REGISTER_TPM_BACKEND(BackEndMem);
72} // namespace tpm
73
74namespace v2 {
75
Alexander Afanasyev83eb1cc2017-01-04 17:34:34 -080076NDN_LOG_INIT(ndn.security.v2.KeyChain);
77
Yingdi Yufe4733a2015-10-22 14:24:12 -070078std::string KeyChain::s_defaultPibLocator;
79std::string KeyChain::s_defaultTpmLocator;
80
81KeyChain::PibFactories&
82KeyChain::getPibFactories()
83{
84 static PibFactories pibFactories;
85 return pibFactories;
86}
87
88KeyChain::TpmFactories&
89KeyChain::getTpmFactories()
90{
91 static TpmFactories tpmFactories;
92 return tpmFactories;
93}
94
95const std::string&
96KeyChain::getDefaultPibScheme()
97{
98 return pib::PibSqlite3::getScheme();;
99}
100
101const std::string&
102KeyChain::getDefaultTpmScheme()
103{
Alexander Afanasyev0cf887d2017-03-26 16:58:59 -0500104#if defined(NDN_CXX_HAVE_OSX_FRAMEWORKS) && defined(NDN_CXX_WITH_OSX_KEYCHAIN)
Yingdi Yufe4733a2015-10-22 14:24:12 -0700105 return tpm::BackEndOsx::getScheme();;
106#else
107 return tpm::BackEndFile::getScheme();
Alexander Afanasyev0cf887d2017-03-26 16:58:59 -0500108#endif // defined(NDN_CXX_HAVE_OSX_FRAMEWORKS) && defined(NDN_CXX_WITH_OSX_KEYCHAIN)
Yingdi Yufe4733a2015-10-22 14:24:12 -0700109}
110
111const std::string&
112KeyChain::getDefaultPibLocator()
113{
114 if (!s_defaultPibLocator.empty())
115 return s_defaultPibLocator;
116
117 if (getenv("NDN_CLIENT_PIB") != nullptr) {
118 s_defaultPibLocator = getenv("NDN_CLIENT_PIB");
119 }
120 else {
121 ConfigFile config;
122 s_defaultPibLocator = config.getParsedConfiguration().get<std::string>("pib", getDefaultPibScheme() + ":");
123 }
124
125 return s_defaultPibLocator;
126}
127
128const std::string&
129KeyChain::getDefaultTpmLocator()
130{
131 if (!s_defaultTpmLocator.empty())
132 return s_defaultTpmLocator;
133
134 if (getenv("NDN_CLIENT_TPM") != nullptr) {
135 s_defaultTpmLocator = getenv("NDN_CLIENT_TPM");
136 }
137 else {
138 ConfigFile config;
139 s_defaultTpmLocator = config.getParsedConfiguration().get<std::string>("tpm", getDefaultTpmScheme() + ":");
140 }
141
142 return s_defaultTpmLocator;
143}
144
145
146// Other defaults
147
148const SigningInfo&
149KeyChain::getDefaultSigningInfo()
150{
151 static SigningInfo signingInfo;
152 return signingInfo;
153}
154
155const KeyParams&
156KeyChain::getDefaultKeyParams()
157{
Spyridon Mastorakis1ece2e32015-08-27 18:52:21 -0700158 static EcKeyParams keyParams;
Yingdi Yufe4733a2015-10-22 14:24:12 -0700159 return keyParams;
160}
161
162//
163
164KeyChain::KeyChain()
165 : KeyChain(getDefaultPibLocator(), getDefaultTpmLocator(), true)
166{
167}
168
169KeyChain::KeyChain(const std::string& pibLocator, const std::string& tpmLocator, bool allowReset)
170{
171 // PIB Locator
172 std::string pibScheme, pibLocation;
173 std::tie(pibScheme, pibLocation) = parseAndCheckPibLocator(pibLocator);
174 std::string canonicalPibLocator = pibScheme + ":" + pibLocation;
175
176 // Create PIB
177 m_pib = createPib(canonicalPibLocator);
178 std::string oldTpmLocator;
179 try {
180 oldTpmLocator = m_pib->getTpmLocator();
181 }
182 catch (const Pib::Error&) {
183 // TPM locator is not set in PIB yet.
184 }
185
186 // TPM Locator
187 std::string tpmScheme, tpmLocation;
188 std::tie(tpmScheme, tpmLocation) = parseAndCheckTpmLocator(tpmLocator);
189 std::string canonicalTpmLocator = tpmScheme + ":" + tpmLocation;
190
191 if (canonicalPibLocator == getDefaultPibLocator()) {
192 // Default PIB must use default TPM
193 if (!oldTpmLocator.empty() && oldTpmLocator != getDefaultTpmLocator()) {
194 m_pib->reset();
195 canonicalTpmLocator = getDefaultTpmLocator();
196 }
197 }
198 else {
199 // non-default PIB check consistency
200 if (!oldTpmLocator.empty() && oldTpmLocator != canonicalTpmLocator) {
201 if (allowReset)
202 m_pib->reset();
203 else
204 BOOST_THROW_EXCEPTION(LocatorMismatchError("TPM locator supplied does not match TPM locator in PIB: " +
205 oldTpmLocator + " != " + canonicalTpmLocator));
206 }
207 }
208
209 // note that key mismatch may still happen if the TPM locator is initially set to a
210 // wrong one or if the PIB was shared by more than one TPMs before. This is due to the
211 // old PIB does not have TPM info, new pib should not have this problem.
212 m_tpm = createTpm(canonicalTpmLocator);
213 m_pib->setTpmLocator(canonicalTpmLocator);
214}
215
216KeyChain::~KeyChain() = default;
217
218// public: management
219
220Identity
221KeyChain::createIdentity(const Name& identityName, const KeyParams& params)
222{
223 Identity id = m_pib->addIdentity(identityName);
224
225 Key key;
226 try {
227 key = id.getDefaultKey();
228 }
229 catch (const Pib::Error&) {
230 key = createKey(id, params);
231 }
232
233 try {
234 key.getDefaultCertificate();
235 }
236 catch (const Pib::Error&) {
Alexander Afanasyev83eb1cc2017-01-04 17:34:34 -0800237 NDN_LOG_DEBUG("No default cert for " << key.getName() << ", requesting self-signing");
Yingdi Yufe4733a2015-10-22 14:24:12 -0700238 selfSign(key);
239 }
240
241 return id;
242}
243
244void
245KeyChain::deleteIdentity(const Identity& identity)
246{
247 BOOST_ASSERT(static_cast<bool>(identity));
248
249 Name identityName = identity.getName();
250
251 for (const auto& key : identity.getKeys()) {
252 m_tpm->deleteKey(key.getName());
253 }
254
255 m_pib->removeIdentity(identityName);
256}
257
258void
259KeyChain::setDefaultIdentity(const Identity& identity)
260{
261 BOOST_ASSERT(static_cast<bool>(identity));
262
263 m_pib->setDefaultIdentity(identity.getName());
264}
265
266Key
267KeyChain::createKey(const Identity& identity, const KeyParams& params)
268{
269 BOOST_ASSERT(static_cast<bool>(identity));
270
271 // create key in TPM
272 Name keyName = m_tpm->createKey(identity.getName(), params);
273
274 // set up key info in PIB
275 ConstBufferPtr pubKey = m_tpm->getPublicKey(keyName);
276 Key key = identity.addKey(pubKey->buf(), pubKey->size(), keyName);
Alexander Afanasyev83eb1cc2017-01-04 17:34:34 -0800277
278 NDN_LOG_DEBUG("Requesting self-signing for newly created key " << key.getName());
Yingdi Yufe4733a2015-10-22 14:24:12 -0700279 selfSign(key);
280
281 return key;
282}
283
284void
285KeyChain::deleteKey(const Identity& identity, const Key& key)
286{
287 BOOST_ASSERT(static_cast<bool>(identity));
288 BOOST_ASSERT(static_cast<bool>(key));
289
290 Name keyName = key.getName();
291 if (identity.getName() != key.getIdentity()) {
292 BOOST_THROW_EXCEPTION(std::invalid_argument("Identity `" + identity.getName().toUri() + "` "
Muktadir Chowdhurycab16962017-06-12 12:19:43 -0500293 "does not match key `" + keyName.toUri() + "`"));
Yingdi Yufe4733a2015-10-22 14:24:12 -0700294 }
295
296 identity.removeKey(keyName);
297 m_tpm->deleteKey(keyName);
298}
299
300void
301KeyChain::setDefaultKey(const Identity& identity, const Key& key)
302{
303 BOOST_ASSERT(static_cast<bool>(identity));
304 BOOST_ASSERT(static_cast<bool>(key));
305
306 if (identity.getName() != key.getIdentity())
307 BOOST_THROW_EXCEPTION(std::invalid_argument("Identity `" + identity.getName().toUri() + "` "
Muktadir Chowdhurycab16962017-06-12 12:19:43 -0500308 "does not match key `" + key.getName().toUri() + "`"));
Yingdi Yufe4733a2015-10-22 14:24:12 -0700309
310 identity.setDefaultKey(key.getName());
311}
312
313void
314KeyChain::addCertificate(const Key& key, const Certificate& certificate)
315{
316 BOOST_ASSERT(static_cast<bool>(key));
317
318 if (key.getName() != certificate.getKeyName() ||
319 !std::equal(certificate.getContent().value_begin(), certificate.getContent().value_end(),
320 key.getPublicKey().begin()))
321 BOOST_THROW_EXCEPTION(std::invalid_argument("Key `" + key.getName().toUri() + "` "
Muktadir Chowdhurycab16962017-06-12 12:19:43 -0500322 "does not match certificate `" + certificate.getName().toUri() + "`"));
Yingdi Yufe4733a2015-10-22 14:24:12 -0700323
324 key.addCertificate(certificate);
325}
326
327void
328KeyChain::deleteCertificate(const Key& key, const Name& certificateName)
329{
330 BOOST_ASSERT(static_cast<bool>(key));
331
332 if (!Certificate::isValidName(certificateName)) {
333 BOOST_THROW_EXCEPTION(std::invalid_argument("Wrong certificate name `" + certificateName.toUri() + "`"));
334 }
335
336 key.removeCertificate(certificateName);
337}
338
339void
340KeyChain::setDefaultCertificate(const Key& key, const Certificate& cert)
341{
342 BOOST_ASSERT(static_cast<bool>(key));
343
Davide Pesavento3ce6d4e2017-10-05 01:48:24 -0400344 addCertificate(key, cert);
Yingdi Yufe4733a2015-10-22 14:24:12 -0700345 key.setDefaultCertificate(cert.getName());
346}
347
348shared_ptr<SafeBag>
349KeyChain::exportSafeBag(const Certificate& certificate, const char* pw, size_t pwLen)
350{
351 Name identity = certificate.getIdentity();
352 Name keyName = certificate.getKeyName();
353
354 ConstBufferPtr encryptedKey;
355 try {
356 encryptedKey = m_tpm->exportPrivateKey(keyName, pw, pwLen);
357 }
358 catch (const tpm::BackEnd::Error&) {
359 BOOST_THROW_EXCEPTION(Error("Private `" + keyName.toUri() + "` key does not exist"));
360 }
361
362 return make_shared<SafeBag>(certificate, *encryptedKey);
363}
364
365void
366KeyChain::importSafeBag(const SafeBag& safeBag, const char* pw, size_t pwLen)
367{
368 Data certData = safeBag.getCertificate();
369 Certificate cert(std::move(certData));
370 Name identity = cert.getIdentity();
371 Name keyName = cert.getKeyName();
372 const Buffer publicKeyBits = cert.getPublicKey();
373
374 if (m_tpm->hasKey(keyName)) {
375 BOOST_THROW_EXCEPTION(Error("Private key `" + keyName.toUri() + "` already exists"));
376 }
377
378 try {
379 Identity existingId = m_pib->getIdentity(identity);
380 existingId.getKey(keyName);
381 BOOST_THROW_EXCEPTION(Error("Public key `" + keyName.toUri() + "` already exists"));
382 }
383 catch (const Pib::Error&) {
384 // Either identity or key doesn't exist. OK to import.
385 }
386
387 try {
388 m_tpm->importPrivateKey(keyName,
389 safeBag.getEncryptedKeyBag().buf(), safeBag.getEncryptedKeyBag().size(),
390 pw, pwLen);
391 }
392 catch (const std::runtime_error&) {
393 BOOST_THROW_EXCEPTION(Error("Fail to import private key `" + keyName.toUri() + "`"));
394 }
395
396 // check the consistency of private key and certificate
397 const uint8_t content[] = {0x01, 0x02, 0x03, 0x04};
398 ConstBufferPtr sigBits;
399 try {
400 sigBits = m_tpm->sign(content, 4, keyName, DigestAlgorithm::SHA256);
401 }
402 catch (const std::runtime_error&) {
403 m_tpm->deleteKey(keyName);
404 BOOST_THROW_EXCEPTION(Error("Invalid private key `" + keyName.toUri() + "`"));
405 }
406 bool isVerified = false;
407 {
408 using namespace transform;
409 PublicKey publicKey;
410 publicKey.loadPkcs8(publicKeyBits.buf(), publicKeyBits.size());
411 bufferSource(content, sizeof(content)) >> verifierFilter(DigestAlgorithm::SHA256, publicKey,
412 sigBits->buf(), sigBits->size())
413 >> boolSink(isVerified);
414 }
415 if (!isVerified) {
416 m_tpm->deleteKey(keyName);
417 BOOST_THROW_EXCEPTION(Error("Certificate `" + cert.getName().toUri() + "` "
418 "and private key `" + keyName.toUri() + "` do not match"));
419 }
420
421 Identity id = m_pib->addIdentity(identity);
422 Key key = id.addKey(cert.getPublicKey().buf(), cert.getPublicKey().size(), keyName);
423 key.addCertificate(cert);
424}
425
426
427// public: signing
428
429void
430KeyChain::sign(Data& data, const SigningInfo& params)
431{
432 Name keyName;
433 SignatureInfo sigInfo;
434 std::tie(keyName, sigInfo) = prepareSignatureInfo(params);
435
436 data.setSignature(Signature(sigInfo));
437
438 EncodingBuffer encoder;
439 data.wireEncode(encoder, true);
440
441 Block sigValue = sign(encoder.buf(), encoder.size(), keyName, params.getDigestAlgorithm());
442
443 data.wireEncode(encoder, sigValue);
444}
445
446void
447KeyChain::sign(Interest& interest, const SigningInfo& params)
448{
449 Name keyName;
450 SignatureInfo sigInfo;
451 std::tie(keyName, sigInfo) = prepareSignatureInfo(params);
452
453 Name signedName = interest.getName();
454 signedName.append(sigInfo.wireEncode()); // signatureInfo
455
456 Block sigValue = sign(signedName.wireEncode().value(), signedName.wireEncode().value_size(),
457 keyName, params.getDigestAlgorithm());
458
459 sigValue.encode();
460 signedName.append(sigValue); // signatureValue
461 interest.setName(signedName);
462}
463
464Block
465KeyChain::sign(const uint8_t* buffer, size_t bufferLength, const SigningInfo& params)
466{
467 Name keyName;
468 SignatureInfo sigInfo;
469 std::tie(keyName, sigInfo) = prepareSignatureInfo(params);
470
471 return sign(buffer, bufferLength, keyName, params.getDigestAlgorithm());
472}
473
474// public: PIB/TPM creation helpers
475
476static inline std::tuple<std::string/*type*/, std::string/*location*/>
477parseLocatorUri(const std::string& uri)
478{
479 size_t pos = uri.find(':');
480 if (pos != std::string::npos) {
481 return std::make_tuple(uri.substr(0, pos), uri.substr(pos + 1));
482 }
483 else {
484 return std::make_tuple(uri, "");
485 }
486}
487
488std::tuple<std::string/*type*/, std::string/*location*/>
489KeyChain::parseAndCheckPibLocator(const std::string& pibLocator)
490{
491 std::string pibScheme, pibLocation;
492 std::tie(pibScheme, pibLocation) = parseLocatorUri(pibLocator);
493
494 if (pibScheme.empty()) {
495 pibScheme = getDefaultPibScheme();
496 }
497
498 auto pibFactory = getPibFactories().find(pibScheme);
499 if (pibFactory == getPibFactories().end()) {
500 BOOST_THROW_EXCEPTION(KeyChain::Error("PIB scheme `" + pibScheme + "` is not supported"));
501 }
502
503 return std::make_tuple(pibScheme, pibLocation);
504}
505
506unique_ptr<Pib>
507KeyChain::createPib(const std::string& pibLocator)
508{
509 std::string pibScheme, pibLocation;
510 std::tie(pibScheme, pibLocation) = parseAndCheckPibLocator(pibLocator);
511 auto pibFactory = getPibFactories().find(pibScheme);
512 BOOST_ASSERT(pibFactory != getPibFactories().end());
513 return unique_ptr<Pib>(new Pib(pibScheme, pibLocation, pibFactory->second(pibLocation)));
514}
515
516std::tuple<std::string/*type*/, std::string/*location*/>
517KeyChain::parseAndCheckTpmLocator(const std::string& tpmLocator)
518{
519 std::string tpmScheme, tpmLocation;
520 std::tie(tpmScheme, tpmLocation) = parseLocatorUri(tpmLocator);
521
522 if (tpmScheme.empty()) {
523 tpmScheme = getDefaultTpmScheme();
524 }
525 auto tpmFactory = getTpmFactories().find(tpmScheme);
526 if (tpmFactory == getTpmFactories().end()) {
527 BOOST_THROW_EXCEPTION(KeyChain::Error("TPM scheme `" + tpmScheme + "` is not supported"));
528 }
529
530 return std::make_tuple(tpmScheme, tpmLocation);
531}
532
533unique_ptr<Tpm>
534KeyChain::createTpm(const std::string& tpmLocator)
535{
536 std::string tpmScheme, tpmLocation;
537 std::tie(tpmScheme, tpmLocation) = parseAndCheckTpmLocator(tpmLocator);
538 auto tpmFactory = getTpmFactories().find(tpmScheme);
539 BOOST_ASSERT(tpmFactory != getTpmFactories().end());
540 return unique_ptr<Tpm>(new Tpm(tpmScheme, tpmLocation, tpmFactory->second(tpmLocation)));
541}
542
543// private: signing
544
545Certificate
546KeyChain::selfSign(Key& key)
547{
548 Certificate certificate;
549
550 // set name
551 Name certificateName = key.getName();
552 certificateName
553 .append("self")
554 .appendVersion();
555 certificate.setName(certificateName);
556
557 // set metainfo
558 certificate.setContentType(tlv::ContentType_Key);
559 certificate.setFreshnessPeriod(time::hours(1));
560
561 // set content
562 certificate.setContent(key.getPublicKey().buf(), key.getPublicKey().size());
563
564 // set signature-info
Alexander Afanasyev83eb1cc2017-01-04 17:34:34 -0800565 SignatureInfo signatureInfo;
Alexander Afanasyevf8379172017-01-11 16:56:04 -0800566 // Note time::system_clock::max() or other NotAfter date results in incorrect encoded value
567 // because of overflow during conversion to boost::posix_time::ptime (bug #3915).
568 signatureInfo.setValidityPeriod(ValidityPeriod(time::system_clock::TimePoint(),
569 time::system_clock::now() + time::days(20 * 365)));
Yingdi Yufe4733a2015-10-22 14:24:12 -0700570
Alexander Afanasyev83eb1cc2017-01-04 17:34:34 -0800571 sign(certificate, SigningInfo(key).setSignatureInfo(signatureInfo));
Yingdi Yufe4733a2015-10-22 14:24:12 -0700572
573 key.addCertificate(certificate);
574 return certificate;
575}
576
577std::tuple<Name, SignatureInfo>
578KeyChain::prepareSignatureInfo(const SigningInfo& params)
579{
580 SignatureInfo sigInfo = params.getSignatureInfo();
581
582 Name identityName;
583 name::Component keyId;
584 Name certificateName;
585
586 pib::Identity identity;
587 pib::Key key;
588
589 switch (params.getSignerType()) {
590 case SigningInfo::SIGNER_TYPE_NULL: {
591 try {
592 identity = m_pib->getDefaultIdentity();
593 }
594 catch (const Pib::Error&) { // no default identity, use sha256 for signing.
595 sigInfo.setSignatureType(tlv::DigestSha256);
596 return std::make_tuple(SigningInfo::getDigestSha256Identity(), sigInfo);
597 }
598 break;
599 }
600 case SigningInfo::SIGNER_TYPE_ID: {
Junxiao Shife1239a2017-01-27 20:36:12 +0000601 identity = params.getPibIdentity();
602 if (!identity) {
603 try {
604 identity = m_pib->getIdentity(params.getSignerName());
605 }
606 catch (const Pib::Error&) {
607 BOOST_THROW_EXCEPTION(InvalidSigningInfoError("Signing identity `" +
608 params.getSignerName().toUri() + "` does not exist"));
609 }
Yingdi Yufe4733a2015-10-22 14:24:12 -0700610 }
611 break;
612 }
613 case SigningInfo::SIGNER_TYPE_KEY: {
Junxiao Shife1239a2017-01-27 20:36:12 +0000614 key = params.getPibKey();
615 if (!key) {
616 Name identityName = extractIdentityFromKeyName(params.getSignerName());
Yingdi Yufe4733a2015-10-22 14:24:12 -0700617
Junxiao Shife1239a2017-01-27 20:36:12 +0000618 try {
619 identity = m_pib->getIdentity(identityName);
620 key = identity.getKey(params.getSignerName());
621 identity = Identity(); // we will use the PIB key instance, so reset identity;
622 }
623 catch (const Pib::Error&) {
624 BOOST_THROW_EXCEPTION(InvalidSigningInfoError("Signing key `" +
625 params.getSignerName().toUri() + "` does not exist"));
626 }
Yingdi Yufe4733a2015-10-22 14:24:12 -0700627 }
628 break;
629 }
630 case SigningInfo::SIGNER_TYPE_CERT: {
631 Name identityName = extractIdentityFromCertName(params.getSignerName());
632 Name keyName = extractKeyNameFromCertName(params.getSignerName());
633
634 try {
635 identity = m_pib->getIdentity(identityName);
636 key = identity.getKey(keyName);
637 }
638 catch (const Pib::Error&) {
639 BOOST_THROW_EXCEPTION(InvalidSigningInfoError("Signing certificate `" +
640 params.getSignerName().toUri() + "` does not exist"));
641 }
642
643 break;
644 }
645 case SigningInfo::SIGNER_TYPE_SHA256: {
646 sigInfo.setSignatureType(tlv::DigestSha256);
647 return std::make_tuple(SigningInfo::getDigestSha256Identity(), sigInfo);
648 }
Yingdi Yufe4733a2015-10-22 14:24:12 -0700649 default: {
650 BOOST_THROW_EXCEPTION(InvalidSigningInfoError("Unrecognized signer type " +
651 boost::lexical_cast<std::string>(params.getSignerType())));
652 }
653 }
654
655 if (!identity && !key) {
656 BOOST_THROW_EXCEPTION(InvalidSigningInfoError("Cannot determine signing parameters"));
657 }
658
659 if (identity && !key) {
660 try {
661 key = identity.getDefaultKey();
662 }
663 catch (const Pib::Error&) {
664 BOOST_THROW_EXCEPTION(InvalidSigningInfoError("Signing identity `" + identity.getName().toUri() +
665 "` does not have default certificate"));
666 }
667 }
668
669 BOOST_ASSERT(key);
670
671 sigInfo.setSignatureType(getSignatureType(key.getKeyType(), params.getDigestAlgorithm()));
672 sigInfo.setKeyLocator(KeyLocator(key.getName()));
Alexander Afanasyev7e721412017-01-11 13:36:08 -0800673
674 NDN_LOG_TRACE("Prepared signature info: " << sigInfo);
Yingdi Yufe4733a2015-10-22 14:24:12 -0700675 return std::make_tuple(key.getName(), sigInfo);
676}
677
678Block
679KeyChain::sign(const uint8_t* buf, size_t size,
680 const Name& keyName, DigestAlgorithm digestAlgorithm) const
681{
682 if (keyName == SigningInfo::getDigestSha256Identity())
Davide Pesavento10b24be2017-07-12 23:23:46 -0400683 return Block(tlv::SignatureValue, util::Sha256::computeDigest(buf, size));
Yingdi Yufe4733a2015-10-22 14:24:12 -0700684
685 return Block(tlv::SignatureValue, m_tpm->sign(buf, size, keyName, digestAlgorithm));
686}
687
688tlv::SignatureTypeValue
689KeyChain::getSignatureType(KeyType keyType, DigestAlgorithm digestAlgorithm)
690{
691 switch (keyType) {
692 case KeyType::RSA:
693 return tlv::SignatureSha256WithRsa;
694 case KeyType::EC:
695 return tlv::SignatureSha256WithEcdsa;
696 default:
697 BOOST_THROW_EXCEPTION(Error("Unsupported key types"));
698 }
699}
700
701} // namespace v2
702} // namespace security
703} // namespace ndn