security: Add new TPM framework

The TPM framework is separated into two parts:
1) The front end class Tpm provides the interface to KeyChain. The public
   interface of Tpm is read-only.
2) The back end classes represent concrete implementations, such as
   tpm::BackEndFile and tpm::BackEndOsx which may also provide
   implementation-specific management interfaces.

New TPM supports different key id type when generating new key.  The
default type is changed to 64-bit random number.

Change-Id: I41154c2ded4b65fb0bef2f4a0d2c5b77843be05d
Refs: #2948
diff --git a/src/security/pib/key.cpp b/src/security/pib/key.cpp
index c59a39d..51f368c 100644
--- a/src/security/pib/key.cpp
+++ b/src/security/pib/key.cpp
@@ -22,6 +22,7 @@
 #include "key.hpp"
 #include "pib-impl.hpp"
 #include "pib.hpp"
+#include "../v2/certificate.hpp"
 
 namespace ndn {
 namespace security {
@@ -196,5 +197,19 @@
     BOOST_THROW_EXCEPTION(std::domain_error("Invalid Key instance"));
 }
 
+namespace v2 {
+
+Name
+constructKeyName(const Name& identity, const name::Component& keyId)
+{
+  Name keyName = identity;
+  keyName
+    .append(Certificate::KEY_COMPONENT)
+    .append(keyId);
+  return keyName;
+}
+
+} // namespace v2
+
 } // namespace security
 } // namespace ndn
diff --git a/src/security/pib/key.hpp b/src/security/pib/key.hpp
index 7118149..53a0ba1 100644
--- a/src/security/pib/key.hpp
+++ b/src/security/pib/key.hpp
@@ -201,7 +201,17 @@
   shared_ptr<PibImpl> m_impl;
 };
 
+namespace v2 {
+
+/**
+ * @brief Construct key name based on the appropriate naming conventions
+ */
+Name
+constructKeyName(const Name& identity, const name::Component& keyId);
+
+} // namespace v2
+
 } // namespace security
 } // namespace ndn
 
-#endif // NDN_SECURITY_PIB_PIB_HPP
+#endif // NDN_SECURITY_PIB_KEY_HPP
diff --git a/src/security/tpm/back-end-file.cpp b/src/security/tpm/back-end-file.cpp
new file mode 100644
index 0000000..f16d7cf
--- /dev/null
+++ b/src/security/tpm/back-end-file.cpp
@@ -0,0 +1,192 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 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.
+ */
+
+#include "back-end-file.hpp"
+#include "key-handle-mem.hpp"
+#include "../transform.hpp"
+#include "../transform/private-key.hpp"
+#include "../../encoding/buffer-stream.hpp"
+#include <unordered_map>
+#include <fstream>
+#include <cstdlib>
+#include <boost/filesystem.hpp>
+
+namespace ndn {
+namespace security {
+namespace tpm {
+
+using transform::PrivateKey;
+
+class BackEndFile::Impl
+{
+public:
+  explicit
+  Impl(const std::string& dir)
+  {
+    if (!dir.empty()) {
+      keystorePath = boost::filesystem::path(dir);
+    }
+#ifdef NDN_CXX_HAVE_TESTS
+    else if (getenv("TEST_HOME") != nullptr) {
+      keystorePath = boost::filesystem::path(getenv("TEST_HOME")) / ".ndn";
+    }
+#endif // NDN_CXX_HAVE_TESTS
+    else if (getenv("HOME") != nullptr) {
+      keystorePath = boost::filesystem::path(getenv("HOME")) / ".ndn";
+    }
+    else {
+      keystorePath = boost::filesystem::current_path() / ".ndn";
+    }
+
+    keystorePath /= "ndnsec-key-file";
+    boost::filesystem::create_directories(keystorePath);
+  }
+
+  boost::filesystem::path
+  toFileName(const Name& keyName)
+  {
+    std::stringstream os;
+    {
+      using namespace transform;
+      bufferSource(keyName.wireEncode().wire(), keyName.wireEncode().size()) >>
+        digestFilter(DigestAlgorithm::SHA256) >> hexEncode() >> streamSink(os);
+    }
+    return keystorePath / (os.str() + ".privkey");
+  }
+
+public:
+  boost::filesystem::path keystorePath;
+};
+
+BackEndFile::BackEndFile(const std::string& location)
+  : m_impl(new Impl(location))
+{
+}
+
+BackEndFile::~BackEndFile() = default;
+
+bool
+BackEndFile::doHasKey(const Name& keyName) const
+{
+  if (!boost::filesystem::exists(m_impl->toFileName(keyName)))
+    return false;
+
+  try {
+    loadKey(keyName);
+    return true;
+  }
+  catch (const std::runtime_error&) {
+    return false;
+  }
+}
+
+unique_ptr<KeyHandle>
+BackEndFile::doGetKeyHandle(const Name& keyName) const
+{
+  if (!doHasKey(keyName))
+    return nullptr;
+
+  return make_unique<KeyHandleMem>(loadKey(keyName));
+}
+
+unique_ptr<KeyHandle>
+BackEndFile::doCreateKey(const Name& identityName, const KeyParams& params)
+{
+  shared_ptr<PrivateKey> key(transform::generatePrivateKey(params).release());
+  unique_ptr<KeyHandle> keyHandle = make_unique<KeyHandleMem>(key);
+
+  setKeyName(*keyHandle, identityName, params);
+
+  try {
+    saveKey(keyHandle->getKeyName(), key);
+    return keyHandle;
+  }
+  catch (const std::runtime_error& e) {
+    BOOST_THROW_EXCEPTION(Error(std::string("Cannot write key to disk: ") + e.what()));
+  }
+}
+
+void
+BackEndFile::doDeleteKey(const Name& keyName)
+{
+  boost::filesystem::path keyPath(m_impl->toFileName(keyName));
+
+  if (boost::filesystem::exists(keyPath)) {
+    try {
+      boost::filesystem::remove(keyPath);
+    }
+    catch (const boost::filesystem::filesystem_error&) {
+      BOOST_THROW_EXCEPTION(Error("Cannot delete key"));
+    }
+  }
+}
+
+ConstBufferPtr
+BackEndFile::doExportKey(const Name& keyName, const char* pw, size_t pwLen)
+{
+  shared_ptr<PrivateKey> key;
+  try {
+    key = loadKey(keyName);
+  }
+  catch (const PrivateKey::Error&) {
+    BOOST_THROW_EXCEPTION(Error("Cannot export private key"));
+  }
+  OBufferStream os;
+  key->savePkcs8(os, pw, pwLen);
+  return os.buf();
+}
+
+void
+BackEndFile::doImportKey(const Name& keyName, const uint8_t* buf, size_t size, const char* pw, size_t pwLen)
+{
+  try {
+    auto key = make_shared<PrivateKey>();
+    key->loadPkcs8(buf, size, pw, pwLen);
+    saveKey(keyName, key);
+  }
+  catch (const PrivateKey::Error&) {
+    BOOST_THROW_EXCEPTION(Error("Cannot import private key"));
+  }
+}
+
+shared_ptr<PrivateKey>
+BackEndFile::loadKey(const Name& keyName) const
+{
+  auto key = make_shared<PrivateKey>();
+  std::fstream is(m_impl->toFileName(keyName).string(), std::ios_base::in);
+  key->loadPkcs1Base64(is);
+  return key;
+}
+
+void
+BackEndFile::saveKey(const Name& keyName, shared_ptr<PrivateKey> key)
+{
+  std::string fileName = m_impl->toFileName(keyName).string();
+  std::fstream os(fileName, std::ios_base::out);
+  key->savePkcs1Base64(os);
+
+  // set file permission
+  chmod(fileName.c_str(), 0000400);
+}
+
+} // namespace tpm
+} // namespace security
+} // namespace ndn
diff --git a/src/security/tpm/back-end-file.hpp b/src/security/tpm/back-end-file.hpp
new file mode 100644
index 0000000..02b575f
--- /dev/null
+++ b/src/security/tpm/back-end-file.hpp
@@ -0,0 +1,137 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 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.
+ */
+
+#ifndef NDN_SECURITY_TPM_BACK_END_FILE_HPP
+#define NDN_SECURITY_TPM_BACK_END_FILE_HPP
+
+#include "back-end.hpp"
+
+namespace ndn {
+namespace security {
+namespace transform {
+class PrivateKey;
+} // namespace transform
+
+namespace tpm {
+
+/**
+ * @brief The back-end implementation of file-based TPM.
+ *
+ * In this TPM, each private key is stored in a separate file with permission 0400, i.e.,
+ * owner read-only.  The key is stored in PKCS #1 format in base64 encoding.
+ */
+class BackEndFile : public BackEnd
+{
+public:
+  class Error : public BackEnd::Error
+  {
+  public:
+    explicit
+    Error(const std::string& what)
+      : BackEnd::Error(what)
+    {
+    }
+  };
+
+public:
+  explicit
+  BackEndFile(const std::string& location = "");
+
+  ~BackEndFile() override;
+
+private: // inherited from tpm::BackEnd
+  /**
+   * @return True if a key with name @p keyName exists in TPM.
+   */
+  bool
+  doHasKey(const Name& keyName) const final;
+
+  /**
+   * @return The handle of a key with name @p keyName, or nullptr if the key does not exist
+   */
+  unique_ptr<KeyHandle>
+  doGetKeyHandle(const Name& keyName) const final;
+
+  /**
+   * @brief Create key for @p identityName according to @p params.
+   *
+   * The created key is named as: /<identityName>/[keyId]/KEY
+   * The key name is set in the returned KeyHandle.
+   *
+   * If the key with the same name exists, the old key will be overwritten.
+   * The behavior of using KeyHandler of removed key is undefined.
+   *
+   * @return The handle of the created key.
+   */
+  unique_ptr<KeyHandle>
+  doCreateKey(const Name& identityName, const KeyParams& params) final;
+
+  /**
+   * @brief Delete a key with name @p keyName.
+   *
+   * @throws Error if the deletion fails.
+   */
+  void
+  doDeleteKey(const Name& keyName) final;
+
+  /**
+   * @return A private key with name @p keyName in encrypted PKCS #8 format using password @p pw
+   * @throws Error if the key cannot be exported, e.g., not enough privilege
+   */
+  ConstBufferPtr
+  doExportKey(const Name& keyName, const char* pw, size_t pwLen) final;
+
+  /**
+   * @brief Import a private key in encrypted PKCS #8 format
+   *
+   * @param keyName The name of imported private key
+   * @param buf Pointer to the key in encrypted PKCS #8 format
+   * @param size The size of the key in encrypted PKCS #8 format
+   * @param pw The password to decrypt the key
+   * @param pwLen The length of the password
+   * @throws Error if import fails.
+   */
+  void
+  doImportKey(const Name& keyName, const uint8_t* buf, size_t size, const char* pw, size_t pwLen) final;
+
+private:
+  /**
+   * @brief Load a private key with name @p keyName from the key file directory
+   */
+  shared_ptr<transform::PrivateKey>
+  loadKey(const Name& keyName) const;
+
+  /**
+   * @brief Save a private key with name @p keyName into the key file directory
+   */
+  void
+  saveKey(const Name& keyName, shared_ptr<transform::PrivateKey> key);
+
+private:
+  class Impl;
+  unique_ptr<Impl> m_impl;
+};
+
+} // namespace tpm
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_SECURITY_TPM_BACK_END_FILE_HPP
diff --git a/src/security/tpm/back-end-mem.cpp b/src/security/tpm/back-end-mem.cpp
new file mode 100644
index 0000000..beac9db
--- /dev/null
+++ b/src/security/tpm/back-end-mem.cpp
@@ -0,0 +1,103 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 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.
+ */
+
+#include "back-end-mem.hpp"
+#include "key-handle-mem.hpp"
+#include "../transform/private-key.hpp"
+#include "../../encoding/buffer-stream.hpp"
+#include <unordered_map>
+
+namespace ndn {
+namespace security {
+namespace tpm {
+
+using transform::PrivateKey;
+
+class BackEndMem::Impl
+{
+public:
+  std::unordered_map<Name, shared_ptr<PrivateKey>> keys;
+};
+
+BackEndMem::BackEndMem()
+  : m_impl(new Impl)
+{
+}
+
+BackEndMem::~BackEndMem() = default;
+
+bool
+BackEndMem::doHasKey(const Name& keyName) const
+{
+  return (m_impl->keys.count(keyName) > 0);
+}
+
+unique_ptr<KeyHandle>
+BackEndMem::doGetKeyHandle(const Name& keyName) const
+{
+  auto it = m_impl->keys.find(keyName);
+  if (it == m_impl->keys.end())
+    return nullptr;
+  return make_unique<KeyHandleMem>(it->second);
+}
+
+unique_ptr<KeyHandle>
+BackEndMem::doCreateKey(const Name& identityName, const KeyParams& params)
+{
+  shared_ptr<PrivateKey> key(transform::generatePrivateKey(params).release());
+  unique_ptr<KeyHandle> keyHandle = make_unique<KeyHandleMem>(key);
+
+  setKeyName(*keyHandle, identityName, params);
+
+  m_impl->keys[keyHandle->getKeyName()] = key;
+  return keyHandle;
+}
+
+void
+BackEndMem::doDeleteKey(const Name& keyName)
+{
+  m_impl->keys.erase(keyName);
+}
+
+ConstBufferPtr
+BackEndMem::doExportKey(const Name& keyName, const char* pw, size_t pwLen)
+{
+  OBufferStream os;
+  m_impl->keys[keyName]->savePkcs8(os, pw, pwLen);
+  return os.buf();
+}
+
+void
+BackEndMem::doImportKey(const Name& keyName, const uint8_t* buf, size_t size, const char* pw, size_t pwLen)
+{
+  try {
+    auto key = make_shared<PrivateKey>();
+    key->loadPkcs8(buf, size, pw, pwLen);
+    m_impl->keys[keyName] = key;
+  }
+  catch (const PrivateKey::Error& e) {
+    BOOST_THROW_EXCEPTION(Error(std::string("Cannot import private key: ") + e.what()));
+  }
+}
+
+} // namespace tpm
+} // namespace security
+} // namespace ndn
diff --git a/src/security/tpm/back-end-mem.hpp b/src/security/tpm/back-end-mem.hpp
new file mode 100644
index 0000000..4253b5e
--- /dev/null
+++ b/src/security/tpm/back-end-mem.hpp
@@ -0,0 +1,117 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 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.
+ */
+
+#ifndef NDN_SECURITY_TPM_BACK_END_MEM_HPP
+#define NDN_SECURITY_TPM_BACK_END_MEM_HPP
+
+#include "back-end.hpp"
+
+namespace ndn {
+namespace security {
+namespace tpm {
+
+/**
+ * @brief The back-end implementation of in-memory TPM.
+ */
+class BackEndMem : public BackEnd
+{
+public:
+  class Error : public BackEnd::Error
+  {
+  public:
+    explicit
+    Error(const std::string& what)
+      : BackEnd::Error(what)
+    {
+    }
+  };
+
+public:
+  explicit
+  BackEndMem();
+
+  ~BackEndMem() override;
+
+private: // inherited from tpm::BackEnd
+
+  /**
+   * @return True if a key with name @p keyName exists in TPM.
+   */
+  bool
+  doHasKey(const Name& keyName) const final;
+
+  /**
+   * @return The handle of a key with name @p keyName, or nullptr if the key does not exist
+   */
+  unique_ptr<KeyHandle>
+  doGetKeyHandle(const Name& keyName) const final;
+
+  /**
+   * @brief Create key for @p identityName according to @p params.
+   *
+   * The created key is named as: /<identityName>/[keyId]/KEY
+   * The key name is set in the returned KeyHandle.
+   * If the key with the same name is created, the old one will be removed.
+   * The behavior of using KeyHandler of removed key is undefined.
+   *
+   * @return The handle of the created key.
+   */
+  unique_ptr<KeyHandle>
+  doCreateKey(const Name& identityName, const KeyParams& params) final;
+
+  /**
+   * @brief Delete a key with name @p keyName.
+   *
+   * @throws Error if the deletion fails.
+   */
+  void
+  doDeleteKey(const Name& keyName) final;
+
+  /**
+   * @return A private key with name @p keyName in encrypted PKCS #8 format using password @p pw
+   * @throws Error if the key cannot be exported, e.g., not enough privilege
+   */
+  ConstBufferPtr
+  doExportKey(const Name& keyName, const char* pw, size_t pwLen) final;
+
+  /**
+   * @brief Import a private key in encrypted PKCS #8 format
+   *
+   * @param keyName The name of imported private key
+   * @param buf Pointer to the key in encrypted PKCS #8 format
+   * @param size The size of the key in encrypted PKCS #8 format
+   * @param pw The password to decrypt the key
+   * @param pwLen The length of password
+   * @throws Error if import fails.
+   */
+  void
+  doImportKey(const Name& keyName, const uint8_t* buf, size_t size, const char* pw, size_t pwLen) final;
+
+private:
+  class Impl;
+  unique_ptr<Impl> m_impl;
+};
+
+} // namespace tpm
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_SECURITY_TPM_BACK_END_MEM_HPP
diff --git a/src/security/tpm/back-end-osx.cpp b/src/security/tpm/back-end-osx.cpp
new file mode 100644
index 0000000..d423b10
--- /dev/null
+++ b/src/security/tpm/back-end-osx.cpp
@@ -0,0 +1,514 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 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.
+ */
+
+#include "back-end-osx.hpp"
+#include "key-handle-osx.hpp"
+#include "helper-osx.hpp"
+#include "../transform/private-key.hpp"
+#include "tpm.hpp"
+
+#include <CoreServices/CoreServices.h>
+#include <Security/Security.h>
+#include <Security/SecRandom.h>
+#include <Security/SecDigestTransform.h>
+
+namespace ndn {
+namespace security {
+namespace tpm {
+
+class BackEndOsx::Impl
+{
+public:
+  Impl()
+    : isTerminalMode(false)
+  {
+  }
+
+  /**
+   * @brief Get private key reference with name @p keyName.
+   *
+   * @param keyName
+   * @returns reference to the key
+   */
+  CFReleaser<SecKeychainItemRef>
+  getKey(const Name& keyName)
+  {
+    CFReleaser<CFStringRef> keyLabel = CFStringCreateWithCString(nullptr, keyName.toUri().c_str(), kCFStringEncodingUTF8);
+
+    CFReleaser<CFMutableDictionaryRef> attrDict =
+      CFDictionaryCreateMutable(nullptr, 5, &kCFTypeDictionaryKeyCallBacks, nullptr);
+
+    CFDictionaryAddValue(attrDict.get(), kSecClass, kSecClassKey);
+    CFDictionaryAddValue(attrDict.get(), kSecAttrLabel, keyLabel.get());
+    CFDictionaryAddValue(attrDict.get(), kSecAttrKeyClass, kSecAttrKeyClassPrivate);
+    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());
+    keyItem.retain();
+
+    if (res != errSecSuccess) {
+      if (res == errSecAuthFailed) {
+        BOOST_THROW_EXCEPTION(Error("Fail to unlock the keychain"));
+      }
+      BOOST_THROW_EXCEPTION(std::domain_error("Key does not exist"));
+    }
+
+    return keyItem;
+  }
+
+public:
+  SecKeychainRef keyChainRef;
+  bool isTerminalMode;
+};
+
+
+static CFTypeRef
+getAsymKeyType(KeyType keyType)
+{
+  switch (keyType) {
+  case KeyType::RSA:
+    return kSecAttrKeyTypeRSA;
+  case KeyType::EC:
+    return kSecAttrKeyTypeECDSA;
+  default:
+    BOOST_THROW_EXCEPTION(Tpm::Error("Unsupported key type"));
+  }
+}
+
+static CFTypeRef
+getDigestAlgorithm(DigestAlgorithm digestAlgo)
+{
+  switch (digestAlgo) {
+  case DigestAlgorithm::SHA256:
+    return kSecDigestSHA2;
+  default:
+    return 0;
+  }
+}
+
+static long
+getDigestSize(DigestAlgorithm digestAlgo)
+{
+  switch (digestAlgo) {
+  case DigestAlgorithm::SHA256:
+    return 256;
+  default:
+    return -1;
+  }
+}
+
+BackEndOsx::BackEndOsx()
+  : m_impl(new Impl)
+{
+  SecKeychainSetUserInteractionAllowed(!m_impl->isTerminalMode);
+
+  OSStatus res = SecKeychainCopyDefault(&m_impl->keyChainRef);
+
+  if (res == errSecNoDefaultKeychain) { //If no default key chain, create one.
+    BOOST_THROW_EXCEPTION(Error("No default keychain, create one first"));
+  }
+}
+
+BackEndOsx::~BackEndOsx() = default;
+
+void
+BackEndOsx::setTerminalMode(bool isTerminal)
+{
+  m_impl->isTerminalMode = isTerminal;
+  SecKeychainSetUserInteractionAllowed(!isTerminal);
+}
+
+bool
+BackEndOsx::isTerminalMode() const
+{
+  return m_impl->isTerminalMode;
+}
+
+bool
+BackEndOsx::isLocked() const
+{
+  SecKeychainStatus keychainStatus;
+
+  OSStatus res = SecKeychainGetStatus(m_impl->keyChainRef, &keychainStatus);
+  if (res != errSecSuccess)
+    return true;
+  else
+    return ((kSecUnlockStateStatus & keychainStatus) == 0);
+}
+
+bool
+BackEndOsx::unlockTpm(const char* password, size_t passwordLength)
+{
+  // If the default key chain is already unlocked, return immediately.
+  if (!isLocked())
+    return true;
+
+  if (m_impl->isTerminalMode) {
+    // Use the supplied password.
+    SecKeychainUnlock(m_impl->keyChainRef, passwordLength, password, true);
+  }
+  else {
+    // If inTerminal is not set, get the password from GUI.
+    SecKeychainUnlock(m_impl->keyChainRef, 0, nullptr, false);
+  }
+
+  return !isLocked();
+}
+
+ConstBufferPtr
+BackEndOsx::sign(const KeyRefOsx& key, DigestAlgorithm digestAlgorithm,
+                 const uint8_t* buf, size_t size) const
+{
+  CFReleaser<CFDataRef> dataRef = CFDataCreateWithBytesNoCopy(nullptr, buf, size, kCFAllocatorNull);
+
+  CFReleaser<CFErrorRef> error;
+  // C-style cast is used as per Apple convention
+  CFReleaser<SecTransformRef> signer = SecSignTransformCreate(key.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, getDigestAlgorithm(digestAlgorithm), &error.get());
+  if (error != nullptr) {
+    BOOST_THROW_EXCEPTION(Error("Fail to configure digest algorithm of signer"));
+  }
+
+  // Set digest attribute
+  long digestSize = getDigestSize(digestAlgorithm);
+  CFReleaser<CFNumberRef> cfDigestSize = CFNumberCreate(nullptr, 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) {
+    CFShow(error.get());
+    BOOST_THROW_EXCEPTION(Error("Fail to sign data"));
+  }
+
+  if (signature == nullptr) {
+    BOOST_THROW_EXCEPTION(Error("Signature is NULL!\n"));
+  }
+
+  return make_shared<Buffer>(CFDataGetBytePtr(signature.get()), CFDataGetLength(signature.get()));
+}
+
+ConstBufferPtr
+BackEndOsx::decrypt(const KeyRefOsx& key, const uint8_t* cipherText, size_t cipherSize) const
+{
+  CFReleaser<CFDataRef> dataRef = CFDataCreateWithBytesNoCopy(nullptr, cipherText, cipherSize, kCFAllocatorNull);
+
+  CFReleaser<CFErrorRef> error;
+  CFReleaser<SecTransformRef> decryptor = SecDecryptTransformCreate(key.get(), &error.get());
+  if (error != nullptr) {
+    BOOST_THROW_EXCEPTION(Error("Fail to create decrypt"));
+  }
+
+  SecTransformSetAttribute(decryptor.get(), kSecTransformInputAttributeName, dataRef.get(), &error.get());
+  if (error != nullptr) {
+    BOOST_THROW_EXCEPTION(Error("Fail to configure decrypt"));
+  }
+
+  SecTransformSetAttribute(decryptor.get(), kSecPaddingKey, kSecPaddingOAEPKey, &error.get());
+  if (error != nullptr) {
+    BOOST_THROW_EXCEPTION(Error("Fail to configure decrypt #2"));
+  }
+
+  CFReleaser<CFDataRef> output = (CFDataRef)SecTransformExecute(decryptor.get(), &error.get());
+  if (error != nullptr) {
+    // CFShow(error);
+    BOOST_THROW_EXCEPTION(Error("Fail to decrypt data"));
+  }
+
+  if (output == nullptr) {
+    BOOST_THROW_EXCEPTION(Error("Output is NULL!\n"));
+  }
+  return make_shared<Buffer>(CFDataGetBytePtr(output.get()), CFDataGetLength(output.get()));
+}
+
+ConstBufferPtr
+BackEndOsx::derivePublicKey(const KeyRefOsx& key) const
+{
+  CFReleaser<CFDataRef> exportedKey;
+  OSStatus res = SecItemExport(key.get(),           // secItemOrArray
+                               kSecFormatOpenSSL,   // outputFormat
+                               0,                   // flags
+                               nullptr,             // keyParams
+                               &exportedKey.get()); // exportedData
+
+  if (res != errSecSuccess) {
+    if (res == errSecAuthFailed) {
+      BOOST_THROW_EXCEPTION(Error("Fail to unlock the keychain"));
+    }
+    else {
+      BOOST_THROW_EXCEPTION(Error("Fail to export private key"));
+    }
+  }
+
+  transform::PrivateKey privateKey;
+  privateKey.loadPkcs1(CFDataGetBytePtr(exportedKey.get()), CFDataGetLength(exportedKey.get()));
+  return privateKey.derivePublicKey();
+}
+
+bool
+BackEndOsx::doHasKey(const Name& keyName) const
+{
+  CFReleaser<CFStringRef> keyLabel = CFStringCreateWithCString(nullptr, keyName.toUri().c_str(), kCFStringEncodingUTF8);
+
+  CFReleaser<CFMutableDictionaryRef> attrDict =
+    CFDictionaryCreateMutable(nullptr, 4, &kCFTypeDictionaryKeyCallBacks, nullptr);
+
+  CFDictionaryAddValue(attrDict.get(), kSecClass, kSecClassKey);
+  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());
+  itemRef.retain();
+
+  return (res == errSecSuccess);
+}
+
+unique_ptr<KeyHandle>
+BackEndOsx::doGetKeyHandle(const Name& keyName) const
+{
+  CFReleaser<SecKeychainItemRef> keyItem;
+  try {
+    keyItem = m_impl->getKey(keyName);
+  }
+  catch (const std::domain_error&) {
+    return nullptr;
+  }
+
+  return make_unique<KeyHandleOsx>(*this, (SecKeyRef)keyItem.get());
+}
+
+unique_ptr<KeyHandle>
+BackEndOsx::doCreateKey(const Name& identityName, const KeyParams& params)
+{
+  KeyType keyType = params.getKeyType();
+  uint32_t keySize;
+  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(Tpm::Error("Fail to create a key pair: Unsupported key type"));
+    }
+  }
+  CFReleaser<CFNumberRef> cfKeySize = CFNumberCreate(nullptr, kCFNumberIntType, &keySize);
+
+  CFReleaser<CFMutableDictionaryRef> attrDict =
+    CFDictionaryCreateMutable(nullptr, 2, &kCFTypeDictionaryKeyCallBacks, nullptr);
+  CFDictionaryAddValue(attrDict.get(), kSecAttrKeyType, getAsymKeyType(keyType));
+  CFDictionaryAddValue(attrDict.get(), kSecAttrKeySizeInBits, cfKeySize.get());
+
+  KeyRefOsx publicKey, privateKey;
+  // C-style cast is used as per Apple convention
+  OSStatus res = SecKeyGeneratePair((CFDictionaryRef)attrDict.get(), &publicKey.get(), &privateKey.get());
+
+  BOOST_ASSERT(privateKey != nullptr);
+
+  publicKey.retain();
+  privateKey.retain();
+
+  BOOST_ASSERT(privateKey != nullptr);
+
+  if (res != errSecSuccess) {
+    if (res == errSecAuthFailed) {
+      BOOST_THROW_EXCEPTION(Error("Fail to unlock the keychain"));
+    }
+    else {
+      BOOST_THROW_EXCEPTION(Error("Fail to create a key pair"));
+    }
+  }
+
+  unique_ptr<KeyHandle> keyHandle = make_unique<KeyHandleOsx>(*this, privateKey.get());
+  setKeyName(*keyHandle, identityName, params);
+
+  SecKeychainAttribute attrs[1]; // maximum number of attributes
+  SecKeychainAttributeList attrList = { 0, attrs };
+  std::string keyUri = keyHandle->getKeyName().toUri();
+  {
+    attrs[attrList.count].tag = kSecKeyPrintName;
+    attrs[attrList.count].length = keyUri.size();
+    attrs[attrList.count].data = const_cast<char*>(keyUri.data());
+    attrList.count++;
+  }
+
+  SecKeychainItemModifyAttributesAndData((SecKeychainItemRef)privateKey.get(), &attrList, 0, nullptr);
+  SecKeychainItemModifyAttributesAndData((SecKeychainItemRef)publicKey.get(), &attrList, 0, nullptr);
+
+  return keyHandle;
+}
+
+void
+BackEndOsx::doDeleteKey(const Name& keyName)
+{
+  CFReleaser<CFStringRef> keyLabel = CFStringCreateWithCString(nullptr, keyName.toUri().c_str(), kCFStringEncodingUTF8);
+
+  CFReleaser<CFMutableDictionaryRef> searchDict =
+    CFDictionaryCreateMutable(nullptr, 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) {
+    if (res == errSecAuthFailed) {
+      BOOST_THROW_EXCEPTION(Error("Fail to unlock the keychain"));
+    }
+    else if (res != errSecItemNotFound) {
+      BOOST_THROW_EXCEPTION(Error("Fail to delete a key pair"));
+    }
+  }
+}
+
+ConstBufferPtr
+BackEndOsx::doExportKey(const Name& keyName, const char* pw, size_t pwLen)
+{
+  CFReleaser<SecKeychainItemRef> privateKey;
+
+  try {
+    privateKey = m_impl->getKey(keyName);
+  }
+  catch (const std::domain_error&) {
+    BOOST_THROW_EXCEPTION(Tpm::Error("Private key does not exist in OSX Keychain"));
+  }
+
+  CFReleaser<CFDataRef> exportedKey;
+  SecItemImportExportKeyParameters keyParams;
+  memset(&keyParams, 0, sizeof(keyParams));
+  CFReleaser<CFStringRef> passphrase =
+    CFStringCreateWithBytes(0, reinterpret_cast<const uint8_t*>(pw), pwLen, kCFStringEncodingUTF8, false);
+  keyParams.passphrase = passphrase.get();
+  OSStatus res = SecItemExport(privateKey.get(),       // secItemOrArray
+                               kSecFormatWrappedPKCS8, // outputFormat
+                               0,                      // flags
+                               &keyParams,             // keyParams
+                               &exportedKey.get());    // exportedData
+
+  if (res != errSecSuccess) {
+    if (res == errSecAuthFailed) {
+      BOOST_THROW_EXCEPTION(Error("Fail to unlock the keychain"));
+    }
+    else {
+      BOOST_THROW_EXCEPTION(Error("Fail to export private key"));
+    }
+  }
+
+  return make_shared<Buffer>(CFDataGetBytePtr(exportedKey.get()), CFDataGetLength(exportedKey.get()));
+}
+
+void
+BackEndOsx::doImportKey(const Name& keyName, const uint8_t* buf, size_t size,
+                        const char* pw, size_t pwLen)
+{
+  CFReleaser<CFDataRef> importedKey = CFDataCreateWithBytesNoCopy(nullptr, buf, size, kCFAllocatorNull);
+
+  SecExternalFormat externalFormat = kSecFormatWrappedPKCS8;
+  SecExternalItemType externalType = kSecItemTypePrivateKey;
+
+  CFReleaser<CFStringRef> keyLabel = CFStringCreateWithCString(nullptr, keyName.toUri().c_str(), kCFStringEncodingUTF8);
+  CFReleaser<CFStringRef> passphrase =
+    CFStringCreateWithBytes(nullptr, reinterpret_cast<const uint8_t*>(pw), pwLen, kCFStringEncodingUTF8, false);
+  CFReleaser<SecAccessRef> access;
+  SecAccessCreate(keyLabel.get(), nullptr, &access.get());
+
+  CFArrayRef attributes = nullptr;
+
+  const SecItemImportExportKeyParameters keyParams{
+    SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION, // version
+    0, // flags
+    passphrase.get(), // passphrase
+    nullptr, // alert title
+    nullptr, // alert prompt
+    access.get(), // access ref
+    nullptr, // key usage
+    attributes // key attributes
+  };
+
+  CFReleaser<CFArrayRef> outItems;
+  OSStatus res = SecItemImport(importedKey.get(),   // importedData
+                               nullptr,             // fileNameOrExtension
+                               &externalFormat,     // inputFormat
+                               &externalType,       // itemType
+                               0,                   // flags
+                               &keyParams,          // keyParams
+                               m_impl->keyChainRef, // importKeychain
+                               &outItems.get());    // outItems
+
+  if (res != errSecSuccess) {
+    if (res == errSecAuthFailed) {
+      BOOST_THROW_EXCEPTION(Error("Fail to unlock the keychain"));
+    }
+    else {
+      BOOST_THROW_EXCEPTION(Error("Cannot import the private key"));
+    }
+  }
+
+  // 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 };
+  std::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);
+}
+
+} // namespace tpm
+} // namespace security
+} // namespace ndn
diff --git a/src/security/tpm/back-end-osx.hpp b/src/security/tpm/back-end-osx.hpp
new file mode 100644
index 0000000..0fcd49f
--- /dev/null
+++ b/src/security/tpm/back-end-osx.hpp
@@ -0,0 +1,162 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 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.
+ */
+
+#ifndef NDN_SECURITY_TPM_BACK_END_OSX_HPP
+#define NDN_SECURITY_TPM_BACK_END_OSX_HPP
+
+#include "back-end.hpp"
+#include "helper-osx.hpp"
+
+#ifndef NDN_CXX_HAVE_OSX_SECURITY
+#error "This file should not be compiled ..."
+#endif
+
+namespace ndn {
+namespace security {
+namespace tpm {
+
+/**
+ * @brief The back-end implementation of TPM based on OS X KeyChain service.
+ */
+class BackEndOsx : public BackEnd
+{
+public:
+  class Error : public BackEnd::Error
+  {
+  public:
+    explicit
+    Error(const std::string& what)
+      : BackEnd::Error(what)
+    {
+    }
+  };
+
+public:
+  BackEndOsx();
+
+  ~BackEndOsx() override;
+
+public: // management
+  /**
+   * @brief Set the terminal mode of TPM.
+   *
+   * In terminal mode, TPM will not ask user permission from GUI.
+   */
+  void
+  setTerminalMode(bool isTerminal);
+
+  /**
+   * @brief Check if TPM is in terminal mode
+   */
+  bool
+  isTerminalMode() const;
+
+  /**
+   * @return True if TPM is locked, otherwise false
+   */
+  bool
+  isLocked() const;
+
+  /**
+   * @brief Unlock TPM
+   *
+   * @param password       The password to unlock TPM
+   * @param passwordLength The password size.
+   */
+  bool
+  unlockTpm(const char* password = nullptr, size_t passwordLength = 0);
+
+public: // crypto transformation
+  /**
+   * @brief Sign @p buf with @p key using @p digestAlgorithm.
+   */
+  ConstBufferPtr
+  sign(const KeyRefOsx& key, DigestAlgorithm digestAlgorithm, const uint8_t* buf, size_t size) const;
+
+  ConstBufferPtr
+  decrypt(const KeyRefOsx& key, const uint8_t* cipherText, size_t cipherSize) const;
+
+  ConstBufferPtr
+  derivePublicKey(const KeyRefOsx& key) const;
+
+private: // inherited from tpm::BackEnd
+
+  /**
+   * @return True if a key with name @p keyName exists in TPM.
+   */
+  bool
+  doHasKey(const Name& keyName) const final;
+
+  /**
+   * @return The handle of a key with name @p keyName, or nullptr if the key does not exist
+   */
+  unique_ptr<KeyHandle>
+  doGetKeyHandle(const Name& keyName) const final;
+
+  /**
+   * @brief Create key for @p identityName according to @p params.
+   *
+   * The created key is named as: /<identityName>/[keyId]/KEY
+   * The key name is set in the returned KeyHandle.
+   *
+   * @return The handle of the created key.
+   */
+  unique_ptr<KeyHandle>
+  doCreateKey(const Name& identityName, const KeyParams& params) final;
+
+  /**
+   * @brief Delete a key with name @p keyName.
+   *
+   * @throws Error if the deletion fails.
+   */
+  void
+  doDeleteKey(const Name& keyName) final;
+
+  /**
+   * @return A private key with name @p keyName in encrypted PKCS #8 format using password @p pw
+   * @throws Error if the key cannot be exported, e.g., not enough privilege
+   */
+  ConstBufferPtr
+  doExportKey(const Name& keyName, const char* pw, size_t pwLen) final;
+
+  /**
+   * @brief Import a private key in encrypted PKCS #8 format
+   *
+   * @param keyName The name of imported private key
+   * @param buf Pointer to the key in encrypted PKCS #8 format
+   * @param size The size of the key in encrypted PKCS #8 format
+   * @param pw The password to decrypt the private key
+   * @param pwLen The length of the password
+   * @throws Error if import fails
+   */
+  void
+  doImportKey(const Name& keyName, const uint8_t* buf, size_t size, const char* pw, size_t pwLen) final;
+
+private:
+  class Impl;
+  unique_ptr<Impl> m_impl;
+};
+
+} // namespace tpm
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_SECURITY_TPM_BACK_END_OSX_HPP
diff --git a/src/security/tpm/back-end.cpp b/src/security/tpm/back-end.cpp
new file mode 100644
index 0000000..18df659
--- /dev/null
+++ b/src/security/tpm/back-end.cpp
@@ -0,0 +1,138 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 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.
+ */
+
+#include "back-end.hpp"
+#include "key-handle.hpp"
+#include "tpm.hpp"
+#include "../transform.hpp"
+#include "../../encoding/buffer-stream.hpp"
+#include "../../util/random.hpp"
+#include "../pib/key.hpp"
+
+namespace ndn {
+namespace security {
+namespace tpm {
+
+BackEnd::~BackEnd() = default;
+
+bool
+BackEnd::hasKey(const Name& keyName) const
+{
+  return doHasKey(keyName);
+}
+
+unique_ptr<KeyHandle>
+BackEnd::getKeyHandle(const Name& keyName) const
+{
+  return doGetKeyHandle(keyName);
+}
+
+unique_ptr<KeyHandle>
+BackEnd::createKey(const Name& identity, const KeyParams& params)
+{
+  // key name checking
+  switch (params.getKeyIdType()) {
+    case KeyIdType::USER_SPECIFIED: { // keyId is pre-set.
+      Name keyName = v2::constructKeyName(identity, params.getKeyId());
+      if (hasKey(keyName)) {
+        BOOST_THROW_EXCEPTION(Tpm::Error("Key `" + keyName.toUri() + "` already exists"));
+      }
+      break;
+    }
+    case KeyIdType::SHA256: {
+      // KeyName will be assigned in setKeyName after key is generated
+      break;
+    }
+    case KeyIdType::RANDOM: {
+      Name keyName;
+      name::Component keyId;
+      do {
+        keyId = name::Component::fromNumber(random::generateSecureWord64());
+        keyName = v2::constructKeyName(identity, params.getKeyId());
+      } while (hasKey(keyName));
+
+      const_cast<KeyParams&>(params).setKeyId(keyId);
+      break;
+    }
+    default: {
+      BOOST_THROW_EXCEPTION(Error("Unsupported key id type"));
+    }
+  }
+
+  return doCreateKey(identity, params);
+}
+
+void
+BackEnd::deleteKey(const Name& keyName)
+{
+  doDeleteKey(keyName);
+}
+
+ConstBufferPtr
+BackEnd::exportKey(const Name& keyName, const char* pw, size_t pwLen)
+{
+  if (!hasKey(keyName)) {
+    BOOST_THROW_EXCEPTION(Error("Key `" + keyName.toUri() + "` does not exist"));
+  }
+  return doExportKey(keyName, pw, pwLen);
+}
+
+void
+BackEnd::importKey(const Name& keyName, const uint8_t* pkcs8, size_t pkcs8Len, const char* pw, size_t pwLen)
+{
+  if (hasKey(keyName)) {
+    BOOST_THROW_EXCEPTION(Error("Key `" + keyName.toUri() + "` already exists"));
+  }
+  doImportKey(keyName, pkcs8, pkcs8Len, pw, pwLen);
+}
+
+void
+BackEnd::setKeyName(KeyHandle& keyHandle, const Name& identity, const KeyParams& params)
+{
+  name::Component keyId;
+  switch (params.getKeyIdType()) {
+    case KeyIdType::USER_SPECIFIED:
+      keyId = params.getKeyId();
+      break;
+    case KeyIdType::SHA256: {
+      using namespace transform;
+
+      OBufferStream os;
+      bufferSource(*keyHandle.derivePublicKey()) >> digestFilter() >> streamSink(os);
+      keyId = name::Component(os.buf());
+      break;
+    }
+    case KeyIdType::RANDOM: {
+      BOOST_ASSERT(!params.getKeyId().empty());
+      keyId = params.getKeyId();
+      break;
+    }
+    default: {
+      BOOST_ASSERT(false);
+    }
+  }
+
+  keyHandle.setKeyName(v2::constructKeyName(identity, keyId));
+}
+
+} // namespace tpm
+} // namespace security
+} // namespace ndn
diff --git a/src/security/tpm/back-end.hpp b/src/security/tpm/back-end.hpp
new file mode 100644
index 0000000..749b53d
--- /dev/null
+++ b/src/security/tpm/back-end.hpp
@@ -0,0 +1,182 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 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.
+ */
+
+#ifndef NDN_SECURITY_TPM_BACK_END_HPP
+#define NDN_SECURITY_TPM_BACK_END_HPP
+
+#include "../../common.hpp"
+#include "../../name.hpp"
+#include "../../encoding/buffer.hpp"
+#include "../key-params.hpp"
+
+namespace ndn {
+namespace security {
+namespace tpm {
+
+class KeyHandle;
+
+/**
+ * @brief Abstraction of Tpm back-end.
+ *
+ * This class provides KeyHandle to the front-end and other TPM management operations.
+ */
+class BackEnd : noncopyable
+{
+public:
+  class Error : public std::runtime_error
+  {
+  public:
+    explicit
+    Error(const std::string& what)
+      : std::runtime_error(what)
+    {
+    }
+  };
+
+public:
+  virtual
+  ~BackEnd();
+
+public: // key management
+  /**
+   * @return True if a key with name @p keyName exists in TPM.
+   */
+  bool
+  hasKey(const Name& keyName) const;
+
+  /**
+   * @return The handle of a key with name @p keyName, or nullptr if the key does not exist.
+   *
+   * Calling getKeyHandle multiple times with the same keyName will return different KeyHandle
+   * objects that all refer to the same key.
+   */
+  unique_ptr<KeyHandle>
+  getKeyHandle(const Name& keyName) const;
+
+  /**
+   * @brief Create key for @p identity according to @p params.
+   *
+   * The key name is set in the returned KeyHandle.
+   *
+   * @return The handle of the created key.
+   * @throws Tpm::Error if @p params is invalid
+   * @throws Error if the key cannot be created.
+   */
+  unique_ptr<KeyHandle>
+  createKey(const Name& identity, const KeyParams& params);
+
+  /**
+   * @brief Delete a key with name @p keyName.
+   *
+   * Continuing to use existing KeyHandles on a deleted key results in undefined behavior.
+   *
+   * @throws Error if the deletion fails.
+   */
+  void
+  deleteKey(const Name& keyName);
+
+  /**
+   * @return A private key with name @p keyName in encrypted PKCS #8 format using password @p pw
+   * @throws Error if the key does not exist
+   * @throws Error if the key cannot be exported, e.g., insufficient privilege
+   */
+  ConstBufferPtr
+  exportKey(const Name& keyName, const char* pw, size_t pwLen);
+
+  /**
+   * @brief Import a private key in encrypted PKCS #8 format
+   *
+   * @param keyName The name of imported private key
+   * @param pkcs8 Pointer to the key in encrypted PKCS #8 format
+   * @param pkcs8Len The size of the key in encrypted PKCS #8 format
+   * @param pw The password to decrypt the private key
+   * @param pwLen The length of the password
+   * @throws Error if import fails.
+   */
+  void
+  importKey(const Name& keyName, const uint8_t* pkcs8, size_t pkcs8Len, const char* pw, size_t pwLen);
+
+protected: // static helper method
+  /**
+   * @brief Set the key name in @p keyHandle according to @p identity and @p params
+   */
+  static void
+  setKeyName(KeyHandle& keyHandle, const Name& identity, const KeyParams& params);
+
+private: // pure virtual methods
+  /**
+   * @return True if a key with name @p keyName exists in TPM.
+   */
+  virtual bool
+  doHasKey(const Name& keyName) const = 0;
+
+  /**
+   * @return The handle of a key with name @p keyName, or nullptr if the key does not exist
+   */
+  virtual unique_ptr<KeyHandle>
+  doGetKeyHandle(const Name& keyName) const = 0;
+
+  /**
+   * @brief Create key for @p identityName according to @p params.
+   *
+   * The created key is named as: /<identityName>/[keyId]/KEY
+   * The key name is set in the returned KeyHandle.
+   *
+   * @return The handle of the created key.
+   * @throws Error when key cannot be created.
+   */
+  virtual unique_ptr<KeyHandle>
+  doCreateKey(const Name& identity, const KeyParams& params) = 0;
+
+  /**
+   * @brief Delete a key with name @p keyName.
+   *
+   * @throws Error if the deletion fails.
+   */
+  virtual void
+  doDeleteKey(const Name& keyName) = 0;
+
+  /**
+   * @return A private key with name @p keyName in encrypted PKCS #8 format using password @p pw
+   * @throws Error if the key cannot be exported, e.g., insufficient privilege
+   */
+  virtual ConstBufferPtr
+  doExportKey(const Name& keyName, const char* pw, size_t pwLen) = 0;
+
+  /**
+   * @brief Import a private key in encrypted PKCS #8 format using @p password
+   *
+   * @param keyName The name of imported private key
+   * @param pkcs8 Pointer to the key in PKCS #8 format
+   * @param pkcs8Len The size of the key in PKCS #8 format
+   * @param pw The password to decrypt the private key
+   * @param pwLen The length of the password
+   * @throws Error if import fails.
+   */
+  virtual void
+  doImportKey(const Name& keyName, const uint8_t* pkcs8, size_t pkcs8Len, const char* pw, size_t pwLen) = 0;
+};
+
+} // namespace tpm
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_SECURITY_TPM_BACK_END_HPP
diff --git a/src/security/tpm/helper-osx.hpp b/src/security/tpm/helper-osx.hpp
new file mode 100644
index 0000000..2e7d827
--- /dev/null
+++ b/src/security/tpm/helper-osx.hpp
@@ -0,0 +1,154 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 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.
+ */
+
+#ifndef NDN_SECURITY_TPM_HELPER_OSX_HPP
+#define NDN_SECURITY_TPM_HELPER_OSX_HPP
+
+#include "../../common.hpp"
+
+#ifndef NDN_CXX_HAVE_OSX_SECURITY
+#error "This file should not be included ..."
+#endif
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <Security/Security.h>
+
+namespace ndn {
+namespace security {
+namespace tpm {
+
+/**
+ * @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();
+  }
+
+public: // Access
+  const T&
+  get() const
+  {
+    return m_typeRef;
+  }
+
+  T&
+  get()
+  {
+    return m_typeRef;
+  }
+
+  bool
+  operator==(const std::nullptr_t&)
+  {
+    return m_typeRef == nullptr;
+  }
+
+  bool
+  operator!=(const std::nullptr_t&)
+  {
+    return m_typeRef != nullptr;
+  }
+
+  ///////////////////
+  // Miscellaneous //
+
+  void
+  retain(const T& typeRef)
+  {
+    if (typeRef != nullptr) {
+      CFRetain(typeRef);
+    }
+    release();
+    m_typeRef = typeRef;
+  }
+
+  void
+  retain()
+  {
+    T typeRef = m_typeRef;
+    m_typeRef = nullptr;
+    retain(typeRef);
+  }
+
+  void
+  release()
+  {
+    if (m_typeRef != nullptr) {
+      CFRelease(m_typeRef);
+      m_typeRef = nullptr;
+    }
+  };
+
+private:
+  T m_typeRef;
+};
+
+typedef CFReleaser<SecKeyRef> KeyRefOsx;
+
+} // namespace tpm
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_SECURITY_TPM_HELPER_OSX_HPP
diff --git a/src/security/tpm/key-handle-mem.cpp b/src/security/tpm/key-handle-mem.cpp
new file mode 100644
index 0000000..00f5b21
--- /dev/null
+++ b/src/security/tpm/key-handle-mem.cpp
@@ -0,0 +1,69 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 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.
+ */
+
+#include "key-handle-mem.hpp"
+#include "../../encoding/buffer-stream.hpp"
+#include "../transform.hpp"
+#include "../transform/private-key.hpp"
+
+namespace ndn {
+namespace security {
+namespace tpm {
+
+using transform::PrivateKey;
+
+KeyHandleMem::KeyHandleMem(shared_ptr<PrivateKey> key)
+  : m_key(key)
+{
+  BOOST_ASSERT(key != nullptr);
+}
+
+ConstBufferPtr
+KeyHandleMem::doSign(DigestAlgorithm digestAlgorithm, const uint8_t* buf, size_t size) const
+{
+  switch (digestAlgorithm) {
+    case DigestAlgorithm::SHA256: {
+      using namespace transform;
+
+      OBufferStream sigOs;
+      bufferSource(buf, size) >> signerFilter(digestAlgorithm, *m_key) >> streamSink(sigOs);
+      return sigOs.buf();
+    }
+    default:
+      return nullptr;
+  }
+}
+
+ConstBufferPtr
+KeyHandleMem::doDecrypt(const uint8_t* cipherText, size_t cipherTextLen) const
+{
+  return m_key->decrypt(cipherText, cipherTextLen);
+}
+
+ConstBufferPtr
+KeyHandleMem::doDerivePublicKey() const
+{
+  return m_key->derivePublicKey();
+}
+
+} // namespace tpm
+} // namespace security
+} // namespace ndn
diff --git a/src/security/tpm/key-handle-mem.hpp b/src/security/tpm/key-handle-mem.hpp
new file mode 100644
index 0000000..006c4ec
--- /dev/null
+++ b/src/security/tpm/key-handle-mem.hpp
@@ -0,0 +1,63 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 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.
+ */
+
+#ifndef NDN_SECURITY_TPM_KEY_HANDLE_MEM_HPP
+#define NDN_SECURITY_TPM_KEY_HANDLE_MEM_HPP
+
+#include "key-handle.hpp"
+
+namespace ndn {
+namespace security {
+
+namespace transform {
+class PrivateKey;
+} // namespace transform
+
+namespace tpm {
+
+/**
+ * @brief A TPM key handle that keeps the private key in memory
+ */
+class KeyHandleMem : public KeyHandle
+{
+public:
+  explicit
+  KeyHandleMem(shared_ptr<transform::PrivateKey> key);
+
+private:
+  ConstBufferPtr
+  doSign(DigestAlgorithm digestAlgorithm, const uint8_t* buf, size_t size) const final;
+
+  ConstBufferPtr
+  doDecrypt(const uint8_t* cipherText, size_t cipherTextLen) const final;
+
+  ConstBufferPtr
+  doDerivePublicKey() const final;
+
+private:
+  shared_ptr<transform::PrivateKey> m_key;
+};
+
+} // namespace tpm
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_SECURITY_TPM_KEY_HANDLE_MEM_HPP
diff --git a/src/security/tpm/key-handle-osx.cpp b/src/security/tpm/key-handle-osx.cpp
new file mode 100644
index 0000000..518a673
--- /dev/null
+++ b/src/security/tpm/key-handle-osx.cpp
@@ -0,0 +1,57 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 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.
+ */
+
+#include "key-handle-osx.hpp"
+#include "back-end-osx.hpp"
+
+namespace ndn {
+namespace security {
+namespace tpm {
+
+KeyHandleOsx::KeyHandleOsx(const BackEndOsx& impl, const KeyRefOsx& key)
+  : m_impl(impl)
+  , m_key(key)
+{
+  if (m_key.get() == 0)
+    BOOST_THROW_EXCEPTION(Error("key is not set"));
+}
+
+ConstBufferPtr
+KeyHandleOsx::doSign(DigestAlgorithm digestAlgorithm, const uint8_t* buf, size_t size) const
+{
+  return m_impl.sign(m_key, digestAlgorithm, buf, size);
+}
+
+ConstBufferPtr
+KeyHandleOsx::doDecrypt(const uint8_t* cipherText, size_t cipherTextLen) const
+{
+  return m_impl.decrypt(m_key, cipherText, cipherTextLen);
+}
+
+ConstBufferPtr
+KeyHandleOsx::doDerivePublicKey() const
+{
+  return m_impl.derivePublicKey(m_key);
+}
+
+} // namespace tpm
+} // namespace security
+} // namespace ndn
diff --git a/src/security/tpm/key-handle-osx.hpp b/src/security/tpm/key-handle-osx.hpp
new file mode 100644
index 0000000..4337f0d
--- /dev/null
+++ b/src/security/tpm/key-handle-osx.hpp
@@ -0,0 +1,76 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 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.
+ */
+
+#ifndef NDN_SECURITY_TPM_KEY_HANDLE_OSX_HPP
+#define NDN_SECURITY_TPM_KEY_HANDLE_OSX_HPP
+
+#include "key-handle.hpp"
+#include "helper-osx.hpp"
+
+#ifndef NDN_CXX_HAVE_OSX_SECURITY
+#error "This file should not be compiled ..."
+#endif
+
+namespace ndn {
+namespace security {
+namespace tpm {
+
+class BackEndOsx;
+
+/**
+ * @brief Abstraction of TPM key handle used by the TPM based on OS X Keychain Service.
+ */
+class KeyHandleOsx : public KeyHandle
+{
+public:
+  class Error : public KeyHandle::Error
+  {
+  public:
+    explicit
+    Error(const std::string& what)
+      : KeyHandle::Error(what)
+    {
+    }
+  };
+
+public:
+  KeyHandleOsx(const BackEndOsx& impl, const KeyRefOsx& key);
+
+private:
+  ConstBufferPtr
+  doSign(DigestAlgorithm digestAlgorithm, const uint8_t* buf, size_t size) const final;
+
+  ConstBufferPtr
+  doDecrypt(const uint8_t* cipherText, size_t cipherTextLen) const final;
+
+  ConstBufferPtr
+  doDerivePublicKey() const final;
+
+private:
+  const BackEndOsx& m_impl;
+  KeyRefOsx m_key;
+};
+
+} // namespace tpm
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_SECURITY_TPM_KEY_HANDLE_OSX_HPP
diff --git a/src/security/tpm/key-handle.cpp b/src/security/tpm/key-handle.cpp
new file mode 100644
index 0000000..70553b4
--- /dev/null
+++ b/src/security/tpm/key-handle.cpp
@@ -0,0 +1,62 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 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.
+ */
+
+#include "key-handle.hpp"
+
+namespace ndn {
+namespace security {
+namespace tpm {
+
+KeyHandle::~KeyHandle() = default;
+
+ConstBufferPtr
+KeyHandle::sign(DigestAlgorithm digestAlgorithm, const uint8_t* buf, size_t size) const
+{
+  return doSign(digestAlgorithm, buf, size);
+}
+
+ConstBufferPtr
+KeyHandle::decrypt(const uint8_t* cipherText, size_t cipherTextLen) const
+{
+  return doDecrypt(cipherText, cipherTextLen);
+}
+
+ConstBufferPtr
+KeyHandle::derivePublicKey() const
+{
+  return doDerivePublicKey();
+}
+
+void
+KeyHandle::setKeyName(const Name& keyName)
+{
+  m_keyName = keyName;
+}
+
+Name
+KeyHandle::getKeyName() const
+{
+  return m_keyName;
+}
+
+} // namespace tpm
+} // namespace security
+} // namespace ndn
diff --git a/src/security/tpm/key-handle.hpp b/src/security/tpm/key-handle.hpp
new file mode 100644
index 0000000..d6faf4d
--- /dev/null
+++ b/src/security/tpm/key-handle.hpp
@@ -0,0 +1,97 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 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.
+ */
+
+#ifndef NDN_SECURITY_TPM_KEY_HANDLE_HPP
+#define NDN_SECURITY_TPM_KEY_HANDLE_HPP
+
+#include "../../common.hpp"
+#include "../../name.hpp"
+#include "../security-common.hpp"
+
+namespace ndn {
+namespace security {
+namespace tpm {
+
+/**
+ * @brief Abstraction of TPM key handle.
+ *
+ * Handle provides an interface to perform crypto operations with a key in TPM.
+ */
+class KeyHandle : noncopyable
+{
+public:
+  class Error : public std::runtime_error
+  {
+  public:
+    explicit
+    Error(const std::string& what)
+      : std::runtime_error(what)
+    {
+    }
+  };
+
+public:
+  virtual
+  ~KeyHandle();
+
+  /**
+   * @return a digital signature created on @p buf using this key with @p digestAlgorithm.
+   */
+  ConstBufferPtr
+  sign(DigestAlgorithm digestAlgorithm, const uint8_t* buf, size_t size) const;
+
+  /**
+   * @return plain text content decrypted from @p cipherText using this key.
+   */
+  ConstBufferPtr
+  decrypt(const uint8_t* cipherText, size_t cipherTextLen) const;
+
+  /**
+   * @return the PCKS#8 encoded public key bits derived from this key.
+   */
+  ConstBufferPtr
+  derivePublicKey() const;
+
+  void
+  setKeyName(const Name& keyName);
+
+  Name
+  getKeyName() const;
+
+private:
+  virtual ConstBufferPtr
+  doSign(DigestAlgorithm digestAlgorithm, const uint8_t* buf, size_t size) const = 0;
+
+  virtual ConstBufferPtr
+  doDecrypt(const uint8_t* cipherText, size_t cipherTextLen) const = 0;
+
+  virtual ConstBufferPtr
+  doDerivePublicKey() const = 0;
+
+private:
+  Name m_keyName;
+};
+
+} // namespace tpm
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_SECURITY_TPM_KEY_HANDLE_HPP
diff --git a/src/security/tpm/tpm.cpp b/src/security/tpm/tpm.cpp
new file mode 100644
index 0000000..234c48d
--- /dev/null
+++ b/src/security/tpm/tpm.cpp
@@ -0,0 +1,150 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 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.
+ */
+
+#include "tpm.hpp"
+#include "back-end.hpp"
+#include "../../encoding/buffer-stream.hpp"
+
+namespace ndn {
+namespace security {
+namespace tpm {
+
+Tpm::Tpm(const std::string& scheme, const std::string& location, unique_ptr<BackEnd> backEnd)
+  : m_scheme(scheme)
+  , m_location(location)
+  , m_backEnd(std::move(backEnd))
+{
+}
+
+Tpm::~Tpm() = default;
+
+std::string
+Tpm::getTpmLocator() const
+{
+  return m_scheme + ":" + m_location;
+}
+
+bool
+Tpm::hasKey(const Name& keyName) const
+{
+  return m_backEnd->hasKey(keyName);
+}
+
+Name
+Tpm::createKey(const Name& identityName, const KeyParams& params)
+{
+  switch (params.getKeyType()) {
+    case KeyType::RSA:
+    case KeyType::EC: {
+      unique_ptr<KeyHandle> keyHandle = m_backEnd->createKey(identityName, params);
+      Name keyName = keyHandle->getKeyName();
+      m_keys[keyName] = std::move(keyHandle);
+      return keyName;
+    }
+    default: {
+      BOOST_THROW_EXCEPTION(Error("Fail to create a key pair: Unsupported key type"));
+    }
+  }
+}
+
+void
+Tpm::deleteKey(const Name& keyName)
+{
+  auto it = m_keys.find(keyName);
+  if (it != m_keys.end())
+    m_keys.erase(it);
+
+  m_backEnd->deleteKey(keyName);
+}
+
+ConstBufferPtr
+Tpm::getPublicKey(const Name& keyName) const
+{
+  const KeyHandle* key = findKey(keyName);
+
+  if (key == nullptr)
+    return nullptr;
+  else
+    return key->derivePublicKey();
+}
+
+ConstBufferPtr
+Tpm::sign(const uint8_t* buf, size_t size, const Name& keyName, DigestAlgorithm digestAlgorithm) const
+{
+  const KeyHandle* key = findKey(keyName);
+
+  if (key == nullptr)
+    return nullptr;
+  else
+    return key->sign(digestAlgorithm, buf, size);
+}
+
+ConstBufferPtr
+Tpm::decrypt(const uint8_t* buf, size_t size, const Name& keyName) const
+{
+  const KeyHandle* key = findKey(keyName);
+
+  if (key == nullptr)
+    return nullptr;
+  else
+    return key->decrypt(buf, size);
+}
+
+ConstBufferPtr
+Tpm::exportPrivateKey(const Name& keyName, const char* pw, size_t pwLen)
+{
+  return m_backEnd->exportKey(keyName, pw, pwLen);
+}
+
+bool
+Tpm::importPrivateKey(const Name& keyName, const uint8_t* pkcs8, size_t pkcs8Len, const char* pw, size_t pwLen)
+{
+  try {
+    m_backEnd->importKey(keyName, pkcs8, pkcs8Len, pw, pwLen);
+  }
+  catch (const BackEnd::Error&) {
+    return false;
+  }
+  return true;
+}
+
+const KeyHandle*
+Tpm::findKey(const Name& keyName) const
+{
+  auto it = m_keys.find(keyName);
+
+  if (it != m_keys.end())
+    return it->second.get();
+
+  unique_ptr<KeyHandle> handle = m_backEnd->getKeyHandle(keyName);
+
+  if (handle != nullptr) {
+    KeyHandle* key = handle.get();
+    m_keys[keyName] = std::move(handle);
+    return key;
+  }
+
+  return nullptr;
+}
+
+} // namespace tpm
+} // namespace security
+} // namespace ndn
diff --git a/src/security/tpm/tpm.hpp b/src/security/tpm/tpm.hpp
new file mode 100644
index 0000000..01b22ae
--- /dev/null
+++ b/src/security/tpm/tpm.hpp
@@ -0,0 +1,207 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 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.
+ */
+
+#ifndef NDN_SECURITY_TPM_TPM_HPP
+#define NDN_SECURITY_TPM_TPM_HPP
+
+#include "../../common.hpp"
+#include "../security-common.hpp"
+#include "../../name.hpp"
+#include "../key-params.hpp"
+#include "key-handle.hpp"
+#include <unordered_map>
+
+namespace ndn {
+namespace security {
+namespace tpm {
+
+class BackEnd;
+
+/**
+ * @brief represents the front-end of TPM
+ *
+ * The TPM (Trusted Platform Module) stores the private portion of a user's cryptography keys.
+ * The format and location of stored information is indicated by the TpmLocator.
+ * The TPM is designed to work with a PIB (Public Information Base) which stores public keys and
+ * related information such as certificate.
+ *
+ * The TPM also provides functionalities of crypto transformation, such as signing and decryption.
+ *
+ * A TPM consists of a unified front-end interface and a back-end implementation. The front-end
+ * cache the handles of private keys which is provided by the back-end implementation.
+ *
+ * @throw tpm::BackEnd::Error when underlying implementation has non-semantic error.
+ * @throw Tpm::Error when there is an semantic error.
+ */
+class Tpm : noncopyable
+{
+public:
+  friend class KeyChain;
+
+  class Error : public std::runtime_error
+  {
+  public:
+    explicit
+    Error(const std::string& what)
+      : std::runtime_error(what)
+    {
+    }
+  };
+
+public:
+  ~Tpm();
+
+  std::string
+  getTpmLocator() const;
+
+  /**
+   * @brief Check if a private key exist
+   *
+   * @param keyName The key name
+   * @return true if the key exists
+   */
+  bool
+  hasKey(const Name& keyName) const;
+
+  /**
+   * @return The public portion of an asymmetric key with name @p name
+   *         or nullptr if the key does not exist
+   *
+   * The public key is in PKCS#8 format
+   */
+  ConstBufferPtr
+  getPublicKey(const Name& keyName) const;
+
+  /**
+   * @brief Sign blob using key with name @p keyName with digest @p digestAlgorithm.
+   *
+   * @return The signature, or nullptr if the key does not exist
+   */
+  ConstBufferPtr
+  sign(const uint8_t* buf, size_t size, const Name& keyName, DigestAlgorithm digestAlgorithm) const;
+
+  /**
+   * @brief Decrypt blob using key with name @p keyName.
+   *
+   * @return The signature, or nullptr if the key does not exist
+   */
+  ConstBufferPtr
+  decrypt(const uint8_t* buf, size_t size, const Name& keyName) const;
+
+NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
+  /*
+   * @brief Create a new TPM instance with the specified @p location
+   *
+   * @param scheme The scheme for the TPM
+   * @param location The location for the TPM
+   * @param impl The back-end implementation
+   */
+  Tpm(const std::string& scheme, const std::string& location, unique_ptr<BackEnd> impl);
+
+  BackEnd*
+  getBackEnd()
+  {
+    return m_backEnd.get();
+  }
+
+  /**
+   * @brief Create key for @p identityName according to @p params.
+   *
+   * The created key is named as: /<identityName>/[keyId]/KEY
+   *
+   * @return the key name
+   * @throws Tpm::Error if the key has already existed or the params is invalid
+   */
+  Name
+  createKey(const Name& identityName, const KeyParams& params);
+
+  /**
+   * @brief Delete a key pair with name @p keyName.
+   */
+  void
+  deleteKey(const Name& keyName);
+
+  /**
+   * @brief Export a private key
+   *
+   * This method will export the private key in encrypted PKCS #8 format if the key exists.
+   *
+   * @param keyName  The private key name
+   * @param pw The password to encrypt the private key
+   * @param pwLen The length of the password
+   * @return The encoded private key wrapper or an empty block if the key cannot be exported.
+   */
+  ConstBufferPtr
+  exportPrivateKey(const Name& keyName, const char* pw, size_t pwLen);
+
+  /**
+   * @brief Import a private key
+   *
+   * @param keyName The private key name
+   * @param pkcs8 The private key wrapper
+   * @param pkcs8Len The length of the private key wrapper
+   * @param pw The password to encrypt the private key
+   * @param pwLen The length of the password
+   * @return false if importing fails
+   */
+  bool
+  importPrivateKey(const Name& keyName,
+                   const uint8_t* pkcs8, size_t pkcs8Len,
+                   const char* pw, size_t pwLen);
+
+  /**
+   * @brief Clear the key cache
+   *
+   * An empty cache can force Tpm to do key lookup in back-end.
+   */
+  void
+  clearKeyCache()
+  {
+    m_keys.clear();
+  }
+
+private:
+
+  /**
+   * @brief Internal KeyHandle lookup
+   *
+   * @return A pointer to the handle of key @p keyName if it exists, otherwise nullptr.
+   */
+  const KeyHandle*
+  findKey(const Name& keyName) const;
+
+private:
+  std::string m_scheme;
+  std::string m_location;
+
+  mutable std::unordered_map<Name, unique_ptr<KeyHandle>> m_keys;
+
+  unique_ptr<BackEnd> m_backEnd;
+};
+
+} // namespace tpm
+
+using tpm::Tpm;
+
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_SECURITY_TPM_TPM_HPP
diff --git a/tests/unit-tests/security/tpm/back-end-wrapper-file.hpp b/tests/unit-tests/security/tpm/back-end-wrapper-file.hpp
new file mode 100644
index 0000000..3e403ce
--- /dev/null
+++ b/tests/unit-tests/security/tpm/back-end-wrapper-file.hpp
@@ -0,0 +1,72 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 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.
+ */
+
+#ifndef NDN_TESTS_SECURITY_TPM_BACK_END_WRAPPER_FILE_HPP
+#define NDN_TESTS_SECURITY_TPM_BACK_END_WRAPPER_FILE_HPP
+
+#include "security/tpm/back-end-file.hpp"
+#include <boost/filesystem.hpp>
+
+namespace ndn {
+namespace security {
+namespace tpm {
+namespace tests {
+
+/**
+ * @brief A wrapper of tpm::BackEndFile for unit test template.
+ */
+class BackEndWrapperFile
+{
+public:
+  BackEndWrapperFile()
+    : m_tmpPath(boost::filesystem::path(UNIT_TEST_CONFIG_PATH) / "TpmFileTest")
+    , m_impl(new BackEndFile(m_tmpPath.string()))
+  {
+  }
+
+  ~BackEndWrapperFile()
+  {
+    boost::filesystem::remove_all(m_tmpPath);
+  }
+
+  BackEnd&
+  getTpm()
+  {
+    return *m_impl;
+  }
+
+  std::string
+  getScheme()
+  {
+    return "tpm-file";
+  }
+
+private:
+  boost::filesystem::path m_tmpPath;
+  unique_ptr<BackEnd> m_impl;
+};
+
+} // namespace tests
+} // namespace tpm
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_TESTS_SECURITY_TPM_BACK_END_WRAPPER_FILE_HPP
diff --git a/tests/unit-tests/security/tpm/back-end-wrapper-mem.hpp b/tests/unit-tests/security/tpm/back-end-wrapper-mem.hpp
new file mode 100644
index 0000000..ea10295
--- /dev/null
+++ b/tests/unit-tests/security/tpm/back-end-wrapper-mem.hpp
@@ -0,0 +1,64 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 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.
+ */
+
+#ifndef NDN_TESTS_SECURITY_TPM_BACK_END_WRAPPER_MEM_HPP
+#define NDN_TESTS_SECURITY_TPM_BACK_END_WRAPPER_MEM_HPP
+
+#include "security/tpm/back-end-mem.hpp"
+
+namespace ndn {
+namespace security {
+namespace tpm {
+namespace tests {
+
+/**
+ * @brief A wrapper of tpm::BackEndMem for unit test template.
+ */
+class BackEndWrapperMem
+{
+public:
+  BackEndWrapperMem()
+  {
+    m_impl = unique_ptr<BackEnd>(new BackEndMem);
+  }
+
+  BackEnd&
+  getTpm()
+  {
+    return *m_impl;
+  }
+
+  std::string
+  getScheme()
+  {
+    return "tpm-memory";
+  }
+
+private:
+  unique_ptr<BackEnd> m_impl;
+};
+
+} // namespace tests
+} // namespace tpm
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_TESTS_SECURITY_TPM_BACK_END_WRAPPER_MEM_HPP
diff --git a/tests/unit-tests/security/tpm/back-end-wrapper-osx.hpp b/tests/unit-tests/security/tpm/back-end-wrapper-osx.hpp
new file mode 100644
index 0000000..d02b717
--- /dev/null
+++ b/tests/unit-tests/security/tpm/back-end-wrapper-osx.hpp
@@ -0,0 +1,87 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 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.
+ */
+
+#ifndef NDN_TESTS_SECURITY_TPM_BACK_END_WRAPPER_OSX_HPP
+#define NDN_TESTS_SECURITY_TPM_BACK_END_WRAPPER_OSX_HPP
+
+#include "security/tpm/back-end-osx.hpp"
+#include "security/tpm/key-handle-osx.hpp"
+#include <Availability.h>
+
+namespace ndn {
+namespace security {
+namespace tpm {
+namespace tests {
+
+/**
+ * @brief A wrapper of tpm::BackEndOsx for unit test template.
+ */
+class BackEndWrapperOsx
+{
+public:
+  BackEndWrapperOsx()
+  {
+    std::string oldHOME;
+    if (std::getenv("OLD_HOME"))
+      oldHOME = std::getenv("OLD_HOME");
+
+    if (std::getenv("HOME"))
+      m_HOME = std::getenv("HOME");
+
+    if (!oldHOME.empty())
+      setenv("HOME", oldHOME.c_str(), 1);
+    else
+      unsetenv("HOME");
+
+    m_impl = unique_ptr<BackEnd>(new BackEndOsx);
+  }
+
+  ~BackEndWrapperOsx()
+  {
+    if (!m_HOME.empty())
+      setenv("HOME", m_HOME.c_str(), 1);
+    else
+      unsetenv("HOME");
+  }
+
+  BackEnd&
+  getTpm()
+  {
+    return *m_impl;
+  }
+
+  std::string
+  getScheme()
+  {
+    return "tpm-osxkeychain";
+  }
+
+private:
+  std::string m_HOME;
+  unique_ptr<BackEnd> m_impl;
+};
+
+} // namespace tests
+} // namespace tpm
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_TESTS_SECURITY_TPM_BACK_END_WRAPPER_OSX_HPP
diff --git a/tests/unit-tests/security/tpm/back-end.t.cpp b/tests/unit-tests/security/tpm/back-end.t.cpp
new file mode 100644
index 0000000..01b9e6c
--- /dev/null
+++ b/tests/unit-tests/security/tpm/back-end.t.cpp
@@ -0,0 +1,268 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 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.
+ */
+
+#include "security/tpm/back-end.hpp"
+#include "security/tpm/back-end-mem.hpp"
+#include "security/tpm/key-handle.hpp"
+#include "security/tpm/tpm.hpp"
+#include "security/transform.hpp"
+#include "security/transform/public-key.hpp"
+#include "security/transform/private-key.hpp"
+#include "encoding/buffer-stream.hpp"
+#include "security/pib/key.hpp"
+
+#include "back-end-wrapper-file.hpp"
+#include "back-end-wrapper-mem.hpp"
+#ifdef NDN_CXX_HAVE_OSX_SECURITY
+#include "back-end-wrapper-osx.hpp"
+#endif // NDN_CXX_HAVE_OSX_SECURITY
+#include "boost-test.hpp"
+
+#include <boost/mpl/list.hpp>
+#include <set>
+
+namespace ndn {
+namespace security {
+namespace tpm {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(Tpm)
+BOOST_AUTO_TEST_SUITE(TestBackEnd)
+
+using tpm::Tpm;
+
+typedef boost::mpl::list<
+#ifdef NDN_CXX_HAVE_OSX_SECURITY
+  BackEndWrapperOsx,
+#endif // NDN_CXX_HAVE_OSX_SECURITY
+  BackEndWrapperMem,
+  BackEndWrapperFile
+  > TestBackEnds;
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(KeyManagement, T, TestBackEnds)
+{
+  T wrapper;
+  BackEnd& tpm = wrapper.getTpm();
+
+  Name identity("/Test/KeyName");
+  name::Component keyId("1");
+  Name keyName = v2::constructKeyName(identity, keyId);
+
+  // key should not exist
+  BOOST_CHECK_EQUAL(tpm.hasKey(keyName), false);
+  BOOST_CHECK(tpm.getKeyHandle(keyName) == nullptr);
+
+  // create key, should exist
+  BOOST_CHECK(tpm.createKey(identity, RsaKeyParams(keyId)) != nullptr);
+  BOOST_CHECK(tpm.hasKey(keyName));
+  BOOST_CHECK(tpm.getKeyHandle(keyName) != nullptr);
+
+  // create a key with the same name, should throw error
+  BOOST_CHECK_THROW(tpm.createKey(identity, RsaKeyParams(keyId)), Tpm::Error);
+
+  // delete key, should not exist
+  tpm.deleteKey(keyName);
+  BOOST_CHECK_EQUAL(tpm.hasKey(keyName), false);
+  BOOST_CHECK(tpm.getKeyHandle(keyName) == nullptr);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(RsaSigning, T, TestBackEnds)
+{
+  T wrapper;
+  BackEnd& tpm = wrapper.getTpm();
+
+  // create an rsa key
+  Name identity("/Test/KeyName");
+
+  unique_ptr<KeyHandle> key = tpm.createKey(identity, RsaKeyParams());
+  Name keyName = key->getKeyName();
+
+  const uint8_t content[] = {0x01, 0x02, 0x03, 0x04};
+  Block sigBlock(tlv::SignatureValue, key->sign(DigestAlgorithm::SHA256, content, sizeof(content)));
+
+  transform::PublicKey pubKey;
+  ConstBufferPtr pubKeyBits = key->derivePublicKey();
+  pubKey.loadPkcs8(pubKeyBits->buf(), pubKeyBits->size());
+
+  bool result;
+  {
+    using namespace transform;
+    bufferSource(content, sizeof(content)) >> verifierFilter(DigestAlgorithm::SHA256, pubKey,
+                                                             sigBlock.value(), sigBlock.value_size())
+                                           >> boolSink(result);
+  }
+  BOOST_CHECK_EQUAL(result, true);
+
+  tpm.deleteKey(keyName);
+  BOOST_CHECK_EQUAL(tpm.hasKey(keyName), false);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(RsaDecryption, T, TestBackEnds)
+{
+  T wrapper;
+  BackEnd& tpm = wrapper.getTpm();
+
+  // create an rsa key
+  Name identity("/Test/KeyName");
+
+  unique_ptr<KeyHandle> key = tpm.createKey(identity, RsaKeyParams());
+  Name keyName = key->getKeyName();
+
+  const uint8_t content[] = {0x01, 0x02, 0x03, 0x04};
+
+  transform::PublicKey pubKey;
+  ConstBufferPtr pubKeyBits = key->derivePublicKey();
+  pubKey.loadPkcs8(pubKeyBits->buf(), pubKeyBits->size());
+
+  ConstBufferPtr cipherText = pubKey.encrypt(content, sizeof(content));
+
+  ConstBufferPtr plainText = key->decrypt(cipherText->buf(), cipherText->size());
+
+  BOOST_CHECK_EQUAL_COLLECTIONS(content, content + sizeof(content),
+                                plainText->begin(), plainText->end());
+
+  tpm.deleteKey(keyName);
+  BOOST_CHECK_EQUAL(tpm.hasKey(keyName), false);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(EcdsaSigning, T, TestBackEnds)
+{
+  T wrapper;
+  BackEnd& tpm = wrapper.getTpm();
+
+  // create an ecdsa key
+  Name identity("/Test/Ecdsa/KeyName");
+
+  unique_ptr<KeyHandle> key = tpm.createKey(identity, EcdsaKeyParams());
+  Name ecdsaKeyName = key->getKeyName();
+
+  const uint8_t content[] = {0x01, 0x02, 0x03, 0x04};
+  Block sigBlock(tlv::SignatureValue, key->sign(DigestAlgorithm::SHA256, content, sizeof(content)));
+
+  transform::PublicKey pubKey;
+  ConstBufferPtr pubKeyBits = key->derivePublicKey();
+  pubKey.loadPkcs8(pubKeyBits->buf(), pubKeyBits->size());
+
+  bool result;
+  {
+    using namespace transform;
+    bufferSource(content, sizeof(content)) >> verifierFilter(DigestAlgorithm::SHA256, pubKey,
+                                                             sigBlock.value(), sigBlock.value_size())
+                                           >> boolSink(result);
+  }
+  BOOST_CHECK_EQUAL(result, true);
+
+  tpm.deleteKey(ecdsaKeyName);
+  BOOST_CHECK_EQUAL(tpm.hasKey(ecdsaKeyName), false);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(ImportExport, T, TestBackEnds)
+{
+  std::string privateKeyPkcs1 =
+    "MIIEpAIBAAKCAQEAw0WM1/WhAxyLtEqsiAJgWDZWuzkYpeYVdeeZcqRZzzfRgBQT\n"
+    "sNozS5t4HnwTZhwwXbH7k3QN0kRTV826Xobws3iigohnM9yTK+KKiayPhIAm/+5H\n"
+    "GT6SgFJhYhqo1/upWdueojil6RP4/AgavHhopxlAVbk6G9VdVnlQcQ5Zv0OcGi73\n"
+    "c+EnYD/YgURYGSngUi/Ynsh779p2U69/te9gZwIL5PuE9BiO6I39cL9z7EK1SfZh\n"
+    "OWvDe/qH7YhD/BHwcWit8FjRww1glwRVTJsA9rH58ynaAix0tcR/nBMRLUX+e3rU\n"
+    "RHg6UbSjJbdb9qmKM1fTGHKUzL/5pMG6uBU0ywIDAQABAoIBADQkckOIl4IZMUTn\n"
+    "W8LFv6xOdkJwMKC8G6bsPRFbyY+HvC2TLt7epSvfS+f4AcYWaOPcDu2E49vt2sNr\n"
+    "cASly8hgwiRRAB3dHH9vcsboiTo8bi2RFvMqvjv9w3tK2yMxVDtmZamzrrnaV3YV\n"
+    "Q+5nyKo2F/PMDjQ4eUAKDOzjhBuKHsZBTFnA1MFNI+UKj5X4Yp64DFmKlxTX/U2b\n"
+    "wzVywo5hzx2Uhw51jmoLls4YUvMJXD0wW5ZtYRuPogXvXb/of9ef/20/wU11WFKg\n"
+    "Xb4gfR8zUXaXS1sXcnVm3+24vIs9dApUwykuoyjOqxWqcHRec2QT2FxVGkFEraze\n"
+    "CPa4rMECgYEA5Y8CywomIcTgerFGFCeMHJr8nQGqY2V/owFb3k9maczPnC9p4a9R\n"
+    "c5szLxA9FMYFxurQZMBWSEG2JS1HR2mnjigx8UKjYML/A+rvvjZOMe4M6Sy2ggh4\n"
+    "SkLZKpWTzjTe07ByM/j5v/SjNZhWAG7sw4/LmPGRQkwJv+KZhGojuOkCgYEA2cOF\n"
+    "T6cJRv6kvzTz9S0COZOVm+euJh/BXp7oAsAmbNfOpckPMzqHXy8/wpdKl6AAcB57\n"
+    "OuztlNfV1D7qvbz7JuRlYwQ0cEfBgbZPcz1p18HHDXhwn57ZPb8G33Yh9Omg0HNA\n"
+    "Imb4LsVuSqxA6NwSj7cpRekgTedrhLFPJ+Ydb5MCgYEAsM3Q7OjILcIg0t6uht9e\n"
+    "vrlwTsz1mtCV2co2I6crzdj9HeI2vqf1KAElDt6G7PUHhglcr/yjd8uEqmWRPKNX\n"
+    "ddnnfVZB10jYeP/93pac6z/Zmc3iU4yKeUe7U10ZFf0KkiiYDQd59CpLef/2XScS\n"
+    "HB0oRofnxRQjfjLc4muNT+ECgYEAlcDk06MOOTly+F8lCc1bA1dgAmgwFd2usDBd\n"
+    "Y07a3e0HGnGLN3Kfl7C5i0tZq64HvxLnMd2vgLVxQlXGPpdQrC1TH+XLXg+qnlZO\n"
+    "ivSH7i0/gx75bHvj75eH1XK65V8pDVDEoSPottllAIs21CxLw3N1ObOZWJm2EfmR\n"
+    "cuHICmsCgYAtFJ1idqMoHxES3mlRpf2JxyQudP3SCm2WpGmqVzhRYInqeatY5sUd\n"
+    "lPLHm/p77RT7EyxQHTlwn8FJPuM/4ZH1rQd/vB+Y8qAtYJCexDMsbvLW+Js+VOvk\n"
+    "jweEC0nrcL31j9mF0vz5E6tfRu4hhJ6L4yfWs0gSejskeVB/w8QY4g==\n";
+
+  T wrapper;
+  BackEnd& tpm = wrapper.getTpm();
+
+  Name keyName("/Test/KeyName/KEY/1");
+
+  tpm.deleteKey(keyName);
+  BOOST_CHECK_EQUAL(tpm.hasKey(keyName), false);
+
+  transform::PrivateKey sKey;
+  BOOST_REQUIRE_NO_THROW(sKey.loadPkcs1Base64(reinterpret_cast<const uint8_t*>(privateKeyPkcs1.c_str()),
+                                              privateKeyPkcs1.size()));
+
+  std::string password("password");
+
+  OBufferStream os;
+  sKey.savePkcs8(os, password.c_str(), password.size());
+  ConstBufferPtr privateKeyBuffer = os.buf();
+
+  BOOST_REQUIRE_NO_THROW(tpm.importKey(keyName,
+                                       privateKeyBuffer->buf(), privateKeyBuffer->size(),
+                                       password.c_str(), password.size()));
+  BOOST_CHECK_EQUAL(tpm.hasKey(keyName), true);
+
+  ConstBufferPtr exportedKey = tpm.exportKey(keyName, password.c_str(), password.size());
+  BOOST_CHECK_EQUAL(tpm.hasKey(keyName), true);
+
+  transform::PrivateKey sKey2;
+  sKey2.loadPkcs8(exportedKey->buf(), exportedKey->size(), password.c_str(), password.size());
+  OBufferStream os2;
+  sKey.savePkcs1Base64(os2);
+  ConstBufferPtr pkcs1Buffer = os2.buf();
+
+  BOOST_CHECK_EQUAL_COLLECTIONS(privateKeyPkcs1.begin(), privateKeyPkcs1.end(),
+                                pkcs1Buffer->begin(), pkcs1Buffer->end());
+
+  tpm.deleteKey(keyName);
+  BOOST_CHECK_EQUAL(tpm.hasKey(keyName), false);
+}
+
+BOOST_AUTO_TEST_CASE(RandomKeyId)
+{
+  BackEndWrapperMem wrapper;
+  BackEnd& tpm = wrapper.getTpm();
+  Name identity("/Test/KeyName");
+
+  std::set<Name> keyNames;
+  for (int i = 0; i < 100; i++) {
+    auto key = tpm.createKey(identity, RsaKeyParams());
+    Name keyName = key->getKeyName();
+    tpm.deleteKey(keyName);
+    BOOST_CHECK(keyNames.insert(keyName).second);
+  }
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestBackEnd
+BOOST_AUTO_TEST_SUITE_END() // Tpm
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace tpm
+} // namespace security
+} // namespace ndn