security: avoid parsing PIB and TPM locators multiple times

Change-Id: I2a8831e03d05b499f1f8939e03ea88cb82005743
diff --git a/ndn-cxx/security/key-chain.cpp b/ndn-cxx/security/key-chain.cpp
index f65b286..573f5c1 100644
--- a/ndn-cxx/security/key-chain.cpp
+++ b/ndn-cxx/security/key-chain.cpp
@@ -44,6 +44,7 @@
 #include "ndn-cxx/security/transform/verifier-filter.hpp"
 
 #include <boost/lexical_cast.hpp>
+#include <cstdlib>  // for std::getenv()
 
 namespace ndn {
 namespace security {
@@ -70,8 +71,6 @@
 NDN_LOG_INIT(ndn.security.KeyChain);
 
 const name::Component SELF("self");
-std::string KeyChain::s_defaultPibLocator;
-std::string KeyChain::s_defaultTpmLocator;
 
 KeyChain::PibFactories&
 KeyChain::getPibFactories()
@@ -87,14 +86,14 @@
   return tpmFactories;
 }
 
-const std::string&
-KeyChain::getDefaultPibScheme()
+static const auto&
+getDefaultPibScheme()
 {
   return pib::PibSqlite3::getScheme();
 }
 
-const std::string&
-KeyChain::getDefaultTpmScheme()
+static const auto&
+getDefaultTpmScheme()
 {
 #if defined(NDN_CXX_HAVE_OSX_FRAMEWORKS) && defined(NDN_CXX_WITH_OSX_KEYCHAIN)
   return tpm::BackEndOsx::getScheme();
@@ -103,48 +102,6 @@
 #endif // defined(NDN_CXX_HAVE_OSX_FRAMEWORKS) && defined(NDN_CXX_WITH_OSX_KEYCHAIN)
 }
 
-const std::string&
-KeyChain::getDefaultPibLocator()
-{
-  if (!s_defaultPibLocator.empty())
-    return s_defaultPibLocator;
-
-  if (getenv("NDN_CLIENT_PIB") != nullptr) {
-    s_defaultPibLocator = getenv("NDN_CLIENT_PIB");
-  }
-  else {
-    ConfigFile config;
-    s_defaultPibLocator = config.getParsedConfiguration().get<std::string>("pib", getDefaultPibScheme() + ":");
-  }
-
-  std::string pibScheme, pibLocation;
-  std::tie(pibScheme, pibLocation) = parseAndCheckPibLocator(s_defaultPibLocator);
-  s_defaultPibLocator = pibScheme + ":" + pibLocation;
-
-  return s_defaultPibLocator;
-}
-
-const std::string&
-KeyChain::getDefaultTpmLocator()
-{
-  if (!s_defaultTpmLocator.empty())
-    return s_defaultTpmLocator;
-
-  if (getenv("NDN_CLIENT_TPM") != nullptr) {
-    s_defaultTpmLocator = getenv("NDN_CLIENT_TPM");
-  }
-  else {
-    ConfigFile config;
-    s_defaultTpmLocator = config.getParsedConfiguration().get<std::string>("tpm", getDefaultTpmScheme() + ":");
-  }
-
-  std::string tpmScheme, tpmLocation;
-  std::tie(tpmScheme, tpmLocation) = parseAndCheckTpmLocator(s_defaultTpmLocator);
-  s_defaultTpmLocator = tpmScheme + ":" + tpmLocation;
-
-  return s_defaultTpmLocator;
-}
-
 const KeyParams&
 KeyChain::getDefaultKeyParams()
 {
@@ -154,56 +111,86 @@
 
 //
 
+class KeyChain::Locator
+{
+public:
+  NDN_CXX_NODISCARD bool
+  empty() const
+  {
+    return scheme.empty();
+  }
+
+  NDN_CXX_NODISCARD std::string
+  canonical() const
+  {
+    return scheme + ':' + location;
+  }
+
+  friend bool
+  operator==(const Locator& lhs, const Locator& rhs)
+  {
+    return lhs.scheme == rhs.scheme && lhs.location == rhs.location;
+  }
+
+public:
+  std::string scheme;
+  std::string location;
+};
+
+KeyChain::Locator KeyChain::s_defaultPibLocator;
+KeyChain::Locator KeyChain::s_defaultTpmLocator;
+
+//
+
 KeyChain::KeyChain()
   : KeyChain(getDefaultPibLocator(), getDefaultTpmLocator(), true)
 {
 }
 
 KeyChain::KeyChain(const std::string& pibLocator, const std::string& tpmLocator, bool allowReset)
+  : KeyChain(parseAndCheckPibLocator(pibLocator),
+             parseAndCheckTpmLocator(tpmLocator),
+             allowReset)
 {
-  // PIB Locator
-  std::string pibScheme, pibLocation;
-  std::tie(pibScheme, pibLocation) = parseAndCheckPibLocator(pibLocator);
-  std::string canonicalPibLocator = pibScheme + ":" + pibLocation;
+}
 
+KeyChain::KeyChain(Locator pibLocator, Locator tpmLocator, bool allowReset)
+{
   // Create PIB
-  m_pib = createPib(canonicalPibLocator);
-  std::string oldTpmLocator;
-  try {
-    oldTpmLocator = m_pib->getTpmLocator();
-  }
-  catch (const Pib::Error&) {
-    // TPM locator is not set in PIB yet.
-  }
+  auto pibFactory = getPibFactories().find(pibLocator.scheme);
+  BOOST_ASSERT(pibFactory != getPibFactories().end());
+  m_pib.reset(new Pib(pibLocator.canonical(), pibFactory->second(pibLocator.location)));
 
-  // TPM Locator
-  std::string tpmScheme, tpmLocation;
-  std::tie(tpmScheme, tpmLocation) = parseAndCheckTpmLocator(tpmLocator);
-  std::string canonicalTpmLocator = tpmScheme + ":" + tpmLocation;
-
-  if (canonicalPibLocator == getDefaultPibLocator()) {
+  // Figure out the TPM Locator
+  std::string oldTpmLocator = m_pib->getTpmLocator();
+  if (pibLocator == getDefaultPibLocator()) {
     // Default PIB must use default TPM
-    if (!oldTpmLocator.empty() && oldTpmLocator != getDefaultTpmLocator()) {
+    if (!oldTpmLocator.empty() && oldTpmLocator != getDefaultTpmLocator().canonical()) {
       m_pib->reset();
-      canonicalTpmLocator = getDefaultTpmLocator();
+      tpmLocator = getDefaultTpmLocator();
     }
   }
   else {
     // non-default PIB check consistency
-    if (!oldTpmLocator.empty() && oldTpmLocator != canonicalTpmLocator) {
+    if (!oldTpmLocator.empty() && oldTpmLocator != tpmLocator.canonical()) {
       if (allowReset)
         m_pib->reset();
       else
-        NDN_THROW(LocatorMismatchError("TPM locator supplied does not match TPM locator in PIB: " +
-                                       oldTpmLocator + " != " + canonicalTpmLocator));
+        NDN_THROW(LocatorMismatchError("Supplied TPM locator (" + tpmLocator.canonical() +
+                                       ") does not match TPM locator in PIB (" + oldTpmLocator + ")"));
     }
   }
-
-  // note that key mismatch may still happen if the TPM locator is initially set to a
+  // Note that key mismatch may still happen if the TPM locator is initially set to a
   // wrong one or if the PIB was shared by more than one TPMs before.  This is due to the
-  // old PIB does not have TPM info, new pib should not have this problem.
-  m_tpm = createTpm(canonicalTpmLocator);
-  m_pib->setTpmLocator(canonicalTpmLocator);
+  // old PIB not having TPM info, the new PIB should not have this problem.
+
+  // Create TPM
+  auto tpmFactory = getTpmFactories().find(tpmLocator.scheme);
+  BOOST_ASSERT(tpmFactory != getTpmFactories().end());
+  m_tpm.reset(new Tpm(tpmLocator.canonical(), tpmFactory->second(tpmLocator.location)));
+
+  // Link PIB with TPM
+  m_pib->setTpmLocator(tpmLocator.canonical());
 }
 
 KeyChain::~KeyChain() = default;
@@ -498,28 +485,28 @@
     transform::PublicKey pub;
     pub.loadPkcs8(pkcs8);
   }
-  catch (const transform::PublicKey::Error& e) {
+  catch (const transform::PublicKey::Error&) {
     NDN_THROW_NESTED(std::invalid_argument("Certificate request contains invalid public key"));
   }
 
   return makeCertificate(extractKeyNameFromCertName(certRequest.getName()), pkcs8, params, opts);
 }
 
-// public: PIB/TPM creation helpers
+// private: PIB/TPM locator helpers
 
-static inline std::tuple<std::string/*type*/, std::string/*location*/>
+static std::tuple<std::string/*scheme*/, std::string/*location*/>
 parseLocatorUri(const std::string& uri)
 {
-  size_t pos = uri.find(':');
+  auto pos = uri.find(':');
   if (pos != std::string::npos) {
-    return std::make_tuple(uri.substr(0, pos), uri.substr(pos + 1));
+    return {uri.substr(0, pos), uri.substr(pos + 1)};
   }
   else {
-    return std::make_tuple(uri, "");
+    return {uri, ""};
   }
 }
 
-std::tuple<std::string/*type*/, std::string/*location*/>
+KeyChain::Locator
 KeyChain::parseAndCheckPibLocator(const std::string& pibLocator)
 {
   std::string pibScheme, pibLocation;
@@ -534,20 +521,10 @@
     NDN_THROW(Error("PIB scheme `" + pibScheme + "` is not supported"));
   }
 
-  return std::make_tuple(pibScheme, pibLocation);
+  return {pibScheme, pibLocation};
 }
 
-unique_ptr<Pib>
-KeyChain::createPib(const std::string& pibLocator)
-{
-  std::string pibScheme, pibLocation;
-  std::tie(pibScheme, pibLocation) = parseAndCheckPibLocator(pibLocator);
-  auto pibFactory = getPibFactories().find(pibScheme);
-  BOOST_ASSERT(pibFactory != getPibFactories().end());
-  return unique_ptr<Pib>(new Pib(pibScheme, pibLocation, pibFactory->second(pibLocation)));
-}
-
-std::tuple<std::string/*type*/, std::string/*location*/>
+KeyChain::Locator
 KeyChain::parseAndCheckTpmLocator(const std::string& tpmLocator)
 {
   std::string tpmScheme, tpmLocation;
@@ -562,19 +539,60 @@
     NDN_THROW(Error("TPM scheme `" + tpmScheme + "` is not supported"));
   }
 
-  return std::make_tuple(tpmScheme, tpmLocation);
+  return {tpmScheme, tpmLocation};
 }
 
-unique_ptr<Tpm>
-KeyChain::createTpm(const std::string& tpmLocator)
+const KeyChain::Locator&
+KeyChain::getDefaultPibLocator()
 {
-  std::string tpmScheme, tpmLocation;
-  std::tie(tpmScheme, tpmLocation) = parseAndCheckTpmLocator(tpmLocator);
-  auto tpmFactory = getTpmFactories().find(tpmScheme);
-  BOOST_ASSERT(tpmFactory != getTpmFactories().end());
-  return unique_ptr<Tpm>(new Tpm(tpmScheme, tpmLocation, tpmFactory->second(tpmLocation)));
+  if (!s_defaultPibLocator.empty())
+    return s_defaultPibLocator;
+
+  std::string input;
+  const char* pibEnv = std::getenv("NDN_CLIENT_PIB");
+  if (pibEnv != nullptr) {
+    input = pibEnv;
+  }
+  else {
+    ConfigFile config;
+    input = config.getParsedConfiguration().get<std::string>("pib", getDefaultPibScheme());
+  }
+
+  s_defaultPibLocator = parseAndCheckPibLocator(input);
+  BOOST_ASSERT(!s_defaultPibLocator.empty());
+  return s_defaultPibLocator;
 }
 
+const KeyChain::Locator&
+KeyChain::getDefaultTpmLocator()
+{
+  if (!s_defaultTpmLocator.empty())
+    return s_defaultTpmLocator;
+
+  std::string input;
+  const char* tpmEnv = std::getenv("NDN_CLIENT_TPM");
+  if (tpmEnv != nullptr) {
+    input = tpmEnv;
+  }
+  else {
+    ConfigFile config;
+    input = config.getParsedConfiguration().get<std::string>("tpm", getDefaultTpmScheme());
+  }
+
+  s_defaultTpmLocator = parseAndCheckTpmLocator(input);
+  BOOST_ASSERT(!s_defaultTpmLocator.empty());
+  return s_defaultTpmLocator;
+}
+
+#ifdef NDN_CXX_HAVE_TESTS
+void
+KeyChain::resetDefaultLocators()
+{
+  s_defaultPibLocator = {};
+  s_defaultTpmLocator = {};
+}
+#endif
+
 // private: signing
 
 Certificate
diff --git a/ndn-cxx/security/key-chain.hpp b/ndn-cxx/security/key-chain.hpp
index 2fa84ca..12123bd 100644
--- a/ndn-cxx/security/key-chain.hpp
+++ b/ndn-cxx/security/key-chain.hpp
@@ -113,24 +113,22 @@
   /**
    * @brief Constructor to create KeyChain with default PIB and TPM.
    *
-   * Default PIB and TPM are platform-dependent and can be overriden system-wide or
-   * individually for the user.
+   * The default PIB and TPM are platform-dependent and can be overridden system-wide
+   * or on a per-user or even per-application basis.
    *
-   * @sa manpage ndn-client.conf
-   *
-   * @todo Add detailed description about config file behavior here
+   * @sa man ndn-client.conf(5)
    */
   KeyChain();
 
   /**
-   * @brief KeyChain constructor
-   *
-   * @sa manpage ndn-client.conf
+   * @brief KeyChain constructor.
    *
    * @param pibLocator PIB locator, e.g., `pib-sqlite3:/example/dir`
    * @param tpmLocator TPM locator, e.g., `tpm-memory:`
    * @param allowReset if true, the PIB will be reset when the supplied @p tpmLocator
    *                   does not match the one in the PIB
+   *
+   * @sa man ndn-client.conf(5)
    */
   KeyChain(const std::string& pibLocator, const std::string& tpmLocator, bool allowReset = false);
 
@@ -402,36 +400,36 @@
 
 public: // PIB & TPM backend registry
   /**
-   * @brief Register a new PIB backend
-   * @param scheme Name for the registered PIB backend scheme
-   *
-   * @note This interface is implementation detail and may change without notice.
+   * @brief Register a new PIB backend type.
+   * @param scheme Unique identifier for the registered PIB backend type.
    */
   template<class PibBackendType>
   static void
   registerPibBackend(const std::string& scheme)
   {
-    getPibFactories().emplace(scheme, [] (const std::string& locator) {
-      return shared_ptr<pib::PibImpl>(new PibBackendType(locator));
+    getPibFactories().emplace(scheme, [] (const std::string& location) {
+      return shared_ptr<pib::PibImpl>(new PibBackendType(location));
     });
   }
 
   /**
-   * @brief Register a new TPM backend
-   * @param scheme Name for the registered TPM backend scheme
-   *
-   * @note This interface is implementation detail and may change without notice.
+   * @brief Register a new TPM backend type.
+   * @param scheme Unique identifier for the registered TPM backend type.
    */
   template<class TpmBackendType>
   static void
   registerTpmBackend(const std::string& scheme)
   {
-    getTpmFactories().emplace(scheme, [] (const std::string& locator) {
-      return unique_ptr<tpm::BackEnd>(new TpmBackendType(locator));
+    getTpmFactories().emplace(scheme, [] (const std::string& location) {
+      return unique_ptr<tpm::BackEnd>(new TpmBackendType(location));
     });
   }
 
 private:
+  class Locator;
+
+  KeyChain(Locator pibLocator, Locator tpmLocator, bool allowReset);
+
   using PibFactories = std::map<std::string, std::function<shared_ptr<pib::PibImpl>(const std::string&)>>;
   using TpmFactories = std::map<std::string, std::function<unique_ptr<tpm::BackEnd>(const std::string&)>>;
 
@@ -441,37 +439,24 @@
   static TpmFactories&
   getTpmFactories();
 
-  static std::tuple<std::string/*type*/, std::string/*location*/>
+  static Locator
   parseAndCheckPibLocator(const std::string& pibLocator);
 
-  static std::tuple<std::string/*type*/, std::string/*location*/>
+  static Locator
   parseAndCheckTpmLocator(const std::string& tpmLocator);
 
-  static const std::string&
-  getDefaultPibScheme();
-
-  static const std::string&
-  getDefaultTpmScheme();
-
-  /**
-    * @brief Create a PIB according to @p pibLocator
-    */
-  static unique_ptr<Pib>
-  createPib(const std::string& pibLocator);
-
-  /**
-   * @brief Create a TPM according to @p tpmLocator
-   */
-  static unique_ptr<Tpm>
-  createTpm(const std::string& tpmLocator);
-
 NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
-  static const std::string&
+  static const Locator&
   getDefaultPibLocator();
 
-  static const std::string&
+  static const Locator&
   getDefaultTpmLocator();
 
+#ifdef NDN_CXX_HAVE_TESTS
+  static void
+  resetDefaultLocators();
+#endif
+
   /**
    * @brief Derive SignatureTypeValue according to key type and digest algorithm.
    */
@@ -526,17 +511,15 @@
   unique_ptr<Pib> m_pib;
   unique_ptr<Tpm> m_tpm;
 
-  static std::string s_defaultPibLocator;
-  static std::string s_defaultTpmLocator;
+  static Locator s_defaultPibLocator;
+  static Locator s_defaultTpmLocator;
 };
 
 /**
  * @brief Register Pib backend class in KeyChain
  *
  * This macro should be placed once in the implementation file of the
- * Pib backend class within the namespace where the type is declared.
- *
- * @note This interface is an implementation detail and may change without notice.
+ * Pib backend class, inside the namespace where the type is declared.
  */
 #define NDN_CXX_KEYCHAIN_REGISTER_PIB_BACKEND(PibType)     \
 static class NdnCxxAuto ## PibType ## PibRegistrationClass    \
@@ -552,9 +535,7 @@
  * @brief Register Tpm backend class in KeyChain
  *
  * This macro should be placed once in the implementation file of the
- * Tpm backend class within the namespace where the type is declared.
- *
- * @note This interface is an implementation detail and may change without notice.
+ * Tpm backend class, inside the namespace where the type is declared.
  */
 #define NDN_CXX_KEYCHAIN_REGISTER_TPM_BACKEND(TpmType)     \
 static class NdnCxxAuto ## TpmType ## TpmRegistrationClass    \
diff --git a/ndn-cxx/security/pib/pib-impl.hpp b/ndn-cxx/security/pib/pib-impl.hpp
index bdf742b..3cad8e4 100644
--- a/ndn-cxx/security/pib/pib-impl.hpp
+++ b/ndn-cxx/security/pib/pib-impl.hpp
@@ -57,21 +57,21 @@
   virtual
   ~PibImpl() = default;
 
-public: // TpmLocator management
+public: // TPM Locator management
   /**
-   * @brief Set the corresponding TPM information to @p tpmLocator
-   *
-   * This method does not reset contents of the PIB
-   */
-  virtual void
-  setTpmLocator(const std::string& tpmLocator) = 0;
-
-  /**
-   * @brief Get TPM Locator
+   * @brief Return the associated TPM Locator or an empty string if unset.
    */
   virtual std::string
   getTpmLocator() const = 0;
 
+  /**
+   * @brief Set the associated TPM information to @p tpmLocator.
+   *
+   * This method does *not* reset the contents of the PIB.
+   */
+  virtual void
+  setTpmLocator(const std::string& tpmLocator) = 0;
+
 public: // Identity management
   /**
    * @brief Check the existence of an identity.
diff --git a/ndn-cxx/security/pib/pib.cpp b/ndn-cxx/security/pib/pib.cpp
index 936a5ec..8fb52cc 100644
--- a/ndn-cxx/security/pib/pib.cpp
+++ b/ndn-cxx/security/pib/pib.cpp
@@ -29,9 +29,8 @@
 
 NDN_LOG_INIT(ndn.security.Pib);
 
-Pib::Pib(const std::string& scheme, const std::string& location, shared_ptr<PibImpl> impl)
-  : m_scheme(scheme)
-  , m_location(location)
+Pib::Pib(const std::string& locator, shared_ptr<PibImpl> impl)
+  : m_locator(locator)
   , m_impl(std::move(impl))
   , m_identities(m_impl)
 {
@@ -41,9 +40,9 @@
 Pib::~Pib() = default;
 
 std::string
-Pib::getPibLocator() const
+Pib::getTpmLocator() const
 {
-  return m_scheme + ":" + m_location;
+  return m_impl->getTpmLocator();
 }
 
 void
@@ -58,16 +57,6 @@
   m_impl->setTpmLocator(tpmLocator);
 }
 
-std::string
-Pib::getTpmLocator() const
-{
-  auto tpmLocator = m_impl->getTpmLocator();
-  if (tpmLocator.empty()) {
-    NDN_THROW(Pib::Error("TPM info does not exist"));
-  }
-  return tpmLocator;
-}
-
 void
 Pib::reset()
 {
diff --git a/ndn-cxx/security/pib/pib.hpp b/ndn-cxx/security/pib/pib.hpp
index 837e029..e6a26bf 100644
--- a/ndn-cxx/security/pib/pib.hpp
+++ b/ndn-cxx/security/pib/pib.hpp
@@ -62,19 +62,19 @@
   ~Pib();
 
   /**
-   * @brief Return the scheme of the PIB Locator.
+   * @brief Return the PIB Locator.
    */
   const std::string&
-  getScheme() const
+  getPibLocator() const
   {
-    return m_scheme;
+    return m_locator;
   }
 
   /**
-   * @brief Return the PIB Locator.
+   * @brief Return the associated TPM Locator or an empty string if unset.
    */
   std::string
-  getPibLocator() const;
+  getTpmLocator() const;
 
   /**
    * @brief Set the associated TPM information to @p tpmLocator.
@@ -84,13 +84,6 @@
   setTpmLocator(const std::string& tpmLocator);
 
   /**
-   * @brief Return the associated TPM Locator.
-   * @throws Error TPM locator is not set
-   */
-  std::string
-  getTpmLocator() const;
-
-  /**
    * @brief Reset the contents of the PIB, including reset of the TPM Locator.
    */
   void
@@ -120,11 +113,10 @@
   /**
    * @brief Create a Pib instance.
    *
-   * @param scheme The scheme for the Pib
-   * @param location The location for the Pib
+   * @param locator The PIB locator
    * @param impl The backend implementation
    */
-  Pib(const std::string& scheme, const std::string& location, shared_ptr<PibImpl> impl);
+  Pib(const std::string& locator, shared_ptr<PibImpl> impl);
 
   /**
    * @brief Add an identity.
@@ -155,8 +147,7 @@
   setDefaultIdentity(const Name& identity);
 
 private:
-  const std::string m_scheme;
-  const std::string m_location;
+  const std::string m_locator;
   const shared_ptr<PibImpl> m_impl;
 
   IdentityContainer m_identities;
diff --git a/ndn-cxx/security/tpm/impl/back-end-file.cpp b/ndn-cxx/security/tpm/impl/back-end-file.cpp
index 67d23ab..8bf11b4 100644
--- a/ndn-cxx/security/tpm/impl/back-end-file.cpp
+++ b/ndn-cxx/security/tpm/impl/back-end-file.cpp
@@ -96,7 +96,7 @@
 const std::string&
 BackEndFile::getScheme()
 {
-  static std::string scheme = "tpm-file";
+  static const std::string scheme("tpm-file");
   return scheme;
 }
 
diff --git a/ndn-cxx/security/tpm/impl/back-end-mem.cpp b/ndn-cxx/security/tpm/impl/back-end-mem.cpp
index 094c7af..f80c0f8 100644
--- a/ndn-cxx/security/tpm/impl/back-end-mem.cpp
+++ b/ndn-cxx/security/tpm/impl/back-end-mem.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2021 Regents of the University of California.
+ * Copyright (c) 2013-2022 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -50,14 +50,14 @@
 const std::string&
 BackEndMem::getScheme()
 {
-  static std::string scheme = "tpm-memory";
+  static const std::string scheme("tpm-memory");
   return scheme;
 }
 
 bool
 BackEndMem::doHasKey(const Name& keyName) const
 {
-  return (m_impl->keys.count(keyName) > 0);
+  return m_impl->keys.count(keyName) > 0;
 }
 
 unique_ptr<KeyHandle>
diff --git a/ndn-cxx/security/tpm/impl/back-end-osx.cpp b/ndn-cxx/security/tpm/impl/back-end-osx.cpp
index 6bdb17e..654d957 100644
--- a/ndn-cxx/security/tpm/impl/back-end-osx.cpp
+++ b/ndn-cxx/security/tpm/impl/back-end-osx.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2021 Regents of the University of California.
+ * Copyright (c) 2013-2022 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -202,7 +202,7 @@
 const std::string&
 BackEndOsx::getScheme()
 {
-  static std::string scheme = "tpm-osxkeychain";
+  static const std::string scheme("tpm-osxkeychain");
   return scheme;
 }
 
diff --git a/ndn-cxx/security/tpm/tpm.cpp b/ndn-cxx/security/tpm/tpm.cpp
index 9722adf..3218be9 100644
--- a/ndn-cxx/security/tpm/tpm.cpp
+++ b/ndn-cxx/security/tpm/tpm.cpp
@@ -29,21 +29,14 @@
 namespace security {
 namespace tpm {
 
-Tpm::Tpm(const std::string& scheme, const std::string& location, unique_ptr<BackEnd> backEnd)
-  : m_scheme(scheme)
-  , m_location(location)
+Tpm::Tpm(const std::string& locator, unique_ptr<BackEnd> backEnd)
+  : m_locator(locator)
   , m_backEnd(std::move(backEnd))
 {
 }
 
 Tpm::~Tpm() = default;
 
-std::string
-Tpm::getTpmLocator() const
-{
-  return m_scheme + ":" + m_location;
-}
-
 bool
 Tpm::hasKey(const Name& keyName) const
 {
diff --git a/ndn-cxx/security/tpm/tpm.hpp b/ndn-cxx/security/tpm/tpm.hpp
index 5fe254a..4c239ed 100644
--- a/ndn-cxx/security/tpm/tpm.hpp
+++ b/ndn-cxx/security/tpm/tpm.hpp
@@ -73,8 +73,14 @@
 
   ~Tpm();
 
-  std::string
-  getTpmLocator() const;
+  /**
+   * @brief Return the TPM Locator.
+   */
+  const std::string&
+  getTpmLocator() const
+  {
+    return m_locator;
+  }
 
   /**
    * @brief Check if a private key exists.
@@ -153,15 +159,14 @@
   NDN_CXX_NODISCARD bool
   unlockTpm(const char* password, size_t passwordLength) const;
 
-NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
+NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE: // operations accessible only by KeyChain
   /**
-   * @brief Create a new TPM instance with the specified @p location.
+   * @brief Create a Tpm instance.
    *
-   * @param scheme The scheme for the TPM
-   * @param location The location for the TPM
-   * @param impl The back-end implementation
+   * @param locator The TPM locator
+   * @param impl The backend implementation
    */
-  Tpm(const std::string& scheme, const std::string& location, unique_ptr<BackEnd> impl);
+  Tpm(const std::string& locator, unique_ptr<BackEnd> impl);
 
   /**
    * @brief Create key for @p identityName according to @p params.
@@ -239,13 +244,11 @@
   findKey(const Name& keyName) const;
 
 private:
-  std::string m_scheme;
-  std::string m_location;
+  const std::string m_locator;
+  const unique_ptr<BackEnd> m_backEnd;
 
   mutable std::unordered_map<Name, unique_ptr<KeyHandle>> m_keys;
 
-  const unique_ptr<BackEnd> m_backEnd;
-
   friend KeyChain;
 };
 
diff --git a/tests/test-home-fixture.hpp b/tests/test-home-fixture.hpp
index 3d4f056..3e3673f 100644
--- a/tests/test-home-fixture.hpp
+++ b/tests/test-home-fixture.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2021 Regents of the University of California.
+ * Copyright (c) 2013-2022 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -77,8 +77,7 @@
     }
 
     boost::filesystem::remove_all(m_pibDir);
-    const_cast<std::string&>(KeyChain::getDefaultPibLocator()).clear();
-    const_cast<std::string&>(KeyChain::getDefaultTpmLocator()).clear();
+    KeyChain::resetDefaultLocators();
   }
 
 protected:
diff --git a/tests/unit/security/key-chain.t.cpp b/tests/unit/security/key-chain.t.cpp
index ba84081..f01aab9 100644
--- a/tests/unit/security/key-chain.t.cpp
+++ b/tests/unit/security/key-chain.t.cpp
@@ -53,19 +53,7 @@
 
   ~TestHomeAndPibFixture()
   {
-    try {
-      const_cast<std::string&>(KeyChain::getDefaultPibLocator()).clear();
-    }
-    catch (const KeyChain::Error&) {
-      // ignore
-    }
-
-    try {
-      const_cast<std::string&>(KeyChain::getDefaultTpmLocator()).clear();
-    }
-    catch (const KeyChain::Error&) {
-      // ignore
-    }
+    KeyChain::resetDefaultLocators();
   }
 };
 
@@ -78,8 +66,6 @@
 {
   createClientConf({"pib=pib-memory:", "tpm=tpm-memory:"});
 
-  BOOST_REQUIRE_NO_THROW(KeyChain());
-
   KeyChain keyChain;
   BOOST_CHECK_EQUAL(keyChain.getPib().getPibLocator(), "pib-memory:");
   BOOST_CHECK_EQUAL(keyChain.getPib().getTpmLocator(), "tpm-memory:");
@@ -110,7 +96,6 @@
     unsetenv("HOME");
 #endif
 
-  BOOST_REQUIRE_NO_THROW(KeyChain());
   KeyChain keyChain;
   BOOST_CHECK_EQUAL(keyChain.getPib().getPibLocator(), "pib-memory:");
 
@@ -144,8 +129,6 @@
 {
   createClientConf({"tpm=tpm-memory:"});
 
-  BOOST_REQUIRE_NO_THROW(KeyChain());
-
   KeyChain keyChain;
   BOOST_CHECK_EQUAL(keyChain.getPib().getPibLocator(), "pib-sqlite3:");
   BOOST_CHECK_EQUAL(keyChain.getPib().getTpmLocator(), "tpm-memory:");
@@ -200,14 +183,13 @@
 
 BOOST_AUTO_TEST_CASE(KeyChainWithCustomTpmAndPib)
 {
-  BOOST_REQUIRE_NO_THROW((KeyChain("pib-memory", "tpm-memory")));
-  BOOST_REQUIRE_NO_THROW((KeyChain("pib-memory:", "tpm-memory:")));
-  BOOST_REQUIRE_NO_THROW((KeyChain("pib-memory:/something", "tpm-memory:/something")));
-
   KeyChain keyChain("pib-memory", "tpm-memory");
   BOOST_CHECK_EQUAL(keyChain.getPib().getPibLocator(), "pib-memory:");
   BOOST_CHECK_EQUAL(keyChain.getPib().getTpmLocator(), "tpm-memory:");
   BOOST_CHECK_EQUAL(keyChain.getTpm().getTpmLocator(), "tpm-memory:");
+
+  BOOST_CHECK_NO_THROW(KeyChain("pib-memory:", "tpm-memory:"));
+  BOOST_CHECK_NO_THROW(KeyChain("pib-memory:/something", "tpm-memory:/something"));
 }
 
 BOOST_FIXTURE_TEST_CASE(SigningWithCorruptedPibTpm, KeyChainFixture)
diff --git a/tests/unit/security/pib/pib-impl.t.cpp b/tests/unit/security/pib/pib-impl.t.cpp
index 3d579c6..d88bad6 100644
--- a/tests/unit/security/pib/pib-impl.t.cpp
+++ b/tests/unit/security/pib/pib-impl.t.cpp
@@ -66,9 +66,8 @@
 BOOST_FIXTURE_TEST_CASE_TEMPLATE(TpmLocator, T, PibImpls, T)
 {
   // Basic getting and setting
-  BOOST_CHECK_NO_THROW(this->pib.getTpmLocator());
-
-  BOOST_CHECK_NO_THROW(this->pib.setTpmLocator("tpmLocator"));
+  BOOST_CHECK_EQUAL(this->pib.getTpmLocator(), "");
+  this->pib.setTpmLocator("tpmLocator");
   BOOST_CHECK_EQUAL(this->pib.getTpmLocator(), "tpmLocator");
 
   // Add cert, and do not change TPM locator
@@ -101,7 +100,6 @@
   // add id1, should be default
   this->pib.addIdentity(this->id1);
   BOOST_CHECK_EQUAL(this->pib.hasIdentity(this->id1), true);
-  BOOST_CHECK_NO_THROW(this->pib.getDefaultIdentity());
   BOOST_CHECK_EQUAL(this->pib.getDefaultIdentity(), this->id1);
 
   // add id2, should not be default
@@ -164,8 +162,7 @@
   BOOST_CHECK_EQUAL(this->pib.hasKey(this->id1Key1Name), true);
   BOOST_CHECK_EQUAL(this->pib.hasIdentity(this->id1), true);
   const Buffer& keyBits = this->pib.getKeyBits(this->id1Key1Name);
-  BOOST_CHECK(keyBits == this->id1Key1);
-  BOOST_CHECK_NO_THROW(this->pib.getDefaultKeyOfIdentity(this->id1));
+  BOOST_TEST(keyBits == this->id1Key1, boost::test_tools::per_element());
   BOOST_CHECK_EQUAL(this->pib.getDefaultKeyOfIdentity(this->id1), this->id1Key1Name);
 
   // add id1Key2, should not be default
@@ -221,7 +218,6 @@
   BOOST_CHECK_EQUAL(this->pib.hasKey(this->id1Key1Name), true);
   BOOST_CHECK_EQUAL(this->pib.getCertificate(this->id1Key1Cert1.getName()).wireEncode(),
                     this->id1Key1Cert1.wireEncode());
-  BOOST_CHECK_NO_THROW(this->pib.getDefaultCertificateOfKey(this->id1Key1Name));
   BOOST_CHECK_EQUAL(this->pib.getDefaultCertificateOfKey(this->id1Key1Name), this->id1Key1Cert1);
 
   // add id1Key1Cert2, should not be default
diff --git a/tests/unit/security/pib/pib.t.cpp b/tests/unit/security/pib/pib.t.cpp
index 929082e..8d668e5 100644
--- a/tests/unit/security/pib/pib.t.cpp
+++ b/tests/unit/security/pib/pib.t.cpp
@@ -38,13 +38,13 @@
 
 BOOST_AUTO_TEST_CASE(TpmLocator)
 {
-  Pib pib("pib-memory", "", make_shared<PibMemory>());
+  Pib pib("pib-memory:", make_shared<PibMemory>());
 
   BOOST_CHECK_EQUAL(pib.getPibLocator(), "pib-memory:");
-  BOOST_CHECK_THROW(pib.getTpmLocator(), Pib::Error);
+  BOOST_CHECK_EQUAL(pib.getTpmLocator(), "");
 
   pib.setTpmLocator("test-tpm-locator");
-  BOOST_CHECK_NO_THROW(pib.getTpmLocator());
+  BOOST_CHECK_EQUAL(pib.getTpmLocator(), "test-tpm-locator");
 
   BOOST_CHECK_THROW(pib.getIdentity(id1), Pib::Error);
   pib.addIdentity(id1);
@@ -52,17 +52,18 @@
 
   pib.setTpmLocator("another-tpm-locator");
   BOOST_CHECK_THROW(pib.getIdentity(id1), Pib::Error);
+  BOOST_CHECK_EQUAL(pib.getTpmLocator(), "another-tpm-locator");
 
   pib.addIdentity(id1);
   BOOST_CHECK_NO_THROW(pib.getIdentity(id1));
   pib.reset();
   BOOST_CHECK_THROW(pib.getIdentity(id1), Pib::Error);
-  BOOST_CHECK_THROW(pib.getTpmLocator(), Pib::Error);
+  BOOST_CHECK_EQUAL(pib.getTpmLocator(), "");
 }
 
 BOOST_AUTO_TEST_CASE(IdentityOperations)
 {
-  Pib pib("pib-memory", "", make_shared<PibMemory>());
+  Pib pib("pib-memory:", make_shared<PibMemory>());
 
   // PIB starts with no identities
   BOOST_CHECK_EQUAL(pib.getIdentities().size(), 0);