security: Move KeyChain to security::v1 namespace and deprecated it

Change-Id: Ic4b6915ca15998a83b410f3f8fac027f797ee7ca
Refs: #3098
diff --git a/tests/unit-tests/security/v1/certificate.t.cpp b/tests/unit-tests/security/v1/certificate.t.cpp
index 043a1fb..5b410c5 100644
--- a/tests/unit-tests/security/v1/certificate.t.cpp
+++ b/tests/unit-tests/security/v1/certificate.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2013-2016 Regents of the University of California.
+ * Copyright (c) 2013-2017 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -22,8 +22,6 @@
 #include "security/v1/certificate.hpp"
 #include "security/v1/public-key.hpp"
 
-#include "security/key-chain.hpp"
-
 #include "security/v1/cryptopp.hpp"
 
 #include "boost-test.hpp"
diff --git a/tests/unit-tests/security/v1/dummy-keychain.cpp b/tests/unit-tests/security/v1/dummy-keychain.cpp
new file mode 100644
index 0000000..21db30c
--- /dev/null
+++ b/tests/unit-tests/security/v1/dummy-keychain.cpp
@@ -0,0 +1,395 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2017 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "dummy-keychain.hpp"
+#include "encoding/buffer-stream.hpp"
+#include "util/io.hpp"
+#include <boost/iostreams/device/array.hpp>
+
+namespace ndn {
+namespace security {
+namespace v1 {
+
+static const uint8_t DUMMY_CERT[] =
+  "Bv0C8Ac4CAVkdW1teQgDa2V5CANLRVkIEWtzay0xNDE4NjAwMzkxMDUwCAdJRC1D"
+  "RVJUCAn9AAABSkssIl4UAxgBAhX9AXMwggFvMCIYDzIwMTQxMjE0MjMzOTUxWhgP"
+  "MjAzNDEyMDkyMzM5NTFaMCUwIwYDVQQpExwvZHVtbXkva2V5L2tzay0xNDE4NjAw"
+  "MzkxMDUwMIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0AMIIBCAKCAQEAxUfhv54Jdgeq"
+  "0wmQ/ru9ew/ByCKcQawaZT9Xm9o/sMahwQ9IbNx2Dz4Jkelaxra7+DI0QP3pYctv"
+  "Ykn/jwq5y3cO0LJQB+kf/7FtSKG9qBEv8aqq5hDVteBUKiyUXqDmQzbe+mTcJ9Yd"
+  "D7siF1dhrjnM3KL1xpcXu3QaV5m/I6cKVwYrJxp3JKr6k5pHhxJlPIyUu7oU3kFW"
+  "7bHq2uq4ec9gBXCKwA64IVYVQm1GVDk+V0wr7pw9qD6QNa7eMzrCME6vfM0deSiU"
+  "a4TovUJDQFDsM287kYm3tZu7iuJzmOC63tl4YZdyqyOgnqSrUGE1soNHfLokI13H"
+  "hSwxok7nuQIBERY0GwEBHC8HLQgFZHVtbXkIA2tleQgDS0VZCBFrc2stMTQxODYw"
+  "MDM5MTA1MAgHSUQtQ0VSVBf9AQBLLJoQt9HE93NI3Mv1JCb3ezBCWMwTDnZA+XQV"
+  "UgVSvISJfU/lo2sne0SfGp4KsUhj206CDpuh3q0Th5gKSJeysy/bv66V2m2G8aDn"
+  "OkJ7Ut+2o/QnFpIMJz+oZf2f9Z0Pchocmkv8y4Fj02t8HCuFO1ekEvOcocZvWbKy"
+  "HX+P0OdefPzSC535/rsNHXTzgPsoV+yb13vrm4wPeqPPBs+scQYneIFKkRkGE5PU"
+  "pkncAMBN6iWgmSA2RcjcbmT6utCjJTqWviX1XPQtHoF/hBGC0D/TtQDgwVGGibXB"
+  "zb+klRHvCC/uUIfjU2HrE705kaw8btPhTP5/PMe8YKkk+hjh";
+
+static const uint8_t DUMMY_SIGNATURE[] =
+  {0x17, 0xfd, 0x01, 0x00, 0x93, 0x15, 0x09, 0x49, 0x79, 0x9e, 0xb7, 0x9c, 0xd3, 0xc1, 0xbf, 0x61,
+   0x89, 0xd5, 0xd9, 0xca, 0xf2, 0xb0, 0x14, 0xae, 0x72, 0x7c, 0x1f, 0x8f, 0xf5, 0xb1, 0x70, 0xd6,
+   0x9b, 0x8f, 0xf8, 0xd7, 0x2d, 0xbc, 0x92, 0x6f, 0x7d, 0x77, 0x96, 0x46, 0xea, 0xd4, 0x7d, 0x90,
+   0xbc, 0x7a, 0xeb, 0xe2, 0x03, 0x93, 0xb1, 0xd2, 0x62, 0xec, 0x9d, 0xff, 0x9c, 0x9c, 0x2a, 0x14,
+   0x7d, 0x23, 0xca, 0x29, 0x3d, 0x15, 0x1a, 0x40, 0x42, 0x2c, 0x59, 0x33, 0x8a, 0xf7, 0xc0, 0x6b,
+   0xc4, 0x9c, 0xf3, 0xc4, 0x99, 0xa4, 0x1a, 0x60, 0xf5, 0x28, 0x7d, 0x4c, 0xef, 0x43, 0x7d, 0xbd,
+   0x7d, 0x00, 0x51, 0xee, 0x41, 0xf5, 0x25, 0x80, 0xce, 0xe6, 0x64, 0x4f, 0x75, 0x54, 0xf3, 0xb2,
+   0x99, 0x9a, 0x0f, 0x93, 0x9a, 0x28, 0x1d, 0xfe, 0x12, 0x8a, 0xe0, 0xc1, 0x02, 0xeb, 0xa4, 0x35,
+   0x52, 0x88, 0xac, 0x44, 0x1a, 0x44, 0x82, 0x97, 0x4f, 0x5f, 0xa8, 0xd8, 0x9f, 0x67, 0x38, 0xa8,
+   0x64, 0xb6, 0x62, 0x99, 0xbd, 0x96, 0x3c, 0xf5, 0x86, 0x09, 0x5c, 0x97, 0x6b, 0x8f, 0xae, 0xe0,
+   0x60, 0xe7, 0x23, 0x98, 0x6a, 0xee, 0xc1, 0xb0, 0x14, 0xbe, 0x46, 0x2c, 0xfb, 0xa7, 0x27, 0x73,
+   0xe4, 0xf3, 0x26, 0x33, 0xba, 0x99, 0xd4, 0x01, 0x38, 0xa8, 0xf2, 0x9e, 0x87, 0xe0, 0x71, 0x0b,
+   0x25, 0x44, 0x07, 0x35, 0x88, 0xab, 0x67, 0x27, 0x56, 0x0e, 0xb5, 0xb5, 0xe8, 0x27, 0xb4, 0x49,
+   0xdc, 0xb8, 0x48, 0x31, 0xff, 0x99, 0x48, 0xab, 0x11, 0xb4, 0xa0, 0xdf, 0x8a, 0x6d, 0xff, 0x43,
+   0x69, 0x32, 0xa7, 0xbc, 0x63, 0x9d, 0x0f, 0xe0, 0x95, 0x34, 0x36, 0x25, 0x4b, 0x3e, 0x36, 0xbd,
+   0x81, 0x91, 0x0b, 0x91, 0x9f, 0x3a, 0x04, 0xa2, 0x44, 0x28, 0x19, 0xa1, 0x38, 0x21, 0x4f, 0x25,
+   0x59, 0x8a, 0x48, 0xc2};
+
+const std::string DummyPublicInfo::SCHEME = "pib-dummy";
+const std::string DummyTpm::SCHEME = "tpm-dummy";
+
+NDN_CXX_V1_KEYCHAIN_REGISTER_PIB(DummyPublicInfo, "pib-dummy", "dummy");
+NDN_CXX_V1_KEYCHAIN_REGISTER_TPM(DummyTpm, "tpm-dummy", "dummy");
+
+typedef DummyPublicInfo DummyPublicInfo2;
+typedef DummyTpm DummyTpm2;
+
+NDN_CXX_V1_KEYCHAIN_REGISTER_PIB(DummyPublicInfo2, "pib-dummy2");
+NDN_CXX_V1_KEYCHAIN_REGISTER_TPM(DummyTpm2, "tpm-dummy2");
+
+DummyPublicInfo::DummyPublicInfo(const std::string& locator)
+  : SecPublicInfo(locator)
+{
+}
+
+bool
+DummyPublicInfo::doesIdentityExist(const Name& identityName)
+{
+  return true;
+}
+
+void
+DummyPublicInfo::addIdentity(const Name& identityName)
+{
+}
+
+bool
+DummyPublicInfo::revokeIdentity()
+{
+  return true;
+}
+
+bool
+DummyPublicInfo::doesPublicKeyExist(const Name& keyName)
+{
+  return true;
+}
+
+void
+DummyPublicInfo::addKey(const Name& keyName, const v1::PublicKey& publicKey)
+{
+}
+
+shared_ptr<v1::PublicKey>
+DummyPublicInfo::getPublicKey(const Name& keyName)
+{
+  static shared_ptr<v1::PublicKey> publicKey = nullptr;
+  if (publicKey == nullptr) {
+    typedef boost::iostreams::stream<boost::iostreams::array_source> ArrayStream;
+    ArrayStream is(reinterpret_cast<const char*>(DUMMY_CERT), sizeof(DUMMY_CERT));
+    auto cert = io::load<v1::IdentityCertificate>(is, io::NO_ENCODING);
+    publicKey = make_shared<v1::PublicKey>(cert->getPublicKeyInfo());
+  }
+
+  return publicKey;
+}
+
+KeyType
+DummyPublicInfo::getPublicKeyType(const Name& keyName)
+{
+  return KeyType::RSA;
+}
+
+bool
+DummyPublicInfo::doesCertificateExist(const Name& certificateName)
+{
+  return true;
+}
+
+void
+DummyPublicInfo::addCertificate(const v1::IdentityCertificate& certificate)
+{
+}
+
+shared_ptr<v1::IdentityCertificate>
+DummyPublicInfo::getCertificate(const Name& certificateName)
+{
+  static shared_ptr<v1::IdentityCertificate> cert = nullptr;
+  if (cert == nullptr) {
+    typedef boost::iostreams::stream<boost::iostreams::array_source> ArrayStream;
+    ArrayStream is(reinterpret_cast<const char*>(DUMMY_CERT), sizeof(DUMMY_CERT));
+    cert = io::load<v1::IdentityCertificate>(is);
+  }
+
+  return cert;
+}
+
+Name
+DummyPublicInfo::getDefaultIdentity()
+{
+  return "/dummy/key";
+}
+
+Name
+DummyPublicInfo::getDefaultKeyNameForIdentity(const Name& identityName)
+{
+  return "/dummy/key/ksk-1418600391050";
+}
+
+Name
+DummyPublicInfo::getDefaultCertificateNameForKey(const Name& keyName)
+{
+  return "/dummy/key/KEY/ksk-1418600391050/ID-CERT/%FD%00%00%01JK%2C%22%5E";
+}
+
+void
+DummyPublicInfo::getAllIdentities(std::vector<Name>& nameList, bool isDefault)
+{
+  if (isDefault) {
+    nameList.push_back("/dummy");
+  }
+}
+
+void
+DummyPublicInfo::getAllKeyNames(std::vector<Name>& nameList, bool isDefault)
+{
+  if (isDefault) {
+    nameList.push_back("/dummy/key/ksk-1418600391050");
+  }
+}
+
+void
+DummyPublicInfo::getAllKeyNamesOfIdentity(const Name& identity, std::vector<Name>& nameList,
+                                          bool isDefault)
+{
+  if (isDefault) {
+    nameList.push_back("/dummy/key/ksk-1418600391050");
+  }
+}
+
+void
+DummyPublicInfo::getAllCertificateNames(std::vector<Name>& nameList, bool isDefault)
+{
+  if (isDefault) {
+    nameList.push_back("/dummy/key/KEY/ksk-1418600391050/ID-CERT/%FD%00%00%01JK%2C%22%5E");
+  }
+}
+
+void
+DummyPublicInfo::getAllCertificateNamesOfKey(const Name& keyName, std::vector<Name>& nameList,
+                                             bool isDefault)
+{
+  if (isDefault) {
+    nameList.push_back("/dummy/key/KEY/ksk-1418600391050/ID-CERT/%FD%00%00%01JK%2C%22%5E");
+  }
+}
+
+void
+DummyPublicInfo::deleteCertificateInfo(const Name& certificateName)
+{
+}
+
+void
+DummyPublicInfo::deletePublicKeyInfo(const Name& keyName)
+{
+}
+
+void
+DummyPublicInfo::deleteIdentityInfo(const Name& identity)
+{
+}
+
+void
+DummyPublicInfo::setDefaultIdentityInternal(const Name& identityName)
+{
+}
+
+void
+DummyPublicInfo::setDefaultKeyNameForIdentityInternal(const Name& keyName)
+{
+}
+
+void
+DummyPublicInfo::setDefaultCertificateNameForKeyInternal(const Name& certificateName)
+{
+}
+
+void
+DummyPublicInfo::setTpmLocator(const std::string& tpmLocator)
+{
+  m_tpmLocator = tpmLocator;
+}
+
+std::string
+DummyPublicInfo::getTpmLocator()
+{
+  return m_tpmLocator;
+}
+
+std::string
+DummyPublicInfo::getScheme()
+{
+  return DummyPublicInfo::SCHEME;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DummyTpm::DummyTpm(const std::string& locator)
+  : SecTpm(locator)
+{
+}
+
+void
+DummyTpm::setTpmPassword(const uint8_t* password, size_t passwordLength)
+{
+}
+
+void
+DummyTpm::resetTpmPassword()
+{
+}
+
+void
+DummyTpm::setInTerminal(bool inTerminal)
+{
+}
+
+bool
+DummyTpm::getInTerminal() const
+{
+  return false;
+}
+
+bool
+DummyTpm::isLocked()
+{
+  return false;
+}
+
+bool
+DummyTpm::unlockTpm(const char* password, size_t passwordLength, bool usePassword)
+{
+  return true;
+}
+
+void
+DummyTpm::generateKeyPairInTpm(const Name& keyName, const KeyParams& params)
+{
+}
+
+void
+DummyTpm::deleteKeyPairInTpm(const Name& keyName)
+{
+}
+
+shared_ptr<v1::PublicKey>
+DummyTpm::getPublicKeyFromTpm(const Name& keyName)
+{
+  return nullptr;
+}
+
+Block
+DummyTpm::signInTpm(const uint8_t* data, size_t dataLength, const Name& keyName,
+                    DigestAlgorithm digestAlgorithm)
+{
+  return Block(DUMMY_SIGNATURE, sizeof(DUMMY_SIGNATURE));
+}
+
+ConstBufferPtr
+DummyTpm::decryptInTpm(const uint8_t* data, size_t dataLength, const Name& keyName,
+                       bool isSymmetric)
+{
+  BOOST_THROW_EXCEPTION(Error("Not supported"));
+}
+
+ConstBufferPtr
+DummyTpm::encryptInTpm(const uint8_t* data, size_t dataLength, const Name& keyName,
+                       bool isSymmetric)
+{
+  BOOST_THROW_EXCEPTION(Error("Not supported"));
+}
+
+void
+DummyTpm::generateSymmetricKeyInTpm(const Name& keyName, const KeyParams& params)
+{
+}
+
+bool
+DummyTpm::doesKeyExistInTpm(const Name& keyName, KeyClass keyClass)
+{
+  return true;
+}
+
+bool
+DummyTpm::generateRandomBlock(uint8_t* res, size_t size)
+{
+  return false;
+}
+
+void
+DummyTpm::addAppToAcl(const Name& keyName, KeyClass keyClass, const std::string& appPath,
+                      AclType acl)
+{
+}
+
+ConstBufferPtr
+DummyTpm::exportPrivateKeyPkcs8FromTpm(const Name& keyName)
+{
+  BOOST_THROW_EXCEPTION(Error("Not supported"));
+}
+
+bool
+DummyTpm::importPrivateKeyPkcs8IntoTpm(const Name& keyName, const uint8_t* buffer,
+                                       size_t bufferSize)
+{
+  return false;
+}
+
+bool
+DummyTpm::importPublicKeyPkcs1IntoTpm(const Name& keyName, const uint8_t* buffer, size_t bufferSize)
+{
+  return false;
+}
+
+std::string
+DummyTpm::getScheme()
+{
+  return DummyTpm::SCHEME;
+}
+
+} // namespace v1
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit-tests/security/v1/dummy-keychain.hpp b/tests/unit-tests/security/v1/dummy-keychain.hpp
new file mode 100644
index 0000000..3fe2101
--- /dev/null
+++ b/tests/unit-tests/security/v1/dummy-keychain.hpp
@@ -0,0 +1,205 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2017 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_TESTS_SECURITY_V1_DUMMY_KEYCHAIN_HPP
+#define NDN_TESTS_SECURITY_V1_DUMMY_KEYCHAIN_HPP
+
+#include "security/v1/key-chain.hpp"
+
+namespace ndn {
+namespace security {
+namespace v1 {
+
+class DummyPublicInfo : public SecPublicInfo
+{
+public:
+  explicit
+  DummyPublicInfo(const std::string& locator);
+
+  virtual bool
+  doesIdentityExist(const Name& identityName);
+
+  virtual void
+  addIdentity(const Name& identityName);
+
+  virtual bool
+  revokeIdentity();
+
+  virtual bool
+  doesPublicKeyExist(const Name& keyName);
+
+  virtual void
+  addKey(const Name& keyName, const v1::PublicKey& publicKey);
+
+  virtual shared_ptr<v1::PublicKey>
+  getPublicKey(const Name& keyName);
+
+  virtual KeyType
+  getPublicKeyType(const Name& keyName);
+
+  virtual bool
+  doesCertificateExist(const Name& certificateName);
+
+  virtual void
+  addCertificate(const v1::IdentityCertificate& certificate);
+
+  virtual shared_ptr<v1::IdentityCertificate>
+  getCertificate(const Name& certificateName);
+
+  virtual Name
+  getDefaultIdentity();
+
+  virtual Name
+  getDefaultKeyNameForIdentity(const Name& identityName);
+
+  virtual Name
+  getDefaultCertificateNameForKey(const Name& keyName);
+
+  virtual void
+  getAllIdentities(std::vector<Name>& nameList, bool isDefault);
+
+  virtual void
+  getAllKeyNames(std::vector<Name>& nameList, bool isDefault);
+
+  virtual void
+  getAllKeyNamesOfIdentity(const Name& identity, std::vector<Name>& nameList, bool isDefault);
+
+  virtual void
+  getAllCertificateNames(std::vector<Name>& nameList, bool isDefault);
+
+  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);
+
+  virtual void
+  setTpmLocator(const std::string& tpmLocator);
+
+  virtual std::string
+  getTpmLocator();
+
+protected:
+  virtual void
+  setDefaultIdentityInternal(const Name& identityName);
+
+  virtual void
+  setDefaultKeyNameForIdentityInternal(const Name& keyName);
+
+  virtual void
+  setDefaultCertificateNameForKeyInternal(const Name& certificateName);
+
+  virtual std::string
+  getScheme();
+
+public:
+  static const std::string SCHEME;
+
+private:
+  std::string m_tpmLocator;
+};
+
+//////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////
+
+class DummyTpm : public SecTpm
+{
+public:
+  explicit
+  DummyTpm(const std::string& locator);
+
+  virtual void
+  setTpmPassword(const uint8_t* password, size_t passwordLength);
+
+  virtual void
+  resetTpmPassword();
+
+  virtual void
+  setInTerminal(bool inTerminal);
+
+  virtual bool
+  getInTerminal() const;
+
+  virtual bool
+  isLocked();
+
+  virtual bool
+  unlockTpm(const char* password, size_t passwordLength, bool usePassword);
+
+  virtual void
+  generateKeyPairInTpm(const Name& keyName, const KeyParams& params);
+
+  virtual void
+  deleteKeyPairInTpm(const Name& keyName);
+
+  virtual shared_ptr<v1::PublicKey>
+  getPublicKeyFromTpm(const Name& keyName);
+
+  virtual Block
+  signInTpm(const uint8_t* data, size_t dataLength, const Name& keyName,
+            DigestAlgorithm digestAlgorithm);
+
+  virtual ConstBufferPtr
+  decryptInTpm(const uint8_t* data, size_t dataLength, const Name& keyName, bool isSymmetric);
+
+  virtual ConstBufferPtr
+  encryptInTpm(const uint8_t* data, size_t dataLength, const Name& keyName, bool isSymmetric);
+
+  virtual void
+  generateSymmetricKeyInTpm(const Name& keyName, const KeyParams& params);
+
+  virtual bool
+  doesKeyExistInTpm(const Name& keyName, KeyClass keyClass);
+
+  virtual bool
+  generateRandomBlock(uint8_t* res, size_t size);
+
+  virtual void
+  addAppToAcl(const Name& keyName, KeyClass keyClass, const std::string& appPath, AclType acl);
+
+  virtual std::string
+  getScheme();
+
+protected:
+  virtual ConstBufferPtr
+  exportPrivateKeyPkcs8FromTpm(const Name& keyName);
+
+  virtual bool
+  importPrivateKeyPkcs8IntoTpm(const Name& keyName, const uint8_t* buffer, size_t bufferSize);
+
+  virtual bool
+  importPublicKeyPkcs1IntoTpm(const Name& keyName, const uint8_t* buffer, size_t bufferSize);
+
+public:
+  static const std::string SCHEME;
+};
+
+} // namespace v1
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_TESTS_SECURITY_V1_DUMMY_KEYCHAIN_HPP
diff --git a/tests/unit-tests/security/v1/key-chain.t.cpp b/tests/unit-tests/security/v1/key-chain.t.cpp
new file mode 100644
index 0000000..6130cae
--- /dev/null
+++ b/tests/unit-tests/security/v1/key-chain.t.cpp
@@ -0,0 +1,430 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2017 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/v1/key-chain.hpp"
+#include "security/validator.hpp"
+#include "security/signing-helpers.hpp"
+
+#include "boost-test.hpp"
+#include "dummy-keychain.hpp"
+#include "../../test-home-env-saver.hpp"
+#include "key-chain-fixture.hpp"
+#include "identity-management-fixture.hpp"
+
+#include <boost/algorithm/string.hpp>
+#include <boost/filesystem.hpp>
+#include <cstdlib>
+
+namespace ndn {
+namespace security {
+namespace v1 {
+namespace tests {
+
+using namespace ndn::tests;
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(V1)
+BOOST_FIXTURE_TEST_SUITE(TestKeyChain, TestHomeEnvSaver)
+
+template<class Path>
+class TestHomeAndPibFixture : public TestHomeFixture<Path>
+{
+public:
+  TestHomeAndPibFixture()
+  {
+    unsetenv("NDN_CLIENT_PIB");
+    unsetenv("NDN_CLIENT_TPM");
+  }
+};
+
+struct PibPathSqlite3File
+{
+  const std::string PATH = "build/keys-sqlite3-file/";
+};
+
+BOOST_FIXTURE_TEST_CASE(ConstructorNormalConfig, TestHomeAndPibFixture<PibPathSqlite3File>)
+{
+  createClientConf({"pib=pib-sqlite3:%PATH%", "tpm=tpm-file:%PATH%"});
+
+  BOOST_REQUIRE_NO_THROW(KeyChain());
+
+  KeyChain keyChain;
+  BOOST_CHECK_EQUAL(keyChain.getPib().getPibLocator(), "pib-sqlite3:" + m_pibDir);
+  BOOST_CHECK_EQUAL(keyChain.getPib().getTpmLocator(), "tpm-file:" + m_pibDir);
+  BOOST_CHECK_EQUAL(keyChain.getTpm().getTpmLocator(), "tpm-file:" + m_pibDir);
+}
+
+struct PibPathSqlite3Empty
+{
+  const std::string PATH = "build/keys-sqlite3-empty/";
+};
+
+BOOST_FIXTURE_TEST_CASE(ConstructorEmptyConfig, TestHomeAndPibFixture<PibPathSqlite3Empty>)
+{
+  createClientConf({"pib=pib-sqlite3:%PATH%"});
+
+#if defined(NDN_CXX_HAVE_OSX_SECURITY)
+  std::string oldHOME;
+  if (std::getenv("OLD_HOME"))
+    oldHOME = std::getenv("OLD_HOME");
+
+  std::string HOME;
+  if (std::getenv("HOME"))
+    HOME = std::getenv("HOME");
+
+  if (!oldHOME.empty())
+    setenv("HOME", oldHOME.c_str(), true);
+  else
+    unsetenv("HOME");
+#endif
+
+  BOOST_REQUIRE_NO_THROW(KeyChain());
+  KeyChain keyChain;
+  BOOST_CHECK_EQUAL(keyChain.getPib().getPibLocator(), "pib-sqlite3:" + m_pibDir);
+
+#if defined(NDN_CXX_HAVE_OSX_SECURITY)
+  BOOST_CHECK_EQUAL(keyChain.getPib().getTpmLocator(), "tpm-osxkeychain:");
+  BOOST_CHECK_EQUAL(keyChain.getTpm().getTpmLocator(), "tpm-osxkeychain:");
+#else
+  BOOST_CHECK_EQUAL(keyChain.getPib().getTpmLocator(), "tpm-file:");
+  BOOST_CHECK_EQUAL(keyChain.getTpm().getTpmLocator(), "tpm-file:");
+#endif
+
+#if defined(NDN_CXX_HAVE_OSX_SECURITY)
+  if (!HOME.empty())
+    setenv("HOME", HOME.c_str(), true);
+  else
+    unsetenv("HOME");
+#endif
+}
+
+struct PibPathEmptyFile
+{
+  const std::string PATH = "build/keys-empty-file/";
+};
+
+BOOST_FIXTURE_TEST_CASE(ConstructorEmpty2Config, TestHomeAndPibFixture<PibPathEmptyFile>)
+{
+  createClientConf({"tpm=tpm-file:%PATH%"});
+
+  BOOST_REQUIRE_NO_THROW(KeyChain());
+
+  KeyChain keyChain;
+  BOOST_CHECK_EQUAL(keyChain.getPib().getPibLocator(), "pib-sqlite3:");
+  BOOST_CHECK_EQUAL(keyChain.getPib().getTpmLocator(), "tpm-file:" + m_pibDir);
+  BOOST_CHECK_EQUAL(keyChain.getTpm().getTpmLocator(), "tpm-file:" + m_pibDir);
+}
+
+BOOST_FIXTURE_TEST_CASE(ConstructorMalConfig, TestHomeAndPibFixture<DefaultPibDir>)
+{
+  createClientConf({"pib=lord", "tpm=ring"});
+
+  BOOST_REQUIRE_THROW(KeyChain(), KeyChain::Error); // Wrong configuration. Error expected.
+}
+
+BOOST_FIXTURE_TEST_CASE(ConstructorMal2Config, TestHomeAndPibFixture<DefaultPibDir>)
+{
+  createClientConf({"pib=pib-sqlite3:%PATH%", "tpm=just-wrong"});
+  BOOST_REQUIRE_THROW(KeyChain(), KeyChain::Error); // Wrong configuration. Error expected.
+}
+
+BOOST_FIXTURE_TEST_CASE(ExportIdentity, IdentityManagementFixture)
+{
+  Name identity("/TestKeyChain/ExportIdentity/");
+  identity.appendVersion();
+  addIdentity(identity);
+
+  shared_ptr<SecuredBag> exported = m_keyChain.exportIdentity(identity, "1234");
+
+  Block block = exported->wireEncode();
+
+  Name keyName = m_keyChain.getDefaultKeyNameForIdentity(identity);
+  Name certName = m_keyChain.getDefaultCertificateNameForKey(keyName);
+
+  m_keyChain.deleteIdentity(identity);
+
+  BOOST_CHECK_EQUAL(m_keyChain.doesIdentityExist(identity), false);
+  BOOST_CHECK_EQUAL(m_keyChain.doesPublicKeyExist(keyName), false);
+  BOOST_CHECK_EQUAL(m_keyChain.doesKeyExistInTpm(keyName, KeyClass::PRIVATE), false);
+  BOOST_CHECK_EQUAL(m_keyChain.doesKeyExistInTpm(keyName, KeyClass::PUBLIC), false);
+  BOOST_CHECK_EQUAL(m_keyChain.doesCertificateExist(certName), false);
+
+  SecuredBag imported;
+  imported.wireDecode(block);
+  m_keyChain.importIdentity(imported, "1234");
+
+  BOOST_CHECK(m_keyChain.doesIdentityExist(identity));
+  BOOST_CHECK(m_keyChain.doesPublicKeyExist(keyName));
+  BOOST_CHECK(m_keyChain.doesKeyExistInTpm(keyName, KeyClass::PRIVATE));
+  BOOST_CHECK(m_keyChain.doesKeyExistInTpm(keyName, KeyClass::PUBLIC));
+  BOOST_CHECK(m_keyChain.doesCertificateExist(certName));
+}
+
+BOOST_FIXTURE_TEST_CASE(PrepareIdentityCertificate, IdentityManagementFixture)
+{
+  Name identity("/TestKeyChain/PrepareIdentityCertificate/");
+  identity.appendVersion();
+  addIdentity(identity);
+
+  std::vector<v1::CertificateSubjectDescription> subjectDescription;
+  Name lowerIdentity = identity;
+  lowerIdentity.append("Lower").appendVersion();
+  Name lowerKeyName = m_keyChain.generateRsaKeyPair(lowerIdentity, true);
+  shared_ptr<v1::IdentityCertificate> idCert =
+    m_keyChain.prepareUnsignedIdentityCertificate(lowerKeyName, identity,
+                                                  time::system_clock::now(),
+                                                  time::system_clock::now() + time::days(365),
+                                                  subjectDescription);
+  BOOST_CHECK(static_cast<bool>(idCert));
+  BOOST_CHECK_EQUAL(idCert->getName().getPrefix(5),
+                    Name().append(identity).append("KEY").append("Lower"));
+  BOOST_CHECK(idCert->getFreshnessPeriod() >= time::milliseconds::zero());
+
+  shared_ptr<v1::IdentityCertificate> idCert11 =
+    m_keyChain.prepareUnsignedIdentityCertificate(lowerKeyName, identity,
+                                                  time::system_clock::now(),
+                                                  time::system_clock::now() + time::days(365),
+                                                  subjectDescription,
+                                                  lowerIdentity);
+  BOOST_CHECK(static_cast<bool>(idCert11));
+  BOOST_CHECK_EQUAL(idCert11->getName().getPrefix(6),
+              Name().append(lowerIdentity).append("KEY"));
+
+  Name anotherIdentity("/TestKeyChain/PrepareIdentityCertificate/Another/");
+  anotherIdentity.appendVersion();
+  Name anotherKeyName = m_keyChain.generateRsaKeyPair(anotherIdentity, true);
+  shared_ptr<v1::IdentityCertificate> idCert2 =
+    m_keyChain.prepareUnsignedIdentityCertificate(anotherKeyName, identity,
+                                                  time::system_clock::now(),
+                                                  time::system_clock::now() + time::days(365),
+                                                  subjectDescription);
+  BOOST_CHECK(static_cast<bool>(idCert2));
+  BOOST_CHECK_EQUAL(idCert2->getName().getPrefix(5), Name().append(anotherIdentity).append("KEY"));
+
+
+  Name wrongKeyName1;
+  shared_ptr<v1::IdentityCertificate> idCert3 =
+    m_keyChain.prepareUnsignedIdentityCertificate(wrongKeyName1, identity,
+                                                  time::system_clock::now(),
+                                                  time::system_clock::now() + time::days(365),
+                                                  subjectDescription);
+  BOOST_CHECK_EQUAL(static_cast<bool>(idCert3), false);
+
+
+  Name wrongKeyName2("/TestKeyChain/PrepareIdentityCertificate");
+  shared_ptr<v1::IdentityCertificate> idCert4 =
+    m_keyChain.prepareUnsignedIdentityCertificate(wrongKeyName2, identity,
+                                                  time::system_clock::now(),
+                                                  time::system_clock::now() + time::days(365),
+                                                  subjectDescription);
+  BOOST_CHECK_EQUAL(static_cast<bool>(idCert4), false);
+
+
+  Name wrongKeyName3("/TestKeyChain/PrepareIdentityCertificate/ksk-1234");
+  shared_ptr<v1::IdentityCertificate> idCert5 =
+    m_keyChain.prepareUnsignedIdentityCertificate(wrongKeyName3, identity,
+                                                  time::system_clock::now(),
+                                                  time::system_clock::now() + time::days(365),
+                                                  subjectDescription);
+  BOOST_CHECK_EQUAL(static_cast<bool>(idCert5), false);
+}
+
+BOOST_FIXTURE_TEST_CASE(Delete, IdentityManagementFixture)
+{
+  Name identity("/TestSecPublicInfoSqlite3/Delete");
+  identity.appendVersion();
+
+  Name certName1;
+  BOOST_REQUIRE_NO_THROW(certName1 = m_keyChain.createIdentity(identity));
+
+  Name keyName1 = v1::IdentityCertificate::certificateNameToPublicKeyName(certName1);
+  Name keyName2;
+  BOOST_REQUIRE_NO_THROW(keyName2 = m_keyChain.generateRsaKeyPairAsDefault(identity));
+
+  shared_ptr<v1::IdentityCertificate> cert2;
+  BOOST_REQUIRE_NO_THROW(cert2 = m_keyChain.selfSign(keyName2));
+  Name certName2 = cert2->getName();
+  BOOST_REQUIRE_NO_THROW(m_keyChain.addCertificateAsKeyDefault(*cert2));
+
+  Name keyName3;
+  BOOST_REQUIRE_NO_THROW(keyName3 = m_keyChain.generateRsaKeyPairAsDefault(identity));
+
+  shared_ptr<v1::IdentityCertificate> cert3;
+  BOOST_REQUIRE_NO_THROW(cert3 = m_keyChain.selfSign(keyName3));
+  Name certName3 = cert3->getName();
+  BOOST_REQUIRE_NO_THROW(m_keyChain.addCertificateAsKeyDefault(*cert3));
+  shared_ptr<v1::IdentityCertificate> cert4;
+  BOOST_REQUIRE_NO_THROW(cert4 = m_keyChain.selfSign(keyName3));
+  Name certName4 = cert4->getName();
+  BOOST_REQUIRE_NO_THROW(m_keyChain.addCertificateAsKeyDefault(*cert4));
+  shared_ptr<v1::IdentityCertificate> cert5;
+  BOOST_REQUIRE_NO_THROW(cert5 = m_keyChain.selfSign(keyName3));
+  Name certName5 = cert5->getName();
+  BOOST_REQUIRE_NO_THROW(m_keyChain.addCertificateAsKeyDefault(*cert5));
+
+  BOOST_CHECK_EQUAL(m_keyChain.doesIdentityExist(identity), true);
+  BOOST_CHECK_EQUAL(m_keyChain.doesPublicKeyExist(keyName1), true);
+  BOOST_CHECK_EQUAL(m_keyChain.doesPublicKeyExist(keyName2), true);
+  BOOST_CHECK_EQUAL(m_keyChain.doesPublicKeyExist(keyName3), true);
+  BOOST_CHECK_EQUAL(m_keyChain.doesCertificateExist(certName1), true);
+  BOOST_CHECK_EQUAL(m_keyChain.doesCertificateExist(certName2), true);
+  BOOST_CHECK_EQUAL(m_keyChain.doesCertificateExist(certName3), true);
+  BOOST_CHECK_EQUAL(m_keyChain.doesCertificateExist(certName4), true);
+  BOOST_CHECK_EQUAL(m_keyChain.doesCertificateExist(certName5), true);
+
+  BOOST_REQUIRE_NO_THROW(m_keyChain.deleteCertificate(certName5));
+  BOOST_CHECK_EQUAL(m_keyChain.doesCertificateExist(certName5), false);
+  BOOST_CHECK_EQUAL(m_keyChain.doesCertificateExist(certName3), true);
+  BOOST_CHECK_EQUAL(m_keyChain.doesCertificateExist(certName4), true);
+  BOOST_CHECK_EQUAL(m_keyChain.doesPublicKeyExist(keyName3), true);
+
+  BOOST_REQUIRE_NO_THROW(m_keyChain.deleteKey(keyName3));
+  BOOST_CHECK_EQUAL(m_keyChain.doesCertificateExist(certName4), false);
+  BOOST_CHECK_EQUAL(m_keyChain.doesCertificateExist(certName3), false);
+  BOOST_CHECK_EQUAL(m_keyChain.doesPublicKeyExist(keyName3), false);
+  BOOST_CHECK_EQUAL(m_keyChain.doesPublicKeyExist(keyName2), true);
+  BOOST_CHECK_EQUAL(m_keyChain.doesPublicKeyExist(keyName1), true);
+  BOOST_CHECK_EQUAL(m_keyChain.doesIdentityExist(identity), true);
+
+  BOOST_REQUIRE_NO_THROW(m_keyChain.deleteIdentity(identity));
+  BOOST_CHECK_EQUAL(m_keyChain.doesCertificateExist(certName2), false);
+  BOOST_CHECK_EQUAL(m_keyChain.doesPublicKeyExist(keyName2), false);
+  BOOST_CHECK_EQUAL(m_keyChain.doesCertificateExist(certName1), false);
+  BOOST_CHECK_EQUAL(m_keyChain.doesPublicKeyExist(keyName1), false);
+  BOOST_CHECK_EQUAL(m_keyChain.doesIdentityExist(identity), false);
+}
+
+BOOST_AUTO_TEST_CASE(KeyChainWithCustomTpmAndPib)
+{
+  BOOST_REQUIRE_NO_THROW((KeyChain("pib-dummy", "tpm-dummy")));
+  BOOST_REQUIRE_NO_THROW((KeyChain("pib-dummy2", "tpm-dummy2")));
+  BOOST_REQUIRE_NO_THROW((KeyChain("dummy", "dummy")));
+  BOOST_REQUIRE_NO_THROW((KeyChain("dummy:", "dummy:")));
+  BOOST_REQUIRE_NO_THROW((KeyChain("dummy:/something", "dummy:/something")));
+
+  KeyChain keyChain("dummy", "dummy");
+  BOOST_CHECK_EQUAL(keyChain.getPib().getPibLocator(), "pib-dummy:");
+  BOOST_CHECK_EQUAL(keyChain.getPib().getTpmLocator(), "tpm-dummy:");
+  BOOST_CHECK_EQUAL(keyChain.getTpm().getTpmLocator(), "tpm-dummy:");
+  BOOST_CHECK_EQUAL(keyChain.getDefaultIdentity(), "/dummy/key");
+}
+
+BOOST_FIXTURE_TEST_CASE(GeneralSigningInterface, IdentityManagementFixture)
+{
+  Name id("/id");
+  Name certName = m_keyChain.createIdentity(id);
+  shared_ptr<v1::IdentityCertificate> idCert = m_keyChain.getCertificate(certName);
+  Name keyName = idCert->getPublicKeyName();
+  m_keyChain.setDefaultIdentity(id);
+
+  Name id2("/id2");
+  Name cert2Name = m_keyChain.createIdentity(id2);
+  shared_ptr<v1::IdentityCertificate> id2Cert = m_keyChain.getCertificate(cert2Name);
+
+  // SigningInfo is set to default
+  Data data1("/data1");
+  m_keyChain.sign(data1);
+  BOOST_CHECK(Validator::verifySignature(data1, idCert->getPublicKeyInfo()));
+  BOOST_CHECK_EQUAL(data1.getSignature().getKeyLocator().getName(), certName.getPrefix(-1));
+
+  Interest interest1("/interest1");
+  m_keyChain.sign(interest1);
+  BOOST_CHECK(Validator::verifySignature(interest1, idCert->getPublicKeyInfo()));
+  SignatureInfo sigInfo1(interest1.getName()[-2].blockFromValue());
+  BOOST_CHECK_EQUAL(sigInfo1.getKeyLocator().getName(), certName.getPrefix(-1));
+
+  // SigningInfo is set to Identity
+  Data data2("/data2");
+  m_keyChain.sign(data2, SigningInfo(SigningInfo::SIGNER_TYPE_ID, id2));
+  BOOST_CHECK(Validator::verifySignature(data2, id2Cert->getPublicKeyInfo()));
+  BOOST_CHECK_EQUAL(data2.getSignature().getKeyLocator().getName(), cert2Name.getPrefix(-1));
+
+  Interest interest2("/interest2");
+  m_keyChain.sign(interest2, SigningInfo(SigningInfo::SIGNER_TYPE_ID, id2));
+  BOOST_CHECK(Validator::verifySignature(interest2, id2Cert->getPublicKeyInfo()));
+  SignatureInfo sigInfo2(interest2.getName()[-2].blockFromValue());
+  BOOST_CHECK_EQUAL(sigInfo2.getKeyLocator().getName(), cert2Name.getPrefix(-1));
+
+  // SigningInfo is set to Key
+  Data data3("/data3");
+  m_keyChain.sign(data3, SigningInfo(SigningInfo::SIGNER_TYPE_KEY, keyName));
+  BOOST_CHECK(Validator::verifySignature(data3, idCert->getPublicKeyInfo()));
+  BOOST_CHECK_EQUAL(data3.getSignature().getKeyLocator().getName(), certName.getPrefix(-1));
+
+  Interest interest3("/interest3");
+  m_keyChain.sign(interest3);
+  BOOST_CHECK(Validator::verifySignature(interest3, idCert->getPublicKeyInfo()));
+  SignatureInfo sigInfo3(interest1.getName()[-2].blockFromValue());
+  BOOST_CHECK_EQUAL(sigInfo3.getKeyLocator().getName(), certName.getPrefix(-1));
+
+  // SigningInfo is set to Cert
+  Data data4("/data4");
+  m_keyChain.sign(data4, SigningInfo(SigningInfo::SIGNER_TYPE_CERT, certName));
+  BOOST_CHECK(Validator::verifySignature(data4, idCert->getPublicKeyInfo()));
+  BOOST_CHECK_EQUAL(data4.getSignature().getKeyLocator().getName(), certName.getPrefix(-1));
+
+  Interest interest4("/interest4");
+  m_keyChain.sign(interest4, SigningInfo(SigningInfo::SIGNER_TYPE_CERT, certName));
+  BOOST_CHECK(Validator::verifySignature(interest4, idCert->getPublicKeyInfo()));
+  SignatureInfo sigInfo4(interest4.getName()[-2].blockFromValue());
+  BOOST_CHECK_EQUAL(sigInfo4.getKeyLocator().getName(), certName.getPrefix(-1));
+
+
+  // SigningInfo is set to DigestSha256
+  Data data5("/data5");
+  m_keyChain.sign(data5, SigningInfo(SigningInfo::SIGNER_TYPE_SHA256));
+  BOOST_CHECK(Validator::verifySignature(data5, DigestSha256(data5.getSignature())));
+
+  Interest interest5("/interest4");
+  m_keyChain.sign(interest5, SigningInfo(SigningInfo::SIGNER_TYPE_SHA256));
+  BOOST_CHECK(Validator::verifySignature(interest5,
+                                         DigestSha256(Signature(interest5.getName()[-2].blockFromValue(),
+                                                                interest5.getName()[-1].blockFromValue()))));
+}
+
+BOOST_FIXTURE_TEST_CASE(EcdsaSigningByIdentityNoCert, IdentityManagementFixture)
+{
+  Data data("/test/data");
+
+  Name nonExistingIdentity = Name("/non-existing/identity").appendVersion();
+
+  BOOST_CHECK_NO_THROW(m_keyChain.sign(data, signingByIdentity(nonExistingIdentity)));
+  BOOST_CHECK_EQUAL(data.getSignature().getType(),
+                    KeyChain::getSignatureType(KeyChain::DEFAULT_KEY_PARAMS.getKeyType(),
+                                               DigestAlgorithm::SHA256));
+  BOOST_CHECK(nonExistingIdentity.isPrefixOf(data.getSignature().getKeyLocator().getName()));
+
+  Name ecdsaIdentity = Name("/ndn/test/ecdsa").appendVersion();
+  Name ecdsaKeyName = m_keyChain.generateEcdsaKeyPairAsDefault(ecdsaIdentity, false, 256);
+  BOOST_CHECK_NO_THROW(m_keyChain.sign(data, signingByIdentity(ecdsaIdentity)));
+  BOOST_CHECK_EQUAL(data.getSignature().getType(),
+                    KeyChain::getSignatureType(EcdsaKeyParams().getKeyType(), DigestAlgorithm::SHA256));
+  BOOST_CHECK(ecdsaIdentity.isPrefixOf(data.getSignature().getKeyLocator().getName()));
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestKeyChain
+BOOST_AUTO_TEST_SUITE_END() // V1
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace v1
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit-tests/security/v1/sec-public-info-sqlite3.t.cpp b/tests/unit-tests/security/v1/sec-public-info-sqlite3.t.cpp
new file mode 100644
index 0000000..e2d668b
--- /dev/null
+++ b/tests/unit-tests/security/v1/sec-public-info-sqlite3.t.cpp
@@ -0,0 +1,156 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2017 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/v1/sec-public-info-sqlite3.hpp"
+#include "security/v1/key-chain.hpp"
+#include "security/v1/cryptopp.hpp"
+#include "encoding/buffer-stream.hpp"
+#include "util/time.hpp"
+
+#include "boost-test.hpp"
+
+#include <boost/filesystem.hpp>
+#include <boost/lexical_cast.hpp>
+
+namespace ndn {
+namespace security {
+namespace v1 {
+namespace tests {
+
+class PibTmpPathFixture
+{
+public:
+  PibTmpPathFixture()
+  {
+    boost::system::error_code error;
+    tmpPath = boost::filesystem::temp_directory_path(error);
+    BOOST_REQUIRE(boost::system::errc::success == error.value());
+    tmpPath /= boost::lexical_cast<std::string>(random::generateWord32());
+  }
+
+  ~PibTmpPathFixture()
+  {
+    boost::filesystem::remove_all(tmpPath);
+  }
+
+public:
+  boost::filesystem::path tmpPath;
+};
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(V1)
+BOOST_AUTO_TEST_SUITE(TestSecPublicInfoSqlite3)
+
+const std::string RSA_DER("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuFoDcNtffwbfFix64fw0\
+hI2tKMkFrc6Ex7yw0YLMK9vGE8lXOyBl/qXabow6RCz+GldmFN6E2Qhm1+AX3Zm5\
+sj3H53/HPtzMefvMQ9X7U+lK8eNMWawpRzvBh4/36VrK/awlkNIVIQ9aXj6q6BVe\
+zL+zWT/WYemLq/8A1/hHWiwCtfOH1xQhGqWHJzeSgwIgOOrzxTbRaCjhAb1u2TeV\
+yx/I9H/DV+AqSHCaYbB92HDcDN0kqwSnUf5H1+osE9MR5DLBLhXdSiULSgxT3Or/\
+y2QgsgUK59WrjhlVMPEiHHRs15NZJbL1uQFXjgScdEarohcY3dilqotineFZCeN8\
+DwIDAQAB");
+const std::string ECDSA_DER("MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENZpqkPJDj8uhSpffOiCbvSYMLsGB\
+1Eo/WU6mrexjGvduQXjqwon/eSHFI6EgHZk8L9KfiV5XVtVsk2g5wIpJVg==");
+
+BOOST_FIXTURE_TEST_CASE(Basic, PibTmpPathFixture)
+{
+  SecPublicInfoSqlite3 pib(tmpPath.generic_string());
+
+  BOOST_CHECK(pib.doesTableExist("Identity"));
+  BOOST_CHECK(pib.doesTableExist("Key"));
+  BOOST_CHECK(pib.doesTableExist("Certificate"));
+}
+
+BOOST_FIXTURE_TEST_CASE(TpmLocatorTest, PibTmpPathFixture)
+{
+  SecPublicInfoSqlite3 pib(tmpPath.generic_string());
+
+  BOOST_REQUIRE_THROW(pib.getTpmLocator(), SecPublicInfo::Error);
+  pib.addIdentity("/test/id1");
+  BOOST_CHECK(pib.doesIdentityExist("/test/id1"));
+
+  // Pib does not have tpmInfo set yet, setTpmInfo simply set the tpmInfo.
+  std::string tpmLocator("tpm-file:");
+  tpmLocator.append((tmpPath / "tpm").generic_string());
+  pib.setTpmLocator(tpmLocator);
+  BOOST_CHECK(pib.doesIdentityExist("/test/id1"));
+
+  BOOST_REQUIRE_NO_THROW(pib.getTpmLocator());
+  BOOST_CHECK_EQUAL(tpmLocator, pib.getTpmLocator());
+
+  // Pib has tpmInfo set, set a different tpmInfo will reset Pib content.
+  std::string tpmLocator3("tpm-osxkeychain:");
+  pib.setTpmLocator(tpmLocator3);
+  BOOST_CHECK(!pib.doesIdentityExist("/test/id1"));
+}
+
+BOOST_AUTO_TEST_CASE(KeyTypeRsa)
+{
+  using namespace CryptoPP;
+
+  OBufferStream os;
+  StringSource ss(reinterpret_cast<const uint8_t*>(RSA_DER.c_str()), RSA_DER.size(),
+                  true, new Base64Decoder(new FileSink(os)));
+
+  shared_ptr<v1::PublicKey> rsaKey;
+  BOOST_REQUIRE_NO_THROW(rsaKey = make_shared<v1::PublicKey>(os.buf()->buf(), os.buf()->size()));
+  Name rsaKeyName("/TestSecPublicInfoSqlite3/KeyType/RSA/ksk-123");
+  SecPublicInfoSqlite3 pib;
+  pib.addKey(rsaKeyName, *rsaKey);
+
+  BOOST_CHECK_EQUAL(KeyType::RSA, pib.getPublicKeyType(rsaKeyName));
+
+  pib.deleteIdentityInfo(Name("/TestSecPublicInfoSqlite3/KeyType/RSA"));
+}
+
+BOOST_AUTO_TEST_CASE(KeyTypeEcdsa)
+{
+  using namespace CryptoPP;
+
+  OBufferStream os;
+  StringSource ss(reinterpret_cast<const uint8_t*>(ECDSA_DER.c_str()), ECDSA_DER.size(),
+                  true, new Base64Decoder(new FileSink(os)));
+
+  shared_ptr<v1::PublicKey> ecdsaKey;
+  BOOST_REQUIRE_NO_THROW(ecdsaKey = make_shared<v1::PublicKey>(os.buf()->buf(), os.buf()->size()));
+  Name ecdsaKeyName("/TestSecPublicInfoSqlite3/KeyType/ECDSA/ksk-123");
+  SecPublicInfoSqlite3 pib;
+  pib.addKey(ecdsaKeyName, *ecdsaKey);
+
+  BOOST_CHECK_EQUAL(KeyType::EC, pib.getPublicKeyType(ecdsaKeyName));
+  pib.deleteIdentityInfo(Name("/TestSecPublicInfoSqlite3/KeyType/ECDSA"));
+}
+
+BOOST_AUTO_TEST_CASE(KeyTypeNonExistent)
+{
+  Name nullKeyName("/TestSecPublicInfoSqlite3/KeyType/Null");
+  SecPublicInfoSqlite3 pib;
+
+  BOOST_CHECK_EQUAL(KeyType::NONE, pib.getPublicKeyType(nullKeyName));
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestSecPublicInfoSqlite3
+BOOST_AUTO_TEST_SUITE_END() // V1
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace v1
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit-tests/security/v1/sec-tpm-file.t.cpp b/tests/unit-tests/security/v1/sec-tpm-file.t.cpp
new file mode 100644
index 0000000..79e3645
--- /dev/null
+++ b/tests/unit-tests/security/v1/sec-tpm-file.t.cpp
@@ -0,0 +1,417 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2017 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/v1/sec-tpm-file.hpp"
+#include "security/v1/key-chain.hpp"
+#include "security/v1/cryptopp.hpp"
+#include "util/time.hpp"
+
+#include "boost-test.hpp"
+
+#include <boost/filesystem.hpp>
+#include <boost/lexical_cast.hpp>
+
+namespace ndn {
+namespace security {
+namespace v1 {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(V1)
+BOOST_AUTO_TEST_SUITE(TestSecTpmFile)
+
+BOOST_AUTO_TEST_CASE(Delete)
+{
+  SecTpmFile tpm;
+
+  Name keyName("/TestSecTpmFile/Delete/ksk-" +
+               boost::lexical_cast<std::string>(time::toUnixTimestamp(time::system_clock::now())));
+  RsaKeyParams params(2048);
+  BOOST_CHECK_NO_THROW(tpm.generateKeyPairInTpm(keyName, params));
+
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KeyClass::PUBLIC), true);
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KeyClass::PRIVATE), true);
+
+  tpm.deleteKeyPairInTpm(keyName);
+
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KeyClass::PUBLIC), false);
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KeyClass::PRIVATE), false);
+}
+
+BOOST_AUTO_TEST_CASE(SignVerify)
+{
+  SecTpmFile tpm;
+
+  Name keyName("/TestSecTpmFile/SignVerify/ksk-" +
+               boost::lexical_cast<std::string>(time::toUnixTimestamp(time::system_clock::now())));
+  RsaKeyParams params(2048);
+  BOOST_CHECK_NO_THROW(tpm.generateKeyPairInTpm(keyName, params));
+
+  Data data("/tmp/test/1");
+  const uint8_t content[] = {0x01, 0x02, 0x03, 0x04};
+
+  Block sigBlock;
+  BOOST_CHECK_NO_THROW(sigBlock = tpm.signInTpm(content, sizeof(content),
+                                                keyName, DigestAlgorithm::SHA256));
+  shared_ptr<v1::PublicKey> publicKey;
+  BOOST_CHECK_NO_THROW(publicKey = tpm.getPublicKeyFromTpm(keyName));
+
+  try
+    {
+      using namespace CryptoPP;
+
+      RSA::PublicKey rsaPublicKey;
+      ByteQueue queue;
+      queue.Put(reinterpret_cast<const byte*>(publicKey->get().buf()), publicKey->get().size());
+      rsaPublicKey.Load(queue);
+
+      RSASS<PKCS1v15, SHA256>::Verifier verifier(rsaPublicKey);
+      bool result = verifier.VerifyMessage(content, sizeof(content),
+                                           sigBlock.value(), sigBlock.value_size());
+
+      BOOST_CHECK_EQUAL(result, true);
+    }
+  catch (CryptoPP::Exception& e)
+    {
+      BOOST_CHECK(false);
+    }
+
+  tpm.deleteKeyPairInTpm(keyName);
+}
+
+BOOST_AUTO_TEST_CASE(RandomGenerator)
+{
+  SecTpmFile tpm;
+
+  constexpr size_t scale = 1000;
+  constexpr size_t size = 256 * scale;
+  auto block = unique_ptr<uint8_t[]>{new uint8_t[size]};
+  tpm.generateRandomBlock(block.get(), size);
+
+  std::map<uint8_t, size_t> counter;
+  for (size_t i = 0; i < size; i++) {
+    counter[block[i]] += 1;
+  }
+
+  double dev = 0.0;
+  for (uint8_t i = 0; i < 255; i++) {
+    dev += static_cast<double>((counter[i] - scale) * (counter[i] - scale)) / (scale * scale);
+  }
+  dev /= 256;
+
+  BOOST_CHECK_CLOSE(dev, 0.001, 100);
+}
+
+BOOST_AUTO_TEST_CASE(ImportExportKey)
+{
+  using namespace CryptoPP;
+
+  std::string imported =
+"MIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIIJzwsbTIVqgCAggAMBQGCCqG"
+"SIb3DQMHBAiEsSKdgGkCEQSCBMjaYsEeHM/EPzGNDAPaSxE1ASKxjyNkXEVPQbtGx/ju1PlQ"
+"QakTCzPpia8ziVGihrVfuacHrxxbLh+ufNZtbVVsv9kGQL2g15BN2Nic8VqyTxplKrduFkEb"
+"eOipqu627gb6eTsrSj7kubXfs/w9OAdhRZFaEc7I/S6rcPUaDai4i3O03VuvuTOrzZL/unhD"
+"CDzOa3pr2aUQlO/5Pck6GbSYL1/4aW/fB7djZrZAjsGPTqIYpPa16oWlrzsILQ4650Zlvdn8"
+"feh6elTrA4qy6RljZfhIHxzGAeuGbVVLT7zavs01y+QE88sxPpeZ0RGtlVxCYp+xoB5hOO/x"
+"Xm3n0r+HVIaBV9rHLuUSUiHVAtzwuOj/XKh7YBNXeF58lcv8Npsx10etrPuV5hRQelYirKo1"
+"QbT+Aq7sLdWI09eGClDHjvRgw54lCFEUAVUFLxhBnzfVUfw/UiR2SheixH+c7cY3gOOvSMQh"
+"1oL9Omii4S6yhzfbD3hRN/wBKC0NgiIOLRR+Ti0mEEbTxYQrVcHC9rpRcnr1fFAiQvOXrOw0"
+"HyxsbnOeYpoURgLJmUyItPi09xUMCHwUPZ/sI6aG5eRqVUGgcYaQib7MBbGG/D2PlWaKZx1w"
+"iEYtYUI7rrc7Qc2ltp4i1u46ZLtSOxUi8kM7qK2Yp1AOtcWFlGn0XBXpGsHanZRzs8KzfDjQ"
+"OPmRIuFXFmuJweqUGmg6c8P3wHYueenB4oowYELYaDwmmV96obXMG5hbsKne5kcem875d6K+"
+"hL2QzjAl+na4tUZyXYXDdUO2lgTT8IItujBn6c+b8vDcZ24NcYyWPHHb16J4uvKi/6Zb245g"
+"/N0NC6hB43KE+2F0BH0eyXRzCnen6AjF8nvx/wgYrXsFlsU47P8gaL1e7V6QECkY4vIk6//b"
+"LINmpcgZoAv23fgjvYYTMfS/IyPsooS5DJarbHzbsgAWOuqP2ewYulrKqLi0vaUyoErRedQC"
+"8J5p9c4KF56++ameiwxbyKnDynHIIFCOM8eamLnDH4VvU9E2mtfZxmi8kWDWx/NhKEK9zbQv"
+"WuaGDpOysgPK4myTp2QGQNQDvBB92gMcrVTcY//3OGHSXeJrkUfDKLOUDyz7ROghEt1vpRTL"
+"j9Xdbm/01O/0MLBqyXDY119b1qAVVY7Y2CxRIRFdw2V76INWNIwPi46t/VUGwMBGmEux8S8+"
+"79Mv7UyGhKvSUr88pWCS1KdSz1HhN1VWjDvyXPyg96+SecpZMwXCdkUCLdLdD3/8rJLt7wS5"
+"3K5/1V4sacds8GHx7NckhQ/KV0VDlUEFuaOCS4Sd3XXetXs4IFSqtKH+Rn0jX7d8Igcw7X2b"
+"eaV1gxOVquDEwLDT5+wXURw96ahq0caL/4YfoBUQIOQ6HGtPTWJz1Yax0pGu9F30VEY/ObrK"
+"L/B6peJKfqhQGJ+MObqOiP6yHBZH75EImLAkksSVmREdNVjwWkz9D9vzPoAnmP8sQ3/NZarB"
+"Ak+ynQjc19t+CCecPrS2Tlh0cJZkHRiGFF7J5a3ci7yBvg3HfD86AXMRBQuSG1UG8TrzC6BK"
+"+qIQ8DWecQwBMZ3nv/Flo2Fejd/G4/wWe6ObMytC5SB8pJNOq9ri0Ff6Zh3rPrwaSv1PPgFJ"
+"GOw=";
+
+  std::string decoded;
+  BOOST_CHECK_NO_THROW(StringSource source(imported,
+                                           true,
+                                           new Base64Decoder(new StringSink(decoded))));
+
+  SecTpmFile tpm;
+
+  Name keyName("/TestSecTpmFile/ImportKey/ksk-" +
+               boost::lexical_cast<std::string>(time::toUnixTimestamp(time::system_clock::now())));
+
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KeyClass::PRIVATE), false);
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KeyClass::PUBLIC), false);
+
+  BOOST_REQUIRE_NO_THROW(
+    tpm.importPrivateKeyPkcs5IntoTpm(keyName,
+                                     reinterpret_cast<const uint8_t*>(decoded.c_str()),
+                                     decoded.size(),
+                                     "1234"));
+
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KeyClass::PRIVATE), true);
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KeyClass::PUBLIC), true);
+
+  shared_ptr<v1::PublicKey> publicKey;
+  BOOST_CHECK_NO_THROW(publicKey = tpm.getPublicKeyFromTpm(keyName));
+
+  const uint8_t content[] = {0x01, 0x02, 0x03, 0x04};
+  Block sigBlock;
+  BOOST_CHECK_NO_THROW(sigBlock = tpm.signInTpm(content, sizeof(content),
+                                                keyName, DigestAlgorithm::SHA256));
+
+  try
+    {
+      using namespace CryptoPP;
+
+      RSA::PublicKey rsaPublicKey;
+      ByteQueue queue;
+      queue.Put(reinterpret_cast<const byte*>(publicKey->get().buf()), publicKey->get().size());
+      rsaPublicKey.Load(queue);
+
+      RSASS<PKCS1v15, SHA256>::Verifier verifier(rsaPublicKey);
+      bool isVerified = verifier.VerifyMessage(content, sizeof(content),
+                                               sigBlock.value(), sigBlock.value_size());
+
+      BOOST_CHECK_EQUAL(isVerified, true);
+    }
+  catch (CryptoPP::Exception& e)
+    {
+      BOOST_CHECK(false);
+    }
+
+  ConstBufferPtr exported;
+  BOOST_CHECK_NO_THROW(exported = tpm.exportPrivateKeyPkcs5FromTpm(keyName, "5678"));
+
+  tpm.deleteKeyPairInTpm(keyName);
+
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KeyClass::PRIVATE), false);
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KeyClass::PUBLIC), false);
+
+  BOOST_REQUIRE(tpm.importPrivateKeyPkcs5IntoTpm(keyName, exported->buf(), exported->size(),
+                                                 "5678"));
+
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KeyClass::PRIVATE), true);
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KeyClass::PUBLIC), true);
+
+  const uint8_t content2[] = {0x05, 0x06, 0x07, 0x08};
+  Block sigBlock2;
+  BOOST_CHECK_NO_THROW(sigBlock2 = tpm.signInTpm(content2, sizeof(content2),
+                                                 keyName, DigestAlgorithm::SHA256));
+
+  try
+    {
+      using namespace CryptoPP;
+
+      RSA::PublicKey rsaPublicKey;
+      ByteQueue queue;
+      queue.Put(reinterpret_cast<const byte*>(publicKey->get().buf()), publicKey->get().size());
+      rsaPublicKey.Load(queue);
+
+      RSASS<PKCS1v15, SHA256>::Verifier verifier(rsaPublicKey);
+      bool isVerified = verifier.VerifyMessage(content2, sizeof(content2),
+                                               sigBlock2.value(), sigBlock2.value_size());
+
+      BOOST_CHECK_EQUAL(isVerified, true);
+    }
+  catch (CryptoPP::Exception& e)
+    {
+      BOOST_CHECK(false);
+    }
+
+  tpm.deleteKeyPairInTpm(keyName);
+
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KeyClass::PRIVATE), false);
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KeyClass::PUBLIC), false);
+}
+
+BOOST_AUTO_TEST_CASE(EcdsaSigning)
+{
+  SecTpmFile tpm;
+
+  Name keyName("/TestSecTpmFile/EcdsaSigning/ksk-" +
+               boost::lexical_cast<std::string>(time::toUnixTimestamp(time::system_clock::now())));
+  EcdsaKeyParams params;
+  BOOST_CHECK_NO_THROW(tpm.generateKeyPairInTpm(keyName, params));
+
+  Data data("/TestSecTpmFile/EcdsaSigning/Data/1");
+  const uint8_t content[] = {0x01, 0x02, 0x03, 0x04};
+
+  Block sigBlock;
+  BOOST_CHECK_NO_THROW(sigBlock = tpm.signInTpm(content, sizeof(content),
+                                                keyName, DigestAlgorithm::SHA256));
+
+  shared_ptr<v1::PublicKey> pubkeyPtr;
+  BOOST_CHECK_NO_THROW(pubkeyPtr = tpm.getPublicKeyFromTpm(keyName));
+
+  try
+    {
+      using namespace CryptoPP;
+
+      ECDSA<ECP, SHA256>::PublicKey publicKey;
+      ByteQueue queue;
+      queue.Put(reinterpret_cast<const byte*>(pubkeyPtr->get().buf()), pubkeyPtr->get().size());
+      publicKey.Load(queue);
+
+      uint8_t buffer[64];
+      size_t usedSize = DSAConvertSignatureFormat(buffer, 64, DSA_P1363,
+                                                  sigBlock.value(), sigBlock.value_size(), DSA_DER);
+
+      ECDSA<ECP, SHA256>::Verifier verifier(publicKey);
+      bool result = verifier.VerifyMessage(content, sizeof(content),
+                                           buffer, usedSize);
+
+      BOOST_CHECK_EQUAL(result, true);
+    }
+  catch (CryptoPP::Exception& e)
+    {
+      BOOST_CHECK(false);
+    }
+
+  tpm.deleteKeyPairInTpm(keyName);
+}
+
+
+BOOST_AUTO_TEST_CASE(ImportExportEcdsaKey)
+{
+  using namespace CryptoPP;
+
+  std::string imported =
+    "MIGMMEAGCSqGSIb3DQEFDTAzMBsGCSqGSIb3DQEFDDAOBAhqkJiLfzFWtQICCAAw"
+    "FAYIKoZIhvcNAwcECJ1HLtP8OZC6BEgNv9OH2mZdbkxvqTVlRBkUqPbbP3580OG6"
+    "f0htqWSRppcb4IEKYfuPt2qPCYKL2GcAN2pU3eJqhiM7LFTSFaxgBRFozzIwusk=";
+
+  std::string decoded;
+  BOOST_CHECK_NO_THROW(StringSource source(imported,
+                                           true,
+                                           new Base64Decoder(new StringSink(decoded))));
+
+  SecTpmFile tpm;
+
+  Name keyName("/TestSecTpmFile/ImportExportEcdsaKey/ksk-" +
+               boost::lexical_cast<std::string>(time::toUnixTimestamp(time::system_clock::now())));
+
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KeyClass::PRIVATE), false);
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KeyClass::PUBLIC), false);
+
+  BOOST_REQUIRE_NO_THROW(
+    tpm.importPrivateKeyPkcs5IntoTpm(keyName,
+                                     reinterpret_cast<const uint8_t*>(decoded.c_str()),
+                                     decoded.size(),
+                                     "5678"));
+
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KeyClass::PRIVATE), true);
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KeyClass::PUBLIC), true);
+
+  shared_ptr<v1::PublicKey> publicKey;
+  BOOST_CHECK_NO_THROW(publicKey = tpm.getPublicKeyFromTpm(keyName));
+
+  const uint8_t content[] = {0x01, 0x02, 0x03, 0x04};
+  Block sigBlock;
+  BOOST_CHECK_NO_THROW(sigBlock = tpm.signInTpm(content, sizeof(content),
+                                                keyName, DigestAlgorithm::SHA256));
+
+  try
+    {
+      using namespace CryptoPP;
+
+      ECDSA<ECP, SHA256>::PublicKey ecdsaPublicKey;
+      ByteQueue queue;
+      queue.Put(reinterpret_cast<const byte*>(publicKey->get().buf()), publicKey->get().size());
+      ecdsaPublicKey.Load(queue);
+
+      uint8_t buffer[64];
+      size_t usedSize = DSAConvertSignatureFormat(buffer, 64, DSA_P1363,
+                                                  sigBlock.value(), sigBlock.value_size(), DSA_DER);
+
+      ECDSA<ECP, SHA256>::Verifier verifier(ecdsaPublicKey);
+      bool isVerified = verifier.VerifyMessage(content, sizeof(content),
+                                               buffer, usedSize);
+
+      BOOST_CHECK_EQUAL(isVerified, true);
+    }
+  catch (CryptoPP::Exception& e)
+    {
+      BOOST_CHECK(false);
+    }
+
+  ConstBufferPtr exported;
+  BOOST_CHECK_NO_THROW(exported = tpm.exportPrivateKeyPkcs5FromTpm(keyName, "1234"));
+
+  tpm.deleteKeyPairInTpm(keyName);
+
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KeyClass::PRIVATE), false);
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KeyClass::PUBLIC), false);
+
+  BOOST_REQUIRE(tpm.importPrivateKeyPkcs5IntoTpm(keyName, exported->buf(), exported->size(),
+                                                 "1234"));
+
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KeyClass::PRIVATE), true);
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KeyClass::PUBLIC), true);
+
+  const uint8_t content2[] = {0x05, 0x06, 0x07, 0x08};
+  Block sigBlock2;
+  BOOST_CHECK_NO_THROW(sigBlock2 = tpm.signInTpm(content2, sizeof(content2),
+                                                 keyName, DigestAlgorithm::SHA256));
+
+  try
+    {
+      using namespace CryptoPP;
+
+      ECDSA<ECP, SHA256>::PublicKey ecdsaPublicKey;
+      ByteQueue queue;
+      queue.Put(reinterpret_cast<const byte*>(publicKey->get().buf()), publicKey->get().size());
+      ecdsaPublicKey.Load(queue);
+
+      uint8_t buffer[64];
+      size_t usedSize = DSAConvertSignatureFormat(buffer, 64, DSA_P1363,
+                                                  sigBlock2.value(), sigBlock2.value_size(),
+                                                  DSA_DER);
+
+      ECDSA<ECP, SHA256>::Verifier verifier(ecdsaPublicKey);
+      bool isVerified = verifier.VerifyMessage(content2, sizeof(content2),
+                                               buffer, usedSize);
+
+      BOOST_CHECK_EQUAL(isVerified, true);
+
+    }
+  catch (CryptoPP::Exception& e)
+    {
+      BOOST_CHECK(false);
+    }
+
+  tpm.deleteKeyPairInTpm(keyName);
+
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KeyClass::PRIVATE), false);
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KeyClass::PUBLIC), false);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestSecTpmFile
+BOOST_AUTO_TEST_SUITE_END() // V1
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace v1
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit-tests/security/v1/sec-tpm-osx.t.cpp b/tests/unit-tests/security/v1/sec-tpm-osx.t.cpp
new file mode 100644
index 0000000..2d6fbcc
--- /dev/null
+++ b/tests/unit-tests/security/v1/sec-tpm-osx.t.cpp
@@ -0,0 +1,372 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2017 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/v1/sec-tpm-osx.hpp"
+#include "security/v1/cryptopp.hpp"
+#include "util/time.hpp"
+
+#include "boost-test.hpp"
+
+#include <boost/lexical_cast.hpp>
+#include <Availability.h>
+
+namespace ndn {
+namespace security {
+namespace v1 {
+namespace tests {
+
+class OsxKeyChainTestFixture
+{
+public:
+  OsxKeyChainTestFixture()
+  {
+    std::string oldHOME;
+    if (std::getenv("OLD_HOME"))
+      oldHOME = std::getenv("OLD_HOME");
+
+    if (std::getenv("HOME"))
+      m_HOME = std::getenv("HOME");
+
+    if (!oldHOME.empty())
+      setenv("HOME", oldHOME.c_str(), 1);
+    else
+      unsetenv("HOME");
+  }
+
+  ~OsxKeyChainTestFixture()
+  {
+    if (!m_HOME.empty())
+      setenv("HOME", m_HOME.c_str(), 1);
+    else
+      unsetenv("HOME");
+  }
+
+protected:
+  std::string m_HOME;
+};
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(V1)
+BOOST_FIXTURE_TEST_SUITE(TestSecTpmOsx, OsxKeyChainTestFixture)
+
+BOOST_AUTO_TEST_CASE(Delete)
+{
+  SecTpmOsx tpm;
+
+  Name keyName("/TestSecTpmOsx/Delete/ksk-" +
+               boost::lexical_cast<std::string>(
+                 time::toUnixTimestamp(time::system_clock::now()).count()));
+  RsaKeyParams params(2048);
+  BOOST_CHECK_NO_THROW(tpm.generateKeyPairInTpm(keyName, params));
+
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KeyClass::PUBLIC), true);
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KeyClass::PRIVATE), true);
+
+  tpm.deleteKeyPairInTpm(keyName);
+
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KeyClass::PUBLIC), false);
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KeyClass::PRIVATE), false);
+}
+
+BOOST_AUTO_TEST_CASE(SignVerify)
+{
+  SecTpmOsx tpm;
+
+  Name keyName("/TestSecTpmOsx/SignVerify/ksk-" +
+               boost::lexical_cast<std::string>(
+                 time::toUnixTimestamp(time::system_clock::now()).count()));
+  RsaKeyParams params(2048);
+  BOOST_CHECK_NO_THROW(tpm.generateKeyPairInTpm(keyName, params));
+
+  Data data("/TestSecTpmOsx/SignVaerify/Data/1");
+  const uint8_t content[] = {0x01, 0x02, 0x03, 0x04};
+
+  Block sigBlock;
+  BOOST_CHECK_NO_THROW(sigBlock = tpm.signInTpm(content, sizeof(content),
+                                                keyName, DigestAlgorithm::SHA256));
+
+  shared_ptr<v1::PublicKey> publicKey;
+  BOOST_CHECK_NO_THROW(publicKey = tpm.getPublicKeyFromTpm(keyName));
+  try
+    {
+      using namespace CryptoPP;
+
+      RSA::PublicKey rsaPublicKey;
+      ByteQueue queue;
+      queue.Put(reinterpret_cast<const byte*>(publicKey->get().buf()), publicKey->get().size());
+      rsaPublicKey.Load(queue);
+
+      RSASS<PKCS1v15, SHA256>::Verifier verifier(rsaPublicKey);
+      bool isVerified = verifier.VerifyMessage(content, sizeof(content),
+                                               sigBlock.value(), sigBlock.value_size());
+
+      BOOST_CHECK_EQUAL(isVerified, true);
+    }
+  catch (CryptoPP::Exception& e)
+    {
+      BOOST_CHECK(false);
+    }
+
+  tpm.deleteKeyPairInTpm(keyName);
+}
+
+BOOST_AUTO_TEST_CASE(RandomGenerator)
+{
+  SecTpmOsx tpm;
+
+  size_t scale = 1000;
+  size_t size = 256 * scale;
+  uint8_t* block = new uint8_t[size];
+  tpm.generateRandomBlock(block, size);
+
+  std::map<uint8_t, int> counter;
+  for (size_t i = 0; i < size; i++)
+    {
+      counter[block[i]] += 1;
+    }
+
+  float dev = 0.0;
+  for (size_t i = 0; i != 255; i++)
+    {
+      dev += ((counter[i] - scale) * (counter[i] - scale)) * 1.0 / (scale * scale);
+    }
+
+  BOOST_CHECK_CLOSE(dev / 256, 0.001, 100);
+
+}
+
+BOOST_AUTO_TEST_CASE(ExportImportKey)
+{
+  using namespace CryptoPP;
+
+  SecTpmOsx tpm;
+
+  Name keyName("/TestSecTpmOsx/ExportImportKey/ksk-" +
+               boost::lexical_cast<std::string>(
+                 time::toUnixTimestamp(time::system_clock::now()).count()));
+
+  RsaKeyParams params(2048);
+  BOOST_CHECK_NO_THROW(tpm.generateKeyPairInTpm(keyName, params));
+
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KeyClass::PRIVATE), true);
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KeyClass::PUBLIC), true);
+
+  ConstBufferPtr exported;
+  BOOST_CHECK_NO_THROW(exported = tpm.exportPrivateKeyPkcs5FromTpm(keyName, "1234"));
+  shared_ptr<v1::PublicKey> publicKey;
+  BOOST_REQUIRE_NO_THROW(publicKey = tpm.getPublicKeyFromTpm(keyName));
+
+  tpm.deleteKeyPairInTpm(keyName);
+
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KeyClass::PRIVATE), false);
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KeyClass::PUBLIC), false);
+
+  BOOST_REQUIRE(tpm.importPrivateKeyPkcs5IntoTpm(keyName,
+                                                 exported->buf(), exported->size(),
+                                                 "1234"));
+
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KeyClass::PUBLIC), true);
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KeyClass::PRIVATE), true);
+
+  const uint8_t content[] = {0x01, 0x02, 0x03, 0x04};
+  Block sigBlock;
+  BOOST_CHECK_NO_THROW(sigBlock = tpm.signInTpm(content, sizeof(content),
+                                                keyName, DigestAlgorithm::SHA256));
+
+  try
+    {
+      using namespace CryptoPP;
+
+      RSA::PublicKey rsaPublicKey;
+      ByteQueue queue;
+      queue.Put(reinterpret_cast<const byte*>(publicKey->get().buf()), publicKey->get().size());
+      rsaPublicKey.Load(queue);
+
+      RSASS<PKCS1v15, SHA256>::Verifier verifier(rsaPublicKey);
+      bool isVerified = verifier.VerifyMessage(content, sizeof(content),
+                                               sigBlock.value(), sigBlock.value_size());
+
+      BOOST_CHECK_EQUAL(isVerified, true);
+    }
+  catch (CryptoPP::Exception& e)
+    {
+      BOOST_CHECK(false);
+    }
+
+  tpm.deleteKeyPairInTpm(keyName);
+  // This is some problem related to Mac OS Key chain.
+  // On OSX 10.8, we cannot delete imported keys, but there is no such problem on OSX 10.9.
+#ifdef __MAC_OS_X_VERSION_MAX_ALLOWED
+#if __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_9
+  BOOST_REQUIRE(tpm.doesKeyExistInTpm(keyName, KeyClass::PRIVATE) == false);
+  BOOST_REQUIRE(tpm.doesKeyExistInTpm(keyName, KeyClass::PUBLIC) == false);
+#endif
+#endif
+}
+
+BOOST_AUTO_TEST_CASE(NonExistingKey)
+{
+  using namespace CryptoPP;
+
+  SecTpmOsx tpm;
+
+  Name keyName("/TestSecTpmOsx/NonExistingKey");
+
+  BOOST_REQUIRE_THROW(tpm.getPublicKeyFromTpm(keyName), SecTpmOsx::Error);
+
+  const uint8_t content[] = {0x01, 0x02, 0x03, 0x04};
+  BOOST_REQUIRE_THROW(tpm.signInTpm(content, sizeof(content), keyName, DigestAlgorithm::SHA256),
+                      SecTpmOsx::Error);
+
+  BOOST_REQUIRE_THROW(tpm.signInTpm(0, 1, keyName, DigestAlgorithm::SHA256),
+                      SecTpmOsx::Error);
+}
+
+BOOST_AUTO_TEST_CASE(EcdsaSigning)
+{
+  SecTpmOsx tpm;
+
+  Name keyName("/TestSecTpmOsx/EcdsaSigning/ksk-" +
+               boost::lexical_cast<std::string>(time::toUnixTimestamp(time::system_clock::now())));
+  EcdsaKeyParams params;
+  BOOST_CHECK_NO_THROW(tpm.generateKeyPairInTpm(keyName, params));
+
+  Data data("/TestSecTpmOsx/EcdsaSigning/Data/1");
+  const uint8_t content[] = {0x01, 0x02, 0x03, 0x04};
+
+  Block sigBlock;
+  BOOST_CHECK_NO_THROW(sigBlock = tpm.signInTpm(content, sizeof(content),
+                                                keyName, DigestAlgorithm::SHA256));
+
+  shared_ptr<v1::PublicKey> pubkeyPtr;
+  BOOST_CHECK_NO_THROW(pubkeyPtr = tpm.getPublicKeyFromTpm(keyName));
+
+  try
+    {
+      using namespace CryptoPP;
+
+      ECDSA<ECP, SHA256>::PublicKey publicKey;
+      ByteQueue queue;
+      queue.Put(reinterpret_cast<const byte*>(pubkeyPtr->get().buf()), pubkeyPtr->get().size());
+      publicKey.Load(queue);
+
+      uint8_t buffer[64];
+      size_t usedSize = DSAConvertSignatureFormat(buffer, 64, DSA_P1363,
+                                                  sigBlock.value(), sigBlock.value_size(), DSA_DER);
+
+      ECDSA<ECP, SHA256>::Verifier verifier(publicKey);
+      bool result = verifier.VerifyMessage(content, sizeof(content),
+                                           buffer, usedSize);
+
+      BOOST_CHECK_EQUAL(result, true);
+    }
+  catch (CryptoPP::Exception& e)
+    {
+      BOOST_CHECK(false);
+    }
+
+  tpm.deleteKeyPairInTpm(keyName);
+}
+
+
+BOOST_AUTO_TEST_CASE(ExportImportEcdsaKey)
+{
+  using namespace CryptoPP;
+
+  SecTpmOsx tpm;
+
+  Name keyName("/TestSecTpmOsx/ExportImportEcdsaKey/ksk-" +
+               boost::lexical_cast<std::string>(
+                 time::toUnixTimestamp(time::system_clock::now()).count()));
+
+  EcdsaKeyParams params;
+  BOOST_CHECK_NO_THROW(tpm.generateKeyPairInTpm(keyName, params));
+
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KeyClass::PRIVATE), true);
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KeyClass::PUBLIC), true);
+
+  ConstBufferPtr exported;
+  BOOST_CHECK_NO_THROW(exported = tpm.exportPrivateKeyPkcs5FromTpm(keyName, "1234"));
+
+  shared_ptr<v1::PublicKey> publicKey;
+  BOOST_REQUIRE_NO_THROW(publicKey = tpm.getPublicKeyFromTpm(keyName));
+
+  tpm.deleteKeyPairInTpm(keyName);
+
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KeyClass::PRIVATE), false);
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KeyClass::PUBLIC), false);
+
+  BOOST_REQUIRE(tpm.importPrivateKeyPkcs5IntoTpm(keyName,
+                                                 exported->buf(), exported->size(),
+                                                 "1234"));
+
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KeyClass::PUBLIC), true);
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KeyClass::PRIVATE), true);
+
+  const uint8_t content[] = {0x01, 0x02, 0x03, 0x04};
+  Block sigBlock;
+  BOOST_CHECK_NO_THROW(sigBlock = tpm.signInTpm(content, sizeof(content),
+                                                keyName, DigestAlgorithm::SHA256));
+
+  try
+    {
+      using namespace CryptoPP;
+
+      ECDSA<ECP, SHA256>::PublicKey ecdsaPublicKey;
+      ByteQueue queue;
+      queue.Put(reinterpret_cast<const byte*>(publicKey->get().buf()), publicKey->get().size());
+      ecdsaPublicKey.Load(queue);
+
+      uint8_t buffer[64];
+      size_t usedSize = DSAConvertSignatureFormat(buffer, 64, DSA_P1363,
+                                                  sigBlock.value(), sigBlock.value_size(),
+                                                  DSA_DER);
+
+      ECDSA<ECP, SHA256>::Verifier verifier(ecdsaPublicKey);
+      bool isVerified = verifier.VerifyMessage(content, sizeof(content),
+                                               buffer, usedSize);
+
+      BOOST_CHECK_EQUAL(isVerified, true);
+    }
+  catch (CryptoPP::Exception& e)
+    {
+      BOOST_CHECK(false);
+    }
+
+  tpm.deleteKeyPairInTpm(keyName);
+  // This is some problem related to Mac OS Key chain.
+  // On OSX 10.8, we cannot delete imported keys, but there is no such problem on OSX 10.9.
+#ifdef __MAC_OS_X_VERSION_MAX_ALLOWED
+#if __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_9
+  BOOST_REQUIRE(tpm.doesKeyExistInTpm(keyName, KeyClass::PRIVATE) == false);
+  BOOST_REQUIRE(tpm.doesKeyExistInTpm(keyName, KeyClass::PUBLIC) == false);
+#endif
+#endif
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestSecTpmOsx
+BOOST_AUTO_TEST_SUITE_END() // V1
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace v1
+} // namespace security
+} // namespace ndn