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