/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2014-2018, Regents of the University of California
 *
 * This file is part of NAC (Name-Based Access Control for NDN).
 * See AUTHORS.md for complete list of NAC authors and contributors.
 *
 * NAC 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.
 *
 * NAC 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
 * NAC, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 */

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

#include "boost-test.hpp"
#include <boost/mpl/list.hpp>
#include <algorithm>

namespace ndn {
namespace nac {
namespace algo {
namespace tests {

BOOST_AUTO_TEST_SUITE(TestEncryptor)

class TestDataAesCbc
{
public:
  TestDataAesCbc()
    : keyName("/test")
    , encryptParams(tlv::AlgorithmAesCbc)
  {
    const uint8_t raw_content[] = {
      0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
      0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
      0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73
    };
    plainText = Buffer(raw_content, sizeof(raw_content));

    const uint8_t aes_key[] = {
      0xdd, 0x60, 0x77, 0xec, 0xa9, 0x6b, 0x23, 0x1b,
      0x40, 0x6b, 0x5a, 0xf8, 0x7d, 0x3d, 0x55, 0x32
    };
    key = Buffer(aes_key, sizeof(aes_key));

    const uint8_t iv[] = {
      0x73, 0x6f, 0x6d, 0x65, 0x72, 0x61, 0x6e, 0x64,
      0x6f, 0x6d, 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72
    };

    encryptParams.setIV(iv, sizeof(iv));

    const uint8_t encrypted_content[] = {
      0x15, 0x43, // Content
        0x82, 0x41, // EncryptedContent
          0x1c, 0x08, // KeyLocator /test
            0x07, 0x06,
              0x08, 0x04, 0x74, 0x65, 0x73, 0x74,
        0x83, 0x01, // EncryptedAlgorithm
          0x01, // AlgorithmAesCbc
        0x85, 0x10,
          0x73, 0x6f, 0x6d, 0x65, 0x72, 0x61, 0x6e, 0x64,
          0x6f, 0x6d, 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72,
        0x84, 0x20, // EncryptedPayLoad
          0x6a, 0x6b, 0x58, 0x9c, 0x30, 0x3b, 0xd9, 0xa6,
          0xed, 0xd2, 0x12, 0xef, 0x29, 0xad, 0xc3, 0x60,
          0x1f, 0x1b, 0x6b, 0xc7, 0x03, 0xff, 0x53, 0x52,
          0x82, 0x6d, 0x82, 0x73, 0x05, 0xf9, 0x03, 0xdc
    };
    encryptedContent = Buffer(encrypted_content, sizeof(encrypted_content));
  }

public:
  Buffer plainText;
  Buffer key;
  Name keyName;
  EncryptParams encryptParams;
  Buffer encryptedContent;
};

typedef boost::mpl::list<TestDataAesCbc> EncryptorAesTestInputs;

BOOST_AUTO_TEST_CASE_TEMPLATE(ContentSymmetricEncrypt, T, EncryptorAesTestInputs)
{
  T input;

  Data data;
  encryptData(data,
              input.plainText.data(),
              input.plainText.size(),
              input.keyName,
              input.key.data(),
              input.key.size(),
              input.encryptParams);

  BOOST_CHECK_EQUAL(data.getName(), Name("/FOR").append(input.keyName));

  BOOST_CHECK_EQUAL_COLLECTIONS(input.encryptedContent.begin(),
                                input.encryptedContent.end(),
                                data.getContent().wire(),
                                data.getContent().wire() + data.getContent().size());

  EncryptedContent content(data.getContent().blockFromValue());
  const Buffer& decryptedOutput = Aes::decrypt(input.key.data(),
                                               input.key.size(),
                                               content.getPayload().data(),
                                               content.getPayload().size(),
                                               input.encryptParams);

  BOOST_CHECK_EQUAL_COLLECTIONS(input.plainText.begin(),
                                input.plainText.end(),
                                decryptedOutput.begin(),
                                decryptedOutput.end());
}

class TestDataRsaOaep
{
public:
  TestDataRsaOaep()
    : type(tlv::AlgorithmRsaOaep)
  {
  }

public:
  tlv::AlgorithmTypeValue type;
};

class TestDataRsaPkcs
{
public:
  TestDataRsaPkcs()
    : type(tlv::AlgorithmRsaPkcs)
  {
  }

public:
  tlv::AlgorithmTypeValue type;
};

typedef boost::mpl::list<TestDataRsaOaep, TestDataRsaPkcs> EncryptorRsaTestInputs;

BOOST_AUTO_TEST_CASE_TEMPLATE(ContentAsymmetricEncryptSmall, T, EncryptorRsaTestInputs)
{
  T type;

  const uint8_t raw_content[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
                                 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
                                 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73};

  Data data;
  RsaKeyParams rsaParams(1024);

  Name keyName("test");

  DecryptKey<Rsa> decryptKey = Rsa::generateKey(rsaParams);
  EncryptKey<Rsa> encryptKey = Rsa::deriveEncryptKey(decryptKey.getKeyBits());

  Buffer eKey = encryptKey.getKeyBits();
  Buffer dKey = decryptKey.getKeyBits();

  EncryptParams encryptParams(type.type);

  encryptData(data, raw_content, sizeof(raw_content), keyName, eKey.data(), eKey.size(), encryptParams);

  BOOST_CHECK_EQUAL(data.getName(), Name("/FOR").append(keyName));

  Block dataContent = data.getContent();
  dataContent.parse();
  BOOST_CHECK_EQUAL(dataContent.elements_size(), 1);

  EncryptedContent extractContent(data.getContent().blockFromValue());
  BOOST_CHECK_EQUAL(extractContent.getKeyLocator().getName(), keyName);
  BOOST_CHECK_EQUAL(extractContent.getInitialVector().size(), 0);
  BOOST_CHECK_EQUAL(extractContent.getAlgorithmType(), type.type);

  const Buffer& recovered = extractContent.getPayload();
  Buffer decrypted =
    Rsa::decrypt(dKey.data(), dKey.size(), recovered.data(), recovered.size());
  BOOST_CHECK_EQUAL_COLLECTIONS(raw_content,
                                raw_content + sizeof(raw_content),
                                decrypted.begin(),
                                decrypted.end());
}

BOOST_AUTO_TEST_CASE_TEMPLATE(ContentAsymmetricEncryptLarge, T, EncryptorRsaTestInputs)
{
  T type;

  const uint8_t large_content[] =
    {0x73, 0x5a, 0xbd, 0x47, 0x0c, 0xfe, 0xf8, 0x7d, 0x2e, 0x17, 0xaa, 0x11, 0x6f, 0x23, 0xc5,
     0x10, 0x23, 0x36, 0x88, 0xc4, 0x2a, 0x0f, 0x9a, 0x72, 0x54, 0x31, 0xa8, 0xb3, 0x51, 0x18,
     0x9f, 0x0e, 0x1b, 0x93, 0x62, 0xd9, 0xc4, 0xf5, 0xf4, 0x3d, 0x61, 0x9a, 0xca, 0x05, 0x65,
     0x6b, 0xc6, 0x41, 0xf9, 0xd5, 0x1c, 0x67, 0xc1, 0xd0, 0xd5, 0x6f, 0x7b, 0x70, 0xb8, 0x8f,
     0xdb, 0x19, 0x68, 0x7c, 0xe0, 0x2d, 0x04, 0x49, 0xa9, 0xa2, 0x77, 0x4e, 0xfc, 0x60, 0x0d,
     0x7c, 0x1b, 0x93, 0x6c, 0xd2, 0x61, 0xc4, 0x6b, 0x01, 0xe9, 0x12, 0x28, 0x6d, 0xf5, 0x78,
     0xe9, 0x99, 0x0b, 0x9c, 0x4f, 0x90, 0x34, 0x3e, 0x06, 0x92, 0x57, 0xe3, 0x7a, 0x8f, 0x13,
     0xc7, 0xf3, 0xfe, 0xf0, 0xe2, 0x59, 0x48, 0x15, 0xb9, 0xdb, 0x77, 0x07, 0x1d, 0x6d, 0xb5,
     0x65, 0x17, 0xdf, 0x76, 0x6f, 0xb5, 0x43, 0xde, 0x71, 0xac, 0xf1, 0x22, 0xbf, 0xb2, 0xe5,
     0xd9, 0x22, 0xf1, 0x67, 0x76, 0x71, 0x0c, 0xff, 0x99, 0x7b, 0x94, 0x9b, 0x24, 0x20, 0x80,
     0xe3, 0xcc, 0x06, 0x4a, 0xed, 0xdf, 0xec, 0x50, 0xd5, 0x87, 0x3d, 0xa0, 0x7d, 0x9c, 0xe5,
     0x13, 0x10, 0x98, 0x14, 0xc3, 0x90, 0x10, 0xd9, 0x25, 0x9a, 0x59, 0xe9, 0x37, 0x26, 0xfd,
     0x87, 0xd7, 0xf4, 0xf9, 0x11, 0x91, 0xad, 0x5c, 0x00, 0x95, 0xf5, 0x2b, 0x37, 0xf7, 0x4e,
     0xb4, 0x4b, 0x42, 0x7c, 0xb3, 0xad, 0xd6, 0x33, 0x5f, 0x0b, 0x84, 0x57, 0x7f, 0xa7, 0x07,
     0x73, 0x37, 0x4b, 0xab, 0x2e, 0xfb, 0xfe, 0x1e, 0xcb, 0xb6, 0x4a, 0xc1, 0x21, 0x5f, 0xec,
     0x92, 0xb7, 0xac, 0x97, 0x75, 0x20, 0xc9, 0xd8, 0x9e, 0x93, 0xd5, 0x12, 0x7a, 0x64, 0xb9,
     0x4c, 0xed, 0x49, 0x87, 0x44, 0x5b, 0x4f, 0x90, 0x34, 0x3e, 0x06, 0x92, 0x57, 0xe3, 0x7a,
     0x8f, 0x13, 0xc7, 0xf3, 0xfe, 0xf0, 0xe2, 0x59, 0x48, 0x15, 0xb9, 0xdb, 0x77, 0x07, 0x1d,
     0x6d, 0xb5, 0x65, 0x17, 0xdf, 0x76, 0x6f, 0xb5, 0x43, 0xde, 0x71, 0xac, 0xf1, 0x22, 0xbf,
     0xb2, 0xe5, 0xd9};

  Data data;
  RsaKeyParams rsaParams(1024);

  Name keyName("test");

  DecryptKey<Rsa> decryptKey = Rsa::generateKey(rsaParams);
  EncryptKey<Rsa> encryptKey = Rsa::deriveEncryptKey(decryptKey.getKeyBits());

  Buffer eKey = encryptKey.getKeyBits();
  Buffer dKey = decryptKey.getKeyBits();

  EncryptParams encryptParams(type.type);
  encryptData(data, large_content, sizeof(large_content), keyName, eKey.data(), eKey.size(), encryptParams);

  BOOST_CHECK_EQUAL(data.getName(), Name("/FOR").append(keyName));

  Block largeDataContent = data.getContent();
  largeDataContent.parse();
  BOOST_CHECK_EQUAL(largeDataContent.elements_size(), 2);

  Block::element_const_iterator it = largeDataContent.elements_begin();

  BOOST_CHECK(it != largeDataContent.elements_end());
  Block nonceContent(*it);
  BOOST_CHECK_EQUAL(nonceContent.type(), tlv::EncryptedContent);
  EncryptedContent encryptedNonce(nonceContent);
  BOOST_CHECK_EQUAL(encryptedNonce.getKeyLocator().getName(), keyName);
  BOOST_CHECK_EQUAL(encryptedNonce.getInitialVector().size(), 0);
  BOOST_CHECK_EQUAL(encryptedNonce.getAlgorithmType(), type.type);

  it++;
  BOOST_CHECK(it != largeDataContent.elements_end());
  Block payloadContent(*it);
  BOOST_CHECK_EQUAL(payloadContent.type(), tlv::EncryptedContent);
  EncryptedContent encryptedPayload(payloadContent);
  Name nonceKeyName = keyName.append("nonce");
  BOOST_CHECK_EQUAL(encryptedPayload.getKeyLocator().getName(), nonceKeyName);
  BOOST_CHECK_EQUAL(encryptedPayload.getInitialVector().size(), 16);
  BOOST_CHECK_EQUAL(encryptedPayload.getAlgorithmType(), tlv::AlgorithmAesCbc);

  it++;
  BOOST_CHECK(it == largeDataContent.elements_end());

  const Buffer& bufferNonce = encryptedNonce.getPayload();
  Buffer nonce =
    Rsa::decrypt(dKey.data(), dKey.size(), bufferNonce.data(), bufferNonce.size());

  encryptParams.setAlgorithmType(tlv::AlgorithmAesCbc);
  encryptParams.setIV(encryptedPayload.getInitialVector().data(),
                      encryptedPayload.getInitialVector().size());
  const Buffer& bufferPayload = encryptedPayload.getPayload();
  Buffer largePayload =
    Aes::decrypt(nonce.data(), nonce.size(), bufferPayload.data(), bufferPayload.size(), encryptParams);

  BOOST_CHECK_EQUAL_COLLECTIONS(large_content,
                                large_content + sizeof(large_content),
                                largePayload.begin(),
                                largePayload.end());
}

BOOST_AUTO_TEST_SUITE_END()

} // namespace tests
} // namespace algo
} // namespace nac
} // namespace ndn
