security: Construct KeyChain from configuration file.

Change-Id: Iaddac24e2c4e199fdde83fa1d0067a87e18729c4
Refs: #1532
diff --git a/client.conf.sample b/client.conf.sample
index 7e31b04..9dc8605 100644
--- a/client.conf.sample
+++ b/client.conf.sample
@@ -7,4 +7,19 @@
 ;   nrd-0.1
 ;   ndnd-tlv-0.7
 ;   ndnx-0.7
-protocol=nrd-0.1
\ No newline at end of file
+protocol=nrd-0.1
+
+; "pib" determines which Public Info Base (PIB) should used by default in applications.
+; If "pib" is not specified, the default PIB will be used.
+; Note that default PIB could be different on different system.
+; If "pib" is specified, it may have a value of:
+;   sqlite3
+; pib=sqlite3
+
+; "tpm" determines which Trusted Platform Module (TPM) should used by default in applications.
+; If "tpm" is not specified, the default TPM will be used.
+; Note that default TPM could be different on different system.
+; If "tpm" is specified, it may have a value of:
+;   file
+;   osx-keychain
+; tpm=file
\ No newline at end of file
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))
         {
diff --git a/tests-integrated/security/test-validator-config.cpp b/tests-integrated/security/test-validator-config.cpp
index a192c6c..6a7ffd9 100644
--- a/tests-integrated/security/test-validator-config.cpp
+++ b/tests-integrated/security/test-validator-config.cpp
@@ -559,7 +559,7 @@
 
 
   Name sld("/TestValidatorConfig/HierarchicalChecker");
-  Name sldKeyName = keyChain.generateRSAKeyPairAsDefault(sld, true);
+  Name sldKeyName = keyChain.generateRsaKeyPairAsDefault(sld, true);
   shared_ptr<IdentityCertificate> sldCert =
     keyChain.prepareUnsignedIdentityCertificate(sldKeyName,
                                                 root,
@@ -570,7 +570,7 @@
   keyChain.addCertificateAsIdentityDefault(*sldCert);
 
   Name nld("/TestValidatorConfig/HierarchicalChecker/NextLevel");
-  Name nldKeyName = keyChain.generateRSAKeyPairAsDefault(nld, true);
+  Name nldKeyName = keyChain.generateRsaKeyPairAsDefault(nld, true);
   shared_ptr<IdentityCertificate> nldCert =
     keyChain.prepareUnsignedIdentityCertificate(nldKeyName,
                                                 sld,
@@ -764,7 +764,7 @@
 
 
   Name sld("/TestValidatorConfig/Nrd-1");
-  Name sldKeyName = keyChain.generateRSAKeyPairAsDefault(sld, true);
+  Name sldKeyName = keyChain.generateRsaKeyPairAsDefault(sld, true);
   shared_ptr<IdentityCertificate> sldCert =
     keyChain.prepareUnsignedIdentityCertificate(sldKeyName,
                                                 root,
@@ -775,7 +775,7 @@
   keyChain.addCertificateAsIdentityDefault(*sldCert);
 
   Name nld("/TestValidatorConfig/Nrd-1/Nrd-2");
-  Name nldKeyName = keyChain.generateRSAKeyPairAsDefault(nld, true);
+  Name nldKeyName = keyChain.generateRsaKeyPairAsDefault(nld, true);
   shared_ptr<IdentityCertificate> nldCert =
     keyChain.prepareUnsignedIdentityCertificate(nldKeyName,
                                                 sld,
diff --git a/tests/security/config-file-empty-home/.ndn/client.conf b/tests/security/config-file-empty-home/.ndn/client.conf
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/security/config-file-empty-home/.ndn/client.conf
diff --git a/tests/security/config-file-home/.ndn/client.conf b/tests/security/config-file-home/.ndn/client.conf
new file mode 100644
index 0000000..cc05409
--- /dev/null
+++ b/tests/security/config-file-home/.ndn/client.conf
@@ -0,0 +1,2 @@
+pib=sqlite3
+tpm=file
\ No newline at end of file
diff --git a/tests/security/config-file-malformed-home/.ndn/client.conf b/tests/security/config-file-malformed-home/.ndn/client.conf
new file mode 100644
index 0000000..4ed6728
--- /dev/null
+++ b/tests/security/config-file-malformed-home/.ndn/client.conf
@@ -0,0 +1,2 @@
+pib=lord
+tpm=ring
diff --git a/tests/security/config-file-malformed2-home/.ndn/client.conf b/tests/security/config-file-malformed2-home/.ndn/client.conf
new file mode 100644
index 0000000..3f7795d
--- /dev/null
+++ b/tests/security/config-file-malformed2-home/.ndn/client.conf
@@ -0,0 +1,2 @@
+pib=sqlite3
+tpm=just-wrong
diff --git a/tests/security/test-keychain.cpp b/tests/security/test-keychain.cpp
index 01c9502..214aa9a 100644
--- a/tests/security/test-keychain.cpp
+++ b/tests/security/test-keychain.cpp
@@ -11,18 +11,88 @@
  */
 
 #include "security/key-chain.hpp"
+#include <boost/filesystem.hpp>
 
 #include "boost-test.hpp"
 
 using namespace std;
 
 namespace ndn {
+namespace tests {
 
-BOOST_AUTO_TEST_SUITE(SecurityTestKeyChain)
-
-BOOST_AUTO_TEST_CASE (ExportIdentity)
+class KeychainConfigFileFixture
 {
-  KeyChainImpl<SecPublicInfoSqlite3, SecTpmFile> keyChain;
+public:
+  KeychainConfigFileFixture()
+  {
+    if (std::getenv("TEST_HOME"))
+      m_HOME = std::getenv("TEST_HOME");
+  }
+
+  ~KeychainConfigFileFixture()
+  {
+    if (!m_HOME.empty())
+      setenv("TEST_HOME", m_HOME.c_str(), 1);
+    else
+      unsetenv("TEST_HOME");
+  }
+
+protected:
+  std::string m_HOME;
+};
+
+BOOST_FIXTURE_TEST_SUITE(SecurityTestKeyChain, KeychainConfigFileFixture)
+
+BOOST_AUTO_TEST_CASE(ConstructorNormalConfig)
+{
+  using namespace boost::filesystem;
+
+  setenv("TEST_HOME", "tests/security/config-file-home", 1);
+
+  BOOST_REQUIRE_NO_THROW(KeyChain());
+
+  path pibPath(absolute(std::getenv("TEST_HOME")));
+  pibPath /= ".ndn/ndnsec-public-info.db";
+
+  boost::filesystem::remove(pibPath);
+}
+
+BOOST_AUTO_TEST_CASE(ConstructorEmptyConfig)
+{
+  using namespace boost::filesystem;
+
+  setenv("TEST_HOME", "tests/security/config-file-empty-home", 1);
+
+  BOOST_REQUIRE_NO_THROW(KeyChain());
+
+  path pibPath(absolute(std::getenv("TEST_HOME")));
+  pibPath /= ".ndn/ndnsec-public-info.db";
+
+  boost::filesystem::remove(pibPath);
+}
+
+BOOST_AUTO_TEST_CASE(ConstructorMalConfig)
+{
+  using namespace boost::filesystem;
+
+  setenv("TEST_HOME", "tests/security/config-file-malformed-home", 1);
+
+  BOOST_REQUIRE_THROW(KeyChain(), KeyChain::Error); // Wrong configuration. Error expected.
+}
+
+BOOST_AUTO_TEST_CASE(ConstructorMal2Config)
+{
+  using namespace boost::filesystem;
+
+  setenv("TEST_HOME", "tests/security/config-file-malformed2-home", 1);
+
+  BOOST_REQUIRE_THROW(KeyChain(), KeyChain::Error); // Wrong configuration. Error expected.
+}
+
+BOOST_AUTO_TEST_CASE(ExportIdentity)
+{
+  BOOST_REQUIRE_NO_THROW(KeyChain("sqlite3", "file"));
+  KeyChain keyChain("sqlite3", "file");
 
   Name identity("/TestKeyChain/ExportIdentity/");
   identity.appendVersion();
@@ -62,9 +132,10 @@
   BOOST_REQUIRE(keyChain.doesCertificateExist(certName) == false);
 }
 
-BOOST_AUTO_TEST_CASE (PrepareIdentityCertificate)
+BOOST_AUTO_TEST_CASE(PrepareIdentityCertificate)
 {
-  KeyChainImpl<SecPublicInfoSqlite3, SecTpmFile> keyChain;
+  BOOST_REQUIRE_NO_THROW(KeyChain("sqlite3", "file"));
+  KeyChain keyChain("sqlite3", "file");
 
   Name identity("/TestKeyChain/PrepareIdentityCertificate/");
   identity.appendVersion();
@@ -73,24 +144,25 @@
   vector<CertificateSubjectDescription> subjectDescription;
   Name lowerIdentity = identity;
   lowerIdentity.append("Lower").appendVersion();
-  Name lowerKeyName = keyChain.generateRSAKeyPair(lowerIdentity, true);
+  Name lowerKeyName = keyChain.generateRsaKeyPair(lowerIdentity, true);
   shared_ptr<IdentityCertificate> idCert
     = keyChain.prepareUnsignedIdentityCertificate(lowerKeyName, identity,
-						  time::system_clock::now(),
-						  time::system_clock::now() + time::days(365),
-						  subjectDescription);
+                                                  time::system_clock::now(),
+                                                  time::system_clock::now() + time::days(365),
+                                                  subjectDescription);
   BOOST_CHECK(static_cast<bool>(idCert));
-  BOOST_CHECK(idCert->getName().getPrefix(5) == Name().append(identity).append("KEY").append("Lower"));
+  BOOST_CHECK(idCert->getName().getPrefix(5) ==
+              Name().append(identity).append("KEY").append("Lower"));
 
 
   Name anotherIdentity("/TestKeyChain/PrepareIdentityCertificate/Another/");
   anotherIdentity.appendVersion();
-  Name anotherKeyName = keyChain.generateRSAKeyPair(anotherIdentity, true);
+  Name anotherKeyName = keyChain.generateRsaKeyPair(anotherIdentity, true);
   shared_ptr<IdentityCertificate> idCert2
     = keyChain.prepareUnsignedIdentityCertificate(anotherKeyName, identity,
-						  time::system_clock::now(),
-						  time::system_clock::now() + time::days(365),
-						  subjectDescription);
+                                                  time::system_clock::now(),
+                                                  time::system_clock::now() + time::days(365),
+                                                  subjectDescription);
   BOOST_CHECK(static_cast<bool>(idCert2));
   BOOST_CHECK(idCert2->getName().getPrefix(5) == Name().append(anotherIdentity).append("KEY"));
 
@@ -98,27 +170,27 @@
   Name wrongKeyName1;
   shared_ptr<IdentityCertificate> idCert3
     = keyChain.prepareUnsignedIdentityCertificate(wrongKeyName1, identity,
-						  time::system_clock::now(),
-						  time::system_clock::now() + time::days(365),
-						  subjectDescription);
+                                                  time::system_clock::now(),
+                                                  time::system_clock::now() + time::days(365),
+                                                  subjectDescription);
   BOOST_CHECK(!static_cast<bool>(idCert3));
 
 
   Name wrongKeyName2("/TestKeyChain/PrepareIdentityCertificate");
   shared_ptr<IdentityCertificate> idCert4
     = keyChain.prepareUnsignedIdentityCertificate(wrongKeyName2, identity,
-						  time::system_clock::now(),
-						  time::system_clock::now() + time::days(365),
-						  subjectDescription);
+                                                  time::system_clock::now(),
+                                                  time::system_clock::now() + time::days(365),
+                                                  subjectDescription);
   BOOST_CHECK(!static_cast<bool>(idCert4));
 
 
   Name wrongKeyName3("/TestKeyChain/PrepareIdentityCertificate/ksk-1234");
   shared_ptr<IdentityCertificate> idCert5
     = keyChain.prepareUnsignedIdentityCertificate(wrongKeyName3, identity,
-						  time::system_clock::now(),
-						  time::system_clock::now() + time::days(365),
-						  subjectDescription);
+                                                  time::system_clock::now(),
+                                                  time::system_clock::now() + time::days(365),
+                                                  subjectDescription);
   BOOST_CHECK(!static_cast<bool>(idCert5));
 
   keyChain.deleteIdentity(identity);
@@ -128,4 +200,5 @@
 
 BOOST_AUTO_TEST_SUITE_END()
 
+} // namespace tests
 } // namespace ndn
diff --git a/tests/security/test-sec-public-info-sqlite3.cpp b/tests/security/test-sec-public-info-sqlite3.cpp
index ae7135b..6215762 100644
--- a/tests/security/test-sec-public-info-sqlite3.cpp
+++ b/tests/security/test-sec-public-info-sqlite3.cpp
@@ -10,6 +10,7 @@
  * ndn-cxx library copyright, permissions, and redistribution restrictions.
  */
 
+#include "security/sec-public-info-sqlite3.hpp"
 #include "security/key-chain.hpp"
 #include "util/time.hpp"
 
@@ -20,9 +21,10 @@
 
 BOOST_AUTO_TEST_SUITE(SecurityTestSecPublicInfoSqlite3)
 
-BOOST_AUTO_TEST_CASE (Delete)
+BOOST_AUTO_TEST_CASE(Delete)
 {
-  KeyChainImpl<SecPublicInfoSqlite3, SecTpmFile> keyChain;
+  BOOST_REQUIRE_NO_THROW(KeyChain("sqlite3", "file"));
+  KeyChain keyChain("sqlite3", "file");
 
   Name identity("/TestSecPublicInfoSqlite3/Delete");
   identity.appendVersion();
@@ -32,7 +34,7 @@
 
   Name keyName1 = IdentityCertificate::certificateNameToPublicKeyName(certName1);
   Name keyName2;
-  BOOST_REQUIRE_NO_THROW(keyName2 = keyChain.generateRSAKeyPairAsDefault(identity));
+  BOOST_REQUIRE_NO_THROW(keyName2 = keyChain.generateRsaKeyPairAsDefault(identity));
 
   shared_ptr<IdentityCertificate> cert2;
   BOOST_REQUIRE_NO_THROW(cert2 = keyChain.selfSign(keyName2));
@@ -40,7 +42,7 @@
   BOOST_REQUIRE_NO_THROW(keyChain.addCertificateAsKeyDefault(*cert2));
 
   Name keyName3;
-  BOOST_REQUIRE_NO_THROW(keyName3 = keyChain.generateRSAKeyPairAsDefault(identity));
+  BOOST_REQUIRE_NO_THROW(keyName3 = keyChain.generateRsaKeyPairAsDefault(identity));
 
   shared_ptr<IdentityCertificate> cert3;
   BOOST_REQUIRE_NO_THROW(cert3 = keyChain.selfSign(keyName3));
diff --git a/tests/security/test-sec-tpm-file.cpp b/tests/security/test-sec-tpm-file.cpp
index 1bf895e..05f1afc 100644
--- a/tests/security/test-sec-tpm-file.cpp
+++ b/tests/security/test-sec-tpm-file.cpp
@@ -10,10 +10,12 @@
  * ndn-cxx library copyright, permissions, and redistribution restrictions.
  */
 
+#include "security/sec-tpm-file.hpp"
 #include "security/key-chain.hpp"
-#include "util/time.hpp"
 #include "security/cryptopp.hpp"
 
+#include "util/time.hpp"
+
 #include "boost-test.hpp"
 
 using namespace std;
diff --git a/tests/security/test-sec-tpm-osx.cpp b/tests/security/test-sec-tpm-osx.cpp
index e8aa9a8..0da4233 100644
--- a/tests/security/test-sec-tpm-osx.cpp
+++ b/tests/security/test-sec-tpm-osx.cpp
@@ -10,10 +10,11 @@
  * ndn-cxx library copyright, permissions, and redistribution restrictions.
  */
 
-#include "security/key-chain.hpp"
-#include "util/time.hpp"
+#include "security/sec-tpm-osx.hpp"
 #include "security/cryptopp.hpp"
 
+#include "util/time.hpp"
+
 #include "boost-test.hpp"
 
 using namespace std;
diff --git a/tests/security/test-signature-sha256.cpp b/tests/security/test-signature-sha256.cpp
index 77e5bae..611ac2e 100644
--- a/tests/security/test-signature-sha256.cpp
+++ b/tests/security/test-signature-sha256.cpp
@@ -45,8 +45,10 @@
   char content[5] = "1234";
   testData.setContent(reinterpret_cast<uint8_t*>(content), 5);
 
-  KeyChainImpl<SecPublicInfoSqlite3, SecTpmFile> keychain;
-  keychain.signWithSha256(testData);
+  BOOST_REQUIRE_NO_THROW(KeyChain("sqlite3", "file"));
+  KeyChain keyChain("sqlite3", "file");
+
+  keyChain.signWithSha256(testData);
 
   testData.wireEncode();
 
diff --git a/tests/security/test-signed-interest.cpp b/tests/security/test-signed-interest.cpp
index 4fd92e1..62cec61 100644
--- a/tests/security/test-signed-interest.cpp
+++ b/tests/security/test-signed-interest.cpp
@@ -23,9 +23,10 @@
 
 BOOST_AUTO_TEST_SUITE(SecurityTestSignedInterest)
 
-BOOST_AUTO_TEST_CASE (SignedInterest)
+BOOST_AUTO_TEST_CASE(SignedInterest)
 {
-  KeyChainImpl<SecPublicInfoSqlite3, SecTpmFile> keyChain;
+  BOOST_REQUIRE_NO_THROW(KeyChain("sqlite3", "file"));
+  KeyChain keyChain("sqlite3", "file");
 
   Name identityName("/TestSignedInterest/SignVerify");
   identityName.appendVersion();
@@ -95,8 +96,8 @@
     make_shared<Interest>("/TestCommandInterest/Validation/Command1");
   generator.generateWithIdentity(*commandInterest1, identity);
   validator.validate(*commandInterest1,
-  		     bind(&CommandInterestFixture::validated, this, _1),
-  		     bind(&CommandInterestFixture::validationFailed, this, _1, _2));
+                     bind(&CommandInterestFixture::validated, this, _1),
+                     bind(&CommandInterestFixture::validationFailed, this, _1, _2));
 
   BOOST_CHECK_EQUAL(m_validity, true);
 
@@ -115,8 +116,8 @@
 
   keyChain.signByIdentity(*commandInterest2, identity);
   validator.validate(*commandInterest2,
-  		     bind(&CommandInterestFixture::validated, this, _1),
-  		     bind(&CommandInterestFixture::validationFailed, this, _1, _2));
+                     bind(&CommandInterestFixture::validated, this, _1),
+                     bind(&CommandInterestFixture::validationFailed, this, _1, _2));
 
   BOOST_CHECK_EQUAL(m_validity, false);
 
@@ -129,8 +130,8 @@
     make_shared<Interest>("/TestCommandInterest/Validation/Command3");
   generator.generateWithIdentity(*commandInterest3, identity2);
   validator.validate(*commandInterest3,
-  		     bind(&CommandInterestFixture::validated, this, _1),
-  		     bind(&CommandInterestFixture::validationFailed, this, _1, _2));
+                     bind(&CommandInterestFixture::validated, this, _1),
+                     bind(&CommandInterestFixture::validationFailed, this, _1, _2));
 
   BOOST_CHECK_EQUAL(m_validity, false);
 
@@ -139,8 +140,8 @@
     make_shared<Interest>("/TestCommandInterest/Validation2/Command");
   generator.generateWithIdentity(*commandInterest4, identity);
   validator.validate(*commandInterest4,
-  		     bind(&CommandInterestFixture::validated, this, _1),
-  		     bind(&CommandInterestFixture::validationFailed, this, _1, _2));
+                     bind(&CommandInterestFixture::validated, this, _1),
+                     bind(&CommandInterestFixture::validationFailed, this, _1, _2));
 
   BOOST_CHECK_EQUAL(m_validity, false);
 
diff --git a/tests/security/test-validator.cpp b/tests/security/test-validator.cpp
index 219fbc4..47ab79a 100644
--- a/tests/security/test-validator.cpp
+++ b/tests/security/test-validator.cpp
@@ -32,9 +32,10 @@
   BOOST_CHECK(false);
 }
 
-BOOST_AUTO_TEST_CASE (Null)
+BOOST_AUTO_TEST_CASE(Null)
 {
-  KeyChainImpl<SecPublicInfoSqlite3, SecTpmFile> keyChain;
+  BOOST_REQUIRE_NO_THROW(KeyChain("sqlite3", "file"));
+  KeyChain keyChain("sqlite3", "file");
 
   Name identity("/TestValidator/Null");
   identity.appendVersion();
diff --git a/tests/transport/test-unix-transport.cpp b/tests/transport/test-unix-transport.cpp
index 7e3d36f..8b74523 100644
--- a/tests/transport/test-unix-transport.cpp
+++ b/tests/transport/test-unix-transport.cpp
@@ -40,6 +40,7 @@
 BOOST_AUTO_TEST_CASE(TestGetDefaultSocketNameOk)
 {
   setenv("HOME", "tests/transport/test-homes/ok", 1);
+
   ConfigFile config;
   BOOST_REQUIRE_EQUAL(UnixTransport::getDefaultSocketName(config), "/tmp/test/nfd.sock");
 }
diff --git a/tests/util/test-config-file.cpp b/tests/util/test-config-file.cpp
index ef05416..b472bb2 100644
--- a/tests/util/test-config-file.cpp
+++ b/tests/util/test-config-file.cpp
@@ -17,6 +17,7 @@
 #include "boost-test.hpp"
 
 namespace ndn {
+namespace tests {
 
 class ConfigFileFixture
 {
@@ -101,4 +102,5 @@
 
 BOOST_AUTO_TEST_SUITE_END()
 
+} // namespace tests
 } // namespace ndn
diff --git a/tests/util/test-io.cpp b/tests/util/test-io.cpp
index ffb9c61..38f3ca1 100644
--- a/tests/util/test-io.cpp
+++ b/tests/util/test-io.cpp
@@ -21,15 +21,16 @@
 
 BOOST_AUTO_TEST_CASE(Basic)
 {
-  KeyChainImpl<SecPublicInfoSqlite3, SecTpmFile> keychain;
+  BOOST_REQUIRE_NO_THROW(KeyChain("sqlite3", "file"));
+  KeyChain keyChain("sqlite3", "file");
 
   Name identity("/TestIO/Basic");
   identity.appendVersion();
 
   Name certName;
-  BOOST_REQUIRE_NO_THROW(certName = keychain.createIdentity(identity));
+  BOOST_REQUIRE_NO_THROW(certName = keyChain.createIdentity(identity));
   shared_ptr<IdentityCertificate> idCert;
-  BOOST_REQUIRE_NO_THROW(idCert = keychain.getCertificate(certName));
+  BOOST_REQUIRE_NO_THROW(idCert = keyChain.getCertificate(certName));
 
   std::string file("/tmp/TestIO-Basic");
   io::save(*idCert, file);
@@ -37,7 +38,7 @@
 
   BOOST_CHECK(static_cast<bool>(readCert));
   BOOST_CHECK(idCert->getName() == readCert->getName());
-  keychain.deleteIdentity(identity);
+  keyChain.deleteIdentity(identity);
 }
 
 BOOST_AUTO_TEST_SUITE_END()
diff --git a/tools/ndnsec-dsk-gen.hpp b/tools/ndnsec-dsk-gen.hpp
index a36a85b..d99ea2b 100644
--- a/tools/ndnsec-dsk-gen.hpp
+++ b/tools/ndnsec-dsk-gen.hpp
@@ -104,7 +104,7 @@
     {
     case 'r':
       {
-        newKeyName = keyChain.generateRSAKeyPair(Name(identityName), false, keySize);
+        newKeyName = keyChain.generateRsaKeyPair(Name(identityName), false, keySize);
         if (0 == newKeyName.size())
           {
             std::cerr << "fail to generate key!" << std::endl;
diff --git a/tools/ndnsec-key-gen.hpp b/tools/ndnsec-key-gen.hpp
index 4781ddf..627af4b 100644
--- a/tools/ndnsec-key-gen.hpp
+++ b/tools/ndnsec-key-gen.hpp
@@ -79,7 +79,7 @@
 
         KeyChain keyChain;
 
-        Name keyName = keyChain.generateRSAKeyPair(Name(identityName), true, keySize);
+        Name keyName = keyChain.generateRsaKeyPair(Name(identityName), true, keySize);
 
         if (0 == keyName.size())
           return 1;
diff --git a/tools/ndnsec-set-acl.hpp b/tools/ndnsec-set-acl.hpp
index a7fc519..9721325 100644
--- a/tools/ndnsec-set-acl.hpp
+++ b/tools/ndnsec-set-acl.hpp
@@ -71,7 +71,7 @@
     }
 
   KeyChain keyChain;
-  keyChain.addAppToACL(keyName, KEY_CLASS_PRIVATE, appPath, ACL_TYPE_PRIVATE);
+  keyChain.addAppToAcl(keyName, KEY_CLASS_PRIVATE, appPath, ACL_TYPE_PRIVATE);
 
   return 0;
 }
diff --git a/wscript b/wscript
index ba5a327..80e74f2 100644
--- a/wscript
+++ b/wscript
@@ -68,6 +68,7 @@
                        'regex', 'program_options', 'chrono']
     if conf.env['WITH_TESTS']:
         USED_BOOST_LIBS += ['unit_test_framework']
+        conf.define('HAVE_TESTS', 1)
 
     conf.check_boost(lib=USED_BOOST_LIBS, mandatory=True)
     if conf.env.BOOST_VERSION_NUMBER < 104800: