security: Construct KeyChain from configuration file.

Change-Id: Iaddac24e2c4e199fdde83fa1d0067a87e18729c4
Refs: #1532
diff --git a/src/security/key-chain.cpp b/src/security/key-chain.cpp
new file mode 100644
index 0000000..58c3570
--- /dev/null
+++ b/src/security/key-chain.cpp
@@ -0,0 +1,323 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/**
+ * Copyright (c) 2013-2014,  Regents of the University of California.
+ * All rights reserved.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ *
+ * This file licensed under New BSD License.  See COPYING for detailed information about
+ * ndn-cxx library copyright, permissions, and redistribution restrictions.
+ *
+ * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
+ */
+
+#include "key-chain.hpp"
+
+#include "sec-public-info-sqlite3.hpp"
+#include "sec-tpm-file.hpp"
+
+#ifdef NDN_CXX_HAVE_OSX_SECURITY
+#include "sec-tpm-osx.hpp"
+#endif
+
+#include "../util/random.hpp"
+#include "../util/config-file.hpp"
+
+namespace ndn {
+
+KeyChain::KeyChain()
+  : m_pib(0)
+  , m_tpm(0)
+{
+
+  ConfigFile config;
+  const ConfigFile::Parsed& parsed = config.getParsedConfiguration();
+
+  std::string pibName;
+  try
+    {
+      pibName = parsed.get<std::string>("pib");
+    }
+  catch (boost::property_tree::ptree_bad_path& error)
+    {
+      // pib is not specified, take the default
+    }
+  catch (boost::property_tree::ptree_bad_data& error)
+    {
+      throw ConfigFile::Error(error.what());
+    }
+
+  std::string tpmName;
+  try
+    {
+      tpmName = parsed.get<std::string>("tpm");
+    }
+  catch (boost::property_tree::ptree_bad_path& error)
+    {
+      // tpm is not specified, take the default
+    }
+  catch (boost::property_tree::ptree_bad_data& error)
+    {
+      throw ConfigFile::Error(error.what());
+    }
+
+
+  if (pibName.empty() || pibName == "sqlite3")
+    m_pib = new SecPublicInfoSqlite3;
+  else
+    throw Error("PIB type '" + pibName + "' is not supported");
+
+  if (tpmName.empty())
+#if defined(NDN_CXX_HAVE_OSX_SECURITY) and defined(NDN_CXX_WITH_OSX_KEYCHAIN)
+    m_tpm = new SecTpmOsx();
+#else
+    m_tpm = new SecTpmFile();
+#endif // defined(NDN_CXX_HAVE_OSX_SECURITY) and defined(NDN_CXX_WITH_OSX_KEYCHAIN)
+  else if (tpmName == "osx-keychain")
+#if defined(NDN_CXX_HAVE_OSX_SECURITY)
+    m_tpm = new SecTpmOsx();
+#else
+    throw Error("TPM type '" + tpmName + "' is not supported on this platform");
+#endif // NDN_CXX_HAVE_OSX_SECURITY
+  else if (tpmName == "file")
+    m_tpm = new SecTpmFile();
+  else
+    throw Error("TPM type '" + tpmName + "' is not supported");
+}
+
+KeyChain::KeyChain(const std::string& pibName,
+                   const std::string& tpmName)
+  : m_pib(0)
+  , m_tpm(0)
+{
+  if (pibName == "sqlite3")
+    m_pib = new SecPublicInfoSqlite3;
+  else
+    throw Error("PIB type '" + pibName + "' is not supported");
+
+  if (tpmName == "file")
+    m_tpm = new SecTpmFile;
+#if defined(NDN_CXX_HAVE_OSX_SECURITY)
+  else if (tpmName == "osx-keychain")
+    m_tpm = new SecTpmOsx();
+#endif //NDN_CXX_HAVE_OSX_SECURITY
+  else
+    throw Error("TPM type '" + tpmName + "' is not supported");
+}
+
+shared_ptr<IdentityCertificate>
+KeyChain::prepareUnsignedIdentityCertificate(const Name& keyName,
+  const Name& signingIdentity,
+  const time::system_clock::TimePoint& notBefore,
+  const time::system_clock::TimePoint& notAfter,
+  const std::vector<CertificateSubjectDescription>& subjectDescription)
+{
+  if (keyName.size() < 1)
+    return shared_ptr<IdentityCertificate>();
+
+  std::string keyIdPrefix = keyName.get(-1).toEscapedString().substr(0, 4);
+  if (keyIdPrefix != "ksk-" && keyIdPrefix != "dsk-")
+    return shared_ptr<IdentityCertificate>();
+
+  shared_ptr<IdentityCertificate> certificate = make_shared<IdentityCertificate>();
+  Name certName;
+
+  if (signingIdentity.isPrefixOf(keyName))
+    {
+      certName.append(signingIdentity)
+        .append("KEY")
+        .append(keyName.getSubName(signingIdentity.size()))
+        .append("ID-CERT")
+        .appendVersion();
+    }
+  else
+    {
+      certName.append(keyName.getPrefix(-1))
+        .append("KEY")
+        .append(keyName.get(-1))
+        .append("ID-CERT")
+        .appendVersion();
+    }
+
+  certificate->setName(certName);
+  certificate->setNotBefore(notBefore);
+  certificate->setNotAfter(notAfter);
+
+  shared_ptr<PublicKey> publicKey;
+  try
+    {
+      publicKey = m_pib->getPublicKey(keyName);
+    }
+  catch (SecPublicInfo::Error& e)
+    {
+      return shared_ptr<IdentityCertificate>();
+    }
+  certificate->setPublicKeyInfo(*publicKey);
+
+  if (subjectDescription.empty())
+    {
+      CertificateSubjectDescription subjectName("2.5.4.41", keyName.getPrefix(-1).toUri());
+      certificate->addSubjectDescription(subjectName);
+    }
+  else
+    {
+      std::vector<CertificateSubjectDescription>::const_iterator sdIt =
+        subjectDescription.begin();
+      std::vector<CertificateSubjectDescription>::const_iterator sdEnd =
+        subjectDescription.end();
+      for(; sdIt != sdEnd; sdIt++)
+        certificate->addSubjectDescription(*sdIt);
+    }
+
+  certificate->encode();
+
+  return certificate;
+}
+
+Signature
+KeyChain::sign(const uint8_t* buffer, size_t bufferLength, const Name& certificateName)
+{
+  if (!m_pib->doesCertificateExist(certificateName))
+    throw SecPublicInfo::Error("Requested certificate ["
+                               + certificateName.toUri() + "] doesn't exist");
+
+  Name keyName = IdentityCertificate::certificateNameToPublicKeyName(certificateName);
+
+  SignatureSha256WithRsa signature;
+  // implicit conversion should take care
+  signature.setKeyLocator(certificateName.getPrefix(-1));
+
+  // For temporary usage, we support RSA + SHA256 only, but will support more.
+  signature.setValue(m_tpm->signInTpm(buffer, bufferLength, keyName, DIGEST_ALGORITHM_SHA256));
+  return signature;
+}
+
+shared_ptr<IdentityCertificate>
+KeyChain::selfSign(const Name& keyName)
+{
+  shared_ptr<PublicKey> pubKey;
+  try
+    {
+      pubKey = m_pib->getPublicKey(keyName); // may throw an exception.
+    }
+  catch (SecPublicInfo::Error& e)
+    {
+      return shared_ptr<IdentityCertificate>();
+    }
+
+  shared_ptr<IdentityCertificate> certificate = make_shared<IdentityCertificate>();
+
+  Name certificateName = keyName.getPrefix(-1);
+  certificateName.append("KEY").append(keyName.get(-1)).append("ID-CERT").appendVersion();
+
+  certificate->setName(certificateName);
+  certificate->setNotBefore(time::system_clock::now());
+  certificate->setNotAfter(time::system_clock::now() + time::days(7300)/* ~20 years*/);
+  certificate->setPublicKeyInfo(*pubKey);
+  certificate->addSubjectDescription(CertificateSubjectDescription("2.5.4.41", keyName.toUri()));
+  certificate->encode();
+
+  selfSign(*certificate);
+  return certificate;
+}
+
+void
+KeyChain::selfSign(IdentityCertificate& cert)
+{
+  Name keyName = IdentityCertificate::certificateNameToPublicKeyName(cert.getName());
+  if (!m_tpm->doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE))
+    throw SecTpm::Error("private key does not exist!");
+
+  SignatureSha256WithRsa signature;
+  signature.setKeyLocator(cert.getName().getPrefix(-1)); // implicit conversion should take care
+
+  // For temporary usage, we support RSA + SHA256 only, but will support more.
+  signPacketWrapper(cert, signature, keyName, DIGEST_ALGORITHM_SHA256);
+}
+
+shared_ptr<SecuredBag>
+KeyChain::exportIdentity(const Name& identity, const std::string& passwordStr)
+{
+  if (!m_pib->doesIdentityExist(identity))
+    throw SecPublicInfo::Error("Identity does not exist!");
+
+  Name keyName = m_pib->getDefaultKeyNameForIdentity(identity);
+
+  ConstBufferPtr pkcs5;
+  try
+    {
+      pkcs5 = m_tpm->exportPrivateKeyPkcs5FromTpm(keyName, passwordStr);
+    }
+  catch (SecTpm::Error& e)
+    {
+      throw SecPublicInfo::Error("Fail to export PKCS5 of private key");
+    }
+
+  shared_ptr<IdentityCertificate> cert;
+  try
+    {
+      cert = m_pib->getCertificate(m_pib->getDefaultCertificateNameForKey(keyName));
+    }
+  catch (SecPublicInfo::Error& e)
+    {
+      cert = selfSign(keyName);
+      m_pib->addCertificateAsIdentityDefault(*cert);
+    }
+
+  shared_ptr<SecuredBag> secureBag = make_shared<SecuredBag>(boost::cref(*cert),
+                                                             boost::cref(pkcs5));
+
+  return secureBag;
+}
+
+void
+KeyChain::importIdentity(const SecuredBag& securedBag, const std::string& passwordStr)
+{
+  Name certificateName = securedBag.getCertificate().getName();
+  Name keyName = IdentityCertificate::certificateNameToPublicKeyName(certificateName);
+  Name identity = keyName.getPrefix(-1);
+
+  // Add identity
+  m_pib->addIdentity(identity);
+
+  // Add key
+  m_tpm->importPrivateKeyPkcs5IntoTpm(keyName,
+                                      securedBag.getKey()->buf(),
+                                      securedBag.getKey()->size(),
+                                      passwordStr);
+
+  shared_ptr<PublicKey> pubKey = m_tpm->getPublicKeyFromTpm(keyName.toUri());
+  // HACK! We should set key type according to the pkcs8 info.
+  m_pib->addPublicKey(keyName, KEY_TYPE_RSA, *pubKey);
+  m_pib->setDefaultKeyNameForIdentity(keyName);
+
+  // Add cert
+  m_pib->addCertificateAsIdentityDefault(securedBag.getCertificate());
+}
+
+void
+KeyChain::setDefaultCertificateInternal()
+{
+  m_pib->refreshDefaultCertificate();
+
+  if (!static_cast<bool>(m_pib->defaultCertificate()))
+    {
+      Name defaultIdentity;
+      try
+        {
+          defaultIdentity = m_pib->getDefaultIdentity();
+        }
+      catch (SecPublicInfo::Error& e)
+        {
+          uint32_t random = random::generateWord32();
+          defaultIdentity.append("tmp-identity")
+            .append(reinterpret_cast<uint8_t*>(&random), 4);
+        }
+      createIdentity(defaultIdentity);
+      m_pib->setDefaultIdentity(defaultIdentity);
+      m_pib->refreshDefaultCertificate();
+    }
+}
+
+}
diff --git a/src/security/key-chain.hpp b/src/security/key-chain.hpp
index 69d5ffb..bb0f650 100644
--- a/src/security/key-chain.hpp
+++ b/src/security/key-chain.hpp
@@ -15,41 +15,57 @@
 #ifndef NDN_SECURITY_KEY_CHAIN_HPP
 #define NDN_SECURITY_KEY_CHAIN_HPP
 
-#include "identity-certificate.hpp"
-#include "public-key.hpp"
+#include "sec-public-info.hpp"
+#include "sec-tpm.hpp"
+#include "secured-bag.hpp"
 #include "signature-sha256-with-rsa.hpp"
 #include "signature-sha256.hpp"
-#include "secured-bag.hpp"
+
 #include "../interest.hpp"
-#include "../util/random.hpp"
 #include "../util/crypto.hpp"
 
-//PublicInfo
-#include "sec-public-info-sqlite3.hpp"
-#include "sec-public-info-memory.hpp"
-//TPM
-#include "sec-tpm-file.hpp"
-#include "sec-tpm-memory.hpp"
-
-#ifdef NDN_CXX_HAVE_OSX_SECURITY
-#include "sec-tpm-osx.hpp"
-#endif
-
 
 namespace ndn {
 
-/**
- * @brief KeyChain is one of the main classes of the security library.
- *
- * The KeyChain class provides a set of interfaces of identity management and private key related
- * operations.
- */
-template<class Info, class Tpm>
-class KeyChainImpl : public Info, public Tpm
+template<class TypePib, class TypeTpm>
+class KeyChainTraits
 {
-  typedef SecPublicInfo::Error InfoError;
-  typedef SecTpm::Error TpmError;
 public:
+  typedef TypePib Pib;
+  typedef TypeTpm Tpm;
+};
+
+class KeyChain
+{
+public:
+  class Error : public std::runtime_error
+  {
+  public:
+    explicit
+    Error(const std::string& what)
+      : std::runtime_error(what)
+    {
+    }
+  };
+
+  KeyChain();
+
+  template<class KeyChainTraits>
+  KeyChain(KeyChainTraits traits);
+
+  KeyChain(const std::string& pibName,
+           const std::string& tpmName);
+
+  virtual
+  ~KeyChain()
+  {
+    if (m_pib != 0)
+      delete m_pib;
+
+    if (m_tpm != 0)
+      delete m_tpm;
+  }
+
   /**
    * @brief Create an identity by creating a pair of Key-Signing-Key (KSK) for this identity and a
    *        self-signed certificate of the KSK.
@@ -57,35 +73,8 @@
    * @param identityName The name of the identity.
    * @return The name of the default certificate of the identity.
    */
-  Name
-  createIdentity(const Name& identityName)
-  {
-    Info::addIdentity(identityName);
-
-    Name keyName;
-    try
-      {
-        keyName = Info::getDefaultKeyNameForIdentity(identityName);
-      }
-    catch (InfoError& e)
-      {
-        keyName = generateRSAKeyPairAsDefault(identityName, true);
-      }
-
-    Name certName;
-    try
-      {
-        certName = Info::getDefaultCertificateNameForKey(keyName);
-      }
-    catch (InfoError& e)
-      {
-        shared_ptr<IdentityCertificate> selfCert = selfSign(keyName);
-        Info::addCertificateAsIdentityDefault(*selfCert);
-        certName = selfCert->getName();
-      }
-
-    return certName;
-  }
+  inline Name
+  createIdentity(const Name& identityName);
 
   /**
    * @brief Generate a pair of RSA keys for the specified identity.
@@ -95,11 +84,8 @@
    * @param keySize The size of the key.
    * @return The generated key name.
    */
-  Name
-  generateRSAKeyPair(const Name& identityName, bool isKsk = false, int keySize = 2048)
-  {
-    return generateKeyPair(identityName, isKsk, KEY_TYPE_RSA, keySize);
-  }
+  inline Name
+  generateRsaKeyPair(const Name& identityName, bool isKsk = false, int keySize = 2048);
 
   /**
    * @brief Generate a pair of RSA keys for the specified identity and set it as default key for
@@ -110,15 +96,8 @@
    * @param keySize The size of the key.
    * @return The generated key name.
    */
-  Name
-  generateRSAKeyPairAsDefault(const Name& identityName, bool isKsk = false, int keySize = 2048)
-  {
-    Name keyName = generateKeyPair(identityName, isKsk, KEY_TYPE_RSA, keySize);
-
-    Info::setDefaultKeyNameForIdentity(keyName);
-
-    return keyName;
-  }
+  inline Name
+  generateRsaKeyPairAsDefault(const Name& identityName, bool isKsk = false, int keySize = 2048);
 
   /**
    * @brief prepare an unsigned identity certificate
@@ -132,73 +111,10 @@
    */
   shared_ptr<IdentityCertificate>
   prepareUnsignedIdentityCertificate(const Name& keyName,
-                                     const Name& signingIdentity,
-                                     const time::system_clock::TimePoint& notBefore,
-                                     const time::system_clock::TimePoint& notAfter,
-                                     const std::vector<CertificateSubjectDescription>& subjectDescription)
-
-  {
-    if (keyName.size() < 1)
-      return shared_ptr<IdentityCertificate>();
-
-    std::string keyIdPrefix = keyName.get(-1).toEscapedString().substr(0, 4);
-    if (keyIdPrefix != "ksk-" && keyIdPrefix != "dsk-")
-      return shared_ptr<IdentityCertificate>();
-
-    shared_ptr<IdentityCertificate> certificate = make_shared<IdentityCertificate>();
-    Name certName;
-
-    if (signingIdentity.isPrefixOf(keyName))
-      {
-        certName.append(signingIdentity)
-          .append("KEY")
-          .append(keyName.getSubName(signingIdentity.size()))
-          .append("ID-CERT")
-          .appendVersion();
-      }
-    else
-      {
-        certName.append(keyName.getPrefix(-1))
-          .append("KEY")
-          .append(keyName.get(-1))
-          .append("ID-CERT")
-          .appendVersion();
-      }
-
-    certificate->setName(certName);
-    certificate->setNotBefore(notBefore);
-    certificate->setNotAfter(notAfter);
-
-    shared_ptr<PublicKey> publicKey;
-    try
-      {
-        publicKey = Info::getPublicKey(keyName);
-      }
-    catch (InfoError& e)
-      {
-        return shared_ptr<IdentityCertificate>();
-      }
-    certificate->setPublicKeyInfo(*publicKey);
-
-    if (subjectDescription.empty())
-      {
-        CertificateSubjectDescription subDescryptName("2.5.4.41", keyName.getPrefix(-1).toUri());
-        certificate->addSubjectDescription(subDescryptName);
-      }
-    else
-      {
-        std::vector<CertificateSubjectDescription>::const_iterator sdIt =
-          subjectDescription.begin();
-        std::vector<CertificateSubjectDescription>::const_iterator sdEnd =
-          subjectDescription.end();
-        for(; sdIt != sdEnd; sdIt++)
-          certificate->addSubjectDescription(*sdIt);
-      }
-
-    certificate->encode();
-
-    return certificate;
-  }
+    const Name& signingIdentity,
+    const time::system_clock::TimePoint& notBefore,
+    const time::system_clock::TimePoint& notAfter,
+    const std::vector<CertificateSubjectDescription>& subjectDescription);
 
   /**
    * @brief Sign packet with default identity
@@ -211,33 +127,7 @@
    */
   template<typename T>
   void
-  sign(T& packet)
-  {
-    if (!static_cast<bool>(Info::defaultCertificate()))
-      {
-        Info::refreshDefaultCertificate();
-
-        if (!static_cast<bool>(Info::defaultCertificate()))
-          {
-            Name defaultIdentity;
-            try
-              {
-                defaultIdentity = Info::getDefaultIdentity();
-              }
-            catch (InfoError& e)
-              {
-                uint32_t random = random::generateWord32();
-                defaultIdentity.append("tmp-identity")
-                  .append(reinterpret_cast<uint8_t*>(&random), 4);
-              }
-            createIdentity(defaultIdentity);
-            Info::setDefaultIdentity(defaultIdentity);
-            Info::refreshDefaultCertificate();
-          }
-      }
-
-    sign(packet, *Info::defaultCertificate());
-  }
+  sign(T& packet);
 
   /**
    * @brief Sign packet with a particular certificate.
@@ -248,20 +138,7 @@
    */
   template<typename T>
   void
-  sign(T& packet, const Name& certificateName)
-  {
-    if (!Info::doesCertificateExist(certificateName))
-      throw InfoError("Requested certificate [" + certificateName.toUri() + "] doesn't exist");
-
-    SignatureSha256WithRsa signature;
-    // implicit conversion should take care
-    signature.setKeyLocator(certificateName.getPrefix(-1));
-
-    // For temporary usage, we support RSA + SHA256 only, but will support more.
-    signPacketWrapper(packet, signature,
-                      IdentityCertificate::certificateNameToPublicKeyName(certificateName),
-                      DIGEST_ALGORITHM_SHA256);
-  }
+  sign(T& packet, const Name& certificateName);
 
   /**
    * @brief Sign the byte array using a particular certificate.
@@ -273,21 +150,7 @@
    * @throws SecPublicInfo::Error if certificate does not exist.
    */
   Signature
-  sign(const uint8_t* buffer, size_t bufferLength, const Name& certificateName)
-  {
-    if (!Info::doesCertificateExist(certificateName))
-      throw InfoError("Requested certificate [" + certificateName.toUri() + "] doesn't exist");
-
-    Name keyName = IdentityCertificate::certificateNameToPublicKeyName(certificateName);
-
-    SignatureSha256WithRsa signature;
-    // implicit conversion should take care
-    signature.setKeyLocator(certificateName.getPrefix(-1));
-
-    // For temporary usage, we support RSA + SHA256 only, but will support more.
-    signature.setValue(Tpm::signInTpm(buffer, bufferLength, keyName, DIGEST_ALGORITHM_SHA256));
-    return signature;
-  }
+  sign(const uint8_t* buffer, size_t bufferLength, const Name& certificateName);
 
   /**
    * @brief Sign packet using the default certificate of a particular identity.
@@ -300,24 +163,7 @@
    */
   template<typename T>
   void
-  signByIdentity(T& packet, const Name& identityName)
-  {
-    Name signingCertificateName;
-    try
-      {
-        signingCertificateName = Info::getDefaultCertificateNameForIdentity(identityName);
-      }
-    catch (InfoError& e)
-      {
-        signingCertificateName = createIdentity(identityName);
-        // Ideally, no exception will be thrown out, unless something goes wrong in the TPM, which
-        // is a fatal error.
-      }
-
-    // We either get or create the signing certificate, sign packet! (no exception unless fatal
-    // error in TPM)
-    sign(packet, signingCertificateName);
-  }
+  signByIdentity(T& packet, const Name& identityName);
 
   /**
    * @brief Sign the byte array using the default certificate of a particular identity.
@@ -327,43 +173,16 @@
    * @param identityName The identity name.
    * @return The Signature.
    */
-  Signature
-  signByIdentity(const uint8_t* buffer, size_t bufferLength, const Name& identityName)
-  {
-    Name signingCertificateName;
-    try
-      {
-        signingCertificateName = Info::getDefaultCertificateNameForIdentity(identityName);
-      }
-    catch (InfoError& e)
-      {
-        signingCertificateName = createIdentity(identityName);
-        // Ideally, no exception will be thrown out, unless something goes wrong in the TPM, which
-        // is a fatal error.
-      }
-
-    // We either get or create the signing certificate, sign data! (no exception unless fatal error
-    // in TPM)
-    return sign(buffer, bufferLength, signingCertificateName);
-  }
+  inline Signature
+  signByIdentity(const uint8_t* buffer, size_t bufferLength, const Name& identityName);
 
   /**
    * @brief Set Sha256 weak signature.
    *
    * @param data.
    */
-  void
-  signWithSha256(Data& data)
-  {
-    SignatureSha256 sig;
-    data.setSignature(sig);
-
-    Block sigValue(Tlv::SignatureValue,
-                   crypto::sha256(data.wireEncode().value(),
-                                  data.wireEncode().value_size() -
-                                  data.getSignature().getValue().size()));
-    data.setSignatureValue(sigValue);
-  }
+  inline void
+  signWithSha256(Data& data);
 
   /**
    * @brief Generate a self-signed certificate for a public key.
@@ -372,33 +191,7 @@
    * @return The generated certificate, NULL if selfSign fails.
    */
   shared_ptr<IdentityCertificate>
-  selfSign(const Name& keyName)
-  {
-    shared_ptr<PublicKey> pubKey;
-    try
-      {
-        pubKey = Info::getPublicKey(keyName); // may throw an exception.
-      }
-    catch (InfoError& e)
-      {
-        return shared_ptr<IdentityCertificate>();
-      }
-
-    shared_ptr<IdentityCertificate> certificate = make_shared<IdentityCertificate>();
-
-    Name certificateName = keyName.getPrefix(-1);
-    certificateName.append("KEY").append(keyName.get(-1)).append("ID-CERT").appendVersion();
-
-    certificate->setName(certificateName);
-    certificate->setNotBefore(time::system_clock::now());
-    certificate->setNotAfter(time::system_clock::now() + time::days(7300)/* ~20 years*/);
-    certificate->setPublicKeyInfo(*pubKey);
-    certificate->addSubjectDescription(CertificateSubjectDescription("2.5.4.41", keyName.toUri()));
-    certificate->encode();
-
-    selfSign(*certificate);
-    return certificate;
-  }
+  selfSign(const Name& keyName);
 
   /**
    * @brief Self-sign the supplied identity certificate.
@@ -407,18 +200,7 @@
    * @throws SecTpm::Error if the private key does not exist.
    */
   void
-  selfSign (IdentityCertificate& cert)
-  {
-    Name keyName = IdentityCertificate::certificateNameToPublicKeyName(cert.getName());
-    if (!Tpm::doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE))
-      throw TpmError("private key does not exist!");
-
-    SignatureSha256WithRsa signature;
-    signature.setKeyLocator(cert.getName().getPrefix(-1)); // implicit conversion should take care
-
-    // For temporary usage, we support RSA + SHA256 only, but will support more.
-    signPacketWrapper(cert, signature, keyName, DIGEST_ALGORITHM_SHA256);
-  }
+  selfSign(IdentityCertificate& cert);
 
   /**
    * @brief delete a certificate.
@@ -428,21 +210,8 @@
    *
    * @param certificateName The certificate to be deleted.
    */
-  void
-  deleteCertificate (const Name& certificateName)
-  {
-    try
-      {
-        if (Info::getDefaultCertificateName() == certificateName)
-          return;
-      }
-    catch (InfoError& e)
-      {
-        // Not a real error, just try to delete the certificate
-      }
-
-    Info::deleteCertificateInfo(certificateName);
-  }
+  inline void
+  deleteCertificate(const Name& certificateName);
 
   /**
    * @brief delete a key.
@@ -452,22 +221,8 @@
    *
    * @param keyName The key to be deleted.
    */
-  void
-  deleteKey (const Name& keyName)
-  {
-    try
-      {
-        if (Info::getDefaultKeyNameForIdentity(Info::getDefaultIdentity()) == keyName)
-          return;
-      }
-    catch (InfoError& e)
-      {
-        // Not a real error, just try to delete the key
-      }
-
-    Info::deletePublicKeyInfo(keyName);
-    Tpm::deleteKeyPairInTpm(keyName);
-  }
+  inline void
+  deleteKey(const Name& keyName);
 
   /**
    * @brief delete an identity.
@@ -477,29 +232,8 @@
    *
    * @param identity The identity to be deleted.
    */
-  void
-  deleteIdentity (const Name& identity)
-  {
-    try
-      {
-        if (Info::getDefaultIdentity() == identity)
-          return;
-      }
-    catch (InfoError& e)
-      {
-        // Not a real error, just try to delete the identity
-      }
-
-    std::vector<Name> nameList;
-    Info::getAllKeyNamesOfIdentity(identity, nameList, true);
-    Info::getAllKeyNamesOfIdentity(identity, nameList, false);
-
-    Info::deleteIdentityInfo(identity);
-
-    std::vector<Name>::const_iterator it = nameList.begin();
-    for(; it != nameList.end(); it++)
-      Tpm::deleteKeyPairInTpm(*it);
-  }
+  inline void
+  deleteIdentity(const Name& identity);
 
   /**
    * @brief export an identity.
@@ -507,42 +241,10 @@
    * @param identity The identity to export.
    * @param passwordStr The password to secure the private key.
    * @return The encoded export data.
-   * @throws InfoError if anything goes wrong in exporting.
+   * @throws SecPublicInfo::Error if anything goes wrong in exporting.
    */
   shared_ptr<SecuredBag>
-  exportIdentity(const Name& identity, const std::string& passwordStr)
-  {
-    if (!Info::doesIdentityExist(identity))
-      throw InfoError("Identity does not exist!");
-
-    Name keyName = Info::getDefaultKeyNameForIdentity(identity);
-
-    ConstBufferPtr pkcs5;
-    try
-      {
-        pkcs5 = Tpm::exportPrivateKeyPkcs5FromTpm(keyName, passwordStr);
-      }
-    catch (TpmError& e)
-      {
-        throw InfoError("Fail to export PKCS5 of private key");
-      }
-
-    shared_ptr<IdentityCertificate> cert;
-    try
-      {
-        cert = Info::getCertificate(Info::getDefaultCertificateNameForKey(keyName));
-      }
-    catch (InfoError& e)
-      {
-        cert = selfSign(keyName);
-        Info::addCertificateAsIdentityDefault(*cert);
-      }
-
-    shared_ptr<SecuredBag> secureBag = make_shared<SecuredBag>(boost::cref(*cert),
-                                                               boost::cref(pkcs5));
-
-    return secureBag;
-  }
+  exportIdentity(const Name& identity, const std::string& passwordStr);
 
   /**
    * @brief import an identity.
@@ -551,48 +253,349 @@
    * @param passwordStr The password to secure the private key.
    */
   void
-  importIdentity(const SecuredBag& securedBag, const std::string& passwordStr)
+  importIdentity(const SecuredBag& securedBag, const std::string& passwordStr);
+
+  SecPublicInfo&
+  getPib()
   {
-    Name certificateName = securedBag.getCertificate().getName();
-    Name keyName = IdentityCertificate::certificateNameToPublicKeyName(certificateName);
-    Name identity = keyName.getPrefix(-1);
-
-    // Add identity
-    Info::addIdentity(identity);
-
-    // Add key
-    Tpm::importPrivateKeyPkcs5IntoTpm(keyName,
-                                      securedBag.getKey()->buf(),
-                                      securedBag.getKey()->size(),
-                                      passwordStr);
-
-    shared_ptr<PublicKey> pubKey = Tpm::getPublicKeyFromTpm(keyName.toUri());
-    // HACK! We should set key type according to the pkcs8 info.
-    Info::addPublicKey(keyName, KEY_TYPE_RSA, *pubKey);
-    Info::setDefaultKeyNameForIdentity(keyName);
-
-    // Add cert
-    Info::addCertificateAsIdentityDefault(securedBag.getCertificate());
+    return *m_pib;
   }
 
+  const SecPublicInfo&
+  getPib() const
+  {
+    return *m_pib;
+  }
+
+  SecTpm&
+  getTpm()
+  {
+    return *m_tpm;
+  }
+
+  const SecTpm&
+  getTpm() const
+  {
+    return *m_tpm;
+  }
+
+  /*******************************
+   *  Wrapper of SecPublicInfo   *
+   *******************************/
+  bool
+  doesIdentityExist(const Name& identityName) const
+  {
+    return m_pib->doesIdentityExist(identityName);
+  }
+
+  void
+  addIdentity(const Name& identityName)
+  {
+    return m_pib->addIdentity(identityName);
+  }
+
+  bool
+  doesPublicKeyExist(const Name& keyName) const
+  {
+    return m_pib->doesPublicKeyExist(keyName);
+  }
+
+  void
+  addPublicKey(const Name& keyName, KeyType keyType, const PublicKey& publicKeyDer)
+  {
+    return m_pib->addPublicKey(keyName, keyType, publicKeyDer);
+  }
+
+  shared_ptr<PublicKey>
+  getPublicKey(const Name& keyName) const
+  {
+    return m_pib->getPublicKey(keyName);
+  }
+
+  bool
+  doesCertificateExist(const Name& certificateName) const
+  {
+    return m_pib->doesCertificateExist(certificateName);
+  }
+
+  void
+  addCertificate(const IdentityCertificate& certificate)
+  {
+    return m_pib->addCertificate(certificate);
+  }
+
+  shared_ptr<IdentityCertificate>
+  getCertificate(const Name& certificateName) const
+  {
+    return m_pib->getCertificate(certificateName);
+  }
+
+  Name
+  getDefaultIdentity() const
+  {
+    return m_pib->getDefaultIdentity();
+  }
+
+  Name
+  getDefaultKeyNameForIdentity(const Name& identityName) const
+  {
+    return m_pib->getDefaultKeyNameForIdentity(identityName);
+  }
+
+  Name
+  getDefaultCertificateNameForKey(const Name& keyName) const
+  {
+    return m_pib->getDefaultCertificateNameForKey(keyName);
+  }
+
+  void
+  getAllIdentities(std::vector<Name>& nameList, bool isDefault) const
+  {
+    return m_pib->getAllIdentities(nameList, isDefault);
+  }
+
+  void
+  getAllKeyNames(std::vector<Name>& nameList, bool isDefault) const
+  {
+    return m_pib->getAllKeyNames(nameList, isDefault);
+  }
+
+  void
+  getAllKeyNamesOfIdentity(const Name& identity, std::vector<Name>& nameList, bool isDefault) const
+  {
+    return m_pib->getAllKeyNamesOfIdentity(identity, nameList, isDefault);
+  }
+
+  void
+  getAllCertificateNames(std::vector<Name>& nameList, bool isDefault) const
+  {
+    return m_pib->getAllCertificateNames(nameList, isDefault);
+  }
+
+  void
+  getAllCertificateNamesOfKey(const Name& keyName,
+                              std::vector<Name>& nameList,
+                              bool isDefault) const
+  {
+    return m_pib->getAllCertificateNamesOfKey(keyName, nameList, isDefault);
+  }
+
+  void
+  deleteCertificateInfo(const Name& certificateName)
+  {
+    return m_pib->deleteCertificateInfo(certificateName);
+  }
+
+  void
+  deletePublicKeyInfo(const Name& keyName)
+  {
+    return m_pib->deletePublicKeyInfo(keyName);
+  }
+
+  void
+  deleteIdentityInfo(const Name& identity)
+  {
+    return m_pib->deleteIdentityInfo(identity);
+  }
+
+  void
+  setDefaultIdentity(const Name& identityName)
+  {
+    return m_pib->setDefaultIdentity(identityName);
+  }
+
+  void
+  setDefaultKeyNameForIdentity(const Name& keyName)
+  {
+    return m_pib->setDefaultKeyNameForIdentity(keyName);
+  }
+
+  void
+  setDefaultCertificateNameForKey(const Name& certificateName)
+  {
+    return m_pib->setDefaultCertificateNameForKey(certificateName);
+  }
+
+  Name
+  getNewKeyName(const Name& identityName, bool useKsk)
+  {
+    return m_pib->getNewKeyName(identityName, useKsk);
+  }
+
+  Name
+  getDefaultCertificateNameForIdentity(const Name& identityName) const
+  {
+    return m_pib->getDefaultCertificateNameForIdentity(identityName);
+  }
+
+  Name
+  getDefaultCertificateName() const
+  {
+    return m_pib->getDefaultCertificateName();
+  }
+
+  void
+  addCertificateAsKeyDefault(const IdentityCertificate& certificate)
+  {
+    return m_pib->addCertificateAsKeyDefault(certificate);
+  }
+
+  void
+  addCertificateAsIdentityDefault(const IdentityCertificate& certificate)
+  {
+    return m_pib->addCertificateAsIdentityDefault(certificate);
+  }
+
+  void
+  addCertificateAsSystemDefault(const IdentityCertificate& certificate)
+  {
+    return m_pib->addCertificateAsSystemDefault(certificate);
+  }
+
+  shared_ptr<IdentityCertificate>
+  getDefaultCertificate() const
+  {
+    return m_pib->defaultCertificate();
+  }
+
+  void
+  refreshDefaultCertificate()
+  {
+    return m_pib->refreshDefaultCertificate();
+  }
+
+  /*******************************
+   *  Wrapper of SecTpm          *
+   *******************************/
+
+  void
+  setTpmPassword(const uint8_t* password, size_t passwordLength)
+  {
+    return m_tpm->setTpmPassword(password, passwordLength);
+  }
+
+  void
+  resetTpmPassword()
+  {
+    return m_tpm->resetTpmPassword();
+  }
+
+  void
+  setInTerminal(bool inTerminal)
+  {
+    return m_tpm->setInTerminal(inTerminal);
+  }
+
+  bool
+  getInTerminal() const
+  {
+    return m_tpm->getInTerminal();
+  }
+
+  bool
+  isLocked() const
+  {
+    return m_tpm->isLocked();
+  }
+
+  bool
+  unlockTpm(const char* password, size_t passwordLength, bool usePassword)
+  {
+    return m_tpm->unlockTpm(password, passwordLength, usePassword);
+  }
+
+  void
+  generateKeyPairInTpm(const Name& keyName, KeyType keyType, int keySize)
+  {
+    return m_tpm->generateKeyPairInTpm(keyName, keyType, keySize);
+  }
+
+  void
+  deleteKeyPairInTpm(const Name& keyName)
+  {
+    return m_tpm->deleteKeyPairInTpm(keyName);
+  }
+
+  shared_ptr<PublicKey>
+  getPublicKeyFromTpm(const Name& keyName) const
+  {
+    return m_tpm->getPublicKeyFromTpm(keyName);
+  }
+
+  Block
+  signInTpm(const uint8_t* data, size_t dataLength,
+            const Name& keyName,
+            DigestAlgorithm digestAlgorithm)
+  {
+    return m_tpm->signInTpm(data, dataLength, keyName, digestAlgorithm);
+  }
+
+  ConstBufferPtr
+  decryptInTpm(const uint8_t* data, size_t dataLength, const Name& keyName, bool isSymmetric)
+  {
+    return m_tpm->decryptInTpm(data, dataLength, keyName, isSymmetric);
+  }
+
+  ConstBufferPtr
+  encryptInTpm(const uint8_t* data, size_t dataLength, const Name& keyName, bool isSymmetric)
+  {
+    return m_tpm->encryptInTpm(data, dataLength, keyName, isSymmetric);
+  }
+
+  void
+  generateSymmetricKeyInTpm(const Name& keyName, KeyType keyType, int keySize)
+  {
+    return m_tpm->generateSymmetricKeyInTpm(keyName, keyType, keySize);
+  }
+
+  bool
+  doesKeyExistInTpm(const Name& keyName, KeyClass keyClass) const
+  {
+    return m_tpm->doesKeyExistInTpm(keyName, keyClass);
+  }
+
+  bool
+  generateRandomBlock(uint8_t* res, size_t size) const
+  {
+    return m_tpm->generateRandomBlock(res, size);
+  }
+
+  void
+  addAppToAcl(const Name& keyName, KeyClass keyClass, const std::string& appPath, AclType acl)
+  {
+    return m_tpm->addAppToAcl(keyName, keyClass, appPath, acl);
+  }
+
+  ConstBufferPtr
+  exportPrivateKeyPkcs5FromTpm(const Name& keyName, const std::string& password)
+  {
+    return m_tpm->exportPrivateKeyPkcs5FromTpm(keyName, password);
+  }
+
+  bool
+  importPrivateKeyPkcs5IntoTpm(const Name& keyName,
+                               const uint8_t* buf, size_t size,
+                               const std::string& password)
+  {
+    return m_tpm->importPrivateKeyPkcs5IntoTpm(keyName, buf, size, password);
+  }
 
 private:
   /**
-   * @brief sign a packet using a pariticular certificate.
+   * @brief Set default certificate if it is not initialized
+   */
+  void
+  setDefaultCertificateInternal();
+
+  /**
+   * @brief Sign a packet using a pariticular certificate.
    *
    * @param packet The packet to be signed.
    * @param certificate The signing certificate.
    */
   template<typename T>
   void
-  sign(T& packet, const IdentityCertificate& certificate)
-  {
-    SignatureSha256WithRsa signature;
-    signature.setKeyLocator(certificate.getName().getPrefix(-1));
-
-    // For temporary usage, we support RSA + SHA256 only, but will support more.
-    signPacketWrapper(packet, signature, certificate.getPublicKeyName(), DIGEST_ALGORITHM_SHA256);
-  }
+  sign(T& packet, const IdentityCertificate& certificate);
 
   /**
    * @brief Generate a key pair for the specified identity.
@@ -603,19 +606,9 @@
    * @param keySize The size of the key pair.
    * @return The name of the generated key.
    */
-  Name
+  inline Name
   generateKeyPair(const Name& identityName, bool isKsk = false,
-                  KeyType keyType = KEY_TYPE_RSA, int keySize = 2048)
-  {
-    Name keyName = Info::getNewKeyName(identityName, isKsk);
-
-    Tpm::generateKeyPairInTpm(keyName.toUri(), keyType, keySize);
-
-    shared_ptr<PublicKey> pubKey = Tpm::getPublicKeyFromTpm(keyName.toUri());
-    Info::addPublicKey(keyName, keyType, *pubKey);
-
-    return keyName;
-  }
+                  KeyType keyType = KEY_TYPE_RSA, int keySize = 2048);
 
   /**
    * @brief Sign the data using a particular key.
@@ -626,16 +619,9 @@
    * @param digestAlgorithm the digest algorithm.
    * @throws Tpm::Error
    */
-  void
+  inline void
   signPacketWrapper(Data& data, const SignatureSha256WithRsa& signature,
-                    const Name& keyName, DigestAlgorithm digestAlgorithm)
-  {
-    data.setSignature(signature);
-    data.setSignatureValue(Tpm::signInTpm(data.wireEncode().value(),
-                                          data.wireEncode().value_size() -
-                                          data.getSignature().getValue().size(),
-                                          keyName, digestAlgorithm));
-  }
+                    const Name& keyName, DigestAlgorithm digestAlgorithm);
 
   /**
    * @brief Sign the interest using a particular key.
@@ -646,44 +632,260 @@
    * @param digestAlgorithm the digest algorithm.
    * @throws Tpm::Error
    */
-  void
+  inline void
   signPacketWrapper(Interest& interest, const SignatureSha256WithRsa& signature,
-                    const Name& keyName, DigestAlgorithm digestAlgorithm)
-  {
-    Name signedName = interest.getName();
-    signedName.append(signature.getInfo());
+                    const Name& keyName, DigestAlgorithm digestAlgorithm);
 
-    Block sigValue = Tpm::signInTpm(signedName.wireEncode().value(),
+
+private:
+  SecPublicInfo* m_pib;
+  SecTpm* m_tpm;
+};
+
+template<class T>
+inline
+KeyChain::KeyChain(T)
+  : m_pib(new typename T::Pib)
+  , m_tpm(new typename T::Tpm)
+{
+}
+
+inline Name
+KeyChain::createIdentity(const Name& identityName)
+{
+  m_pib->addIdentity(identityName);
+
+  Name keyName;
+  try
+    {
+      keyName = m_pib->getDefaultKeyNameForIdentity(identityName);
+    }
+  catch (SecPublicInfo::Error& e)
+    {
+      keyName = generateRsaKeyPairAsDefault(identityName, true);
+    }
+
+  Name certName;
+  try
+    {
+      certName = m_pib->getDefaultCertificateNameForKey(keyName);
+    }
+  catch (SecPublicInfo::Error& e)
+    {
+      shared_ptr<IdentityCertificate> selfCert = selfSign(keyName);
+      m_pib->addCertificateAsIdentityDefault(*selfCert);
+      certName = selfCert->getName();
+    }
+
+  return certName;
+}
+
+inline Name
+KeyChain::generateRsaKeyPair(const Name& identityName, bool isKsk, int keySize)
+{
+  return generateKeyPair(identityName, isKsk, KEY_TYPE_RSA, keySize);
+}
+
+inline Name
+KeyChain::generateRsaKeyPairAsDefault(const Name& identityName, bool isKsk, int keySize)
+{
+  Name keyName = generateKeyPair(identityName, isKsk, KEY_TYPE_RSA, keySize);
+
+  m_pib->setDefaultKeyNameForIdentity(keyName);
+
+  return keyName;
+}
+
+template<typename T>
+void
+KeyChain::sign(T& packet)
+{
+  if (!static_cast<bool>(m_pib->defaultCertificate()))
+    setDefaultCertificateInternal();
+
+  sign(packet, *m_pib->defaultCertificate());
+}
+
+template<typename T>
+void
+KeyChain::sign(T& packet, const Name& certificateName)
+{
+  if (!m_pib->doesCertificateExist(certificateName))
+    throw SecPublicInfo::Error("Requested certificate [" +
+                               certificateName.toUri() + "] doesn't exist");
+
+  SignatureSha256WithRsa signature;
+  // implicit conversion should take care
+  signature.setKeyLocator(certificateName.getPrefix(-1));
+
+  // For temporary usage, we support RSA + SHA256 only, but will support more.
+  signPacketWrapper(packet, signature,
+                    IdentityCertificate::certificateNameToPublicKeyName(certificateName),
+                    DIGEST_ALGORITHM_SHA256);
+}
+
+template<typename T>
+void
+KeyChain::signByIdentity(T& packet, const Name& identityName)
+{
+  Name signingCertificateName;
+  try
+    {
+      signingCertificateName = m_pib->getDefaultCertificateNameForIdentity(identityName);
+    }
+  catch (SecPublicInfo::Error& e)
+    {
+      signingCertificateName = createIdentity(identityName);
+      // Ideally, no exception will be thrown out, unless something goes wrong in the TPM, which
+      // is a fatal error.
+    }
+
+  // We either get or create the signing certificate, sign packet! (no exception unless fatal
+  // error in TPM)
+  sign(packet, signingCertificateName);
+}
+
+inline Signature
+KeyChain::signByIdentity(const uint8_t* buffer, size_t bufferLength, const Name& identityName)
+{
+  Name signingCertificateName;
+  try
+    {
+      signingCertificateName = m_pib->getDefaultCertificateNameForIdentity(identityName);
+    }
+  catch (SecPublicInfo::Error& e)
+    {
+      signingCertificateName = createIdentity(identityName);
+      // Ideally, no exception will be thrown out, unless something goes wrong in the TPM, which
+      // is a fatal error.
+    }
+
+  // We either get or create the signing certificate, sign data! (no exception unless fatal error
+  // in TPM)
+  return sign(buffer, bufferLength, signingCertificateName);
+}
+
+inline void
+KeyChain::signWithSha256(Data& data)
+{
+  SignatureSha256 sig;
+  data.setSignature(sig);
+
+  Block sigValue(Tlv::SignatureValue,
+                 crypto::sha256(data.wireEncode().value(),
+                                data.wireEncode().value_size() -
+                                data.getSignature().getValue().size()));
+  data.setSignatureValue(sigValue);
+}
+
+inline void
+KeyChain::deleteCertificate(const Name& certificateName)
+{
+  try
+    {
+      if (m_pib->getDefaultCertificateName() == certificateName)
+        return;
+    }
+  catch (SecPublicInfo::Error& e)
+    {
+      // Not a real error, just try to delete the certificate
+    }
+
+  m_pib->deleteCertificateInfo(certificateName);
+}
+
+inline void
+KeyChain::deleteKey(const Name& keyName)
+{
+  try
+    {
+      if (m_pib->getDefaultKeyNameForIdentity(m_pib->getDefaultIdentity()) == keyName)
+        return;
+    }
+  catch (SecPublicInfo::Error& e)
+    {
+      // Not a real error, just try to delete the key
+    }
+
+  m_pib->deletePublicKeyInfo(keyName);
+  m_tpm->deleteKeyPairInTpm(keyName);
+}
+
+inline void
+KeyChain::deleteIdentity(const Name& identity)
+{
+  try
+    {
+      if (m_pib->getDefaultIdentity() == identity)
+        return;
+    }
+  catch (SecPublicInfo::Error& e)
+    {
+      // Not a real error, just try to delete the identity
+    }
+
+  std::vector<Name> nameList;
+  m_pib->getAllKeyNamesOfIdentity(identity, nameList, true);
+  m_pib->getAllKeyNamesOfIdentity(identity, nameList, false);
+
+  m_pib->deleteIdentityInfo(identity);
+
+  std::vector<Name>::const_iterator it = nameList.begin();
+  for(; it != nameList.end(); it++)
+    m_tpm->deleteKeyPairInTpm(*it);
+}
+
+template<typename T>
+void
+KeyChain::sign(T& packet, const IdentityCertificate& certificate)
+{
+  SignatureSha256WithRsa signature;
+  signature.setKeyLocator(certificate.getName().getPrefix(-1));
+
+  // For temporary usage, we support RSA + SHA256 only, but will support more.
+  signPacketWrapper(packet, signature, certificate.getPublicKeyName(), DIGEST_ALGORITHM_SHA256);
+}
+
+inline Name
+KeyChain::generateKeyPair(const Name& identityName, bool isKsk, KeyType keyType, int keySize)
+{
+  Name keyName = m_pib->getNewKeyName(identityName, isKsk);
+
+  m_tpm->generateKeyPairInTpm(keyName.toUri(), keyType, keySize);
+
+  shared_ptr<PublicKey> pubKey = m_tpm->getPublicKeyFromTpm(keyName.toUri());
+  m_pib->addPublicKey(keyName, keyType, *pubKey);
+
+  return keyName;
+}
+
+inline void
+KeyChain::signPacketWrapper(Data& data, const SignatureSha256WithRsa& signature,
+                            const Name& keyName, DigestAlgorithm digestAlgorithm)
+{
+  data.setSignature(signature);
+  data.setSignatureValue(m_tpm->signInTpm(data.wireEncode().value(),
+                                          data.wireEncode().value_size() -
+                                          data.getSignature().getValue().size(),
+                                          keyName, digestAlgorithm));
+}
+
+inline void
+KeyChain::signPacketWrapper(Interest& interest, const SignatureSha256WithRsa& signature,
+                            const Name& keyName, DigestAlgorithm digestAlgorithm)
+{
+  Name signedName = interest.getName();
+  signedName.append(signature.getInfo());
+
+  Block sigValue = m_tpm->signInTpm(signedName.wireEncode().value(),
                                     signedName.wireEncode().value_size(),
                                     keyName,
                                     DIGEST_ALGORITHM_SHA256);
-    sigValue.encode();
-    signedName.append(sigValue);
-    interest.setName(signedName);
-  }
+  sigValue.encode();
+  signedName.append(sigValue);
+  interest.setName(signedName);
+}
 
-};
-
-} // namespace ndn
-
-
-
-#if defined(NDN_CXX_HAVE_OSX_SECURITY) and defined(NDN_CXX_WITH_OSX_KEYCHAIN)
-
-namespace ndn {
-
-typedef KeyChainImpl<SecPublicInfoSqlite3, SecTpmOsx> KeyChain;
-
-} // namespace ndn
-
-#else
-
-namespace ndn {
-
-typedef KeyChainImpl<SecPublicInfoSqlite3, SecTpmFile> KeyChain;
-
-} // namespace ndn
-
-#endif // NDN_CXX_HAVE_OSX_SECURITY
+}
 
 #endif // NDN_SECURITY_KEY_CHAIN_HPP
diff --git a/src/security/sec-public-info-sqlite3.hpp b/src/security/sec-public-info-sqlite3.hpp
index 3e9f3b7..c11ac44 100644
--- a/src/security/sec-public-info-sqlite3.hpp
+++ b/src/security/sec-public-info-sqlite3.hpp
@@ -97,6 +97,15 @@
   virtual void
   getAllCertificateNamesOfKey(const Name& keyName, std::vector<Name>& nameList, bool isDefault);
 
+  virtual void
+  deleteCertificateInfo(const Name& certificateName);
+
+  virtual void
+  deletePublicKeyInfo(const Name& keyName);
+
+  virtual void
+  deleteIdentityInfo(const Name& identity);
+
 protected:
   virtual void
   setDefaultIdentityInternal(const Name& identityName);
@@ -107,15 +116,6 @@
   virtual void
   setDefaultCertificateNameForKeyInternal(const Name& certificateName);
 
-  virtual void
-  deleteCertificateInfo(const Name& certificateName);
-
-  virtual void
-  deletePublicKeyInfo(const Name& keyName);
-
-  virtual void
-  deleteIdentityInfo(const Name& identity);
-
 private:
   sqlite3 * m_database;
 };
diff --git a/src/security/sec-public-info.hpp b/src/security/sec-public-info.hpp
index f8f2e09..790ad36 100644
--- a/src/security/sec-public-info.hpp
+++ b/src/security/sec-public-info.hpp
@@ -30,7 +30,7 @@
  * It specify interfaces related to public information, such as identity, public keys and
  * certificates.
  */
-class SecPublicInfo
+class SecPublicInfo : noncopyable
 {
 public:
   class Error : public std::runtime_error
@@ -47,7 +47,9 @@
    * @brief The virtual Destructor.
    */
   virtual
-  ~SecPublicInfo() {}
+  ~SecPublicInfo()
+  {
+  }
 
   /**
    * @brief Check if the specified identity already exists.
@@ -215,6 +217,34 @@
   virtual void
   getAllCertificateNamesOfKey(const Name& keyName, std::vector<Name>& nameList, bool isDefault) = 0;
 
+  /*****************************************
+   *            Delete Methods             *
+   *****************************************/
+
+  /**
+   * @brief Delete a certificate.
+   *
+   * @param certificateName The certificate name.
+   */
+  virtual void
+  deleteCertificateInfo(const Name& certificateName) = 0;
+
+  /**
+   * @brief Delete a public key and related certificates.
+   *
+   * @param keyName The key name.
+   */
+  virtual void
+  deletePublicKeyInfo(const Name& keyName) = 0;
+
+  /**
+   * @brief Delete an identity and related public keys and certificates.
+   *
+   * @param identity The identity name.
+   */
+  virtual void
+  deleteIdentityInfo(const Name& identity) = 0;
+
 protected:
 
   /*****************************************
@@ -247,34 +277,6 @@
   virtual void
   setDefaultCertificateNameForKeyInternal(const Name& certificateName) = 0;
 
-  /*****************************************
-   *            Delete Methods             *
-   *****************************************/
-
-  /**
-   * @brief Delete a certificate.
-   *
-   * @param certificateName The certificate name.
-   */
-  virtual void
-  deleteCertificateInfo(const Name& certificateName) = 0;
-
-  /**
-   * @brief Delete a public key and related certificates.
-   *
-   * @param keyName The key name.
-   */
-  virtual void
-  deletePublicKeyInfo(const Name& keyName) = 0;
-
-  /**
-   * @brief Delete an identity and related public keys and certificates.
-   *
-   * @param identity The identity name.
-   */
-  virtual void
-  deleteIdentityInfo(const Name& identity) = 0;
-
 public:
 
   /*****************************************
diff --git a/src/security/sec-tpm-file.hpp b/src/security/sec-tpm-file.hpp
index 4b8496e..0f1d8be 100644
--- a/src/security/sec-tpm-file.hpp
+++ b/src/security/sec-tpm-file.hpp
@@ -66,7 +66,7 @@
   }
 
   virtual bool
-  locked()
+  isLocked()
   {
     return false;
   }
@@ -74,7 +74,7 @@
   virtual bool
   unlockTpm(const char* password, size_t passwordLength, bool usePassword)
   {
-    return !locked();
+    return !isLocked();
   }
 
   virtual void
@@ -106,7 +106,7 @@
   generateRandomBlock(uint8_t* res, size_t size);
 
   virtual void
-  addAppToACL(const Name& keyName, KeyClass keyClass, const std::string& appPath, AclType acl)
+  addAppToAcl(const Name& keyName, KeyClass keyClass, const std::string& appPath, AclType acl)
   {
   }
 
diff --git a/src/security/sec-tpm-memory.hpp b/src/security/sec-tpm-memory.hpp
index eac75ed..df0c7e3 100644
--- a/src/security/sec-tpm-memory.hpp
+++ b/src/security/sec-tpm-memory.hpp
@@ -70,15 +70,15 @@
   }
 
   virtual bool
-  locked()
+  isLocked()
   {
-    return true;
+    return false;
   }
 
   virtual bool
   unlockTpm(const char* password, size_t passwordLength, bool usePassword)
   {
-    return !locked();
+    return !isLocked();
   }
 
   virtual void
@@ -110,7 +110,7 @@
   generateRandomBlock(uint8_t* res, size_t size);
 
   virtual void
-  addAppToACL(const Name& keyName, KeyClass keyClass, const std::string& appPath, AclType acl)
+  addAppToAcl(const Name& keyName, KeyClass keyClass, const std::string& appPath, AclType acl)
   {
   }
 
diff --git a/src/security/sec-tpm-osx.cpp b/src/security/sec-tpm-osx.cpp
index 2dbe928..5132c3d 100644
--- a/src/security/sec-tpm-osx.cpp
+++ b/src/security/sec-tpm-osx.cpp
@@ -15,8 +15,7 @@
 #include "common.hpp"
 
 #include "sec-tpm-osx.hpp"
-
-#include "security/public-key.hpp"
+#include "public-key.hpp"
 #include "cryptopp.hpp"
 
 #include <pwd.h>
@@ -172,7 +171,7 @@
 }
 
 bool
-SecTpmOsx::locked()
+SecTpmOsx::isLocked()
 {
   SecKeychainStatus keychainStatus;
 
@@ -189,7 +188,7 @@
   OSStatus res;
 
   // If the default key chain is already unlocked, return immediately.
-  if (!locked())
+  if (!isLocked())
     return true;
 
   // If the default key chain is locked, unlock the key chain.
@@ -212,11 +211,11 @@
   else if (m_impl->m_inTerminal)
     {
       // If no configured password, get password from terminal if inTerminal set.
-      bool locked = true;
+      bool isLocked = true;
       const char* fmt = "Password to unlock the default keychain: ";
       int count = 0;
 
-      while(locked)
+      while (isLocked)
         {
           if (count > 2)
             break;
@@ -245,7 +244,7 @@
       SecKeychainUnlock(m_impl->m_keyChainRef, 0, 0, false);
     }
 
-  return !locked();
+  return !isLocked();
 }
 
 void
@@ -711,7 +710,7 @@
 }
 
 void
-SecTpmOsx::addAppToACL(const Name& keyName, KeyClass keyClass, const string& appPath, AclType acl)
+SecTpmOsx::addAppToAcl(const Name& keyName, KeyClass keyClass, const string& appPath, AclType acl)
 {
   if (keyClass == KEY_CLASS_PRIVATE && acl == ACL_TYPE_PRIVATE)
     {
diff --git a/src/security/sec-tpm-osx.hpp b/src/security/sec-tpm-osx.hpp
index 664b978..f7d9959 100644
--- a/src/security/sec-tpm-osx.hpp
+++ b/src/security/sec-tpm-osx.hpp
@@ -16,6 +16,11 @@
 #define NDN_SECURITY_SEC_TPM_OSX_HPP
 
 #include "../common.hpp"
+
+#ifndef NDN_CXX_HAVE_OSX_SECURITY
+#error "This files should not be compiled ..."
+#endif
+
 #include "sec-tpm.hpp"
 
 namespace ndn {
@@ -56,7 +61,7 @@
   getInTerminal();
 
   virtual bool
-  locked();
+  isLocked();
 
   virtual bool
   unlockTpm(const char* password, size_t passwordLength, bool usePassword);
@@ -99,7 +104,7 @@
   generateRandomBlock(uint8_t* res, size_t size);
 
   virtual void
-  addAppToACL(const Name& keyName, KeyClass keyClass, const std::string& appPath, AclType acl);
+  addAppToAcl(const Name& keyName, KeyClass keyClass, const std::string& appPath, AclType acl);
 
 protected:
   /******************************
diff --git a/src/security/sec-tpm.hpp b/src/security/sec-tpm.hpp
index b6ea71e..5a163c6 100644
--- a/src/security/sec-tpm.hpp
+++ b/src/security/sec-tpm.hpp
@@ -28,7 +28,7 @@
  *
  * It specifies the interfaces of private/secret key related operations.
  */
-class SecTpm
+class SecTpm : noncopyable
 {
 public:
   class Error : public std::runtime_error
@@ -42,7 +42,9 @@
   };
 
   virtual
-  ~SecTpm() {}
+  ~SecTpm()
+  {
+  }
 
   /**
    * @brief set password of TPM
@@ -88,7 +90,7 @@
    * @return true if locked, false otherwise
    */
   virtual bool
-  locked() = 0;
+  isLocked() = 0;
 
   /**
    * @brief Unlock the TPM.
@@ -211,7 +213,7 @@
    * @param acl the new acl of the key
    */
   virtual void
-  addAppToACL(const Name& keyName, KeyClass keyClass, const std::string& appPath, AclType acl) = 0;
+  addAppToAcl(const Name& keyName, KeyClass keyClass, const std::string& appPath, AclType acl) = 0;
 
   /**
    * @brief Export a private key in PKCS#5 format.
diff --git a/src/util/config-file.cpp b/src/util/config-file.cpp
index 162cf60..6ba45aa 100644
--- a/src/util/config-file.cpp
+++ b/src/util/config-file.cpp
@@ -40,9 +40,21 @@
 {
   using namespace boost::filesystem;
 
-  path home(std::getenv("HOME"));
-  if (!home.empty())
+#ifdef NDN_CXX_HAVE_TESTS
+  if (std::getenv("TEST_HOME"))
     {
+      path testHome(std::getenv("TEST_HOME"));
+      testHome /= ".ndn/client.conf";
+      if (exists(testHome))
+        {
+          return absolute(testHome);
+        }
+    }
+#endif // NDN_CXX_HAVE_TESTS
+
+  if (std::getenv("HOME"))
+    {
+      path home(std::getenv("HOME"));
       home /= ".ndn/client.conf";
       if (exists(home))
         {