/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2014-2018, 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 "access-manager.hpp"
#include "encrypted-content.hpp"

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

NDN_LOG_INIT(nac.AccessManager);

namespace ndn {
namespace nac {

AccessManager::AccessManager(const Identity& identity, const Name& dataset,
                             KeyChain& keyChain, Face& face)
  : m_identity(identity)
  , m_keyChain(keyChain)
  , m_face(face)
{
  // NAC Identity: <identity>/NAC/<dataset>
  // generate NAC key
  auto nacId = m_keyChain.createIdentity(Name(identity.getName()).append(NAC).append(dataset), RsaKeyParams());
  m_nacKey = nacId.getDefaultKey();
  if (m_nacKey.getKeyType() != KeyType::RSA) {
    NDN_LOG_INFO("Cannot re-use existing KEK/KDK pair, as it is not an RSA key, regenerating");
    m_nacKey = m_keyChain.createKey(nacId, RsaKeyParams());
  }
  auto nacKeyId = m_nacKey.getName().at(-1);

  auto kekPrefix = Name(m_nacKey.getIdentity()).append(KEK);

  auto kek = make_shared<Data>(m_nacKey.getDefaultCertificate());
  kek->setName(Name(kekPrefix).append(nacKeyId));
  kek->setFreshnessPeriod(DEFAULT_KEK_FRESHNESS_PERIOD);
  m_keyChain.sign(*kek, signingByIdentity(m_identity));
  // kek looks like a cert, but doesn't have ValidityPeriod
  m_ims.insert(*kek);

  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 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_kekRegId = m_face.setInterestFilter(kekPrefix, serveFromIms, handleError);

  auto kdkPrefix = Name(m_nacKey.getIdentity()).append(KDK).append(nacKeyId);
  m_kdkRegId = m_face.setInterestFilter(kdkPrefix, serveFromIms, handleError);
}

AccessManager::~AccessManager()
{
  m_face.unsetInterestFilter(m_kekRegId);
  m_face.unsetInterestFilter(m_kdkRegId);
}

Data
AccessManager::addMember(const Certificate& memberCert)
{
  Name kdkName(m_nacKey.getIdentity());
  kdkName
    .append(KDK)
    .append(m_nacKey.getName().at(-1)) // key-id
    .append(ENCRYPTED_BY)
    .append(memberCert.getKeyName());

  const size_t secretLength = 32;
  uint8_t secret[secretLength + 1];
  random::generateSecureBytes(secret, secretLength);
  // because of stupid bug in ndn-cxx, remove all \0 in generated secret, replace with 1
  for (size_t i = 0; i < secretLength; ++i) {
    if (secret[i] == 0) {
      secret[i] = 1;
    }
  }
  secret[secretLength] = 0;

  auto kdkData = m_keyChain.exportSafeBag(m_nacKey.getDefaultCertificate(),
                                          reinterpret_cast<const char*>(secret), secretLength);

  PublicKey memberKey;
  memberKey.loadPkcs8(memberCert.getPublicKey().data(), memberCert.getPublicKey().size());

  EncryptedContent content;
  content.setPayload(kdkData->wireEncode());
  content.setPayloadKey(memberKey.encrypt(secret, secretLength));

  auto kdk = make_shared<Data>(kdkName);
  kdk->setContent(content.wireEncode());
  // FreshnessPeriod can serve as a soft access control for revoking access
  kdk->setFreshnessPeriod(DEFAULT_KDK_FRESHNESS_PERIOD);
  m_keyChain.sign(*kdk, signingByIdentity(m_identity));

  m_ims.insert(*kdk);

  return *kdk;
}

void
AccessManager::removeMember(const Name& identity)
{
  m_ims.erase(Name(m_nacKey.getName()).append(KDK).append(ENCRYPTED_BY).append(identity));
}

} // namespace nac
} // namespace ndn
