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

#include "common.hpp"

#include "sec-tpm-osx.hpp"

#include "security/public-key.hpp"
#include "util/logging.hpp"
#include "cryptopp.hpp"

#include <pwd.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

#include <CoreFoundation/CoreFoundation.h>
#include <Security/Security.h>
#include <Security/SecRandom.h>
#include <CoreServices/CoreServices.h>

using namespace std;

INIT_LOGGER("ndn.SecTpmOsx");

namespace ndn {

class SecTpmOsx::Impl {
public:
  Impl()
    : m_passwordSet(false)
    , m_inTerminal(false)
  {}

  /**
   * @brief Convert NDN name of a key to internal name of the key.
   *
   * @param keyName
   * @param keyClass
   * @return the internal key name
   */
  std::string
  toInternalKeyName(const Name & keyName, KeyClass keyClass);

  /**
   * @brief Get key.
   *
   * @param keyName
   * @param keyClass
   * @returns pointer to the key
   */
  SecKeychainItemRef
  getKey(const Name & keyName, KeyClass keyClass);

  /**
   * @brief Convert keyType to MAC OS symmetric key key type
   *
   * @param keyType
   * @returns MAC OS key type
   */
  const CFTypeRef
  getSymKeyType(KeyType keyType);

  /**
   * @brief Convert keyType to MAC OS asymmetirc key type
   *
   * @param keyType
   * @returns MAC OS key type
   */
  const CFTypeRef
  getAsymKeyType(KeyType keyType);

  /**
   * @brief Convert keyClass to MAC OS key class
   *
   * @param keyClass
   * @returns MAC OS key class
   */
  const CFTypeRef
  getKeyClass(KeyClass keyClass);

  /**
   * @brief Convert digestAlgo to MAC OS algorithm id
   *
   * @param digestAlgo
   * @returns MAC OS algorithm id
   */
  const CFStringRef
  getDigestAlgorithm(DigestAlgorithm digestAlgo);

  /**
   * @brief Get the digest size of the corresponding algorithm
   *
   * @param digestAlgo
   * @return digest size
   */
  long
  getDigestSize(DigestAlgorithm digestAlgo);

  ///////////////////////////////////////////////
  // everything here is public, including data //
  ///////////////////////////////////////////////
public:
  SecKeychainRef m_keyChainRef;
  bool m_passwordSet;
  string m_password;
  bool m_inTerminal;
};


SecTpmOsx::SecTpmOsx()
  : m_impl(new Impl)
{
  if(m_impl->m_inTerminal)
    SecKeychainSetUserInteractionAllowed (false);
  else
    SecKeychainSetUserInteractionAllowed (true);

  OSStatus res = SecKeychainCopyDefault(&m_impl->m_keyChainRef);

  if (res == errSecNoDefaultKeychain) //If no default key chain, create one.
    throw Error("No default keychain, create one first!");
}

SecTpmOsx::~SecTpmOsx(){
  //TODO: implement
}

void
SecTpmOsx::setTpmPassword(const uint8_t* password, size_t passwordLength)
{
  m_impl->m_passwordSet = true;
  memset(const_cast<char*>(m_impl->m_password.c_str()), 0, m_impl->m_password.size());
  m_impl->m_password.clear();
  m_impl->m_password.append(reinterpret_cast<const char*>(password), passwordLength);
}

void
SecTpmOsx::resetTpmPassword()
{
  m_impl->m_passwordSet = false;
  memset(const_cast<char*>(m_impl->m_password.c_str()), 0, m_impl->m_password.size());
  m_impl->m_password.clear();
}

void
SecTpmOsx::setInTerminal(bool inTerminal)
{
  m_impl->m_inTerminal = inTerminal;
  if(inTerminal)
    SecKeychainSetUserInteractionAllowed (false);
  else
    SecKeychainSetUserInteractionAllowed (true);
}

bool
SecTpmOsx::getInTerminal()
{
  return m_impl->m_inTerminal;
}

bool
SecTpmOsx::locked()
{
  SecKeychainStatus keychainStatus;

  OSStatus res = SecKeychainGetStatus(m_impl->m_keyChainRef, &keychainStatus);
  if(res != errSecSuccess)
    return true;
  else
    return ((kSecUnlockStateStatus & keychainStatus) == 0);
}

bool
SecTpmOsx::unlockTpm(const char* password, size_t passwordLength, bool usePassword)
{
  OSStatus res;

  // If the default key chain is already unlocked, return immediately.
  if(!locked())
    return true;

  // If the default key chain is locked, unlock the key chain.
  if(usePassword)
    {
      // Use the supplied password.
      res = SecKeychainUnlock(m_impl->m_keyChainRef,
                              passwordLength,
                              password,
                              true);
    }
  else if(m_impl->m_passwordSet)
    {
      // If no password supplied, then use the configured password if exists.
      SecKeychainUnlock(m_impl->m_keyChainRef,
                        m_impl->m_password.size(),
                        m_impl->m_password.c_str(),
                        true);
    }
  else if(m_impl->m_inTerminal)
    {
      // If no configured password, get password from terminal if inTerminal set.
      bool locked = true;
      const char* fmt = "Password to unlock the default keychain: ";
      int count = 0;

      while(locked)
        {
          if(count > 2)
            break;

          char* getPassword = NULL;
          getPassword = getpass(fmt);
          count++;

          if (!getPassword)
            continue;

          res = SecKeychainUnlock(m_impl->m_keyChainRef,
                                  strlen(getPassword),
                                  getPassword,
                                  true);

          memset(getPassword, 0, strlen(getPassword));

          if(res == errSecSuccess)
            break;
        }
    }
  else
    {
      // If inTerminal is not set, get the password from GUI.
      SecKeychainUnlock(m_impl->m_keyChainRef, 0, 0, false);
    }

  return !locked();
}

void
SecTpmOsx::generateKeyPairInTpmInternal(const Name & keyName, KeyType keyType, int keySize, bool retry)
{

  if(doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC)){
    _LOG_DEBUG("keyName has existed");
    throw Error("keyName has existed");
  }

  string keyNameUri = m_impl->toInternalKeyName(keyName, KEY_CLASS_PUBLIC);

  SecKeyRef publicKey, privateKey;

  CFStringRef keyLabel = CFStringCreateWithCString(NULL,
                                                   keyNameUri.c_str(),
                                                   kCFStringEncodingUTF8);

  CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(NULL,
                                                              3,
                                                              &kCFTypeDictionaryKeyCallBacks,
                                                              NULL);

  CFDictionaryAddValue(attrDict, kSecAttrKeyType, m_impl->getAsymKeyType(keyType));
  CFDictionaryAddValue(attrDict, kSecAttrKeySizeInBits, CFNumberCreate(NULL, kCFNumberIntType, &keySize));
  CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);

  OSStatus res = SecKeyGeneratePair((CFDictionaryRef)attrDict, &publicKey, &privateKey);

  if (res == errSecSuccess)
    {
      CFRelease(publicKey);
      CFRelease(privateKey);
      return;
    }

  if (res == errSecAuthFailed && !retry)
    {
      if(unlockTpm(0, 0, false))
        generateKeyPairInTpmInternal(keyName, keyType, keySize, true);
      else
        throw Error("Fail to unlock the keychain");
    }
  else
    {
      _LOG_DEBUG("Fail to create a key pair: " << res);
      throw Error("Fail to create a key pair");
    }
}

void
SecTpmOsx::deleteKeyPairInTpmInternal(const Name &keyName, bool retry)
{
  CFStringRef keyLabel = CFStringCreateWithCString(NULL,
                                                   keyName.toUri().c_str(),
                                                   kCFStringEncodingUTF8);

  CFMutableDictionaryRef searchDict =
    CFDictionaryCreateMutable(NULL, 5, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);

  CFDictionaryAddValue(searchDict, kSecClass, kSecClassKey);
  CFDictionaryAddValue(searchDict, kSecAttrLabel, keyLabel);
  CFDictionaryAddValue(searchDict, kSecMatchLimit, kSecMatchLimitAll);
  OSStatus res = SecItemDelete(searchDict);

  if (res == errSecSuccess)
    return;

  if (res == errSecAuthFailed && !retry)
    {
      if(unlockTpm(0, 0, false))
        deleteKeyPairInTpmInternal(keyName, true);
    }
}

void
SecTpmOsx::generateSymmetricKeyInTpm(const Name & keyName, KeyType keyType, int keySize)
{
  throw Error("SecTpmOsx::generateSymmetricKeyInTpm is not supported");
  // if(doesKeyExistInTpm(keyName, KEY_CLASS_SYMMETRIC))
  //   throw Error("keyName has existed!");

  // string keyNameUri =  m_impl->toInternalKeyName(keyName, KEY_CLASS_SYMMETRIC);

  // CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(kCFAllocatorDefault,
  //                                                             0,
  //                                                             &kCFTypeDictionaryKeyCallBacks,
  //                                                             &kCFTypeDictionaryValueCallBacks);

  // CFStringRef keyLabel = CFStringCreateWithCString(NULL,
  //                                                  keyNameUri.c_str(),
  //                                                  kCFStringEncodingUTF8);

  // CFDictionaryAddValue(attrDict, kSecAttrKeyType, m_impl->getSymKeyType(keyType));
  // CFDictionaryAddValue(attrDict, kSecAttrKeySizeInBits, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &keySize));
  // CFDictionaryAddValue(attrDict, kSecAttrIsPermanent, kCFBooleanTrue);
  // CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);

  // CFErrorRef error = NULL;

  // SecKeyRef symmetricKey = SecKeyGenerateSymmetric(attrDict, &error);

  // if (error)
  //   throw Error("Fail to create a symmetric key");
}

shared_ptr<PublicKey>
SecTpmOsx::getPublicKeyFromTpm(const Name & keyName)
{
  _LOG_TRACE("OSXPrivateKeyStorage::getPublickey");

  SecKeychainItemRef publicKey = m_impl->getKey(keyName, KEY_CLASS_PUBLIC);

  CFDataRef exportedKey;

  OSStatus res = SecItemExport(publicKey,
                               kSecFormatOpenSSL,
                               0,
                               NULL,
                               &exportedKey);
  if (res != errSecSuccess)
    {
      throw Error("Cannot export requested public key from OSX Keychain");
    }

  shared_ptr<PublicKey> key = make_shared<PublicKey>(CFDataGetBytePtr(exportedKey), CFDataGetLength(exportedKey));
  CFRelease(exportedKey);
  return key;
}

ConstBufferPtr
SecTpmOsx::exportPrivateKeyPkcs1FromTpmInternal(const Name& keyName, bool retry)
{
  using namespace CryptoPP;

  SecKeychainItemRef privateKey = m_impl->getKey(keyName, KEY_CLASS_PRIVATE);
  CFDataRef exportedKey;
  OSStatus res = SecItemExport(privateKey,
                               kSecFormatOpenSSL,
                               0,
                               NULL,
                               &exportedKey);

  if(res != errSecSuccess)
    {
      if(res == errSecAuthFailed && !retry)
        {
          if(unlockTpm(0, 0, false))
            return exportPrivateKeyPkcs1FromTpmInternal(keyName, true);
          else
            return shared_ptr<Buffer>();
        }
      else
        return shared_ptr<Buffer>();
    }

  OBufferStream pkcs1Os;
  FileSink sink(pkcs1Os);

  uint32_t version = 0;
  OID algorithm("1.2.840.113549.1.1.1");
  SecByteBlock rawKeyBits;
  // PrivateKeyInfo ::= SEQUENCE {
  //   version              INTEGER,
  //   privateKeyAlgorithm  SEQUENCE,
  //   privateKey           OCTECT STRING}
  DERSequenceEncoder privateKeyInfo(sink);
  {
    DEREncodeUnsigned<uint32_t>(privateKeyInfo, version, INTEGER);
    DERSequenceEncoder privateKeyAlgorithm(privateKeyInfo);
    {
      algorithm.encode(privateKeyAlgorithm);
      DEREncodeNull(privateKeyAlgorithm);
    }
    privateKeyAlgorithm.MessageEnd();
    DEREncodeOctetString(privateKeyInfo, CFDataGetBytePtr(exportedKey), CFDataGetLength(exportedKey));
  }
  privateKeyInfo.MessageEnd();

  CFRelease(exportedKey);
  return pkcs1Os.buf();
}

#ifdef __GNUC__
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
#pragma GCC diagnostic push
#endif // __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif // __GNUC__

bool
SecTpmOsx::importPrivateKeyPkcs1IntoTpmInternal(const Name& keyName, const uint8_t* buf, size_t size, bool retry)
{
  using namespace CryptoPP;

  StringSource privateKeySource(buf, size, true);
  uint32_t tmpNum;
  OID tmpOID;
  SecByteBlock rawKeyBits;
  // PrivateKeyInfo ::= SEQUENCE {
  //   INTEGER,
  //   SEQUENCE,
  //   OCTECT STRING}
  BERSequenceDecoder privateKeyInfo(privateKeySource);
  {
    BERDecodeUnsigned<uint32_t>(privateKeyInfo, tmpNum, INTEGER);
    BERSequenceDecoder sequenceDecoder(privateKeyInfo);
    {
      tmpOID.decode(sequenceDecoder);
      BERDecodeNull(sequenceDecoder);
    }
    BERDecodeOctetString(privateKeyInfo, rawKeyBits);
  }
  privateKeyInfo.MessageEnd();

  CFDataRef importedKey = CFDataCreateWithBytesNoCopy(NULL,
                                                      rawKeyBits.BytePtr(),
                                                      rawKeyBits.size(),
                                                      kCFAllocatorNull);

  SecExternalFormat externalFormat = kSecFormatOpenSSL;
  SecExternalItemType externalType = kSecItemTypePrivateKey;
  SecKeyImportExportParameters keyParams;
  memset(&keyParams, 0, sizeof(keyParams));
  keyParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
  keyParams.keyAttributes = CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_PERMANENT;
  SecAccessRef access;
  CFStringRef keyLabel = CFStringCreateWithCString(NULL,
                                                   keyName.toUri().c_str(),
                                                   kCFStringEncodingUTF8);
  SecAccessCreate(keyLabel, NULL, &access);
  keyParams.accessRef = access;
  CFArrayRef outItems;

#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#endif // __clang__

  OSStatus res = SecKeychainItemImport (importedKey,
                                        NULL,
                                        &externalFormat,
                                        &externalType,
                                        0,
                                        &keyParams,
                                        m_impl->m_keyChainRef,
                                        &outItems);

#ifdef __clang__
#pragma clang diagnostic pop
#endif // __clang__

  if(res != errSecSuccess)
    {
      if(res == errSecAuthFailed && !retry)
        {
          if(unlockTpm(0, 0, false))
            return importPrivateKeyPkcs1IntoTpmInternal(keyName, buf, size, true);
          else
            return false;
        }
      else
        return false;
    }

  SecKeychainItemRef privateKey = (SecKeychainItemRef)CFArrayGetValueAtIndex(outItems, 0);
  SecKeychainAttribute attrs[1]; // maximum number of attributes
  SecKeychainAttributeList attrList = { 0, attrs };
  string keyUri = keyName.toUri();
  {
    attrs[attrList.count].tag = kSecKeyPrintName;
    attrs[attrList.count].length = keyUri.size();
    attrs[attrList.count].data = (void *)keyUri.c_str();
    attrList.count++;
  }

  res = SecKeychainItemModifyAttributesAndData(privateKey,
                                               &attrList,
                                               0,
                                               NULL);

  if(res != errSecSuccess)
    {
      return false;
    }

  CFRelease(importedKey);
  return true;
}

#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
#pragma GCC diagnostic pop
#endif // __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)

bool
SecTpmOsx::importPublicKeyPkcs1IntoTpm(const Name& keyName, const uint8_t* buf, size_t size)
{
  CFDataRef importedKey = CFDataCreateWithBytesNoCopy(NULL,
                                                      buf,
                                                      size,
                                                      kCFAllocatorNull);

  SecExternalFormat externalFormat = kSecFormatOpenSSL;
  SecExternalItemType externalType = kSecItemTypePublicKey;
  CFArrayRef outItems;

  OSStatus res = SecItemImport (importedKey,
                                NULL,
                                &externalFormat,
                                &externalType,
                                0,
                                NULL,
                                m_impl->m_keyChainRef,
                                &outItems);

  if(res != errSecSuccess)
    return false;

  SecKeychainItemRef publicKey = (SecKeychainItemRef)CFArrayGetValueAtIndex(outItems, 0);
  SecKeychainAttribute attrs[1]; // maximum number of attributes
  SecKeychainAttributeList attrList = { 0, attrs };
  string keyUri = keyName.toUri();
  {
    attrs[attrList.count].tag = kSecKeyPrintName;
    attrs[attrList.count].length = keyUri.size();
    attrs[attrList.count].data = (void *)keyUri.c_str();
    attrList.count++;
  }

  res = SecKeychainItemModifyAttributesAndData(publicKey,
                                               &attrList,
                                               0,
                                               NULL);

  if(res != errSecSuccess)
    return false;

  CFRelease(importedKey);
  return true;
}

Block
SecTpmOsx::signInTpmInternal(const uint8_t *data, size_t dataLength, const Name& keyName, DigestAlgorithm digestAlgorithm, bool retry)
{
  _LOG_TRACE("OSXPrivateKeyStorage::Sign");

  CFDataRef dataRef = CFDataCreateWithBytesNoCopy(NULL,
                                                  data,
                                                  dataLength,
                                                  kCFAllocatorNull);

  SecKeyRef privateKey = (SecKeyRef)m_impl->getKey(keyName, KEY_CLASS_PRIVATE);

  CFErrorRef error;
  SecTransformRef signer = SecSignTransformCreate((SecKeyRef)privateKey, &error);
  if (error) throw Error("Fail to create signer");

  // Set input
  Boolean set_res = SecTransformSetAttribute(signer,
                                             kSecTransformInputAttributeName,
                                             dataRef,
                                             &error);
  if (error) throw Error("Fail to configure input of signer");

  // Enable use of padding
  SecTransformSetAttribute(signer,
                           kSecPaddingKey,
                           kSecPaddingPKCS1Key,
                           &error);
  if (error) throw Error("Fail to configure digest algorithm of signer");

  // Set padding type
  set_res = SecTransformSetAttribute(signer,
                                     kSecDigestTypeAttribute,
                                     m_impl->getDigestAlgorithm(digestAlgorithm),
                                     &error);
  if (error) throw Error("Fail to configure digest algorithm of signer");

  // Set padding attribute
  long digestSize = m_impl->getDigestSize(digestAlgorithm);
  set_res = SecTransformSetAttribute(signer,
                                     kSecDigestLengthAttribute,
                                     CFNumberCreate(NULL, kCFNumberLongType, &digestSize),
                                     &error);
  if (error) throw Error("Fail to configure digest size of signer");

  // Actually sign
  CFDataRef signature = (CFDataRef) SecTransformExecute(signer, &error);
  if (error)
    {
      if(!retry)
        {
          if(unlockTpm(0, 0, false))
            return signInTpmInternal(data, dataLength, keyName, digestAlgorithm, true);
          else
            throw Error("Fail to unlock the keychain");
        }
      else
        {
          CFShow(error);
          throw Error("Fail to sign data");
        }
    }

  if (!signature) throw Error("Signature is NULL!\n");

  return Block(Tlv::SignatureValue,
               make_shared<Buffer>(CFDataGetBytePtr(signature), CFDataGetLength(signature)));
}

ConstBufferPtr
SecTpmOsx::decryptInTpm(const uint8_t* data, size_t dataLength, const Name & keyName, bool sym)
{
  throw Error("SecTpmOsx::decryptInTpm is not supported");
  // _LOG_TRACE("OSXPrivateKeyStorage::Decrypt");

  // KeyClass keyClass;
  // if(sym)
  //   keyClass = KEY_CLASS_SYMMETRIC;
  // else
  //   keyClass = KEY_CLASS_PRIVATE;

  // CFDataRef dataRef = CFDataCreate(NULL,
  //                                  reinterpret_cast<const unsigned char*>(data),
  //                                  dataLength
  //                                  );

  // // _LOG_DEBUG("CreateData");

  // SecKeyRef decryptKey = (SecKeyRef)m_impl->getKey(keyName, keyClass);

  // // _LOG_DEBUG("GetKey");

  // CFErrorRef error;
  // SecTransformRef decrypt = SecDecryptTransformCreate(decryptKey, &error);
  // if (error) throw Error("Fail to create decrypt");

  // Boolean set_res = SecTransformSetAttribute(decrypt,
  //                                            kSecTransformInputAttributeName,
  //                                            dataRef,
  //                                            &error);
  // if (error) throw Error("Fail to configure decrypt");

  // CFDataRef output = (CFDataRef) SecTransformExecute(decrypt, &error);
  // if (error)
  //   {
  //     CFShow(error);
  //     throw Error("Fail to decrypt data");
  //   }
  // if (!output) throw Error("Output is NULL!\n");

  // return make_shared<Buffer>(CFDataGetBytePtr(output), CFDataGetLength(output));
}

void
SecTpmOsx::addAppToACL(const Name & keyName, KeyClass keyClass, const string & appPath, AclType acl)
{
  if(keyClass == KEY_CLASS_PRIVATE && acl == ACL_TYPE_PRIVATE)
    {
      SecKeychainItemRef privateKey = m_impl->getKey(keyName, keyClass);

      SecAccessRef accRef;
      OSStatus acc_res = SecKeychainItemCopyAccess(privateKey, &accRef);

      CFArrayRef signACL = SecAccessCopyMatchingACLList(accRef,
                                                        kSecACLAuthorizationSign);

      SecACLRef aclRef = (SecACLRef) CFArrayGetValueAtIndex(signACL, 0);

      CFArrayRef appList;
      CFStringRef description;
      SecKeychainPromptSelector promptSelector;
      OSStatus acl_res = SecACLCopyContents(aclRef,
                                            &appList,
                                            &description,
                                            &promptSelector);

      CFMutableArrayRef newAppList = CFArrayCreateMutableCopy(NULL,
                                                              0,
                                                              appList);

      SecTrustedApplicationRef trustedApp;
      acl_res = SecTrustedApplicationCreateFromPath(appPath.c_str(),
                                                    &trustedApp);

      CFArrayAppendValue(newAppList, trustedApp);

      acl_res = SecACLSetContents(aclRef,
                                  newAppList,
                                  description,
                                  promptSelector);

      acc_res = SecKeychainItemSetAccess(privateKey, accRef);
    }
}

ConstBufferPtr
SecTpmOsx::encryptInTpm(const uint8_t* data, size_t dataLength, const Name & keyName, bool sym)
{
  throw Error("SecTpmOsx::encryptInTpm is not supported");
  // _LOG_TRACE("OSXPrivateKeyStorage::Encrypt");

  // KeyClass keyClass;
  // if(sym)
  //   keyClass = KEY_CLASS_SYMMETRIC;
  // else
  //   keyClass = KEY_CLASS_PUBLIC;

  // CFDataRef dataRef = CFDataCreate(NULL,
  //                                  reinterpret_cast<const unsigned char*>(data),
  //                                  dataLength
  //                                  );

  // SecKeyRef encryptKey = (SecKeyRef)m_impl->getKey(keyName, keyClass);

  // CFErrorRef error;
  // SecTransformRef encrypt = SecEncryptTransformCreate(encryptKey, &error);
  // if (error) throw Error("Fail to create encrypt");

  // Boolean set_res = SecTransformSetAttribute(encrypt,
  //                                            kSecTransformInputAttributeName,
  //                                            dataRef,
  //                                            &error);
  // if (error) throw Error("Fail to configure encrypt");

  // CFDataRef output = (CFDataRef) SecTransformExecute(encrypt, &error);
  // if (error) throw Error("Fail to encrypt data");

  // if (!output) throw Error("Output is NULL!\n");

  // return make_shared<Buffer> (CFDataGetBytePtr(output), CFDataGetLength(output));
}

bool
SecTpmOsx::doesKeyExistInTpm(const Name & keyName, KeyClass keyClass)
{
  _LOG_TRACE("OSXPrivateKeyStorage::doesKeyExist");

  string keyNameUri = m_impl->toInternalKeyName(keyName, keyClass);

  CFStringRef keyLabel = CFStringCreateWithCString(NULL,
                                                   keyNameUri.c_str(),
                                                   kCFStringEncodingUTF8);

  CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(NULL,
                                                              4,
                                                              &kCFTypeDictionaryKeyCallBacks,
                                                              NULL);

  CFDictionaryAddValue(attrDict, kSecClass, kSecClassKey);
  // CFDictionaryAddValue(attrDict, kSecAttrKeyClass, m_impl->getKeyClass(keyClass));
  CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
  CFDictionaryAddValue(attrDict, kSecReturnRef, kCFBooleanTrue);

  SecKeychainItemRef itemRef;
  OSStatus res = SecItemCopyMatching((CFDictionaryRef)attrDict, (CFTypeRef*)&itemRef);

  if(res == errSecSuccess)
    return true;
  else
    return false;

}

bool
SecTpmOsx::generateRandomBlock(uint8_t* res, size_t size)
{
  return (SecRandomCopyBytes(kSecRandomDefault, size, res) == 0);
}

////////////////////////////////
// OSXPrivateKeyStorage::Impl //
////////////////////////////////

SecKeychainItemRef
SecTpmOsx::Impl::getKey(const Name & keyName, KeyClass keyClass)
{
  string keyNameUri = toInternalKeyName(keyName, keyClass);

  CFStringRef keyLabel = CFStringCreateWithCString(NULL,
                                                   keyNameUri.c_str(),
                                                   kCFStringEncodingUTF8);

  CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(NULL,
                                                              5,
                                                              &kCFTypeDictionaryKeyCallBacks,
                                                              NULL);

  CFDictionaryAddValue(attrDict, kSecClass, kSecClassKey);
  CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
  CFDictionaryAddValue(attrDict, kSecAttrKeyClass, getKeyClass(keyClass));
  CFDictionaryAddValue(attrDict, kSecReturnRef, kCFBooleanTrue);

  SecKeychainItemRef keyItem;

  OSStatus res = SecItemCopyMatching((CFDictionaryRef) attrDict, (CFTypeRef*)&keyItem);

  if(res != errSecSuccess){
    _LOG_DEBUG("Fail to find the key!");
    return NULL;
  }
  else
    return keyItem;
}

string
SecTpmOsx::Impl::toInternalKeyName(const Name & keyName, KeyClass keyClass)
{
  string keyUri = keyName.toUri();

  if(KEY_CLASS_SYMMETRIC == keyClass)
    return keyUri + "/symmetric";
  else
    return keyUri;
}

const CFTypeRef
SecTpmOsx::Impl::getAsymKeyType(KeyType keyType)
{
  switch(keyType){
  case KEY_TYPE_RSA:
    return kSecAttrKeyTypeRSA;
  default:
    _LOG_DEBUG("Unrecognized key type!")
      return NULL;
  }
}

const CFTypeRef
SecTpmOsx::Impl::getSymKeyType(KeyType keyType)
{
  switch(keyType){
  case KEY_TYPE_AES:
    return kSecAttrKeyTypeAES;
  default:
    _LOG_DEBUG("Unrecognized key type!")
      return NULL;
  }
}

const CFTypeRef
SecTpmOsx::Impl::getKeyClass(KeyClass keyClass)
{
  switch(keyClass){
  case KEY_CLASS_PRIVATE:
    return kSecAttrKeyClassPrivate;
  case KEY_CLASS_PUBLIC:
    return kSecAttrKeyClassPublic;
  case KEY_CLASS_SYMMETRIC:
    return kSecAttrKeyClassSymmetric;
  default:
    _LOG_DEBUG("Unrecognized key class!");
    return NULL;
  }
}

const CFStringRef
SecTpmOsx::Impl::getDigestAlgorithm(DigestAlgorithm digestAlgo)
{
  switch(digestAlgo){
    // case DIGEST_MD2:
    //   return kSecDigestMD2;
    // case DIGEST_MD5:
    //   return kSecDigestMD5;
    // case DIGEST_SHA1:
    //   return kSecDigestSHA1;
  case DIGEST_ALGORITHM_SHA256:
    return kSecDigestSHA2;
  default:
    _LOG_DEBUG("Unrecognized digest algorithm!");
    return NULL;
  }
}

long
SecTpmOsx::Impl::getDigestSize(DigestAlgorithm digestAlgo)
{
  switch(digestAlgo){
  case DIGEST_ALGORITHM_SHA256:
    return 256;
    // case DIGEST_SHA1:
    // case DIGEST_MD2:
    // case DIGEST_MD5:
    //   return 0;
  default:
    _LOG_DEBUG("Unrecognized digest algorithm! Unknown digest size");
    return -1;
  }
}

} // namespace ndn
