/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
/**
 * Copyright (C) 2013 Regents of the University of California.
 * @author: Yingdi Yu <yingdi@cs.ucla.edu>
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * See COPYING for copyright and distribution information.
 */

#ifndef NDN_SECURITY_KEY_CHAIN_HPP
#define NDN_SECURITY_KEY_CHAIN_HPP

#include "identity-certificate.hpp"
#include "public-key.hpp"
#include "signature-sha256-with-rsa.hpp"
#include "signature-sha256.hpp"
#include "secured-bag.hpp"
#include "../interest.hpp"
#include "../util/random.hpp"
#include "../util/crypto.hpp"

//PublicInfo
#include "sec-public-info-sqlite3.hpp"
#include "sec-public-info-memory.hpp"
//TPM
#include "sec-tpm-file.hpp"
#include "sec-tpm-memory.hpp"

#ifdef NDN_CPP_HAVE_OSX_SECURITY
#include "sec-tpm-osx.hpp"
#endif


namespace ndn {

/**
 * @brief KeyChain is one of the main classes of the security library.
 *
 * The KeyChain class provides a set of interfaces of identity management and private key related operations.
 */
template<class Info, class Tpm>
class KeyChainImpl : public Info, public Tpm
{
  typedef SecPublicInfo::Error InfoError;
  typedef SecTpm::Error TpmError;
public:
  /**
   * @brief Create an identity by creating a pair of Key-Signing-Key (KSK) for this identity and a self-signed certificate of the KSK.
   *
   * @param identityName The name of the identity.
   * @return The name of the default certificate of the identity.
   */
  Name
  createIdentity(const Name& identityName)
  {
    Info::addIdentity(identityName);

    Name keyName;
    try
      {
        keyName = Info::getDefaultKeyNameForIdentity(identityName);
      }
    catch (InfoError& e)
      {
        keyName = generateRSAKeyPairAsDefault(identityName, true);
      }

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

    return certName;
  }

  /**
   * @brief Generate a pair of RSA keys for the specified identity.
   *
   * @param identityName The name of the identity.
   * @param isKsk true for generating a Key-Signing-Key (KSK), false for a Data-Signing-Key (KSK).
   * @param keySize The size of the key.
   * @return The generated key name.
   */
  Name
  generateRSAKeyPair(const Name& identityName, bool isKsk = false, int keySize = 2048)
  {
    return generateKeyPair(identityName, isKsk, KEY_TYPE_RSA, keySize);
  }

  /**
   * @brief Generate a pair of RSA keys for the specified identity and set it as default key for the identity.
   *
   * @param identityName The name of the identity.
   * @param isKsk true for generating a Key-Signing-Key (KSK), false for a Data-Signing-Key (KSK).
   * @param keySize The size of the key.
   * @return The generated key name.
   */
  Name
  generateRSAKeyPairAsDefault(const Name& identityName, bool isKsk = false, int keySize = 2048)
  {
    Name keyName = generateKeyPair(identityName, isKsk, KEY_TYPE_RSA, keySize);

    Info::setDefaultKeyNameForIdentity(keyName);

    return keyName;
  }

  /**
   * @brief prepare an unsigned identity certificate
   *
   * @param keyName Key name, e.g., /<identity_name>/ksk-123456.
   * @param signingIdentity The signing identity.
   * @param notBefore Refer to IdentityCertificate.
   * @param notAfter Refer to IdentityCertificate.
   * @param subjectDescription Refer to IdentityCertificate.
   * @return IdentityCertificate.
   */
  shared_ptr<IdentityCertificate>
  prepareUnsignedIdentityCertificate(const Name& keyName,
                                     const Name& signingIdentity,
                                     const time::system_clock::TimePoint& notBefore,
                                     const time::system_clock::TimePoint& notAfter,
                                     const std::vector<CertificateSubjectDescription>& subjectDescription)

  {
    if (keyName.size() < 1)
      return shared_ptr<IdentityCertificate>();

    std::string keyIdPrefix = keyName.get(-1).toEscapedString().substr(0, 4);
    if (keyIdPrefix != "ksk-" && keyIdPrefix != "dsk-")
      return shared_ptr<IdentityCertificate>();

    shared_ptr<IdentityCertificate> certificate = make_shared<IdentityCertificate>();
    Name certName;

    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();
      }

    certificate->setName(certName);
    certificate->setNotBefore(notBefore);
    certificate->setNotAfter(notAfter);

    shared_ptr<PublicKey> publicKey;
    try
      {
        publicKey = Info::getPublicKey(keyName);
      }
    catch (InfoError& e)
      {
        return shared_ptr<IdentityCertificate>();
      }
    certificate->setPublicKeyInfo(*publicKey);

    if (subjectDescription.empty())
      {
        CertificateSubjectDescription subDescryptName("2.5.4.41", keyName.getPrefix(-1).toUri());
        certificate->addSubjectDescription(subDescryptName);
      }
    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;
  }

  /**
   * @brief Sign packet with default identity
   *
   * On return, signatureInfo and signatureValue in the packet are set.
   * If default identity does not exist,
   * a temporary identity will be created and set as default.
   *
   * @param packet The packet to be signed
   */
  template<typename T>
  void
  sign(T& packet)
  {
    if (!static_cast<bool>(Info::defaultCertificate()))
      {
        Info::refreshDefaultCertificate();

        if (!static_cast<bool>(Info::defaultCertificate()))
          {
            Name defaultIdentity;
            try
              {
                defaultIdentity = Info::getDefaultIdentity();
              }
            catch (InfoError& e)
              {
                uint32_t random = random::generateWord32();
                defaultIdentity.append("tmp-identity")
                  .append(reinterpret_cast<uint8_t*>(&random), 4);
              }
            createIdentity(defaultIdentity);
            Info::setDefaultIdentity(defaultIdentity);
            Info::refreshDefaultCertificate();
          }
      }

    sign(packet, *Info::defaultCertificate());
  }

  /**
   * @brief Sign packet with a particular certificate.
   *
   * @param packet The packet to be signed.
   * @param certificateName The certificate name of the key to use for signing.
   * @throws SecPublicInfo::Error if certificate does not exist.
   */
  template<typename T>
  void
  sign(T& packet, const Name& certificateName)
  {
    if (!Info::doesCertificateExist(certificateName))
      throw InfoError("Requested certificate [" + certificateName.toUri() + "] doesn't exist");

    SignatureSha256WithRsa signature;
    signature.setKeyLocator(certificateName.getPrefix(-1)); // implicit conversion should take care

    // For temporary usage, we support RSA + SHA256 only, but will support more.
    signPacketWrapper(packet, signature,
                      IdentityCertificate::certificateNameToPublicKeyName(certificateName),
                      DIGEST_ALGORITHM_SHA256);
  }

  /**
   * @brief Sign the byte array using a particular certificate.
   *
   * @param buffer The byte array to be signed.
   * @param bufferLength the length of buffer.
   * @param certificateName The certificate name of the signing key.
   * @return The Signature.
   * @throws SecPublicInfo::Error if certificate does not exist.
   */
  Signature
  sign(const uint8_t* buffer, size_t bufferLength, const Name& certificateName)
  {
    if (!Info::doesCertificateExist(certificateName))
      throw InfoError("Requested certificate [" + certificateName.toUri() + "] doesn't exist");

    SignatureSha256WithRsa signature;
    signature.setKeyLocator(certificateName.getPrefix(-1)); // implicit conversion should take care

    // For temporary usage, we support RSA + SHA256 only, but will support more.
    signature.setValue(Tpm::signInTpm(buffer, bufferLength,
                                      IdentityCertificate::certificateNameToPublicKeyName(certificateName),
                                      DIGEST_ALGORITHM_SHA256));
    return signature;
  }

  /**
   * @brief Sign packet using the default certificate of a particular identity.
   *
   * If there is no default certificate of that identity, this method will create a self-signed certificate.
   *
   * @param packet The packet to be signed.
   * @param identityName The signing identity name.
   */
  template<typename T>
  void
  signByIdentity(T& packet, const Name& identityName)
  {
    Name signingCertificateName;
    try
      {
        signingCertificateName = Info::getDefaultCertificateNameForIdentity(identityName);
      }
    catch (InfoError& e)
      {
        signingCertificateName = createIdentity(identityName);
        // Ideally, no exception will be thrown out, unless something goes wrong in the TPM, which is a fatal error.
      }

    // We either get or create the signing certificate, sign packet! (no exception unless fatal error in TPM)
    sign(packet, signingCertificateName);
  }

  /**
   * @brief Sign the byte array using the default certificate of a particular identity.
   *
   * @param buffer The byte array to be signed.
   * @param bufferLength the length of buffer.
   * @param identityName The identity name.
   * @return The Signature.
   */
  Signature
  signByIdentity(const uint8_t* buffer, size_t bufferLength, const Name& identityName)
  {
    Name signingCertificateName;
    try
      {
        signingCertificateName = Info::getDefaultCertificateNameForIdentity(identityName);
      }
    catch (InfoError& e)
      {
        signingCertificateName = createIdentity(identityName);
        // Ideally, no exception will be thrown out, unless something goes wrong in the TPM, which is a fatal error.
      }

    // We either get or create the signing certificate, sign data! (no exception unless fatal error in TPM)
    return sign(buffer, bufferLength, signingCertificateName);
  }

  /**
   * @brief Set Sha256 weak signature.
   *
   * @param data.
   */
  void
  signWithSha256(Data& data)
  {
    SignatureSha256 sig;
    data.setSignature(sig);

    Block sigValue(Tlv::SignatureValue,
                   crypto::sha256(data.wireEncode().value(),
                                  data.wireEncode().value_size() - data.getSignature().getValue().size()));
    data.setSignatureValue(sigValue);

  }

  /**
   * @brief Generate a self-signed certificate for a public key.
   *
   * @param keyName The name of the public key.
   * @return The generated certificate, NULL if selfSign fails.
   */
  shared_ptr<IdentityCertificate>
  selfSign(const Name& keyName)
  {
    shared_ptr<PublicKey> pubKey;
    try
      {
        pubKey = Info::getPublicKey(keyName); // may throw an exception.
      }
    catch (InfoError& e)
      {
        return shared_ptr<IdentityCertificate>();
      }

    shared_ptr<IdentityCertificate> 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("2.5.4.41", keyName.toUri()));
    certificate->encode();

    selfSign(*certificate);
    return certificate;
  }

  /**
   * @brief Self-sign the supplied identity certificate.
   *
   * @param cert The supplied cert.
   * @throws SecTpm::Error if the private key does not exist.
   */
  void
  selfSign (IdentityCertificate& cert)
  {
    Name keyName = IdentityCertificate::certificateNameToPublicKeyName(cert.getName());
    if (!Tpm::doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE))
      throw TpmError("private key does not exist!");

    SignatureSha256WithRsa signature;
    signature.setKeyLocator(cert.getName().getPrefix(-1)); // implicit conversion should take care

    // For temporary usage, we support RSA + SHA256 only, but will support more.
    signPacketWrapper(cert, signature, keyName, DIGEST_ALGORITHM_SHA256);
  }

  /**
   * @brief delete a certificate.
   *
   * If the certificate to be deleted is current default system default,
   * the method will not delete the certificate and return immediately.
   *
   * @param certificateName The certificate to be deleted.
   */
  void
  deleteCertificate (const Name& certificateName)
  {
    try
      {
        if (Info::getDefaultCertificateName() == certificateName)
          return;
      }
    catch (InfoError& e)
      {
        // Not a real error, just try to delete the certificate
      }

    Info::deleteCertificateInfo(certificateName);
  }

  /**
   * @brief delete a key.
   *
   * If the key to be deleted is current default system default,
   * the method will not delete the key and return immediately.
   *
   * @param keyName The key to be deleted.
   */
  void
  deleteKey (const Name& keyName)
  {
    try
      {
        if (Info::getDefaultKeyNameForIdentity(Info::getDefaultIdentity()) == keyName)
          return;
      }
    catch (InfoError& e)
      {
        // Not a real error, just try to delete the key
      }

    Info::deletePublicKeyInfo(keyName);
    Tpm::deleteKeyPairInTpm(keyName);
  }

  /**
   * @brief delete an identity.
   *
   * If the identity to be deleted is current default system default,
   * the method will not delete the identity and return immediately.
   *
   * @param identity The identity to be deleted.
   */
  void
  deleteIdentity (const Name& identity)
  {
    try
      {
        if (Info::getDefaultIdentity() == identity)
          return;
      }
    catch (InfoError& e)
      {
        // Not a real error, just try to delete the identity
      }

    std::vector<Name> nameList;
    Info::getAllKeyNamesOfIdentity(identity, nameList, true);
    Info::getAllKeyNamesOfIdentity(identity, nameList, false);

    Info::deleteIdentityInfo(identity);

    std::vector<Name>::const_iterator it = nameList.begin();
    for(; it != nameList.end(); it++)
      Tpm::deleteKeyPairInTpm(*it);
  }

  /**
   * @brief export an identity.
   *
   * @param identity The identity to export.
   * @param passwordStr The password to secure the private key.
   * @return The encoded export data.
   * @throws InfoError if anything goes wrong in exporting.
   */
  shared_ptr<SecuredBag>
  exportIdentity(const Name& identity, const std::string& passwordStr)
  {
    if (!Info::doesIdentityExist(identity))
      throw InfoError("Identity does not exist!");

    Name keyName = Info::getDefaultKeyNameForIdentity(identity);

    ConstBufferPtr pkcs8;
    try
      {
        pkcs8 = Tpm::exportPrivateKeyPkcs8FromTpm(keyName, passwordStr);
      }
    catch (TpmError& e)
      {
        throw InfoError("Fail to export PKCS8 of private key");
      }

    shared_ptr<IdentityCertificate> cert;
    try
      {
        cert = Info::getCertificate(Info::getDefaultCertificateNameForKey(keyName));
      }
    catch (InfoError& e)
      {
        cert = selfSign(keyName);
        Info::addCertificateAsIdentityDefault(*cert);
      }

    shared_ptr<SecuredBag> secureBag = make_shared<SecuredBag>(boost::cref(*cert), boost::cref(pkcs8));

    return secureBag;
  }

  /**
   * @brief import an identity.
   *
   * @param securedBag The encoded import data.
   * @param passwordStr The password to secure the private key.
   */
  void
  importIdentity(const SecuredBag& securedBag, const std::string& passwordStr)
  {
    Name keyName = IdentityCertificate::certificateNameToPublicKeyName(securedBag.getCertificate().getName());
    Name identity = keyName.getPrefix(-1);

    // Add identity
    Info::addIdentity(identity);

    // Add key
    Tpm::importPrivateKeyPkcs8IntoTpm(keyName, securedBag.getKey()->buf(), securedBag.getKey()->size(), passwordStr);
    shared_ptr<PublicKey> pubKey = Tpm::getPublicKeyFromTpm(keyName.toUri());
    Info::addPublicKey(keyName, KEY_TYPE_RSA, *pubKey); // HACK! We should set key type according to the pkcs8 info.
    Info::setDefaultKeyNameForIdentity(keyName);

    // Add cert
    Info::addCertificateAsIdentityDefault(securedBag.getCertificate());
  }


private:
  /**
   * @brief sign a packet using a pariticular certificate.
   *
   * @param packet The packet to be signed.
   * @param certificate The signing certificate.
   */
  template<typename T>
  void
  sign(T& packet, const IdentityCertificate& certificate)
  {
    SignatureSha256WithRsa signature;
    signature.setKeyLocator(certificate.getName().getPrefix(-1));

    // For temporary usage, we support RSA + SHA256 only, but will support more.
    signPacketWrapper(packet, signature, certificate.getPublicKeyName(), DIGEST_ALGORITHM_SHA256);
  }

  /**
   * @brief Generate a key pair for the specified identity.
   *
   * @param identityName The name of the specified identity.
   * @param isKsk true for generating a Key-Signing-Key (KSK), false for a Data-Signing-Key (KSK).
   * @param keyType The type of the key pair, e.g. KEY_TYPE_RSA.
   * @param keySize The size of the key pair.
   * @return The name of the generated key.
   */
  Name
  generateKeyPair(const Name& identityName, bool isKsk = false, KeyType keyType = KEY_TYPE_RSA, int keySize = 2048)
  {
    Name keyName = Info::getNewKeyName(identityName, isKsk);

    Tpm::generateKeyPairInTpm(keyName.toUri(), keyType, keySize);

    shared_ptr<PublicKey> pubKey = Tpm::getPublicKeyFromTpm(keyName.toUri());
    Info::addPublicKey(keyName, keyType, *pubKey);

    return keyName;
  }

  /**
   * @brief Sign the data using a particular key.
   *
   * @param data Reference to the data packet.
   * @param signature Signature to be added.
   * @param keyName The name of the signing key.
   * @param digestAlgorithm the digest algorithm.
   * @throws Tpm::Error
   */
  void
  signPacketWrapper(Data& data, const SignatureSha256WithRsa& signature, const Name& keyName, DigestAlgorithm digestAlgorithm)
  {
    data.setSignature(signature);
    data.setSignatureValue
      (Tpm::signInTpm(data.wireEncode().value(),
                      data.wireEncode().value_size() - data.getSignature().getValue().size(),
                      keyName, digestAlgorithm));
  }

  /**
   * @brief Sign the interest using a particular key.
   *
   * @param interest Reference to the interest packet.
   * @param signature Signature to be added.
   * @param keyName The name of the signing key.
   * @param digestAlgorithm the digest algorithm.
   * @throws Tpm::Error
   */
  void
  signPacketWrapper(Interest& interest, const SignatureSha256WithRsa& signature, const Name& keyName, DigestAlgorithm digestAlgorithm)
  {
    Name signedName = Name(interest.getName()).append(signature.getInfo());

    Block sigValue = Tpm::signInTpm(signedName.wireEncode().value(),
                                    signedName.wireEncode().value_size(),
                                    keyName,
                                    DIGEST_ALGORITHM_SHA256);
    sigValue.encode();
    signedName.append(sigValue);
    interest.setName(signedName);
  }


};

} // namespace ndn



#if defined(NDN_CPP_HAVE_OSX_SECURITY) and defined(NDN_CPP_WITH_OSX_KEYCHAIN)

namespace ndn {

typedef KeyChainImpl<SecPublicInfoSqlite3, SecTpmOsx> KeyChain;

} // namespace ndn

#else

namespace ndn {

typedef KeyChainImpl<SecPublicInfoSqlite3, SecTpmFile> KeyChain;

} // namespace ndn

#endif //NDN_CPP_HAVE_OSX_SECURITY

#endif //NDN_SECURITY_KEY_CHAIN_HPP
