/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2014-2019, Regents of the University of California
 *
 * NAC 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.
 *
 * NAC 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 NAC library authors and contributors.
 */

#include "decryptor.hpp"

#include <ndn-cxx/util/logger.hpp>

namespace ndn {
namespace nac {

NDN_LOG_INIT(nac.Decryptor);

const size_t N_RETRIES = 3;

Decryptor::Decryptor(const Key& credentialsKey, Validator& validator, KeyChain& keyChain, Face& face)
  : m_credentialsKey(credentialsKey)
  // , m_validator(validator)
  , m_face(face)
  , m_keyChain(keyChain)
  , m_internalKeyChain("pib-memory:", "tpm-memory:")
{
}

Decryptor::~Decryptor()
{
  for (auto& i : m_cks) {
    if (i.second.pendingInterest) {
      i.second.pendingInterest->cancel();
      for (const auto& p : i.second.pendingDecrypts) {
        p.onFailure(ErrorCode::CkRetrievalFailure,
                    "Cancel pending decrypt as ContentKey is being destroyed");
      }
    }
  }
}

void
Decryptor::decrypt(const Block& encryptedContent,
                   const DecryptSuccessCallback& onSuccess,
                   const ErrorCallback& onFailure)
{
  EncryptedContent ec(encryptedContent);
  if (!ec.hasKeyLocator()) {
    NDN_LOG_INFO("Missing required KeyLocator in the supplied EncryptedContent block");
    return onFailure(ErrorCode::MissingRequiredKeyLocator,
                     "Missing required KeyLocator in the supplied EncryptedContent block");
  }

  if (!ec.hasIv()) {
    NDN_LOG_INFO("Missing required InitialVector in the supplied EncryptedContent block");
    return onFailure(ErrorCode::MissingRequiredKeyLocator,
                     "Missing required InitialVector in the supplied EncryptedContent block");
  }

  ContentKeys::iterator ck;
  bool isNew = false;
  std::tie(ck, isNew) = m_cks.emplace(ec.getKeyLocator(), ContentKey{});

  if (ck->second.isRetrieved) {
    doDecrypt(ec, ck->second.bits, onSuccess, onFailure);
  }
  else {
    NDN_LOG_DEBUG("CK " << ec.getKeyLocator() << " not yet available, adding decrypt to the pending queue");
    ck->second.pendingDecrypts.push_back({ec, onSuccess, onFailure});
  }

  if (isNew) {
    fetchCk(ck, onFailure, N_RETRIES);
  }
}

void
Decryptor::fetchCk(ContentKeys::iterator ck, const ErrorCallback& onFailure, size_t nTriesLeft)
{
  // full name of CK is

  // <whatever-prefix>/CK/<ck-id>  /ENCRYPTED-BY /<kek-prefix>/KEK/<key-id>
  // \                          /                \                        /
  //  -----------  -------------                  -----------  -----------
  //             \/                                          \/
  //   from the encrypted data          unknown (name in retrieved CK is used to determine KDK)

  const Name& ckName = ck->first;

  NDN_LOG_DEBUG("Fetching CK " << ckName);

  ck->second.pendingInterest = m_face.expressInterest(Interest(ckName)
                                                       .setMustBeFresh(false) // ?
                                                       .setCanBePrefix(true),
    [=] (const Interest& ckInterest, const Data& ckData) {
      ck->second.pendingInterest = nullopt;
      // @TODO verify if the key is legit
      Name kdkPrefix, kdkIdentity, kdkKeyName;
      std::tie(kdkPrefix, kdkIdentity, kdkKeyName) =
        extractKdkInfoFromCkName(ckData.getName(), ckInterest.getName(), onFailure);
      if (kdkPrefix.empty()) {
        return; // error has been already reported
      }

      // check if KDK already exists (there is a corresponding
      auto kdkIdentityIt = m_internalKeyChain.getPib().getIdentities().find(kdkIdentity);
      if (kdkIdentityIt != m_internalKeyChain.getPib().getIdentities().end()) {
        auto kdkKeyIt = (*kdkIdentityIt).getKeys().find(kdkKeyName);
        if (kdkKeyIt != (*kdkIdentityIt).getKeys().end()) {
          // KDK was already fetched and imported
          NDN_LOG_DEBUG("KDK " << kdkKeyName << " already exists, directly using it to decrypt CK");
          return decryptCkAndProcessPendingDecrypts(ck, ckData, kdkKeyName, onFailure);
        }
      }

      fetchKdk(ck, kdkPrefix, ckData, onFailure, N_RETRIES);
    },
    [=] (const Interest& i, const lp::Nack& nack) {
      ck->second.pendingInterest = nullopt;
      onFailure(ErrorCode::CkRetrievalFailure,
                "Retrieval of CK [" + i.getName().toUri() + "] failed. "
                "Got NACK (" + boost::lexical_cast<std::string>(nack.getReason()) + ")");
    },
    [=] (const Interest& i) {
      ck->second.pendingInterest = nullopt;
      if (nTriesLeft > 1) {
        fetchCk(ck, onFailure, nTriesLeft - 1);
      }
      else {
        onFailure(ErrorCode::CkRetrievalTimeout,
                  "Retrieval of CK [" + i.getName().toUri() + "] timed out");
      }
    });
}

void
Decryptor::fetchKdk(ContentKeys::iterator ck, const Name& kdkPrefix, const Data& ckData,
                    const ErrorCallback& onFailure, size_t nTriesLeft)
{
  // <kdk-prefix>/KDK/<kdk-id>    /ENCRYPTED-BY  /<credential-identity>/KEY/<key-id>
  // \                          /                \                                /
  //  -----------  -------------                  ---------------  ---------------
  //             \/                                              \/
  //     from the CK data                                from configuration

  Name kdkName = kdkPrefix;
  kdkName
    .append(ENCRYPTED_BY)
    .append(m_credentialsKey.getName());

  NDN_LOG_DEBUG("Fetching KDK " << kdkName);

  ck->second.pendingInterest = m_face.expressInterest(Interest(kdkName)
                                                     .setMustBeFresh(true)
                                                     .setCanBePrefix(false),
    [=] (const Interest&, const Data& kdkData) {
      ck->second.pendingInterest = nullopt;
      // @TODO verify if the key is legit

      bool isOk = decryptAndImportKdk(kdkData, onFailure);
      if (!isOk)
        return;
      decryptCkAndProcessPendingDecrypts(ck, ckData,
                                         kdkPrefix.getPrefix(-2).append("KEY").append(kdkPrefix.get(-1)), // a bit hacky
                                         onFailure);
    },
    [=] (const Interest& i, const lp::Nack& nack) {
      ck->second.pendingInterest = nullopt;
      onFailure(ErrorCode::KdkRetrievalFailure,
                "Retrieval of KDK [" + i.getName().toUri() + "] failed. "
                "Got NACK (" + boost::lexical_cast<std::string>(nack.getReason()) + ")");
    },
    [=] (const Interest& i) {
      ck->second.pendingInterest = nullopt;
      if (nTriesLeft > 1) {
        fetchKdk(ck, kdkPrefix, ckData, onFailure, nTriesLeft - 1);
      }
      else {
        onFailure(ErrorCode::KdkRetrievalTimeout,
                  "Retrieval of KDK [" + i.getName().toUri() + "] timed out");
      }
    });
}

bool
Decryptor::decryptAndImportKdk(const Data& kdkData, const ErrorCallback& onFailure)
{
  try {
    NDN_LOG_DEBUG("Decrypting and importing KDK " << kdkData.getName());
    EncryptedContent content(kdkData.getContent().blockFromValue());

    SafeBag safeBag(content.getPayload().blockFromValue());
    auto secret = m_keyChain.getTpm().decrypt(content.getPayloadKey().value(),
                                              content.getPayloadKey().value_size(),
                                              m_credentialsKey.getName());
    if (secret == nullptr) {
      onFailure(ErrorCode::TpmKeyNotFound,
                "Could not decrypt secret, " + m_credentialsKey.getName().toUri() + " not found in TPM");
      return false;
    }

    m_internalKeyChain.importSafeBag(safeBag, reinterpret_cast<const char*>(secret->data()), secret->size());
    return true;
  }
  catch (const std::runtime_error& e) {
    // can be tlv::Error, pib::Error, tpm::Error, and bunch of other runtime-derived errors
    onFailure(ErrorCode::KdkDecryptionFailure,
              "Failed to decrypt KDK [" + kdkData.getName().toUri() + "]: " + e.what());
    return false;
  }
}

void
Decryptor::decryptCkAndProcessPendingDecrypts(ContentKeys::iterator ck, const Data& ckData, const Name& kdkKeyName,
                                              const ErrorCallback& onFailure)
{
  NDN_LOG_DEBUG("Decrypting CK data " << ckData.getName());

  EncryptedContent content(ckData.getContent().blockFromValue());

  auto ckBits = m_internalKeyChain.getTpm().decrypt(content.getPayload().value(), content.getPayload().value_size(),
                                                    kdkKeyName);
  if (ckBits == nullptr) {
    onFailure(ErrorCode::TpmKeyNotFound, "Could not decrypt secret, " + kdkKeyName.toUri() + " not found in TPM");
    return;
  }

  ck->second.bits = *ckBits;
  ck->second.isRetrieved = true;

  for (const auto& item : ck->second.pendingDecrypts) {
    doDecrypt(item.encryptedContent, ck->second.bits, item.onSuccess, item.onFailure);
  }
  ck->second.pendingDecrypts.clear();
}

void
Decryptor::doDecrypt(const EncryptedContent& content, const Buffer& ckBits,
                     const DecryptSuccessCallback& onSuccess,
                     const ErrorCallback& onFailure)
{
  if (!content.hasIv()) {
    BOOST_THROW_EXCEPTION(Error("Expecting Initial Vector in the encrypted content, but it is not present"));
  }

  OBufferStream os;
  security::transform::bufferSource(content.getPayload().value(), content.getPayload().value_size())
    >> security::transform::blockCipher(BlockCipherAlgorithm::AES_CBC,
                                        CipherOperator::DECRYPT,
                                        ckBits.data(), ckBits.size(),
                                        content.getIv().value(), content.getIv().value_size())
    >> security::transform::streamSink(os);

  onSuccess(os.buf());
}

} // namespace nac
} // namespace ndn
