/* -*- 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);
}

void
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;

  // 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)
            return;
        }
    }
  else
    {
      // If inTerminal is not set, get the password from GUI.
      SecKeychainUnlock(m_impl->m_keyChainRef, 0, 0, false);
    }
}

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);

  CFRelease(publicKey);
  CFRelease(privateKey);

  if (res == errSecSuccess)
    return;
  
  if (res == errSecAuthFailed && !retry)
    {
      unlockTpm(0, 0, false);
      generateKeyPairInTpmInternal(keyName, keyType, keySize, true);
    }
  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)
    {
      unlockTpm(0, 0, false);
      deleteKeyPairInTpmInternal(keyName, true);
    }
  else
    {
      _LOG_DEBUG("Fail to delete a key pair: " << res);
      throw Error("Fail to delete a key pair");
    }
}

void 
SecTpmOsx::generateSymmetricKeyInTpm(const Name & keyName, KeyType keyType, int keySize)
{

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

ptr_lib::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);

  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)
        {
          unlockTpm(0, 0, false);
          return exportPrivateKeyPkcs1FromTpmInternal(keyName, true);
        }
      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)
        {
          unlockTpm(0, 0, false);
          return importPrivateKeyPkcs1IntoTpmInternal(keyName, buf, size, true);
        }
      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);
  
  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) 
        {
          unlockTpm(0, 0, false);
          return signInTpmInternal(data, dataLength, keyName, digestAlgorithm, true);
        }
      else
        {
          CFShow(error);
          throw Error("Fail to sign data");
        }
    }

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

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

ConstBufferPtr
SecTpmOsx::decryptInTpm(const uint8_t* data, size_t dataLength, const Name & keyName, bool sym)
{
  _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 ptr_lib::make_shared<Buffer>(CFDataGetBytePtr(output), CFDataGetLength(output));
}
  
bool
SecTpmOsx::setACL(const Name & keyName, KeyClass keyClass, int acl, const string & appPath)
{
  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);


  CFArrayRef authList = SecACLCopyAuthorizations(aclRef);
    
  acl_res = SecACLRemove(aclRef);

  SecACLRef newACL;
  acl_res = SecACLCreateWithSimpleContents(accRef,
                                           newAppList,
                                           description,
                                           promptSelector,
                                           &newACL);

  acl_res = SecACLUpdateAuthorizations(newACL, authList);

  acc_res = SecKeychainItemSetAccess(privateKey, accRef);

  return true;
}

ConstBufferPtr
SecTpmOsx::encryptInTpm(const uint8_t* data, size_t dataLength, const Name & keyName, bool sym)
{
  _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 ptr_lib::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
