/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2013-2017 Regents of the University of California.
 *
 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
 *
 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later version.
 *
 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
 *
 * You should have received copies of the GNU General Public License and GNU Lesser
 * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
 * <http://www.gnu.org/licenses/>.
 *
 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
 *
 * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
 */

#include "key-chain.hpp"
#include "../signing-helpers.hpp"

#include "../../util/random.hpp"
#include "../../util/config-file.hpp"

#include "sec-public-info-sqlite3.hpp"

#ifdef NDN_CXX_HAVE_OSX_FRAMEWORKS
#include "sec-tpm-osx.hpp"
#endif // NDN_CXX_HAVE_OSX_FRAMEWORKS

#include "sec-tpm-file.hpp"

namespace ndn {
namespace security {
namespace v1 {

// Use a GUID as a magic number of KeyChain::DEFAULT_PREFIX identifier
const Name KeyChain::DEFAULT_PREFIX("/723821fd-f534-44b3-80d9-44bf5f58bbbb");

// Note: cannot use default constructor, as it depends on static variables which may or may not be
// initialized at this point
const SigningInfo KeyChain::DEFAULT_SIGNING_INFO(SigningInfo::SIGNER_TYPE_NULL, Name(), SignatureInfo());

const RsaKeyParams KeyChain::DEFAULT_KEY_PARAMS;

const std::string DEFAULT_PIB_SCHEME = "pib-sqlite3";

#if defined(NDN_CXX_HAVE_OSX_FRAMEWORKS) and defined(NDN_CXX_WITH_OSX_KEYCHAIN)
const std::string DEFAULT_TPM_SCHEME = "tpm-osxkeychain";
#else
const std::string DEFAULT_TPM_SCHEME = "tpm-file";
#endif // defined(NDN_CXX_HAVE_OSX_FRAMEWORKS) and defined(NDN_CXX_WITH_OSX_KEYCHAIN)

// When static library is used, not everything is compiled into the resulting binary.
// Therefore, the following standard PIB and TPMs need to be registered here.
// http://stackoverflow.com/q/9459980/2150331
//
// Also, cannot use Type::SCHEME, as its value may be uninitialized
NDN_CXX_V1_KEYCHAIN_REGISTER_PIB(SecPublicInfoSqlite3, "pib-sqlite3", "sqlite3");

#ifdef NDN_CXX_HAVE_OSX_FRAMEWORKS
NDN_CXX_V1_KEYCHAIN_REGISTER_TPM(SecTpmOsx, "tpm-osxkeychain", "osx-keychain");
#endif // NDN_CXX_HAVE_OSX_FRAMEWORKS

NDN_CXX_V1_KEYCHAIN_REGISTER_TPM(SecTpmFile, "tpm-file", "file");

template<class T>
struct Factory
{
  Factory(const std::string& canonicalName, const T& create)
    : canonicalName(canonicalName)
    , create(create)
  {
  }

  std::string canonicalName;
  T create;
};
typedef Factory<KeyChain::PibCreateFunc> PibFactory;
typedef Factory<KeyChain::TpmCreateFunc> TpmFactory;

static std::map<std::string, PibFactory>&
getPibFactories()
{
  static std::map<std::string, PibFactory> pibFactories;
  return pibFactories;
}

static std::map<std::string, TpmFactory>&
getTpmFactories()
{
  static std::map<std::string, TpmFactory> tpmFactories;
  return tpmFactories;
}

void
KeyChain::registerPibImpl(const std::string& canonicalName,
                          std::initializer_list<std::string> aliases,
                          KeyChain::PibCreateFunc createFunc)
{
  for (const std::string& alias : aliases) {
    getPibFactories().insert(make_pair(alias, PibFactory(canonicalName, createFunc)));
  }
}

void
KeyChain::registerTpmImpl(const std::string& canonicalName,
                          std::initializer_list<std::string> aliases,
                          KeyChain::TpmCreateFunc createFunc)
{
  for (const std::string& alias : aliases) {
    getTpmFactories().insert(make_pair(alias, TpmFactory(canonicalName, createFunc)));
  }
}

KeyChain::KeyChain()
  : m_pib(nullptr)
  , m_tpm(nullptr)
  , m_lastTimestamp(time::toUnixTimestamp(time::system_clock::now()))
{
  std::string pibLocator;
  std::string tpmLocator;

  if (getenv("NDN_CLIENT_PIB") != nullptr) {
    pibLocator = getenv("NDN_CLIENT_PIB");
  }

  if (getenv("NDN_CLIENT_TPM") != nullptr) {
    tpmLocator = getenv("NDN_CLIENT_TPM");
  }

  if (pibLocator.empty() || tpmLocator.empty()) {
    ConfigFile config;
    const ConfigFile::Parsed& parsed = config.getParsedConfiguration();

    if (pibLocator.empty()) {
      pibLocator = parsed.get<std::string>("pib", "");
    }

    if (tpmLocator.empty()) {
      tpmLocator = parsed.get<std::string>("tpm", "");
    }
  }

  initialize(pibLocator, tpmLocator, false);
}

KeyChain::KeyChain(const std::string& pibName,
                   const std::string& tpmName,
                   bool allowReset)
  : m_pib(nullptr)
  , m_tpm(nullptr)
  , m_lastTimestamp(time::toUnixTimestamp(time::system_clock::now()))
{
  initialize(pibName, tpmName, allowReset);
}

KeyChain::~KeyChain()
{
}

static inline std::tuple<std::string/*type*/, std::string/*location*/>
parseUri(const std::string& uri)
{
  size_t pos = uri.find(':');
  if (pos != std::string::npos) {
    return std::make_tuple(uri.substr(0, pos),
                           uri.substr(pos + 1));
  }
  else {
    return std::make_tuple(uri, "");
  }
}

std::string
KeyChain::getDefaultPibLocator()
{
  std::string defaultPibLocator = DEFAULT_PIB_SCHEME + ":";
  return defaultPibLocator;
}

static inline std::tuple<std::string/*type*/, std::string/*location*/>
getCanonicalPibLocator(const std::string& pibLocator)
{
  std::string pibScheme, pibLocation;
  std::tie(pibScheme, pibLocation) = parseUri(pibLocator);

  if (pibScheme.empty()) {
    pibScheme = DEFAULT_PIB_SCHEME;
  }

  auto pibFactory = getPibFactories().find(pibScheme);
  if (pibFactory == getPibFactories().end()) {
    BOOST_THROW_EXCEPTION(KeyChain::Error("PIB scheme '" + pibScheme + "' is not supported"));
  }
  pibScheme = pibFactory->second.canonicalName;

  return std::make_tuple(pibScheme, pibLocation);
}

unique_ptr<SecPublicInfo>
KeyChain::createPib(const std::string& pibLocator)
{
  BOOST_ASSERT(!getPibFactories().empty());

  std::string pibScheme, pibLocation;
  std::tie(pibScheme, pibLocation) = getCanonicalPibLocator(pibLocator);
  auto pibFactory = getPibFactories().find(pibScheme);
  BOOST_ASSERT(pibFactory != getPibFactories().end());
  return pibFactory->second.create(pibLocation);
}

std::string
KeyChain::getDefaultTpmLocator()
{
  std::string defaultTpmLocator = DEFAULT_TPM_SCHEME + ":";
  return defaultTpmLocator;
}

static inline std::tuple<std::string/*type*/, std::string/*location*/>
getCanonicalTpmLocator(const std::string& tpmLocator)
{
  std::string tpmScheme, tpmLocation;
  std::tie(tpmScheme, tpmLocation) = parseUri(tpmLocator);

  if (tpmScheme.empty()) {
    tpmScheme = DEFAULT_TPM_SCHEME;
  }
  auto tpmFactory = getTpmFactories().find(tpmScheme);
  if (tpmFactory == getTpmFactories().end()) {
    BOOST_THROW_EXCEPTION(KeyChain::Error("TPM scheme '" + tpmScheme + "' is not supported"));
  }
  tpmScheme = tpmFactory->second.canonicalName;

  return std::make_tuple(tpmScheme, tpmLocation);
}

unique_ptr<SecTpm>
KeyChain::createTpm(const std::string& tpmLocator)
{
  BOOST_ASSERT(!getTpmFactories().empty());

  std::string tpmScheme, tpmLocation;
  std::tie(tpmScheme, tpmLocation) = getCanonicalTpmLocator(tpmLocator);
  auto tpmFactory = getTpmFactories().find(tpmScheme);
  BOOST_ASSERT(tpmFactory != getTpmFactories().end());
  return tpmFactory->second.create(tpmLocation);
}

void
KeyChain::initialize(const std::string& pibLocator,
                     const std::string& tpmLocator,
                     bool allowReset)
{
  // PIB Locator
  std::string pibScheme, pibLocation;
  std::tie(pibScheme, pibLocation) = getCanonicalPibLocator(pibLocator);
  std::string canonicalPibLocator = pibScheme + ":" + pibLocation;

  // Create PIB
  m_pib = createPib(canonicalPibLocator);

  // TPM Locator
  std::string tpmScheme, tpmLocation;
  std::tie(tpmScheme, tpmLocation) = getCanonicalTpmLocator(tpmLocator);
  std::string canonicalTpmLocator = tpmScheme + ":" + tpmLocation;

  // Create TPM, checking that it matches to the previously associated one
  try {
    if (!allowReset &&
        !m_pib->getTpmLocator().empty() && m_pib->getTpmLocator() != canonicalTpmLocator)
      // Tpm mismatch, but we do not want to reset PIB
      BOOST_THROW_EXCEPTION(MismatchError("TPM locator supplied does not match TPM locator in PIB: "
                                          + m_pib->getTpmLocator() + " != " + canonicalTpmLocator));
  }
  catch (const SecPublicInfo::Error&) {
    // TPM locator is not set in PIB yet.
  }

  // note that key mismatch may still happen if the TPM locator is initially set to a
  // wrong one or if the PIB was shared by more than one TPMs before.  This is due to the
  // old PIB does not have TPM info, new pib should not have this problem.
  m_tpm = createTpm(canonicalTpmLocator);
  m_pib->setTpmLocator(canonicalTpmLocator);
}

Name
KeyChain::createIdentity(const Name& identityName, const KeyParams& params)
{
  m_pib->addIdentity(identityName);

  Name keyName;
  try {
    keyName = m_pib->getDefaultKeyNameForIdentity(identityName);

    shared_ptr<PublicKey> key = m_pib->getPublicKey(keyName);

    if (key->getKeyType() != params.getKeyType()) {
      keyName = generateKeyPair(identityName, true, params);
      m_pib->setDefaultKeyNameForIdentity(keyName);
    }
  }
  catch (const SecPublicInfo::Error& e) {
    keyName = generateKeyPair(identityName, true, params);
    m_pib->setDefaultKeyNameForIdentity(keyName);
  }

  Name certName;
  try {
    certName = m_pib->getDefaultCertificateNameForKey(keyName);
  }
  catch (const SecPublicInfo::Error& e) {
    shared_ptr<IdentityCertificate> selfCert = selfSign(keyName);
    m_pib->addCertificateAsIdentityDefault(*selfCert);
    certName = selfCert->getName();
  }

  return certName;
}

Name
KeyChain::generateRsaKeyPair(const Name& identityName, bool isKsk, uint32_t keySize)
{
  RsaKeyParams params(keySize);
  return generateKeyPair(identityName, isKsk, params);
}

Name
KeyChain::generateEcKeyPair(const Name& identityName, bool isKsk, uint32_t keySize)
{
  EcKeyParams params(keySize);
  return generateKeyPair(identityName, isKsk, params);
}

Name
KeyChain::generateRsaKeyPairAsDefault(const Name& identityName, bool isKsk, uint32_t keySize)
{
  Name keyName = generateRsaKeyPair(identityName, isKsk, keySize);

  m_pib->setDefaultKeyNameForIdentity(keyName);

  return keyName;
}

Name
KeyChain::generateEcKeyPairAsDefault(const Name& identityName, bool isKsk, uint32_t keySize)
{
  Name keyName = generateEcKeyPair(identityName, isKsk, keySize);

  m_pib->setDefaultKeyNameForIdentity(keyName);

  return keyName;
}


shared_ptr<IdentityCertificate>
KeyChain::prepareUnsignedIdentityCertificate(const Name& keyName,
  const Name& signingIdentity,
  const time::system_clock::TimePoint& notBefore,
  const time::system_clock::TimePoint& notAfter,
  const std::vector<CertificateSubjectDescription>& subjectDescription,
  const Name& certPrefix)
{
  shared_ptr<PublicKey> publicKey;
  try {
    publicKey = m_pib->getPublicKey(keyName);
  }
  catch (const SecPublicInfo::Error& e) {
    return nullptr;
  }

  return prepareUnsignedIdentityCertificate(keyName, *publicKey, signingIdentity,
                                            notBefore, notAfter,
                                            subjectDescription, certPrefix);
}

shared_ptr<IdentityCertificate>
KeyChain::prepareUnsignedIdentityCertificate(const Name& keyName,
  const PublicKey& publicKey,
  const Name& signingIdentity,
  const time::system_clock::TimePoint& notBefore,
  const time::system_clock::TimePoint& notAfter,
  const std::vector<CertificateSubjectDescription>& subjectDescription,
  const Name& certPrefix)
{
  if (keyName.size() < 1)
    return nullptr;

  std::string keyIdPrefix = keyName.get(-1).toUri().substr(0, 4);
  if (keyIdPrefix != "ksk-" && keyIdPrefix != "dsk-")
    return nullptr;

  Name certName;

  if (certPrefix == KeyChain::DEFAULT_PREFIX) {
    // No certificate prefix hint, infer the prefix
    if (signingIdentity.isPrefixOf(keyName))
      certName.append(signingIdentity)
        .append("KEY")
        .append(keyName.getSubName(signingIdentity.size()))
        .append("ID-CERT")
        .appendVersion();
    else
      certName.append(keyName.getPrefix(-1))
        .append("KEY")
        .append(keyName.get(-1))
        .append("ID-CERT")
        .appendVersion();
  }
  else {
    // cert prefix hint is supplied, determine the cert name.
    if (certPrefix.isPrefixOf(keyName) && certPrefix != keyName)
      certName.append(certPrefix)
        .append("KEY")
        .append(keyName.getSubName(certPrefix.size()))
        .append("ID-CERT")
        .appendVersion();
    else
      return nullptr;
  }

  auto certificate = make_shared<IdentityCertificate>();
  certificate->setName(certName);
  certificate->setNotBefore(notBefore);
  certificate->setNotAfter(notAfter);
  certificate->setPublicKeyInfo(publicKey);

  if (subjectDescription.empty()) {
    CertificateSubjectDescription subjectName(oid::ATTRIBUTE_NAME, keyName.getPrefix(-1).toUri());
    certificate->addSubjectDescription(subjectName);
  }
  else {
    std::vector<CertificateSubjectDescription>::const_iterator sdIt = subjectDescription.begin();
    std::vector<CertificateSubjectDescription>::const_iterator sdEnd = subjectDescription.end();
    for(; sdIt != sdEnd; sdIt++)
      certificate->addSubjectDescription(*sdIt);
  }

  certificate->encode();

  return certificate;
}

std::tuple<Name, SignatureInfo>
KeyChain::prepareSignatureInfo(const SigningInfo& params)
{
  SignatureInfo sigInfo = params.getSignatureInfo();

  shared_ptr<IdentityCertificate> signingCert;

  switch (params.getSignerType()) {
    case SigningInfo::SIGNER_TYPE_NULL: {
      if (m_pib->getDefaultCertificate() == nullptr)
        setDefaultCertificateInternal();

      signingCert = m_pib->getDefaultCertificate();
      break;
    }
    case SigningInfo::SIGNER_TYPE_ID:  {
      Name signingCertName;
      try {
        signingCertName = m_pib->getDefaultCertificateNameForIdentity(params.getSignerName());
      }
      catch (const SecPublicInfo::Error&) {
        signingCertName = createIdentity(params.getSignerName(), getDefaultKeyParamsForIdentity(params.getSignerName()));
      }

      signingCert = m_pib->getCertificate(signingCertName);

      break;
    }
    case SigningInfo::SIGNER_TYPE_KEY: {
      Name signingCertName;
      try {
        signingCertName = m_pib->getDefaultCertificateNameForKey(params.getSignerName());
      }
      catch (const SecPublicInfo::Error&) {
        BOOST_THROW_EXCEPTION(Error("signing certificate does not exist"));
      }

      signingCert = m_pib->getCertificate(signingCertName);

      break;
    }
    case SigningInfo::SIGNER_TYPE_CERT: {
      signingCert = m_pib->getCertificate(params.getSignerName());
      if (signingCert == nullptr)
        BOOST_THROW_EXCEPTION(Error("signing certificate does not exist"));

      break;
    }
    case SigningInfo::SIGNER_TYPE_SHA256: {
      sigInfo.setSignatureType(tlv::DigestSha256);
      return std::make_tuple(SigningInfo::getDigestSha256Identity(), sigInfo);
    }
    default:
      BOOST_THROW_EXCEPTION(Error("Unrecognized signer type"));
  }

  sigInfo.setSignatureType(getSignatureType(signingCert->getPublicKeyInfo().getKeyType(),
                                            params.getDigestAlgorithm()));
  sigInfo.setKeyLocator(KeyLocator(signingCert->getName().getPrefix(-1)));

  return std::make_tuple(signingCert->getPublicKeyName(), sigInfo);
}

void
KeyChain::sign(Data& data, const SigningInfo& params)
{
  signImpl(data, params);
}

void
KeyChain::sign(Interest& interest, const SigningInfo& params)
{
  signImpl(interest, params);
}

Block
KeyChain::sign(const uint8_t* buffer, size_t bufferLength, const SigningInfo& params)
{
  Name keyName;
  SignatureInfo sigInfo;
  std::tie(keyName, sigInfo) = prepareSignatureInfo(params);
  return pureSign(buffer, bufferLength, keyName, DigestAlgorithm::SHA256);
}

Signature
KeyChain::sign(const uint8_t* buffer, size_t bufferLength, const Name& certificateName)
{
  shared_ptr<IdentityCertificate> certificate = m_pib->getCertificate(certificateName);

  if (certificate == nullptr) {
    BOOST_THROW_EXCEPTION(SecPublicInfo::Error("certificate does not exist"));
  }

  Signature sig;

  // For temporary usage, we support SHA256 only, but will support more.
  sig.setValue(m_tpm->signInTpm(buffer, bufferLength,
                                certificate->getPublicKeyName(),
                                DigestAlgorithm::SHA256));

  return sig;
}

shared_ptr<IdentityCertificate>
KeyChain::selfSign(const Name& keyName)
{
  shared_ptr<PublicKey> pubKey;
  try {
    pubKey = m_pib->getPublicKey(keyName); // may throw an exception.
  }
  catch (const SecPublicInfo::Error&) {
    return nullptr;
  }

  auto certificate = make_shared<IdentityCertificate>();

  Name certificateName = keyName.getPrefix(-1);
  certificateName.append("KEY").append(keyName.get(-1)).append("ID-CERT").appendVersion();

  certificate->setName(certificateName);
  certificate->setNotBefore(time::system_clock::now());
  certificate->setNotAfter(time::system_clock::now() + time::days(7300)); // ~20 years
  certificate->setPublicKeyInfo(*pubKey);
  certificate->addSubjectDescription(CertificateSubjectDescription(oid::ATTRIBUTE_NAME,
                                                                       keyName.toUri()));
  certificate->encode();

  certificate->setSignature(Signature(SignatureInfo()));

  selfSign(*certificate);
  return certificate;
}

void
KeyChain::selfSign(IdentityCertificate& cert)
{
  Name keyName = cert.getPublicKeyName();

  if (!m_tpm->doesKeyExistInTpm(keyName, KeyClass::PRIVATE))
    BOOST_THROW_EXCEPTION(SecTpm::Error("Private key does not exist"));

  SignatureInfo sigInfo(cert.getSignature().getInfo());
  sigInfo.setKeyLocator(KeyLocator(cert.getName().getPrefix(-1)));
  sigInfo.setSignatureType(getSignatureType(cert.getPublicKeyInfo().getKeyType(),
                                            DigestAlgorithm::SHA256));

  signPacketWrapper(cert, Signature(sigInfo), keyName, DigestAlgorithm::SHA256);
}

shared_ptr<SecuredBag>
KeyChain::exportIdentity(const Name& identity, const std::string& passwordStr)
{
  if (!m_pib->doesIdentityExist(identity))
    BOOST_THROW_EXCEPTION(SecPublicInfo::Error("Identity does not exist"));

  Name keyName = m_pib->getDefaultKeyNameForIdentity(identity);

  ConstBufferPtr pkcs5;
  try {
    pkcs5 = m_tpm->exportPrivateKeyPkcs5FromTpm(keyName, passwordStr);
  }
  catch (const SecTpm::Error& e) {
    BOOST_THROW_EXCEPTION(SecPublicInfo::Error("Fail to export PKCS5 of private key"));
  }

  shared_ptr<IdentityCertificate> cert;
  try {
    cert = m_pib->getCertificate(m_pib->getDefaultCertificateNameForKey(keyName));
  }
  catch (const SecPublicInfo::Error& e) {
    cert = selfSign(keyName);
    m_pib->addCertificateAsIdentityDefault(*cert);
  }

  // make_shared on OSX 10.9 has some strange problem here
  return shared_ptr<SecuredBag>(new SecuredBag(*cert, pkcs5));
}

void
KeyChain::importIdentity(const SecuredBag& securedBag, const std::string& passwordStr)
{
  Name certificateName = securedBag.getCertificate().getName();
  Name keyName = IdentityCertificate::certificateNameToPublicKeyName(certificateName);
  Name identity = keyName.getPrefix(-1);

  // Add identity
  m_pib->addIdentity(identity);

  // Add key
  m_tpm->importPrivateKeyPkcs5IntoTpm(keyName,
                                      securedBag.getKey()->buf(),
                                      securedBag.getKey()->size(),
                                      passwordStr);

  shared_ptr<PublicKey> pubKey = m_tpm->getPublicKeyFromTpm(keyName.toUri());
  // HACK! We should set key type according to the pkcs8 info.
  m_pib->addKey(keyName, *pubKey);
  m_pib->setDefaultKeyNameForIdentity(keyName);

  // Add cert
  m_pib->addCertificateAsIdentityDefault(securedBag.getCertificate());
}

const KeyParams&
KeyChain::getDefaultKeyParamsForIdentity(const Name& identityName) const
{
  KeyType keyType = KeyType::NONE;
  try {
    keyType = m_pib->getPublicKeyType(m_pib->getDefaultKeyNameForIdentity(identityName));
  }
  catch (const SecPublicInfo::Error& e) { // @TODO Switch to Pib::Error
    return DEFAULT_KEY_PARAMS;
  }

  switch (keyType) {
    case KeyType::RSA: {
      static RsaKeyParams defaultRsaParams;
      return defaultRsaParams;
    }
    case KeyType::EC: {
      static EcKeyParams defaultEcParams;
      return defaultEcParams;
    }
    case KeyType::NONE: {
      return DEFAULT_KEY_PARAMS;
    }
    default:
      BOOST_THROW_EXCEPTION(Error("Unsupported key type"));
  }
}

void
KeyChain::setDefaultCertificateInternal()
{
  m_pib->refreshDefaultCertificate();

  if (m_pib->getDefaultCertificate() == nullptr) {
    Name defaultIdentity;
    try {
      defaultIdentity = m_pib->getDefaultIdentity();
    }
    catch (const SecPublicInfo::Error& e) {
      uint32_t random = random::generateWord32();
      defaultIdentity.append("tmp-identity")
        .append(reinterpret_cast<uint8_t*>(&random), 4);
    }
    createIdentity(defaultIdentity);
    m_pib->setDefaultIdentity(defaultIdentity);
    m_pib->refreshDefaultCertificate();
  }
}

Name
KeyChain::generateKeyPair(const Name& identityName, bool isKsk, const KeyParams& params)
{
  Name keyName = m_pib->getNewKeyName(identityName, isKsk);

  m_tpm->generateKeyPairInTpm(keyName.toUri(), params);

  shared_ptr<PublicKey> pubKey = m_tpm->getPublicKeyFromTpm(keyName.toUri());
  m_pib->addKey(keyName, *pubKey);

  return keyName;
}

void
KeyChain::signPacketWrapper(Data& data, const Signature& signature,
                            const Name& keyName, DigestAlgorithm digestAlgorithm)
{
  data.setSignature(signature);

  EncodingBuffer encoder;
  data.wireEncode(encoder, true);

  Block sigValue = pureSign(encoder.buf(), encoder.size(), keyName, digestAlgorithm);

  data.wireEncode(encoder, sigValue);
}

void
KeyChain::signPacketWrapper(Interest& interest, const Signature& signature,
                            const Name& keyName, DigestAlgorithm digestAlgorithm)
{
  time::milliseconds timestamp = time::toUnixTimestamp(time::system_clock::now());
  if (timestamp <= m_lastTimestamp) {
    timestamp = m_lastTimestamp + time::milliseconds(1);
  }

  Name signedName = interest.getName();
  signedName
    .append(name::Component::fromNumber(timestamp.count()))        // timestamp
    .append(name::Component::fromNumber(random::generateWord64())) // nonce
    .append(signature.getInfo());                                  // signatureInfo

  Block sigValue = pureSign(signedName.wireEncode().value(),
                            signedName.wireEncode().value_size(),
                            keyName,
                            digestAlgorithm);

  sigValue.encode();
  signedName.append(sigValue);                                     // signatureValue
  interest.setName(signedName);
}

Block
KeyChain::pureSign(const uint8_t* buf, size_t size,
                   const Name& keyName, DigestAlgorithm digestAlgorithm) const
{
  if (keyName == SigningInfo::getDigestSha256Identity())
    return Block(tlv::SignatureValue, crypto::computeSha256Digest(buf, size));

  return m_tpm->signInTpm(buf, size, keyName, digestAlgorithm);
}

Signature
KeyChain::signByIdentity(const uint8_t* buffer, size_t bufferLength, const Name& identityName)
{
  Signature sig;
  sig.setValue(sign(buffer, bufferLength, signingByIdentity(identityName)));
  return sig;
}

void
KeyChain::signWithSha256(Data& data)
{
  return sign(data, signingWithSha256());
}

void
KeyChain::signWithSha256(Interest& interest)
{
  DigestSha256 sig;

  time::milliseconds timestamp = time::toUnixTimestamp(time::system_clock::now());
  if (timestamp <= m_lastTimestamp)
    timestamp = m_lastTimestamp + time::milliseconds(1);

  Name signedName = interest.getName();
  signedName
    .append(name::Component::fromNumber(timestamp.count()))        // timestamp
    .append(name::Component::fromNumber(random::generateWord64())) // nonce
    .append(sig.getInfo());                                        // signatureInfo

  Block sigValue(tlv::SignatureValue,
                 crypto::computeSha256Digest(signedName.wireEncode().value(),
                                             signedName.wireEncode().value_size()));

  sigValue.encode();
  signedName.append(sigValue);                                     // signatureValue
  interest.setName(signedName);
}

void
KeyChain::deleteCertificate(const Name& certificateName)
{
  m_pib->deleteCertificateInfo(certificateName);
}

void
KeyChain::deleteKey(const Name& keyName)
{
  m_pib->deletePublicKeyInfo(keyName);
  m_tpm->deleteKeyPairInTpm(keyName);
}

void
KeyChain::deleteIdentity(const Name& identity)
{
  std::vector<Name> keyNames;
  m_pib->getAllKeyNamesOfIdentity(identity, keyNames, true);
  m_pib->getAllKeyNamesOfIdentity(identity, keyNames, false);

  m_pib->deleteIdentityInfo(identity);

  for (const auto& keyName : keyNames)
    m_tpm->deleteKeyPairInTpm(keyName);
}

tlv::SignatureTypeValue
KeyChain::getSignatureType(KeyType keyType, DigestAlgorithm digestAlgorithm)
{
  switch (keyType) {
    case KeyType::RSA:
      return tlv::SignatureSha256WithRsa;
    case KeyType::EC:
      return tlv::SignatureSha256WithEcdsa;
    default:
      BOOST_THROW_EXCEPTION(Error("Unsupported key types"));
  }
}

} // namespace v1
} // namespace security
} // namespace ndn
