blob: b63287d9446f38707ae85cd32baaa1cd327c3dfc [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
344 try {
345 addCertificate(key, cert);
346 }
347 catch (const Pib::Error&) { // force to overwrite the existing certificates
348 key.removeCertificate(cert.getName());
349 addCertificate(key, cert);
350 }
351 key.setDefaultCertificate(cert.getName());
352}
353
354shared_ptr<SafeBag>
355KeyChain::exportSafeBag(const Certificate& certificate, const char* pw, size_t pwLen)
356{
357 Name identity = certificate.getIdentity();
358 Name keyName = certificate.getKeyName();
359
360 ConstBufferPtr encryptedKey;
361 try {
362 encryptedKey = m_tpm->exportPrivateKey(keyName, pw, pwLen);
363 }
364 catch (const tpm::BackEnd::Error&) {
365 BOOST_THROW_EXCEPTION(Error("Private `" + keyName.toUri() + "` key does not exist"));
366 }
367
368 return make_shared<SafeBag>(certificate, *encryptedKey);
369}
370
371void
372KeyChain::importSafeBag(const SafeBag& safeBag, const char* pw, size_t pwLen)
373{
374 Data certData = safeBag.getCertificate();
375 Certificate cert(std::move(certData));
376 Name identity = cert.getIdentity();
377 Name keyName = cert.getKeyName();
378 const Buffer publicKeyBits = cert.getPublicKey();
379
380 if (m_tpm->hasKey(keyName)) {
381 BOOST_THROW_EXCEPTION(Error("Private key `" + keyName.toUri() + "` already exists"));
382 }
383
384 try {
385 Identity existingId = m_pib->getIdentity(identity);
386 existingId.getKey(keyName);
387 BOOST_THROW_EXCEPTION(Error("Public key `" + keyName.toUri() + "` already exists"));
388 }
389 catch (const Pib::Error&) {
390 // Either identity or key doesn't exist. OK to import.
391 }
392
393 try {
394 m_tpm->importPrivateKey(keyName,
395 safeBag.getEncryptedKeyBag().buf(), safeBag.getEncryptedKeyBag().size(),
396 pw, pwLen);
397 }
398 catch (const std::runtime_error&) {
399 BOOST_THROW_EXCEPTION(Error("Fail to import private key `" + keyName.toUri() + "`"));
400 }
401
402 // check the consistency of private key and certificate
403 const uint8_t content[] = {0x01, 0x02, 0x03, 0x04};
404 ConstBufferPtr sigBits;
405 try {
406 sigBits = m_tpm->sign(content, 4, keyName, DigestAlgorithm::SHA256);
407 }
408 catch (const std::runtime_error&) {
409 m_tpm->deleteKey(keyName);
410 BOOST_THROW_EXCEPTION(Error("Invalid private key `" + keyName.toUri() + "`"));
411 }
412 bool isVerified = false;
413 {
414 using namespace transform;
415 PublicKey publicKey;
416 publicKey.loadPkcs8(publicKeyBits.buf(), publicKeyBits.size());
417 bufferSource(content, sizeof(content)) >> verifierFilter(DigestAlgorithm::SHA256, publicKey,
418 sigBits->buf(), sigBits->size())
419 >> boolSink(isVerified);
420 }
421 if (!isVerified) {
422 m_tpm->deleteKey(keyName);
423 BOOST_THROW_EXCEPTION(Error("Certificate `" + cert.getName().toUri() + "` "
424 "and private key `" + keyName.toUri() + "` do not match"));
425 }
426
427 Identity id = m_pib->addIdentity(identity);
428 Key key = id.addKey(cert.getPublicKey().buf(), cert.getPublicKey().size(), keyName);
429 key.addCertificate(cert);
430}
431
432
433// public: signing
434
435void
436KeyChain::sign(Data& data, const SigningInfo& params)
437{
438 Name keyName;
439 SignatureInfo sigInfo;
440 std::tie(keyName, sigInfo) = prepareSignatureInfo(params);
441
442 data.setSignature(Signature(sigInfo));
443
444 EncodingBuffer encoder;
445 data.wireEncode(encoder, true);
446
447 Block sigValue = sign(encoder.buf(), encoder.size(), keyName, params.getDigestAlgorithm());
448
449 data.wireEncode(encoder, sigValue);
450}
451
452void
453KeyChain::sign(Interest& interest, const SigningInfo& params)
454{
455 Name keyName;
456 SignatureInfo sigInfo;
457 std::tie(keyName, sigInfo) = prepareSignatureInfo(params);
458
459 Name signedName = interest.getName();
460 signedName.append(sigInfo.wireEncode()); // signatureInfo
461
462 Block sigValue = sign(signedName.wireEncode().value(), signedName.wireEncode().value_size(),
463 keyName, params.getDigestAlgorithm());
464
465 sigValue.encode();
466 signedName.append(sigValue); // signatureValue
467 interest.setName(signedName);
468}
469
470Block
471KeyChain::sign(const uint8_t* buffer, size_t bufferLength, const SigningInfo& params)
472{
473 Name keyName;
474 SignatureInfo sigInfo;
475 std::tie(keyName, sigInfo) = prepareSignatureInfo(params);
476
477 return sign(buffer, bufferLength, keyName, params.getDigestAlgorithm());
478}
479
480// public: PIB/TPM creation helpers
481
482static inline std::tuple<std::string/*type*/, std::string/*location*/>
483parseLocatorUri(const std::string& uri)
484{
485 size_t pos = uri.find(':');
486 if (pos != std::string::npos) {
487 return std::make_tuple(uri.substr(0, pos), uri.substr(pos + 1));
488 }
489 else {
490 return std::make_tuple(uri, "");
491 }
492}
493
494std::tuple<std::string/*type*/, std::string/*location*/>
495KeyChain::parseAndCheckPibLocator(const std::string& pibLocator)
496{
497 std::string pibScheme, pibLocation;
498 std::tie(pibScheme, pibLocation) = parseLocatorUri(pibLocator);
499
500 if (pibScheme.empty()) {
501 pibScheme = getDefaultPibScheme();
502 }
503
504 auto pibFactory = getPibFactories().find(pibScheme);
505 if (pibFactory == getPibFactories().end()) {
506 BOOST_THROW_EXCEPTION(KeyChain::Error("PIB scheme `" + pibScheme + "` is not supported"));
507 }
508
509 return std::make_tuple(pibScheme, pibLocation);
510}
511
512unique_ptr<Pib>
513KeyChain::createPib(const std::string& pibLocator)
514{
515 std::string pibScheme, pibLocation;
516 std::tie(pibScheme, pibLocation) = parseAndCheckPibLocator(pibLocator);
517 auto pibFactory = getPibFactories().find(pibScheme);
518 BOOST_ASSERT(pibFactory != getPibFactories().end());
519 return unique_ptr<Pib>(new Pib(pibScheme, pibLocation, pibFactory->second(pibLocation)));
520}
521
522std::tuple<std::string/*type*/, std::string/*location*/>
523KeyChain::parseAndCheckTpmLocator(const std::string& tpmLocator)
524{
525 std::string tpmScheme, tpmLocation;
526 std::tie(tpmScheme, tpmLocation) = parseLocatorUri(tpmLocator);
527
528 if (tpmScheme.empty()) {
529 tpmScheme = getDefaultTpmScheme();
530 }
531 auto tpmFactory = getTpmFactories().find(tpmScheme);
532 if (tpmFactory == getTpmFactories().end()) {
533 BOOST_THROW_EXCEPTION(KeyChain::Error("TPM scheme `" + tpmScheme + "` is not supported"));
534 }
535
536 return std::make_tuple(tpmScheme, tpmLocation);
537}
538
539unique_ptr<Tpm>
540KeyChain::createTpm(const std::string& tpmLocator)
541{
542 std::string tpmScheme, tpmLocation;
543 std::tie(tpmScheme, tpmLocation) = parseAndCheckTpmLocator(tpmLocator);
544 auto tpmFactory = getTpmFactories().find(tpmScheme);
545 BOOST_ASSERT(tpmFactory != getTpmFactories().end());
546 return unique_ptr<Tpm>(new Tpm(tpmScheme, tpmLocation, tpmFactory->second(tpmLocation)));
547}
548
549// private: signing
550
551Certificate
552KeyChain::selfSign(Key& key)
553{
554 Certificate certificate;
555
556 // set name
557 Name certificateName = key.getName();
558 certificateName
559 .append("self")
560 .appendVersion();
561 certificate.setName(certificateName);
562
563 // set metainfo
564 certificate.setContentType(tlv::ContentType_Key);
565 certificate.setFreshnessPeriod(time::hours(1));
566
567 // set content
568 certificate.setContent(key.getPublicKey().buf(), key.getPublicKey().size());
569
570 // set signature-info
Alexander Afanasyev83eb1cc2017-01-04 17:34:34 -0800571 SignatureInfo signatureInfo;
Alexander Afanasyevf8379172017-01-11 16:56:04 -0800572 // Note time::system_clock::max() or other NotAfter date results in incorrect encoded value
573 // because of overflow during conversion to boost::posix_time::ptime (bug #3915).
574 signatureInfo.setValidityPeriod(ValidityPeriod(time::system_clock::TimePoint(),
575 time::system_clock::now() + time::days(20 * 365)));
Yingdi Yufe4733a2015-10-22 14:24:12 -0700576
Alexander Afanasyev83eb1cc2017-01-04 17:34:34 -0800577 sign(certificate, SigningInfo(key).setSignatureInfo(signatureInfo));
Yingdi Yufe4733a2015-10-22 14:24:12 -0700578
579 key.addCertificate(certificate);
580 return certificate;
581}
582
583std::tuple<Name, SignatureInfo>
584KeyChain::prepareSignatureInfo(const SigningInfo& params)
585{
586 SignatureInfo sigInfo = params.getSignatureInfo();
587
588 Name identityName;
589 name::Component keyId;
590 Name certificateName;
591
592 pib::Identity identity;
593 pib::Key key;
594
595 switch (params.getSignerType()) {
596 case SigningInfo::SIGNER_TYPE_NULL: {
597 try {
598 identity = m_pib->getDefaultIdentity();
599 }
600 catch (const Pib::Error&) { // no default identity, use sha256 for signing.
601 sigInfo.setSignatureType(tlv::DigestSha256);
602 return std::make_tuple(SigningInfo::getDigestSha256Identity(), sigInfo);
603 }
604 break;
605 }
606 case SigningInfo::SIGNER_TYPE_ID: {
Junxiao Shife1239a2017-01-27 20:36:12 +0000607 identity = params.getPibIdentity();
608 if (!identity) {
609 try {
610 identity = m_pib->getIdentity(params.getSignerName());
611 }
612 catch (const Pib::Error&) {
613 BOOST_THROW_EXCEPTION(InvalidSigningInfoError("Signing identity `" +
614 params.getSignerName().toUri() + "` does not exist"));
615 }
Yingdi Yufe4733a2015-10-22 14:24:12 -0700616 }
617 break;
618 }
619 case SigningInfo::SIGNER_TYPE_KEY: {
Junxiao Shife1239a2017-01-27 20:36:12 +0000620 key = params.getPibKey();
621 if (!key) {
622 Name identityName = extractIdentityFromKeyName(params.getSignerName());
Yingdi Yufe4733a2015-10-22 14:24:12 -0700623
Junxiao Shife1239a2017-01-27 20:36:12 +0000624 try {
625 identity = m_pib->getIdentity(identityName);
626 key = identity.getKey(params.getSignerName());
627 identity = Identity(); // we will use the PIB key instance, so reset identity;
628 }
629 catch (const Pib::Error&) {
630 BOOST_THROW_EXCEPTION(InvalidSigningInfoError("Signing key `" +
631 params.getSignerName().toUri() + "` does not exist"));
632 }
Yingdi Yufe4733a2015-10-22 14:24:12 -0700633 }
634 break;
635 }
636 case SigningInfo::SIGNER_TYPE_CERT: {
637 Name identityName = extractIdentityFromCertName(params.getSignerName());
638 Name keyName = extractKeyNameFromCertName(params.getSignerName());
639
640 try {
641 identity = m_pib->getIdentity(identityName);
642 key = identity.getKey(keyName);
643 }
644 catch (const Pib::Error&) {
645 BOOST_THROW_EXCEPTION(InvalidSigningInfoError("Signing certificate `" +
646 params.getSignerName().toUri() + "` does not exist"));
647 }
648
649 break;
650 }
651 case SigningInfo::SIGNER_TYPE_SHA256: {
652 sigInfo.setSignatureType(tlv::DigestSha256);
653 return std::make_tuple(SigningInfo::getDigestSha256Identity(), sigInfo);
654 }
Yingdi Yufe4733a2015-10-22 14:24:12 -0700655 default: {
656 BOOST_THROW_EXCEPTION(InvalidSigningInfoError("Unrecognized signer type " +
657 boost::lexical_cast<std::string>(params.getSignerType())));
658 }
659 }
660
661 if (!identity && !key) {
662 BOOST_THROW_EXCEPTION(InvalidSigningInfoError("Cannot determine signing parameters"));
663 }
664
665 if (identity && !key) {
666 try {
667 key = identity.getDefaultKey();
668 }
669 catch (const Pib::Error&) {
670 BOOST_THROW_EXCEPTION(InvalidSigningInfoError("Signing identity `" + identity.getName().toUri() +
671 "` does not have default certificate"));
672 }
673 }
674
675 BOOST_ASSERT(key);
676
677 sigInfo.setSignatureType(getSignatureType(key.getKeyType(), params.getDigestAlgorithm()));
678 sigInfo.setKeyLocator(KeyLocator(key.getName()));
Alexander Afanasyev7e721412017-01-11 13:36:08 -0800679
680 NDN_LOG_TRACE("Prepared signature info: " << sigInfo);
Yingdi Yufe4733a2015-10-22 14:24:12 -0700681 return std::make_tuple(key.getName(), sigInfo);
682}
683
684Block
685KeyChain::sign(const uint8_t* buf, size_t size,
686 const Name& keyName, DigestAlgorithm digestAlgorithm) const
687{
688 if (keyName == SigningInfo::getDigestSha256Identity())
Davide Pesavento10b24be2017-07-12 23:23:46 -0400689 return Block(tlv::SignatureValue, util::Sha256::computeDigest(buf, size));
Yingdi Yufe4733a2015-10-22 14:24:12 -0700690
691 return Block(tlv::SignatureValue, m_tpm->sign(buf, size, keyName, digestAlgorithm));
692}
693
694tlv::SignatureTypeValue
695KeyChain::getSignatureType(KeyType keyType, DigestAlgorithm digestAlgorithm)
696{
697 switch (keyType) {
698 case KeyType::RSA:
699 return tlv::SignatureSha256WithRsa;
700 case KeyType::EC:
701 return tlv::SignatureSha256WithEcdsa;
702 default:
703 BOOST_THROW_EXCEPTION(Error("Unsupported key types"));
704 }
705}
706
707} // namespace v2
708} // namespace security
709} // namespace ndn