/* -*- 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 "encryptor.hpp"

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

namespace ndn {
namespace nac {

NDN_LOG_INIT(nac.Encryptor);

const size_t N_RETRIES = 3;

Encryptor::Encryptor(const Name& accessPrefix,
                     const Name& ckPrefix, SigningInfo ckDataSigningInfo,
                     const ErrorCallback& onFailure,
                     Validator& validator, KeyChain& keyChain, Face& face)
  : m_accessPrefix{accessPrefix}
  , m_ckPrefix{ckPrefix}
  , m_ckBits{AES_KEY_SIZE}
  , m_ckDataSigningInfo{std::move(ckDataSigningInfo)}
  , m_isKekRetrievalInProgress(false)
  , m_onFailure(onFailure)
  , m_ckRegId{nullptr}
  , m_keyChain{keyChain}
  , m_face{face}
  , m_scheduler{face.getIoService()}
{
  regenerateCk();

  auto serveFromIms = [this] (const Name& prefix, const Interest& interest) {
    auto data = m_ims.find(interest);
    if (data != nullptr) {
      NDN_LOG_DEBUG("Serving " << data->getName() << " from InMemoryStorage");
      m_face.put(*data);
    }
    else {
      NDN_LOG_DEBUG("Didn't find CK data for " << interest.getName());
      // send NACK?
    }
  };

  auto handleError = [] (const Name& prefix, const std::string& msg) {
    NDN_LOG_ERROR("Failed to register prefix " << prefix << ": " << msg);
  };

  m_ckRegId = m_face.setInterestFilter(Name(ckPrefix).append(CK), serveFromIms, handleError);
}

Encryptor::~Encryptor()
{
  m_face.unsetInterestFilter(m_ckRegId);
  if (m_kekPendingInterest != nullptr) {
    m_face.removePendingInterest(m_kekPendingInterest);
  }
}

void
Encryptor::retryFetchingKek()
{
  if (m_isKekRetrievalInProgress) {
    return;
  }

  NDN_LOG_DEBUG("Retrying fetching of KEK");
  m_isKekRetrievalInProgress = true;
  fetchKekAndPublishCkData([&] {
      NDN_LOG_DEBUG("KEK retrieved and published");
      m_isKekRetrievalInProgress = false;
    },
    [=] (const ErrorCode& code, const std::string& msg) {
      NDN_LOG_ERROR("Failed to retrieved KEK: " + msg);
      m_isKekRetrievalInProgress = false;
      m_onFailure(code, msg);
    },
    N_RETRIES);
}

void
Encryptor::regenerateCk()
{
  m_ckName = m_ckPrefix;
  m_ckName
    .append(CK)
    .appendVersion(); // version = ID of CK
  NDN_LOG_DEBUG("Generating new CK: " << m_ckName);
  random::generateSecureBytes(m_ckBits.data(), m_ckBits.size());

  // one implication: if CK updated before KEK fetched, KDK for the old CK will not be published
  if (!m_kek) {
    retryFetchingKek();
  }
  else {
    makeAndPublishCkData(m_onFailure);
  }
}

EncryptedContent
Encryptor::encrypt(const uint8_t* data, size_t size)
{
  // Generate initial vector
  auto iv = make_shared<Buffer>(AES_IV_SIZE);
  random::generateSecureBytes(iv->data(), iv->size());

  OBufferStream os;
  security::transform::bufferSource(data, size)
    >> security::transform::blockCipher(BlockCipherAlgorithm::AES_CBC,
                                        CipherOperator::ENCRYPT,
                                        m_ckBits.data(), m_ckBits.size(), iv->data(), iv->size())
    >> security::transform::streamSink(os);

  EncryptedContent content;
  content.setIv(iv);
  content.setPayload(os.buf());
  content.setKeyLocator(m_ckName);

  return content;
}

void
Encryptor::fetchKekAndPublishCkData(const std::function<void()>& onReady,
                                    const ErrorCallback& onFailure,
                                    size_t nTriesLeft)
{
  // interest for <access-prefix>/KEK to retrieve  <access-prefix>/KEK/<key-id> KekData

  NDN_LOG_DEBUG("Fetching KEK " << Name(m_accessPrefix).append(KEK));

  BOOST_ASSERT(m_kekPendingInterest == nullptr);
  m_kekPendingInterest =
    m_face.expressInterest(Interest(Name(m_accessPrefix).append(KEK))
                             .setMustBeFresh(true)
                             .setCanBePrefix(true),
                           [=] (const Interest&, const Data& kek) {
                             m_kekPendingInterest = nullptr;
                             // @todo verify if the key is legit
                             m_kek = kek;
                             if (makeAndPublishCkData(onFailure)) {
                               onReady();
                             }
                             // otherwise, failure has been already declared
                           },
                           [=] (const Interest& i, const lp::Nack& nack) {
                             m_kekPendingInterest = nullptr;
                             if (nTriesLeft > 1) {
                               m_scheduler.schedule(RETRY_DELAY_AFTER_NACK, [=] {
                                 fetchKekAndPublishCkData(onReady, onFailure, nTriesLeft - 1);
                               });
                             }
                             else {
                               onFailure(ErrorCode::KekRetrievalFailure,
                                         "Retrieval of KEK [" + i.getName().toUri() + "] failed. "
                                         "Got NACK (" + boost::lexical_cast<std::string>(nack.getReason()) + ")");
                               NDN_LOG_DEBUG("Scheduling retry from NACK");
                               m_scheduler.schedule(RETRY_DELAY_KEK_RETRIEVAL, [this] { retryFetchingKek(); });
                             }
                           },
                           [=] (const Interest& i) {
                             m_kekPendingInterest = nullptr;
                             if (nTriesLeft > 1) {
                               fetchKekAndPublishCkData(onReady, onFailure, nTriesLeft - 1);
                             }
                             else {
                               onFailure(ErrorCode::KekRetrievalTimeout,
                                         "Retrieval of KEK [" + i.getName().toUri() + "] timed out");
                               NDN_LOG_DEBUG("Scheduling retry after all timeouts");
                               m_scheduler.schedule(RETRY_DELAY_KEK_RETRIEVAL, [this] { retryFetchingKek(); });
                             }
                           });
}

bool
Encryptor::makeAndPublishCkData(const ErrorCallback& onFailure)
{
  try {
    PublicKey kek;
    kek.loadPkcs8(m_kek->getContent().value(), m_kek->getContent().value_size());

    EncryptedContent content;
    content.setPayload(kek.encrypt(m_ckBits.data(), m_ckBits.size()));

    auto ckData = make_shared<Data>(Name(m_ckName).append(ENCRYPTED_BY).append(m_kek->getName()));
    ckData->setContent(content.wireEncode());
    // FreshnessPeriod can serve as a soft access control for revoking access
    ckData->setFreshnessPeriod(DEFAULT_CK_FRESHNESS_PERIOD);
    m_keyChain.sign(*ckData, m_ckDataSigningInfo);
    m_ims.insert(*ckData);

    NDN_LOG_DEBUG("Publishing CK data: " << ckData->getName());
    return true;
  }
  catch (const std::runtime_error& error) {
    onFailure(ErrorCode::EncryptionFailure, "Failed to encrypt generated CK with KEK " + m_kek->getName().toUri());
    return false;
  }
}

} // namespace nac
} // namespace ndn
