security: Adjust unlocking TPM process.

Change-Id: Iee8787bb9aaa8e05fab9544bd35ce9fe31eecf29
diff --git a/src/security/key-chain.hpp b/src/security/key-chain.hpp
index 7a3ff42..b9cb2d4 100644
--- a/src/security/key-chain.hpp
+++ b/src/security/key-chain.hpp
@@ -39,6 +39,20 @@
 {
   typedef typename Info::Error InfoError;
 public:
+
+  /**
+   * @brief Unlock key chain
+   *
+   * @param password The password.
+   * @param passwordLength The password size.
+   * @param usePassword True if password parameter is used.
+   */
+  void
+  unlock(const char* password, size_t passwordLength, bool usePassword)
+  { 
+    return Tpm::unlockTpm(password, passwordLength, usePassword); 
+  }
+
   
   /**
    * Create an identity by creating a pair of Key-Signing-Key (KSK) for this identity and a self-signed certificate of the KSK.
@@ -384,7 +398,7 @@
   }
 
   Block
-  exportIdentity(const Name& identity, bool inTerminal = true, std::string passwordStr = "")
+  exportIdentity(const Name& identity, const std::string& passwordStr)
   {
     if (!Info::doesIdentityExist(identity))
       throw InfoError("Identity does not exist!");
@@ -394,7 +408,7 @@
     if(keyName.empty())
       throw InfoError("Default key does not exist!");
 
-    ConstBufferPtr pkcs8 = Tpm::exportPrivateKeyPkcs8FromTpm(keyName, inTerminal, passwordStr);
+    ConstBufferPtr pkcs8 = Tpm::exportPrivateKeyPkcs8FromTpm(keyName, passwordStr);
     Block wireKey(tlv::security::KeyPackage, pkcs8);
 
     Name certName = Info::getDefaultCertificateNameForKey(keyName);
@@ -417,7 +431,7 @@
   }
 
   void
-  importIdentity(const Block& block, bool inTerminal = true, std::string passwordStr = "")
+  importIdentity(const Block& block, const std::string& passwordStr)
   {
     block.parse();
     
@@ -437,7 +451,7 @@
     Block wireKey = block.get(tlv::security::KeyPackage);
     if (Tpm::doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE))
       deleteKey(keyName);
-    Tpm::importPrivateKeyPkcs8IntoTpm(keyName, wireKey.value(), wireKey.value_size(), inTerminal, passwordStr);
+    Tpm::importPrivateKeyPkcs8IntoTpm(keyName, wireKey.value(), wireKey.value_size(), passwordStr);
     shared_ptr<PublicKey> pubKey = Tpm::getPublicKeyFromTpm(keyName.toUri());
     Info::addPublicKey(keyName, KEY_TYPE_RSA, *pubKey); // HACK! We should set key type according to the pkcs8 info.
     Info::setDefaultKeyNameForIdentity(keyName);
diff --git a/src/security/sec-tpm-file.cpp b/src/security/sec-tpm-file.cpp
index ecb8237..d25c593 100644
--- a/src/security/sec-tpm-file.cpp
+++ b/src/security/sec-tpm-file.cpp
@@ -81,8 +81,9 @@
 };
 
 
-SecTpmFile::SecTpmFile(const string & dir)
+SecTpmFile::SecTpmFile(const string& dir)
   : m_impl(new Impl(dir))
+  , m_inTerminal(false)
 {}
 
 void
diff --git a/src/security/sec-tpm-file.hpp b/src/security/sec-tpm-file.hpp
index 5f40200..4887a15 100644
--- a/src/security/sec-tpm-file.hpp
+++ b/src/security/sec-tpm-file.hpp
@@ -25,12 +25,36 @@
   virtual
   ~SecTpmFile() {};
 
-  /**
-   * Generate a pair of asymmetric keys.
-   * @param keyName The name of the key pair.
-   * @param keyType The type of the key pair, e.g. KEY_TYPE_RSA.
-   * @param keySize The size of the key pair.
-   */
+  virtual void
+  setTpmPassword(const uint8_t* password, size_t passwordLength)
+  {}
+
+  virtual void
+  resetTpmPassword()
+  {}
+
+  virtual void
+  setInTerminal(bool inTerminal)
+  {
+    m_inTerminal = inTerminal;
+  }
+
+  virtual bool
+  getInTerminal()
+  {
+    return m_inTerminal;
+  }
+
+  virtual bool
+  locked()
+  {
+    return false;
+  }
+
+  virtual void
+  unlockTpm(const char* password, size_t passwordLength, bool usePassword)
+  {}
+
   virtual void
   generateKeyPairInTpm(const Name & keyName, KeyType keyType, int keySize);
 
@@ -74,6 +98,7 @@
 private:
   class Impl;
   shared_ptr<Impl> m_impl;
+  bool m_inTerminal;
 };
 
 } // namespace ndn
diff --git a/src/security/sec-tpm-memory.hpp b/src/security/sec-tpm-memory.hpp
index 01860e2..5bddf88 100644
--- a/src/security/sec-tpm-memory.hpp
+++ b/src/security/sec-tpm-memory.hpp
@@ -30,6 +30,36 @@
    * From TrustedPlatformModule *
    ******************************/
 
+  virtual void
+  setTpmPassword(const uint8_t* password, size_t passwordLength)
+  {}
+
+  virtual void
+  resetTpmPassword()
+  {}
+
+  virtual void
+  setInTerminal(bool inTerminal)
+  {
+    m_inTerminal = inTerminal;
+  }
+  
+  virtual bool
+  getInTerminal()
+  {
+    return m_inTerminal;
+  }
+
+  virtual bool
+  locked()
+  {
+    return true;
+  }
+
+  virtual void
+  unlockTpm(const char* password, size_t passwordLength, bool usePassword)
+  {}
+
   virtual void 
   generateKeyPairInTpm(const Name& keyName, KeyType keyType, int keySize);
 
@@ -96,6 +126,8 @@
   
   PublicKeyStore  publicKeyStore_;  /**< The map key is the keyName.toUri() */
   PrivateKeyStore privateKeyStore_; /**< The map key is the keyName.toUri() */
+
+  bool m_inTerminal;
 };
 
 } // namespace ndn
diff --git a/src/security/sec-tpm-osx.cpp b/src/security/sec-tpm-osx.cpp
index 94d3bfe..fc04ba0 100644
--- a/src/security/sec-tpm-osx.cpp
+++ b/src/security/sec-tpm-osx.cpp
@@ -33,6 +33,8 @@
 class SecTpmOsx::Impl {
 public:
   Impl()
+    : m_passwordSet(false)
+    , m_inTerminal(false)
   {}
   
   /**
@@ -105,94 +107,140 @@
   ///////////////////////////////////////////////
 public:
   SecKeychainRef m_keyChainRef;
+  bool m_passwordSet;
+  string m_password;
+  bool m_inTerminal;
 };
 
 
 SecTpmOsx::SecTpmOsx()
   : m_impl(new Impl)
 {
-  OSStatus res = SecKeychainCopyDefault(&m_impl->m_keyChainRef);
+  if(m_impl->m_inTerminal)
+    SecKeychainSetUserInteractionAllowed (false);
+  else
+    SecKeychainSetUserInteractionAllowed (true);
 
+  OSStatus res = SecKeychainCopyDefault(&m_impl->m_keyChainRef);
  
   if (res == errSecNoDefaultKeychain) //If no default key chain, create one.
-    {
-      //Get the password for the new key chain.
-      string keyChainName("ndnroot.keychain");
-      cerr << "No Default KeyChain! Create " << keyChainName << ":" << endl;
-      string password;
-      while(!getPassWord(password, keyChainName))
-        {
-          cerr << "Password mismatch!" << endl;
-        }
-
-      //Create the key chain
-      res = SecKeychainCreate(keyChainName.c_str(),    //Keychain path
-                              password.size(),         //Keychain password length
-                              password.c_str(),        //Keychain password
-                              false,                   //User prompt
-                              NULL,                    //Initial access of Keychain
-                              &m_impl->m_keyChainRef); //Keychain reference
-
-      if(res == errSecSuccess)
-        cerr << keyChainName << " has been created!" << endl;
-      else
-        {
-          char* pw = const_cast<char*>(password.c_str());
-          memset(pw, 0, password.size());
-          throw Error("No default keychain!");
-        }
-      
-      //Unlock the default key chain
-      SecKeychainUnlock(m_impl->m_keyChainRef,
-                        password.size(),
-                        password.c_str(),
-                        true);
-      
-      char* pw = const_cast<char*>(password.c_str());
-      memset(pw, 0, password.size());
-      
-      return;
-    }
-
-  //If the default key chain exists, check if it is unlocked
-  SecKeychainStatus keychainStatus;
-  res = SecKeychainGetStatus(m_impl->m_keyChainRef, &keychainStatus);
-  if(kSecUnlockStateStatus & keychainStatus)
-    return;
-  
-
-  //If the default key chain is locked, unlock the key chain
-  bool locked = true;
-  while(locked)
-    {
-      const char* fmt = "Password to unlock the default keychain: ";
-      char* password = NULL;
-      password = getpass(fmt);
-
-      if (!password)
-        {
-          memset(password, 0, strlen(password));
-          continue;
-        }
-
-      res = SecKeychainUnlock(m_impl->m_keyChainRef,
-                              strlen(password),
-                              password,
-                              true);
-
-      memset(password, 0, strlen(password));
-
-      if(res == errSecSuccess)
-        locked = false;
-    }
+    throw Error("No default keychain, create one first!");
 }
 
 SecTpmOsx::~SecTpmOsx(){
   //TODO: implement
 }
 
+void
+SecTpmOsx::setTpmPassword(const uint8_t* password, size_t passwordLength)
+{
+  m_impl->m_passwordSet = true;
+  memset(const_cast<char*>(m_impl->m_password.c_str()), 0, m_impl->m_password.size());
+  m_impl->m_password.clear();
+  m_impl->m_password.append(reinterpret_cast<const char*>(password), passwordLength);
+}
+
+void
+SecTpmOsx::resetTpmPassword()
+{
+  m_impl->m_passwordSet = false;
+  memset(const_cast<char*>(m_impl->m_password.c_str()), 0, m_impl->m_password.size());
+  m_impl->m_password.clear();
+}
+
+void
+SecTpmOsx::setInTerminal(bool inTerminal)
+{
+  m_impl->m_inTerminal = inTerminal;
+  if(inTerminal)
+    SecKeychainSetUserInteractionAllowed (false);
+  else
+    SecKeychainSetUserInteractionAllowed (true);
+}
+
+bool
+SecTpmOsx::getInTerminal()
+{
+  return m_impl->m_inTerminal;
+}
+
+bool
+SecTpmOsx::locked()
+{
+  SecKeychainStatus keychainStatus;
+
+  OSStatus res = SecKeychainGetStatus(m_impl->m_keyChainRef, &keychainStatus);
+  if(res != errSecSuccess)
+    return true;
+  else
+    return ((kSecUnlockStateStatus & keychainStatus) == 0);
+}
+
+void
+SecTpmOsx::unlockTpm(const char* password, size_t passwordLength, bool usePassword)
+{
+  OSStatus res; 
+
+  // If the default key chain is already unlocked, return immediately.
+  if(!locked())
+    return;
+
+  // If the default key chain is locked, unlock the key chain.
+  if(usePassword)
+    {
+      // Use the supplied password.
+      res = SecKeychainUnlock(m_impl->m_keyChainRef,
+                              passwordLength,
+                              password,
+                              true);
+    }
+  else if(m_impl->m_passwordSet)
+    {
+      // If no password supplied, then use the configured password if exists.
+      SecKeychainUnlock(m_impl->m_keyChainRef,
+                        m_impl->m_password.size(),
+                        m_impl->m_password.c_str(),
+                        true);
+    }
+  else if(m_impl->m_inTerminal)
+    {
+      // If no configured password, get password from terminal if inTerminal set.
+      bool locked = true;
+      const char* fmt = "Password to unlock the default keychain: ";
+      int count = 0;
+      
+      while(locked)
+        {
+          if(count > 2)
+            break;
+          
+          char* getPassword = NULL;
+          getPassword = getpass(fmt);
+          count++;
+          
+          if (!getPassword)
+            continue;
+          
+          res = SecKeychainUnlock(m_impl->m_keyChainRef,
+                                  strlen(getPassword),
+                                  getPassword,
+                                  true);
+          
+          memset(getPassword, 0, strlen(getPassword));
+          
+          if(res == errSecSuccess)
+            return;
+        }
+    }
+  else
+    {
+      // If inTerminal is not set, get the password from GUI.
+      SecKeychainUnlock(m_impl->m_keyChainRef, 0, 0, false);
+    }
+}
+
 void 
-SecTpmOsx::generateKeyPairInTpm(const Name & keyName, KeyType keyType, int keySize)
+SecTpmOsx::generateKeyPairInTpmInternal(const Name & keyName, KeyType keyType, int keySize, bool retry)
 { 
     
   if(doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC)){
@@ -222,14 +270,23 @@
   CFRelease(publicKey);
   CFRelease(privateKey);
 
-  if (res != errSecSuccess){
-    _LOG_DEBUG("Fail to create a key pair: " << res);
-    throw Error("Fail to create a key pair");
-  }
+  if (res == errSecSuccess)
+    return;
+  
+  if (res == errSecAuthFailed && !retry)
+    {
+      unlockTpm(0, 0, false);
+      generateKeyPairInTpmInternal(keyName, keyType, keySize, true);
+    }
+  else
+    {
+      _LOG_DEBUG("Fail to create a key pair: " << res);
+      throw Error("Fail to create a key pair");
+    }
 }
 
 void
-SecTpmOsx::deleteKeyPairInTpm(const Name &keyName)
+SecTpmOsx::deleteKeyPairInTpmInternal(const Name &keyName, bool retry)
 {
   CFStringRef keyLabel = CFStringCreateWithCString(NULL, 
                                                    keyName.toUri().c_str(), 
@@ -241,7 +298,21 @@
   CFDictionaryAddValue(searchDict, kSecClass, kSecClassKey);
   CFDictionaryAddValue(searchDict, kSecAttrLabel, keyLabel);
   CFDictionaryAddValue(searchDict, kSecMatchLimit, kSecMatchLimitAll);
-  SecItemDelete(searchDict);
+  OSStatus res = SecItemDelete(searchDict);
+
+  if (res == errSecSuccess)
+    return;
+  
+  if (res == errSecAuthFailed && !retry)
+    {
+      unlockTpm(0, 0, false);
+      deleteKeyPairInTpmInternal(keyName, true);
+    }
+  else
+    {
+      _LOG_DEBUG("Fail to delete a key pair: " << res);
+      throw Error("Fail to delete a key pair");
+    }
 }
 
 void 
@@ -296,7 +367,7 @@
 }
 
 ConstBufferPtr
-SecTpmOsx::exportPrivateKeyPkcs1FromTpm(const Name& keyName)
+SecTpmOsx::exportPrivateKeyPkcs1FromTpmInternal(const Name& keyName, bool retry)
 {
   using namespace CryptoPP;
 
@@ -310,7 +381,13 @@
 
   if(res != errSecSuccess)
     {
-      return shared_ptr<Buffer>();
+      if(res == errSecAuthFailed && !retry)
+        {
+          unlockTpm(0, 0, false);
+          return exportPrivateKeyPkcs1FromTpmInternal(keyName, true);
+        }
+      else
+        return shared_ptr<Buffer>();
     }
 
   OBufferStream pkcs1Os;
@@ -341,7 +418,7 @@
 }
 
 bool
-SecTpmOsx::importPrivateKeyPkcs1IntoTpm(const Name& keyName, const uint8_t* buf, size_t size)
+SecTpmOsx::importPrivateKeyPkcs1IntoTpmInternal(const Name& keyName, const uint8_t* buf, size_t size, bool retry)
 {
   using namespace CryptoPP;
 
@@ -395,7 +472,13 @@
   
   if(res != errSecSuccess)
     {
-      return false;
+      if(res == errSecAuthFailed && !retry)
+        {
+          unlockTpm(0, 0, false);
+          return importPrivateKeyPkcs1IntoTpmInternal(keyName, buf, size, true);
+        }
+      else
+        return false;
     }
 
   SecKeychainItemRef privateKey = (SecKeychainItemRef)CFArrayGetValueAtIndex(outItems, 0);
@@ -468,7 +551,7 @@
 }
 
 Block
-SecTpmOsx::signInTpm(const uint8_t *data, size_t dataLength, const Name& keyName, DigestAlgorithm digestAlgorithm)
+SecTpmOsx::signInTpmInternal(const uint8_t *data, size_t dataLength, const Name& keyName, DigestAlgorithm digestAlgorithm, bool retry)
 {
   _LOG_TRACE("OSXPrivateKeyStorage::Sign");
     
@@ -516,10 +599,19 @@
 
   // Actually sign
   CFDataRef signature = (CFDataRef) SecTransformExecute(signer, &error);
-  if (error) {
-    CFShow(error);
-    throw Error("Fail to sign data");
-  }
+  if (error)
+    {
+      if(!retry) 
+        {
+          unlockTpm(0, 0, false);
+          return signInTpmInternal(data, dataLength, keyName, digestAlgorithm, true);
+        }
+      else
+        {
+          CFShow(error);
+          throw Error("Fail to sign data");
+        }
+    }
 
   if (!signature) throw Error("Signature is NULL!\n");
 
diff --git a/src/security/sec-tpm-osx.hpp b/src/security/sec-tpm-osx.hpp
index d10ce7d..e18d3bc 100644
--- a/src/security/sec-tpm-osx.hpp
+++ b/src/security/sec-tpm-osx.hpp
@@ -23,18 +23,48 @@
   ~SecTpmOsx();
 
 
-  // From TrustedPlatformModule
-  virtual void 
-  generateKeyPairInTpm(const Name& keyName, KeyType keyType, int keySize);
+  /******************************
+   * From TrustedPlatformModule *
+   ******************************/
 
   virtual void
-  deleteKeyPairInTpm(const Name& keyName);
+  setTpmPassword(const uint8_t* password, size_t passwordLength);
+
+  virtual void
+  resetTpmPassword();
+
+  virtual void
+  setInTerminal(bool inTerminal);
+
+  virtual bool
+  getInTerminal();
+
+  virtual bool
+  locked();
+
+  virtual void
+  unlockTpm(const char* password, size_t passwordLength, bool usePassword);
+
+  virtual void 
+  generateKeyPairInTpm(const Name& keyName, KeyType keyType, int keySize)
+  {
+    generateKeyPairInTpmInternal(keyName, keyType, keySize, false);
+  }
+
+  virtual void
+  deleteKeyPairInTpm(const Name& keyName)
+  {
+    deleteKeyPairInTpmInternal(keyName, false);
+  }
 
   virtual ptr_lib::shared_ptr<PublicKey> 
   getPublicKeyFromTpm(const Name& keyName);
   
   virtual Block
-  signInTpm(const uint8_t* data, size_t dataLength, const Name& keyName, DigestAlgorithm digestAlgorithm);
+  signInTpm(const uint8_t* data, size_t dataLength, const Name& keyName, DigestAlgorithm digestAlgorithm)
+  {
+    return signInTpmInternal(data, dataLength, keyName, digestAlgorithm, false);
+  }
 
   virtual ConstBufferPtr 
   decryptInTpm(const uint8_t* data, size_t dataLength, const Name& keyName, bool isSymmetric);
@@ -73,13 +103,37 @@
    * From TrustedPlatformModule *
    ******************************/
   virtual ConstBufferPtr
-  exportPrivateKeyPkcs1FromTpm(const Name& keyName);
+  exportPrivateKeyPkcs1FromTpm(const Name& keyName)
+  {
+    return exportPrivateKeyPkcs1FromTpmInternal(keyName, false);
+  }
 
   virtual bool
-  importPrivateKeyPkcs1IntoTpm(const Name& keyName, const uint8_t* buf, size_t size);
+  importPrivateKeyPkcs1IntoTpm(const Name& keyName, const uint8_t* buf, size_t size)
+  {
+    return importPrivateKeyPkcs1IntoTpmInternal(keyName, buf, size, false);
+  }
 
   virtual bool
   importPublicKeyPkcs1IntoTpm(const Name& keyName, const uint8_t* buf, size_t size);
+
+  /******************************
+   *       OSX-specifics        *
+   ******************************/
+  void
+  generateKeyPairInTpmInternal(const Name & keyName, KeyType keyType, int keySize, bool retry);
+  
+  void
+  deleteKeyPairInTpmInternal(const Name &keyName, bool retry);
+
+  ConstBufferPtr
+  exportPrivateKeyPkcs1FromTpmInternal(const Name& keyName, bool retry);
+
+  bool
+  importPrivateKeyPkcs1IntoTpmInternal(const Name& keyName, const uint8_t* buf, size_t size, bool retry);
+
+  Block
+  signInTpmInternal(const uint8_t *data, size_t dataLength, const Name& keyName, DigestAlgorithm digestAlgorithm, bool retry);
   
 private:
   class Impl;
diff --git a/src/security/sec-tpm.cpp b/src/security/sec-tpm.cpp
index a52d839..f93169d 100644
--- a/src/security/sec-tpm.cpp
+++ b/src/security/sec-tpm.cpp
@@ -24,7 +24,7 @@
 namespace ndn {
 
 ConstBufferPtr
-SecTpm::exportPrivateKeyPkcs8FromTpm(const Name& keyName, bool inTerminal, const string& passwordStr)
+SecTpm::exportPrivateKeyPkcs8FromTpm(const Name& keyName, const string& passwordStr)
 {
   uint8_t salt[8] = {0};
   uint8_t iv[8] = {0};
@@ -32,25 +32,6 @@
   try{
     using namespace CryptoPP;
 
-    // check password
-    string password;
-    if(passwordStr.empty())
-      if(!inTerminal)
-        return shared_ptr<Buffer>();
-      else
-        {
-          int count = 0;
-          while(!getPassWord(password, keyName.toUri()))
-            {
-              cerr << "Password mismatch!" << endl;
-              count++;
-              if(count > 3)
-                return shared_ptr<Buffer>();
-            }
-        }
-    else
-      password = passwordStr;
-
     // derive key
     if(!generateRandomBlock(salt, 8))
       return shared_ptr<Buffer>();
@@ -67,11 +48,9 @@
 
     keyGenerator.DeriveKey(derived, derivedLen, 
                            purpose, 
-                           reinterpret_cast<const byte*>(password.c_str()), password.size(), 
+                           reinterpret_cast<const byte*>(passwordStr.c_str()), passwordStr.size(), 
                            salt, 8, 
-                           iterationCount); 
-    
-    memset(const_cast<char*>(password.c_str()), 0, password.size());
+                           iterationCount);
 
     //encrypt
     CBC_Mode< DES_EDE3 >::Encryption e;
@@ -152,7 +131,7 @@
 }
 
 bool
-SecTpm::importPrivateKeyPkcs8IntoTpm(const Name& keyName, const uint8_t* buf, size_t size, bool inTerminal, const string& passwordStr)
+SecTpm::importPrivateKeyPkcs8IntoTpm(const Name& keyName, const uint8_t* buf, size_t size, const string& passwordStr)
 {
   try{
     using namespace CryptoPP;
@@ -227,29 +206,13 @@
     size_t derivedLen = 24; //For DES-EDE3-CBC-PAD
     byte derived[24] = {0};
     byte purpose = 0;
-
-    string password;
-    if(passwordStr.empty())
-      if(inTerminal)
-        {
-          char* pw = getpass("Password for the private key: ");
-          if (!pw)
-            return false;
-          password = pw;
-          memset(pw, 0, strlen(pw));
-        }
-      else
-        return false;
-    else
-      password = passwordStr;
       
     keyGenerator.DeriveKey(derived, derivedLen, 
                            purpose, 
-                           reinterpret_cast<const byte*>(password.c_str()), password.size(), 
+                           reinterpret_cast<const byte*>(passwordStr.c_str()), passwordStr.size(), 
                            saltBlock.BytePtr(), saltBlock.size(), 
                            iterationCount);
 
-    memset(const_cast<char*>(password.c_str()), 0, password.size());
         
     //decrypt
     CBC_Mode< DES_EDE3 >::Decryption d;
diff --git a/src/security/sec-tpm.hpp b/src/security/sec-tpm.hpp
index f49518d..5d836ee 100644
--- a/src/security/sec-tpm.hpp
+++ b/src/security/sec-tpm.hpp
@@ -26,13 +26,65 @@
 public:
   struct Error : public std::runtime_error { Error(const std::string &what) : std::runtime_error(what) {} };
 
-  /**
-   * The virtual destructor.
-   */    
   virtual 
   ~SecTpm() {}
 
   /**
+   * @brief set password of TPM
+   * 
+   * Password is used to unlock TPM when it is locked.
+   * You should be cautious when using this method, because remembering password is kind of dangerous.
+   *
+   * @param password The password.
+   * @param passwordLength The length of password.
+   */
+  virtual void
+  setTpmPassword(const uint8_t* password, size_t passwordLength) = 0;
+
+  /**
+   * @brief reset password of TPM
+   */
+  virtual void
+  resetTpmPassword() = 0;
+
+  /**
+   * @brief set inTerminal flag
+   * 
+   * If the inTerminal flag is set, and password is not set, TPM may ask for password via terminal.
+   * inTerminal flag is set by default.
+   *
+   * @param inTerminal.
+   */
+  virtual void
+  setInTerminal(bool inTerminal) = 0;
+
+  /**
+   * @brief get inTerminal flag
+   * 
+   * @return inTerminal flag.
+   */
+  virtual bool
+  getInTerminal() = 0;
+
+  /**
+   * @brief check if TPM is locked.
+   * 
+   * @return true if locked, false otherwise
+   */
+  virtual bool
+  locked() = 0;
+
+  /**
+   * @brief Unlock the TPM.
+   *
+   * @param password The password.
+   * @param passwordLength The password size. 0 indicates no password.
+   * @param usePassword True if we want to use the supplied password to unlock the TPM.
+   */
+  virtual void
+  unlockTpm(const char* password, size_t passwordLength, bool usePassword) = 0;
+
+  /**
    * @brief Generate a pair of asymmetric keys.
    *
    * @param keyName The name of the key pair.
@@ -134,11 +186,10 @@
    * 
    * @param keyName The private key name.
    * @param password The password to encrypt the private key.
-   * @param inTerminal If password is not supplied, get it via terminal if inTerminal is true, otherwise fail.
    * @return The private key info (in PKCS8 format) if exist, otherwise a NULL pointer.
    */
   ConstBufferPtr
-  exportPrivateKeyPkcs8FromTpm(const Name& keyName, bool inTerminal, const std::string& password);
+  exportPrivateKeyPkcs8FromTpm(const Name& keyName, const std::string& password);
 
   /**
    * @brief Import a private key in PKCS#8 format.
@@ -148,11 +199,10 @@
    * @param keyName The private key name.
    * @param key The encoded private key info.
    * @param password The password to encrypt the private key.
-   * @param inTerminal If password is not supplied, get it via terminal if inTerminal is true, otherwise fail.
    * @return False if import fails.
    */
   bool
-  importPrivateKeyPkcs8IntoTpm(const Name& keyName, const uint8_t* buf, size_t size, bool inTerminal, const std::string& password);
+  importPrivateKeyPkcs8IntoTpm(const Name& keyName, const uint8_t* buf, size_t size, const std::string& password);
 
 protected:
   /**
@@ -186,18 +236,18 @@
 
 
   /**
-   * @brief Get password.
+   * @brief Get import/export password.
    *
    * @param password On return, the password.
    * @param prompt Prompt for password, i.e., "Password for key:"
    * @return true if password has been obtained.
    */
   inline virtual bool
-  getPassWord(std::string& password, const std::string& prompt);
+  getImpExpPassWord(std::string& password, const std::string& prompt);
 };
 
 bool
-SecTpm::getPassWord(std::string& password, const std::string& prompt)
+SecTpm::getImpExpPassWord(std::string& password, const std::string& prompt)
 {
   int result = false;
 
@@ -225,7 +275,11 @@
 
   char* pw1 = const_cast<char*>(password1.c_str());
   memset(pw1, 0, password1.size());
-  memset(pw0, 0, strlen(pw0));  
+  memset(pw0, 0, strlen(pw0));
+
+  if(password.empty())
+    return false;
+
   return result;
 }