/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2014-2015,  Regents of the University of California
 *
 * This file is part of ndn-group-encrypt (Group-based Encryption Protocol for NDN).
 * See AUTHORS.md for complete list of ndn-group-encrypt authors and contributors.
 *
 * ndn-group-encrypt is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later version.
 *
 * ndn-group-encrypt 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * ndn-group-encrypt, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "encryptor.hpp"
#include "random-number-generator.hpp"
#include "encrypted-content.hpp"
#include "algo/aes.hpp"
#include "algo/rsa.hpp"

#include "algo/error.hpp"

namespace ndn {
namespace gep {
namespace algo {

using namespace CryptoPP;

/**
 * @brief Helper method for symmetric encryption
 *
 * Encrypt @p payload using @p key according to @p params.
 *
 * @return An EncryptedContent
 */
static EncryptedContent
encryptSymmetric(const uint8_t* payload, size_t payloadLen,
                 const uint8_t* key, size_t keyLen,
                 const Name& keyName, const EncryptParams& params)
{
  tlv::AlgorithmTypeValue algType = params.getAlgorithmType();
  const Buffer& iv = params.getIV();
  KeyLocator keyLocator(keyName);

  switch (algType) {
    case tlv::AlgorithmAesCbc:
    case tlv::AlgorithmAesEcb: {
      BOOST_ASSERT(iv.size() == static_cast<size_t>(AES::BLOCKSIZE));

      const Buffer& encryptedPayload = Aes::encrypt(key, keyLen, payload, payloadLen, params);
      return EncryptedContent(algType, keyLocator, encryptedPayload.buf(), encryptedPayload.size(), iv.buf(), iv.size());
    }
    default: {
      BOOST_ASSERT(false);
      throw algo::Error("Unsupported encryption method");
    }
  }
}

/**
 * @brief Helper method for asymmetric encryption
 *
 * Encrypt @p payload using @p key according to @p params.
 *
 * @pre @p payloadLen should be within the range of the key.
 * @return An EncryptedContent
 */
static EncryptedContent
encryptAsymmetric(const uint8_t* payload, size_t payloadLen,
                  const uint8_t* key, size_t keyLen,
                  const Name& keyName, const EncryptParams& params)
{
  tlv::AlgorithmTypeValue algType = params.getAlgorithmType();
  KeyLocator keyLocator(keyName);

  switch (algType) {
    case tlv::AlgorithmRsaPkcs:
    case tlv::AlgorithmRsaOaep: {
      Buffer encryptedPayload = Rsa::encrypt(key, keyLen, payload, payloadLen, params);
      return EncryptedContent(algType, keyLocator, encryptedPayload.buf(), encryptedPayload.size());
    }
    default: {
      BOOST_ASSERT(false);
      throw algo::Error("Unsupported encryption method");
    }
  }
}

void
encryptData(Data& data, const uint8_t* payload, size_t payloadLen,
            const Name& keyName, const uint8_t* key, size_t keyLen,
            const EncryptParams& params)
{
  switch(params.getAlgorithmType()) {
    case tlv::AlgorithmAesCbc:
    case tlv::AlgorithmAesEcb: {
      const EncryptedContent& content = encryptSymmetric(payload, payloadLen, key, keyLen, keyName, params);
      data.setContent(content.wireEncode());
      break;
    }
    case tlv::AlgorithmRsaPkcs:
    case tlv::AlgorithmRsaOaep: {
      size_t maxPlaintextLength = 0;
      RSA::PublicKey publicKey;
      ByteQueue keyQueue;

      keyQueue.LazyPut(key, keyLen);
      publicKey.Load(keyQueue);
      RSAES_PKCS1v15_Encryptor enc(publicKey);
      maxPlaintextLength = enc.FixedMaxPlaintextLength();

      if (maxPlaintextLength < payloadLen) {
        RandomNumberGenerator rng;
        SecByteBlock nonceKey(0x00, 16);  // 128 bits key.
        rng.GenerateBlock(nonceKey.data(), nonceKey.size());

        Name nonceKeyName(keyName);
        nonceKeyName.append("nonce");

        EncryptParams symParams(tlv::AlgorithmAesCbc, AES::BLOCKSIZE);

        const EncryptedContent& nonceContent =
          encryptSymmetric(payload, payloadLen, nonceKey.data(), nonceKey.size(), nonceKeyName, symParams);

        const EncryptedContent& payloadContent =
          encryptAsymmetric(nonceKey.data(), nonceKey.size(), key, keyLen, keyName, params);

        Block content(tlv::Content);
        content.push_back(payloadContent.wireEncode());
        content.push_back(nonceContent.wireEncode());

        data.setContent(content);
        return;
      }
      else {
        const EncryptedContent& content = encryptAsymmetric(payload, payloadLen, key, keyLen, keyName, params);
        data.setContent(content.wireEncode());
        return;
      }
    }
    default:
      throw algo::Error("Unsupported encryption method");
  }
}

} // namespace algo
} // namespace gep
} // namespace ndn
