/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "enctool.h"
#include "argparse.h"
#include "util.h"

#include "nss.h"

#include <assert.h>
#include <chrono>
#include <fstream>
#include <iomanip>
#include <iostream>

void EncTool::PrintError(const std::string& m, size_t line_number) {
  std::cerr << m << " - enctool.cc:" << line_number << std::endl;
}

void EncTool::PrintError(const std::string& m, PRErrorCode err,
                         size_t line_number) {
  std::cerr << m << " (error " << err << ")"
            << " - enctool.cc:" << line_number << std::endl;
}

void EncTool::PrintBytes(const std::vector<uint8_t>& bytes,
                         const std::string& txt) {
  if (debug_) {
    std::cerr << txt << ": ";
    for (uint8_t b : bytes) {
      std::cerr << std::setfill('0') << std::setw(2) << std::hex
                << static_cast<int>(b);
    }
    std::cerr << std::endl << std::dec;
  }
}

std::vector<uint8_t> EncTool::GenerateRandomness(size_t num_bytes) {
  std::vector<uint8_t> bytes(num_bytes);
  if (PK11_GenerateRandom(bytes.data(), num_bytes) != SECSuccess) {
    PrintError("No randomness available. Abort!", __LINE__);
    exit(1);
  }
  return bytes;
}

bool EncTool::WriteBytes(const std::vector<uint8_t>& bytes,
                         std::string out_file) {
  std::fstream output(out_file, std::ios::out | std::ios::binary);
  if (!output.good()) {
    return false;
  }
  output.write(reinterpret_cast<const char*>(
                   const_cast<const unsigned char*>(bytes.data())),
               bytes.size());
  output.flush();
  output.close();
  return true;
}

bool EncTool::GetKey(const std::vector<uint8_t>& key_bytes,
                     ScopedSECItem& key_item) {
  if (key_bytes.empty()) {
    return false;
  }

  // Build key.
  key_item =
      ScopedSECItem(SECITEM_AllocItem(nullptr, nullptr, key_bytes.size()));
  if (!key_item) {
    return false;
  }
  key_item->type = siBuffer;
  memcpy(key_item->data, key_bytes.data(), key_bytes.size());
  key_item->len = key_bytes.size();

  return true;
}

bool EncTool::GetAesGcmKey(const std::vector<uint8_t>& aad,
                           const std::vector<uint8_t>& iv_bytes,
                           const std::vector<uint8_t>& key_bytes,
                           ScopedSECItem& aes_key, ScopedSECItem& params) {
  if (iv_bytes.empty()) {
    return false;
  }

  // GCM params.
  CK_NSS_GCM_PARAMS* gcm_params = static_cast<CK_NSS_GCM_PARAMS*>(
      PORT_Malloc(sizeof(struct CK_NSS_GCM_PARAMS)));
  if (!gcm_params) {
    return false;
  }

  uint8_t* iv = static_cast<uint8_t*>(PORT_Malloc(iv_bytes.size()));
  if (!iv) {
    return false;
  }
  memcpy(iv, iv_bytes.data(), iv_bytes.size());
  gcm_params->pIv = iv;
  gcm_params->ulIvLen = iv_bytes.size();
  gcm_params->ulTagBits = 128;
  if (aad.empty()) {
    gcm_params->pAAD = nullptr;
    gcm_params->ulAADLen = 0;
  } else {
    uint8_t* ad = static_cast<uint8_t*>(PORT_Malloc(aad.size()));
    if (!ad) {
      return false;
    }
    memcpy(ad, aad.data(), aad.size());
    gcm_params->pAAD = ad;
    gcm_params->ulAADLen = aad.size();
  }

  params =
      ScopedSECItem(SECITEM_AllocItem(nullptr, nullptr, sizeof(*gcm_params)));
  if (!params) {
    return false;
  }
  params->len = sizeof(*gcm_params);
  params->type = siBuffer;
  params->data = reinterpret_cast<unsigned char*>(gcm_params);

  return GetKey(key_bytes, aes_key);
}

bool EncTool::GenerateAesGcmKey(const std::vector<uint8_t>& aad,
                                ScopedSECItem& aes_key, ScopedSECItem& params) {
  size_t key_size = 16, iv_size = 12;
  std::vector<uint8_t> iv_bytes = GenerateRandomness(iv_size);
  PrintBytes(iv_bytes, "IV");
  std::vector<uint8_t> key_bytes = GenerateRandomness(key_size);
  PrintBytes(key_bytes, "key");
  // Maybe write out the key and parameters.
  if (write_key_ && !WriteBytes(key_bytes, key_file_)) {
    return false;
  }
  if (write_iv_ && !WriteBytes(iv_bytes, iv_file_)) {
    return false;
  }
  return GetAesGcmKey(aad, iv_bytes, key_bytes, aes_key, params);
}

bool EncTool::ReadAesGcmKey(const std::vector<uint8_t>& aad,
                            ScopedSECItem& aes_key, ScopedSECItem& params) {
  std::vector<uint8_t> iv_bytes = ReadInputData(iv_file_);
  PrintBytes(iv_bytes, "IV");
  std::vector<uint8_t> key_bytes = ReadInputData(key_file_);
  PrintBytes(key_bytes, "key");
  return GetAesGcmKey(aad, iv_bytes, key_bytes, aes_key, params);
}

bool EncTool::GetChachaKey(const std::vector<uint8_t>& aad,
                           const std::vector<uint8_t>& iv_bytes,
                           const std::vector<uint8_t>& key_bytes,
                           ScopedSECItem& chacha_key, ScopedSECItem& params) {
  if (iv_bytes.empty()) {
    return false;
  }

  // AEAD params.
  CK_NSS_AEAD_PARAMS* aead_params = static_cast<CK_NSS_AEAD_PARAMS*>(
      PORT_Malloc(sizeof(struct CK_NSS_AEAD_PARAMS)));
  if (!aead_params) {
    return false;
  }

  uint8_t* iv = static_cast<uint8_t*>(PORT_Malloc(iv_bytes.size()));
  if (!iv) {
    return false;
  }
  memcpy(iv, iv_bytes.data(), iv_bytes.size());
  aead_params->pNonce = iv;
  aead_params->ulNonceLen = iv_bytes.size();
  aead_params->ulTagLen = 16;
  if (aad.empty()) {
    aead_params->pAAD = nullptr;
    aead_params->ulAADLen = 0;
  } else {
    uint8_t* ad = static_cast<uint8_t*>(PORT_Malloc(aad.size()));
    if (!ad) {
      return false;
    }
    memcpy(ad, aad.data(), aad.size());
    aead_params->pAAD = ad;
    aead_params->ulAADLen = aad.size();
  }

  params =
      ScopedSECItem(SECITEM_AllocItem(nullptr, nullptr, sizeof(*aead_params)));
  if (!params) {
    return false;
  }
  params->len = sizeof(*aead_params);
  params->type = siBuffer;
  params->data = reinterpret_cast<unsigned char*>(aead_params);

  return GetKey(key_bytes, chacha_key);
}

bool EncTool::GenerateChachaKey(const std::vector<uint8_t>& aad,
                                ScopedSECItem& chacha_key,
                                ScopedSECItem& params) {
  size_t key_size = 32, iv_size = 12;
  std::vector<uint8_t> iv_bytes = GenerateRandomness(iv_size);
  PrintBytes(iv_bytes, "IV");
  std::vector<uint8_t> key_bytes = GenerateRandomness(key_size);
  PrintBytes(key_bytes, "key");
  // Maybe write out the key and parameters.
  if (write_key_ && !WriteBytes(key_bytes, key_file_)) {
    return false;
  }
  if (write_iv_ && !WriteBytes(iv_bytes, iv_file_)) {
    return false;
  }
  return GetChachaKey(aad, iv_bytes, key_bytes, chacha_key, params);
}

bool EncTool::ReadChachaKey(const std::vector<uint8_t>& aad,
                            ScopedSECItem& chacha_key, ScopedSECItem& params) {
  std::vector<uint8_t> iv_bytes = ReadInputData(iv_file_);
  PrintBytes(iv_bytes, "IV");
  std::vector<uint8_t> key_bytes = ReadInputData(key_file_);
  PrintBytes(key_bytes, "key");
  return GetChachaKey(aad, iv_bytes, key_bytes, chacha_key, params);
}

bool EncTool::DoCipher(std::string file_name, std::string out_file,
                       bool encrypt, key_func_t get_params) {
  SECStatus rv;
  unsigned int outLen = 0, chunkSize = 1024;
  char buffer[1040];
  const unsigned char* bufferStart =
      reinterpret_cast<const unsigned char*>(buffer);

  ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
  if (!slot) {
    PrintError("Unable to find security device", PR_GetError(), __LINE__);
    return false;
  }

  ScopedSECItem key, params;
  if (!(this->*get_params)(std::vector<uint8_t>(), key, params)) {
    PrintError("Geting keys and params failed.", __LINE__);
    return false;
  }

  ScopedPK11SymKey symKey(
      PK11_ImportSymKey(slot.get(), cipher_mech_, PK11_OriginUnwrap,
                        CKA_DECRYPT | CKA_ENCRYPT, key.get(), nullptr));
  if (!symKey) {
    PrintError("Failure to import key into NSS", PR_GetError(), __LINE__);
    return false;
  }

  std::streambuf* buf;
  std::ofstream output_file(out_file, std::ios::out | std::ios::binary);
  if (!out_file.empty()) {
    if (!output_file.good()) {
      return false;
    }
    buf = output_file.rdbuf();
  } else {
    buf = std::cout.rdbuf();
  }
  std::ostream output(buf);

  // Read from stdin.
  if (file_name.empty()) {
    std::vector<uint8_t> data = ReadInputData("");
    std::vector<uint8_t> out(data.size() + 16);
    if (encrypt) {
      rv = PK11_Encrypt(symKey.get(), cipher_mech_, params.get(), out.data(),
                        &outLen, data.size() + 16, data.data(), data.size());
    } else {
      rv = PK11_Decrypt(symKey.get(), cipher_mech_, params.get(), out.data(),
                        &outLen, data.size() + 16, data.data(), data.size());
    }
    if (rv != SECSuccess) {
      PrintError(encrypt ? "Error encrypting" : "Error decrypting",
                 PR_GetError(), __LINE__);
      return false;
    };
    output.write(reinterpret_cast<char*>(out.data()), outLen);
    output.flush();
    if (output_file.good()) {
      output_file.close();
    } else {
      output << std::endl;
    }

    std::cerr << "Done " << (encrypt ? "encrypting" : "decrypting")
              << std::endl;
    return true;
  }

  // Read file from file_name.
  std::ifstream input(file_name, std::ios::binary);
  if (!input.good()) {
    return false;
  }
  uint8_t out[1040];
  while (input) {
    if (encrypt) {
      input.read(buffer, chunkSize);
      rv = PK11_Encrypt(symKey.get(), cipher_mech_, params.get(), out, &outLen,
                        chunkSize + 16, bufferStart, input.gcount());
    } else {
      // We have to read the tag when decrypting.
      input.read(buffer, chunkSize + 16);
      rv = PK11_Decrypt(symKey.get(), cipher_mech_, params.get(), out, &outLen,
                        chunkSize + 16, bufferStart, input.gcount());
    }
    if (rv != SECSuccess) {
      PrintError(encrypt ? "Error encrypting" : "Error decrypting",
                 PR_GetError(), __LINE__);
      return false;
    };
    output.write(reinterpret_cast<const char*>(out), outLen);
    output.flush();
  }
  if (output_file.good()) {
    output_file.close();
  } else {
    output << std::endl;
  }
  std::cerr << "Done " << (encrypt ? "encrypting" : "decrypting") << std::endl;

  return true;
}

size_t EncTool::PrintFileSize(std::string file_name) {
  std::ifstream input(file_name, std::ifstream::ate | std::ifstream::binary);
  auto size = input.tellg();
  std::cerr << "Size of file to encrypt: " << size / 1024 / 1024 << " MB"
            << std::endl;
  return size;
}

bool EncTool::IsValidCommand(ArgParser arguments) {
  // Either encrypt or decrypt is fine.
  bool valid = arguments.Has("--encrypt") != arguments.Has("--decrypt");
  // An input file is required for decryption only.
  valid &= arguments.Has("--in") || arguments.Has("--encrypt");
  // An output file is required for encryption only.
  valid &= arguments.Has("--out") || arguments.Has("--decrypt");
  // Files holding the IV and key are required for decryption.
  valid &= arguments.Has("--iv") || arguments.Has("--encrypt");
  valid &= arguments.Has("--key") || arguments.Has("--encrypt");
  // Cipher is always required.
  valid &= arguments.Has("--cipher");
  return valid;
}

bool EncTool::Run(const std::vector<std::string>& arguments) {
  ArgParser parser(arguments);

  if (!IsValidCommand(parser)) {
    Usage();
    return false;
  }

  if (NSS_NoDB_Init(nullptr) != SECSuccess) {
    PrintError("NSS initialization failed", PR_GetError(), __LINE__);
    return false;
  }

  if (parser.Has("--debug")) {
    debug_ = 1;
  }
  if (parser.Has("--iv")) {
    iv_file_ = parser.Get("--iv");
  } else {
    write_iv_ = false;
  }
  if (parser.Has("--key")) {
    key_file_ = parser.Get("--key");
  } else {
    write_key_ = false;
  }

  key_func_t get_params;
  bool encrypt = parser.Has("--encrypt");
  if (parser.Get("--cipher") == kAESCommand) {
    cipher_mech_ = CKM_AES_GCM;
    if (encrypt) {
      get_params = &EncTool::GenerateAesGcmKey;
    } else {
      get_params = &EncTool::ReadAesGcmKey;
    }
  } else if (parser.Get("--cipher") == kChaChaCommand) {
    cipher_mech_ = CKM_NSS_CHACHA20_POLY1305;
    if (encrypt) {
      get_params = &EncTool::GenerateChachaKey;
    } else {
      get_params = &EncTool::ReadChachaKey;
    }
  } else {
    Usage();
    return false;
  }
  // Don't write out key and iv when decrypting.
  if (!encrypt) {
    write_key_ = false;
    write_iv_ = false;
  }

  std::string input_file = parser.Has("--in") ? parser.Get("--in") : "";
  std::string output_file = parser.Has("--out") ? parser.Get("--out") : "";
  size_t file_size = 0;
  if (!input_file.empty()) {
    file_size = PrintFileSize(input_file);
  }
  auto begin = std::chrono::high_resolution_clock::now();
  if (!DoCipher(input_file, output_file, encrypt, get_params)) {
    (void)NSS_Shutdown();
    return false;
  }
  auto end = std::chrono::high_resolution_clock::now();
  auto ns =
      std::chrono::duration_cast<std::chrono::nanoseconds>(end - begin).count();
  auto seconds = ns / 1000000000;
  std::cerr << ns << " ns (~" << seconds << " s) and " << std::endl;
  std::cerr << "That's approximately " << (double)file_size / ns << " b/ns"
            << std::endl;

  if (NSS_Shutdown() != SECSuccess) {
    return false;
  }

  return true;
}

void EncTool::Usage() {
  std::string const txt = R"~(
Usage: nss encrypt|decrypt --cipher aes|chacha [--in <file>] [--out <file>]
           [--key <file>] [--iv <file>]

    --cipher         Set the cipher to use.
                     --cipher aes:    Use AES-GCM to encrypt/decrypt.
                     --cipher chacha: Use ChaCha20/Poly1305 to encrypt/decrypt.
    --in             The file to encrypt/decrypt. If no file is given, we read
                     from stdin (only when encrypting).
    --out            The file to write the ciphertext/plaintext to. If no file
                     is given we write the plaintext to stdout (only when
                     decrypting).
    --key            The file to write the used key to/to read the key
                     from. Optional parameter. When not given, don't write out
                     the key.
    --iv             The file to write the used IV to/to read the IV
                     from. Optional parameter. When not given, don't write out
                     the IV.

    Examples:
        nss encrypt --cipher aes --iv iv --key key --out ciphertext
        nss decrypt --cipher chacha --iv iv --key key --in ciphertex

    Note: This tool overrides files without asking.
)~";
  std::cerr << txt << std::endl;
}
