/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
/**
 * Copyright (C) 2013 Regents of the University of California.
 * @author: Xingyu Ma <maxy12@cs.ucla.edu>
 *          Alexander Afanasyev <alexander.afanasyev@ucla.edu>
 *          Yingdi Yu <yingdi@cs.ucla.edu>
 * See COPYING for copyright and distribution information.
 */

#include "common.hpp"

#include "sec-tpm-file.hpp"

#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>

#include <cryptopp/rsa.h>
#include <cryptopp/files.h>
#include <cryptopp/base64.h>
#include <cryptopp/hex.h>
#include <cryptopp/osrng.h>
#include <cryptopp/sha.h>
#include <cryptopp/pssr.h>
#include <cryptopp/modes.h>
#include <cryptopp/pwdbased.h>
#include <cryptopp/sha.h>
#include <cryptopp/des.h>

#include <sys/types.h>
#include <sys/stat.h>

#include <algorithm>

using namespace std;

namespace ndn {

class SecTpmFile::Impl {
public:
  Impl(const string& dir)
  {
    if(dir.empty())
      m_keystorePath = boost::filesystem::path(getenv("HOME")) / ".ndnx" / "ndnsec-tpm-file";
    else
      m_keystorePath = dir;
    
    boost::filesystem::create_directories (m_keystorePath);
  }

  boost::filesystem::path
  nameTransform(const string& keyName, const string& extension)
  {
    using namespace CryptoPP;
    string digest;
    SHA256 hash;
    StringSource src(keyName, true, new HashFilter(hash, new Base64Encoder (new CryptoPP::StringSink(digest))));

    boost::algorithm::trim(digest);
    std::replace(digest.begin(), digest.end(), '/', '%');
    
    return m_keystorePath / (digest + extension);
  }

  string 
  maintainMapping(const string& keyName)
  {
    string keyFileName = nameTransform(keyName, "").string();
    
    ofstream outfile;
    string dirFile = (m_keystorePath / "mapping.txt").string();
    
    outfile.open(dirFile.c_str(), std::ios_base::app);
    outfile << keyName << ' ' << keyFileName << '\n';
    outfile.close();
    
    return keyFileName;
  }

public:
  boost::filesystem::path m_keystorePath;
};


SecTpmFile::SecTpmFile(const string& dir)
  : m_impl(new Impl(dir))
  , m_inTerminal(false)
{}

void
SecTpmFile::generateKeyPairInTpm(const Name & keyName, KeyType keyType, int keySize)
{
  string keyURI = keyName.toUri();

  if(doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC))
    throw Error("public key exists");
  if(doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE))
    throw Error("private key exists");

  string keyFileName = m_impl->maintainMapping(keyURI);

  try{
    switch(keyType){
    case KEY_TYPE_RSA:
      {
        using namespace CryptoPP;
        AutoSeededRandomPool rng;

	InvertibleRSAFunction privateKey;
	privateKey.Initialize(rng, keySize);
	
	string privateKeyFileName = keyFileName + ".pri";
	Base64Encoder privateKeySink(new FileSink(privateKeyFileName.c_str()));
	privateKey.DEREncode(privateKeySink);
	privateKeySink.MessageEnd();
	
	RSAFunction publicKey(privateKey);
	string publicKeyFileName = keyFileName + ".pub";
	Base64Encoder publicKeySink(new FileSink(publicKeyFileName.c_str()));
	publicKey.DEREncode(publicKeySink);
	publicKeySink.MessageEnd();
	
	/*set file permission*/
	chmod(privateKeyFileName.c_str(), 0000400);
	chmod(publicKeyFileName.c_str(), 0000444);
	return;
      }
    default:
      throw Error("Unsupported key type!");
    }
  }catch(const CryptoPP::Exception& e){
    throw Error(e.what());
  }
}

void
SecTpmFile::deleteKeyPairInTpm(const Name &keyName)
{
  boost::filesystem::path publicKeyPath(m_impl->nameTransform(keyName.toUri(), ".pub"));
  boost::filesystem::path privateKeyPath(m_impl->nameTransform(keyName.toUri(), ".pri"));

  if(boost::filesystem::exists(publicKeyPath))
    boost::filesystem::remove(publicKeyPath);

  if(boost::filesystem::exists(privateKeyPath))
    boost::filesystem::remove(privateKeyPath);
}

shared_ptr<PublicKey>
SecTpmFile::getPublicKeyFromTpm(const Name & keyName)
{
  string keyURI = keyName.toUri();

  if(!doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC))
    return shared_ptr<PublicKey>();

  ostringstream os;
  try{
    using namespace CryptoPP;
    FileSource(m_impl->nameTransform(keyURI, ".pub").string().c_str(), true, new Base64Decoder(new FileSink(os)));
  }catch(const CryptoPP::Exception& e){
    return shared_ptr<PublicKey>();
  }

  return make_shared<PublicKey>(reinterpret_cast<const uint8_t*>(os.str().c_str()), os.str().size());
}

ConstBufferPtr
SecTpmFile::exportPrivateKeyPkcs1FromTpm(const Name& keyName)
{
  OBufferStream privateKeyOs;
  CryptoPP::FileSource(m_impl->nameTransform(keyName.toUri(), ".pri").string().c_str(), true, 
                       new CryptoPP::Base64Decoder(new CryptoPP::FileSink(privateKeyOs)));
  
  return privateKeyOs.buf();
}

bool
SecTpmFile::importPrivateKeyPkcs1IntoTpm(const Name& keyName, const uint8_t* buf, size_t size)
{
  try{
    string keyFileName = m_impl->maintainMapping(keyName.toUri());
    keyFileName.append(".pri");
    CryptoPP::StringSource(buf, size, true,
                           new CryptoPP::Base64Encoder(new CryptoPP::FileSink(keyFileName.c_str())));
    return true;
  }catch(...){
    return false;
  }
}

bool
SecTpmFile::importPublicKeyPkcs1IntoTpm(const Name& keyName, const uint8_t* buf, size_t size)
{
  try{
    string keyFileName = m_impl->maintainMapping(keyName.toUri());
    keyFileName.append(".pub");
    CryptoPP::StringSource(buf, size, true,
                           new CryptoPP::Base64Encoder(new CryptoPP::FileSink(keyFileName.c_str())));
    return true;
  }catch(...){
    return false;
  }
}

Block
SecTpmFile::signInTpm(const uint8_t *data, size_t dataLength, const Name& keyName, DigestAlgorithm digestAlgorithm)
{
  string keyURI = keyName.toUri();

  if(!doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE))
    throw Error("private key doesn't exists");
 
  try{
    using namespace CryptoPP;
    AutoSeededRandomPool rng;

    //Read private key
    ByteQueue bytes;
    FileSource file(m_impl->nameTransform(keyURI, ".pri").string().c_str(), true, new Base64Decoder);
    file.TransferTo(bytes);
    bytes.MessageEnd();
    RSA::PrivateKey privateKey;
    privateKey.Load(bytes);
  
    //Sign message
    switch(digestAlgorithm){
    case DIGEST_ALGORITHM_SHA256:
      {
	RSASS<PKCS1v15, SHA256>::Signer signer(privateKey);
	
	OBufferStream os;
	StringSource(data, dataLength, true, new SignerFilter(rng, signer, new FileSink(os)));
	
	return Block(Tlv::SignatureValue, os.buf());
      }
    default:
      throw Error("Unsupported digest algorithm!");
    }
  }catch(const CryptoPP::Exception& e){
    throw Error(e.what());
  }
}


ConstBufferPtr
SecTpmFile::decryptInTpm(const uint8_t* data, size_t dataLength, const Name& keyName, bool isSymmetric)
{
  string keyURI = keyName.toUri();
  if (!isSymmetric)
    {
      if(!doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE))
	throw Error("private key doesn't exist");

      try{
	using namespace CryptoPP;
        AutoSeededRandomPool rng;

	//Read private key
	ByteQueue bytes;
	FileSource file(m_impl->nameTransform(keyURI, ".pri").string().c_str(), true, new Base64Decoder);
	file.TransferTo(bytes);
	bytes.MessageEnd();
	RSA::PrivateKey privateKey;
	privateKey.Load(bytes);
	RSAES_PKCS1v15_Decryptor decryptor(privateKey);
	
	OBufferStream os;
	StringSource(data, dataLength, true, new PK_DecryptorFilter(rng, decryptor, new FileSink(os)));
	
	return os.buf();
      }
      catch(const CryptoPP::Exception& e){
	throw Error(e.what());
      }
    }
  else
    {
      throw Error("Symmetric encryption is not implemented!");
      // if(!doesKeyExistInTpm(keyName, KEY_CLASS_SYMMETRIC))
      // 	throw Error("symmetric key doesn't exist");

      // try{
      // 	string keyBits;
      // 	string symKeyFileName = m_impl->nameTransform(keyURI, ".key");
      // 	FileSource(symKeyFileName, true, new HexDecoder(new StringSink(keyBits)));
	
      // 	using CryptoPP::AES;
      // 	AutoSeededRandomPool rnd;
      // 	byte iv[AES::BLOCKSIZE];
      // 	rnd.GenerateBlock(iv, AES::BLOCKSIZE);

      // 	CFB_Mode<AES>::Decryption decryptor;
      // 	decryptor.SetKeyWithIV(reinterpret_cast<const uint8_t*>(keyBits.c_str()), keyBits.size(), iv);
	
      // 	OBufferStream os;
      // 	StringSource(data, dataLength, true, new StreamTransformationFilter(decryptor,new FileSink(os)));
      // 	return os.buf();

      // }catch(const CryptoPP::Exception& e){
      // 	throw Error(e.what());
      // }
    }
}

ConstBufferPtr
SecTpmFile::encryptInTpm(const uint8_t* data, size_t dataLength, const Name& keyName, bool isSymmetric)
{
  string keyURI = keyName.toUri();

  if (!isSymmetric)
    {
      if(!doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC))
	throw Error("public key doesn't exist");
      try
	{
          using namespace CryptoPP;
          AutoSeededRandomPool rng;

	  //Read private key
	  ByteQueue bytes;
	  FileSource file(m_impl->nameTransform(keyURI, ".pub").string().c_str(), true, new Base64Decoder);
	  file.TransferTo(bytes);
	  bytes.MessageEnd();
	  RSA::PublicKey publicKey;
	  publicKey.Load(bytes);

	  OBufferStream os;
	  RSAES_PKCS1v15_Encryptor encryptor(publicKey);

	  StringSource(data, dataLength, true, new PK_EncryptorFilter(rng, encryptor, new FileSink(os)));
	  return os.buf();
	}
      catch(const CryptoPP::Exception& e){
	throw Error(e.what());
      }
    }
  else
    {
      throw Error("Symmetric encryption is not implemented!");
      // if(!doesKeyExistInTpm(keyName, KEY_CLASS_SYMMETRIC))
      // 	throw Error("symmetric key doesn't exist");

      // try{
      // 	string keyBits;
      // 	string symKeyFileName = m_impl->nameTransform(keyURI, ".key");
      // 	FileSource(symKeyFileName, true, new HexDecoder(new StringSink(keyBits)));

      // 	using CryptoPP::AES;
      // 	AutoSeededRandomPool rnd;
      // 	byte iv[AES::BLOCKSIZE];
      // 	rnd.GenerateBlock(iv, AES::BLOCKSIZE);

      // 	CFB_Mode<AES>::Encryption encryptor;
      // 	encryptor.SetKeyWithIV(reinterpret_cast<const uint8_t*>(keyBits.c_str()), keyBits.size(), iv);

      // 	OBufferStream os;
      // 	StringSource(data, dataLength, true, new StreamTransformationFilter(encryptor, new FileSink(os)));
      // 	return os.buf();
      // }catch(const CryptoPP::Exception& e){
      // 	throw Error(e.what());
      // }
    }
}


void
SecTpmFile::generateSymmetricKeyInTpm(const Name & keyName, KeyType keyType, int keySize)
{
  string keyURI = keyName.toUri();

  if(doesKeyExistInTpm(keyName, KEY_CLASS_SYMMETRIC))
    throw Error("symmetric key exists");

  string keyFileName = m_impl->maintainMapping(keyURI);
  string symKeyFileName = keyFileName + ".key";

  try{
    switch(keyType){
    case KEY_TYPE_AES:
      {
        using namespace CryptoPP;
        AutoSeededRandomPool rng;

	SecByteBlock key(0x00, keySize);
	rng.GenerateBlock(key, keySize);
	
	StringSource(key, key.size(), true, new HexEncoder(new FileSink(symKeyFileName.c_str())));
	
	chmod(symKeyFileName.c_str(), 0000400);
	return;
      }
    default:
      throw Error("Unsupported symmetric key type!");
    }
  }catch(const CryptoPP::Exception& e){
    throw Error(e.what());
  }
}

bool
SecTpmFile::doesKeyExistInTpm(const Name & keyName, KeyClass keyClass)
{
  string keyURI = keyName.toUri();
  if (keyClass == KEY_CLASS_PUBLIC)
    {
      if(boost::filesystem::exists(m_impl->nameTransform(keyURI, ".pub")))
        return true;
      else
        return false;
    }
  if (keyClass == KEY_CLASS_PRIVATE)
    {
      if(boost::filesystem::exists(m_impl->nameTransform(keyURI, ".pri")))
        return true;
      else
        return false;
    }
  if (keyClass == KEY_CLASS_SYMMETRIC)
    {
      if(boost::filesystem::exists(m_impl->nameTransform(keyURI, ".key")))
        return true;
      else
        return false;
    }
  return false;
}

bool
SecTpmFile::generateRandomBlock(uint8_t* res, size_t size)
{
  try{
    CryptoPP::AutoSeededRandomPool rng;
    rng.GenerateBlock(res, size);
    return true;
  }catch(const CryptoPP::Exception& e){
    return false;
  }
}

} // namespace ndn
