/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2013-2017 Regents of the University of California.
 *
 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
 *
 * ndn-cxx 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.
 *
 * ndn-cxx 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 ndn-cxx authors and contributors.
 */

#include "block-cipher.hpp"
#include "../detail/openssl.hpp"

#include <boost/lexical_cast.hpp>

namespace ndn {
namespace security {
namespace transform {

class BlockCipher::Impl
{
public:
  Impl()
    : m_cipher(BIO_new(BIO_f_cipher()))
    , m_sink(BIO_new(BIO_s_mem()))
  {
    BIO_push(m_cipher, m_sink);
  }

  ~Impl()
  {
    BIO_free_all(m_cipher);
  }

public:
  BIO* m_cipher;
  BIO* m_sink; // BIO_f_cipher alone does not work without a sink
};


BlockCipher::BlockCipher(BlockCipherAlgorithm algo, CipherOperator op,
                         const uint8_t* key, size_t keyLen,
                         const uint8_t* iv, size_t ivLen)
  : m_impl(make_unique<Impl>())
{
  switch (algo) {
  case BlockCipherAlgorithm::AES_CBC:
    initializeAesCbc(key, keyLen, iv, ivLen, op);
    break;
  default:
    BOOST_THROW_EXCEPTION(Error(getIndex(), "Unsupported block cipher algorithm " +
                                boost::lexical_cast<std::string>(algo)));
  }
}

BlockCipher::~BlockCipher() = default;

void
BlockCipher::preTransform()
{
  fillOutputBuffer();
}

size_t
BlockCipher::convert(const uint8_t* data, size_t dataLen)
{
  if (dataLen == 0)
    return 0;

  int wLen = BIO_write(m_impl->m_cipher, data, dataLen);

  if (wLen <= 0) { // fail to write data
    if (!BIO_should_retry(m_impl->m_cipher)) {
      // we haven't written everything but some error happens, and we cannot retry
      BOOST_THROW_EXCEPTION(Error(getIndex(), "Failed to accept more input"));
    }
    return 0;
  }
  else { // update number of bytes written
    fillOutputBuffer();
    return wLen;
  }
}

void
BlockCipher::finalize()
{
  if (BIO_flush(m_impl->m_cipher) != 1)
    BOOST_THROW_EXCEPTION(Error(getIndex(), "Failed to flush"));

  while (!isConverterEmpty()) {
    fillOutputBuffer();
    while (!isOutputBufferEmpty()) {
      flushOutputBuffer();
    }
  }
}

void
BlockCipher::fillOutputBuffer()
{
  int nRead = BIO_pending(m_impl->m_sink);
  if (nRead <= 0)
    return;

  // there is something to read from BIO
  auto buffer = make_unique<OBuffer>(nRead);
  int rLen = BIO_read(m_impl->m_sink, buffer->data(), nRead);
  if (rLen < 0)
    return;

  if (rLen < nRead)
    buffer->erase(buffer->begin() + rLen, buffer->end());
  setOutputBuffer(std::move(buffer));
}

bool
BlockCipher::isConverterEmpty() const
{
  return (BIO_pending(m_impl->m_sink) <= 0);
}

void
BlockCipher::initializeAesCbc(const uint8_t* key, size_t keyLen,
                              const uint8_t* iv, size_t ivLen,
                              CipherOperator op)
{
  if (keyLen != ivLen)
    BOOST_THROW_EXCEPTION(Error(getIndex(), "Key length must be the same as IV length"));

  const EVP_CIPHER* cipherType = nullptr;
  switch (keyLen) {
  case 16:
    cipherType = EVP_aes_128_cbc();
    break;
  case 24:
    cipherType = EVP_aes_192_cbc();
    break;
  case 32:
    cipherType = EVP_aes_256_cbc();
    break;
  default:
    BOOST_THROW_EXCEPTION(Error(getIndex(), "Key length is not supported"));
  }
  BIO_set_cipher(m_impl->m_cipher, cipherType, key, iv, static_cast<int>(op));
}

unique_ptr<Transform>
blockCipher(BlockCipherAlgorithm algo, CipherOperator op,
            const uint8_t* key, size_t keyLen,
            const uint8_t* iv, size_t ivLen)
{
  return make_unique<BlockCipher>(algo, op, key, keyLen, iv, ivLen);
}

} // namespace transform
} // namespace security
} // namespace ndn
