/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2014-2022, 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/security/signing-helpers.hpp>
#include <ndn-cxx/util/logger.hpp>
#include <ndn-cxx/util/random.hpp>

namespace ndn::nac {

NDN_LOG_INIT(nac.AccessManager);

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

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

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

  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 ndn::nac
