security: Add new v2::KeyChain

Change-Id: I5fdf51ecd96b50db2a7cbf730c6e8b1d9fbe09e9
Refs: #2926
diff --git a/src/security/tpm/back-end-file.cpp b/src/security/tpm/back-end-file.cpp
index f16d7cf..1adcf1c 100644
--- a/src/security/tpm/back-end-file.cpp
+++ b/src/security/tpm/back-end-file.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).
  *
@@ -83,6 +83,13 @@
 
 BackEndFile::~BackEndFile() = default;
 
+const std::string&
+BackEndFile::getScheme()
+{
+  static std::string scheme = "tpm-file";
+  return scheme;
+}
+
 bool
 BackEndFile::doHasKey(const Name& keyName) const
 {
diff --git a/src/security/tpm/back-end-file.hpp b/src/security/tpm/back-end-file.hpp
index 02b575f..db58907 100644
--- a/src/security/tpm/back-end-file.hpp
+++ b/src/security/tpm/back-end-file.hpp
@@ -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).
  *
@@ -52,11 +52,18 @@
   };
 
 public:
+  /**
+   * @brief Create file-based TPM backend
+   * @param location Directory to store private keys
+   */
   explicit
   BackEndFile(const std::string& location = "");
 
   ~BackEndFile() override;
 
+  static const std::string&
+  getScheme();
+
 private: // inherited from tpm::BackEnd
   /**
    * @return True if a key with name @p keyName exists in TPM.
@@ -87,14 +94,14 @@
   /**
    * @brief Delete a key with name @p keyName.
    *
-   * @throws Error if the deletion fails.
+   * @throw Error the deletion failed
    */
   void
   doDeleteKey(const Name& keyName) final;
 
   /**
    * @return A private key with name @p keyName in encrypted PKCS #8 format using password @p pw
-   * @throws Error if the key cannot be exported, e.g., not enough privilege
+   * @throw Error the key cannot be exported, e.g., not enough privilege
    */
   ConstBufferPtr
   doExportKey(const Name& keyName, const char* pw, size_t pwLen) final;
@@ -107,7 +114,7 @@
    * @param size The size of the key in encrypted PKCS #8 format
    * @param pw The password to decrypt the key
    * @param pwLen The length of the password
-   * @throws Error if import fails.
+   * @throw Error import failed
    */
   void
   doImportKey(const Name& keyName, const uint8_t* buf, size_t size, const char* pw, size_t pwLen) final;
diff --git a/src/security/tpm/back-end-mem.cpp b/src/security/tpm/back-end-mem.cpp
index beac9db..9d051c6 100644
--- a/src/security/tpm/back-end-mem.cpp
+++ b/src/security/tpm/back-end-mem.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).
  *
@@ -37,13 +37,20 @@
   std::unordered_map<Name, shared_ptr<PrivateKey>> keys;
 };
 
-BackEndMem::BackEndMem()
+BackEndMem::BackEndMem(const std::string&)
   : m_impl(new Impl)
 {
 }
 
 BackEndMem::~BackEndMem() = default;
 
+const std::string&
+BackEndMem::getScheme()
+{
+  static std::string scheme = "tpm-memory";
+  return scheme;
+}
+
 bool
 BackEndMem::doHasKey(const Name& keyName) const
 {
diff --git a/src/security/tpm/back-end-mem.hpp b/src/security/tpm/back-end-mem.hpp
index 4253b5e..4bfa212 100644
--- a/src/security/tpm/back-end-mem.hpp
+++ b/src/security/tpm/back-end-mem.hpp
@@ -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).
  *
@@ -45,11 +45,18 @@
   };
 
 public:
+  /**
+   * @brief Create memory-based TPM backend
+   * @param location Not used (required by the TPM-registration interface)
+   */
   explicit
-  BackEndMem();
+  BackEndMem(const std::string& location = "");
 
   ~BackEndMem() override;
 
+  static const std::string&
+  getScheme();
+
 private: // inherited from tpm::BackEnd
 
   /**
@@ -80,14 +87,14 @@
   /**
    * @brief Delete a key with name @p keyName.
    *
-   * @throws Error if the deletion fails.
+   * @throw Error the deletion failed
    */
   void
   doDeleteKey(const Name& keyName) final;
 
   /**
    * @return A private key with name @p keyName in encrypted PKCS #8 format using password @p pw
-   * @throws Error if the key cannot be exported, e.g., not enough privilege
+   * @throw Error the key cannot be exported, e.g., not enough privilege
    */
   ConstBufferPtr
   doExportKey(const Name& keyName, const char* pw, size_t pwLen) final;
@@ -100,7 +107,7 @@
    * @param size The size of the key in encrypted PKCS #8 format
    * @param pw The password to decrypt the key
    * @param pwLen The length of password
-   * @throws Error if import fails.
+   * @throw Error import failed
    */
   void
   doImportKey(const Name& keyName, const uint8_t* buf, size_t size, const char* pw, size_t pwLen) final;
diff --git a/src/security/tpm/back-end-osx.cpp b/src/security/tpm/back-end-osx.cpp
index d423b10..178ae55 100644
--- a/src/security/tpm/back-end-osx.cpp
+++ b/src/security/tpm/back-end-osx.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).
  *
@@ -117,7 +117,7 @@
   }
 }
 
-BackEndOsx::BackEndOsx()
+BackEndOsx::BackEndOsx(const std::string&)
   : m_impl(new Impl)
 {
   SecKeychainSetUserInteractionAllowed(!m_impl->isTerminalMode);
@@ -131,11 +131,11 @@
 
 BackEndOsx::~BackEndOsx() = default;
 
-void
-BackEndOsx::setTerminalMode(bool isTerminal)
+const std::string&
+BackEndOsx::getScheme()
 {
-  m_impl->isTerminalMode = isTerminal;
-  SecKeychainSetUserInteractionAllowed(!isTerminal);
+  static std::string scheme = "tpm-osxkeychain";
+  return scheme;
 }
 
 bool
@@ -144,8 +144,15 @@
   return m_impl->isTerminalMode;
 }
 
+void
+BackEndOsx::setTerminalMode(bool isTerminal) const
+{
+  m_impl->isTerminalMode = isTerminal;
+  SecKeychainSetUserInteractionAllowed(!isTerminal);
+}
+
 bool
-BackEndOsx::isLocked() const
+BackEndOsx::isTpmLocked() const
 {
   SecKeychainStatus keychainStatus;
 
@@ -157,22 +164,22 @@
 }
 
 bool
-BackEndOsx::unlockTpm(const char* password, size_t passwordLength)
+BackEndOsx::unlockTpm(const char* pw, size_t pwLen) const
 {
   // If the default key chain is already unlocked, return immediately.
-  if (!isLocked())
+  if (!isTpmLocked())
     return true;
 
   if (m_impl->isTerminalMode) {
     // Use the supplied password.
-    SecKeychainUnlock(m_impl->keyChainRef, passwordLength, password, true);
+    SecKeychainUnlock(m_impl->keyChainRef, pwLen, pw, true);
   }
   else {
     // If inTerminal is not set, get the password from GUI.
     SecKeychainUnlock(m_impl->keyChainRef, 0, nullptr, false);
   }
 
-  return !isLocked();
+  return !isTpmLocked();
 }
 
 ConstBufferPtr
diff --git a/src/security/tpm/back-end-osx.hpp b/src/security/tpm/back-end-osx.hpp
index 0fcd49f..29465c8 100644
--- a/src/security/tpm/back-end-osx.hpp
+++ b/src/security/tpm/back-end-osx.hpp
@@ -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).
  *
@@ -34,7 +34,7 @@
 namespace tpm {
 
 /**
- * @brief The back-end implementation of TPM based on OS X KeyChain service.
+ * @brief The back-end implementation of TPM based on macOS Keychain Services.
  */
 class BackEndOsx : public BackEnd
 {
@@ -50,39 +50,30 @@
   };
 
 public:
-  BackEndOsx();
+  /**
+   * @brief Create TPM backed based on macOS KeyChain service
+   * @param location Not used (required by the TPM-registration interface)
+   */
+  explicit
+  BackEndOsx(const std::string& location = "");
 
   ~BackEndOsx() override;
 
+  static const std::string&
+  getScheme();
+
 public: // management
-  /**
-   * @brief Set the terminal mode of TPM.
-   *
-   * In terminal mode, TPM will not ask user permission from GUI.
-   */
+  bool
+  isTerminalMode() const final;
+
   void
-  setTerminalMode(bool isTerminal);
+  setTerminalMode(bool isTerminal) const final;
 
-  /**
-   * @brief Check if TPM is in terminal mode
-   */
   bool
-  isTerminalMode() const;
+  isTpmLocked() const final;
 
-  /**
-   * @return True if TPM is locked, otherwise false
-   */
   bool
-  isLocked() const;
-
-  /**
-   * @brief Unlock TPM
-   *
-   * @param password       The password to unlock TPM
-   * @param passwordLength The password size.
-   */
-  bool
-  unlockTpm(const char* password = nullptr, size_t passwordLength = 0);
+  unlockTpm(const char* pw, size_t pwLen) const final;
 
 public: // crypto transformation
   /**
@@ -125,14 +116,14 @@
   /**
    * @brief Delete a key with name @p keyName.
    *
-   * @throws Error if the deletion fails.
+   * @throw Error the deletion failed
    */
   void
   doDeleteKey(const Name& keyName) final;
 
   /**
    * @return A private key with name @p keyName in encrypted PKCS #8 format using password @p pw
-   * @throws Error if the key cannot be exported, e.g., not enough privilege
+   * @throw Error the key cannot be exported, e.g., not enough privilege
    */
   ConstBufferPtr
   doExportKey(const Name& keyName, const char* pw, size_t pwLen) final;
@@ -145,7 +136,7 @@
    * @param size The size of the key in encrypted PKCS #8 format
    * @param pw The password to decrypt the private key
    * @param pwLen The length of the password
-   * @throws Error if import fails
+   * @throw Error import fails
    */
   void
   doImportKey(const Name& keyName, const uint8_t* buf, size_t size, const char* pw, size_t pwLen) final;
diff --git a/src/security/tpm/back-end.cpp b/src/security/tpm/back-end.cpp
index 18df659..72ef5fd 100644
--- a/src/security/tpm/back-end.cpp
+++ b/src/security/tpm/back-end.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).
  *
@@ -66,7 +66,7 @@
       name::Component keyId;
       do {
         keyId = name::Component::fromNumber(random::generateSecureWord64());
-        keyName = v2::constructKeyName(identity, params.getKeyId());
+        keyName = v2::constructKeyName(identity, keyId);
       } while (hasKey(keyName));
 
       const_cast<KeyParams&>(params).setKeyId(keyId);
@@ -133,6 +133,29 @@
   keyHandle.setKeyName(v2::constructKeyName(identity, keyId));
 }
 
+bool
+BackEnd::isTerminalMode() const
+{
+  return true;
+}
+
+void
+BackEnd::setTerminalMode(bool isTerminal) const
+{
+}
+
+bool
+BackEnd::isTpmLocked() const
+{
+  return false;
+}
+
+bool
+BackEnd::unlockTpm(const char* pw, size_t pwLen) const
+{
+  return !isTpmLocked();
+}
+
 } // namespace tpm
 } // namespace security
 } // namespace ndn
diff --git a/src/security/tpm/back-end.hpp b/src/security/tpm/back-end.hpp
index 749b53d..4c55ab2 100644
--- a/src/security/tpm/back-end.hpp
+++ b/src/security/tpm/back-end.hpp
@@ -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).
  *
@@ -77,8 +77,8 @@
    * The key name is set in the returned KeyHandle.
    *
    * @return The handle of the created key.
-   * @throws Tpm::Error if @p params is invalid
-   * @throws Error if the key cannot be created.
+   * @throw Tpm::Error @p params are invalid
+   * @throw Error the key cannot be created
    */
   unique_ptr<KeyHandle>
   createKey(const Name& identity, const KeyParams& params);
@@ -88,15 +88,15 @@
    *
    * Continuing to use existing KeyHandles on a deleted key results in undefined behavior.
    *
-   * @throws Error if the deletion fails.
+   * @throw Error if the deletion fails.
    */
   void
   deleteKey(const Name& keyName);
 
   /**
    * @return A private key with name @p keyName in encrypted PKCS #8 format using password @p pw
-   * @throws Error if the key does not exist
-   * @throws Error if the key cannot be exported, e.g., insufficient privilege
+   * @throw Error the key does not exist
+   * @throw Error the key cannot be exported, e.g., insufficient privilege
    */
   ConstBufferPtr
   exportKey(const Name& keyName, const char* pw, size_t pwLen);
@@ -109,11 +109,48 @@
    * @param pkcs8Len The size of the key in encrypted PKCS #8 format
    * @param pw The password to decrypt the private key
    * @param pwLen The length of the password
-   * @throws Error if import fails.
+   * @throw Error import failed
    */
   void
   importKey(const Name& keyName, const uint8_t* pkcs8, size_t pkcs8Len, const char* pw, size_t pwLen);
 
+  /**
+   * @brief Check if TPM is in terminal mode
+   *
+   * Default implementation always returns true.
+   */
+  virtual bool
+  isTerminalMode() const;
+
+  /**
+   * @brief Set the terminal mode of TPM.
+   *
+   * In terminal mode, TPM will not ask user permission from GUI.
+   *
+   * Default implementation does nothing.
+   */
+  virtual void
+  setTerminalMode(bool isTerminal) const;
+
+  /**
+   * @return True if TPM is locked, otherwise false
+   *
+   * Default implementation always returns false.
+   */
+  virtual bool
+  isTpmLocked() const;
+
+  /**
+   * @brief Unlock TPM
+   *
+   * @param pw    The password to unlock TPM
+   * @param pwLen The password size.
+   *
+   * Default implementation always returns !isTpmLocked()
+   */
+  virtual bool
+  unlockTpm(const char* pw, size_t pwLen) const;
+
 protected: // static helper method
   /**
    * @brief Set the key name in @p keyHandle according to @p identity and @p params
@@ -141,7 +178,7 @@
    * The key name is set in the returned KeyHandle.
    *
    * @return The handle of the created key.
-   * @throws Error when key cannot be created.
+   * @throw Error key cannot be created
    */
   virtual unique_ptr<KeyHandle>
   doCreateKey(const Name& identity, const KeyParams& params) = 0;
@@ -149,14 +186,14 @@
   /**
    * @brief Delete a key with name @p keyName.
    *
-   * @throws Error if the deletion fails.
+   * @throw Error the deletion failed
    */
   virtual void
   doDeleteKey(const Name& keyName) = 0;
 
   /**
    * @return A private key with name @p keyName in encrypted PKCS #8 format using password @p pw
-   * @throws Error if the key cannot be exported, e.g., insufficient privilege
+   * @throw Error the key cannot be exported, e.g., insufficient privilege
    */
   virtual ConstBufferPtr
   doExportKey(const Name& keyName, const char* pw, size_t pwLen) = 0;
@@ -169,7 +206,7 @@
    * @param pkcs8Len The size of the key in PKCS #8 format
    * @param pw The password to decrypt the private key
    * @param pwLen The length of the password
-   * @throws Error if import fails.
+   * @throw Error import failed
    */
   virtual void
   doImportKey(const Name& keyName, const uint8_t* pkcs8, size_t pkcs8Len, const char* pw, size_t pwLen) = 0;
diff --git a/src/security/tpm/tpm.cpp b/src/security/tpm/tpm.cpp
index 234c48d..fad73b9 100644
--- a/src/security/tpm/tpm.cpp
+++ b/src/security/tpm/tpm.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).
  *
@@ -108,6 +108,30 @@
     return key->decrypt(buf, size);
 }
 
+bool
+Tpm::isTerminalMode() const
+{
+  return m_backEnd->isTerminalMode();
+}
+
+void
+Tpm::setTerminalMode(bool isTerminal) const
+{
+  m_backEnd->setTerminalMode(isTerminal);
+}
+
+bool
+Tpm::isTpmLocked() const
+{
+  return m_backEnd->isTpmLocked();
+}
+
+bool
+Tpm::unlockTpm(const char* password, size_t passwordLength) const
+{
+  return m_backEnd->unlockTpm(password, passwordLength);
+}
+
 ConstBufferPtr
 Tpm::exportPrivateKey(const Name& keyName, const char* pw, size_t pwLen)
 {
diff --git a/src/security/tpm/tpm.hpp b/src/security/tpm/tpm.hpp
index 01b22ae..5c985f1 100644
--- a/src/security/tpm/tpm.hpp
+++ b/src/security/tpm/tpm.hpp
@@ -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).
  *
@@ -31,6 +31,11 @@
 
 namespace ndn {
 namespace security {
+
+namespace v2 {
+class KeyChain;
+} // namespace v2
+
 namespace tpm {
 
 class BackEnd;
@@ -48,14 +53,17 @@
  * A TPM consists of a unified front-end interface and a back-end implementation. The front-end
  * cache the handles of private keys which is provided by the back-end implementation.
  *
- * @throw tpm::BackEnd::Error when underlying implementation has non-semantic error.
- * @throw Tpm::Error when there is an semantic error.
+ * @note Tpm instance is created and managed only by v2::KeyChain.  v2::KeyChain::getTpm()
+ *       returns a const reference to the managed Tpm instance, through which it is possible to
+ *       check existence of private keys, get public keys for the private keys, sign, and decrypt
+ *       the supplied buffers using managed private keys.
+ *
+ * @throw BackEnd::Error Failure with the underlying implementation having non-semantic errors
+ * @throw Tpm::Error Failure with semantic error in the underlying implementation
  */
 class Tpm : noncopyable
 {
 public:
-  friend class KeyChain;
-
   class Error : public std::runtime_error
   {
   public:
@@ -106,6 +114,36 @@
   ConstBufferPtr
   decrypt(const uint8_t* buf, size_t size, const Name& keyName) const;
 
+public: // Management
+  /**
+   * @brief Check if TPM is in terminal mode
+   */
+  bool
+  isTerminalMode() const;
+
+  /**
+   * @brief Set the terminal mode of TPM.
+   *
+   * In terminal mode, TPM will not ask user permission from GUI.
+   */
+  void
+  setTerminalMode(bool isTerminal) const;
+
+  /**
+   * @return True if TPM is locked, otherwise false
+   */
+  bool
+  isTpmLocked() const;
+
+  /**
+   * @brief Unlock TPM
+   *
+   * @param password       The password to unlock TPM
+   * @param passwordLength The password size.
+   */
+  bool
+  unlockTpm(const char* password, size_t passwordLength) const;
+
 NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
   /*
    * @brief Create a new TPM instance with the specified @p location
@@ -128,7 +166,7 @@
    * The created key is named as: /<identityName>/[keyId]/KEY
    *
    * @return the key name
-   * @throws Tpm::Error if the key has already existed or the params is invalid
+   * @throw Tpm::Error the key has already existed or the params is invalid
    */
   Name
   createKey(const Name& identityName, const KeyParams& params);
@@ -179,7 +217,6 @@
   }
 
 private:
-
   /**
    * @brief Internal KeyHandle lookup
    *
@@ -195,6 +232,8 @@
   mutable std::unordered_map<Name, unique_ptr<KeyHandle>> m_keys;
 
   unique_ptr<BackEnd> m_backEnd;
+
+  friend class v2::KeyChain;
 };
 
 } // namespace tpm