/* -*- 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.
 *
 * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
 */

#include "sec-tpm-osx.hpp"
#include "public-key.hpp"

#include "../../encoding/oid.hpp"
#include "../../encoding/buffer-stream.hpp"
#include "cryptopp.hpp"

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

#include <boost/lexical_cast.hpp>

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

#include <Security/SecDigestTransform.h>

namespace ndn {
namespace security {
namespace v1 {

using std::string;

const std::string SecTpmOsx::SCHEME("tpm-osxkeychain");

/**
 * @brief Helper class to wrap CoreFoundation object pointers
 *
 * The class is similar in spirit to shared_ptr, but uses CoreFoundation
 * mechanisms to retain/release object.
 *
 * Original implementation by Christopher Hunt and it was borrowed from
 * http://www.cocoabuilder.com/archive/cocoa/130776-auto-cfrelease-and.html
 */
template<class T>
class CFReleaser
{
public:
  //////////////////////////////
  // Construction/destruction //

  CFReleaser()
    : m_typeRef(nullptr)
  {
  }

  CFReleaser(const T& typeRef)
    : m_typeRef(typeRef)
  {
  }

  CFReleaser(const CFReleaser& inReleaser)
    : m_typeRef(nullptr)
  {
    retain(inReleaser.m_typeRef);
  }

  CFReleaser&
  operator=(const T& typeRef)
  {
    if (typeRef != m_typeRef) {
      release();
      m_typeRef = typeRef;
    }
    return *this;
  }

  CFReleaser&
  operator=(const CFReleaser& inReleaser)
  {
    retain(inReleaser.m_typeRef);
    return *this;
  }

  ~CFReleaser()
  {
    release();
  }

  ////////////
  // Access //

  // operator const T&() const
  // {
  //   return m_typeRef;
  // }

  // operator T&()
  // {
  //   return m_typeRef;
  // }

  const T&
  get() const
  {
    return m_typeRef;
  }

  T&
  get()
  {
    return m_typeRef;
  }

  ///////////////////
  // Miscellaneous //

  void
  retain(const T& typeRef)
  {
    if (typeRef != nullptr) {
      CFRetain(typeRef);
    }
    release();
    m_typeRef = typeRef;
  }

  void
  release()
  {
    if (m_typeRef != nullptr) {
      CFRelease(m_typeRef);
      m_typeRef = nullptr;
    }
  };

  bool
  operator==(std::nullptr_t)
  {
    return get() == nullptr;
  }

  bool
  operator!=(std::nullptr_t)
  {
    return get() != nullptr;
  }

private:
  T m_typeRef;
};


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

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

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

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

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

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

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

  /**
   * @brief Get the digest size of the corresponding algorithm
   *
   * @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(const std::string& location)
  : SecTpm(location)
  , m_impl(new Impl)
{
  // TODO: add location support
  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.
    BOOST_THROW_EXCEPTION(Error("No default keychain, please create one first"));
}

SecTpmOsx::~SecTpmOsx()
{
}

void
SecTpmOsx::setTpmPassword(const uint8_t* password, size_t passwordLength)
{
  m_impl->m_passwordSet = true;
  std::fill(m_impl->m_password.begin(), m_impl->m_password.end(), 0);
  m_impl->m_password.clear();
  m_impl->m_password.append(reinterpret_cast<const char*>(password), passwordLength);
}

void
SecTpmOsx::resetTpmPassword()
{
  m_impl->m_passwordSet = false;
  std::fill(m_impl->m_password.begin(), m_impl->m_password.end(), 0);
  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() const
{
  return m_impl->m_inTerminal;
}

bool
SecTpmOsx::isLocked()
{
  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 (!isLocked())
    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);
  }
#ifdef NDN_CXX_HAVE_GETPASS
  else if (m_impl->m_inTerminal) {
    // If no configured password, get password from terminal if inTerminal set.
    bool isLocked = true;
    const char* fmt = "Password to unlock the default keychain: ";
    int count = 0;

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

      char* getPassword = nullptr;
      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;
    }
  }
#endif // NDN_CXX_HAVE_GETPASS
  else {
    // If inTerminal is not set, get the password from GUI.
    SecKeychainUnlock(m_impl->m_keyChainRef, 0, nullptr, false);
  }

  return !isLocked();
}

void
SecTpmOsx::generateKeyPairInTpmInternal(const Name& keyName,
                                        const KeyParams& params,
                                        bool needRetry)
{

  if (doesKeyExistInTpm(keyName, KeyClass::PUBLIC)) {
    BOOST_THROW_EXCEPTION(Error("keyName already exists"));
  }

  string keyNameUri = m_impl->toInternalKeyName(keyName, KeyClass::PUBLIC);

  CFReleaser<CFStringRef> keyLabel =
    CFStringCreateWithCString(0,
                              keyNameUri.c_str(),
                              kCFStringEncodingUTF8);

  CFReleaser<CFMutableDictionaryRef> attrDict =
    CFDictionaryCreateMutable(0,
                              3,
                              &kCFTypeDictionaryKeyCallBacks,
                              0);

  KeyType keyType = params.getKeyType();
  uint32_t keySize = 0;
  switch (keyType) {
    case KeyType::RSA: {
      const RsaKeyParams& rsaParams = static_cast<const RsaKeyParams&>(params);
      keySize = rsaParams.getKeySize();
      break;
    }

    case KeyType::EC: {
      const EcdsaKeyParams& ecdsaParams = static_cast<const EcdsaKeyParams&>(params);
      keySize = ecdsaParams.getKeySize();
      break;
    }

    default:
      BOOST_THROW_EXCEPTION(Error("Fail to create a key pair: Unsupported key type"));
  }

  CFReleaser<CFNumberRef> cfKeySize = CFNumberCreate(0, kCFNumberIntType, &keySize);

  CFDictionaryAddValue(attrDict.get(), kSecAttrKeyType, m_impl->getAsymKeyType(keyType));
  CFDictionaryAddValue(attrDict.get(), kSecAttrKeySizeInBits, cfKeySize.get());
  CFDictionaryAddValue(attrDict.get(), kSecAttrLabel, keyLabel.get());

  CFReleaser<SecKeyRef> publicKey, privateKey;
  // C-style cast is used as per Apple convention
  OSStatus res = SecKeyGeneratePair((CFDictionaryRef)attrDict.get(),
                                    &publicKey.get(), &privateKey.get());

  if (res == errSecSuccess) {
    return;
  }

  if (res == errSecAuthFailed && !needRetry) {
    if (unlockTpm(nullptr, 0, false))
      generateKeyPairInTpmInternal(keyName, params, true);
    else
      BOOST_THROW_EXCEPTION(Error("Fail to unlock the keychain"));
  }
  else {
    BOOST_THROW_EXCEPTION(Error("Fail to create a key pair"));
  }
}

void
SecTpmOsx::deleteKeyPairInTpmInternal(const Name& keyName, bool needRetry)
{
  CFReleaser<CFStringRef> keyLabel =
    CFStringCreateWithCString(0,
                              keyName.toUri().c_str(),
                              kCFStringEncodingUTF8);

  CFReleaser<CFMutableDictionaryRef> searchDict =
    CFDictionaryCreateMutable(0, 5,
                              &kCFTypeDictionaryKeyCallBacks,
                              &kCFTypeDictionaryValueCallBacks);

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

  if (res == errSecSuccess)
    return;

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

void
SecTpmOsx::generateSymmetricKeyInTpm(const Name& keyName, const KeyParams& params)
{
  BOOST_THROW_EXCEPTION(Error("SecTpmOsx::generateSymmetricKeyInTpm is not supported"));
  // if (doesKeyExistInTpm(keyName, KeyClass::SYMMETRIC))
  //   throw Error("keyName has existed!");

  // string keyNameUri =  m_impl->toInternalKeyName(keyName, KeyClass::SYMMETRIC);

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

  // CFReleaser<CFStringRef> keyLabel =
  //   CFStringCreateWithCString(0,
  //                             keyNameUri.c_str(),
  //                             kCFStringEncodingUTF8);

  // CFReleaser<CFNumberRef> cfKeySize = CFNumberCreate(0, kCFNumberIntType, &keySize);

  // CFDictionaryAddValue(attrDict.get(), kSecAttrKeyType, m_impl->getSymKeyType(keyType));
  // CFDictionaryAddValue(attrDict.get(), kSecAttrKeySizeInBits, cfKeySize.get());
  // CFDictionaryAddValue(attrDict.get(), kSecAttrIsPermanent, kCFBooleanTrue);
  // CFDictionaryAddValue(attrDict.get(), kSecAttrLabel, keyLabel.get());

  // CFErrorRef error = 0;

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

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

shared_ptr<PublicKey>
SecTpmOsx::getPublicKeyFromTpm(const Name& keyName)
{
  CFReleaser<SecKeychainItemRef> publicKey = m_impl->getKey(keyName, KeyClass::PUBLIC);
  if (publicKey == nullptr) {
    BOOST_THROW_EXCEPTION(Error("Requested public key [" + keyName.toUri() + "] does not exist "
                                "in OSX Keychain"));
  }

  CFReleaser<CFDataRef> exportedKey;
  OSStatus res = SecItemExport(publicKey.get(),
                               kSecFormatOpenSSL,
                               0,
                               nullptr,
                               &exportedKey.get());
  if (res != errSecSuccess) {
    BOOST_THROW_EXCEPTION(Error("Cannot export requested public key from OSX Keychain"));
  }

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

std::string
SecTpmOsx::getScheme()
{
  return SCHEME;
}

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

  CFReleaser<SecKeychainItemRef> privateKey = m_impl->getKey(keyName, KeyClass::PRIVATE);
  if (privateKey == nullptr) {
    /// @todo Can this happen because of keychain is locked?
    BOOST_THROW_EXCEPTION(Error("Private key [" + keyName.toUri() + "] does not exist "
                                "in OSX Keychain"));
  }

  shared_ptr<PublicKey> publicKey = getPublicKeyFromTpm(keyName);

  CFReleaser<CFDataRef> exportedKey;
  OSStatus res = SecItemExport(privateKey.get(),
                               kSecFormatOpenSSL,
                               0,
                               nullptr,
                               &exportedKey.get());

  if (res != errSecSuccess) {
    if (res == errSecAuthFailed && !needRetry) {
      if (unlockTpm(nullptr, 0, false))
        return exportPrivateKeyPkcs8FromTpmInternal(keyName, true);
      else
        return nullptr;
    }
    else
      return nullptr;
  }

  uint32_t version = 0;
  Oid algorithm;
  bool hasParameters = false;
  Oid algorithmParameter;
  switch (publicKey->getKeyType()) {
    case KeyType::RSA: {
      algorithm = oid::RSA; // "RSA encryption"
      hasParameters = false;
      break;
    }

    case KeyType::EC: {
      // "ECDSA encryption"
      StringSource src(publicKey->get().buf(), publicKey->get().size(), true);
      BERSequenceDecoder subjectPublicKeyInfo(src);
      {
        BERSequenceDecoder algorithmInfo(subjectPublicKeyInfo);
        {
          algorithm.decode(algorithmInfo);
          algorithmParameter.decode(algorithmInfo);
        }
      }
      hasParameters = true;
      break;
    }

    default:
      BOOST_THROW_EXCEPTION(Error("Unsupported key type" +
                                  boost::lexical_cast<std::string>(publicKey->getKeyType())));
  }

  OBufferStream pkcs8Os;
  FileSink sink(pkcs8Os);

  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);
      if (hasParameters)
        algorithmParameter.encode(privateKeyAlgorithm);
      else
        DEREncodeNull(privateKeyAlgorithm);
    }
    privateKeyAlgorithm.MessageEnd();
    DEREncodeOctetString(privateKeyInfo,
                         CFDataGetBytePtr(exportedKey.get()),
                         CFDataGetLength(exportedKey.get()));
  }
  privateKeyInfo.MessageEnd();

  return pkcs8Os.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::importPrivateKeyPkcs8IntoTpmInternal(const Name& keyName,
                                                const uint8_t* buf, size_t size,
                                                bool needRetry)
{
  using namespace CryptoPP;

  StringSource privateKeySource(buf, size, true);
  SecByteBlock rawKeyBits;
  // PrivateKeyInfo ::= SEQUENCE {
  //   INTEGER,
  //   SEQUENCE,
  //   OCTECT STRING}
  BERSequenceDecoder privateKeyInfo(privateKeySource);
  {
    uint32_t versionNum;
    BERDecodeUnsigned<uint32_t>(privateKeyInfo, versionNum, INTEGER);
    BERSequenceDecoder sequenceDecoder(privateKeyInfo);
    {
      Oid keyTypeOid;
      keyTypeOid.decode(sequenceDecoder);

      if (keyTypeOid == oid::RSA)
        BERDecodeNull(sequenceDecoder);
      else if (keyTypeOid == oid::ECDSA) {
        Oid parameterOid;
        parameterOid.decode(sequenceDecoder);
      }
      else
        return false; // Unsupported key type;
    }
    BERDecodeOctetString(privateKeyInfo, rawKeyBits);
  }
  privateKeyInfo.MessageEnd();

  CFReleaser<CFDataRef> importedKey = CFDataCreateWithBytesNoCopy(0,
                                                                  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;
  CFReleaser<SecAccessRef> access;
  CFReleaser<CFStringRef> keyLabel = CFStringCreateWithCString(0,
                                                               keyName.toUri().c_str(),
                                                               kCFStringEncodingUTF8);
  SecAccessCreate(keyLabel.get(), 0, &access.get());
  keyParams.accessRef = access.get();
  CFReleaser<CFArrayRef> outItems;

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

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

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

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

  // C-style cast is used as per Apple convention
  SecKeychainItemRef privateKey = (SecKeychainItemRef)CFArrayGetValueAtIndex(outItems.get(), 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 = const_cast<char*>(keyUri.c_str());
    attrList.count++;
  }

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

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

  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)
{
  CFReleaser<CFDataRef> importedKey = CFDataCreateWithBytesNoCopy(0,
                                                                  buf,
                                                                  size,
                                                                  kCFAllocatorNull);

  SecExternalFormat externalFormat = kSecFormatOpenSSL;
  SecExternalItemType externalType = kSecItemTypePublicKey;
  CFReleaser<CFArrayRef> outItems;

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

  if (res != errSecSuccess)
    return false;

  // C-style cast is used as per Apple convention
  SecKeychainItemRef publicKey = (SecKeychainItemRef)CFArrayGetValueAtIndex(outItems.get(), 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 = const_cast<char*>(keyUri.c_str());
    attrList.count++;
  }

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

  if (res != errSecSuccess)
    return false;

  return true;
}

Block
SecTpmOsx::signInTpmInternal(const uint8_t* data, size_t dataLength,
                             const Name& keyName, DigestAlgorithm digestAlgorithm, bool needRetry)
{
  CFReleaser<CFDataRef> dataRef = CFDataCreateWithBytesNoCopy(0,
                                                              data,
                                                              dataLength,
                                                              kCFAllocatorNull);

  CFReleaser<SecKeychainItemRef> privateKey = m_impl->getKey(keyName, KeyClass::PRIVATE);
  if (privateKey == nullptr) {
    BOOST_THROW_EXCEPTION(Error("Private key [" + keyName.toUri() + "] does not exist "
                                "in OSX Keychain"));
  }

  CFReleaser<CFErrorRef> error;
  // C-style cast is used as per Apple convention
  CFReleaser<SecTransformRef> signer = SecSignTransformCreate((SecKeyRef)privateKey.get(),
                                                              &error.get());
  if (error != nullptr)
    BOOST_THROW_EXCEPTION(Error("Fail to create signer"));

  // Set input
  SecTransformSetAttribute(signer.get(),
                           kSecTransformInputAttributeName,
                           dataRef.get(),
                           &error.get());
  if (error != nullptr)
    BOOST_THROW_EXCEPTION(Error("Fail to configure input of signer"));

  // Enable use of padding
  SecTransformSetAttribute(signer.get(),
                           kSecPaddingKey,
                           kSecPaddingPKCS1Key,
                           &error.get());
  if (error != nullptr)
    BOOST_THROW_EXCEPTION(Error("Fail to configure digest algorithm of signer"));

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

  // Set padding attribute
  long digestSize = m_impl->getDigestSize(digestAlgorithm);
  CFReleaser<CFNumberRef> cfDigestSize = CFNumberCreate(0, kCFNumberLongType, &digestSize);
  SecTransformSetAttribute(signer.get(),
                           kSecDigestLengthAttribute,
                           cfDigestSize.get(),
                           &error.get());
  if (error != nullptr)
    BOOST_THROW_EXCEPTION(Error("Fail to configure digest size of signer"));

  // Actually sign
  // C-style cast is used as per Apple convention
  CFReleaser<CFDataRef> signature = (CFDataRef)SecTransformExecute(signer.get(), &error.get());
  if (error != nullptr) {
    if (!needRetry) {
      if (unlockTpm(nullptr, 0, false))
        return signInTpmInternal(data, dataLength, keyName, digestAlgorithm, true);
      else
        BOOST_THROW_EXCEPTION(Error("Fail to unlock the keychain"));
    }
    else {
      CFShow(error.get());
      BOOST_THROW_EXCEPTION(Error("Fail to sign data"));
    }
  }

  if (signature == nullptr)
    BOOST_THROW_EXCEPTION(Error("Signature is NULL!\n"));

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

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

  // KeyClass keyClass;
  // if (sym)
  //   keyClass = KeyClass::SYMMETRIC;
  // else
  //   keyClass = KeyClass::PRIVATE;

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

  // CFReleaser<SecKeyRef> decryptKey = (SecKeyRef)m_impl->getKey(keyName, keyClass);
  // if (decryptKey == nullptr)
  //   {
  //     /// @todo Can this happen because of keychain is locked?
  //     throw Error("Decruption key [" + ??? + "] does not exist in OSX Keychain");
  //   }

  // 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 == KeyClass::PRIVATE && acl == AclType::PRIVATE) {
    CFReleaser<SecKeychainItemRef> privateKey = m_impl->getKey(keyName, keyClass);
    if (privateKey == nullptr) {
      BOOST_THROW_EXCEPTION(Error("Private key [" + keyName.toUri() + "] does not exist "
                                  "in OSX Keychain"));
    }

    CFReleaser<SecAccessRef> accRef;
    SecKeychainItemCopyAccess(privateKey.get(), &accRef.get());

    CFReleaser<CFArrayRef> signACL = SecAccessCopyMatchingACLList(accRef.get(),
                                                                  kSecACLAuthorizationSign);

    // C-style cast is used as per Apple convention
    SecACLRef aclRef = (SecACLRef)CFArrayGetValueAtIndex(signACL.get(), 0);

    CFReleaser<CFArrayRef> appList;
    CFReleaser<CFStringRef> description;
    SecKeychainPromptSelector promptSelector;
    SecACLCopyContents(aclRef,
                       &appList.get(),
                       &description.get(),
                       &promptSelector);

    CFReleaser<CFMutableArrayRef> newAppList = CFArrayCreateMutableCopy(0,
                                                                        0,
                                                                        appList.get());

    CFReleaser<SecTrustedApplicationRef> trustedApp;
    SecTrustedApplicationCreateFromPath(appPath.c_str(),
                                        &trustedApp.get());

    CFArrayAppendValue(newAppList.get(), trustedApp.get());

    SecACLSetContents(aclRef,
                      newAppList.get(),
                      description.get(),
                      promptSelector);

    SecKeychainItemSetAccess(privateKey.get(), accRef.get());
  }
}

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

  // KeyClass keyClass;
  // if (sym)
  //   keyClass = KeyClass::SYMMETRIC;
  // else
  //   keyClass = KeyClass::PUBLIC;

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

  // CFReleaser<SecKeyRef> encryptKey = (SecKeyRef)m_impl->getKey(keyName, keyClass);
  // if (encryptKey == nullptr)
  //   {
  //     throw Error("Encryption key [" + ???? + "] does not exist in OSX Keychain");
  //   }

  // 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)
{
  string keyNameUri = m_impl->toInternalKeyName(keyName, keyClass);

  CFReleaser<CFStringRef> keyLabel = CFStringCreateWithCString(0,
                                                               keyNameUri.c_str(),
                                                               kCFStringEncodingUTF8);

  CFReleaser<CFMutableDictionaryRef> attrDict =
    CFDictionaryCreateMutable(0,
                              4,
                              &kCFTypeDictionaryKeyCallBacks,
                              0);

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

  CFReleaser<SecKeychainItemRef> itemRef;
  // C-style cast is used as per Apple convention
  OSStatus res = SecItemCopyMatching((CFDictionaryRef)attrDict.get(), (CFTypeRef*)&itemRef.get());

  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 //
////////////////////////////////

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

  CFReleaser<CFStringRef> keyLabel = CFStringCreateWithCString(0,
                                                               keyNameUri.c_str(),
                                                               kCFStringEncodingUTF8);

  CFReleaser<CFMutableDictionaryRef> attrDict =
    CFDictionaryCreateMutable(0,
                              5,
                              &kCFTypeDictionaryKeyCallBacks,
                              0);

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

  CFReleaser<SecKeychainItemRef> keyItem;
  // C-style cast is used as per Apple convention
  OSStatus res = SecItemCopyMatching((CFDictionaryRef)attrDict.get(), (CFTypeRef*)&keyItem.get());

  if (res != errSecSuccess)
    return 0;
  else
    return keyItem;
}

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

  if (KeyClass::SYMMETRIC == keyClass)
    return keyUri + "/symmetric";
  else
    return keyUri;
}

CFTypeRef
SecTpmOsx::Impl::getAsymKeyType(KeyType keyType)
{
  switch (keyType) {
  case KeyType::RSA:
    return kSecAttrKeyTypeRSA;
  case KeyType::EC:
    return kSecAttrKeyTypeECDSA;
  default:
    return 0;
  }
}

CFTypeRef
SecTpmOsx::Impl::getSymKeyType(KeyType keyType)
{
  switch (keyType) {
  case KeyType::AES:
    return kSecAttrKeyTypeAES;
  default:
    return 0;
  }
}

CFTypeRef
SecTpmOsx::Impl::getKeyClass(KeyClass keyClass)
{
  switch (keyClass) {
  case KeyClass::PRIVATE:
    return kSecAttrKeyClassPrivate;
  case KeyClass::PUBLIC:
    return kSecAttrKeyClassPublic;
  case KeyClass::SYMMETRIC:
    return kSecAttrKeyClassSymmetric;
  default:
    return 0;
  }
}

CFStringRef
SecTpmOsx::Impl::getDigestAlgorithm(DigestAlgorithm digestAlgo)
{
  switch (digestAlgo) {
  case DigestAlgorithm::SHA256:
    return kSecDigestSHA2;
  default:
    return 0;
  }
}

long
SecTpmOsx::Impl::getDigestSize(DigestAlgorithm digestAlgo)
{
  switch (digestAlgo) {
  case DigestAlgorithm::SHA256:
    return 256;
  default:
    return -1;
  }
}

} // namespace v1
} // namespace security
} // namespace ndn
