/* -*- 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/files.h>
#include <cryptopp/asn.h>

#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("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();
}

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;

  OSStatus res = SecKeychainItemImport (importedKey,
                                        NULL,
                                        &externalFormat,
                                        &externalType,
                                        0,
                                        &keyParams,
                                        m_impl->m_keyChainRef,
                                        &outItems);
  
  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;
}

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
